HashiCorp Vault — Policy Management

2 minute read

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