为报表读取者授予最小权限

AWSBeginner
立即练习

介绍

一个报表读取者需要今天的报表,而其他报表和工资数据应保持私有。你将授予读取权限,缩小范围,测试权限边界,并在清理前撤销权限。

使用你在 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 策略、操作与资源范围及最小权限。

实验概览

概念图:IAM 身份策略只允许报表读取者读取 S3 中今天的报表,同时保护其他报表和工资数据。

授予读取者报表访问权限

在本步骤中,你将编写并附加允许读取报表的身份策略。身份策略(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。这个视图以相同读取者身份发起实际读取请求。

读取者范围限定为一份报表. 示例:只有今天的报表可读;其他已有对象被拒绝。左侧文档是存储的 IAM 策略。

区分显式拒绝与缺少允许

在本步骤中,你将显式保护 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 策略类型与权限语句.