Skip to content
7 min read·Lesson 5 of 8

Static and Dynamic Secrets

Use the KV v2 engine for static secrets and database/AWS/PKI engines to generate short-lived dynamic credentials on demand.

"Secret engines" are Vault's pluggable backends for managing secrets. Some store data you give them (static); others generate fresh credentials on demand (dynamic). Both are central to a real Vault deployment.

The KV v2 Engine (Static Secrets)

The Key/Value version 2 engine is the simplest — Vault as an encrypted key-value store with versioning. It's enabled by default at secret/ on new Vault installations.

vault kv put secret/database/master \
  username=app \
  password='Tr0ub4dor&3'

vault kv get secret/database/master                          # latest version
vault kv get -version=1 secret/database/master               # specific version
vault kv get -field=password secret/database/master          # just one field
vault kv metadata get secret/database/master                 # see all versions

KV v2 features

  • Versioning: Every write creates a new version; old versions are retrievable until purged
  • Soft delete: vault kv delete marks a version as deleted but recoverable
  • Destroy: vault kv destroy permanently removes a version
  • Check-and-set (CAS): Prevent racy overwrites by requiring the current version number
  • Metadata: Per-secret max versions, delete-after, custom metadata

The data/metadata path split

KV v2 uses two API paths:

PathPurpose
secret/data/fooThe actual data — used by the API and policies
secret/metadata/fooVersions, deletion, config — used by the API and policies

Critical: in policies, write secret/data/foo for reading the value. Forgetting /data/ is the #1 reason new operators see "403 Forbidden" on a KV v2 mount.

Dynamic Secrets: The Big Idea

Static secrets work, but every static secret is a long-lived liability. Dynamic secrets flip the model: rather than store one shared password, Vault generates a unique credential per consumer at the moment they need it, with a short lease.

Benefits:

  • No long-lived passwords to rotate or distribute
  • Per-consumer credentials → per-consumer audit
  • Lease expiration automatically revokes — no orphaned access
  • Compromise window measured in minutes, not months

Database Secrets Engine

Vault connects to your database with an admin credential it uses only to create/drop users. Each consumer asks Vault for a credential, Vault creates a fresh DB user, returns the credentials, and tracks the lease.

# 1) Enable the engine
vault secrets enable database

# 2) Configure the connection
vault write database/config/orders-db \
  plugin_name=postgresql-database-plugin \
  allowed_roles=app-role,readonly-role \
  connection_url="postgresql://{{username}}:{{password}}@orders.db.acme:5432/orders?sslmode=require" \
  username=vault-admin \
  password='<rotate-after-init>'

# 3) Define a role
vault write database/roles/app-role \
  db_name=orders-db \
  creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; \
                       GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
  default_ttl=1h \
  max_ttl=4h

# 4) Consumer reads creds
vault read database/creds/app-role
# Returns: username=v-app-role-aXyZ..., password=..., lease_id=..., lease_duration=1h

One hour later, Vault drops the role from Postgres and the credential becomes useless. The application either renewed the lease (extending its TTL) or fetched a new credential.

The same plugin model supports MySQL, MariaDB, MongoDB, MS SQL Server, Cassandra, Elastic, Snowflake, Redis, and ~30 other databases.

AWS Secrets Engine

Vault generates AWS credentials on demand:

ModeWhat Vault returns
iam_userA freshly created IAM user + access keys (cleaned up on lease expiry)
assumed_roleSTS-assumed-role credentials (short-lived by STS design)
federation_tokenSTS GetFederationToken credentials
vault write aws/roles/s3-reader \
  credential_type=assumed_role \
  role_arns=arn:aws:iam::123:role/s3-reader

vault read aws/sts/s3-reader ttl=15m
# Returns: access_key, secret_key, session_token, lease_id, ttl=15m

Same pattern works for Azure (azure engine), GCP (gcp engine), Alibaba, OCI.

PKI Secrets Engine: Vault as a CA

The PKI engine turns Vault into a Certificate Authority. You configure a root or intermediate CA, define roles that constrain CN/SAN/key length/lifetime, then consumers request certs:

vault write pki_int/roles/internal-app \
  allowed_domains="svc.cluster.local" \
  allow_subdomains=true \
  max_ttl=24h

vault write pki_int/issue/internal-app \
  common_name="orders.svc.cluster.local" \
  ttl=24h
# Returns: certificate, private_key, ca_chain, serial_number, lease_id

Pair this with Vault Agent or cert-manager and you get fully automated, short-lived TLS certificates across your fleet — no more manual cert rotations.

Other Notable Secret Engines

  • SSH: Issues SSH OTPs or signed SSH certificates (no more static SSH keys)
  • Kubernetes: Generates short-lived K8s service-account tokens
  • Consul: Generates Consul ACL tokens dynamically
  • RabbitMQ, Nomad, MongoDB Atlas, GitHub: Each generates dynamic creds for its target
  • TOTP: Stores and generates TOTP codes (passes the codes through, doesn't store the secret long-term)

Leases and Revocation

Every dynamic secret is paired with a lease:

vault list sys/leases/lookup/database/creds/app-role
vault read sys/leases/lookup -format=json lease_id=database/creds/app-role/abc...
vault lease renew database/creds/app-role/abc...
vault lease revoke database/creds/app-role/abc...
vault lease revoke -prefix database/creds/app-role     # revoke all

The lease is the auditable record of "Vault gave X to Y at time T, valid until T+TTL". When you suspect compromise, vault lease revoke -prefix is your incident-response tool.

Migrating from Static to Dynamic

Most teams adopt Vault in phases:

  1. Move existing static secrets out of code into KV v2 (instant security win)
  2. Add dynamic credentials for new services, side-by-side with the static
  3. Retire the static credentials as services migrate
  4. Eventually, no service holds a long-lived database password

This pragmatic migration matters — going dynamic-everywhere on day one is a recipe for an outage. Build the muscle gradually.

Key Takeaways

  • KV v2 stores static secrets with versioning, soft-delete, and metadata.
  • Dynamic secrets are generated per request, leased, and automatically revoked when the lease expires.
  • The database secrets engine creates short-lived DB users/passwords for Postgres, MySQL, Mongo, SQL Server, and more.
  • The AWS secrets engine generates IAM users or STS-assumed-role credentials on demand.
  • The PKI secrets engine turns Vault into a Certificate Authority issuing short-lived TLS certs.

Test your knowledge

Try exam-style practice questions to reinforce what you've learned.

Practice Questions →