Claude Skill

secrets-manager

AWS Secrets Manager for secure secret storage and rotation. Use when storing credentials, configuring automatic rotation, managing secret versions, retrieving secrets in applications, or integrating with RDS.

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download itsmostafa-aws-agent-skills-skills_secrets-manager-e786d25.zip · 6 KB
Part of itsmostafa/aws-agent-skills — 17 skills

Install

skills CLI npx skills add https://github.com/itsmostafa/aws-agent-skills/tree/main/skills/secrets-manager
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install itsmostafa-aws-agent-skills@llmmart
Git git clone https://github.com/itsmostafa/aws-agent-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole itsmostafa/aws-agent-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

AWS Secrets Manager

AWS Secrets Manager helps protect access to applications, services, and IT resources. Store, retrieve, and automatically rotate credentials, API keys, and other secrets.

Table of Contents

Core Concepts

Secrets

Encrypted data stored in Secrets Manager. Can contain:

  • Database credentials
  • API keys
  • OAuth tokens
  • Any key-value pairs (up to 64 KB)

Versions

Each secret can have multiple versions:

  • AWSCURRENT: Current active version
  • AWSPENDING: Version being rotated to
  • AWSPREVIOUS: Previous version

Rotation

Automatic credential rotation using Lambda functions. Built-in support for:

  • Amazon RDS
  • Amazon Redshift
  • Amazon DocumentDB
  • Custom secrets

Common Patterns

Create a Secret

AWS CLI:

# Create secret with JSON
aws secretsmanager create-secret \
  --name prod/myapp/database \
  --description "Production database credentials" \
  --secret-string '{"username":"admin","password":"MySecurePassword123!","host":"mydb.cluster-xyz.us-east-1.rds.amazonaws.com","port":5432,"database":"myapp"}'

# Create secret with binary data
aws secretsmanager create-secret \
  --name prod/myapp/certificate \
  --secret-binary fileb://certificate.pem

boto3:

import boto3
import json

secrets = boto3.client('secretsmanager')

response = secrets.create_secret(
    Name='prod/myapp/database',
    Description='Production database credentials',
    SecretString=json.dumps({
        'username': 'admin',
        'password': 'MySecurePassword123!',
        'host': 'mydb.cluster-xyz.us-east-1.rds.amazonaws.com',
        'port': 5432,
        'database': 'myapp'
    }),
    Tags=[
        {'Key': 'Environment', 'Value': 'production'},
        {'Key': 'Application', 'Value': 'myapp'}
    ]
)

Retrieve a Secret

import boto3
import json

secrets = boto3.client('secretsmanager')

def get_secret(secret_name):
    response = secrets.get_secret_value(SecretId=secret_name)

    if 'SecretString' in response:
        return json.loads(response['SecretString'])
    else:
        import base64
        return base64.b64decode(response['SecretBinary'])

# Usage
credentials = get_secret('prod/myapp/database')
db_password = credentials['password']

Caching Secrets

from aws_secretsmanager_caching import SecretCache, SecretCacheConfig

# Configure cache
cache_config = SecretCacheConfig(
    max_cache_size=100,
    secret_refresh_interval=3600,
    secret_version_stage_refresh_interval=3600
)

cache = SecretCache(config=cache_config)

def get_cached_secret(secret_name):
    secret = cache.get_secret_string(secret_name)
    return json.loads(secret)

Update a Secret

# Update secret value
aws secretsmanager update-secret \
  --secret-id prod/myapp/database \
  --secret-string '{"username":"admin","password":"NewPassword456!"}'

# Put new version with staging labels
aws secretsmanager put-secret-value \
  --secret-id prod/myapp/database \
  --secret-string '{"username":"admin","password":"NewPassword456!"}' \
  --version-stages AWSCURRENT

Enable Rotation for RDS

aws secretsmanager rotate-secret \
  --secret-id prod/myapp/database \
  --rotation-lambda-arn arn:aws:lambda:us-east-1:123456789012:function:SecretsManagerRDSPostgreSQLRotation \
  --rotation-rules AutomaticallyAfterDays=30

Create Secret with Rotation

# Use CloudFormation for RDS secret with rotation
aws cloudformation deploy \
  --template-file rds-secret.yaml \
  --stack-name rds-secret
