介绍
存储桶所有者希望授予一个报表角色访问权限,并保护私有数据。你将附加存储桶策略,与角色自身的策略比较,并测试匹配的 Deny 如何影响访问。
请先完成 使用 IAM 角色的临时凭据 和 为报表读取者授予最小权限。这个全新 VM 提供 default、report-role 和 other-role;角色配置档已能获取临时会话。使用 /home/labex/project 和 AWS View。请保密凭据和缓存。
认证考点
| 认证 | 考点 | 本实验练习 |
|---|---|---|
| Cloud Practitioner (CLF-C02) | 任务 2.3 | 资源策略与显式拒绝的优先规则。 |
| Solutions Architect – Associate (SAA-C03) | 任务 1.1 | 资源策略与显式拒绝的优先规则。 |
| Developer – Associate (DVA-C02) | 任务 2.1 | 资源策略与显式拒绝的优先规则。 |
| CloudOps Engineer – Associate (SOA-C03) | 任务 4.1 | 资源策略与显式拒绝的优先规则。 |
| Security – Specialty (SCS-C03) | 任务 4.2 | 基础练习:资源策略与显式拒绝的优先规则。 |
| Data Engineer – Associate (DEA-C01) | 任务 4.2 | 基础练习:资源策略与显式拒绝的优先规则。 |
| DevOps Engineer – Professional (DOP-C02) | 任务 6.1 | 基础练习:资源策略与显式拒绝的优先规则。 |
| Solutions Architect – Professional (SAP-C02) | 任务 2.3 | 基础练习:资源策略与显式拒绝的优先规则。 |
实验概览

