HashiCorp Vault — Vault Agent Exercises

2 minute read

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.

  1. Create an AppRole agent-test with a policy that reads secret/data/myapp/*
  2. Write a Vault Agent config with AppRole auto-auth
  3. Write the token to a sink file
  4. 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.

  1. Store database credentials in secret/myapp/db
  2. Write a template that renders them as a .env file
  3. Configure Vault Agent to render the template
  4. 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.

  1. Configure agent with a local TCP listener on port 8100
  2. Enable caching with use_auto_auth_token
  3. Point VAULT_ADDR to the local agent
  4. 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