{
  "schema": "https://ai-atoms.com/schemas/skill-v1.json",
  "type": "skill",
  "id": "skill/aws-secrets-rotation",
  "version": "1.0.0",
  "name": "Aws Secrets Rotation",
  "description": "Automate AWS secrets rotation for RDS, API keys, and credentials",
  "system_prompt_fragment": "# AWS Secrets Rotation\n\nAutomate rotation of secrets, credentials, and API keys using AWS Secrets Manager and Lambda.\n\n## When to Use\n\nUse this skill when you need to implement automated secrets rotation, manage credentials securely, or comply with security policies requiring regular key rotation.\n\n## Supported Secret Types\n\n**AWS Services**\n- RDS database credentials\n- DocumentDB credentials\n- Redshift credentials\n- ElastiCache credentials\n\n**Third-Party Services**\n- API keys\n- OAuth tokens\n- SSH keys\n- Custom credentials\n\n## Secrets Manager Setup\n\n### Create a Secret\n\n```bash\n# Create RDS secret\naws secretsmanager create-secret \\\n  --name prod/db/mysql \\\n  --description \"Production MySQL credentials\" \\\n  --secret-string '{\n    \"username\": \"admin\",\n    \"password\": \"CHANGE_ME\",\n    \"engine\": \"mysql\",\n    \"host\": \"mydb.cluster-abc.us-east-1.rds.amazonaws.com\",\n    \"port\": 3306,\n    \"dbname\": \"myapp\"\n  }'\n\n# Create API key secret\naws secretsmanager create-secret \\\n  --name prod/api/stripe \\\n  --secret-string '{\n    \"api_key\": \"sk_live_xxxxx\",\n    \"webhook_secret\": \"whsec_xxxxx\"\n  }'\n\n# Create secret from file\naws secretsmanager create-secret \\\n  --name prod/ssh/private-key \\\n  --secret-binary fileb://~/.ssh/id_rsa\n```\n\n### Retrieve Secrets\n\n```bash\n# Get secret value\naws secretsmanager get-secret-value \\\n  --secret-id prod/db/mysql \\\n  --query 'SecretString' --output text\n\n# Get specific field\naws secretsmanager get-secret-value \\\n  --secret-id prod/db/mysql \\\n  --query 'SecretString' --output text | \\\n  jq -r '.password'\n\n# Get binary secret\naws secretsmanager get-secret-value \\\n  --secret-id prod/ssh/private-key \\\n  --query 'SecretBinary' --output text | \\\n  base64 -d > private-key.pem\n```\n\n## Automatic Rotation Setup\n\n### Enable RDS Rotation\n\n```bash\n# Enable automatic rotation (30 days)\naws secretsmanager rotate-secret \\\n  --secret-id prod/db/mysql \\\n  --rotation-lambda-arn arn:aws:lambda:us-east-1:123456789012:function:SecretsManagerRDSMySQLRotation \\\n  --rotation-rules AutomaticallyAfterDays=30\n\n# Rotate immediately\naws secretsmanager rotate-secret \\\n  --secret-id prod/db/mysql\n\n# Check rotation status\naws secretsmanager describe-secret \\\n  --secret-id prod/db/mysql \\\n  --query 'RotationEnabled'\n```\n\n### Lambda Rotation Function\n\n```python\n# lambda_rotation.py\nimport boto3\nimport json\nimport os\n\nsecrets_client = boto3.client('secretsmanager')\nrds_client = boto3.client('rds')\n\ndef lambda_handler(event, context):\n    \"\"\"Rotate RDS MySQL password\"\"\"\n    \n    secret_arn = event['SecretId']\n    token = event['ClientRequestToken']\n    step = event['Step']\n    \n    # Get current secret\n    current = secrets_client.get_secret_value(SecretId=secret_arn)\n    secret = json.loads(current['SecretString'])\n    \n    if step == \"createSecret\":\n        # Generate new password\n        new_password = generate_password()\n        secret['password'] = new_password\n        \n        # Store as pending\n        secrets_client.put_secret_value(\n            SecretId=secret_arn,\n            ClientRequestToken=token,\n            SecretString=json.dumps(secret),\n            VersionStages=['AWSPENDING']\n        )\n    \n    elif step == \"setSecret\":\n        # Update RDS password\n        rds_client.modify_db_instance(\n            DBInstanceIdentifier=secret['dbInstanceIdentifier'],\n            MasterUserPassword=secret['password'],\n            ApplyImmediately=True\n        )\n    \n    elif step == \"testSecret\":\n        # Test new credentials\n        import pymysql\n        conn = pymysql.connect(\n            host=secret['host'],\n            user=secret['username'],\n            password=secret['password'],\n            database=secret['dbname']\n        )\n        conn.close()\n    \n    elif step == \"finishSecret\":\n        # Mark as current\n        secrets_client.update_secret_version_stage(\n            SecretId=secret_arn,\n            VersionStage='AWSCURRENT',\n            MoveToVersionId=token,\n            RemoveFromVersionId=current['VersionId']\n        )\n    \n    return {'statusCode': 200}\n\ndef generate_password(length=32):\n    import secrets\n    import string\n    alphabet = string.ascii_letters + string.digits + \"!@#$%^&*()\"\n    return ''.join(secrets.choice(alphabet) for _ in range(length))\n```\n\n### Custom Rotation for API Keys\n\n```python\n# api_key_rotation.py\nimport boto3\nimport requests\nimport json\n\nsecrets_client = boto3.client('secretsmanager')\n\ndef rotate_stripe_key(secret_arn, token, step):\n    \"\"\"Rotate Stripe API key\"\"\"\n    \n    current = secrets_client.get_secret_value(SecretId=secret_arn)\n    secret = json.loads(current['SecretString'])\n    \n    if step == \"createSecret\":\n        # Create new Stripe key via API\n        response = requests.post(\n            'https://api.stripe.com/v1/api_keys',\n            auth=(secret['api_key'], ''),\n            data={'name': f'rotated-{token[:8]}'}\n        )\n        new_key = response.json()['secret']\n        \n        secret['api_key'] = new_key\n        secrets_client.put_secret_value(\n            SecretId=secret_arn,\n            ClientRequestToken=token,\n            SecretString=json.dumps(secret),\n            VersionStages=['AWSPENDING']\n        )\n    \n    elif step == \"testSecret\":\n        # Test new key\n        response = requests.get(\n            'https://api.stripe.com/v1/balance',\n            auth=(secret['api_key'], '')\n        )\n        if response.status_code != 200:\n            raise Exception(\"New key failed validation\")\n    \n    elif step == \"finishSecret\":\n        # Revoke old key\n        old_key = json.loads(current['SecretString'])['api_key']\n        requests.delete(\n            f'https://api.stripe.com/v1/api_keys/{old_key}',\n            auth=(secret['api_key'], '')\n        )\n        \n        # Promote to current\n        secrets_client.update_secret_version_stage(\n            SecretId=secret_arn,\n            VersionStage='AWSCURRENT',\n            MoveToVersionId=token\n        )\n```\n\n## Rotation Monitoring\n\n### CloudWatch Alarms\n\n```bash\n# Create alarm for rotation failures\naws cloudwatch put-metric-alarm \\\n  --alarm-name secrets-rotation-failures \\\n  --alarm-description \"Alert on secrets rotation failures\" \\\n  --metric-name RotationFailed \\\n  --namespace AWS/SecretsManager \\\n  --statistic Sum \\\n  --period 300 \\\n  --evaluation-periods 1 \\\n  --threshold 1 \\\n  --comparison-operator GreaterThanThreshold \\\n  --alarm-actions arn:aws:sns:us-east-1:123456789012:alerts\n```\n\n### Rotation Audit Script\n\n```bash\n#!/bin/bash\n# audit-rotations.sh\n\necho \"Secrets Rotation Audit\"\necho \"=====================\"\n\naws secretsmanager list-secrets --query 'SecretList[*].[Name,RotationEnabled,LastRotatedDate]' \\\n  --output text | \\\nwhile read name enabled last_rotated; do\n  echo \"\"\n  echo \"Secret: $name\"\n  echo \"  Rotation Enabled: $enabled\"\n  echo \"  Last Rotated: $last_rotated\"\n  \n  if [ \"$enabled\" = \"True\" ]; then\n    # Check rotation schedule\n    rules=$(aws secretsmanager describe-secret --secret-id \"$name\" \\\n      --query 'RotationRules.AutomaticallyAfterDays' --output text)\n    echo \"  Rotation Schedule: Every $rules days\"\n    \n    # Calculate days since last rotation\n    if [ \"$last_rotated\" != \"None\" ]; then\n      days_ago=$(( ($(date +%s) - $(date -d \"$last_rotated\" +%s)) / 86400 ))\n      echo \"  Days Since Rotation: $days_ago\"\n      \n      if [ $days_ago -gt $rules ]; then\n        echo \"  ⚠️  OVERDUE for rotation!\"\n      fi\n    fi\n  fi\ndone\n```\n\n## Application Integration\n\n### Python SDK\n\n```python\nimport boto3\nimport json\n\ndef get_secret(secret_name):\n    \"\"\"Retrieve secret from Secrets Manager\"\"\"\n    client = boto3.client('secretsmanager')\n    \n    try:\n        response = client.get_secret_value(SecretId=secret_name)\n        return json.loads(response['SecretString'])\n    except Exception as e:\n        print(f\"Error retrieving secret: {e}\")\n        raise\n\n# Usage\ndb_creds = get_secret('prod/db/mysql')\nconnection = pymysql.connect(\n    host=db_creds['host'],\n    user=db_creds['username'],\n    password=db_creds['password'],\n    database=db_creds['dbname']\n)\n```\n\n### Node.js SDK\n\n```javascript\nconst AWS = require('aws-sdk');\nconst secretsManager = new AWS.SecretsManager();\n\nasync function getSecret(secretName) {\n  try {\n    const data = await secretsManager.getSecretValue({\n      SecretId: secretName\n    }).promise();\n    \n    return JSON.parse(data.SecretString);\n  } catch (err) {\n    console.error('Error retrieving secret:', err);\n    throw err;\n  }\n}\n\n// Usage\nconst dbCreds = await getSecret('prod/db/mysql');\nconst connection = mysql.createConnection({\n  host: dbCreds.host,\n  user: dbCreds.username,\n  password: dbCreds.password,\n  database: dbCreds.dbname\n});\n```\n\n## Rotation Best Practices\n\n**Planning**\n- [ ] Identify all secrets requiring rotation\n- [ ] Define rotation schedules (30, 60, 90 days)\n- [ ] Test rotation in non-production first\n- [ ] Document rotation procedures\n- [ ] Plan for emergency rotation\n\n**Implementation**\n- [ ] Use AWS managed rotation when possible\n- [ ] Implement proper error handling\n- [ ] Add CloudWatch monitoring\n- [ ] Test application compatibility\n- [ ] Implement gradual rollout\n\n**Operations**\n- [ ] Monitor rotation success/failure\n- [ ] Set up alerts for failures\n- [ ] Regular rotation audits\n- [ ] Document troubleshooting steps\n- [ ] Maintain rotation runbooks\n\n## Emergency Rotation\n\n```bash\n# Immediate rotation (compromise detected)\naws secretsmanager rotate-secret \\\n  --secret-id prod/db/mysql \\\n  --rotate-immediately\n\n# Force rotation even if recently rotated\naws secretsmanager rotate-secret \\\n  --secret-id prod/api/stripe \\\n  --rotation-lambda-arn arn:aws:lambda:us-east-1:123456789012:function:RotateStripeKey \\\n  --rotate-immediately\n\n# Verify rotation completed\naws secretsmanager describe-secret \\\n  --secret-id prod/db/mysql \\\n  --query 'LastRotatedDate'\n```\n\n## Compliance Tracking\n\n```python\n#!/usr/bin/env python3\n# compliance-report.py\n\nimport boto3\nfrom datetime import datetime, timedelta\n\nclient = boto3.client('secretsmanager')\n\ndef generate_compliance_report():\n    secrets = client.list_secrets()['SecretList']\n    \n    compliant = []\n    non_compliant = []\n    \n    for secret in secrets:\n        name = secret['Name']\n        rotation_enabled = secret.get('RotationEnabled', False)\n        last_rotated = secret.get('LastRotatedDate')\n        \n        if not rotation_enabled:\n            non_compliant.append({\n                'name': name,\n                'issue': 'Rotation not enabled'\n            })\n            continue\n        \n        if last_rotated:\n            days_ago = (datetime.now(last_rotated.tzinfo) - last_rotated).days\n            if days_ago > 90:\n                non_compliant.append({\n                    'name': name,\n                    'issue': f'Not rotated in {days_ago} days'\n                })\n            else:\n                compliant.append(name)\n        else:\n            non_compliant.append({\n                'name': name,\n                'issue': 'Never rotated'\n            })\n    \n    print(f\"Compliant Secrets: {len(compliant)}\")\n    print(f\"Non-Compliant Secrets: {len(non_compliant)}\")\n    print(\"\\nNon-Compliant Details:\")\n    for item in non_compliant:\n        print(f\"  - {item['name']}: {item['issue']}\")\n\nif __name__ == \"__main__\":\n    generate_compliance_report()\n```\n\n## Example Prompts\n\n- \"Set up automatic rotation for my RDS credentials\"\n- \"Create a Lambda function to rotate API keys\"\n- \"Audit all secrets for rotation compliance\"\n- \"Implement emergency rotation for compromised credentials\"\n- \"Generate a secrets rotation report\"\n\n## Kiro CLI Integration\n\n```bash\nkiro-cli chat \"Use aws-secrets-rotation to set up RDS credential rotation\"\nkiro-cli chat \"Create a rotation audit report with aws-secrets-rotation\"\n```\n\n## Additional Resources\n\n- [AWS Secrets Manager Rotation](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets.html)\n- [Rotation Lambda Templates](https://github.com/aws-samples/aws-secrets-manager-rotation-lambdas)\n- [Best Practices for Secrets](https://docs.aws.amazon.com/secretsmanager/latest/userguide/best-practices.html)",
  "applicable_domains": [
    "security"
  ],
  "category": "security",
  "invocation": [
    "/aws-secrets-rotation"
  ],
  "authored_by": "claudeskills.in community",
  "source_url": "https://claudeskills.in/skill/aws-secrets-rotation",
  "provenance": {
    "source": "claudeskills.in",
    "source_url": "https://claudeskills.in/skill/aws-secrets-rotation",
    "license": "unknown",
    "imported_at": "2026-09-03",
    "notes": "Aggregated by claudeskills.in from community GitHub lists."
  },
  "tags": [
    "claudeskills",
    "security",
    "risk-reviewed"
  ],
  "lifecycle": "draft"
}