AWS/Secrets Manager/Secret/Rotation
AWS/Secrets Manager secret rotation
Overview
- Rotation replaces a secret's stored value with a new one; see Secret/Rotate for the concept independent of any specific secrets manager. There are three distinct rotation paths, not two, and all of them are opt-in — creating a secret never enables rotation by default. Rotate AWS Secrets Manager secrets — the User Guide's own top-level split: "There are two forms of rotation: Managed rotation ... Managed rotation doesn't use a Lambda function ... Rotation by Lambda function – For other types of secrets, Secrets Manager rotation uses a Lambda function to update the secret." (What that page calls "Lambda function" rotation splits again below into a ready-made-template path and a fully custom path, which is why this page counts three.)
Supported
Path 1: managed rotation, no Lambda at all — gated by how the secret was created, not by its shape
- Only for secrets created through the owning service's own integration: Amazon RDS, Aurora, and DocumentDB master credentials, Amazon Redshift admin passwords, ECS Service Connect TLS certificates, and Secrets Manager managed external secrets (held by Secrets Manager partners — not a database at all). Managed rotation for AWS Secrets Manager secrets — this is the definitive list of what qualifies: "Some services offer managed rotation, where the service configures and manages rotation for you. With managed rotation, you don't use an AWS Lambda function..."
- You cannot get this by hand-crafting your own
CreateSecret call, whatever shape you give it — it depends on which service's UI/API created the secret, not on JSON vs. plaintext. CreateSecret API reference, same page cited below for the schema requirement: "For secrets that use managed rotation, you need to create the secret through the managing service."
- Not just RDS/DocumentDB/Redshift — AWS ships ready-to-use templates for every RDS/Aurora engine (MySQL, PostgreSQL, MariaDB, Oracle, SQL Server, Db2, single- or alternating-user), DocumentDB, Redshift, and Timestream for InfluxDB. AWS Secrets Manager rotation function templates — the full, current list, with a template per engine: "AWS Secrets Manager provides a set of rotation function templates ... ready-to-use Lambda functions."
- Every template on that list requires the secret to be an AWS/Secrets Manager/Secret/KeyValue whose JSON matches the expected credential schema (
username, password, host, ...) — never a plain AWS/Secrets Manager/Secret/SecretString. CreateSecret API reference, the "For database credentials" paragraph: "For database credentials you want to rotate, for Secrets Manager to be able to rotate the secret, you must make sure the JSON you store in the SecretString matches the JSON structure of a database secret."
Path 3: a hand-written Lambda function — works on any secret, either shape, any product at all
- AWS also ships a generic rotation template as an unopinionated starting point, and nothing stops writing one from scratch for a secret belonging to no AWS product whatsoever (a third-party API key, say). AWS Secrets Manager rotation function templates, same page as Path 2's list: "Secrets Manager also provides a generic template that serves as a starting point for any type of secret." Unlike Path 2's ready-to-use templates, the generic template and a from-scratch function carry no schema assumption, so they work on a plain AWS/Secrets Manager/Secret/SecretString just as well as an AWS/Secrets Manager/Secret/KeyValue — the code decides how to parse and replace the value. This is the only rotation path available to a plain single-string secret, and the only one with no product restriction at all.
- Turn it on by attaching the function's ARN:
aws secretsmanager rotate-secret --secret-id "myapp/database-url" --rotation-lambda-arn "arn:aws:lambda:...". --secret-id names one whole secret — the / inside "myapp/database-url" is not a path into a JSON object; see AWS/Secrets Manager/Secret on why it's just an allowed naming character. Rotation always replaces that one secret's entire SecretString, never a sub-key of it. Example command lifted from fnox's AWS Secrets Manager provider docs, under its "Secret rotation" heading. - The four-step contract a hand-written rotation function must implement, per Write a rotation function — the same page the ready-made templates in Path 2 are built from, under "Four steps in a rotation function":
createSecret — generate the new value (e.g. a random password) and store it with put_secret_value, tagged AWSPENDING. Quote from that page: "Then it generates a new secret value ... Next it calls put_secret_value to store it with the staging label AWSPENDING."setSecret — push that AWSPENDING value into the actual database or service so the new credential becomes real there. Quote: "The method setSecret changes the credential in the database or service to match the new secret value in the AWSPENDING version of the secret."testSecret — connect using the AWSPENDING value to confirm it actually works before committing to it.finishSecret — promote AWSPENDING to AWSCURRENT; the label that used to be AWSCURRENT moves to AWSPREVIOUS. Quote: "the Lambda rotation function moves the label AWSCURRENT from the previous secret version to this version, which also removes the AWSPENDING label ... Secrets Manager adds the AWSPREVIOUS staging label to the previous version."- On an AWS/Secrets Manager/Secret/KeyValue secret, a correctly written
createSecret step reads the current AWSCURRENT JSON first and writes back the complete object with only the target field (e.g. password) changed. Secrets Manager itself performs no such merge — that is the function's own job, and it is exactly the job fnox skips, per the hazard noted below.
Versioned staging labels, used by every path above
- Secrets Manager keeps multiple value versions tagged with staging labels, so a rotation stages and tests a new value before promoting it — consumers are never left with zero valid credentials mid-rotation. What's in a Secrets Manager secret?, under "Secrets Manager labels a secret version": "The current version –
AWSCURRENT ... The previous version – AWSPREVIOUS ... The pending version (during rotation) – AWSPENDING."
Not supported
- No ready-to-use rotation template for a plain single-string secret. Path 2's templates target the known database/service credential JSON shapes only — see the template list above; an AWS/Secrets Manager/Secret/SecretString holding a bare API key, OAuth token, certificate, or private key has no ready-made equivalent — only Path 3 (a hand-written function, possibly starting from the generic template).
- Never automatic by default, on any path. A secret sits static until rotation is explicitly attached — either by creating it through a managing service (Path 1) or by attaching a Lambda ARN and schedule (Paths 2–3). Rotate AWS Secrets Manager secrets, same overview page cited at the top: "In Secrets Manager, you can set up automatic rotation for your secrets" — "can," not "does by default."
- fnox performs no rotation at all. It only reads whatever value AWS currently has. AWS Secrets Manager provider docs, "Secret rotation" section: "Direct reads fetch the current version. Refresh an encrypted sync cache or clear the daemon cache to pick up a rotated value." Rotation is configured only in AWS, never through fnox.
Interaction hazard: fnox writes vs. AWS-side rotation
fnox set overwrites a secret's entire SecretString with only the one value given on the command line — it has no read-merge-write for json_path. Verified directly in the fnox source at the commit this page cites: put_secret in aws_sm.rs does a bare put_secret_value/create_secret with whatever string it's handed, and the set command's call site passes it the one value the person typed, with no read-first step.- On an AWS/Secrets Manager/Secret/KeyValue secret, running
fnox set SOME_FIELD newvalue --provider aws against one json_path-scoped field clobbers every other key in that JSON. This is the opposite of the createSecret step described in Path 3 above, which reads AWSCURRENT first and writes back the whole object with only the changed field touched — fnox set has no equivalent read step, rotation-aware or not.