Secrets management
Secrets Manager versus Parameter Store SecureString, rotation with Lambda and managed rotation, single-user and alternating-user strategies, cross-account secrets, caching, and keeping secrets out of code, user data and environment variables.
Exam tasks: 5.3.1 (design management and rotation of secrets for workloads)
The decision: where does each credential live, how does it rotate without an outage, who can read it (and from which account), and how does the application fetch it without the value ending up in code, images or logs?
Where to store it
| Secrets Manager | Parameter Store SecureString | |
|---|---|---|
| Built-in rotation | Yes: managed rotation or a Lambda function on a schedule | No; build your own with EventBridge and Lambda |
| Max value size | 64 KB | 4 KB standard, 8 KB advanced tier |
| Encryption | Always, with aws/secretsmanager or a customer managed key | KMS, with aws/ssm or a customer managed key |
| Resource-based policy | Yes, per secret | No; advanced parameters can be shared through AWS RAM |
| Cross-account read | Resource policy + customer managed key | RAM share of an advanced parameter + key access |
| Multi-Region | Replica secrets that stay in sync | No; copy per Region |
| Versioning | Staging labels (AWSCURRENT, AWSPENDING, AWSPREVIOUS) | Numbered versions and labels |
| Cost | Per secret per month, plus API calls | Standard tier free |
| Good for | Database, API and third-party credentials that must rotate | Config values, feature flags, low-change secrets |
- Parameter Store can reference a Secrets Manager secret (
/aws/reference/secretsmanager/<name>), so tools that only read parameters can still get rotated secrets. - Prefer no secret at all: IAM roles for AWS APIs, IAM database authentication for RDS and Aurora, and Secrets Manager only where a password is unavoidable.
Rotation
Managed rotation
- Services that own the credential rotate it for you, with no Lambda function: for example RDS and Aurora with managed master user passwords, Redshift admin passwords, and some partner-held secrets.
- For RDS, set
ManageMasterUserPasswordand the password lives in Secrets Manager, rotating every 7 days by default. Nobody ever sees it in the console or in CloudFormation.
Rotation with a Lambda function
The function is called four times per rotation, one per step:
AWSPENDING.AWSCURRENT to the new version; the old one becomes AWSPREVIOUS.- Schedules can be as frequent as every 4 hours, with a rotation window during which the rotation may run.
- The function needs a network path to both the database and the Secrets Manager endpoint. In a private subnet with no NAT gateway, add an interface VPC endpoint for Secrets Manager. This is the most common cause of "rotation times out".
- It also needs
kms:Decryptandkms:GenerateDataKeyon the secret's key.
| Strategy | How it works | Trade-off |
|---|---|---|
| Single user | Changes the password of the one user the app uses | Brief window where connections using the old password fail; simplest |
| Alternating users | Two users (for example app and app_clone); each rotation updates the idle one and switches | No downtime; needs a separate admin secret with rights to change the other users |
Exam signal
"Rotate database credentials automatically with no downtime for a high-traffic application" means the alternating users strategy, or managed master user passwords for the master account. "Rotation fails with a timeout" in a private subnet points to a missing Secrets Manager VPC endpoint or NAT route.
Rotating the secret but not the app
Rotation only helps if the application reads the secret at run time. Applications that copy the password into a
config file at deploy time break at the next rotation. Use the caching client, the Lambda extension or native
integrations so the app picks up AWSCURRENT on its own.
Cross-account access
To let account B read a secret in account A:
- Resource policy on the secret in A allows the role in B
secretsmanager:GetSecretValue. - The secret is encrypted with a customer managed key, and its key policy allows the role in B
kms:Decrypt(usually withkms:ViaServiceset to Secrets Manager in that Region). - The IAM policy on the role in B allows both actions on the secret and key ARNs.
- Secrets encrypted with
aws/secretsmanagercan't be read cross-account, because you can't edit that key's policy. Re-encrypt with a customer managed key first. - Turn on
BlockPublicPolicyso a resource policy that grants broad access is rejected, and let IAM Access Analyzer flag secrets shared outside the organization.
Getting secrets into workloads safely
| Workload | Recommended way |
|---|---|
| Lambda | AWS Parameters and Secrets Lambda Extension (local cache over HTTP), not environment variables |
| ECS | secrets in the task definition referencing a Secrets Manager or Parameter Store ARN; injected at start, the task execution role needs access |
| EKS | Secrets Store CSI Driver with the AWS provider (ASCP), with EKS Pod Identity or IRSA for access |
| EC2 | Instance role plus SDK or Secrets Manager Agent; never in user data |
| CloudFormation | Dynamic references (resolve:secretsmanager:...) or ManageMasterUserPassword, never plaintext parameters |
| Any app | Client-side caching libraries to cut latency, cost and throttling |
Places secrets must never be:
- Source code and repositories. Run secret scanning (Amazon Inspector code security, or pre-commit hooks such as git-secrets), and treat anything already committed as compromised: rotate it.
- EC2 user data. Anyone with
ec2:DescribeInstanceAttributecan read it, and it's visible from inside the instance through the metadata service. - Lambda environment variables. With the default key, anyone allowed
lambda:GetFunctionConfigurationsees them in plaintext, and they can't rotate. Fetch the secret at run time instead. - Container images and AMIs. Anyone who pulls them gets the secret.
- Logs. Mask them with CloudWatch Logs data protection.
Scenarios
The function can't reach the Secrets Manager API to write the AWSPENDING version, so rotation times out at the first step. An interface endpoint gives it a private path. A longer timeout doesn't create a route, making the database public is a security regression, and CreateGrant isn't needed for rotation.
Cross-account secret access needs a KMS key the other account can use, which rules out the AWS managed key. Its policy can't be edited. Replicas stay in the owning account. BlockPublicPolicy restricts policies rather than granting access.
Secrets Manager provides rotation, and fetching at run time keeps the value out of user data and function configuration, which read-only principals can view. Base64 is encoding, not encryption. A String parameter is stored in plaintext and has no rotation. A password baked into an AMI is exposed to anyone who can launch it and can't rotate.
Further reading
Backup and ransomware protection
AWS Backup plans and org backup policies, Vault Lock modes, logically air-gapped vaults, cross-account and cross-Region copies, Data Lifecycle Manager, secure transfer with DataSync, integrity checks and restore testing.
Sensitive data
Finding sensitive data in S3 with Macie, masking it in CloudWatch Logs with data protection policies, SNS message data protection and S3 Object Lambda redaction (and their replacements), and choosing between masking, redaction, tokenization and encryption.