本文由『云枢国际/TG @yunshuguoji-亚马逊云代理商 撰写』如需转载请注明!
作者:云枢国际/yunshuguoji
在多账号 AWS 架构中,跨账号访问 Amazon S3 是极常见的基础配置。许多工程师经常遇到类似场景:在账号 A(资源方)的 S3 存储桶策略(Bucket Policy)中明确为账号 B(访问方)授予了读写权限,但在账号 B 的 EC2、Lambda 或本地终端发起请求时,控制台或 AWS CLI 依然返回 403 Access Denied(Forbidden)。
遇到此类 AWS S3 跨账号访问 403 问题,排查往往不能仅停留在“策略语法是否写对”,而需要全面审视 AWS IAM 鉴权流水线中的多层控制机制——尤其是极易被忽视的 S3 阻止公共访问(Block Public Access, BPA)以及加密密钥(KMS)权限。
一、 S3 跨账号授权的评估逻辑
在单账号内部,S3 的访问评估只需“IAM 身份策略”或“Bucket 资源策略”其中一方显式允许,且无显式拒绝(Explicit Deny)即可通过。
但在跨账号访问(Cross-Account Access)场景下,权限判定逻辑完全不同:
- 双向显式放行:必须同时满足“访问方 IAM 身份策略允许访问目标 S3 ARN”与“资源方 Bucket Policy 允许该 IAM 身份操作”。
- 零显式拒绝:链路上任何一级出现 Deny 都会直接拦截。
- 防护边界判定:SCP(服务控制策略)、VPC 端点策略(VPC Endpoint Policy)、会话策略(Session Policy)均具备一票否决权。
- BPA 与公共性判定:若策略存在被识别为“Public”的风险,BPA 会在 Bucket Policy 生效前强行拦截。
二、 破案重点:阻止公共访问(BPA)与跨账号策略的冲突
许多团队在排查 403 时,反复确认了账号 B 的 IAM 策略和存储桶策略,却遗漏了 S3 存储桶层级或账号层级的 Block Public Access (BPA) 配置。
BPA 提供四个细分配置项:
- BlockPublicAcls:阻止新的公共 ACL。
- IgnorePublicAcls:忽略所有现存公共 ACL。
- BlockPublicPolicy:拒绝可能导致存储桶变为公开的 Bucket Policy。
- RestrictPublicBuckets:限制对包含公共策略的存储桶的跨账号访问。
为什么跨账号策略会触发 BPA 拦截?
很多工程师在编写 Bucket Policy 时,为了方便调试,采用了如下常见的宽泛授权格式:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CrossAccountAccess",
"Effect": "Allow",
"Principal": "*",
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": "arn:aws:s3:::target-bucket/*",
"Condition": {
"StringEquals": {
"aws:PrincipalAccount": "222222222222"
}
}
}
]
}
在上述策略中,虽然利用 Condition 限制了仅允许账号 222222222222,但 Principal 字段使用了通配符 *。AWS S3 的评估机制在判定策略是否属于公共访问时,会对这类包含通配符的策略执行严格审查。若此时开启了 RestrictPublicBuckets,S3 可能会将该存储桶判定为具备公共风险,进而直接阻断所有跨账号请求,仅允许桶所属账号内的 IAM 身份及 AWS 托管服务访问。
规范修复方案
对于跨账号授权,必须将外部主体明确绑定到具体的账号根 ARN、IAM Role 或 IAM User,避免使用 Principal: "*":
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "StrictCrossAccountAccess",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::222222222222:root"
},
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::target-bucket",
"arn:aws:s3:::target-bucket/*"
]
}
]
}
如果外部访问通过特定 Role 执行,更推荐直接收敛至角色 ARN,从而在保障 BPA 全开的前提下安全完成跨账号访问。
三、 S3 跨账号 403 全链路排查矩阵
在实际排障中,导致 403 Access Denied 的根因往往分布在不同控制层面。下表梳理了典型故障点及排查定位方法:
| 检查层级 | 典型故障现象 | 根因说明 | 解决与核验建议 |
|---|---|---|---|
| 访问方 IAM | aws s3 ls 或 GetObject 报 403 | 账号 B 内的调用凭据没有附加 S3 基础操作权限。 | 检查执行角色/用户的 IAM Policy,确保包含相应 S3 Action 与目标 ARN。 |
| 资源方 BPA | 修改策略保存报错,或外部账号读取被阻断 | 桶开启了 RestrictPublicBuckets,策略中使用 Principal: * 触发了公共性阻断。 | 策略中指定具体 arn:aws:iam:: |
| 资源所有权 | 账号 B 上传成功,但账号 A 无法读取该对象(403) | 历史对象所有权模式下,写入的对象属于账号 B,账号 A 默认无读取权。 | 将 S3 对象所有权设为 Bucket Owner Enforced,禁用 ACL 并统一归属。 |
| SSE-KMS 加密 | S3 权限完全正确,读取或写入时仍报 403 | 存储桶使用了自定义 KMS 密钥(KMS CMK),但账号 B 无该密钥调用权。 | 在 KMS Key Policy 中增加账号 B 的 kms:Decrypt/kms:GenerateDataKey 授权。 |
| 组织边界策略 | 单独看 IAM 和 Bucket 均正常,实际调用被 Deny | AWS Organizations 的 SCP 或 VPC Endpoint 策略限制了跨账号调用。 | 检查上层组织根节点 SCP,排查是否存在限制 S3 资源归属账号的 Deny 规则。 |
四、 另外两个极易被忽略的 403 触发点
- SSE-KMS 密钥策略双向授权缺失
若存储桶启用了服务端加密并采用 AWS KMS 客户托管密钥(SSE-KMS),S3 的数据读取与写入操作必然联动调用 KMS 接口:
- s3:GetObject 依赖密钥的 kms:Decrypt。
- s3:PutObject 依赖密钥的 kms:GenerateDataKey。
默认情况下,KMS 密钥策略(Key Policy)仅授权本账号。要实现跨账号访问,不仅 S3 桶策略要放行,KMS Key Policy 也必须显式允许账号 B 的根主体或对应 IAM 角色。同时,账号 B 的 IAM 策略中同样需要补充调用该 KMS Key ARN 的权限。
- 对象所有权与 ACL 遗留问题
早期的 S3 架构中,跨账号写入的对象其所有者(Object Owner)属于上传方的 AWS 账号,而非桶拥有者。这会导致账号 A 自身无法读取外部上传的文件。虽然自 2023 年起 AWS 已将新存储桶默认设置为 Bucket Owner Enforced,但在维护长期存量存储桶时,需确认是否已开启此设置以彻底停用 ACL,确保所有写入对象的归属权统一收敛给存储桶拥有者。
五、 推荐的跨账号授权实施闭环
按照标准实践,一次严谨的跨账号授权应按以下步骤闭环部署:
- 设置存储桶对象所有权:在账号 A 存储桶控制台中,将“对象所有权”配置为 Bucket Owner Enforced。
- 规范编写 Bucket Policy:显式声明账号 B 的 ARN,精确划分桶级资源与对象级资源。
- 保持 BPA 开启:在策略显式指定明确 IAM ARN 的前提下,存储桶层级和账号层级的 4 项 BPA 均可维持开启状态。
- 配置 KMS 跨账号权限(如启用 SSE-KMS):在密钥策略中增加账号 B 授权,并在账号 B IAM 策略中补充对应 KMS 行为。
- 在账号 B 赋予 IAM 动作:在访问方的 IAM 角色或策略中添加匹配的 S3 和 KMS 权限。
- 验证日志:若配置后仍遇报错,检查访问方 CloudTrail 记录,查看 errorCode 为 AccessDenied 时的详细上下文。
常见问题(FAQ)
AWS S3 跨账号访问报 403 Access Denied 时,完整的排查顺序是怎样的?
排查应依次遵循四层检查:
1. 访问方 IAM 身份策略:确认调用凭证所在的角色或用户是否具备 s3:GetObject、s3:PutObject 或 s3:ListBucket 等必要权限;
2. 资源方存储桶策略(Bucket Policy):确认策略的 Principal 是否准确包含访问方的 IAM ARN 或外部账号 Root ARN,且 Resource 是否正确区分了桶本身与对象路径(即是否漏写了 /*);
3. 阻止公共访问(BPA)与组织边界:检查存储桶和账号层级 BPA 是否因通配符策略触发了限制,同时核查 SCP 及 VPC Endpoint Policy 是否存在阻断;
4. KMS 加密与对象所有权:若使用了 SSE-KMS 加密,需确认 KMS Key Policy 是否双向放行;若为存量桶,确认是否开启了 Bucket Owner Enforced。
配置了 S3 Bucket Policy 后,为什么启用“阻止公共访问(BPA)”会导致跨账号受阻?
当 Bucket Policy 中使用了含通配符的 Principal(如 "Principal": "*")并结合 Condition 限制外部账号时,S3 的策略评估模块在特定场景下仍可能将该规则判定为具备公共暴露风险。一旦存储桶或账号开启了 RestrictPublicBuckets(限制公共存储桶),S3 会主动屏蔽所有来自外部账号的访问请求,仅保留存储桶拥有者本账号及内部特定服务的调用权限。将 Principal 显式修改为具体的外部账号 ARN 即可恢复正常访问。
跨账号访问 S3 桶,除了 Bucket Policy 和 BPA,还有哪些隐蔽的 403 触发点?
常见隐蔽原因包括:
1. KMS 权限缺失:目标桶启用了自定义 KMS 密钥加密,访问方仅配置了 S3 权限,未配置 KMS 的 kms:Decrypt 或 kms:GenerateDataKey,导致加密解密环节返回 403;
2. 对象所有权冲突:未开启 Bucket Owner Enforced 的存量桶中,外部账号写入对象时未附加 bucket-owner-full-control ACL,导致桶所有者账号无权读取;
3. VPC Endpoint 限制:访问方流量若经过 VPC 端点,端点策略(Endpoint Policy)未放行对跨账号 S3 资源的访问。