介绍
一个报表读取者需要今天的报表,而其他报表和工资数据应保持私有。你将授予读取权限,缩小范围,测试权限边界,并在清理前撤销权限。
使用你在 AWS 基础课程中学到的调用者身份和 ARN 知识,以及 S3 中的对象下载知识。这个全新 VM 准备了 CLI 和两个身份:default 管理练习;reader 代表作业。在 /home/labex/project 中操作,并在上方的 AWS View 中比较请求。
认证考点
| 认证 | 考点 | 本实验练习 |
|---|---|---|
| Cloud Practitioner (CLF-C02) | 任务 2.3 | IAM 策略、操作与资源范围及最小权限。 |
| Solutions Architect – Associate (SAA-C03) | 任务 1.1 | IAM 策略、操作与资源范围及最小权限。 |
| Developer – Associate (DVA-C02) | 任务 2.1 | IAM 策略、操作与资源范围及最小权限。 |
| CloudOps Engineer – Associate (SOA-C03) | 任务 4.1 | IAM 策略、操作与资源范围及最小权限。 |
| Security – Specialty (SCS-C03) | 任务 4.2 | 基础练习:IAM 策略、操作与资源范围及最小权限。 |
| Data Engineer – Associate (DEA-C01) | 任务 4.2 | 基础练习:IAM 策略、操作与资源范围及最小权限。 |
| DevOps Engineer – Professional (DOP-C02) | 任务 6.1 | 基础练习:IAM 策略、操作与资源范围及最小权限。 |
| Solutions Architect – Professional (SAP-C02) | 任务 2.3 | 基础练习:IAM 策略、操作与资源范围及最小权限。 |
实验概览

