秘密的管理艺术:Secrets Manager 基础与 IAM 权限模型

搞安全的人都知道——密码、、数据库凭证这些敏感信息,不能硬编码在代码里。但现实中我见过不少团队把密钥写在配置文件中,甚至提交到 Git 仓库。嗯,这就像把家门钥匙挂在门上。AWS Secrets Manager 就是帮你管好这些“钥匙”的服务,自动轮换、细粒度授权,用起来很顺手。

创建秘密:从控制台到 CLI

创建秘密有两种主流方式:控制台点点点,或者 CLI 一把梭。我个人习惯用 CLI,因为可重复、可自动化。先看一个最基本的例子:

aws secretsmanager create-secret \
    --name MyDBSecret \
    --description "RDS primary credentials" \
    --secret-string '{"username":"admin","password":"P@ssw0rd123"}' \
    --tags Key=Environment,Value=Production

这里要注意几个点:

  • secret-string 可以是任意字符串,但推荐用 JSON 结构,方便后续解析。
  • --tags 不是可选项,我建议生产环境必打标签,后面做成本分摊和权限控制都依赖它。
  • 秘密名称(MyDBSecret)一旦创建就不可修改,只能删除重建。起名要规范。

控制台创建的步骤也差不多,填好键值对,AWS 还提供“自动生成密码”的功能,长度、特殊字符都能定制。我曾经帮一个客户迁移时,他们手动设了 100 位随机字符串——结果程序连接超时,因为密码太长解析慢。经验是 32-64 位,够用且稳定。

Secrets Manager 核心操作流程 ① 创建秘密 ② 存储(KMS加密) ③ 轮换(Lambda) ④ IAM 权限 ⑤ 获取秘密(GetSecretValue) ⑥ CloudTrail 审计 说明:箭头表示数据流向

存储与加密:KMS 自动保护

秘密创建后,Secrets Manager 会用 AWS KMS 自动加密。默认使用服务自带的 aws/secretsmanager 托管密钥,不需要额外付费。但如果你有合规要求(比如必须使用自己的 CMK),在创建时可以指定:

aws secretsmanager create-secret \
    --name MyDBSecret \
    --kms-key-id arn:aws:kms:us-east-1:123456789012:key/xxxx-xxxx-xxxx-xxxx \
    --secret-string '{"username":"admin","password":"P@ssw0rd123"}'
注意: 如果你用自定义 CMK,密钥一旦被禁用或删除,所有用它加密的秘密将无法解密。我曾经遇到过一个团队误删了 KMS 密钥,导致线上服务全部崩溃——这就是为什么我建议对 CMK 开启自动 key rotation,并严格保护其 IAM 策略。

秘密的存储本身不额外收费,但 API 调用、存储大小和轮换次数都会产生费用。我一般建议把大型连接字符串拆成多个小秘密,按模块分类。

自动轮换:Lambda 驱动,零停机

轮换是 Secrets Manager 的杀手锏。它通过 Lambda 函数自动更新密码,期间服务不停顿。工作原理大致分两步:

  1. 创建轮换 Lambda —— 推荐直接用 AWS 提供的轮换模板(RDS、Redshift、DocDB 等),也可以自己写。
  2. 配置轮换周期 —— 在秘密属性中设置 RotationSchedule,比如每 30 天轮换一次。

这里有一个坑:默认的 Lambda 执行角色需要最小权限。我曾在项目中见到有人给 Lambda 绑了 AdministratorAccess——不推荐。按最小权限原则,权限应该只包括:

  • secretsmanager:GetSecretValue(读取当前秘密)
  • secretsmanager:PutSecretValue(写入新版本)
  • secretsmanager:UpdateSecretVersionStage(管理版本阶段)
  • 目标服务的修改密码权限(比如 rds:ModifyDBInstance)
个人经验: 首次启用轮换时,一定要先用 --rotation-rules AutomaticallyRotateAfterDays=90 测试一轮,确认 Lambda 日志没有报错,再改成生产周期。千万别一上来就设 7 天轮换——如果函数有 bug,一周后全体数据库密码都乱了。

IAM 权限模型:谁可以看,谁可以改

Secrets Manager 的权限控制基于 IAM 策略,分成两个维度:

  • 管理操作:CreateSecret、DeleteSecret、PutSecretValue
  • 读取操作:GetSecretValue、DescribeSecret

大部分场景下,只有管理员才需要写权限,普通应用只需要读。下面是一个典型的最小权限策略,只允许某个 EC2 角色读取特定秘密:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "secretsmanager:GetSecretValue",
            "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:MyDBSecret-*"
        }
    ]
}
操作IAM Action最小资源典型场景
创建秘密secretsmanager:CreateSecret*管理员创建新凭证
读取秘密secretsmanager:GetSecretValue特定秘密 ARN应用启动时获取数据库密码
修改秘密secretsmanager:PutSecretValue特定秘密 ARN手动更新凭证
启用轮换secretsmanager:RotateSecret特定秘密 ARN配置自动轮换
删除秘密secretsmanager:DeleteSecret特定秘密 ARN清理废弃秘密

这里要特别强调一个细节:GetSecretValue 返回明文密码,所以该权限一定要收敛。我习惯在策略中加上条件,比如只允许来自 VPC 内的请求:

"Condition": {
    "StringEquals": {
        "aws:SourceVpce": "vpce-xxxxxxxx"
    }
}
核心原则: 永远不要给非管理员实体 secretsmanager:* 权限。我把这句贴在团队 wiki 页面上,谁违反谁请喝咖啡。

避坑指南:我踩过的三个雷

  1. 跨区域访问秘密: 秘密是区域资源,不能跨 region 读取。如果需要,只能通过同步工具(如 aws secretsmanager replicate-secret)复制到其他区域。
  2. 版本管理混乱: Secrets Manager 自动管理版本(AWSCURRENT、AWSPREVIOUS)。如果你手动多次更新又不指定阶段,会堆积废弃版本,产生存储费用。记得定期清理。
  3. Lambda 轮换超时: 默认 Lambda 超时 3 秒,但修改数据库密码可能需要几秒到几十秒。我遇到过超时报错导致轮换失败。建议把 Lambda 超时设为 30 秒以上。

嗯,以上就是 Secrets Manager 的核心基础。创建、存储、轮换、权限管理——这四步走稳了,后面才能放心地把 Secrets 接入 CloudTrail 做审计可视化。下节课我们直接上手实操,看看怎么用 SDK 获取秘密并记录到 CloudTrail。