4. IAM 策略编写实践:最小权限原则与常见模式
聊到 IAM 策略,绕不开一个词 —— 最小权限。说白了,就是给每个用户、角色或服务只分配完成任务所必需的那点权限。多一个 Action 都不给。
听起来简单?我在实际项目里见过太多反面案例了。一开始图方便给了 "Action": "*",后来出事了才追悔莫及。你想想,云上的风险往往就藏在这些“反正以后再说”的策略里。
4.1 最小权限:不只是原则
最小权限不是一句口号,它需要落到每个策略的 Action、Resource、Condition 上。我习惯用三个维度来拆解:
- Action 最小化:只列出业务功能必须的操作,绝不写
"s3:*"或"ec2:*"。 - Resource 最小化:用 ARN 精确到桶、前缀、对象键,比如
arn:aws:s3:::my-bucket/data/*。 - Condition 最小化:附加约束条件,如 IP 限制、MFA 要求、加密状态。
我记得有一次帮一个金融客户做审计,发现他们的数据工程师竟然有 iam:CreateUser 权限。一问才知道,当初复制粘贴了一个管理员的策略模板。嗯,这就是典型的缺乏最小权限意识。
核心检查清单:
- 每个 Action 是否都明确需要?
- Resource 是否只覆盖必要范围?
- 是否有可选的 Condition 可以收紧?
- 是否能用 Deny 排除高风险操作?
4.2 策略编写的基本套路
我写 IAM 策略的流程其实挺固定的。先明确「谁」要「对什么资源」做「哪些操作」,再考虑「在什么条件下允许」。下面这张图能帮你快速理清思路:
4.3 常见模式与反模式
策略写多了,你会发现有些模式反复出现。我整理了下面这张表,方便你对比:
| 模式/反模式 | 说明 | 典型案例 |
|---|---|---|
| 基于角色的策略 | 将权限附加到 IAM 角色,用户通过切换角色获取权限 | 开发者角色只能读写 dev 环境的 S3 |
| 基于资源的策略 | 直接在资源(如 S3 桶)上定义谁可以做什么 | S3 桶策略允许特定账户访问 |
| 条件键限定 | 用 aws:SourceIp、aws:RequestedRegion 等缩小范围 | 只允许公司 VPN IP 调用 API |
| ❌ 超级管理员模式 | 直接给用户 AdministratorAccess 托管策略 | 新员工入职就给 admin,后来误删关键资源 |
| ❌ 通配符滥用 | "Action": "s3:*" 或 "Resource": "*" | 本应只读的脚本获得了删除权限 |
我曾经在一个生产环境里发现某应用使用的服务角色策略写的是 "Action": "ec2:*"。调查后才明白,当初为了“调试方便”临时加上的,交付时忘记改回去了。结果这台实例被入侵后,攻击者能创建任意 EC2 实例并外泄数据。教训很惨痛。
4.4 实战:从宽策略到细粒度
看一个真实的例子。假设需要给一个数据分析师权限,让他可以读取 S3 中某个特定前缀下的 CSV 文件。
第一阶段:新手常犯的宽策略
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "*"
}
]
}
这个策略的问题显而易见:他可以读你账户下任意桶的任意对象。假如桶里还有配置文件或凭据,风险极大。
第二阶段:加上桶限定
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::data-analytics-prod/*"
}
现在他只能读取 data-analytics-prod 这个桶了。但桶里可能有非 CSV 的敏感文件。
第三阶段:增加路径前缀和 Condition
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::data-analytics-prod/team-a/reports/*.csv",
"Condition": {
"Bool": {
"aws:SecureTransport": "true"
}
}
}
这样只允许通过 HTTPS 读取指定前缀下的 CSV 文件。细粒度到位了。
4.5 避坑指南
- 不要依赖 Deny 来兜底:Deny 优先级高,但它不是万能的。更好的方式是让 Allow 本身就足够精准。
- 注意显式 Deny 与隐式 Deny 的区别:没允许的操作默认就是拒绝(隐式 Deny)。显式 Deny 通常用于紧急封锁,使用时要写清楚原因。
- 策略模拟器是好帮手:写完策略后,先用 IAM Policy Simulator 测试一遍,看看实际效果是否满足要求。我每次写新策略都会跑一遍,省得上线后出 bug。
- 定期审计:用 Access Analyzer 或 CloudTrail 分析实际被调用的权限,清理那些“僵尸权限”。
我个人习惯在策略里加上 "Sid": "AllowReadOnlyReports" 这样的描述。半年后回来维护时,一眼就能看出这段策略的意图。别小看这个 Sid,它能省很多沟通成本。
最小权限不是一次性能搞定的。业务在变,角色在变,权限也得跟着迭代。养成“写完策略先问自己三个为什么”的习惯:这个 Action 真的必要吗?Resource 能再缩吗?Condition 能用上吗?久而久之,你写的策略会越来越干净。