BBetterSignΒ· Web app ↔ Postgres, mutually authenticated 1 / 5

The app authenticates to Postgres with a password in its connection string
🌐
web app
πŸ”‘ password in DATABASE_URL
🐘
Postgres
caller: ???
password only
πŸ₯·
anyone with the password
looks the same to Postgres
gets in
The password sits in env files and code, gets copied across deploys, and leaks. Postgres cannot prove the caller is really your app.
πŸ“œ vlad-ca β€” trusts VLADs that pass enrollment
🐘 Postgres enrolls
β†’ prove control of its VLAD
← challenge / signed response
βœ“ vlad-ca issues its cert
🌐 web app enrolls
β†’ prove control of its VLAD
← challenge / signed response
βœ“ vlad-ca issues its cert
The vlad-ca trusts each instance because it enrolled β€” it cryptographically proved control of its VLAD, so the CA issues it a short-lived certificate.
The database owner decides which vlad-ca to trust as its one root
🏒
in-house vlad-ca
the owner runs it
🀝
trusted 3rd-party vlad-ca
a provider they trust
postgresql.conf
ssl = on
ssl_ca_file = the chosen vlad-ca root # trust ONLY this vlad-ca
pg_hba.conf: hostssl … clientcert=verify-full
Once the owner points Postgres at that root, it accepts a client because its certificate came from the trusted vlad-ca β€” including the web app's β€” and refuses anything that did not.
The web app connects β€” both sides prove themselves against the vlad-ca
🌐
web app
presents vlad-ca cert
βœ“ verified by Postgres
🐘
Postgres
presents vlad-ca cert
βœ“ verified by app
πŸ₯·
rogue app
cert from a different CA
β›” rejected β€” not signed by vlad-ca
Encrypted + mutually authenticated β€” no password in files or code. Imposters are rejected because their cert did not come from the vlad-ca.
The certificates are short-lived and renew with the vlad-ca on a regular cadence
🐘 Postgres rotates
β‘  new key β†’ signed plog entry
β‘‘ ask vlad-ca for a cert
β‘’ βœ“ fresh cert for the new key
↻ on a regular cadence
🌐 web app rotates
β‘  new key β†’ signed plog entry
β‘‘ ask vlad-ca for a cert
β‘’ βœ“ fresh cert for the new key
↻ on a regular cadence
Connections stay up. Rotation is just a plog update plus a cert request Β· no re-enrollment, no hand-rotation Β· Postgres keeps trusting because it trusts the vlad-ca, not a pinned cert