[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M717TY81S3ZQAYC95HNEJXRY":3,"skill-same:01M717TY81S3ZQAYC95HNEJXRY":66},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":39,"linkOnly":40,"markdownContent":41,"markdownBody":42,"frontMatter":43,"refName":46,"commitSha":47,"skillDirectory":48,"forksCount":14,"repositoryHtmlUrl":49,"repositoryHomepageUrl":6,"ownerHtmlUrl":50,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":51,"install":52,"resources":65},"01M717TY81S3ZQAYC95HNEJXRY","aws-secrets-rotation",null,"Automate AWS secrets rotation for RDS, API keys, and credentials","sapsapshen\u002Fai-memory-router","sapsapshen","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F20347959?v=4","01M6XDQEF1DP50DKF37H81J3J5","shenmian","01M6XDQEJPE41Y3DT2763X8ZJN",0,"MIT","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fglobal\u002Faws-secrets-rotation\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"aws","rotation","secrets","aws secrets rotation","2026","cli","api keys","for","manager","rds","secrets-manager","kiro-cli","kiro","community","automate","api","credentials","automation","security","safe","2026-11-10 10:12:30",false,"---\nname: aws-secrets-rotation\ndescription: \"Automate AWS secrets rotation for RDS, API keys, and credentials\"\ncategory: security\nrisk: safe\nsource: community\ntags: \"[aws, secrets-manager, security, automation, kiro-cli, credentials]\"\ndate_added: \"2026-02-27\"\n---\n\n# AWS Secrets Rotation\n\nAutomate rotation of secrets, credentials, and API keys using AWS Secrets Manager and Lambda.\n\n## When to Use\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\u002Fdb\u002Fmysql \\\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\u002Fapi\u002Fstripe \\\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\u002Fssh\u002Fprivate-key \\\n  --secret-binary fileb:\u002F\u002F~\u002F.ssh\u002Fid_rsa\n```\n\n### Retrieve Secrets\n\n```bash\n# Get secret value\naws secretsmanager get-secret-value \\\n  --secret-id prod\u002Fdb\u002Fmysql \\\n  --query 'SecretString' --output text\n\n# Get specific field\naws secretsmanager get-secret-value \\\n  --secret-id prod\u002Fdb\u002Fmysql \\\n  --query 'SecretString' --output text | \\\n  jq -r '.password'\n\n# Get binary secret\naws secretsmanager get-secret-value \\\n  --secret-id prod\u002Fssh\u002Fprivate-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\u002Fdb\u002Fmysql \\\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\u002Fdb\u002Fmysql\n\n# Check rotation status\naws secretsmanager describe-secret \\\n  --secret-id prod\u002Fdb\u002Fmysql \\\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:\u002F\u002Fapi.stripe.com\u002Fv1\u002Fapi_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:\u002F\u002Fapi.stripe.com\u002Fv1\u002Fbalance',\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:\u002F\u002Fapi.stripe.com\u002Fv1\u002Fapi_keys\u002F{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\u002FSecretsManager \\\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#!\u002Fbin\u002Fbash\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)) \u002F 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\u002Fdb\u002Fmysql')\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\u002F\u002F Usage\nconst dbCreds = await getSecret('prod\u002Fdb\u002Fmysql');\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\u002Ffailure\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\u002Fdb\u002Fmysql \\\n  --rotate-immediately\n\n# Force rotation even if recently rotated\naws secretsmanager rotate-secret \\\n  --secret-id prod\u002Fapi\u002Fstripe \\\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\u002Fdb\u002Fmysql \\\n  --query 'LastRotatedDate'\n```\n\n## Compliance Tracking\n\n```python\n#!\u002Fusr\u002Fbin\u002Fenv 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:\u002F\u002Fdocs.aws.amazon.com\u002Fsecretsmanager\u002Flatest\u002Fuserguide\u002Frotating-secrets.html)\n- [Rotation Lambda Templates](https:\u002F\u002Fgithub.com\u002Faws-samples\u002Faws-secrets-manager-rotation-lambdas)\n- [Best Practices for Secrets](https:\u002F\u002Fdocs.aws.amazon.com\u002Fsecretsmanager\u002Flatest\u002Fuserguide\u002Fbest-practices.html)\n","# AWS Secrets Rotation\n\nAutomate rotation of secrets, credentials, and API keys using AWS Secrets Manager and Lambda.\n\n## When to Use\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\u002Fdb\u002Fmysql \\\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\u002Fapi\u002Fstripe \\\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\u002Fssh\u002Fprivate-key \\\n  --secret-binary fileb:\u002F\u002F~\u002F.ssh\u002Fid_rsa\n```\n\n### Retrieve Secrets\n\n```bash\n# Get secret value\naws secretsmanager get-secret-value \\\n  --secret-id prod\u002Fdb\u002Fmysql \\\n  --query 'SecretString' --output text\n\n# Get specific field\naws secretsmanager get-secret-value \\\n  --secret-id prod\u002Fdb\u002Fmysql \\\n  --query 'SecretString' --output text | \\\n  jq -r '.password'\n\n# Get binary secret\naws secretsmanager get-secret-value \\\n  --secret-id prod\u002Fssh\u002Fprivate-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\u002Fdb\u002Fmysql \\\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\u002Fdb\u002Fmysql\n\n# Check rotation status\naws secretsmanager describe-secret \\\n  --secret-id prod\u002Fdb\u002Fmysql \\\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:\u002F\u002Fapi.stripe.com\u002Fv1\u002Fapi_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:\u002F\u002Fapi.stripe.com\u002Fv1\u002Fbalance',\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:\u002F\u002Fapi.stripe.com\u002Fv1\u002Fapi_keys\u002F{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\u002FSecretsManager \\\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#!\u002Fbin\u002Fbash\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)) \u002F 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\u002Fdb\u002Fmysql')\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\u002F\u002F Usage\nconst dbCreds = await getSecret('prod\u002Fdb\u002Fmysql');\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\u002Ffailure\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\u002Fdb\u002Fmysql \\\n  --rotate-immediately\n\n# Force rotation even if recently rotated\naws secretsmanager rotate-secret \\\n  --secret-id prod\u002Fapi\u002Fstripe \\\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\u002Fdb\u002Fmysql \\\n  --query 'LastRotatedDate'\n```\n\n## Compliance Tracking\n\n```python\n#!\u002Fusr\u002Fbin\u002Fenv 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:\u002F\u002Fdocs.aws.amazon.com\u002Fsecretsmanager\u002Flatest\u002Fuserguide\u002Frotating-secrets.html)\n- [Rotation Lambda Templates](https:\u002F\u002Fgithub.com\u002Faws-samples\u002Faws-secrets-manager-rotation-lambdas)\n- [Best Practices for Secrets](https:\u002F\u002Fdocs.aws.amazon.com\u002Fsecretsmanager\u002Flatest\u002Fuserguide\u002Fbest-practices.html)\n",{"name":5,"risk":38,"tags":44,"source":32,"category":37,"date_added":45,"description":7},"[aws, secrets-manager, security, automation, kiro-cli, credentials]","2026-02-27","main","7a38d8e7073e61c16eda85681cb32fb68a8657a5","skills-store\u002Fglobal\u002Faws-secrets-rotation","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router","https:\u002F\u002Fgithub.com\u002Fsapsapshen","2026-04-14 21:12:12",{"source":8,"skillName":5,"commands":53,"prompt":63,"zipAvailable":64},[54,57,60],{"tool":55,"command":56},"npx","npx skills add sapsapshen\u002Fai-memory-router --skill aws-secrets-rotation",{"tool":58,"command":59},"bunx","bunx skills add sapsapshen\u002Fai-memory-router --skill aws-secrets-rotation",{"tool":61,"command":62},"pnpm","pnpm dlx skills add sapsapshen\u002Fai-memory-router --skill aws-secrets-rotation","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fglobal\u002Faws-secrets-rotation\u002FSKILL.md",true,[],[67,91,115,125,138,156],{"skillNo":68,"name":69,"nameZh":6,"description":70,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":71,"categories":72,"keywords":78,"publishedAt":39},"01M71ATQRKG48SH06FQ697T5G9","wechat-search","Search WeChat Official Account articles using OpenClaw's web search and fetch capabilities with compliance-focused design.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fwechat-search-release\u002FSKILL.md",[73],{"categoryNo":74,"categoryName":75,"taxonomyType":76,"taxonomyTypeDesc":77},"01JBSEEDCAT000000000000037","律师与法务","PROFESSION","适用职业",[79,80,81,82,83,84,85,86,87,88,89,90],"wechat search","wechat","search","capabilities","openclaw","design","web search","compliance","web","official","fetch","with",{"skillNo":92,"name":93,"nameZh":6,"description":94,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":95,"categories":96,"keywords":97,"publishedAt":39},"01M71ATNAVGZB35PFYM2GC5N00","trend-tap","Real-time trending topics aggregator across 7 platforms (X\u002FTwitter, Reddit, Google Trends, Hacker News, Zhihu, Bilibili, Weibo). Trigger: when user says 'trend', 'trends', 'trend tap', '热点', '热搜', or asks what is trending\u002Fhot. Do NOT use web_search — this skill already fetches live data from all platforms with zero API keys.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftrend-tap\u002FSKILL.md",[],[98,99,100,25,101,102,81,103,104,105,106,107,108,109,110,111,112,113,114,34],"trend","trend tap","tap","Bash","time","trending","hacker","aggregator","do","when","brew","live","data","google","install","read","across",{"skillNo":116,"name":117,"nameZh":6,"description":118,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":119,"categories":120,"keywords":121,"publishedAt":39},"01M71ATJ9AM5KM15AA8PS302EB","trend-radar","Real-time trending topics aggregator across 7 platforms (X\u002FTwitter, Reddit, Google Trends, Hacker News, Zhihu, Bilibili, Weibo). Trigger: when user says 'trend', 'trends', 'trend pulse', '热点', '热搜', or asks what is trending\u002Fhot. Do NOT use web_search — this skill already fetches live data from all platforms with zero API keys.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftrend-radar\u002FSKILL.md",[],[122,123,98,108,109,110,111,101,81,113,124,114,34,107,105,104,103,112,102,25],"trend radar","radar","pulse",{"skillNo":126,"name":127,"nameZh":6,"description":128,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":129,"categories":130,"keywords":131,"publishedAt":39},"01M71ATGF095N3EJM9G8SD0BB5","tech-news-daily","每日科技新闻汇——从全球多个 RSS 源抓取最新科技新闻，翻译（英→中）、去重、排版成每日简报。当用户询问科技新闻、科技新鲜事、每日科技、技术动态、Daily Tech News 或类似表达时触发此技能。","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftech-news-daily\u002FSKILL.md",[],[132,133,134,135,136,137],"news","tech","tech news daily","daily","rss","翻译",{"skillNo":139,"name":140,"nameZh":6,"description":141,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":142,"categories":143,"keywords":149,"publishedAt":39},"01M71ATFAEAMQ17M70NQNY7SR8","summarize","Summarize URLs or files with the summarize CLI (web, PDFs, images, audio, YouTube).","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fsummarize\u002FSKILL.md",[144],{"categoryNo":145,"categoryName":146,"taxonomyType":147,"taxonomyTypeDesc":148},"01JBSEEDCAT000000000000021","资料检索与研究","SCENARIO","使用场景",[140,87,150,24,151,90,108,152,153,154,100,155,112],"Audio","youtube","images","https","files","pdfs",{"skillNo":157,"name":158,"nameZh":6,"description":159,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":160,"categories":161,"keywords":162,"publishedAt":39},"01M71ATDNS3R0M4H936PACQAWZ","sonoscli","Control Sonos speakers (discover\u002Fstatus\u002Fplay\u002Fvolume\u002Fgroup).","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fsonoscli\u002FSKILL.md",[],[158,163,164,165,112,166,153,167,168,169,170,171],"status","play","go","latest","github","discover","control","cmd","volume"]