Chapter 8 of 16 · Application/workload user · orders-api

Dynamic PostgreSQL Credentials

Replace a shared database password with leased PostgreSQL users, least privilege, pool rotation, and revocation.

Chapter contract

Persona: Application/workload user · orders-apiPhase: Applications and pipelinesEstimated time: 55 minutes

Prerequisites:

Chapter 7 complete, PostgreSQL healthy, and the learner token available.

User-visible outcome:

orders-api can query PostgreSQL with a unique leased principal and prove revocation on a new connection.

Learning objectives

Consumer flow

Vault DB rolestep 1Generated DB userstep 2Connection poolstep 3Lease revocationstep 4

Ownership boundary

OwnerConsumer-facing responsibility
You ownDefines consumption, validation, reload, and stop-using behavior.
Platform team ownsProvides trusted runtime identity, protected delivery, network, and telemetry.
Vault ownsOperates auth mounts, policies, engines, audit, and recovery.

Core concepts

Database role

Maps a request to SQL creation and revocation statements.

Dynamic user

A unique principal generated for one lease.

Pool rotation

Build a replacement pool before draining old connections.

Root rotation

Change the privileged credential Vault uses to manage principals.

Commands and configuration

source learn-vault/.runtime/learner.env
cd learn-vault/labs/dynamic-db
./request-and-query.sh
jq '{lease_id_present:(.lease_id|length>0),lease_duration,renewable}' ../../.runtime/db-lease.json
./revoke.sh

Secret-safety stop

Stop: Do not pass generated passwords as command arguments. The lab injects them transiently inside the database container and never echoes them.

Failure drill

SymptomFresh credentials work, then the application gets password failures.
Likely causesLease expired, renewal failed, clock margin too small, or pool retained revoked principals.
Inspect safelyCheck lease age, renew result, pool generation, SQLSTATE class, and Vault health.
Do not printGenerated username, password, DSN, SQL environment, or lease response.

Break it / fix it

Break it: Revoke the dynamic DB lease before opening a new connection.

Show diagnosis and fix

Fix it: Acquire a new lease, validate a replacement pool, then drain the old generation.

Escalate with time, endpoint, auth path, role, mount, namespace when relevant, status code, request ID, and sanitized error class. Never attach a credential or response body.

Try it

Bootstrap boundary

labs/bootstrap owns the disposable server, auth mounts, policies, roles, and engines; learner actions begin after setup.

Cost:

$0; local containers only

Starting state:

Run labs/bootstrap/setup.sh and source .runtime/learner.env unless the chapter lab says AppRole alone is sufficient.

User actions:

Request a lease, run SELECT current_database(), revoke it, then prove a new connection fails.

cd learn-vault/labs/dynamic-db
./request-and-query.sh
jq -e '.lease_duration>0 and (.lease_id|length>0)' ../../.runtime/db-lease.json
./revoke.sh
./verify-revoked.sh
./cleanup.sh

Success criteria:

Complete every item in the Verify section using metadata-only evidence; no secret value appears in terminal output or tracked files.

Troubleshooting:

Use the Failure drill and Break it / fix it evidence fields. Stop before broadening policy, weakening identity or TLS checks, or copying secret-bearing diagnostics.

Verify

  1. The query reports only the expected database name.
  2. Lease metadata is finite and renewable.
  3. A new connection for the revoked principal is rejected.
Evidence rule: retain only status, policy names, TTLs, versions, timestamps, fingerprints, and error classes. Never retain secret values.

Cleanup

Revoke before deleting the response. Cleanup does both when a lease ID exists.

Project Lockbox increment

orders-api no longer owns a shared DB password; readiness tracks lease margin and pool generation.

Quick check

Why is a unique user useful?

It improves attribution and permits per-workload revocation.

Wait for expiry before replacing a pool?

No. Validate a new pool with margin, then drain the old one.

What may survive revocation briefly?

An already-established DB session.

Who reviews SQL grants?

The database owner; Vault policy cannot define database privilege.

Gotchas

Recap and next

Dynamic DB credentials reduce sharing, but applications must rotate pools before the lease clock wins.

Primary references

Continue →