桶策略是什么?为什么我总跟人强调它

说白了,桶策略就是一把「权限锁」。

你在云上存了一堆文件,有财报、有用户照片、有日志备份。谁来读、谁来写、谁能列清单——这些都得有个规矩。桶策略就是那个规矩。

我记得刚带团队那会儿,有个同事问:「我们不是已经设了 IAM 策略吗?为啥还要搞桶策略?」这个问题问得好。IAM 控制的是「谁」可以做什么,桶策略控制的是「对什么」可以做什么。它们俩配合着用,才能把权限关进笼子里。

桶策略的定义与本质

桶策略是一份 JSON 文档,直接挂在一个存储桶(Bucket)上。你可以在里面定义哪些主体(Principal)能从哪些 IP 访问、在什么时间范围操作、允许或拒绝哪些动作。

一句话总结:桶策略 = 附在桶上的访问规则清单。

我在项目中遇到过不少开发者,觉得桶策略就是 IAM 的「简化版」。其实不是的。IAM 是全局的、用户维度的;桶策略是资源的、面向对象的。打个比方:IAM 是你的身份证,桶策略是贴在仓库门口的门禁规则。你拿着身份证(IAM)来,仓库还要根据门禁列表(桶策略)决定放不放你进去。

核心能力:我能用它做什么?

  • 公开访问控制:允许或禁止匿名用户读取某个目录(比如静态网站托管)
  • 跨账户授权:允许另一个 AWS 账户的某个角色拉取你的备份数据
  • 条件限制:只允许来自公司 VPN IP 段的写入请求
  • 强制加密:要求所有上传必须使用特定加密方式(比如 SSE-KMS)
  • 拒绝覆盖:用显式 Deny 覆盖掉任何允许,一刀切(嗯,这个后面会重点讲)

桶策略的结构长什么样?

我们直接看一段最基础的策略 JSON。你不用背,看个大概就行:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::example-bucket/public/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": "203.0.113.0/24"
        }
      }
    }
  ]
}

你看,一个 Statement 就是一个规则。Effect 是允许还是拒绝,Principal 是给谁用的,Action 是具体操作,Resource 是目标路径,Condition 是附加条件。就这么几个字段,组合出千变万化的规则。

个人习惯:我写桶策略时,永远先把 Deny 写好,再写 Allow。因为 Deny 是无条件的,安全兜底。Allow 哪怕写漏了一条,Deny 还能拦住。

桶策略 vs IAM 策略:一张表说清楚

对比维度桶策略IAM 策略
绑定对象存储桶(资源)用户/角色/组(主体)
可授权范围仅限该桶全局或服务级别的多个资源
支持匿名访问✅ 可在 Principal 写 *❌ 必须指定用户
跨账户授权✅ 原生支持需要信任策略配合
是否强制两者同时生效,Deny 优先级最高两者同时生效,Deny 优先级最高

你想想看,如果你只需要控制自己账户里的几个人,用 IAM 就够了。但你要开放给外部合作伙伴、要做静态网站、要限制 IP 来源——桶策略才是正解。

一个典型的应用场景:给前端静态资源开读权限

做 Web 的时候,经常要把图片、CSS、JS 放在 S3 上公开展示。这时候你得写一条策略:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::web-assets/*"
    }
  ]
}

就这么 5 行,全世界都能读你的前端资源了。但是——注意,如果桶里有机密文件,千万别把 Resource 写成整个桶,要精确到路径。

我曾经犯过的错:有一次上线前,我把 Resource 写成了 arn:aws:s3:::my-bucket/*,忘了限制路径。结果整个桶所有的文件都公开了。还好是测试桶,数据都是假的。从那以后,我每条策略都要手动校验 Resource 的颗粒度。

桶策略的生效逻辑:一张图看懂

下面的图展示了请求进来后,桶策略是如何跟 IAM 策略一起判定权限的。你看一遍就能明白整个流程。

桶策略权限判断流程 桶策略 + IAM 策略联合判断流程 用户发起 API 请求 IAM 策略评估 身份是否被允许执行该操作? 桶策略评估 资源上的策略是否允许或拒绝? 显式 Deny 优先 拒绝请求 ❌ 返回 403 允许请求 ✅ 继续执行操作 关键规则:只要有任一策略显式 Deny,不管其他策略是否 Allow,都拒绝。 没有显式 Deny 时,IAM 和桶策略都 Allow 才算通过。

用桶策略的几个核心原则

  1. 最小权限原则:只给需要的操作、只给需要的路径、只给需要的条件。多一个字段都不写。
  2. 显式 Deny 兜底:相信我,你总会有写漏 Allow 的时候。先在桶顶加一条 Deny,留一个精确的 Allow 例外,安全很多。
  3. 定期审计:我每季度会拉一次所有桶的策略清单,手工过一遍。尤其留意 Principal 为 * 的策略。
  4. 不要过度复杂:一句话能搞定的,别拆成十个 Statement。策略越长,越容易出错。
一个小技巧:写策略时可以用 AWS 的 Policy Simulator 模拟一下。省得你上线了才发现 Deny 把正常的请求也拦住了。我每次改生产策略之前,都会先去模拟器里跑一遍。

总结一下

桶策略这东西,说复杂不复杂,说简单却容易出事。你理解了它的定义、结构、与 IAM 的配合方式,就已经掌握了第一层安全护盾。

后面我们会逐渐深入——加密、跨账户、日志审计、条件表达式、安全最佳实践……但今天的基础打牢了,后面的坑就会少很多。

嗯,就这样,先记住一句话:任何权限问题,先看桶策略,再看 IAM,最后看网络。绝大多数翻车都是这个顺序查出来的。