Dynamic credentials with OpenBao and Vault

September 18, 2026

Dynamic credentials with OpenBao and Vault

September 18, 2026
Dynamic credentials with OpenBao and Vault

TL;DR

  • A static database password is a secret with no expiry date, known to everyone who has ever seen it. Dynamic credentials replace it with a user that is created when you ask for it and deleted when its lease ends.
  • We run OpenBao for this, for ourselves and for customers, because the database, SSH and PKI engines are all in the open source build and the licence is one we can plan around.
  • The weak point is not the technology, it is the workflow. If getting a credential takes longer than finding the old shared password, the shared password wins.
  • We wrote Transikey, an open source desktop client for OpenBao and Vault, so that the secure path is also the quick one: sign in, pick a role, copy a psql or ssh command.
  • It is a release candidate. We have tested it on macOS, and the Windows and Linux packages build but need people to try them.

When we take over the running of a platform, one of the first things we usually find is a database password that is older than most of the team. It lives in a wiki page, in a few shell histories, in a CI variable that nobody dares to touch, and in the head of somebody who left two years ago. Rotating it means a change request, a maintenance window and a list of applications that nobody is completely sure about, which is why it never gets rotated.

Dynamic credentials remove the thing being protected rather than protecting it better. This post covers why static secrets fail the way they do, how the database and SSH secrets engines fix that by construction, why we standardise on OpenBao, and the workflow problem that stops most teams from getting the benefit. That last part is why we wrote a desktop client and made it open source.

A static password is a secret with no expiry date

I once watched a penetration tester at a large financial institution gain access to a production database because a DBA had left a plaintext file containing the password on his laptop. It was a hard lesson for everyone, and the only good part of it was that a tester found it rather than an attacker. The consequences could have been dire.

And do not get me started on sharing passwords over Slack or Teams.

The problem is not password strength. However many special characters you use, and whether or not the passphrase is a line of poetry, the password is static. Once somebody else has hold of it, you are done for, and you usually have no way of knowing that it happened.

SSH keys have the same shape. They are ubiquitous now, and every cloud environment expects one for login, but the private key sits on a work laptop. If you lose control of that laptop you have a long list of places where access has to be revoked. Even if you can remember them all, it may already be too late.

A dynamic credential is created on request and deleted on expiry

Dynamic credentials turn the model around. Instead of storing a password, the secrets manager holds a privileged connection to the database and a recipe for creating users. When I ask for access, it creates a brand new database user for me, hands me the username and password together with a lease, and drops that user again when the lease runs out.

This is the role we use in our test environment, which gives read-only access to PostgreSQL for ten minutes at a time:

bao write database/roles/readonly \
  db_name=postgres \
  creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
  default_ttl=10m \
  max_ttl=1h

bao read database/creds/readonly

Everything that was wrong with the shared password is now fixed by construction rather than by policy.

The same four problems, before and after
Question Shared static password Dynamic credential
Who ran this query? One account in the audit log, used by everyone and everything. A username that maps to one person and one request.
When does access end? When somebody remembers to rotate it, which is to say never. At the end of the lease, whether or not anyone is paying attention.
How do I revoke one engineer? Rotate the password, then find every application that used it. Revoke one lease. Nobody else notices.
What is the blast radius of a leak? Everything the account can reach, for as long as the password lives. One role's permissions, for the remainder of a short TTL.

The same idea applies to SSH. The SSH secrets engine will either sign your public key into a certificate that is valid for half an hour, or issue a one-time password that a PAM helper on the server verifies and then throws away. In both cases you get to delete the authorized_keys files that nobody has reviewed since the server was built.

In both cases, if you do lose control of the credential, there is only a very short window in which it is worth anything to an attacker.

We have been using dynamic credentials for databases for years. We wrote vals-operator a long time ago for exactly this purpose, so that passwords for our Kubernetes applications rotate automatically.

We use OpenBao because the engines we need are in the open source build