授予读取者报表访问权限
在本步骤中,你将编写并附加允许读取报表的身份策略。身份策略(identity policy)附加到用户、组或角色。它描述允许或拒绝的操作,不包含访问密钥。
在 S3 中,你已经下载过对象内容。这里,报表作业需要以自己的受限身份完成同样的下载:操作员修改权限,读取者测试结果。报表数据已提供,你可以专注于授权。
AWS Identity and Access Management(IAM,身份与访问管理)控制哪个身份可以对资源执行操作。最小权限只授予作业所需的权限。
AWS CLI 配置档(profile)选择凭据和设置,不会授予权限。这里的 default 是练习操作员,reader 选择 report-reader。先确认两个身份。--profile reader 为单条命令选择作业身份。get-caller-identity 报告调用者身份,不打印凭据。
cd /home/labex/project
aws sts get-caller-identity --query Arn --output text
默认 ARN 以 user/iam01-operator 结尾。使用这个操作员配置档管理策略,测试作业时使用读取者配置档。本实验操作员已获得管理所需准备。生产报表应用会使用受限角色,你将在后续练习。
aws sts get-caller-identity --profile reader --query Arn --output text
读取者 ARN 以 user/report-reader 结尾。ARN,即 Amazon Resource Name,标识资源。对于 S3 对象,它包含存储桶和完整对象键;单独的桶 ARN 不标识桶内对象。
读取者最初没有策略。授予任何权限前,测试读取:
aws s3api get-object --profile reader --bucket labex-iam01-reports --key reports/today.txt before.txt || true
预期为 AccessDenied,而不是下载报表。|| true 让这条有意失败的命令完成,不中断粘贴的命令序列。阅读错误:连接错误不是 IAM 拒绝的证据。
JSON 策略使用三个重要字段:Effect 为 Allow 或 Deny;Action 指定服务操作;Resource 限定操作可以影响哪个 ARN。s3:GetObject 允许读取对象字节。下面的 * 匹配 reports/ 前缀中的对象键,包括今天和昨天。它不匹配 private/ 或另一个桶。Version 选择策略语言版本,不是报表版本。
下面的 here-document 将 JSON 标记之间的行写入 report-policy.json。> 替换本地文件,带引号的标记防止 Shell 展开内容。
cat > report-policy.json <<'JSON'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::labex-iam01-reports/reports/*"
}
]
}
JSON
只写入文件不会授权读取者。put-user-policy 附加内联策略(inline policy),即直接存储在这个用户上的策略。--policy-name 标识策略;之后使用相同名称会更新它。file:// 告诉 CLI 从本地文件读取文档。
aws iam put-user-policy \
--user-name report-reader \
--policy-name ReportRead \
--policy-document file://report-policy.json
成功更新通常没有输出。现在使用读取者凭据请求报表。最后一个参数是本地目标文件。
aws s3api get-object \
--profile reader \
--bucket labex-iam01-reports \
--key reports/today.txt today.txt
cat today.txt
预期为 Daily orders: 145。ETag 等 S3 响应字段标识下载对象;文件本身包含报表字节。
aws s3api get-object \
--profile reader \
--bucket labex-iam01-reports \
--key reports/yesterday.txt yesterday.txt
昨天报表也能成功下载,因为策略覆盖整个 reports 前缀。业务只需要今天的报表,所以现在你将缩小范围。
将资源范围限定为今天的报表
在本步骤中,你将用一个对象 ARN 替换前缀授权,并证明其他资源仍不可访问。隐式拒绝(implicit deny)表示没有适用策略允许请求。你不需要为每个无关对象分别添加 Deny。

替换本地策略。唯一变化是 Resource:准确对象键 reports/today.txt 替换 reports/*。
cat > report-policy.json <<'JSON'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::labex-iam01-reports/reports/today.txt"
}
]
}
JSON
更新同一个读取者上的相同内联策略。编辑文件不会更新 IAM,直到你发送这条命令。
aws iam put-user-policy \
--user-name report-reader \
--policy-name ReportRead \
--policy-document file://report-policy.json
读回存储的策略。--query PolicyDocument 从响应中选择文档,不改变权限。
aws iam get-user-policy \
--user-name report-reader \
--policy-name ReportRead \
--query PolicyDocument
检查 Resource 以 reports/today.txt 结尾。然后再次测试读取者。
aws s3api get-object \
--profile reader \
--bucket labex-iam01-reports \
--key reports/today.txt today.txt
所需报表仍可下载。下面每个请求都应以 AccessDenied 失败,因为对象 ARN 不匹配授权。
aws s3api get-object --profile reader --bucket labex-iam01-reports --key reports/yesterday.txt yesterday-denied.txt || true
aws s3api get-object --profile reader --bucket labex-iam01-reports --key private/payroll.txt payroll-denied.txt || true
aws s3api get-object --profile reader --bucket labex-iam01-reference --key reference.txt reference-denied.txt || true
这些对象都存在;操作员可以读取它们。NoSuchKey 响应表示对象缺失,而这里的权限错误展示读取者的资源边界。在 AWS View 中,今天的报表为 Readable,其他三个对象为 Denied。这个视图以相同读取者身份发起实际读取请求。

区分显式拒绝与缺少允许
在本步骤中,你将显式保护 private 前缀,并测试操作边界。显式拒绝(explicit deny)是匹配的 Deny 语句。它优先于另一个适用身份策略中的 Allow。语句顺序不会使 Allow 覆盖它。
添加第二条语句,同时保留准确读取授权。s3:* 匹配全部 S3 操作,但这条 Deny 仅限于本桶 private/ 前缀下的对象。它不会拒绝访问今天的报表。
cat > report-policy.json <<'JSON'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::labex-iam01-reports/reports/today.txt"
},
{
"Effect": "Deny",
"Action": "s3:*",
"Resource": "arn:aws:s3:::labex-iam01-reports/private/*"
}
]
}
JSON
aws iam put-user-policy \
--user-name report-reader \
--policy-name ReportRead \
--policy-document file://report-policy.json
Deny 加强私有边界。为了观察优先级,临时为本桶附加第二份读取授权。这是受控测试,结束后立即移除。
cat > temporary-read.json <<'JSON'
{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"s3:GetObject","Resource":"arn:aws:s3:::labex-iam01-reports/*"}]}
JSON
aws iam put-user-policy \
--user-name report-reader \
--policy-name TemporaryRead \
--policy-document file://temporary-read.json
aws s3api get-object --profile reader --bucket labex-iam01-reports --key private/payroll.txt payroll-denied.txt || true
即使 TemporaryRead 允许这个对象键,预期仍为 AccessDenied。匹配的显式 Deny 优先。移除临时授权,恢复最小权限。
aws iam delete-user-policy --user-name report-reader --policy-name TemporaryRead
读取授权不允许写入。upload.txt 是提供的未批准替换文件。put-object 尝试将字节存储到今天的对象键,读取者必须被拒绝。
aws s3api put-object --profile reader --bucket labex-iam01-reports --key reports/today.txt --body upload.txt || true
预期 PutObject 返回 AccessDenied;不要将文件缺失或服务失败当作这个结果。再次读取今天的报表,确认失败写入没有改变它。
aws s3api get-object \
--profile reader \
--bucket labex-iam01-reports \
--key reports/today.txt today.txt
cat today.txt
内容必须仍为 Daily orders: 145。读回最终策略,确认范围有限的 Allow 和 private Deny。
aws iam get-user-policy \
--user-name report-reader \
--policy-name ReportRead \
--query PolicyDocument
撤销访问并清理自己的资源
在本步骤中,你将撤回读取者策略,并只删除本练习的报表存储桶。IAM 策略清理与数据清理不同:删除策略不会删除对象,删除对象不会撤销凭据。
使用默认操作员移除 ReportRead。delete-user-policy 按名称删除内联策略。
aws iam delete-user-policy --user-name report-reader --policy-name ReportRead
aws iam list-user-policies --user-name report-reader
预期 PolicyNames 为空。报表仍存在时,测试读取者是否已失去访问权限。
aws s3api get-object --profile reader --bucket labex-iam01-reports --key reports/today.txt revoked.txt || true
预期为 AccessDenied。现在以操作员身份删除三个准确的练习对象键。参考存储桶属于预先准备的平台素材,必须保持完整。
aws s3api delete-object --bucket labex-iam01-reports --key reports/today.txt
aws s3api delete-object --bucket labex-iam01-reports --key reports/yesterday.txt
aws s3api delete-object --bucket labex-iam01-reports --key private/payroll.txt
aws s3api list-objects-v2 --bucket labex-iam01-reports
检查 KeyCount 为 0,且 Contents 中没有对象。这个成功的已认证响应说明练习桶在删除前为空。
aws s3api delete-bucket --bucket labex-iam01-reports
aws s3api list-buckets --query 'Buckets[].Name'
只剩下 labex-iam01-reference。确认原始字节:
aws s3api get-object --bucket labex-iam01-reference --key reference.txt reference.txt
cat reference.txt
预期为 Platform reference: keep。AWS View 现在显示 No inline policy 和 Reports bucket removed。服务中断会显示不可用,不会被显示为清理成功。实验环境结束时,一次性准备身份会被回收;你已删除学习者创建的权限和练习数据,同时保留无关素材。
总结
你附加并修改了 IAM 身份策略,使用 Action 和 Resource 限制报表作业,比较了隐式与显式拒绝,并证明读取权限不授权写入。你撤销了策略,只删除了自己的数据。检查访问权限时,应同时测试预期成功和禁止操作;单独存储策略不能证明应用获得了正确授权。
进一步阅读 AWS 官方资料:IAM 策略类型与权限语句.



