通过 IAM 身份策略限制 S3 访问身份与访问途径
本文介绍了在清空 S3 存储桶策略的前提下,仅通过 IAM 身份策略限制不同用户访问 Amazon S3 的方法。文章分别说明管理员和普通用户通过控制台访问的权限配置,以及 API 用户经由指定 S3 Interface Endpoint 进行内网访问的策略设计,并结合公网、内网和无授权场景验证显式拒绝、隐式拒绝与正常授权结果,帮助读者理解 IAM 条件键、资源 ARN 和策略评估逻辑的实际应用。
一、背景
本文在完全清空 S3 Bucket Policy(存储桶策略)的前提下,仅使用 IAM 身份策略实现访问需求:
- 允许 A 用户(登录 AWS 控制台的管理员)通过 AWS Console 浏览、上传和下载对象。
- 允许 B 用户(登录 AWS 控制台的普通用户)通过 AWS Console 浏览、上传和下载对象。
- 针对 C 用户使用 Access Key/Secret Key 发起的 API 访问,仅允许来自指定 VPC Endpoint 的请求。
- 拒绝未获得 IAM 授权的访问者和其他访问途径。
下面进入具体的策略设计。
二、IAM Policy 设计
1、整理变量用于拼接规则
账号信息:
- AWS Account ID:
<aws-account-id> - 区域:
ap-northeast-1 - 有权限访问的存储桶名称:
<allowed-bucket-name> - 无权限访问的存储桶名称:
<denied-bucket-name>
网络信息:
- S3 Interface Endpoint ID:
<vpce-id> - S3 Interface Endpoint 的 Bucket API 访问地址:
https://bucket.<vpce-id>-<endpoint-dns-suffix>.s3.ap-northeast-1.vpce.amazonaws.com
用户信息:
- A 用户(登录 AWS 控制台的管理员)对应的 IAM Role ARN(可以是联邦认证 Assumed Role):
arn:aws:iam::<aws-account-id>:role/<admin-role-name>,此角色通常已附加AdministratorAccess管理员权限 - B 用户(登录 AWS 控制台的普通用户)对应的 IAM Role ARN(可以是联邦认证 Assumed Role):
arn:aws:iam::<aws-account-id>:role/<user-role-name> - C 用户(通过 API 和 Access Key/Secret Key 访问 S3 的用户)对应的 IAM User ARN:
arn:aws:iam::<aws-account-id>:user/<api-user-name>
2、Console 控制台访问 A 用户管理员权限的 IAM Policy
考虑到是 S3 管理员权限,可直接加挂 AmazonS3FullAccess 策略。
3、Console 控制台访问 B 用户的 IAM Policy 编写
策略如下:(自行修改其中的存储桶名称)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowBucketListForConsoleNavigation",
"Effect": "Allow",
"Action": "s3:ListAllMyBuckets",
"Resource": "*"
},
{
"Sid": "AllowFullAccessToTargetBucket",
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::<allowed-bucket-name>",
"arn:aws:s3:::<allowed-bucket-name>/*"
]
}
]
}
说明:
- 第一条语句用于支撑 S3 控制台首页的存储桶列表。
ListBuckets操作返回账号内全部存储桶,其 IAM 授权只能通过s3:ListAllMyBuckets且资源必须写为*,无法按单个存储桶收敛。如果不希望 B 用户看到账号内其他存储桶的名称,可以删除该语句,此时登陆到控制台后,S3 存储桶列表会显示权限错误。不过用户依然可以通过如下连接格式直接跳转进入自己有权限的存储桶:https://s3.console.aws.amazon.com/s3/buckets/?region= &bucketType=general&tab=objects ,进入目标存储桶后的浏览、上传、下载功能均正常。所以从操作方便来说,一般建议给 ListBuckets操作,方便页面交互。 - 第二条语句中的
s3:*已经覆盖s3:GetBucketLocation、s3:ListBucket、s3:PutObject、s3:GetObject与s3:GetBucketPolicy,不需要单独列出。
4、通过 S3 Interface Endpoint 内网访问的 C 用户的 IAM Policy 编写
C 用户是 IAM 用户 <api-user-name>,要求其请求仅允许来自 <vpce-id>。aws:SourceVpce 是全局条件键,在身份策略中同样可用。策略如下:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowTargetBucketAccessFromDesignatedVpce",
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::<allowed-bucket-name>",
"arn:aws:s3:::<allowed-bucket-name>/*"
],
"Condition": {
"StringEquals": {
"aws:SourceVpce": "<vpce-id>"
}
}
},
{
"Sid": "DenyAllS3AccessOutsideDesignatedVpce",
"Effect": "Deny",
"Action": "s3:*",
"Resource": "*",
"Condition": {
"StringNotEquals": {
"aws:SourceVpce": "<vpce-id>"
}
}
}
]
}
下面进入测试流程。
三、测试流程
1、主要测试流程
| 测试路径 | 测试操作 | 预期结果 |
|---|---|---|
A 用户(<admin-role-name> 角色)访问 AWS 控制台 |
浏览 Bucket、上传测试对象、下载测试对象 | 成功 |
B 用户(<user-role-name> 角色)通过 AWS 控制台访问自己的 Bucket |
浏览 Bucket、上传测试对象、下载测试对象 | 成功 |
B 用户(<user-role-name> 角色)通过 AWS 控制台访问别人的 Bucket |
浏览 Bucket、上传测试对象、下载测试对象 | 失败,报错 Insufficient permissions to list objects |
| C 用户通过公网 S3 Endpoint 访问自己的存储桶 | ListObjectsV2、PutObject、GetObject |
AccessDenied,且报错 with an explicit deny in an identity-based policy |
| C 用户通过内网 S3 Interface Endpoint 访问自己的存储桶 | ListObjectsV2、PutObject、GetObject |
成功 |
| C 用户通过内网 S3 Interface Endpoint 访问别人的存储桶 | ListObjectsV2、PutObject、GetObject |
AccessDenied,且报错 because no identity-based policy allows |
| 无 S3 授权的其他 IAM Principal | 通过公网和指定 Endpoint 分别访问 | AccessDenied,且报错 because no identity-based policy allows |
在使用 API(即 Access Key/Secret Key)进行访问测试时,可以看到,被拒绝的测试场景会出现不同的报错。这是因为:
- 报错
with an explicit deny in an identity-based policy:IAM User Policy 中明确禁止通过非指定 VPC Endpoint 访问。这是一条显式禁止,因此会收到该报错。 - 报错
because no identity-based policy allows:这是因为 IAM User Policy 中没有显式允许访问某存储桶。
下面展开测试。
2、管理员用户 A 以 Federated Login 方式登录(Assume 为角色)
登录控制台后进入目标存储桶,执行浏览、上传与下载操作。
3、普通用户 B 以 Federated Login 方式登录(Assume 为角色)
切换到 <user-role-name> 角色后进入自己有权限的目标存储桶,执行浏览、上传与下载操作,测试成功,符合预期。
切换到 <user-role-name> 角色后点击自己无权限的其他存储桶,页面报错并提示 Insufficient permissions to list objects,符合预期。
如果在第二章第 2 小节中删除了 AllowBucketListForConsoleNavigation 语句,则控制台首页的存储桶列表会提示权限不足;如果直接给出存储桶路径,则可直接跳转进入。
4、应用程序 C 配置 Access Key/Secret Key 后从代码访问(AK/SK 隶属于该 IAM 用户)
配置好 Access Key/Secret Key 后,开始访问。
(1) 从公网调用测试
aws s3 ls <allowed-bucket-name>
收到显式拒绝的错误。
aws: [ERROR]: An error occurred (AccessDenied) when calling the ListObjectsV2 operation:
User: arn:aws:iam::<aws-account-id>:user/<api-user-name> is not authorized to perform: s3:ListBucket on resource: "arn:aws:s3:::<allowed-bucket-name>"
with an explicit deny in an identity-based policy
(2) 从内网调用,包括跨云内网调用(S3 Interface Endpoint 会解析为内网 IP)
注意:此 Endpoint 默认解析为内网 IP,可使用 dig 命令确认解析正确。
dig +short bucket.<vpce-id>-<endpoint-dns-suffix>.s3.ap-northeast-1.vpce.amazonaws.com
从能够访问该 Interface Endpoint 的 VPC 内,或者通过 Direct Connect 专线跨云网络执行如下命令:
访问自己有权限的存储桶:
aws s3 ls <allowed-bucket-name> \
--endpoint-url https://bucket.<vpce-id>-<endpoint-dns-suffix>.s3.ap-northeast-1.vpce.amazonaws.com
预期正常获取存储桶内容,返回结果的形式如下:
2026-08-12 10:07:03 196128 1501022255a86dca6838ee9850.jpg
2026-08-12 09:34:49 28 testfile.txt
访问自己无权限的其他存储桶:
aws s3 ls <denied-bucket-name> \
--endpoint-url https://bucket.<vpce-id>-<endpoint-dns-suffix>.s3.ap-northeast-1.vpce.amazonaws.com
访问被拒绝。将收到报错 because no identity-based policy allows the s3:ListBucket action。
5、无授权的测试
使用账号内一个未附加任何 S3 权限的角色或用户,分别从公网和指定 Endpoint 访问目标存储桶,预期均返回 AccessDenied。此时的报错为 is not authorized to perform。
四、参考文档
Amazon S3 与 IAM 的集成说明,包括身份策略与存储桶策略的授权判定关系、S3 各操作所需的权限。
https://docs.aws.amazon.com/AmazonS3/latest/userguide/security_iam_service-with-iam.html
AWS IAM 策略评估逻辑,包括显式拒绝优先、隐式拒绝与同账号资源策略的合并规则。
https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html
AWS IAM aws:SourceVpce 全局条件键参考,包括该键仅在请求经由 VPC Endpoint 时才进入请求上下文的说明,以及 FAS 场景下的注意事项。
AWS IAM 策略类型与 root 用户的适用范围说明,包括身份策略无法附加到 root 用户、resource-based policy 与 SCP 对 root 用户的作用范围。
https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html
Amazon S3 ListBuckets API 参考,包括必须授予 s3:ListAllMyBuckets 的说明。
https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html
AWS 官方文档:通过 AWS PrivateLink 使用 Amazon S3 Interface Endpoint,包括端点 DNS 格式、Private DNS、AWS CLI 和 SDK 访问示例。
https://docs.aws.amazon.com/AmazonS3/latest/userguide/privatelink-interface-endpoints.html
AWS Organizations 成员账号最佳实践,包括使用 SCP 约束成员账号 root 用户的示例策略。
https://docs.aws.amazon.com/organizations/latest/userguide/orgs_best-practices_member-acct.html
最后修改于 2026-08-12