4. CloudTrail日志存储架构详解

聊到CloudTrail日志存储,很多人的第一反应就是“把日志丢S3桶里就行了”。

嗯,没那么简单。

日志从产生到落地,再到你能随时查、不会被时间吞掉,中间涉及了很多设计决策。桶策略、前缀命名、跨账户访问、生命周期管理——这四块拼起来,才是完整方案。

我个人习惯是:先把存储架构想清楚,再动手配采集。架构定好了,后面基本不动。如果上来就配,后面改来改去,那可真是给自己找麻烦。

总体目标:一个可审计、可检索、可隔离、可自动清理的日志湖。
CloudTrail日志存储架构总览 CloudTrail 日志存储架构 CloudTrail S3 日志存储桶(主桶) 桶策略 前缀 & 分区 跨账户访问 生命周期管理 桶策略 控制谁能写/读 强制加密、拒绝公开 前缀 & 分区 按年/月/日/账户分区 方便 Athena 查询 跨账户访问 集中审计账号收集 子账号授权读权限 生命周期管理 过渡/归档/过期删除 90天后S3 IA 交付成果:可审计 · 可检索 · 可隔离 · 可自动清理

4.1 桶策略配置:别让它裸奔

CloudTrail写入S3的权限,不是天然就有的。

你得在桶策略里明确告诉S3:“CloudTrail这个服务,允许向我写日志”。同时还要卡死“谁可以读”、“从哪来读”。

我记得有一次帮客户排查,发现日志一直没写进去。查到最后——桶策略里忘了写源IP条件。CloudTrail是有固定的源IP段的,不限制的话别人也能往里写,但限制了才能保证写进来的都是正经日志。

核心原则只有两条:

  • 写权限独占:只允许CloudTrail服务主体写入
  • 读权限最小化:只有审计、安全团队需要读

一个比较稳的桶策略模板长这样:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudtrail.amazonaws.com"
      },
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::my-logs-bucket/AWSLogs/*"
    },
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::my-logs-bucket",
        "arn:aws:s3:::my-logs-bucket/*"
      ],
      "Condition": {
        "Bool": { "aws:SecureTransport": "false" }
      }
    }
  ]
}
重要:必须加上 aws:SecureTransport 的 Deny 阻止非 HTTPS 访问。否则日志可能在传输中被截获。

4.2 前缀与分区规则:文件多了就好找?不见得

CloudTrail默认的前缀结构是:AWSLogs/<账户ID>/CloudTrail/<区域>/<年>/<月>/<日>

我用这个结构用了好几年,真的很舒服。为什么?

  • 按账户隔离:多账户场景下,每个账户的日志自动落到自己的目录下
  • 按时间分区:Athena查询时直接指定前缀范围,扫描量小,花钱也少
  • 批量管理方便:生命周期策略可以针对某个年/月的目录直接设置

但我见过一些团队用自定义前缀,比如按项目名来分。你想想看,项目是动态的,今天叫“ProjectX”,明天改叫“ProjectY”,前缀一乱,所有历史查询都得改路径——那叫一个痛苦。

我个人建议:只用AWS的默认前缀结构。如果你有特殊需求,可以在默认结构基础上加前缀后缀,但不要动时间分区体系。

4.3 跨账户访问设置:集中审计怎么做

很多企业有几十甚至上百个AWS账号。每个账号自己管自己的日志?审计能疯了。

最佳实践是:一个审计账号,所有日志都往这个账号的S3桶里写。

这里要注意的是权限关系:

  1. 审计账号创建一个S3桶,把桶策略配置好(允许其他账号的CloudTrail写入)
  2. 在每个子账号里配置CloudTrail,指定日志目标为审计账号的S3桶
  3. 子账号的CloudTrail本身需要一个写权限的IAM角色

桶策略的关键写法:

{
  "Effect": "Allow",
  "Principal": {
    "Service": "cloudtrail.amazonaws.com"
  },
  "Action": "s3:PutObject",
  "Resource": "arn:aws:s3:::audit-logs-bucket/AWSLogs/<子账号ID>/*",
  "Condition": {
    "StringEquals": {
      "s3:x-amz-acl": "bucket-owner-full-control"
    }
  }
}
说个坑:我曾经碰到一个案例,跨账号日志写不进去,原因是子账号的CloudTrail没带上 bucket-owner-full-control 这个ACL。没了它,审计账号虽然存了日志,但桶的所有者是子账号——查询权限乱成一锅粥。一定要加上。

还有一条:审计账号的S3桶要明确拒绝公开访问。这是底线。

4.4 生命周期管理:让日志该走就走

日志越多,账单越痛。但日志又不能随便删,合规查起来你要能拿出来。

生命周期策略就是干这个的。说白了就是告诉S3:日志在某某时间段后自动转档、归档、或者删除。

一个常用的配置思路:

时长 存储类型 原因
0 - 90 天 S3 Standard 频繁查询,需要快速响应
90 - 365 天 S3 Infrequent Access 偶尔查一下,省存储费
1 - 3 年 S3 Glacier Deep Archive 合规留存,基本不查
3 年以上 删除 超过多数合规要求

具体怎么配?在S3桶的「管理」->「生命周期规则」里新建就行。注意规则要基于 前缀 来匹配,比如 AWSLogs/<账户ID>/CloudTrail/。

核心逻辑:生命周期配置是前缀敏感的。如果你改了前缀结构,旧的日志不会被新规则覆盖。

我自己的习惯是:保留90天的Standard + 1年的IA + 永久归档。 3年以上的日志在Deep Archive里,几乎不花钱,但真要查也能取出来。嗯,这个节奏对大多数公司够用。

总结一下这个章节的核心:桶策略锁住权限,前缀结构决定查询效率,跨账户让日志集中,生命周期控制成本与合规。 这四个点环环相扣。你配好了一个桶,就等于给整个CloudTrail系统搭好了地基。