site logo

Marico's space

无人撤销的凭证:通过 CloudTrail 和 Lambda 在 Slack 中发送 AWS 安全警报

AI技术与应用 2026-11-06 20:56:04 6

最近折腾 AWS(亚马逊云服务)安全告警时,我踩过几个坑:CloudTrail 明明记下了所有操作,却没人盯着日志;等发现异常时,往往已经过去了好几天。这篇把整件事说清楚:如何用 CloudTrail 和 Lambda(无服务器计算服务)筛选高风险事件,再把告警实时推到 Slack,顺便算清楚这套方案到底要花多少钱。

你是否想知道,有人通过访问密钥(access key)越权访问,或者擅自扮演某个角色?又或者离职员工还在使用克隆到自己笔记本上的凭证,准备把生产环境全部毁掉?

好消息是,AWS 已经记录了这些操作。坏消息是,大多数团队并不会实时查看这些日志,通常要等到几天后服务异常才发现问题。这里要讨论的,不是具体的命令和配置,而是一套补上监控缺口的基本思路:它如何工作、能告警什么、能带来什么收益,以及实际成本是多少。

如果准备落地,后面这个 AWS Builder Center 技术版文章会给出关键代码、命令,以及每个组件的完整配置。

一句话讲清思路

AWS 账户里的所有活动都有日志记录。我们的做法是,在日志上增加一个过滤器,只放行危险事件;再用一个函数判断每个事件有多严重,最后把告警发到团队的 Slack 频道,让值班人员几分钟内就能看到。

完整的数据流大致如下:

每次调用 AWS 都会留下痕迹

一切从 CloudTrail 开始,它是 AWS 的审计日志。每当有人或某个程序调用 API(应用程序接口)时,CloudTrail 都会记录:具体做了什么、涉及哪个服务、发生时间、来源 IP(互联网协议地址)、所属账户,以及操作最终成功还是失败。

但真正让整套方案成为可能的是另一个字段:userIdentity.type。它表示每次调用使用的是哪种类型的凭证。

类型 含义
Root 有人使用了账户的 root 权限
IAMUser 长期凭证,例如 IAM(身份与访问管理)用户的访问密钥或密码
AssumedRole 扮演角色后获得的临时凭证
AWSAccount 另一个 AWS 账户扮演了你的角色
AWSService 某个 AWS 服务代表你执行了操作

有了这张表,文章开头提到的每种场景都有可识别的特征。遗留在笔记本上的访问密钥会显示为 IAMUser;第三方从自己的账户扮演你的角色,会显示为 AWSAccount;使用 root 登录,则会直接标记为 Root。

实现这套方案需要的组件

既然已经明确能拿到哪些信息,接下来看看这些工作分别由谁负责:

  • Organization Trail。在 AWS Organization 中,例如由 Control Tower 管理的组织,只需一条 trail 就能记录所有账户的事件,相当于一个统一审计入口。
  • CloudWatch Logs。Trail 会把事件发送到这里的日志组,日志组位于管理账户中。
  • 订阅过滤器(subscription filters)。它们是绑定在日志组上的规则,只放行符合指定模式的事件。它就像门卫,函数根本不会看到数百万条正常调用记录。
  • Lambda 函数。它接收过滤器放行的事件,并计算严重程度。这是整套系统中唯一包含自定义逻辑的组件,而且逻辑边界很明确:解码、分类、发布。
  • Amazon Q Developer。这是 AWS 用来把 SNS(简单通知服务)Topic 中的消息发布到 Slack 或 Teams 的服务。借助它,不必再把 Slack Webhook 当成密钥保存。

有人动了资源之后会发生什么

组件已经齐了,接下来跟踪一个具体案例:有人使用访问密钥删除生产环境中的数据库。

  1. CloudTrail 将事件写入 Organization Trail。
  2. 事件被投递到 CloudWatch Logs。平均耗时约 5 分钟,但 AWS 明确表示这个时间不保证固定。
  3. 过滤器评估事件。如果不匹配任何模式,流程就到此结束,也不会产生计算费用。在这个案例中,事件成功命中规则。
  4. 函数计算严重程度。判断依据分为三个维度:
    • 账户:生产环境的权重高于开发环境;
    • 服务:操作 RDS(关系型数据库服务)、DynamoDB、KMS(密钥管理服务)、AWS Backup、Secrets Manager 或 IAM,比删除一个临时实例严重得多;
    • 凭证类型:长期凭证(IAMUser)比临时凭证更值得警惕。
  5. 消息发送到 Slack。根据严重程度显示 🔴、🟠 或 🟡,并附上账户、操作、执行者、使用的凭证和来源 IP。

