策略元素详解:Effect、Action、Resource、Condition
好,咱们直接切入正题。写IAM策略,说白了就是在写四个东西:Effect、Action、Resource、Condition。这四个元素组合起来,就决定了谁能在什么条件下对哪些资源干什么事。
我个人习惯,每次写策略前都会把这四个要素在脑子里过一遍。为什么?因为我在项目中遇到过,一个初级的工程师仅仅把Resource写错了,就导致整个业务崩溃了一个下午。所以,别小看这四个单词。
Effect:Allow 还是 Deny?
Effect是最简单的,也是最容易被忽略的。它只有两个值:Allow 和 Deny。你可能会觉得,“这有什么好讲的?”但这里有个坑——Deny优先原则。
核心原则:AWS 的策略引擎在处理时,先评估所有匹配的Deny策略。只要有一条Deny命中,直接拒绝,不再看其他Allow。
我记得有一次,一个团队的S3存储桶总是无法访问,主账号明明给了所有权限。查了半天,发现另一个账号下的服务控制策略(SCP)里写了Deny。这就是Deny优先的威力。
我的一点建议:除非你有明确的“开黑名单”需求,否则尽量只用Allow。Deny用得越多,出问题的风险越大,排查起来也越痛苦。
Action:你到底想干什么?
Action指定了具体的操作。格式是服务前缀:操作名称。比如 s3:GetObject、ec2:RunInstances。
这里有一个常见误区:很多人喜欢用通配符 *,图省事。但我建议你,永远用最细的Action粒度。你想想看,给一个IAM用户s3:*的权限,那他就能删除所有桶。这真的安全吗?
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-bucket/*"
}
上面这个例子,只允许读和写对象,不能删除、不能列出桶。这就是细粒度控制。
| Action 写法 | 含义 | 风险等级 |
|---|---|---|
s3:GetObject |
只允许读取对象 | 低 |
s3:* |
允许所有S3操作 | 高 |
ec2:RunInstances |
只允许启动实例 | 中 |
Resource:你操作的资源是谁?
Resource就是你要操作的对象。它的格式是一个ARN(亚马逊资源名称)。ARN的结构是:arn:partition:service:region:account-id:resource。
嗯,这里要注意:Resource的写法直接影响权限生效范围。我见过有人写"Resource": "*",结果这个IAM用户能访问所有资源。这在开发环境可能没事,但生产环境是个大坑。
曾经有一次:我在审计一个客户的配置文件时,发现他的IAM角色竟然对所有EC2实例都有权限。排查后发现,他把Resource写成了arn:aws:ec2:*:*:*,而不是指定的实例ID。后来我帮他把策略改成了arn:aws:ec2:us-east-1:123456789012:instance/*,并加上了条件限制。
一句话总结:Resource一定要精确,能用具体的ARN就用具体的,别偷懒用*。尤其是跨账户场景,Resource写错了,你连权限边界都找不到。
Condition:在什么条件下?
Condition是策略里最灵活、最强大的部分。它让你能添加额外的限制,比如指定的IP地址、特定的Tag、或者必须是MFA登录。
为什么说它强大?因为Condition可以让你在不改变Action和Resource的前提下,动态地细粒度控制权限。比如,你允许用户访问S3桶,但要求只有来自公司VPN的请求才有效:
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::company-docs/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "203.0.113.0/24"
}
}
}
这个条件键 aws:SourceIp 的写法很讲究。条件运算符(Condition Operator)决定了判断逻辑,比如 IpAddress 是检查IP是否在给定的CIDR范围内。
我个人的习惯是,Condition能加就加。条件越多,策略越安全。你想想看,只用Action和Resource,最多只能做到“谁对什么资源有什么操作”;加上Condition,就能做到“谁在什么时间、从什么地点、用什么方式对什么资源有什么操作”。
实战建议:刚开始可能觉得Condition复杂,但从最简单的aws:SourceIp和aws:RequestedRegion开始。比如,你可以限制用户只能在某个区域创建资源:
"Condition": {
"StringEquals": {
"aws:RequestedRegion": "us-east-1"
}
}
四大元素如何协作?
Effect、Action、Resource、Condition这四个元素不是孤立的。一个策略的最终效果,是它们的组合结果。来看一张我画的流程图,帮助你理解判断逻辑:
看到没?先匹配Action、Resource和Condition,再判断Effect。记住:Deny优先于Allow。一定要牢记这个顺序,不然你的策略逻辑会全是漏洞。
避坑总结
讲了这么多,我总结几个最常见的坑:
- Resource写得太宽: 别偷懒写
*,除非你真的需要所有资源。否则,后果可能是数据泄露。 - 忽略Condition的默认值: 如果没写Condition,策略引擎就认为“无条件”。这在某些场景下非常非常危险。
- Action用通配符: 能用
s3:GetObject就别用s3:*。细粒度Action设计,是云安全的第一道防线。 - Effect随意使用Deny: 除非有明确的拒绝清单,否则尽量只用Allow。Deny会覆盖其他策略,排查起来很麻烦。
我的血泪教训: 曾经有两个策略作用于同一个IAM用户,一个Allow所有EC2操作,另一个Deny了某个特定实例。因为Deny优先,那个实例死活无法启动。排查了一整天才发现是Deny策略没更新。
好了,Effect、Action、Resource、Condition这四个元素,是IAM策略的核心骨架。理解它们,就是理解了云上的权限管理逻辑。写策略时,把它们当成一个四元组,一个一个核对,基本上不会出大问题。