1. 为什么私有配置会成为一场拉锯战
做云上运维的人应该都有这种体验:S3 桶在创建时默认是私有的,但真正导致数据泄露的从来不是 AWS 的默认策略,而是后续的各种“顺手操作”。比如某个开发为了给前端临时加载图片,勾选了“公开读取”;比如某个分析任务需要跨账号访问,直接在桶策略里写了 "Principal": "*";再比如用 AWS 控制台创建静态网站时,跟着向导一路 Next,最后桶就变成了 public。
问题的本质在于:S3 的权限模型是“允许优先”的,只要有一条显式允许的语句,且没有显式拒绝,访问就可能成功。 这意味着私有状态不是一劳永逸的配置,而是需要在每一次策略变更、每一个新桶创建时都保持的状态。靠“提醒大家小心”是没用的,必须建立一套体系,让错误的配置要么做不了,要么做了立刻被纠正。
这套体系就是标题里说的两条腿:预防性控制(Preventive Controls),把公有访问的路提前堵死;强制执行(Enforcement),在配置偏离预期时自动发现、自动修正。预防性控制适合在开发阶段和基础设施创建环节去落实,强制执行则适合在运行时兜底,两者配合才是一个完整的治理方案。
这篇文章的服务对象很明确:正在为团队设计 AWS 账号体系的安全工程师、被 CIS Benchmark 或等保要求追着整改的运维同学、还有那些“一个人管几个账号”的云管理员。下面讲的内容全部基于我在真实环境里用过的方案和踩过的坑,不是从文档里抄出来的概念堆砌。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. S3 对象私有的权限底层逻辑
2.1 四个访问入口,一个都不能漏
很多人对 S3 权限的理解停留在“桶策略加 Deny 就完事了”,但实际上一个 S3 对象能否被匿名访问,是由四个独立的机制共同决定的,它们是“或”的关系:只要任一入口放行了,对象就公开了。
第一个是 Bucket Policy,这是挂在桶级别的 JSON 策略,可以授权给指定账号、指定用户,也可以授权给所有人。第二个是 IAM Policy,它挂在用户或角色上,决定了一个经过身份认证的主体能对哪些桶和对象做什么操作。第三个是 ACL(访问控制列表),这是 S3 的“老古董”机制,基于 XML 的权限描述,可以单独给某个对象设置 public-read。最后一个是 Block Public Access 设置,这是 AWS 后来推出的“总开关”,可以覆盖掉前三种机制产生的公有访问。四个入口里,最常出问题的是前三个,而第四个恰好是我们做预防性控制时的主力工具。
需要特别提醒的是,S3 对象级别的 ACL 是一个历史包袱很重的功能。 在 2023 年 4 月之后,AWS 已经默认对新创建的桶禁用 ACL,但如果你的账号里存在旧桶,或者因特殊需求重新启用了 ACL,那它就是一个随时可能被点着的火药桶。我曾经在一个客户的桶里发现数千个被单独设置成 public-read 的图片对象,排查下来是很多年前某个上传脚本干的,而且这些对象的上传者早就离职了,连问都问不到。
2.2 私有不等于安全,这是最容易被误解的地方
从 S3 的设计逻辑来看,对象私有只是“没有被显式公开授权”,但如果你的访问密钥泄露了,私有对象一样可以被读取。所以我们在做“确保私有”这个课题时,脑子里要绷紧一根弦:我们做的事情不是让对象变成“锁在保险柜里”,而是确保没有合法的匿名访问通道。
这里有一个很好的生活化类比:S3 桶就像一间办公室,私有策略相当于关了门,但钥匙(访问密钥)还在保安那里。如果保安被收买了,门关不关都没用。所以完整的私有化方案通常包含两层——外层关掉所有匿名通道,内层管好身份和密钥。这篇文章的重点在外层,但如果你在落地时发现对象是私有的、数据却仍然泄露了,那要立刻去查 IAM 身份和密钥的使用情况,而不是继续在桶策略上打转。
理解了这层逻辑,再去设计解决方案时思路就清晰很多:先明确风险在哪里(匿名访问),然后用预防性控制把所有可能产生匿名访问的通道全部关闭,最后用强制执行机制确保这些通道在未来不会被重新打开。
3. 预防性控制的四个层次
3.1 账号级开关:Block Public Access 的全局默认
在我接手过的所有账号里,第一步动作都是同一个:在 AWS 控制台打开 S3 的 Block Public Access 页面,点击“编辑”,把四个复选框全部勾上,然后在弹出确认框时,手动输入 "confirm"。 这一步做完,该账号下所有新建的桶都会默认继承四个开关的全部限制。
这四个开关分别是:BlockPublicAcls(阻止通过 ACL 设置公有访问)、IgnorePublicAcls(忽略已有的公有 ACL)、BlockPublicPolicy(阻止桶策略里出现公有授权)、RestrictPublicBuckets(限制对公有桶的访问方式)。在实际操作中,这四个选项通常应该全部勾选,但有一个例外需要单独辨析,我会在 3.3 节说清楚。
如果你是通过 AWS Organizations 管理多个账号,还可以在管理账号里使用 S3 Block Public Access 的账号级设置 API,通过 SDK 或 CLI 对组织内的所有账号批量设置。这里有一个极其常见的误操作:在子账号手动关闭了 Block Public Access,但 AWS 在关闭时也会要求输入确认文字,很多运维人员看到了“确认”就直接点了,根本没意识到自己是在给“允许公有访问”这一选项颁发许可证。
3.2 服务控制策略:在组织层面禁止“打开”动作
比起逐个账号去设置,在 Organizations 里用 SCP(Service Control Policy) 才是根治方案。SCP 的作用是在账号之上做权限边界,对组织内的所有账号生效。它不会
