HashiCorp Vault — Vault Agent Exercises
Practice Vault Agent auto-auth, caching, and templating with these exercises.
Exercise 1 — Auto-Auth with AppRole
Task: Configure Vault Agent to auto-authenticate using AppRole.
- Create an AppRole
agent-testwith a policy that readssecret/data/myapp/* - Write a Vault Agent config with AppRole auto-auth
- Write the token to a sink file
- Start the agent and verify the token works
Show Answer
# Create policy
vault policy write agent-test - <<EOF
path "secret/data/myapp/*" {
capabilities = ["read"]
}
EOF
# Create AppRole
vault auth enable approle 2>/dev/null
vault write auth/approle/role/agent-test \
secret_id_ttl=60m token_ttl=1h token_max_ttl=4h \
policies="agent-test"
# Get credentials
vault read -field=role_id auth/approle/role/agent-test/role-id > /tmp/role-id
vault write -f -field=secret_id auth/approle/role/agent-test/secret-id > /tmp/secret-id
# /tmp/vault-agent.hcl
vault {
address = "http://127.0.0.1:8200"
}
auto_auth {
method "approle" {
config = {
role_id_file_path = "/tmp/role-id"
secret_id_file_path = "/tmp/secret-id"
remove_secret_id_file_after_reading = true
}
}
sink "file" {
config = {
path = "/tmp/agent-token"
mode = 0640
}
}
}
# Start agent
vault agent -config=/tmp/vault-agent.hcl &
# Verify
VAULT_TOKEN=$(cat /tmp/agent-token) vault kv get secret/myapp/config
Exercise 2 — Template Rendering
Task: Use Vault Agent to render a database config file from secrets.
- Store database credentials in
secret/myapp/db - Write a template that renders them as a
.envfile - Configure Vault Agent to render the template
- Verify the rendered file
Show Answer
# Store secrets
vault kv put secret/myapp/db \
host=db.example.com port=5432 \
username=myapp password=s3cret
# /tmp/templates/db.env.tpl
{{ with secret "secret/data/myapp/db" -}}
DB_HOST={{ .Data.data.host }}
DB_PORT={{ .Data.data.port }}
DB_USER={{ .Data.data.username }}
DB_PASS={{ .Data.data.password }}
{{- end }}
# Add to vault-agent.hcl
template {
source = "/tmp/templates/db.env.tpl"
destination = "/tmp/rendered/db.env"
perms = 0640
}
mkdir -p /tmp/templates /tmp/rendered
vault agent -config=/tmp/vault-agent.hcl &
# Check rendered file
cat /tmp/rendered/db.env
# DB_HOST=db.example.com
# DB_PORT=5432
# DB_USER=myapp
# DB_PASS=s3cret
Exercise 3 — Caching Proxy
Task: Set up Vault Agent as a caching proxy.
- Configure agent with a local TCP listener on port 8100
- Enable caching with
use_auto_auth_token - Point
VAULT_ADDRto the local agent - Read a secret through the cache
Show Answer
# /tmp/vault-agent-cache.hcl
vault {
address = "http://127.0.0.1:8200"
}
auto_auth {
method "approle" {
config = {
role_id_file_path = "/tmp/role-id"
secret_id_file_path = "/tmp/secret-id"
}
}
}
cache {
use_auto_auth_token = true
}
listener "tcp" {
address = "127.0.0.1:8100"
tls_disable = true
}
# Start agent
vault agent -config=/tmp/vault-agent-cache.hcl &
# Use the cache (no token needed — agent injects its auto-auth token)
VAULT_ADDR=http://127.0.0.1:8100 vault kv get secret/myapp/db
Exercise 4 — PKI Template
Task: Use Agent templating to auto-issue and renew a TLS certificate.
Show Answer
# /tmp/templates/cert.tpl
{{ with secret "pki_int/issue/web-server" "common_name=api.example.com" "ttl=24h" }}
{{ .Data.certificate }}
{{ .Data.issuing_ca }}
{{ end }}
# /tmp/templates/key.tpl
{{ with secret "pki_int/issue/web-server" "common_name=api.example.com" "ttl=24h" }}
{{ .Data.private_key }}
{{ end }}
template {
source = "/tmp/templates/cert.tpl"
destination = "/tmp/rendered/cert.pem"
}
template {
source = "/tmp/templates/key.tpl"
destination = "/tmp/rendered/key.pem"
perms = 0600
}
The agent will automatically re-issue the certificate before it expires.
Exercise 5 — Agent Injector Annotations
Task: Write Kubernetes annotations to inject a database secret formatted as a connection string.
Show Answer
metadata:
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "myapp"
vault.hashicorp.com/agent-inject-secret-db-url: "secret/data/myapp/db"
vault.hashicorp.com/agent-inject-template-db-url: |
{{ with secret "secret/data/myapp/db" -}}
postgresql://{{ .Data.data.username }}:{{ .Data.data.password }}@{{ .Data.data.host }}:{{ .Data.data.port }}/mydb?sslmode=require
{{- end }}
The application reads the connection string from /vault/secrets/db-url:
with open('/vault/secrets/db-url') as f:
db_url = f.read().strip()
# postgresql://myapp:s3cret@db.example.com:5432/mydb?sslmode=require
What’s Next?
Vault Agent gets you secrets into applications. Now let’s dive deeper into Kubernetes Integration — Helm charts, CSI provider, and external secrets.
Next Chapter: Kubernetes Integration