Introduction
HashiCorp Vault offers advanced governance through Sentinel policies, which allow administrators to enforce complex rules that go beyond traditional Vault ACL policies. In this guide, we’ll explore using Sentinel to restrict namespace manipulation, a task that is often challenging with standard ACLs due to the hierarchical nature of namespaces.
Introduction
Namespaces in Vault modify request paths. For example:
- A
token lookup
in the root namespace uses the path:auth/token/lookup
. - The same request in a nested namespace (
ns1
) becomes:ns1/auth/token/lookup
.
Vault ACL policies support path wildcards like *
or +
, but they do not currently handle recursive or nested namespace paths. Sentinel policies solve this limitation by enabling regex matching and other advanced rules.
This guide demonstrates how to configure Sentinel to prevent namespace creation, deletion, or updates by all users except a specific super-admin.
Prerequisite:
- Vault Enterprise with a valid license (Sentinel policies require Vault Enterprise).
- sentinel CLI is installed as described here: https://developer.hashicorp.com/sentinel/tutorials/get-started/install
- Familiarity with Sentinel policy syntax.
Scenario
The objective is to:
- Allow general administrative privileges to users (
admin
policy). - Restrict all users from modifying namespaces except for a designated super-admin (
bob
).
Setup Steps
Note: this example will use Docker along with a Vault Enterprise license. As a prerequisite your license should be exported into an environment variable named VAULT_LICENSE
.
1. Start a Vault Instance
sudo docker run \
--cap-add=IPC_LOCK \
-e VAULT_DEV_LISTEN_ADDRESS='0.0.0.0:8200' \
-e VAULT_ADDR='http://0.0.0.0:8200' \
-e VAULT_DEV_ROOT_TOKEN_ID=root \
-e VAULT_LICENSE=$(echo $VAULT_LICENSE) \
-p 8200:8200 \
--name vault \
--detach \
hashicorp/vault-enterprise
export VAULT_ADDR=http://localhost:8200
sleep 2
vault login root
2. Define Vault Users and Policies
-
Create an Admin Policy:
vault policy write admin - << EOF
path "*" {
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}
EOF
2. Enable Userpass Authentication:
vault auth enable userpass
vault write auth/userpass/users/bob password=root token_policies=admin
vault write auth/userpass/users/jill password=root token_policies=admin
3. Link Bob to an Entity for Sentinel Context:
ENTITY_ID=$(vault write -format=json identity/entity name="bob" policies="admin" | jq -r '.data.id')
USERPASS_ACCESSOR=$(vault auth list -format=json | jq -r '.["userpass/"].accessor')
vault write identity/entity-alias name="bob" \
canonical_id=$ENTITY_ID \
mount_accessor=$USERPASS_ACCESSOR
3. Create a Sentinel Policy
-
Policy Definition:
cat <<'EOF' > blockns.sentinel
precond = rule {
request.path matches "^(.*)sys\\/namespaces\\/(.*)$" and request.operation in ["create", "update", "delete"]
}
prevent_namespaces = rule {
identity.entity.name is "bob"
}
main = rule when precond {
prevent_namespaces
}
EOF
2. Enable the Sentinel Policy:
POLICY=$(base64 blockns.sentinel)
vault write sys/policies/egp/blockns \
policy="${POLICY}" \
paths="*" \
enforcement_level="hard-mandatory"
4. Unit Testing with Sentinel
-
Prepare Test Files:
mkdir -p test/blockns
# Test for allowed namespace manipulation by 'bob'
cat <<'EOF' > test/blockns/allow-ns.json
{
"global": {
"request": {
"path": "sys/namespaces/test",
"operation": "create"
},
"identity": {
"entity": {
"name": "bob"
}
}
},
"test": {
"precond": true,
"prevent_namespaces": true,
"main": true
}
}
EOF
# Test for blocking namespace manipulation by 'jill'
cat <<'EOF' > test/blockns/block-ns.json
{
"global": {
"request": {
"path": "sys/namespaces/test",
"operation": "create"
},
"identity": {
"entity": {
"name": "jill"
}
}
},
"test": {
"precond": true,
"prevent_namespaces": false,
"main": false
}
}
EOF
2. Run Sentinel Tests:
sentinel test
5. Field Testing
- Login and Test Namespace Manipulation:
vault login -method=userpass username=bob password=root
vault namespace create ns1 # Allowed
vault login -method=userpass username=jill password=root
vault namespace create ns2 # Blocked
Key Takeaways
- Flexibility: Sentinel provides regex and conditional logic not available in Vault ACL policies.
- Scalability: This policy manages all namespace paths, including deeply nested ones.
-
Governance: Enforcement levels (e.g.,
hard-mandatory
) ensure strict compliance.
This workflow demonstrates Sentinel's power to extend Vault's functionality, ensuring secure and fine-grained control over namespace manipulation.
References:
Getting Started with Sentinel Policies:
https://developer.hashicorp.com/sentinel/tutorials/get-started
Enforce access control with Sentinel policies
https://developer.hashicorp.com/vault/tutorials/policies/sentinel