从存储桶授予一个角色访问权限
在本步骤中,你将附加资源策略,授予 ReportReader 对 reports 前缀的访问权限。与身份策略不同,存储桶策略必须指定 Principal。使用标识角色的 IAM 角色 ARN;assumed-role 会话 ARN 则标识该角色的一次使用。
你已经从身份一侧授予访问权限;现在由桶所有者从资源一侧授权。两个角色配置已准备好,因此保持其信任不变,专注于桶策略和角色权限策略如何影响同一请求。
资源策略(resource policy)存储在资源上。S3 存储桶策略(bucket policy)就是一个例子:其中的 Principal 标识语句针对谁的请求。将它与存储在用户或角色上的身份策略比较。
确认两个活动会话身份,以及报表角色最初为空的权限策略列表。
cd /home/labex/project
aws sts get-caller-identity --profile report-role --query Arn --output text
aws sts get-caller-identity --profile other-role --query Arn --output text
aws iam list-role-policies --role-name ReportReader
预期为 assumed-role/ReportReader/report-run、assumed-role/OtherReader/other-run,以及空的 PolicyNames 列表。验证为角色身份本身不授权 S3 访问。测试当前读取:
aws s3api get-object --profile report-role --bucket labex-iam04-reports --key reports/today.txt before.txt || true
预期为 AccessDenied。|| true 防止预期失败中断粘贴序列。连接失败不能证明拒绝。
编写存储桶策略。GetObject 授予对象读取,Resource 将范围限定为这一个桶的 reports/。角色 Principal 排除 OtherReader,不授予公开访问。
cat > bucket-policy.json <<'JSON'
{
"Version":"2012-10-17",
"Statement":[
{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123456789012:role/ReportReader"},"Action":"s3:GetObject","Resource":"arn:aws:s3:::labex-iam04-reports/reports/*"}
]
}
JSON
aws s3api put-bucket-policy \
--bucket labex-iam04-reports \
--policy file://bucket-policy.json
aws s3api get-bucket-policy --bucket labex-iam04-reports --query Policy --output text
存储桶策略现在存储在桶上,而非附加到角色。在同账户内,只要没有相关 Deny 阻止,这个适用的资源 Allow 可以在没有独立角色身份 Allow 的情况下授予角色访问权限。
aws s3api get-object \
--profile report-role \
--bucket labex-iam04-reports \
--key reports/today.txt today.txt
cat today.txt
aws s3api get-object --profile other-role --bucket labex-iam04-reports --key reports/today.txt other-denied.txt || true
aws s3api get-object --profile report-role --bucket labex-iam04-reports --key private/payroll.txt private-denied.txt || true
aws s3api get-object --profile report-role --bucket labex-iam04-reference --key reference.txt reference-denied.txt || true
ReportReader 获得 Daily orders: 145;另外三个请求均获得 AccessDenied。存储桶授权不覆盖其他角色、其他前缀或其他桶。AWS View 发起相同的实际角色读取。
在额外身份 Allow 下保护私有数据
在本步骤中,你将观察角色身份授权如何与存储桶授权组合,再使用桶 Deny 保护私有数据。对于这些同账户请求,适用的 Allow 合并生效;两种策略来源不会自动取交集。任一适用策略来源中的显式 Deny 都优先于 Allow。

临时扩大 ReportReader 的身份读取范围,允许读取这个练习桶中的对象。这个受控比较使用合成数据,不授予其他桶访问权限。
cat > role-read.json <<'JSON'
{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"s3:GetObject","Resource":"arn:aws:s3:::labex-iam04-reports/*"}]}
JSON
aws iam put-role-policy \
--role-name ReportReader \
--policy-name ReadAllOwned \
--policy-document file://role-read.json
aws s3api get-object \
--profile report-role \
--bucket labex-iam04-reports \
--key private/payroll.txt private-before-deny.txt
cat private-before-deny.txt
预期为 Synthetic payroll: restricted。即使桶 Allow 只覆盖 reports/,身份 Allow 仍适用。添加限定于该角色和 private 前缀的桶 Deny,同时保留报表 Allow。
cat > bucket-policy.json <<'JSON'
{
"Version":"2012-10-17",
"Statement":[
{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123456789012:role/ReportReader"},"Action":"s3:GetObject","Resource":"arn:aws:s3:::labex-iam04-reports/reports/*"},
{"Effect":"Deny","Principal":{"AWS":"arn:aws:iam::123456789012:role/ReportReader"},"Action":"s3:GetObject","Resource":"arn:aws:s3:::labex-iam04-reports/private/*"}
]
}
JSON
aws s3api put-bucket-policy \
--bucket labex-iam04-reports \
--policy file://bucket-policy.json
aws s3api get-object --profile report-role --bucket labex-iam04-reports --key private/payroll.txt private-denied.txt || true
aws s3api get-object \
--profile report-role \
--bucket labex-iam04-reports \
--key reports/today.txt today.txt
cat today.txt
尽管有身份 Allow,私有对象现在仍返回 AccessDenied;报表仍返回 145。Deny 指定 ReportReader,因此操作员仍可以查看并保留素材。语句顺序不会使 Allow 覆盖匹配的 Deny。
确认身份 Deny 优先于存储桶 Allow
在本步骤中,你将测试相反方向:角色身份 Deny 优先于桶 Allow。保留当前读取授权,添加针对 reports 前缀写入的 Deny。
cat > role-read.json <<'JSON'
{"Version":"2012-10-17","Statement":[
{"Effect":"Allow","Action":"s3:GetObject","Resource":"arn:aws:s3:::labex-iam04-reports/*"},
{"Effect":"Deny","Action":"s3:PutObject","Resource":"arn:aws:s3:::labex-iam04-reports/reports/*"}
]}
JSON
aws iam put-role-policy \
--role-name ReportReader \
--policy-name ReadAllOwned \
--policy-document file://role-read.json
为受控测试优先级,临时为相同角色和写入前缀添加桶 Allow。先应用身份 Deny,使报表始终受保护。
cat > bucket-write-test.json <<'JSON'
{
"Version":"2012-10-17",
"Statement":[
{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123456789012:role/ReportReader"},"Action":"s3:GetObject","Resource":"arn:aws:s3:::labex-iam04-reports/reports/*"},
{"Effect":"Deny","Principal":{"AWS":"arn:aws:iam::123456789012:role/ReportReader"},"Action":"s3:GetObject","Resource":"arn:aws:s3:::labex-iam04-reports/private/*"},
{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123456789012:role/ReportReader"},"Action":"s3:PutObject","Resource":"arn:aws:s3:::labex-iam04-reports/reports/*"}
]
}
JSON
aws s3api put-bucket-policy \
--bucket labex-iam04-reports \
--policy file://bucket-write-test.json
aws s3api put-object --profile report-role --bucket labex-iam04-reports --key reports/today.txt --body upload.txt || true
即使桶允许,预期 PutObject 仍为 AccessDenied。身份 Deny 优先。立即恢复上一步保存的两语句策略,移除临时写入 Allow。
aws s3api put-bucket-policy \
--bucket labex-iam04-reports \
--policy file://bucket-policy.json
aws s3api get-object \
--profile report-role \
--bucket labex-iam04-reports \
--key reports/today.txt today.txt
cat today.txt
aws s3api get-object --profile other-role --bucket labex-iam04-reports --key reports/today.txt other-denied.txt || true
报表必须仍为 Daily orders: 145,OtherReader 仍被拒绝。临时写入授权已移除。AWS View 在实际读取结果旁显示桶策略和角色身份策略。

移除两种授权来源并清理
在本步骤中,你将在删除练习数据前撤回两种策略来源。如果另一个策略仍授予相同操作,只移除一个 Allow 并不足够。
删除桶策略,再重复报表读取。ReadAllOwned 仍通过角色身份策略授予读取。
aws s3api delete-bucket-policy --bucket labex-iam04-reports
aws s3api get-object \
--profile report-role \
--bucket labex-iam04-reports \
--key reports/today.txt remaining-grant.txt
cat remaining-grant.txt
预期为 Daily orders: 145。现在删除 ReadAllOwned,并在报表仍存在时再次测试。
aws iam delete-role-policy --role-name ReportReader --policy-name ReadAllOwned
aws s3api get-object --profile report-role --bucket labex-iam04-reports --key reports/today.txt revoked.txt || true
aws iam list-role-policies --role-name ReportReader
预期为 AccessDenied 和空策略列表。已准备好的角色及其调用者信任保持完整;你在移除本练习创建的 S3 授权。
aws s3api delete-object --bucket labex-iam04-reports --key reports/today.txt
aws s3api delete-object --bucket labex-iam04-reports --key private/payroll.txt
aws s3api list-objects-v2 --bucket labex-iam04-reports
在这个成功响应中检查 KeyCount: 0,再删除空报表桶并确认参考字节。
aws s3api delete-bucket --bucket labex-iam04-reports
aws s3api list-buckets --query 'Buckets[].Name'
aws s3api get-object --bucket labex-iam04-reference --key reference.txt reference.txt
cat reference.txt
只剩下参考桶,内容为 Platform reference: keep。网络错误不是删除证据。AWS View 现在显示没有桶策略或角色权限策略,以及 Reports bucket removed。一次性环境结束时,已准备好的身份、素材和本地临时缓存会被回收。
总结
你使用 Principal 通过桶策略授予一个角色访问权限,观察身份和资源 Allow 如何组合,并从两个方向测试显式 Deny 的优先级。禁止的写入没有改变报表字节。你在限定范围的清理前撤回了两种授权来源,并保留已准备好的身份和无关数据。请求仍获授权或意外被拒绝时,应检查全部适用策略来源。
进一步阅读 AWS 官方资料:身份策略与资源策略的评估.



