关于 secrets-manager
面向需要管理 AWS 应用密钥的开发者,介绍 AWS Secrets Manager 的存储、读取和轮换方式。指南覆盖密钥版本、CLI、缓存、访问控制和问题排查。
主要功能
- 01加密存储密钥与凭证
- 02读取、更新和管理密钥版本
- 03使用 Lambda 自动轮换凭证
- 04缓存密钥以减少 API 调用
- 05CLI 命令与访问控制参考
适用场景
- 01存储应用数据库凭证和 API 密钥
- 02定期轮换数据库凭证
- 03在应用中读取并缓存密钥
- 04排查访问权限或轮换失败
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ itsmostafa/ aws-agent-skills --skill secrets-manager安装后在 Claude Code 中输入/secrets-manager确认已加载。
附带文件rotation-strategies.md
详细介绍
AWS Secrets Manager
AWS Secrets Manager 可帮助保护对应用程序、服务和 IT 资源的访问。存储、检索凭证、API 密钥和其他密钥,并自动轮换它们。
目录
核心概念
密钥
存储在 Secrets Manager 中的加密数据。可以包含:
- 数据库凭证
- API 密钥
- OAuth 令牌
- 任意键值对(最大 64 KB)
版本
每个密钥可以有多个版本:
- AWSCURRENT:当前活动版本
- AWSPENDING:正在轮换到的版本
- AWSPREVIOUS:上一版本
轮换
使用 Lambda 函数自动轮换凭证。内置支持:
- Amazon RDS
- Amazon Redshift
- Amazon DocumentDB
- 自定义密钥
常见模式
创建密钥
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'}
]
)
检索密钥
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']
缓存密钥
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 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
为 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
创建并启用轮换的密钥
# 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
在 Lambda 中使用扩展
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 参考
密钥管理
| 命令 | 说明 |
|---|---|
aws secretsmanager create-secret | 创建密钥 |
aws secretsmanager describe-secret | 获取密钥元数据 |
aws secretsmanager get-secret-value | 检索密钥值 |
aws secretsmanager update-secret | 更新密钥 |
aws secretsmanager delete-secret | 删除密钥 |
aws secretsmanager restore-secret | 恢复已删除的密钥 |
aws secretsmanager list-secrets | 列出密钥 |
版本
| 命令 | 说明 |
|---|---|
aws secretsmanager put-secret-value | 添加新版本 |
aws secretsmanager list-secret-version-ids | 列出版本 |
aws secretsmanager update-secret-version-stage | 移动暂存标签 |
轮换
| 命令 | 说明 |
|---|---|
aws secretsmanager rotate-secret | 配置/触发轮换 |
aws secretsmanager cancel-rotate-secret | 取消轮换 |
最佳实践
密钥组织
- 使用分层名称:
environment/application/secret-type - 为密钥添加标签,以便组织管理和成本分配
- 按环境区分(dev、staging、prod)
安全
- 使用资源策略控制访问
- 使用客户管理的 KMS 密钥启用加密
- 定期轮换密钥(30-90 天)
- 使用 CloudTrail 审计访问
- 使用 VPC 端点进行私有访问
访问控制
{
"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"
}
}
}
]
}
应用程序集成
- 缓存密钥以减少 API 调用
- 妥善处理轮换(使用新凭证重试)
- 使用 Lambda 扩展以加快访问速度
- 切勿记录密钥
故障排除
AccessDeniedException
原因:
- IAM 策略缺少
secretsmanager:GetSecretValue - 资源策略拒绝访问
- KMS 密钥策略缺少权限
调试:
# 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
轮换失败
调试:
# 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"
常见原因:
- Lambda 超时(增加到 30 秒以上)
- 网络连接问题(VPC 配置)
- 数据库连接问题
- 密钥格式错误
找不到密钥
# 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
参考资料
评论
支持 Markdown