# rds-secret.yaml
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  DBSecret:
    Type: AWS::SecretsManager::Secret
    Properties:
      Name: prod/myapp/database
      GenerateSecretString:
        SecretStringTemplate: '{"username": "admin"}'
        GenerateStringKey: password
        PasswordLength: 32
        ExcludeCharacters: '"@/\'

  DBSecretRotation:
    Type: AWS::SecretsManager::RotationSchedule
    Properties:
      SecretId: !Ref DBSecret
      RotationLambdaARN: !GetAtt RotationLambda.Arn
      RotationRules:
        AutomaticallyAfterDays: 30

Use in Lambda with Extension

import json
import urllib.request

def handler(event, context):
    # Use AWS Parameters and Secrets Lambda Extension
    secrets_port = 2773
    secret_name = 'prod/myapp/database'

    url = f'http://localhost:{secrets_port}/secretsmanager/get?secretId={secret_name}'
    headers = {'X-Aws-Parameters-Secrets-Token': os.environ['AWS_SESSION_TOKEN']}

    request = urllib.request.Request(url, headers=headers)
    response = urllib.request.urlopen(request)
    secret = json.loads(response.read())['SecretString']

    credentials = json.loads(secret)
    return credentials

CLI Reference

Secret Management

Command Description
aws secretsmanager create-secret Create secret
aws secretsmanager describe-secret Get secret metadata
aws secretsmanager get-secret-value Retrieve secret value
aws secretsmanager update-secret Update secret
aws secretsmanager delete-secret Delete secret
aws secretsmanager restore-secret Restore deleted secret
aws secretsmanager list-secrets List secrets

Versions

Command Description
aws secretsmanager put-secret-value Add new version
aws secretsmanager list-secret-version-ids List versions
aws secretsmanager update-secret-version-stage Move staging labels

Rotation

Command Description
aws secretsmanager rotate-secret Configure/trigger rotation
aws secretsmanager cancel-rotate-secret Cancel rotation

Best Practices

Secret Organization

  • Use hierarchical names: environment/application/secret-type
  • Tag secrets for organization and cost allocation
  • Separate by environment (dev, staging, prod)

Security

  • Use resource policies to control access
  • Enable encryption with customer-managed KMS keys
  • Rotate secrets regularly (30-90 days)
  • Audit access with CloudTrail
  • Use VPC endpoints for private access

Access Control

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "secretsmanager:GetSecretValue",
        "secretsmanager:DescribeSecret"
      ],
      "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/*",
      "Condition": {
        "StringEquals": {
          "secretsmanager:ResourceTag/Environment": "production"
        }
      }
    }
  ]
}

Application Integration

  • Cache secrets to reduce API calls
  • Handle rotation gracefully (retry with new credentials)
  • Use Lambda extension for faster access
  • Never log secrets

Troubleshooting

AccessDeniedException

Causes:

  • IAM policy missing secretsmanager:GetSecretValue
  • Resource policy denying access
  • KMS key policy missing permissions

Debug:

# Check secret resource policy
aws secretsmanager get-resource-policy --secret-id my-secret

# Check IAM permissions
aws iam simulate-principal-policy \
  --policy-source-arn arn:aws:iam::123456789012:role/my-role \
  --action-names secretsmanager:GetSecretValue \
  --resource-arns arn:aws:secretsmanager:us-east-1:123456789012:secret:my-secret

Rotation Failed

Debug:

# Check rotation status
aws secretsmanager describe-secret --secret-id my-secret

# Check Lambda logs
aws logs filter-log-events \
  --log-group-name /aws/lambda/SecretsManagerRotation \
  --filter-pattern "ERROR"

Common causes:

  • Lambda timeout (increase to 30+ seconds)
  • Network connectivity (VPC configuration)
  • Database connection issues
  • Wrong secret format

Secret Not Found

# List secrets to find correct name
aws secretsmanager list-secrets \
  --filters Key=name,Values=myapp

# Check if deleted (within recovery window)
aws secretsmanager list-secrets \
  --include-planned-deletion

References

