Create a New Project Secrets Folder¶
This guide explains how to create a new secrets folder for your project and scope access to a specific Keycloak group.
Prerequisites¶
- OpenBao CLI installed and configured (Setup Guide)
- Authenticated with admin role or root token
- A Keycloak group for your project (or permission to create one)
Overview¶
Setting up a new project involves:
- Creating the secrets path/folder
- Creating a policy to control access
- Creating an external group mapping to Keycloak
- Testing access
Step 1: Plan Your Structure¶
Decide on your secrets path structure:
clusters/
├── hetzner-mgmt/ # Management cluster
│ ├── apps/
│ │ ├── frontend/
│ │ └── backend/
│ ├── databases/
│ └── external-services/
├── production/ # Production cluster
└── staging/ # Staging cluster
Step 2: Create the Secrets Path¶
Create an initial secret to establish the path:
# Login as admin
bao login -method=oidc role=admin
# Create the project folder with metadata
bao kv put clusters/hetzner-mgmt/apps/myproject/info \
description="My Project secrets" \
owner="myteam" \
created="$(date -Iseconds)"
Step 3: Create Access Policy¶
Create a policy file that defines what access the group will have:
bao policy write myproject-admin - <<EOF
# Policy for myproject administrators
# Full access to myproject secrets
# Read and write secrets
path "clusters/data/hetzner-mgmt/apps/myproject/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
# Manage metadata (versions, etc.)
path "clusters/metadata/hetzner-mgmt/apps/myproject/*" {
capabilities = ["list", "read", "delete"]
}
# List the project folder
path "clusters/data/hetzner-mgmt/apps/myproject" {
capabilities = ["list"]
}
path "clusters/metadata/hetzner-mgmt/apps/myproject" {
capabilities = ["list"]
}
EOF
Policy Capabilities Reference¶
| Capability | Description |
|---|---|
create |
Create new secrets |
read |
Read secret values |
update |
Update existing secrets |
delete |
Soft delete secrets |
list |
List secrets in a path |
sudo |
Access protected paths |
Read-Only Policy Example¶
For users who only need to read secrets:
bao policy write myproject-readonly - <<EOF
# Read-only policy for myproject
path "clusters/data/hetzner-mgmt/apps/myproject/*" {
capabilities = ["read", "list"]
}
path "clusters/metadata/hetzner-mgmt/apps/myproject/*" {
capabilities = ["list", "read"]
}
path "clusters/data/hetzner-mgmt/apps/myproject" {
capabilities = ["list"]
}
EOF
Step 4: Create External Group Mapping¶
Map a Keycloak group to the OpenBao policy:
4.1 Get the OIDC Accessor¶
OIDC_ACCESSOR=$(bao auth list -format=json | jq -r '.["oidc/"].accessor')
echo "OIDC Accessor: $OIDC_ACCESSOR"
4.2 Create External Group¶
4.3 Get the Group ID¶
GROUP_ID=$(bao read -format=json identity/group/name/myproject-admins | jq -r '.data.id')
echo "Group ID: $GROUP_ID"
4.4 Create Group Alias¶
Map the OpenBao group to the Keycloak group name:
bao write identity/group-alias \
name="myproject-admins" \
mount_accessor="$OIDC_ACCESSOR" \
canonical_id="$GROUP_ID"
Keycloak Group Name
The name in the group-alias must match exactly the Keycloak group name (case-sensitive).
Step 5: Create Keycloak Group (if needed)¶
If the Keycloak group doesn't exist, create it:
Via Keycloak API¶
# Get admin token
export ADMIN_PASS='your-password'
ADMIN_TOKEN=$(curl -s -X POST "http://localhost:8080/realms/skatzi/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=dunk" \
-d "password=$ADMIN_PASS" \
-d "grant_type=password" \
-d "client_id=admin-cli" | jq -r '.access_token')
# Create group
curl -X POST "http://localhost:8080/admin/realms/skatzi/groups" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "myproject-admins",
"path": "/myproject-admins"
}'
Add Users to Group¶
# Get user ID
USER_ID=$(curl -s -X GET "http://localhost:8080/admin/realms/skatzi/users?username=someuser" \
-H "Authorization: Bearer $ADMIN_TOKEN" | jq -r '.[0].id')
# Get group ID
KC_GROUP_ID=$(curl -s -X GET "http://localhost:8080/admin/realms/skatzi/groups?search=myproject-admins" \
-H "Authorization: Bearer $ADMIN_TOKEN" | jq -r '.[0].id')
# Add user to group
curl -X PUT "http://localhost:8080/admin/realms/skatzi/users/$USER_ID/groups/$KC_GROUP_ID" \
-H "Authorization: Bearer $ADMIN_TOKEN"
Step 6: Test Access¶
Test as Group Member¶
# Login as a user in the myproject-admins group
bao login -method=oidc role=default
# Try to create a secret
bao kv put clusters/hetzner-mgmt/apps/myproject/test message="hello"
# Try to read it
bao kv get clusters/hetzner-mgmt/apps/myproject/test
# Try to list secrets
bao kv list clusters/hetzner-mgmt/apps/myproject/
Verify Access Denied for Others¶
Login as a user NOT in the group:
bao login -method=oidc role=default
# This should fail with "permission denied"
bao kv get clusters/hetzner-mgmt/apps/myproject/test
Complete Example Script¶
Here's a complete script to set up a new project:
#!/bin/bash
set -e
PROJECT_NAME="myproject"
KEYCLOAK_GROUP="myproject-admins"
SECRETS_PATH="clusters/hetzner-mgmt/apps/${PROJECT_NAME}"
echo "Setting up secrets for: $PROJECT_NAME"
# 1. Create initial secret/folder
echo "Creating secrets path..."
bao kv put ${SECRETS_PATH}/info \
description="${PROJECT_NAME} secrets" \
created="$(date -Iseconds)"
# 2. Create policy
echo "Creating policy..."
bao policy write ${PROJECT_NAME}-admin - <<EOF
path "clusters/data/hetzner-mgmt/apps/${PROJECT_NAME}/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
path "clusters/metadata/hetzner-mgmt/apps/${PROJECT_NAME}/*" {
capabilities = ["list", "read", "delete"]
}
path "clusters/data/hetzner-mgmt/apps/${PROJECT_NAME}" {
capabilities = ["list"]
}
path "clusters/metadata/hetzner-mgmt/apps/${PROJECT_NAME}" {
capabilities = ["list"]
}
EOF
# 3. Get OIDC accessor
OIDC_ACCESSOR=$(bao auth list -format=json | jq -r '.["oidc/"].accessor')
# 4. Create external group
echo "Creating external group..."
bao write identity/group \
name="${KEYCLOAK_GROUP}" \
type="external" \
policies="${PROJECT_NAME}-admin"
# 5. Get group ID and create alias
GROUP_ID=$(bao read -format=json identity/group/name/${KEYCLOAK_GROUP} | jq -r '.data.id')
bao write identity/group-alias \
name="${KEYCLOAK_GROUP}" \
mount_accessor="$OIDC_ACCESSOR" \
canonical_id="$GROUP_ID"
echo "✅ Setup complete!"
echo ""
echo "Secrets path: ${SECRETS_PATH}/"
echo "Policy: ${PROJECT_NAME}-admin"
echo "Keycloak group: ${KEYCLOAK_GROUP}"
echo ""
echo "Next steps:"
echo "1. Ensure the Keycloak group '${KEYCLOAK_GROUP}' exists"
echo "2. Add users to the Keycloak group"
echo "3. Users can login with: bao login -method=oidc role=default"
Cleanup¶
To remove a project's access:
# Delete the group alias
bao delete identity/group-alias/id/<alias-id>
# Delete the external group
bao delete identity/group/name/myproject-admins
# Delete the policy
bao policy delete myproject-admin
# Optionally delete the secrets (permanent!)
bao kv metadata delete clusters/hetzner-mgmt/apps/myproject/info
Next Steps¶
- Setup Guide - Install and configure the CLI
- CRUD Operations - Create, read, update, and delete secrets