Secrets Manager 事件类型:CreateSecret、UpdateSecret、DeleteSecret 等操作
审计事件是 CloudTrail 记录的“行为快照”。
说白了,就是 AWS 在某个时间点,替你记下了一句话:谁、在什么时候、通过什么方式、对哪个 Secret 做了什么操作。
Secrets Manager 的操作很多,但审计重点关注三类:创建(CreateSecret)、更新(UpdateSecret)、删除(DeleteSecret)。
我个人习惯把这三种事件称为“审计三兄弟”。
为什么是这三类?因为它们直接决定了 Secret 的生命周期状态,也是合规审查中最常被问到的问题。
4.1 CreateSecret 事件触发条件与字段全解
创建秘钥,是生命周期第一步。
触发条件很简单:你调用了 CreateSecret API,或者通过控制台、CLI、SDK 执行了创建操作。
CloudTrail 会记录一个 CreateSecret 事件。里面有几个字段我特别关注:
| 字段名称 | 说明 | 我常用的判断逻辑 |
|---|---|---|
| eventName | 固定为 "CreateSecret" | 用来区分操作类型,最直接 |
| requestParameters | 包含 Name、Description、KmsKeyId、SecretString 或 SecretBinary(掩码) | 检查 SecretString 是否为 "HIDDEN",如果是,说明控制台操作;否则可能是 CLI/SDK 绕过掩码 |
| responseElements | 返回的 ARN、VersionId、VersionStages | VersionId 可以用来追踪后续更新 |
| userIdentity | 谁创建的 | 重点关注 arn 和 type |
| eventTime | 精确到毫秒 | 配合其他事件做时序分析 |
重要提醒:SecretString 和 SecretBinary 在 CloudTrail 中默认会被记录为 HIDDEN。这其实是保护机制,避免敏感信息泄露。但如果你需要审计秘钥内容本身,那得另想办法——比如在 Lambda 函数里做自定义处理。
我的小技巧:遇到 HIDDEN 字段时,可以结合 VersionId 和 VersionStages 来判断创建后的版本状态。有一次我在项目中发现,有人创建 Secret 后没指定版本标签,导致后续轮转时找不着目标版本。这就是一个审计盲区。
4.2 UpdateSecret 事件识别与版本变化
更新操作,比创建更复杂一点点。
触发条件:你调用了 UpdateSecret API。控制台修改秘钥值、CLI 更新 SecretString、或者 SDK 触发的自动轮转,都会落到这个事件里。
那么如何识别一次更新?
- eventName 等于 "UpdateSecret";
- requestParameters 里可能包含
SecretString或SecretBinary,同样会被掩码; - responseElements 里会返回一个新的
VersionId。
嗯,这里要注意:每次更新都会产生一个新的版本。
我在项目中遇到过一个问题:某个团队每周都手动更新秘钥,但从不清理旧版本。结果 Secrets Manager 积累了 100 多个版本,不仅浪费空间,还让审计日志变得极其混乱。
为什么?因为每个 UpdateSecret 事件都关联一个 VersionId,但 CloudTrail 不会自动帮你删除旧版本。你得自己控制版本数量。
避坑指南:我曾经因为没关注 VersionStages 字段,导致轮转脚本总是更新到旧版本上。记住了:AWSCURRENT 是当前活跃版本,AWSPREVIOUS 是上一个版本。其他标签都是自定义的,需要你自行维护。
4.3 DeleteSecret 事件的两种场景:调度删除与立即删除
删除操作是审计中最敏感的一环。
触发条件:调用 DeleteSecret API。但 Secrets Manager 给了两个选项:
- 调度删除:设置一个等待窗口(默认 30 天),在这期间秘钥不可用,但可以恢复;
- 立即删除:不等待,直接软删除,但同样可以恢复(只要在窗口期内)。
这两种场景在 CloudTrail 里怎么区分?
| 场景 | requestParameters 关键差异 | responseElements 表现 |
|---|---|---|
| 调度删除 | RecoveryWindowInDays 大于 0(默认为 30) |
返回 DeletionDate,表示实际删除时间 |
| 立即删除 | RecoveryWindowInDays 为 0,或未指定 |
返回的 DeletionDate 很接近当前时间 |
我个人建议:生产环境永远不要用立即删除。
为什么?因为一旦误删,你只有极短的时间窗口去恢复——而大多数团队发现问题的速度,往往赶不上这个窗口。
实战经验:我曾在某个金融客户那里遇到过一次事故:运维人员在一个脚本里错误地删除了 5 个数据库凭证,而且还用了立即删除。幸好当时开启了 CloudTrail,我们通过 eventName = 'DeleteSecret' 和 userIdentity.arn 迅速定位到操作者,然后赶在 5 分钟内调用了 RestoreSecret API 恢复了所有秘钥。如果当时用的是调度删除,窗口期长得多,压力会小很多。
4.4 事件类型与审计字段核心逻辑图
为了让你一目了然,我把这三种事件的核心脉络画了出来:
4.5 关键字段对比:三种事件之间的差异
你会不会觉得:这三种事件看起来差不多,怎么区分?
其实看几个关键字段就够了。
| 字段路径 | CreateSecret | UpdateSecret | DeleteSecret |
|---|---|---|---|
| eventName | CreateSecret | UpdateSecret | DeleteSecret |
| requestParameters.secretId | 新创建的 Secret ARN | 已有 Secret ARN | 已有 Secret ARN |
| requestParameters.secretString | HIDDEN | HIDDEN(可能为空) | 无 |
| requestParameters.recoveryWindowInDays | 无 | 无 | 存在(调度删除)或 0(立即删除) |
| responseElements.versionId | 返回新版本 ID | 返回新版本 ID | 无(删除前最后版本不产生新 ID) |
实用技巧:在 CloudTrail 查询里,用 eventName IN ('CreateSecret','UpdateSecret','DeleteSecret') 筛选,就能拿到所有生命周期事件。然后再加上 userIdentity.type 或 sourceIPAddress 做进一步分析。我习惯把它做成一个 Athena 查询语句,自动化跑在安全分析流程里。
4.6 避坑指南:审计事件遗漏常见原因
最后说几个容易被忽略的点:
- 控制台操作 vs API 调用:控制台操作会在 CloudTrail 里产生事件,但你看到的
secretString永远是HIDDEN。如果有特殊情况需要记录明文,必须通过 API/SDK 手动处理。 - 自动轮转产生的 UpdateSecret 事件:Secrets Manager 托管轮转功能会自动调用
UpdateSecret。这个事件同样会被记录,而且 sourceIPAddress 可能是轮转服务的内网地址,别以为是异常行为。 - 恢复操作:
RestoreSecret不是一个单独的事件类型。它本质上是创建一个新的 Secret 版本,并恢复可用状态。CloudTrail 记录的是UpdateSecret事件,别搞混。 - 跨区域复制:如果你用了跨区域复制功能,副本区域的创建操作也会产生
CreateSecret事件。注意看awsRegion字段和userIdentity,可能是服务角色发起的。
避坑指南:我曾经在审计某次安全事件时,发现一堆 DeleteSecret 事件,但就是找不到执行者。后来查了半天,才发现这些删除操作是通过一个 Lambda 角色的临时凭证触发的,而且 Lambda 本身被配置了极短的超时时间,日志都快被覆盖了。从此以后,我习惯在审计策略里加上一条:记录所有与 Secrets Manager 相关的 Lambda 执行角色调用。