Namespaces are available only in Stronghold EE.
A namespace works as a separate virtual Stronghold with its own secrets engines, auth methods, policies, and tokens. A team gets a namespace, and its administrators manage it on their own without access to the root namespace or to other teams’ namespaces.
Goal
Create a namespace for the team-a team, grant its administrators delegated permissions, set up separate auth methods for people and applications, and configure templated policies that do not need changes when new applications are added.
Prerequisites
To follow this example, you need:
- Stronghold EE.
- A root namespace administrator token.
- OIDC client parameters in the IdP for the team (address,
client_id,client_secret) if people log in through OIDC. - The team’s Kubernetes cluster if applications authenticate with the Kubernetes method.
Step 1. Create a namespace
Log in with the root namespace administrator token and create the team-a namespace:
d8 stronghold namespace create -custom-metadata=owner="team-a@example.com" team-aThe commands below are run in this namespace and pass the -namespace=team-a flag explicitly.
Step 2. Create a delegated administrator policy
Paths in the policy are relative to the namespace. The policy allows managing secrets engines, auth methods, policies, and Identity inside team-a, but grants no permissions outside it:
d8 stronghold policy write -namespace=team-a team-admin - <<'POLICY'
# Managing secrets engines and auth methods.
path "sys/mounts/*" {
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}
path "sys/mounts" {
capabilities = ["read"]
}
path "sys/auth/*" {
capabilities = ["create", "read", "update", "delete", "sudo"]
}
path "sys/auth" {
capabilities = ["read"]
}
# Managing policies.
path "sys/policies/acl/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
# Configuring auth methods and Identity.
path "auth/*" {
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}
path "identity/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
# Working with team secrets.
path "secret/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
# Nested namespaces.
path "sys/namespaces/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
POLICYRemove blocks the team must not control, for example sys/namespaces/*.
Step 3. Set up an auth method for people
Set up OIDC login for the team administrators:
Enable OIDC in the team namespace:
d8 stronghold auth enable -namespace=team-a oidcConfigure the method and a role as described in OIDC auth method, passing
-namespace=team-ato each command. In the role, set the claim with user groups (groups_claim).Bind the
team-adminpolicy to the team’s administrator group in the IdP:OIDC_ACCESSOR=$(d8 stronghold read -namespace=team-a -field=accessor sys/auth/oidc) GROUP_ID=$(d8 stronghold write -namespace=team-a -field=id identity/group name=team-a-admins type=external policies=team-admin) d8 stronghold write -namespace=team-a identity/group-alias name=team-a-admins mount_accessor="$OIDC_ACCESSOR" canonical_id="$GROUP_ID"
From now on, team administrators log in with d8 stronghold login -namespace=team-a -method=oidc and continue without the root namespace administrator.
Step 4. Set up an auth method for applications
Set up the Kubernetes auth method and a KV store for the team’s applications:
Enable the Kubernetes method for the team’s cluster:
d8 stronghold auth enable -namespace=team-a kubernetes d8 stronghold write -namespace=team-a auth/kubernetes/config kubernetes_host="https://<API_SERVER_ADDRESS>:6443" kubernetes_ca_cert=@ca.crt<API_SERVER_ADDRESS>is the address of the Kubernetes API server of the team’s cluster. Theca.crtfile contains its CA certificate.Configuration parameters are described in Kubernetes auth method.
Enable the team’s KV store:
d8 stronghold secrets enable -namespace=team-a -path=secret -version=2 kv
Step 5. Configure a templated policy for applications
Instead of a separate policy for each application, use one templated policy: an application gets access to secrets in the directory that matches its Kubernetes namespace.
K8S_ACCESSOR=$(d8 stronghold read -namespace=team-a -field=accessor sys/auth/kubernetes)
d8 stronghold policy write -namespace=team-a app-by-namespace - <<POLICY
path "secret/data/{{identity.entity.aliases.${K8S_ACCESSOR}.metadata.service_account_namespace}}/*" {
capabilities = ["read"]
}
POLICY
d8 stronghold write -namespace=team-a auth/kubernetes/role/apps bound_service_account_names="*" bound_service_account_namespaces="team-a-*" policies=app-by-namespace ttl=1hbound_service_account_namespaces also accepts patterns with a trailing * (for example, team-a-*).
An application from the team-a-billing Kubernetes namespace can read secret/data/team-a-billing/*, but not the team-a-orders secrets.
In the same way, you can give each employee a personal directory:
d8 stronghold policy write -namespace=team-a personal - <<'POLICY'
path "secret/data/users/{{identity.entity.id}}/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
path "secret/metadata/users/{{identity.entity.id}}/*" {
capabilities = ["read", "list", "delete"]
}
POLICYVerification
Check the result:
Log in as a team administrator and check that management inside the namespace is available:
d8 stronghold login -namespace=team-a -method=oidc d8 stronghold secrets list -namespace=team-aCheck that access to the root namespace is denied. The command runs without
-namespace, so the request goes to the root namespace. The command must return apermission deniederror:d8 stronghold secrets listCompare token capabilities on paths of different teams:
d8 stronghold token capabilities -namespace=team-a secret/data/team-a-billing/db
Cleanup
Deleting a namespace deletes all its secrets engines, auth methods, policies, and tokens. The team administrator token cannot delete the namespace. Log in with the root namespace administrator token and delete the namespace:
d8 stronghold login
d8 stronghold namespace delete team-aBefore deleting a production namespace, take a storage snapshot.