Replacing Long-Lived PostgreSQL Passwords with Teleport Certificate-Based Access
Replace static PostgreSQL passwords with short-lived X.509 certificates issued after SSO. Teleport's Database Service brokers connections, enforces RBAC per human identity, and emits audit events without database agents. Includes worked example from tsh login through verified audit trail.
28 Jun 2026, 21:02 UTC

The problem with static database credentials
Long-lived PostgreSQL passwords create a persistent attack surface. They are often shared across teams, stored in CI/CD variables, and rarely rotated. When a credential leaks, the window for misuse lasts until someone remembers to change it — assuming they even know it was compromised. Auditing who did what becomes a forensic exercise because the same password maps to many humans.
Teleport addresses this by issuing short-lived X.509 certificates after a user authenticates through an identity provider (OIDC/SAML). Those certificates are then used to broker PostgreSQL connections through Teleport's Database Service and Proxy. The result: no static passwords in vaults, granular RBAC tied to human identities, and audit events that show exactly which certificate — and therefore which person — executed each query.
How the certificate flow works
When a developer runs tsh login --proxy=teleport.example.com --auth=okta, they complete an SSO challenge. Teleport's Auth Service verifies the identity, checks RBAC rules, and issues a user certificate (typically valid for 1–12 hours). That certificate is stored locally by tsh and presented automatically when the user runs tsh db connect.
The Teleport Database Service runs as a sidecar or separate host with network access to PostgreSQL. It terminates the client TLS connection, validates the user certificate, maps the Teleport principal to a PostgreSQL role (via db_users and db_names in the RBAC role), and forwards the connection to PostgreSQL using either certificate authentication or password proxying. The Proxy Service handles routing and records audit events (db.session.start, db.query) without requiring agents on the database host.
RBAC: least privilege per human, not per shared account
Teleport roles define which database labels, database users, and database names a principal may access. For example, a role named analytics-readonly might allow:
db_labels: { \"environment\": \"production\", \"team\": \"analytics\" }db_users: [\"readonly_reporter\"]db_names: [\"warehouse\"]
When a user with that role runs tsh db list, they only see databases matching those labels. They cannot escalate to postgres superuser or connect to the payments database because the certificate they receive encodes those restrictions. The Database Service enforces them at connection time.
Worked example: from SSO to a verified query
Assume a Teleport cluster at teleport.example.com with an OIDC connector named okta. The target PostgreSQL instance is registered with the label environment=staging and the database user app_reader.
- Authenticate (run on developer workstation):
tsh login --proxy=teleport.example.com --auth=oktaComplete the browser SSO flow.
tshstores the user certificate in~/.tsh/keys/teleport.example.com/. - List accessible databases:
tsh db list --format=jsonConfirm the target appears with the expected labels and
db_users. - Connect and inspect the issued certificate:
tsh db connect --db-user=app_reader --db-name=warehouse staging-warehouseThis command prints a
psqlconnection string that includessslcert,sslkey, andsslrootcertpointing to the short-lived certificate. You can also runtsh db connect --format=json staging-warehouseto see the certificate TTL (e.g.,\"ttl\": \"4h\"). - Run a test query (the previous command drops you into
psql; alternatively, pipe the connection string):psql \"$(tsh db connect --format=json staging-warehouse | jq -r .connection_string)\" -c \"SELECT current_user, now();\"Expected result:
current_usershowsapp_reader. - Verify audit trail (run on Teleport Auth Service host or via
tshwith audit permissions):tsh events ls --type=db.query --user=$(tsh status --format=json | jq -r .active_user) --since=1hLook for an event containing the query text and the certificate's subject (your SSO identity).
Required permissions: The developer needs a Teleport role that grants db_labels matching the target database, db_users including app_reader, and db_names including warehouse. The Teleport Database Service must run with a certificate that PostgreSQL trusts (configured in pg_hba.conf as hostssl all all 0.0.0.0/0 cert map=teleport with a usermap linking the certificate CN to app_reader).
Risks: If the IdP is unavailable, tsh login fails and no new certificates can be issued — existing certificates continue working until expiry. Ensure certificate TTLs (set in the Teleport cluster config auth_service.authentication.second_factor and role max_session_ttl) balance security with IdP outage tolerance.
Trade-offs and limitations
- Managed PostgreSQL constraints: Services like Amazon RDS or Azure Database for PostgreSQL may restrict
pg_hba.confor TLS parameters. Certificate authentication often requires therds_iamorcloudsql_iamextensions instead of raw X.509. Teleport's password proxying mode can work, but it re-introduces a shared secret (the Database Service's static password) unless you rotate it via Teleport'sdb_tokenmechanism. - Version compatibility:
tsh, Auth Service, Proxy, and Database Service must share the same major.minor version (e.g., all 16.x). Mismatched releases cause certificate validation errors or missing audit fields. Pin versions in your deployment pipeline. - Operational overhead: You now manage a control plane (Auth, Proxy, Database Service), certificate rotation, and RBAC policies instead of a few static passwords. Plan for monitoring the Auth Service health, certificate expiry alerts, and audit log shipping to a SIEM.
- Audit visibility is opt-in: Session recording (
db.session.record) and query logging require explicit configuration in the Teleport cluster YAML and the database registration resource. They are not enabled by default in the open-source edition.
Next steps for a staging rollout
- Deploy a Teleport cluster (single-node Auth+Proxy+Database Service is fine for testing) with your OIDC connector.
- Register one PostgreSQL instance using
tctl create -f db.yamlwith a label likeenv=staging. - Create a test role granting
db_users: [\"staging_reader\"],db_names: [\"staging_db\"], and the matching label. - Assign the role to a test SSO group, then run the worked example above end-to-end.
- Confirm audit events appear in the Teleport Web UI (
Activity → Database) and that certificate TTLs match your policy. - Document the
pg_hba.confchanges required for production PostgreSQL hosts and validate them against your managed-service constraints.
Once the staging flow works, you can retire the shared password from your secret store and enforce certificate-only access through Teleport RBAC.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.