HashiCorp Vault — Policy Management
Managing policies through their lifecycle: creating, testing, updating, and organizing policies at scale.
Policy CRUD
Create / Update a Policy
# From a file
vault policy write dev-team dev-team-policy.hcl
# From stdin (inline)
vault policy write app-read - <<EOF
path "secret/data/apps/*" {
capabilities = ["read"]
}
EOF
# Via API
curl --header "X-Vault-Token: $VAULT_TOKEN" \
--request PUT \
--data '{"policy": "path \"secret/data/*\" { capabilities = [\"read\"] }"}' \
"$VAULT_ADDR/v1/sys/policies/acl/my-policy"
Read a Policy
# CLI
vault policy read dev-team
# API
curl -s --header "X-Vault-Token: $VAULT_TOKEN" \
"$VAULT_ADDR/v1/sys/policies/acl/dev-team" | jq -r .data.policy
List All Policies
vault policy list
Delete a Policy
vault policy delete dev-team
Testing Policies
Check Token Capabilities
# What can my current token do on a path?
vault token capabilities secret/data/myapp/config
# create, read, update
# What can a specific token do?
vault token capabilities hvs.CAESI... secret/data/myapp/config
# What can a token accessed by accessor do?
vault token capabilities -accessor abc123 secret/data/myapp/config
Test Before Deploying
# 1. Write the policy
vault policy write test-policy test-policy.hcl
# 2. Create a test token
TEST_TOKEN=$(vault token create -policy=test-policy -ttl=5m -field=token)
# 3. Test access
VAULT_TOKEN=$TEST_TOKEN vault kv get secret/myapp/config
# Should succeed or fail based on policy
VAULT_TOKEN=$TEST_TOKEN vault kv put secret/admin/config key=value
# Should be denied
# 4. Cleanup
vault token revoke $TEST_TOKEN
vault policy delete test-policy
Attaching Policies
To Auth Methods
# Userpass
vault write auth/userpass/users/alice policies="dev-team,deploy"
# AppRole
vault write auth/approle/role/webapp token_policies="webapp-read"
# LDAP group mapping
vault write auth/ldap/groups/engineering policies="dev-team"
# Kubernetes role
vault write auth/kubernetes/role/webapp policies="webapp-read"
To Tokens
# Create token with policies
vault token create -policy=dev-team -policy=deploy
# Token roles with policies
vault write auth/token/roles/ci-runner \
allowed_policies="ci-read,deploy" \
disallowed_policies="admin"
Via Identity Groups
# Create an internal group with policies
vault write identity/group \
name="engineering" \
policies="dev-team" \
member_entity_ids="entity-id-1,entity-id-2"
Policy Organization Best Practices
Naming Convention
<scope>-<team/app>-<access-level>
Examples:
team-backend-rw (team: backend, read-write)
team-frontend-ro (team: frontend, read-only)
app-payment-svc-read (app: payment service, read)
infra-admin (infrastructure admin)
ci-deploy (CI/CD deployment)
emergency-break-glass (emergency access)
Policy as Code
Store policies in Git alongside your infrastructure:
vault-policies/
├── teams/
│ ├── backend-rw.hcl
│ ├── frontend-rw.hcl
│ └── sre-admin.hcl
├── apps/
│ ├── payment-service.hcl
│ └── user-service.hcl
├── ci/
│ ├── ci-deploy.hcl
│ └── ci-read.hcl
└── emergency/
└── break-glass.hcl
Automate Policy Deployment
#!/bin/bash
# deploy-policies.sh
POLICY_DIR="vault-policies"
for file in $(find "$POLICY_DIR" -name "*.hcl" -type f); do
# Extract policy name from filename
policy_name=$(basename "$file" .hcl)
echo "Deploying policy: $policy_name"
vault policy write "$policy_name" "$file"
done
Quick Reference
| Command | Description |
|---|---|
vault policy write NAME file.hcl |
Create/update policy |
vault policy read NAME |
Read policy |
vault policy list |
List all policies |
vault policy delete NAME |
Delete policy |
vault token capabilities PATH |
Check token capabilities |
vault token create -policy=NAME |
Token with policy |
Next: Practice Exercises