We compared HashiCorp Vault and OpenBao when the licence changed, and more recently we wrote about migrating from Vault Enterprise to OpenBao or free Vault. The short version of our position is that OpenBao is a Linux Foundation project under an OSI-approved licence, the database engine, the SSH engine, PKI and OIDC login are all in the open source build, and the HTTP API is the one your tooling already speaks. We use it ourselves for PKI and for dynamic database credentials, and we run it for customers alongside Vault.

Because the two share an API, everything in this post works against Vault as well.

Dynamic credentials fail on workflow, not on technology

The technology is the easy part. What we see going wrong is the daily workflow around it.

An engineer who is paged at three in the morning needs a database prompt in front of them in seconds. The secure route is to log in to OpenBao, remember which mount and which role to use, read the credential, copy a generated username and a generated password, and assemble a psql command around them. The insecure route is the password in the wiki. Under pressure people take the route that works first, and once the shared password has been used during an incident it has quietly become the process again.

SSH is worse, because signing a key means saving the result under exactly the right filename and knowing which ssh options make the client use it. Sharing a secret with a colleague has the same shape: response wrapping gives you a token that reveals the secret exactly once and tells you if somebody else got there first, but very few people remember the commands, so the secret goes into a chat message instead.

None of this is a criticism of the CLI, which is fine for automation. It is simply complex, and without the right tooling it can be cumbersome for a human being in a hurry.

Transikey makes the secure path the quick one

Transikey is a desktop client for OpenBao and HashiCorp Vault that we wrote to close that gap. It is a single Flutter codebase that builds for macOS, Windows and Linux, it is open source under Apache 2.0, and it talks to the standard HTTP API, so it needs nothing installed on the server.

You sign in with a token, userpass, LDAP, OIDC through your browser, or AppRole. From there the screens follow the jobs people actually have. In the database section I pick a role and press one button, and the card shows the username and password masked until I choose to reveal them, a countdown for the lease that goes from green to yellow to red, and buttons to renew or revoke it. Underneath is the part I use most, which is a ready-made command that I can paste straight into a terminal:

PGPASSWORD='<password>' psql -h 'db.internal' -p 5432 -U '<username>' -d 'orders'

The SSH section does the same for both engines. I upload my public key, the app has it signed and offers to save the certificate next to the key, and then gives me the ssh -i ... -o CertificateFile=... command to go with it, or it generates a one-time password and the matching ssh line. The sharing section wraps a secret and produces a transikey:// link that opens the recipient's app with everything filled in, plus a bao unwrap one-liner for anyone who does not have the app.

Requesting a dynamic PostgreSQL credential and copying the generated command.

A client for a secrets manager is a tempting target, so we were deliberate about it

Security decisions in the client, and what each one is defending against
Decision What it prevents
The token is held in memory and in the operating system keystore, nowhere else. A token sitting in a config file that gets backed up, synced or copied.
Secrets stay hidden until you ask to see them, and the clipboard is cleared after thirty seconds. Shoulder surfing, screen sharing, and a password living in the clipboard all afternoon.
The session locks itself when you walk away. An unlocked laptop being an unlocked route into production.
Logs record the method, the path and the status of each request, never a header or a body. Credentials leaking into a log file or a support bundle.
Generated commands pass passwords in environment variables such as PGPASSWORD, not as arguments. The password showing up in ps output and in shell history.
The client refuses to follow HTTP redirects. A redirect quietly sending your token to a server you did not choose.
Signing out revokes the tokens the app obtained for you, and leaves a token you pasted in alone. Revoking the root token of your own test server on day one, which is how I learnt this.

Transikey is a release candidate, and we would rather say so

We develop and test it on macOS. The Windows and Linux packages are built by the release pipeline and have had far less attention, nothing is code signed yet, and OIDC follows the same flow as vault login -method=oidc but has not been tried against many identity providers.

Trying it takes one command, because the test environment ships with it

The repository includes a complete test environment, because a client for a secrets manager is not much use without a secrets manager to point it at. One command starts OpenBao in dev mode together with PostgreSQL, OpenLDAP and an SSH server that trusts OpenBao certificates and one-time passwords, and configures the policy, the roles and the test users:

