Vault’s dynamic database secrets are like a phantom key that only exists when you need it, for exactly as long as you need it.
Let’s watch it in action. Imagine a web application that needs to connect to a PostgreSQL database. Instead of hardcoding credentials or managing a rotating password file, it asks Vault for them.
# From the application server, assuming vault is configured and authenticated
export VAULT_ADDR="http://127.0.0.1:8200"
export VAULT_TOKEN="s.abcdef1234567890" # In a real app, this would be a role-based token
# The app asks Vault for credentials for the 'webapp' role
vault read database/creds/webapp
And Vault spits out temporary credentials:
Key Value
--- ---
lease_id database/creds/webapp/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
lease_duration 768h
password v2_temp_user_yK4xZ5
username v2_temp_user_yK4xZ5
The application uses v2_temp_user_yK4xZ5 and v2_temp_user_yK4xZ5 to connect to PostgreSQL. As soon as the application closes its database connection, Vault’s lease manager notices. If the lease duration expires, Vault automatically revokes these credentials and cleans up the associated database user. The next time the application asks, Vault generates new credentials, potentially with a different username and password, and a new lease.
This whole dance is orchestrated by a Vault database secrets engine. You configure it once, pointing it to your database and providing a static "admin" or "root" credential that Vault uses to connect and manage users. Then, you define roles within that engine. A role specifies:
-
Database connection details: Host, port, username, password, and database name (e.g.,
postgres://vault_admin:vault_admin_pass@db.example.com:5432/mydatabase). -
Credential generation configuration: How to create new users and passwords. For PostgreSQL, this might be
CREATE USER {{name}} WITH PASSWORD '{{password}}'; GRANT CONNECT ON DATABASE mydatabase TO {{name}};. -
Revocation logic: What SQL statement to run when credentials are no longer needed, like
DROP USER {{name}};. -
Lease duration: How long the generated credentials are valid.
The application itself doesn’t need to know about revocation. It just asks for credentials, uses them, and disconnects. Vault handles the rest, ensuring that every connection uses fresh, short-lived credentials. This drastically reduces the attack surface; a compromised credential is only useful for a very short window, and the user account it represents is deleted shortly thereafter.
The most surprising truth is that Vault doesn’t store the dynamic credentials it generates. It dynamically creates them on demand based on templates and then registers them with the database. When the lease expires, it uses another pre-configured superuser account to issue a DROP USER command. The credentials themselves are ephemeral, never existing in a persistent store within Vault.
If you’re using Vault’s dynamic database secrets and find that users are not being dropped from your database after their lease expires, the most likely culprit is the revocation_user or revocation_password configured in your database secrets engine. Vault needs these static, privileged credentials to connect to the database and execute the DROP USER command. If they’re incorrect, expired, or lack the necessary DROP USER privileges, the cleanup will fail, leaving orphaned database users behind.