1. AWS IAM 与 S3 概述

这一章咱们先把地基打好。IAM 和 S3 是 AWS 里最常用的两个服务,一个管「谁能做什么」,一个管「数据放哪儿」。很多初学者把权限配置搞混,往往是因为没理清这两者的关系。我刚开始接触 AWS 的时候,就被桶策略和 IAM 策略绕晕过——明明都写了 Allow,为什么访问还是被拒绝?嗯,踩过坑之后才明白,这两套权限体系是互相独立又必须配合的。

1.1 IAM 基本概念

IAM(Identity and Access Management)说白了就是 AWS 的「用户中心」加「权限管家」。它不负责存储数据,只负责回答三个问题:你是谁?你能访问哪些资源?你能对资源做什么操作?

核心组件就这几个:

  • 用户(User):代表一个人或一个应用程序。每个用户有固定的凭证(密码或访问密钥)。
  • 用户组(Group):把相同权限的用户归到一起,方便统一管理。比如把开发人员都加进 "Developers" 组,然后给这个组绑定策略。
  • 角色(Role):一种临时身份,可以分配给用户、AWS 服务或外部身份。角色没有长期凭证,用的是临时安全令牌(STS)。
  • 策略(Policy):定义权限的规则文档。策略用 JSON 格式写,核心字段是 Effect(Allow/Deny)、Action(允许或拒绝的操作)、Resource(操作对象)。

讲一个我项目里的例子。有一回我帮客户配置跨账号访问 S3,客户要求在账号 A 里用角色,账号 B 里放数据。当时我写完信任策略和权限策略,结果一直报 AccessDenied。排查了半天,发现是角色信任策略里 Principal 写成了用户 ARN 而不是账号 ID——这种细节特别容易漏。

小技巧:IAM 策略遵循「显式 Deny 优先于 Allow」的规则。如果你同时写了 Allow 和 Deny,Deny 永远生效。所以遇到权限问题时,先查有没有 Deny。

1.2 S3 存储模型

S3(Simple Storage Service)是 AWS 的对象存储服务。我经常把它比喻成一个「无限大的硬盘」,不过存取用的是 HTTP API 而不是文件系统路径。

几个关键概念:

  • 桶(Bucket):存储容器,名称全局唯一。每个桶属于一个 AWS 区域,但桶名在所有区域、所有账号里不能重复。你想想看,这设计是为了让 S3 的 URL 变成 https://bucket-name.s3.region.amazonaws.com/key 这种统一格式。
  • 对象(Object):文件 + 元数据。每个对象由键(Key)标识,相当于路径。
  • 区域(Region):桶和对象的物理位置。跨区域访问会产生延迟和传输费用。
  • ARN(Amazon Resource Name):资源的唯一标识。比如 arn:aws:s3:::my-bucket/* 表示 my-bucket 里的所有对象。

我个人的习惯是:生产环境的桶一定开启「阻止公共访问」的默认设置,然后通过 IAM 策略或桶策略精确控制访问。除非明确需要公开静态网站内容,否则绝不打开「公有读取」。

注意:S3 的「对象 ACL」和「桶策略」都能控制访问,但它们的作用范围不同。ACL 是访旧式权限机制,粒度不如策略细。AWS 官方现在推荐使用策略(桶策略 + IAM 策略)代替 ACL。

1.3 两者权限体系的关系

IAM 和 S3 的权限体系是「双轨制」:一套基于身份,一套基于资源。

  • 基于身份的策略(Identity-based Policy):附加给 IAM 用户、组或角色。它们指定「这个身份可以干什么」。比如“允许 Bob 列出所有桶”。
  • 基于资源的策略(Resource-based Policy):附加给 S3 桶或对象。它们指定「这个资源允许谁访问」。比如“允许账号 123456789012 中的特定角色读取本桶”。

访问最终能否成功,取决于两者策略的交集。说白了,就像过两道门:IAM 策略是第一道门,桶策略是第二道门。两道门都必须放行,你才能进去。如果有任何一道门明确拒绝(Deny),你就进不去。

我曾经在排查一个跨账号访问问题时,发现 IAM 角色策略里写了对 S3 的 s3:GetObject 允许,桶策略里也写了允许那个角色 ARN 访问,但依然被拒。后来发现:桶策略里忘记加上 s3:ListBucket 权限。你想想看,没有 ListBucket 权限,客户端连桶里的文件列表都看不到,GetObject 自然也没法用。这就是一个典型的「权限组合漏洞」。

下面这张图能帮你直观理解 IAM 和 S3 权限体系的关系:

IAM 与 S3 权限体系关系 IAM(基于身份) 用户 / 组 / 角色 附加身份策略 身份策略示例: Allow s3:GetObject on arn:aws:s3:::my-bucket/* Deny 优先 显式 Deny 阻止所有 Allow S3(基于资源) 桶 / 对象 桶策略 / 对象 ACL 桶策略示例: Allow s3:GetObject for arn:aws:iam::123456789012:role/CrossAccountRole 资源策略也支持 Deny 与 IAM 策略共同评估 结果:必须同时满足 IAM 策略 Allow 和 S3 桶策略 Allow,且没有 Deny,访问才被允许

再来看一个对比表格,帮你快速区分两种策略:

维度基于身份策略(IAM)基于资源策略(S3 桶策略)
附加对象IAM 用户、组、角色S3 桶(直接贴在桶上)
控制粒度精细到操作和资源 ARN精细到操作、主体(Principal)和条件
跨账号支持通过角色(AssumeRole)实现直接在策略中指定其他账号的 Principal
默认效果隐式 Deny(未显式 Allow 则拒绝)隐式 Deny(但桶策略可以显式 Allow 公共访问)
常见使用场景管理内部员工或服务的权限开放公共读取、跨账号共享数据

核心记忆点:IAM 策略管「谁」,S3 桶策略管「谁可以访问这个桶」。两者共同决定最终权限。如果 IAM 策略里写了 Deny,桶策略里写了 Allow,结果还是 Deny——因为 Deny 优先级最高。

实际配置时,我强烈建议你遵循最小权限原则:先不给任何权限,然后根据业务需求逐步添加。我见过很多开发者图省事,直接写了一个 s3:* 的 Allow,结果有一天不小心把数据删了才追悔莫及。所以,别偷懒。