create vault policies
Intro to Vault Policies
Key features
- Vault policies enable operators to permit or deny access to specific paths or actions in Vault using Role-Based Access Control (RBAC)
- Provide granular control over secret access
- Policy format is written as declarative statements in JSON or HCL
- Principle of least privilege grants users or applications only the permissions they need
- By default, policies implicitly deny access unless explicitly granted
- No policy = no authorization
- Explicit DENY overrides all other permissions
- Policies are attached to tokens, a token can have multiple policies
- Permissions are cumulative and additive
Out-of-the-box Vault policies
- Root policy
- Created by default as a superuser with unrestricted permissions
- Cannot be modified or deleted
- Attached to all root tokens
- Default policy
- Created by default with common permissions
- Modifiable but cannot be deleted
- Attached to all non-root tokens by default (removable if needed)
vault policy list
---
default
root
- Default policy example - token management
vault policy read default
---
path "auth/token/lookup-self" { capabilities = ["read"] }
path "auth/token/renew-self" { capabilities = ["update"] }
path "auth/token/revoke-self" { capabilities = ["update"] }
path "sys/capabilities-self" { capabilities = ["update"] }
- Root policy example - cannot read
vault policy read root
---
No policy named: root
The root policy has no explicit rules but grants full access
path "*" {
capabilities = ["read", "create", "update", "delete", "list", "sudo"]
}
Use the root policy with extreme caution
Managing Policies Using CLI
Use the vault policy command
- delete
- fmt
- list
- read
- write
How to use command
- Syntax:
vault <object_type> <subcommand> <policy_name> <file_location>
vault policy list
---
admin-policy
default
root
vault policy write admin-policy /tmp/admin.hcl
---
Success! Uploaded policy: admin-policy
---
Managing Policies Using UI
Directions: Homepage → Policies → Create ACL policy
Managing Policies Using API
Create a new policy
- Method: POST
curl \
--header "X-Vault-Token: hvs.2kjqZ12ofDr3efPdtMJ1z5dZ" \
--request PUT \
--data @payload.json \
http://127.0.0.1:8200/v1/sys/policy/webapp
- Payload file
{
"policy": "path \"kv/apps/webapp\" { capabilities = [\"read\"] }"
}
Anatomy of a Vault Policy
Vault operates on a path-based system. Policies grant or restrict access to these paths and their operations
- Syntax
path "<path>" {
capabilities = ["<permissions>"]
}
- Examples
path "kv/data/apps/jenkins" {
capabilities = ["read", "update", "delete"]
}
path "sys/policies/*" {
capabilities = ["create", "update", "list", "delete"]
}
path "aws/creds/web-app" {
capabilities = ["read"]
}
Vault Policies - Path
Common paths
- Examples
- sys/policy/vault-admin
- kv/apps/app01/web
- auth/ldap/group/developers
- database/creds/prod-db
- secrets/data/platform/aws/tools/ansible/app01
- sys/rekey
Root-protected paths
- Certain critical paths require a root token or the sudo capability. Examples include
- auth/token/create-orphan (create an orphan token)
- pki/root/sign-self-issued (sign a self-issued certificate)
- sys/rotate (rotate the encryption key)
- sys/seal (manually seal Vault)
- sys/step-down (force leader to relinquish active status)
path "sys/rotate" {
capabilities = ["sudo"]
}
path "sys/seal" {
capabilities = ["sudo"]
}
path "sys/step-down" {
capabilities = ["sudo"]
}
Vault Policies - Capabilities
Capabilities define permitted actions in Vault
- Specified as a list of strings (even for a single capability)
Capability definitions
Capability | HTTP Verb | Description |
---|---|---|
create | POST/PUT | Create a new entry if it doesn't exist |
read | GET | Read credentials, configurations, etc. |
update | POST/PUT | Overwrite an existing secret or configuration |
delete | DELETE | Delete an entry |
list | LIST | View available items (without reading contents) |
sudo | - | Access root-protected paths |
deny | - | Deny access, overriding all other capabilities |
- create: If the key does not exist
- update: If the key exists and we want to replace/update it
Write is not a valid capability
Examples
- Example 1
- Generate database credentials at database/creds/db01
- Manage secrets (create, read, update, delete) at kv/apps/dev-app01
path "database/creds/dev-db01" {
capabilities = ["read"]
}
path "kv/apps/dev-app01" {
capabilities = ["create", "read", "update", "delete"]
}
- Example 2
- Read credentials after kv/apps/webapp
- Deny access to kv/apps/webapp/super-secret
path "kv/apps/webapp/*" {
capabilities = ["read"]
}
path "kv/apps/webapp/super-secret" {
capabilities = ["deny"]
}
Customizing the Path
Using * (Glob)
- Wildcard for anything after a path (only at the end)
- Examples
- secret/apps/application1/*: Matches any path after application1
- kv/platform/db-*: Matches kv/platform/db-2, but not kv/platform/db2
Using + (Single Directory Wildcard)
- Matches a single directory in a path segment
- Can be used multiple times (e.g., secret/+/+/db)
- Examples
- secret/+/db: Matches secret/db2/db or secret/app/db
- kv/data/apps/+/webapp: Matches
- kv/data/apps/dev/webapp
- kv/data/apps/qa/webapp
- kv/data/apps/prod/webapp
Example policy
path "secret/+/+/webapp" {
capabilities = ["read", "list"]
}
path "secret/apps/+/team-*" {
capabilities = ["create", "read"]
}
ACL templating
- Use
{{parameter}}
for variable replacement with token-specific values - Example: Restrict key/value v2 secrets to a specific user's entity ID
path "secret/data/{{identity.entity.id}}/*" {
capabilities = ["create", "update", "read", "delete"]
}
path "secret/metadata/{{identity.entity.id}}/*" {
capabilities = ["list"]
}
Supported parameters
Parameter | Description |
---|---|
identity.entity.id | Entity's ID |
identity.entity.name | Entity's name |
identity.entity.metadata.<key> | Metadata for the entity by key |
identity.entity.aliases.<accessor> .id | Entity alias ID for a mount |
identity.entity.aliases.<accessor> .name | Entity alias name for a mount |
identity.groups.ids.<group-id> .name | Group name for a given group ID |
identity.groups.names.<group-name> .id | Group ID for a given group name |
Working With Policies
Create a token with policy
vault token create -policy="web-app"
---
Key Value
--- -----
token hvs.2kjqZ12ofDr3efPdtMJ1z5dZ
token_accessor 18r88muoe3x1xEqVqXdlTMwJ
token_duration 768h
token_renewable true
token_policies ["default", "web-app"]
- All tokens inherit the default policy plus assigned policies
Test policy requirements
- Example requirements
- Read AWS credentials for an S3 bucket (aws/creds/s3-readonly)
- Read secrets from secret/apikey/Google
vault token create -policy="web-app"
vault login <token>
vault read secret/apikey/Google # Should succeed
vault write secret/apikey/Google key="ABCDE12345" # Should fail
vault read aws/creds/s3-readonly # Should succeed
Administrative policies
-
Manage Vault backend functions under the sys/ path
-
Examples: Unsealing, policy management, secret backend setup
-
Setup
- Licensing
- Setup New Vault Cluster
- Configure UI
- Rotate Keys
- Seal Vault
path "sys/license" {
capabilities = ["read", "list", "create", "update", "delete"]
}
path "sys/init" {
capabilities = ["read", "update", "create"]
}
path "sys/config/ui" {
capabilities = ["read", "list", "update", "delete", "sudo"]
}
path "sys/rekey/*" {
capabilities = ["read", ##### "list", "update", "delete"]
}
path "sys/rotate" {
capabilities = ["update", "sudo"]
}
path "sys/seal" {
capabilities = ["sudo"]
}