CoursesAdvanced secrets managementDynamic secrets & crypto engines

Dynamic secrets at scale

Database and cloud engines, leases, max_ttl, and revocation trees.

Advanced35 min · lesson 4 of 15

Static secrets are inventory you must guard, find, and rotate; dynamic secrets are generated on demand, scoped to one consumer, and destroyed on a schedule. This is the single highest-leverage move in secrets management: instead of storing a database password and handing out copies, Vault holds admin credentials to the database and mints a brand-new, uniquely-named user for each consumer, valid for minutes. When the lease ends, Vault drops the user. There is nothing standing to steal.

Leases, TTL, and max_ttl

Every dynamic secret comes with a lease: a TTL after which it is automatically revoked, and a max_ttl beyond which it cannot be renewed no matter what. The consumer renews the lease while it is still working and simply stops when it is done; the credential then expires on its own. This makes the default state of every credential "about to die," which is exactly backwards from the static world where the default is "valid forever." Tuning TTLs is the core operational dial: short enough that a leak is brief, long enough that renewal traffic and revocation load stay sane.

terminal — dynamic database credentials
# configure once: Vault holds the privileged connection + a role template
$ vault write database/roles/payments-ro \
db_name=app-postgres \
creation_statements="CREATE ROLE \"{{name}}\" LOGIN PASSWORD \x27{{password}}\x27 VALID UNTIL \x27{{expiration}}\x27; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
default_ttl=20m max_ttl=1h
# each consumer gets its own short-lived user:
$ vault read database/creds/payments-ro
username v-kubernetes-payments-ro-x7Qb... # unique, per-request
password A1b2C3...
lease_id database/creds/payments-ro/9f2.. lease_duration 20m
# done early? kill it now — everywhere:
$ vault lease revoke database/creds/payments-ro/9f2..

Revocation trees: pulling one thread unravels the branch

Leases form a tree. A token’s lease is the parent of every secret leased with it; revoking the parent revokes the whole subtree. This is the mechanism behind incident response: revoke the token an attacker stole and every database user, cloud key, and certificate it ever leased dies with it, atomically. It is also why you scope tokens per workload — a shared token means a shared revocation blast radius, and you lose the ability to cut off one compromised consumer without cutting off the rest.

Static vs dynamic — what an attacker gets
static credential
one shared password
copied everywhere
valid until someone rotates
months, usually
revoke = rotate for all
coordinated outage
dynamic credential
unique per consumer
attributable in DB logs
minutes-long lease
expires itself
revoke one leaf
others untouched
Dynamic secrets convert "rotate the world" into "let the lease expire" — and make DB audit logs actually attributable.

The same pattern for cloud and beyond

Databases are the gateway drug; the same engine model covers cloud IAM (Vault assumes a role and vends short-lived AWS/GCP/Azure credentials), message queues, PKI (the next lesson), and SSH. The design rule is identical everywhere: Vault holds one privileged, tightly-audited root credential, and consumers never see it — they receive disposable, scoped children. Your job shrinks to protecting a handful of engine root credentials and rotating those on a schedule, instead of chasing thousands of copies.

The engine root credential is now the crown jewel — rotate it
Dynamic secrets concentrate risk: the database or cloud credential Vault uses to mint users is highly privileged and long-lived. Give it exactly the grants it needs to create/drop scoped users (not full admin where avoidable), put it behind Vault’s own rotation (vault write -f database/rotate-root/...) so even you no longer know it, and alarm on its direct use outside Vault. A compromised engine root is a compromise of everything it can mint.