Files (aws-agent-skills)
  • rotation-strategies.md 10.9 KB
    # Secrets Manager Rotation Strategies
    
    Secret rotation patterns and Lambda rotation functions.
    
    ## Rotation Strategies
    
    ### Single User Rotation
    
    One user, password changes in place. Brief connection interruption during rotation.
    
    ```
    1. AWSCURRENT has current password
    2. Lambda creates new password → AWSPENDING
    3. Lambda updates database with new password
    4. Lambda tests AWSPENDING credentials
    5. Lambda moves AWSPENDING → AWSCURRENT
    ```
    
    ### Alternating Users Rotation
    
    Two users alternate, zero downtime.
    
    ```
    User A (AWSCURRENT) → User B (AWSPENDING)
    1. Lambda creates new password for User B
    2. Lambda updates User B in database
    3. Lambda tests User B credentials
    4. Lambda moves User B → AWSCURRENT
    5. Next rotation: User A becomes AWSPENDING
    ```
    
    ## Built-in Rotation Functions
    
    ### RDS PostgreSQL
    
    ```bash
    # Use AWS-provided rotation Lambda
    aws secretsmanager rotate-secret \
      --secret-id prod/myapp/database \
      --rotation-lambda-arn arn:aws:lambda:us-east-1:123456789012:function:SecretsManagerRDSPostgreSQLRotationSingleUser \
      --rotation-rules AutomaticallyAfterDays=30
    ```
    
    ### RDS MySQL
    
    ```bash
    aws secretsmanager rotate-secret \
      --secret-id prod/myapp/database \
      --rotation-lambda-arn arn:aws:lambda:us-east-1:123456789012:function:SecretsManagerRDSMySQLRotationSingleUser \
      --rotation-rules AutomaticallyAfterDays=30
    ```
    
    ### Deploy Rotation Lambda
    
    ```bash
    # Use SAR to deploy rotation function
    aws serverlessrepo create-cloud-formation-change-set \
      --application-id arn:aws:serverlessrepo:us-east-1:297356227824:applications/SecretsManagerRDSPostgreSQLRotationSingleUser \
      --stack-name rds-rotation-lambda \
      --capabilities CAPABILITY_IAM \
      --parameter-overrides \
        Name=endpoint,Value=mydb.cluster-xyz.us-east-1.rds.amazonaws.com \
        Name=functionName,Value=SecretsManagerRDSPostgreSQLRotation
    ```
    
    ## Custom Rotation Lambda
    
    ### Lambda Structure
    
    ```python
    import boto3
    import json
    import logging
    
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    
    secrets = boto3.client('secretsmanager')
    
    def handler(event, context):
        secret_id = event['SecretId']
        token = event['ClientRequestToken']
        step = event['Step']
    
        if step == 'createSecret':
            create_secret(secret_id, token)
        elif step == 'setSecret':
            set_secret(secret_id, token)
        elif step == 'testSecret':
            test_secret(secret_id, token)
        elif step == 'finishSecret':
            finish_secret(secret_id, token)
        else:
            raise ValueError(f'Unknown step: {step}')
    
    def create_secret(secret_id, token):
        """Create new secret version with AWSPENDING label."""
        # Check if already exists
        try:
            secrets.get_secret_value(
                SecretId=secret_id,
                VersionId=token,
                VersionStage='AWSPENDING'
            )
            logger.info('AWSPENDING already exists')
            return
        except secrets.exceptions.ResourceNotFoundException:
            pass
    
        # Get current secret
        current = secrets.get_secret_value(
            SecretId=secret_id,
            VersionStage='AWSCURRENT'
        )
        current_secret = json.loads(current['SecretString'])
    
        # Generate new password
        new_password = secrets.get_random_password(
            PasswordLength=32,
            ExcludeCharacters='"@/\\'
        )['RandomPassword']
    
        # Create new version
        new_secret = current_secret.copy()
        new_secret['password'] = new_password
    
        secrets.put_secret_value(
            SecretId=secret_id,
            ClientRequestToken=token,
            SecretString=json.dumps(new_secret),
            VersionStages=['AWSPENDING']
        )
    
    def set_secret(secret_id, token):
        """Update the resource with the new credentials."""
        pending = secrets.get_secret_value(
            SecretId=secret_id,
            VersionId=token,
            VersionStage='AWSPENDING'
        )
        pending_secret = json.loads(pending['SecretString'])
    
        # Update the actual resource (e.g., API key in external service)
        # This is where you'd call your service's API to update the credential
        update_resource_credential(pending_secret)
    
    def test_secret(secret_id, token):
        """Test that the new credentials work."""
        pending = secrets.get_secret_value(
            SecretId=secret_id,
            VersionId=token,
            VersionStage='AWSPENDING'
        )
        pending_secret = json.loads(pending['SecretString'])
    
        # Test the credentials
        if not verify_credentials_work(pending_secret):
            raise ValueError('New credentials failed validation')
    
    def finish_secret(secret_id, token):
        """Finalize rotation by moving labels."""
        # Get current version
        metadata = secrets.describe_secret(SecretId=secret_id)
    
        current_version = None
        for version_id, stages in metadata['VersionIdsToStages'].items():
            if 'AWSCURRENT' in stages:
                current_version = version_id
                break
    
        # Move AWSCURRENT to new version
        secrets.update_secret_version_stage(
            SecretId=secret_id,
            VersionStage='AWSCURRENT',
            MoveToVersionId=token,
            RemoveFromVersionId=current_version
        )
    ```
    
    ### API Key Rotation Example
    
    ```python
    import boto3
    import json
    import requests
    
    secrets = boto3.client('secretsmanager')
    
    def set_secret(secret_id, token):
        """Rotate API key in external service."""
        # Get pending secret
        pending = secrets.get_secret_value(
            SecretId=secret_id,
            VersionId=token,
            VersionStage='AWSPENDING'
        )
        pending_secret = json.loads(pending['SecretString'])
    
        # Get current secret (for authentication)
        current = secrets.get_secret_value(
            SecretId=secret_id,
            VersionStage='AWSCURRENT'
        )
        current_secret = json.loads(current['SecretString'])
    
        # Call external API to create new key
        response = requests.post(
            'https://api.example.com/v1/api-keys/rotate',
            headers={'Authorization': f'Bearer {current_secret["api_key"]}'},
            json={'new_key': pending_secret['api_key']}
        )
    
        if response.status_code != 200:
            raise Exception(f'Failed to rotate API key: {response.text}')
    
    def test_secret(secret_id, token):
        """Test new API key works."""
        pending = secrets.get_secret_value(
            SecretId=secret_id,
            VersionId=token,
            VersionStage='AWSPENDING'
        )
        pending_secret = json.loads(pending['SecretString'])
    
        response = requests.get(
            'https://api.example.com/v1/me',
            headers={'Authorization': f'Bearer {pending_secret["api_key"]}'}
        )
    
        if response.status_code != 200:
            raise Exception('New API key validation failed')
    ```
    
    ## VPC Configuration
    
    For RDS rotation, Lambda needs VPC access:
    
    ```yaml
    Resources:
      RotationLambda:
        Type: AWS::Lambda::Function
        Properties:
          VpcConfig:
            SecurityGroupIds:
              - !Ref LambdaSecurityGroup
            SubnetIds:
              - !Ref PrivateSubnet1
              - !Ref PrivateSubnet2
    
      LambdaSecurityGroup:
        Type: AWS::EC2::SecurityGroup
        Properties:
          VpcId: !Ref VPC
          SecurityGroupEgress:
            - IpProtocol: tcp
              FromPort: 443
              ToPort: 443
              CidrIp: 0.0.0.0/0  # For Secrets Manager API
            - IpProtocol: tcp
              FromPort: 5432
              ToPort: 5432
              DestinationSecurityGroupId: !Ref DBSecurityGroup
    
      # VPC Endpoint for Secrets Manager
      SecretsManagerEndpoint:
        Type: AWS::EC2::VPCEndpoint
        Properties:
          VpcId: !Ref VPC
          ServiceName: !Sub com.amazonaws.${AWS::Region}.secretsmanager
          VpcEndpointType: Interface
          SubnetIds:
            - !Ref PrivateSubnet1
            - !Ref PrivateSubnet2
          SecurityGroupIds:
            - !Ref EndpointSecurityGroup
    ```
    
    ## Rotation Permissions
    
    ### Lambda Execution Role
    
    ```json
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "secretsmanager:GetSecretValue",
            "secretsmanager:DescribeSecret",
            "secretsmanager:PutSecretValue",
            "secretsmanager:UpdateSecretVersionStage"
          ],
          "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/*"
        },
        {
          "Effect": "Allow",
          "Action": "secretsmanager:GetRandomPassword",
          "Resource": "*"
        },
        {
          "Effect": "Allow",
          "Action": [
            "kms:Decrypt",
            "kms:GenerateDataKey"
          ],
          "Resource": "arn:aws:kms:us-east-1:123456789012:key/..."
        }
      ]
    }
    ```
    
    ### Secret Resource Policy
    
    ```json
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "AWS": "arn:aws:iam::123456789012:role/rotation-lambda-role"
          },
          "Action": [
            "secretsmanager:GetSecretValue",
            "secretsmanager:PutSecretValue",
            "secretsmanager:UpdateSecretVersionStage"
          ],
          "Resource": "*",
          "Condition": {
            "StringEquals": {
              "secretsmanager:VersionStage": ["AWSCURRENT", "AWSPENDING"]
            }
          }
        }
      ]
    }
    ```
    
    ## Handling Rotation in Applications
    
    ### Retry with New Credentials
    
    ```python
    import boto3
    import json
    import psycopg2
    from functools import wraps
    
    secrets = boto3.client('secretsmanager')
    _cached_secret = None
    _secret_version = None
    
    def get_db_credentials():
        global _cached_secret, _secret_version
    
        response = secrets.get_secret_value(SecretId='prod/myapp/database')
    
        if response['VersionId'] != _secret_version:
            _cached_secret = json.loads(response['SecretString'])
            _secret_version = response['VersionId']
    
        return _cached_secret
    
    def with_credential_refresh(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except psycopg2.OperationalError as e:
                if 'authentication failed' in str(e).lower():
                    # Force refresh and retry
                    global _cached_secret, _secret_version
                    _cached_secret = None
                    _secret_version = None
                    return func(*args, **kwargs)
                raise
        return wrapper
    
    @with_credential_refresh
    def query_database():
        creds = get_db_credentials()
        conn = psycopg2.connect(
            host=creds['host'],
            port=creds['port'],
            database=creds['database'],
            user=creds['username'],
            password=creds['password']
        )
        # Execute query...
    ```
    
    ## Monitoring Rotation
    
    ### CloudWatch Alarms
    
    ```bash
    # Alarm for rotation failures
    aws cloudwatch put-metric-alarm \
      --alarm-name SecretsRotationFailed \
      --metric-name RotationFailure \
      --namespace AWS/SecretsManager \
      --statistic Sum \
      --period 86400 \
      --threshold 1 \
      --comparison-operator GreaterThanOrEqualToThreshold \
      --evaluation-periods 1 \
      --alarm-actions arn:aws:sns:us-east-1:123456789012:alerts
    
    # Alarm for secrets not rotated
    aws cloudwatch put-metric-alarm \
      --alarm-name SecretsNotRotated \
      --metric-name DaysSinceLastRotation \
      --namespace AWS/SecretsManager \
      --dimensions Name=SecretName,Value=prod/myapp/database \
      --statistic Maximum \
      --period 86400 \
      --threshold 45 \
      --comparison-operator GreaterThanThreshold \
      --evaluation-periods 1 \
      --alarm-actions arn:aws:sns:us-east-1:123456789012:alerts
    ```
    
  • SKILL.md 8.8 KB
    ---
    name: secrets-manager
    description: AWS Secrets Manager for secure secret storage and rotation. Use when storing credentials, configuring automatic rotation, managing secret versions, retrieving secrets in applications, or integrating with RDS.
    last_updated: "2026-01-07"
    doc_source: https://docs.aws.amazon.com/secretsmanager/latest/userguide/
    ---
    
    # AWS Secrets Manager
    
    AWS Secrets Manager helps protect access to applications, services, and IT resources. Store, retrieve, and automatically rotate credentials, API keys, and other secrets.
    
    ## Table of Contents
    
    - [Core Concepts](#core-concepts)
    - [Common Patterns](#common-patterns)
    - [CLI Reference](#cli-reference)
    - [Best Practices](#best-practices)
    - [Troubleshooting](#troubleshooting)
    - [References](#references)
    
    ## Core Concepts
    
    ### Secrets
    
    Encrypted data stored in Secrets Manager. Can contain:
    - Database credentials
    - API keys
    - OAuth tokens
    - Any key-value pairs (up to 64 KB)
    
    ### Versions
    
    Each secret can have multiple versions:
    - **AWSCURRENT**: Current active version
    - **AWSPENDING**: Version being rotated to
    - **AWSPREVIOUS**: Previous version
    
    ### Rotation
    
    Automatic credential rotation using Lambda functions. Built-in support for:
    - Amazon RDS
    - Amazon Redshift
    - Amazon DocumentDB
    - Custom secrets
    
    ## Common Patterns
    
    ### Create a Secret
    
    **AWS CLI:**
    
    ```bash
    # Create secret with JSON
    aws secretsmanager create-secret \
      --name prod/myapp/database \
      --description "Production database credentials" \
      --secret-string '{"username":"admin","password":"MySecurePassword123!","host":"mydb.cluster-xyz.us-east-1.rds.amazonaws.com","port":5432,"database":"myapp"}'
    
    # Create secret with binary data
    aws secretsmanager create-secret \
      --name prod/myapp/certificate \
      --secret-binary fileb://certificate.pem
    ```
    
    **boto3:**
    
    ```python
    import boto3
    import json
    
    secrets = boto3.client('secretsmanager')
    
    response = secrets.create_secret(
        Name='prod/myapp/database',
        Description='Production database credentials',
        SecretString=json.dumps({
            'username': 'admin',
            'password': 'MySecurePassword123!',
            'host': 'mydb.cluster-xyz.us-east-1.rds.amazonaws.com',
            'port': 5432,
            'database': 'myapp'
        }),
        Tags=[
            {'Key': 'Environment', 'Value': 'production'},
            {'Key': 'Application', 'Value': 'myapp'}
        ]
    )
    ```
    
    ### Retrieve a Secret
    
    ```python
    import boto3
    import json
    
    secrets = boto3.client('secretsmanager')
    
    def get_secret(secret_name):
        response = secrets.get_secret_value(SecretId=secret_name)
    
        if 'SecretString' in response:
            return json.loads(response['SecretString'])
        else:
            import base64
            return base64.b64decode(response['SecretBinary'])
    
    # Usage
    credentials = get_secret('prod/myapp/database')
    db_password = credentials['password']
    ```
    
    ### Caching Secrets
    
    ```python
    from aws_secretsmanager_caching import SecretCache, SecretCacheConfig
    
    # Configure cache
    cache_config = SecretCacheConfig(
        max_cache_size=100,
        secret_refresh_interval=3600,
        secret_version_stage_refresh_interval=3600
    )
    
    cache = SecretCache(config=cache_config)
    
    def get_cached_secret(secret_name):
        secret = cache.get_secret_string(secret_name)
        return json.loads(secret)
    ```
    
    ### Update a Secret
    
    ```bash
    # Update secret value
    aws secretsmanager update-secret \
      --secret-id prod/myapp/database \
      --secret-string '{"username":"admin","password":"NewPassword456!"}'
    
    # Put new version with staging labels
    aws secretsmanager put-secret-value \
      --secret-id prod/myapp/database \
      --secret-string '{"username":"admin","password":"NewPassword456!"}' \
      --version-stages AWSCURRENT
    ```
    
    ### Enable Rotation for RDS
    
    ```bash
    aws secretsmanager rotate-secret \
      --secret-id prod/myapp/database \
      --rotation-lambda-arn arn:aws:lambda:us-east-1:123456789012:function:SecretsManagerRDSPostgreSQLRotation \
      --rotation-rules AutomaticallyAfterDays=30
    ```
    
    ### Create Secret with Rotation
    
    ```bash
    # Use CloudFormation for RDS secret with rotation
    aws cloudformation deploy \
      --template-file rds-secret.yaml \
      --stack-name rds-secret
    ```
    
    ```yaml
    # rds-secret.yaml
    AWSTemplateFormatVersion: '2010-09-09'
    Resources:
      DBSecret:
        Type: AWS::SecretsManager::Secret
        Properties:
          Name: prod/myapp/database
          GenerateSecretString:
            SecretStringTemplate: '{"username": "admin"}'
            GenerateStringKey: password
            PasswordLength: 32
            ExcludeCharacters: '"@/\'
    
      DBSecretRotation:
        Type: AWS::SecretsManager::RotationSchedule
        Properties:
          SecretId: !Ref DBSecret
          RotationLambdaARN: !GetAtt RotationLambda.Arn
          RotationRules:
            AutomaticallyAfterDays: 30
    ```
    
    ### Use in Lambda with Extension
    
    ```python
    import json
    import urllib.request
    
    def handler(event, context):
        # Use AWS Parameters and Secrets Lambda Extension
        secrets_port = 2773
        secret_name = 'prod/myapp/database'
    
        url = f'http://localhost:{secrets_port}/secretsmanager/get?secretId={secret_name}'
        headers = {'X-Aws-Parameters-Secrets-Token': os.environ['AWS_SESSION_TOKEN']}
    
        request = urllib.request.Request(url, headers=headers)
        response = urllib.request.urlopen(request)
        secret = json.loads(response.read())['SecretString']
    
        credentials = json.loads(secret)
        return credentials
    ```
    
    ## CLI Reference
    
    ### Secret Management
    
    | Command | Description |
    |---------|-------------|
    | `aws secretsmanager create-secret` | Create secret |
    | `aws secretsmanager describe-secret` | Get secret metadata |
    | `aws secretsmanager get-secret-value` | Retrieve secret value |
    | `aws secretsmanager update-secret` | Update secret |
    | `aws secretsmanager delete-secret` | Delete secret |
    | `aws secretsmanager restore-secret` | Restore deleted secret |
    | `aws secretsmanager list-secrets` | List secrets |
    
    ### Versions
    
    | Command | Description |
    |---------|-------------|
    | `aws secretsmanager put-secret-value` | Add new version |
    | `aws secretsmanager list-secret-version-ids` | List versions |
    | `aws secretsmanager update-secret-version-stage` | Move staging labels |
    
    ### Rotation
    
    | Command | Description |
    |---------|-------------|
    | `aws secretsmanager rotate-secret` | Configure/trigger rotation |
    | `aws secretsmanager cancel-rotate-secret` | Cancel rotation |
    
    ## Best Practices
    
    ### Secret Organization
    
    - **Use hierarchical names**: `environment/application/secret-type`
    - **Tag secrets** for organization and cost allocation
    - **Separate by environment** (dev, staging, prod)
    
    ### Security
    
    - **Use resource policies** to control access
    - **Enable encryption** with customer-managed KMS keys
    - **Rotate secrets** regularly (30-90 days)
    - **Audit access** with CloudTrail
    - **Use VPC endpoints** for private access
    
    ### Access Control
    
    ```json
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "secretsmanager:GetSecretValue",
            "secretsmanager:DescribeSecret"
          ],
          "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/*",
          "Condition": {
            "StringEquals": {
              "secretsmanager:ResourceTag/Environment": "production"
            }
          }
        }
      ]
    }
    ```
    
    ### Application Integration
    
    - **Cache secrets** to reduce API calls
    - **Handle rotation** gracefully (retry with new credentials)
    - **Use Lambda extension** for faster access
    - **Never log secrets**
    
    ## Troubleshooting
    
    ### AccessDeniedException
    
    **Causes:**
    - IAM policy missing `secretsmanager:GetSecretValue`
    - Resource policy denying access
    - KMS key policy missing permissions
    
    **Debug:**
    
    ```bash
    # Check secret resource policy
    aws secretsmanager get-resource-policy --secret-id my-secret
    
    # Check IAM permissions
    aws iam simulate-principal-policy \
      --policy-source-arn arn:aws:iam::123456789012:role/my-role \
      --action-names secretsmanager:GetSecretValue \
      --resource-arns arn:aws:secretsmanager:us-east-1:123456789012:secret:my-secret
    ```
    
    ### Rotation Failed
    
    **Debug:**
    
    ```bash
    # Check rotation status
    aws secretsmanager describe-secret --secret-id my-secret
    
    # Check Lambda logs
    aws logs filter-log-events \
      --log-group-name /aws/lambda/SecretsManagerRotation \
      --filter-pattern "ERROR"
    ```
    
    **Common causes:**
    - Lambda timeout (increase to 30+ seconds)
    - Network connectivity (VPC configuration)
    - Database connection issues
    - Wrong secret format
    
    ### Secret Not Found
    
    ```bash
    # List secrets to find correct name
    aws secretsmanager list-secrets \
      --filters Key=name,Values=myapp
    
    # Check if deleted (within recovery window)
    aws secretsmanager list-secrets \
      --include-planned-deletion
    ```
    
    ## References
    
    - [Secrets Manager User Guide](https://docs.aws.amazon.com/secretsmanager/latest/userguide/)
    - [Secrets Manager API Reference](https://docs.aws.amazon.com/secretsmanager/latest/apireference/)
    - [Secrets Manager CLI Reference](https://docs.aws.amazon.com/cli/latest/reference/secretsmanager/)
    - [boto3 Secrets Manager](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/secretsmanager.html)
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related