Loading content...
AWS Secrets Manager represents Amazon's answer to the secrets management challenge—a fully managed service that eliminates the operational burden of running and scaling secrets infrastructure. For organizations deeply invested in the AWS ecosystem, Secrets Manager provides native integrations that make secrets access seamless across AWS services.
Unlike self-hosted solutions, Secrets Manager abstracts away the complexity of high availability, encryption key management, and infrastructure maintenance. You get a secrets API that integrates naturally with IAM, CloudFormation, and the broader AWS service catalog—paying only for what you use.
By the end of this page, you will understand AWS Secrets Manager's architecture, automatic rotation capabilities, integration patterns with AWS services, cross-account access strategies, and cost optimization techniques. You'll be equipped to design secrets management solutions for AWS-centric workloads.
AWS Secrets Manager is a secrets management service that enables you to easily rotate, manage, and retrieve database credentials, API keys, and other secrets throughout their lifecycle. It was purpose-built to solve the challenge of secrets sprawl in cloud environments.
Core Capabilities:
Secret Structure:
Secrets Manager stores secrets as encrypted blobs that can contain any data up to 64KB. The most common pattern is storing structured data as JSON:
12345678910111213141516171819202122232425
// Database credential secret{ "username": "admin", "password": "MyStr0ngP@ssword!", "engine": "postgres", "host": "mydb.cluster-abc123.us-east-1.rds.amazonaws.com", "port": 5432, "dbname": "production", "dbClusterIdentifier": "mydb-cluster"} // API key secret{ "api_key": "sk_live_abc123xyz789", "api_secret": "whsec_def456uvw321", "environment": "production"} // Third-party integration{ "client_id": "oauth_client_abc123", "client_secret": "cs_secret_xyz789", "token_endpoint": "https://auth.example.com/oauth/token", "scopes": ["read", "write"]}Use hierarchical naming with prefixes: 'prod/myapp/database/primary', 'dev/myapp/api/stripe'. This enables IAM policies that grant access to prefixes (e.g., 'prod/*') rather than individual secrets, simplifying permission management as your secret count grows.
AWS Secrets Manager implements multiple layers of security to protect secrets at rest and in transit. Understanding this security model is essential for designing compliant solutions.
Encryption Architecture:
Every secret is encrypted using envelope encryption with AWS KMS:
This means that to decrypt a secret, the caller must have:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
┌─────────────────────────────────────────────────────────────────┐│ SECRET CREATION FLOW │└─────────────────────────────────────────────────────────────────┘ Application Secrets Manager AWS KMS │ │ │ │ CreateSecret(value) │ │ │──────────────────────────────>│ │ │ │ GenerateDataKey() │ │ │─────────────────────────>│ │ │ │ │ │ Return: │ │ │ - Plaintext data key │ │ │ - Encrypted data key │ │ │<─────────────────────────│ │ │ │ │ │ Encrypt secret with │ │ │ plaintext data key │ │ │ │ │ │ Discard plaintext key │ │ │ │ │ │ Store: │ │ │ [encrypted_data_key] │ │ │ [encrypted_secret] │ │ │ │ │ Success (ARN, VersionId) │ │ │<─────────────────────────────│ │ ┌─────────────────────────────────────────────────────────────────┐│ SECRET RETRIEVAL FLOW │└─────────────────────────────────────────────────────────────────┘ Application Secrets Manager AWS KMS │ │ │ │ GetSecretValue(id) │ │ │──────────────────────────────>│ │ │ │ Decrypt(encrypted_key) │ │ │─────────────────────────>│ │ │ │ │ │ Return: plaintext key │ │ │<─────────────────────────│ │ │ │ │ │ Decrypt secret with │ │ │ plaintext data key │ │ │ │ │ Return: secret value │ │ │<─────────────────────────────│ │Choosing KMS Keys:
You have three options for the KMS key used to encrypt secrets:
| Aspect | AWS Managed Key | Customer Managed Key |
|---|---|---|
| Cost | Free | $1/month per key + API calls |
| Cross-Account Access | Not supported | Fully supported via key policy |
| Key Rotation Control | Automatic (annual) | Configurable (automatic or manual) |
| Key Policy Customization | Not allowed | Full control |
| CloudTrail Key Usage | Limited visibility | Full visibility |
| Compliance Requirements | May not meet strict requirements | Meets most compliance needs |
If you need to share secrets across AWS accounts, you must use a customer managed KMS key. The AWS managed key cannot grant cross-account decrypt permissions. Plan your KMS strategy early if you have multi-account architectures.
Automatic rotation is AWS Secrets Manager's most powerful feature, transforming credential rotation from a risky, manual process into an automated operation. Secrets Manager provides built-in rotation for AWS database services and supports custom rotation for any secret type.
Built-in Rotation Support:
| Service | Rotation Type | Mechanism |
|---|---|---|
| Amazon RDS (all engines) | Single user or alternating users | Lambda function manages DB users |
| Amazon Aurora | Single user or alternating users | Same as RDS |
| Amazon Redshift | Single user or alternating users | Lambda manages cluster users |
| Amazon DocumentDB | Single user or alternating users | Lambda manages DB users |
| Amazon ElastiCache Redis | Password rotation | Lambda updates replication group |
Rotation Strategies:
Secrets Manager supports two rotation strategies for database credentials:
1. Single User Rotation:
2. Alternating Users Rotation:
123456789101112131415161718192021222324
# Create a secret for RDS databaseaws secretsmanager create-secret \ --name prod/myapp/db/primary \ --secret-string '{"username":"admin","password":"InitialP@ssword123!"}' \ --kms-key-id alias/myapp-secrets # Configure automatic rotation (alternating users strategy)aws secretsmanager rotate-secret \ --secret-id prod/myapp/db/primary \ --rotation-lambda-arn arn:aws:lambda:us-east-1:123456789012:function:SecretsManagerRDSRotation \ --rotation-rules "{ "AutomaticallyAfterDays": 30, "ScheduleExpression": "cron(0 4 ? * SUN *)", "Duration": "2h" }" # Trigger immediate rotationaws secretsmanager rotate-secret \ --secret-id prod/myapp/db/primary # Check rotation statusaws secretsmanager describe-secret \ --secret-id prod/myapp/db/primary \ --query 'RotationEnabled, LastRotatedDate, NextRotationDate'Custom Rotation with Lambda:
For secrets not natively supported, you implement rotation using a Lambda function. The function receives events for four rotation steps:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
import boto3import jsonimport stringimport secrets as secrets_lib def lambda_handler(event, context): """ Rotation Lambda that follows the four-step rotation protocol. This example rotates an API key for a third-party service. """ arn = event['SecretId'] token = event['ClientRequestToken'] step = event['Step'] secrets_client = boto3.client('secretsmanager') if step == "createSecret": create_secret(secrets_client, arn, token) elif step == "setSecret": set_secret(secrets_client, arn, token) elif step == "testSecret": test_secret(secrets_client, arn, token) elif step == "finishSecret": finish_secret(secrets_client, arn, token) else: raise ValueError(f"Invalid step: {step}") def create_secret(client, arn, token): """Step 1: Create new secret version in AWSPENDING stage.""" # Get current secret current = client.get_secret_value(SecretId=arn, VersionStage="AWSCURRENT") current_dict = json.loads(current['SecretString']) # Generate new API key new_api_key = ''.join(secrets_lib.choice( string.ascii_letters + string.digits ) for _ in range(64)) # Create pending version with new key current_dict['api_key'] = new_api_key client.put_secret_value( SecretId=arn, ClientRequestToken=token, SecretString=json.dumps(current_dict), VersionStages=['AWSPENDING'] ) def set_secret(client, arn, token): """Step 2: Set the new credentials in the target service.""" pending = client.get_secret_value( SecretId=arn, VersionId=token, VersionStage="AWSPENDING" ) pending_dict = json.loads(pending['SecretString']) # Call external API to register new key # This is service-specific response = register_api_key_with_service( pending_dict['api_key'], pending_dict['client_id'] ) if not response.get('success'): raise Exception("Failed to register new API key") def test_secret(client, arn, token): """Step 3: Test that the new credentials work.""" pending = client.get_secret_value( SecretId=arn, VersionId=token, VersionStage="AWSPENDING" ) pending_dict = json.loads(pending['SecretString']) # Test the new API key if not test_api_key(pending_dict['api_key']): raise Exception("New API key validation failed") def finish_secret(client, arn, token): """Step 4: Move AWSPENDING to AWSCURRENT.""" # Get current version metadata = client.describe_secret(SecretId=arn) current_version = None for version_id, stages in metadata['VersionIdsToStages'].items(): if 'AWSCURRENT' in stages: current_version = version_id break # Move staging labels client.update_secret_version_stage( SecretId=arn, VersionStage='AWSCURRENT', MoveToVersionId=token, RemoveFromVersionId=current_version ) # Optionally revoke old API key # revoke_old_api_key(old_key)Rotation Lambdas should be idempotent—they may be retried if they fail. Deploy them in the same VPC as your databases for network access. Set appropriate timeouts (default 30 seconds may be too short). Monitor Lambda errors and set up alerting for rotation failures.
AWS Secrets Manager access control combines IAM policies with resource-based policies to provide fine-grained permissions. Understanding these patterns is essential for implementing least-privilege access.
Access Control Layers:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
// Read-only access to production secrets{ "Version": "2012-10-17", "Statement": [ { "Sid": "ReadProductionSecrets", "Effect": "Allow", "Action": [ "secretsmanager:GetSecretValue", "secretsmanager:DescribeSecret" ], "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/*", "Condition": { "StringEquals": { "secretsmanager:VersionStage": "AWSCURRENT" } } }, { "Sid": "ListSecrets", "Effect": "Allow", "Action": "secretsmanager:ListSecrets", "Resource": "*" }, { "Sid": "DecryptWithKMS", "Effect": "Allow", "Action": "kms:Decrypt", "Resource": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", "Condition": { "StringEquals": { "kms:ViaService": "secretsmanager.us-east-1.amazonaws.com" } } } ]} // Full management for secret administrators{ "Version": "2012-10-17", "Statement": [ { "Sid": "FullSecretsAccess", "Effect": "Allow", "Action": "secretsmanager:*", "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:*" }, { "Sid": "KMSAccess", "Effect": "Allow", "Action": [ "kms:Encrypt", "kms:Decrypt", "kms:GenerateDataKey" ], "Resource": "arn:aws:kms:us-east-1:123456789012:key/*" } ]}Common Access Patterns:
| Scenario | Pattern | Implementation |
|---|---|---|
| Lambda function needs secret | IAM role attached to Lambda | Add GetSecretValue + KMS Decrypt to Lambda execution role |
| ECS task needs secret | Task role + native integration | Reference secret ARN in task definition; ECS injects at runtime |
| EC2 application needs secret | Instance profile role | Grant role access; use SDK with instance metadata credentials |
| Cross-account access | Resource policy + KMS policy | Both secret and KMS key must allow the external account |
| Developer access for debugging | IAM group + MFA requirement | Time-limited access with assume role and MFA condition |
| CI/CD pipeline access | OIDC federation or IAM user | Short-lived credentials via OIDC preferred; rotate IAM keys |
For cross-account secret access, you must configure BOTH: (1) a resource-based policy on the secret allowing the external principal, AND (2) a key policy on the KMS key granting kms:Decrypt to the external principal. Missing either will result in access denied errors.
One of Secrets Manager's greatest strengths is deep integration with AWS services. These integrations enable secrets injection without application code changes.
Native Service Integrations:
1234567891011121314151617181920212223242526272829303132333435
{ "family": "my-app", "containerDefinitions": [ { "name": "app", "image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:latest", "secrets": [ { "name": "DB_USERNAME", "valueFrom": "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/myapp/db:username::" }, { "name": "DB_PASSWORD", "valueFrom": "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/myapp/db:password::" }, { "name": "API_KEY", "valueFrom": "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/myapp/api-key" } ], "environment": [ { "name": "DB_HOST", "value": "mydb.cluster-abc123.us-east-1.rds.amazonaws.com" } ] } ], "taskRoleArn": "arn:aws:iam::123456789012:role/MyAppTaskRole", "executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole"} // The execution role needs:// - secretsmanager:GetSecretValue// - kms:Decrypt (if using CMK)For Lambda functions that frequently access secrets, use the AWS Parameters and Secrets Lambda Extension. It provides local caching with configurable TTL, reducing API calls, latency, and costs. The extension runs as a sidecar process and serves secrets over localhost HTTP.
AWS Secrets Manager pricing is straightforward but can accumulate in high-scale environments. Understanding the cost model helps you optimize usage.
Current Pricing (as of 2024):
| Component | Price | Notes |
|---|---|---|
| Secret storage | $0.40/secret/month | Prorated; minimum 7 days per secret |
| API calls | $0.05 per 10,000 calls | GetSecretValue, DescribeSecret, etc. |
| Rotation Lambda | Standard Lambda pricing | Duration + invocation charges |
| KMS (if using CMK) | $1/key/month + $0.03/10K requests | Only if using customer managed keys |
Cost Optimization Strategies:
For simple secrets without rotation needs, SSM Parameter Store SecureString is an alternative at no per-secret charge. However, it lacks automatic rotation, cross-region replication, and fine-grained resource policies. Use Secrets Manager for database credentials and secrets requiring rotation.
Replica secrets (for cross-region replication) are charged at the same $0.40/month rate. A secret replicated to 3 regions costs $1.20/month total. Budget accordingly for disaster recovery configurations.
Effective monitoring ensures your secrets management implementation remains secure and operational. AWS provides comprehensive observability through CloudTrail, CloudWatch, and EventBridge.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
# CloudFormation for secrets monitoringResources: # Alarm for rotation failures RotationFailureAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: SecretsManager-RotationFailure AlarmDescription: Alert when secret rotation fails MetricName: RotationFailed Namespace: AWS/SecretsManager Statistic: Sum Period: 300 EvaluationPeriods: 1 Threshold: 0 ComparisonOperator: GreaterThanThreshold AlarmActions: - !Ref AlertSNSTopic Dimensions: - Name: SecretName Value: prod/myapp/db # EventBridge rule for secret access SecretAccessRule: Type: AWS::Events::Rule Properties: Description: Capture all secret access events EventPattern: source: - aws.secretsmanager detail-type: - AWS API Call via CloudTrail detail: eventName: - GetSecretValue - DeleteSecret - PutSecretValue State: ENABLED Targets: - Arn: !GetAtt SecretAccessLogGroup.Arn Id: LogSecretAccess # Alert on suspicious access patterns UnauthorizedAccessRule: Type: AWS::Events::Rule Properties: Description: Alert on unauthorized secret access attempts EventPattern: source: - aws.secretsmanager detail-type: - AWS API Call via CloudTrail detail: errorCode: - AccessDenied - UnauthorizedAccess Targets: - Arn: !Ref SecurityAlertSNS Id: SecurityAlertCommon Troubleshooting Scenarios:
| Issue | Likely Cause | Resolution |
|---|---|---|
| AccessDenied on GetSecretValue | Missing IAM or KMS permission | Check both secretsmanager and kms:Decrypt permissions |
| Rotation marked as failed | Lambda timeout or network issue | Check Lambda logs; verify VPC connectivity to RDS |
| Application sees old credentials | Caching stale secrets | Reduce cache TTL; force cache refresh after rotation |
| Cross-account access fails | Missing resource policy or KMS policy | Add both secret resource policy AND KMS key policy |
| Slow secret retrieval | No VPC endpoint configured | Create secretsmanager VPC endpoint for private access |
If rotation fails mid-process, the secret may have an AWSPENDING version that's stuck. To recover: (1) Check Lambda logs for the failure cause, (2) Fix the underlying issue, (3) Trigger rotation again, or (4) Manually finalize by moving version stages using the CLI. Never delete the AWSPENDING version directly.
AWS Secrets Manager provides a fully managed secrets solution deeply integrated with the AWS ecosystem. Let's consolidate the key concepts:
What's Next:
Having explored AWS Secrets Manager, the next page examines Azure Key Vault—Microsoft's comprehensive secrets, keys, and certificate management service. You'll learn how Azure's approach differs, its unique features for enterprise environments, and when to choose it for hybrid or Azure-centric workloads.
You now have a comprehensive understanding of AWS Secrets Manager's capabilities, integration patterns, and operational considerations. This knowledge enables you to design secure, scalable secrets management for AWS-native workloads.