如果函数执行失败呢?AWS 会额外重试两次。仍然失败时,事件会保存在备用队列中,同时告警通知团队,避免任何告警悄无声息地丢失。

真正改变结果的设计决策:谁,以及什么

到这里,看起来都很直接。但有一个设计决策决定了系统究竟能不能真正保护你:究竟让哪些事件通过过滤器。

最自然的做法是,只关注团队成员的操作,例如通过 SSO(单点登录)登录的用户,避免流水线和 Kubernetes 控制器把频道刷爆。但问题是,使用访问密钥的 IAM 用户不会通过 SSO 登录。这样的过滤器,恰好会漏掉员工离职后仍然存活的凭证。

解决办法是把问题拆成两部分。CloudWatch Logs 刚好支持这种设计,因为每个日志组最多可以配置两个订阅过滤器:

  • 谁正在操作?包括使用 root、未启用 MFA(多因素认证)时登录、修改 CloudTrail、使用长期凭证执行任何写操作,以及可能留下后门的 IAM 变更,例如创建访问密钥或修改信任策略。
  • 什么正在被破坏?包括由任意执行者发起的删除和不可逆操作,同时排除 AWS 服务与已知自动化任务。

这些模式也不需要完全从零编写。AWS 在 Security Hub 的 CloudWatch.1 到 CloudWatch.14 安全控制项中,提供了覆盖 root、MFA、IAM 变更、CloudTrail、KMS、S3 和网络配置的官方模式。这些模式基于 CIS(互联网安全中心)AWS Foundations Benchmark,是非常合适的起点。

这套系统能替你发现什么

两个过滤器运行后,以下几类情况会出现在 Slack 中:

  • 离职交接不完整。已经离开团队的人仍在使用无人撤销的访问密钥,告警中会包含凭证类型和对应的 IAM 用户名称。
  • 凭证泄露。暴露在代码仓库中的访问密钥,开始从陌生 IP 地址发起调用。
  • 后门入口。有人创建新的访问密钥,或者修改信任策略,为后续重新进入账户留下通道。
  • 使用 root 或未启用 MFA 的登录。这两项本身就是最基础的安全控制项。
  • 试图销毁证据。例如关闭或修改 CloudTrail。
  • 针对数据的破坏性操作。例如删除数据库、备份,或者安排删除 KMS 密钥。
  • 诚实的误操作。并非所有事件都是攻击,例如在错误账户执行 destroy;能够在几分钟内发现,同样有价值。

为什么值得把它部署起来

除了处理具体事件,这套系统还会改变团队看待基础设施的方式:

  • 从晚发现变成几分钟内发现。这是最关键的差别。
  • 整个组织集中到一个入口。一条 trail、一个日志组和一个函数,就能覆盖当前以及未来新增的所有账户。
  • 每条告警都带着上下文。账户、操作、执行者、凭证和 IP 都在消息中,值班人员不用打开控制台就知道该查什么。
  • 严重程度可以控制噪音。生产环境的删除与开发环境明显不同,分级之后,告警频道才不会被大家直接忽略。
  • 全部使用云上原生服务。不需要客户端、服务器,也不用维护 SIEM(安全信息与事件管理)平台,并且可以像其他基础设施代码一样完成部署。
  • 可以持续扩展。以后增加新的匹配模式,不需要改变整体架构。

继续扩展:数据库、密钥与备份

