Teams understand the value of rotating secrets:
Great, rotation is a best practice. But when is the last time your team rotated a third-party service token or even your database credentials? If it was recently, how long did that process take?
Performing manual rotation is risky and cumbersome. Individuals with access to production running manual workflows for every secret, every N days? Not going to happen. Like any good “thing that has to be done over and over” — this process is ripe for automation, provided it can be done safely.
Doppler is in a unique position to build rotation automation because teams already:
However, a secret rotation feature needs to check some very important boxes before it can trusted for production use.
All rotation state data, including credentials and sensitive parameters, must be encrypted to the same standards as any other secret in our system.
Rotation must occur in “one shot”. Keeping all rotation operations atomic ensures that applications that fetch secrets from Doppler will always receive a valid (i.e. working) credential — even if Doppler’s infrastructure is interrupted (e.g. power or network failure).
Doppler will facilitate rotation via third-party integrations and integration points which are infamous for being the most brittle parts of any software system. Some errors that the engine encounters can be retried, while others will require user intervention.
Above all, data loss must not be possible. If an error or interruption occurs during any point in the rotation process, Doppler’s rotation engine must be able to recover without an issue.
If a secret source (e.g. a database) isn’t publicly accessible, it won’t need to be made public for Doppler to rotate its secrets. Automatic rotation is meant to improve your security posture, not trade one set of risks for another.
We used an interesting strategy to meet this requirement, and the solution deserves its own post. Keep an eye out for our next rotation post on Proxied Rotation to learn more.
To make automatic rotation safe and atomic, we can’t just go revoking old API keys and generating new ones. We need to generate a new key, transition applications to use it, and revoke the old key when it is no longer in use.
Doppler accomplishes this by always maintaining two valid credentials: the active and the inactive. Every N days (we call this the rotation interval), the active credential becomes the inactive credential and the inactive credential is updated or replaced with a new active credential.
Let’s take database rotation on a 15-day rotation interval as an example:
With this strategy, each credential is valid for two rotation intervals (2*N days). As long as applications fetch secrets from Doppler with at least this frequency, they’re guaranteed to always be holding a valid credential.
Doppler supports two types of rotation: Updater and Issuer
The database rotation example above is updater rotation. The user provides Doppler with two starting credentials and Doppler updates them “in-place”.
Not all credentials can be updated in place; some need to be freshly created and revoked. With issuer rotation, the user provides parameters for creating new credentials and Doppler will revoke and reissue credentials to perform the rotation.
Let’s take SendGrid API key rotation with a 15-day rotation interval as an example:
Like the update strategy, applications are guaranteed to always fetch a valid credential as long as they re-fetch at least once every two rotation intervals. The difference with issuer rotation is that we’re continuously revoking old credentials and issuing new ones.
To meet the atomic rotation and encryption requirements, Doppler stores rotation state as a tokenized JSON string.
For those unfamiliar with tokenization: All sensitive data in Doppler is stored and managed by an isolated tokenization service in our infrastructure. Our web applications exchange sensitive data for tokens and vice versa. There’s more information on tokenization in our security facts sheet.
Here’s an example JSON state object for a SendGrid rotated secret:
We found this structure to be sufficiently generic to accommodate all types of rotated secrets, while still allowing our core logic to perform rotation operations abstractly.
When a rotation is performed, the rotation engine applies the necessary changes, builds new state, and commits the tokenized JSON object to the database.
The rotation state must always be accurate to meet our atomicity requirements, but interruptions (e.g. power or network failure) make this tricky for updater rotations.
To update a database password, the rotation engine needs to:
This leaves a critical period between steps 2 and 3 where our engine could experience an interruption (e.g. power or network failure). When rotation is attempted after the interruption, our state might be out-of-sync with the true state of the database. Big yikes.
To avoid this, we generate a new password and immediately commit the credential to the Doppler database in the pendingCredential field. This occurs before we attempt to update the DB user’s password in the source database. If the engine encounters an interruption, it can check the pendingCredential field during the next attempt. If a pending credential is present, the engine can test the pending username and password to verify whether or not the credential was truly updated.
Issuer rotation isn’t affected by this problem, but the engine is careful to ensure that the old credential is revoked (or missing, to be resilient to interruptions) before issuing the next credential. This ensures that used credentials are not “abandoned” in error scenarios.
Whenever rotated secret state is created or updated, the rotation engine saves the resulting secrets as “injected secrets” into the config. This allows advanced functionality like config logs, sync integrations, webhooks, secret references, and access logs to work for rotated secrets the same way they do for static secrets.
For example, if our rotated database secret was named DB_USER, then the secrets DB_USER_NAME, DB_USER_PASSWORD, and DB_USER_SECRET would all be available in the config.
Integrating Doppler into your deployment process is the most reliable way to ensure that your applications are always consuming valid secrets. When a secret is rotated, the new injected secret values are immediately synced to any integrations you’ve configured, just like any other secret change in Doppler. Automatic restarts can be implemented with the Doppler Secrets Operator, External Secrets Operator, or a webhook automation.
In order for automatic rotation to be useful, error states need to be friendly and the dashboard needs to provide clear directions to users on how to resolve problems.
Doppler distinguishes between:
Whenever an error requires user intervention, we notify users with the appropriate permissions to correct the issue via email.
Manual rotation is complex, time-consuming, and error-prone. We believe that automation is the answer — but only if the tooling is secure, reliable, and fails gracefully when necessary. After all, a tool is only as good as its failure modes.
Why not kick the tires and see for yourself?
Trusted by the world’s best DevOps and security teams. Doppler is the secrets manager developers love.