HashiCorp Vault — Database Secrets Engine
The database secrets engine generates unique, short-lived database credentials on demand. Vault creates a real database user, gives it to the client, and automatically drops it when the lease expires.
Architecture
┌──────────┐ ① Request creds ┌──────────┐ ② CREATE USER ┌──────────┐
│ App │──────────────────────▶│ Vault │───────────────────▶│ Database │
│ │ ④ user/password │ │ ③ user created │ │
│ │◀──────────────────────│ │◀───────────────────│ │
│ │ │ │ │ │
│ │ ⑤ Connect to DB │ │ │ │
│ │──────────────────────│──────────│───────────────────▶│ │
│ │ │ │ │ │
│ │ │ ⑥ Lease │ ⑦ DROP USER │ │
│ │ │ expires │───────────────────▶│ │
└──────────┘ └──────────┘ └──────────┘
Setup Overview
Three steps to configure dynamic database credentials:
| Step | What | Command Prefix |
|---|---|---|
| 1 | Enable the database engine | vault secrets enable database |
| 2 | Configure database connection | vault write database/config/... |
| 3 | Create roles (credential templates) | vault write database/roles/... |
Step 1 — Enable the Engine
vault secrets enable database
Step 2 — Configure Connection
Vault needs a privileged connection to the database to create/revoke users:
# PostgreSQL
vault write database/config/my-postgres \
plugin_name="postgresql-database-plugin" \
allowed_roles="app-readonly,app-readwrite" \
connection_url="postgresql://:@db.example.com:5432/mydb?sslmode=require" \
username="vault_admin" \
password="vault_admin_password"
⚠️ The
vault_adminuser must haveCREATEROLEor equivalent privilege to create new database users.
Rotate the Root Password
After configuration, rotate the root password so only Vault knows it:
vault write -f database/rotate-root/my-postgres
Now the original vault_admin_password is no longer valid — only Vault can access the database with admin privileges.
Step 3 — Create Roles
Roles define what credentials look like:
# Read-only role
vault write database/roles/app-readonly \
db_name="my-postgres" \
creation_statements="CREATE ROLE \"\" WITH LOGIN PASSWORD '' VALID UNTIL ''; \
GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"\";" \
revocation_statements="REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM \"\"; \
DROP ROLE IF EXISTS \"\";" \
default_ttl="1h" \
max_ttl="24h"
Understanding Creation Statements
| Placeholder | Value |
|---|---|
{{name}} |
Vault-generated unique username (e.g., v-approle-app-readonly-abc123) |
{{password}} |
Vault-generated random password |
{{expiration}} |
Timestamp when the lease expires |
Generate Credentials
vault read database/creds/app-readonly
Expected output:
Key Value
--- -----
lease_id database/creds/app-readonly/abc123
lease_duration 1h
lease_renewable true
password A1a-random-generated-pwd
username v-token-app-readonly-abc123-1234567890
Each call generates a new, unique credential pair.
Supported Databases
| Database | Plugin Name |
|---|---|
| PostgreSQL | postgresql-database-plugin |
| MySQL/MariaDB | mysql-database-plugin |
| MongoDB | mongodb-database-plugin |
| MSSQL | mssql-database-plugin |
| Oracle | oracle-database-plugin |
| Redis | redis-database-plugin |
| Elasticsearch | elasticsearch-database-plugin |
| Cassandra | cassandra-database-plugin |
| InfluxDB | influxdb-database-plugin |
| Snowflake | snowflake-database-plugin |
Static Roles (Password Rotation)
For applications that need a fixed username but want automatic password rotation:
vault write database/static-roles/my-static-role \
db_name="my-postgres" \
username="existing_app_user" \
rotation_period="24h" \
rotation_statements="ALTER ROLE \"\" WITH PASSWORD '';"
# Get current credentials
vault read database/static-creds/my-static-role
The username stays the same, but the password rotates every 24 hours.
Quick Reference
| Command | Description |
|---|---|
vault secrets enable database |
Enable database engine |
vault write database/config/NAME ... |
Configure connection |
vault write -f database/rotate-root/NAME |
Rotate root password |
vault write database/roles/ROLE ... |
Create dynamic role |
vault read database/creds/ROLE |
Generate credentials |
vault write database/static-roles/NAME ... |
Create static role |
vault read database/static-creds/NAME |
Get static credentials |
Next: PostgreSQL & MySQL