系统跑起来以后,最值得结合自身业务调整的是“正在破坏什么”这个过滤器。下面这些操作建议纳入考虑:

  • RDS 和 Aurora:删除实例、集群、快照或自动备份,停止数据库,尤其是把快照共享给另一个账户或设为公开——这是一种不声不响带走数据的方式。
  • DynamoDB:删除表或备份。
  • KMS:安排删除密钥或禁用密钥。密钥一旦丢失,加密后的数据就无法恢复。
  • AWS Backup:删除恢复点或保管库,或者修改访问策略。它往往是最后一条恢复路径。
  • Secrets Manager:删除密钥。

有个细节需要注意:DynamoDB 默认会记录删除表的操作,但逐条删除数据项不会记录。后者属于数据事件(data events),需要在 trail 中单独启用,并会产生额外费用。

运行成本是多少

大多数情况下,这套方案花不了多少钱。核心取决于一个问题:你的 trail 是否已经把事件发送到 CloudWatch Logs?

组件 计费方式 预期费用
CloudTrail,第一份管理事件副本 投递到 S3 时免费 没有新增成本
CloudTrail 投递到 CloudWatch Logs 每 GB 投递费用 USD 0.25,另加 CloudWatch Logs 摄取费用 如果还没有配置,这通常是主要成本;使用 Control Tower 时已经存在
Lambda 每百万次调用 USD 0.20,每 GB-s USD 0.0000166667(x86);免费额度为每月 100 万次调用和 400,000 GB-s 基本可以视为零成本:只会处理过滤后的事件
SNS 按发布次数计费 每条告警发布一条消息
Amazon Q Developer,自定义通知 没有额外费用 零

可以看一组实际数据:一个包含 7 个账户的组织原本已经把 trail 发送到 CloudWatch Logs,连续统计了 16 天。期间函数执行了 19 次,共发布 103 条消息,折算下来,每月成本不到 1 美分。

如果你的 trail 还没有把事件发送到 CloudWatch Logs,真正需要关注的是组织每月产生的事件量,以 GB 为单位,因为交付和摄取费用都由它决定。

这套系统不做什么

想正确使用它,也需要明确能力边界:

  • 它不能阻止操作。告警会在几分钟后到达。如果需要从源头阻止,可以使用 AWS Organizations 的 SCP(服务控制策略)。
  • 它不能替代离职交接。最好的告警,是根本不会触发的告警,因为访问密钥已经被删除。AWS 建议人员使用临时凭证。
  • 它不是 SIEM。它更像一层轻量安全网,适合没有安全运营中心(SOC)持续盯着 CloudTrail 的团队。

最后总结

只按谁来过滤,看起来似乎已经够了,直到真正值得警惕的执行者恰恰不像日常用户。再按什么正在被破坏增加一层过滤,才能补上这个缺口。而且整套方案都由原生云服务组成,长期运行成本几乎可以忽略。

AWS Builder Center 的技术版文章里,包含了函数的关键代码、连接各组件所需的命令、两个过滤器的设计、需要留意的边界,以及常见问题的处理方法。

换句话说,如果明天有人使用了一直没人撤销的访问密钥,你们会从哪里发现问题?

参考资料

  • CloudTrail userIdentity element
  • About logging in AWS Control Tower
  • Sending CloudTrail events to CloudWatch Logs
  • PutSubscriptionFilter
  • Security Hub CSPM controls for CloudWatch
  • How Lambda handles errors and retries with asynchronous invocation
  • Custom notifications in Amazon Q Developer in chat applications
  • Security best practices in IAM
  • Logging DynamoDB operations by using CloudTrail
  • Monitoring Amazon RDS API calls in CloudTrail
  • AWS CloudTrail pricing
  • AWS Lambda pricing

关注更多平台

这个主题还整理成了 YouTube Shorts、TikTok、Instagram Reels 短视频,LinkedIn 轮播图,Medium 文章,以及 AWS Builder Center 技术版文章。

  • Medium:medium.com/@lucianonicolasloyola
  • YouTube:youtube.com/@dev.luchops
  • TikTok:tiktok.com/@dev.luchops
  • Instagram:instagram.com/dev.luchops
  • LinkedIn:Luciano Nicolás Loyola
━━━━━━━━━━━━━━━━━━━━
🟧 dev.luchops
Cloud & DevOps, explicado sin vueltas.
━━━━━━━━━━━━━━━━━━━━
Enter fullscreen mode Exit fullscreen mode