git clone https://github.com/digitalis-io/transikey.git && cd transikey
make gen        # fetch packages and generate code
make dev-up     # OpenBao, PostgreSQL, OpenLDAP and an SSH target
make run        # start the app

Packages for the three platforms are on the releases page. The policy in dev/init.sh is worth reading even if you never run the app, because it is the complete list of what a human user needs in order to work this way, and it is shorter than most people expect. If you try it, tell us what breaks. Windows and Linux reports are the most useful thing you could send us right now.

The client is the last ten per cent of the job

The rest is an OpenBao or Vault cluster that is highly available, unsealed automatically, backed up in a way that has been proven by a restore, wired to your identity provider, and connected to databases whose applications have been moved off their static passwords one at a time without an outage. That is the work we do for customers, and we support what we build with 24x7 managed services.

If a password older than your team is still in a wiki somewhere, the useful time to talk about it is before the next audit rather than after it.

Frequently asked questions

What is a dynamic credential?

A username and password, or an SSH certificate, that the secrets manager creates at the moment you ask for it and destroys when its lease expires. The secrets manager holds one privileged connection to the target system and a recipe for creating users, so no long-lived password for your account exists anywhere, including inside the secrets manager.

How is this different from rotating a shared password on a schedule?

Rotation shortens the life of a secret that is still shared. Everyone who holds it between rotations is indistinguishable in the audit log, revoking one person still means rotating for everyone, and every rotation is a coordination exercise with the applications that use it. A dynamic credential belongs to one person and one request, so revocation is a single lease and expiry needs nobody's attention.

Does this work with HashiCorp Vault as well as OpenBao?

Yes. OpenBao and Vault share the same HTTP API, so the database and SSH engine configuration in this post and the Transikey client both work against either. We run OpenBao ourselves and we run both for customers.

Why OpenBao rather than Vault?

OpenBao is a Linux Foundation project under an OSI-approved licence, and the parts we need - the database engine, the SSH engine, PKI and OIDC login - are all in the open source build. That makes the licensing position something we can plan around, and it does not force a tooling change, because the API is the one your existing automation already speaks.

What happens to an open session when the lease expires?

That depends on the target system and the role definition. In the PostgreSQL example the role is created with a VALID UNTIL expiry and dropped at the end of the lease, so new connections stop working. Set the default and maximum TTLs to match how the role is actually used, and renew the lease while you still need it rather than relying on a long TTL.

Does Transikey need anything installed on the OpenBao or Vault server?

No. It is a desktop application that talks to the standard HTTP API, and it signs in with a token, userpass, LDAP, OIDC through your browser, or AppRole. What it can do is entirely governed by the policy attached to the identity you sign in with.

Where does Transikey keep my token?

In memory and in the operating system keystore, and nowhere else. Secrets stay masked until you reveal them, the clipboard is cleared after thirty seconds, the session locks when you walk away, request logs never contain a header or a body, and the client refuses to follow HTTP redirects so that a redirect cannot send your token to a server you did not choose.

Is Transikey ready for production use?

It is a release candidate. It is developed and tested on macOS; the Windows and Linux packages are produced by the release pipeline and have had far less attention, nothing is code signed yet, and the OIDC flow has not been tried against many identity providers. Bug reports from Windows and Linux users are the most useful thing you can send right now.

How do I share a secret with a colleague without putting it in chat?

Use response wrapping. The secrets manager returns a token that reveals the secret exactly once and tells you if somebody else got there first, which turns an undetectable leak into a detectable one. Transikey wraps the secret for you and produces a transikey:// link that opens the recipient's app with the details filled in, plus a bao unwrap one-liner for anyone who does not have the app installed.

Still running on static database passwords?

Digitalis.io designs, builds and runs OpenBao and Vault clusters: highly available, automatically unsealed, backed up and restore-tested, wired to your identity provider, and connected to the databases that are still on shared credentials today.

If moving applications off static secrets without an outage is not where you want to spend the next quarter, get in touch at digitalis.io/contact.

References and related reading

Subscribe to newsletter

Subscribe to receive the latest blog posts to your inbox every week.

By subscribing you agree to with our Privacy Policy.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Ready to Transform 

Your Business?