Templated Policies let policies reference identity information as variables and resolve paths dynamically at request time. They let you express a least-privilege design that gives each user or team their own secret space using only a small number of policies.
This article covers how to use information tied to entities and groups in template expansion, the evaluation order and pitfalls, practical configuration steps, and the key points to keep in mind for the exam.
Vault's Templated Policies let you write {{...}} placeholders inside ACL policies, which are substituted using the identity context (entity, its aliases, metadata, and so on) bound to the requesting token. Substitution happens server-side, and ordinary capability evaluation runs against the matched path.
In practice, embedding a user's own name or team into the path lets you safely apply a single policy to many people. From an exam perspective, the basics matter: which identity fields are available, what happens when a token has no entity, that deny always wins, and the difference between kv v2's data and metadata paths.
Minimal example: allow only the user's own area (kv v2)
path "kv/data/users/{{identity.entity.name}}/*" {
capabilities = ["create", "update", "read", "delete"]
}
# for list (kv v2 metadata path)
path "kv/metadata/users/{{identity.entity.name}}/*" {
capabilities = ["list"]
}Even for the same least-privilege design, you can produce many simple static ACLs, consolidate with templates, or control access through an advanced external policy engine like Sentinel. Pick the approach based on operational scale, how dynamic things are, and your audit requirements.
For the Associate and Ops exams, understanding when to use plain ACLs vs. Templated Policies is enough. Sentinel details show up in the context of higher-level certifications and Enterprise features.
| Aspect | Static ACL policies | Templated Policies | External policy engine |
|---|---|---|---|
| Number of definitions | Tends to grow per user | One policy covers many users | Rules consolidate, but runtime evaluation grows |
| Expressiveness | Fixed paths only | Identity-derived variable paths | Complex conditions across time, environment, and attributes |
| Operational cost | Naming and distribution get messy | Easy to keep in sync by updating attributes | Requires expertise in design, review, and operations |
| Exam frequency | High | High (template syntax, evaluation order) | Medium to low (higher-level certifications) |
Templates are expanded each time using the entity context bound to the requesting token. Standard ACL matching is performed against the expanded path string, and the final capabilities are decided (with deny taking precedence).
Groups are the unit you use to control who a policy applies to. Rather than dropping the group name itself into the path, the standard approach is to resolve the template using each member entity's attributes (for example, entity.metadata.team).
Conceptual diagram of template expansion and evaluation
Example: expanding via alias (the auth method's username)
# Assume the userpass accessor is held in an env var
# Example: ACCESSOR=auth_userpass_12345678
path "kv/data/users/{{identity.entity.aliases.${ACCESSOR}.name}}/*" {
capabilities = ["create", "update", "read", "delete"]
}
path "kv/metadata/users/{{identity.entity.aliases.${ACCESSOR}.name}}/*" {
capabilities = ["list"]
}Carving out a personal space is the most common pattern. Because entity.name may be an auto-generated name, use aliases.<mount_accessor>.name when you want to stabilize on the auth method's username.
Team-level spaces branch on an attribute like entity.metadata.team. When someone changes teams, you only need to update metadata and permissions move automatically — no redeploying policies.
HCL example: express both personal and team spaces in a single policy
# Personal space (username)
path "kv/data/users/{{identity.entity.aliases.${ACCESSOR}.name}}/*" {
capabilities = ["create", "update", "read", "delete"]
}
path "kv/metadata/users/{{identity.entity.aliases.${ACCESSOR}.name}}/*" {
capabilities = ["list"]
}
# Team space (entity.metadata.team). If team is unset, paths fail to match → deny
path "kv/data/teams/{{identity.entity.metadata.team}}/*" {
capabilities = ["read", "list"]
}
path "kv/metadata/teams/{{identity.entity.metadata.team}}/*" {
capabilities = ["list"]
}Below is a minimal example that grants users a personal space named after their username after logging in with userpass. Because we use aliases.<mount_accessor>.name, we fetch the userpass mount accessor and bake it into the template.
For production, design alongside entity metadata initialization, group policy attachment, and automation for the user join/leave flow.
End-to-end CLI command example
# 1) Enable kv v2
vault secrets enable -path=kv kv-v2
# 2) Enable userpass and create a user
auth_path=userpass
vault auth enable ${auth_path}
vault write auth/${auth_path}/users/alice password="S3cret!"
# 3) Fetch the userpass mount accessor
ACCESSOR=$(vault auth list -format=json | jq -r '."'${auth_path}'/".accessor')
echo "ACCESSOR=${ACCESSOR}"
# 4) Create the templated policy
cat > user-scoped.hcl <<EOF
path "kv/data/users/{{identity.entity.aliases.${ACCESSOR}.name}}/*" {
capabilities = ["create", "update", "read", "delete"]
}
path "kv/metadata/users/{{identity.entity.aliases.${ACCESSOR}.name}}/*" {
capabilities = ["list"]
}
EOF
vault policy write user-scoped user-scoped.hcl
# 5) Create an identity group and attach the policy
gid=$(vault write -field=id identity/group name="ops" policies="user-scoped")
echo "GROUP_ID=${gid}"
# 6) Log in once as alice so the entity is auto-created
VAULT_TOKEN=$(vault login -method=${auth_path} -format=json username=alice password="S3cret!" | jq -r .auth.client_token)
ENTITY_ID=$(VAULT_TOKEN=$VAULT_TOKEN vault token lookup -format=json | jq -r .data.entity_id)
echo "ENTITY_ID=${ENTITY_ID}"
# 7) Add alice's entity to the group
vault write identity/group/id/${gid} member_entity_ids=${ENTITY_ID}
# 8) Create a secret (substitute with an admin token in real use)
vault kv put kv/users/alice/api key=abc123
# 9) Verify access with alice's token
VAULT_TOKEN=$VAULT_TOKEN vault kv get kv/users/alice/api # succeeds
VAULT_TOKEN=$VAULT_TOKEN vault kv get kv/users/bob/api # fails (path mismatch)Template expansion is convenient, but missing attributes or mixing up path types can lead to unintended denies. Keep a checklist that covers audit and maintenance perspectives to stay safe.
On the exam, expect frequent questions on deny precedence, which identity fields are usable in templates, why list requires kv/metadata, and what happens when no entity exists.
Sample audit log entry (excerpt)
# Assumes the file audit device is enabled
# Confirm request.path matches the post-expansion real path
{
"type": "request",
"auth": {"entity_id": "...", "policies": ["user-scoped"]},
"request": {"path": "kv/data/users/alice/api", "operation": "read"},
"response": {"policy_results": {"allowed": true}}
}Associate / Ops
問題 1
You want to allow a user who logged in with userpass to access only the kv v2 path whose name matches their username. Which templated policy is written correctly (ignore list capability)?
正解: A
aliases.<accessor>.name using the userpass mount accessor is the stable way to expand to the auth method's username. Reads and writes on kv v2 go under kv/data/. B is an invalid placeholder, C uses the wrong namespace, and D uses the metadata path with read/update which is inappropriate (metadata is for list).
How are templates evaluated when the token has no entity?
Without an identity context, most template values are treated as empty, so paths fail to match and the request is denied. If you rely on templated policies, make sure your auth method always creates an entity/alias on login.
Do I need to update the policy when a user changes their name?
If you use aliases.<accessor>.name, the policy follows the auth method's username changes. However, if the mount accessor changes (for example, after recreating the auth method), you need to update the <accessor> value inside the policy. If you rely on entity.metadata, simply updating that key's value will automatically change how the template expands.
Can group information be used directly in template expansion?
Groups are generally used as the unit for policy attachment, while template expansion relies on each member's entity attributes (for example, entity.metadata.team or aliases). In other words, the group decides who the policy applies to, and each member's entity information decides which paths it reaches.
Practice with certification-focused question sets
無料で問題を解いてみるNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
Vault Core Concepts: Sealed/Unsealed, Auth, Secrets (2026)
Vault fundamentals — sealed/unsealed state, auth methods, se...
Vault Operations Professional (VOP-003): Complete Guide (2026)
Pass the Vault Operations Professional exam — enterprise pat...
Vault Path-Based Routing: API URL Structure (2026)
How Vault's path-based routing works — mount points, sub-pat...
Vault Tokens: Auth Token Mechanics (2026)
Token fundamentals — service vs. batch tokens, accessor, ren...
Vault Token Types: Service, Batch, Periodic (2026)
Service vs. batch tokens compared — performance, ACL behavio...