第二章:AWS Secrets Manager 概述

为什么我们需要一个专门的秘密管理器?

说实话,在接触 AWS Secrets Manager 之前,我见过太多团队把数据库密码直接写在代码里、配置文件里,甚至环境变量里。我遇到过最夸张的一次——客户的生产环境 RDS 密码被开发同学顺手贴在团队 Wiki 上。这就像把家门钥匙挂在门外地毯下面,谁都能踩一脚。

你想想看,真正关键的秘密(数据库凭证、、SSH 密钥)需要满足三个基本要求:加密存储、自动轮换、可审计。普通参数存储工具能做到第一条,但后两条往往需要额外开发。AWS Secrets Manager 正是为了解决这些问题而生,它把秘密当作一等公民来管理。

核心概念:Secret 到底长什么样?

一个 Secret 说白了就是一个 JSON 字符串,里面可以放任意键值对。比如一个 RDS 凭证 Secret 大概长这样:

{
  "username": "admin",
  "password": "SuperSecureP@ss1",
  "engine": "mysql",
  "host": "my-db.cluster-xxx.us-east-1.rds.amazonaws.com",
  "port": 3306,
  "dbInstanceIdentifier": "prod-db"
}

每个 Secret 会有版本号(Version ID),当你轮换或更新秘密时会自动生成新版本。我习惯把 Secrets Manager 想象成一个保险柜,每个保险柜(Secret)里有一个活页夹(版本列表),最新一页就是当前有效版本。

审计关键点:无论你存了什么内容,Secrets Manager 都通过 CloudTrail 记录所有 API 调用——谁在什么时间读取了哪个 Secret、哪个版本,都跑不掉。

它是怎么工作的?

来,我画了一张图帮你理清脉络。这张图展示了 Secrets Manager 与周围组件的关系:

AWS Secrets Manager 核心架构关系 AWS Secrets Manager 核心架构 AWS Secrets Manager 存储 · 轮换 · 审计 AWS KMS(主密钥) 加密/解密 Secret 内容 应用程序 / Lambda 通过 SDK/CLI 读取 目标服务(如 RDS) 自动轮换时更新密码 AWS CloudTrail 记录所有 GetSecretValue / RotateSecret 等 注意:KMS 只负责加解密 Secret 的“信封”,实际存储和轮换逻辑全在 Secrets Manager 内部 CloudTrail 会自动捕获 KMS Decrypt 和 Secrets Manager GetSecretValue 两个 API 调用
小提示:从审计角度看,我建议你重点关注两条链路——应用调用 GetSecretValue 时,CloudTrail 会同时记录 Secrets Manager 的 API 以及 KMS 的 Decrypt 事件(如果开启了 KMS 事件记录)。把这两条线索串起来,才能追踪到谁解密了哪个秘密。

自动轮换到底怎么玩?

轮换是 Secrets Manager 最亮眼的功能,也是审计的重灾区。默认情况下,Secrets Manager 会调用一个 Lambda 函数来完成轮换逻辑。比如针对 RDS,它会用两个版本交替更新(当前版本和待定版本),确保轮换过程中应用不中断。

我曾经帮一个金融客户审计时发现,他们的 Secret 轮换周期设置成了 365 天。我问为什么,他们说“怕轮换太频繁影响业务”。实际上,轮换周期超过 90 天就等于没设——攻破一个密码只需要几天,留着一年不换风险极大。

避坑指南:我曾经见过有人把轮换 Lambda 的权限给得太大——轮换函数可以操作所有 RDS 实例。结果有一次 Lambda 脚本出现 bug,把生产库密码改成了空字符串。所以一定要给轮换 Lambda 分配最小权限,只允许修改指定 Secret 关联的 RDS 用户密码。

使用场景速览

我把常见的场景按审计难度排了个序:

场景秘密类型审计要点推荐轮换频率
数据库凭证用户名/密码对谁读?哪些应用读?是否跨账号读取?30~90天
第三方服务 轮换时是否更新下游依赖?按服务商要求
SSH 密钥对私钥+公钥私钥下载后是否立即回收?90~180天
OAuth ClientSecret字符串轮换期间是否导致令牌失效?30~60天

注意,表格里的轮换频率只是参考。我个人习惯在配置中设一个轮换策略的触发器——比如每到周三凌晨 3 点,就跑一次轮换 Lambda,而不是依赖固定的日历天数。

权限模型:谁可以碰我的秘密?

Secrets Manager 使用资源策略和身份策略两层控制。你可以给整个 Secret 写一个资源策略(类似于 S3 桶策略),也可以给 IAM 用户/角色赋权。我见过一个常见误区:给了一个 Lambda 执行角色 secretsmanager:* 权限,结果这个 Lambda 能读取所有 Secret。正确的做法是只允许 secretsmanager:GetSecretValue 针对特定 ARN。

# 示例 IAM 策略——只允许读取一个特定 Secret
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "secretsmanager:GetSecretValue",
      "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/mysql/app-*"
    }
  ]
}
审计提醒:CloudTrail 中每条 GetSecretValue 记录都会包含请求者的 IAM 身份和 ARN。如果你发现某个 Lambda 在凌晨频繁调用了不该读的 Secret,那就是妥妥的异常行为,需要立刻调查。

与 KMS 的关系:加密不是叠加的

很多人会问:Secrets Manager 自带加密吗?答案是:自带,但默认使用的是 AWS 托管密钥(aws/secretsmanager)。你也可以使用自己创建的 CMK(客户主密钥)。我建议审计场景用自定义 CMK,因为你可以通过 KMS 的密钥策略精确控制谁有权解密 Secret,还能通过 CloudTrail 追踪每次解密事件。

注意一个细节——Secrets Manager 对 Secret 内容进行的是信封加密:

  1. Secrets Manager 调用 KMS 生成一个数据密钥(Data Key)。
  2. 用数据密钥加密你的 Secret 内容。
  3. 用 CMK 加密数据密钥,存储密文。
  4. 读取时反向操作。

所以,即使你拿不到 CMK 的权限,也解密不了数据密钥;即使拿到 CMK,没有数据密钥的密文也白搭。这种双重保险在 SOC2 审计中很受欢迎。

好了,Secrets Manager 的全貌基本讲清楚了。说实话,工具本身不复杂,复杂的是怎么用好它、怎么审计它。后面几章我们会在实际操作中把这些概念一一落地。嗯,今天先到这里。