IAM 策略语法:核心六大元素拆解
说白了,IAM 策略就是一段 JSON,告诉 AWS “谁(Principal)在什么条件下(Condition)可以对什么资源(Resource)做什么操作(Action)”。我刚开始接触时,总觉得这东西很绕,后来拆成六个字段就清晰了。来,一个个过。
Version:版本声明
Version 指定策略使用的语法版本。目前只有两个有效值:
"2012-10-17"— 当前标准版本,新策略必须用这个。"2008-10-17"— 旧版本,已不推荐。
小技巧:我习惯在所有策略里直接写 "Version": "2012-10-17",避免兼容性问题。这个字段其实是固定的,你基本不会改它。
Statement:策略的核心载体
Statement 是一个数组,里面每条就是一个权限规则。说白了,一条 Statement 就是一句话:允许或拒绝谁做什么事。它的子元素有四个:Effect、Action、Resource、Condition。
Effect — 允许还是拒绝
只有两个值:"Allow" 或 "Deny"。Deny 优先级总是高于 Allow,这是 AWS 的安全铁律。
注意:我曾经在项目中写了一个全局 Allow 的 S3 策略,然后又加了一条 Deny 特定桶的策略。结果 Deny 生效后,连我自己都访问不了那个桶了… Deny 是真的“一票否决”。
Action — 允许的操作
Action 是一组服务操作,格式为 "服务名:操作名称",比如 "s3:GetObject"。支持通配符 *,但要注意范围。
- 写
"ec2:*"就是所有 EC2 操作。 - 精确写法比如
"kms:Decrypt"只允许解密。
我在项目中常见一个坑:有人写 "Action": "s3:*",结果发现 ListBucket 也允许了,导致桶里文件列表可被枚举。最好按最小权限原则,只写需要的操作。
Resource — 作用于哪些资源
Resource 的格式是 ARN(Amazon Resource Name)。例如:
"Resource": "arn:aws:s3:::my-bucket/*"
注意:有些操作要求 Resource 写 "*",比如 IAM 自身的 iam:PassRole。我刚开始老写错,后来记住了:服务自身管理类操作通常不绑定到具体资源。
| 资源类型 | ARN 示例 |
|---|---|
| S3 桶对象 | arn:aws:s3:::my-bucket/* |
| KMS 密钥 | arn:aws:kms:us-west-2:123456:key/xxxx |
| EC2 实例 | arn:aws:ec2:us-east-1:123456:instance/* |
Condition — 附加条件(可选但强大)
Condition 让你更精细地控制权限,比如限制来源 IP、要求 MFA、限制 TLS 版本。格式是 "条件运算符": { "条件键": "条件值" }。
举个例子:
"Condition": {
"IpAddress": {
"aws:SourceIp": "203.0.113.0/24"
},
"Bool": {
"aws:SecureTransport": "true"
}
}
这个策略只允许来自 203.0.113.0/24 网段且使用 HTTPS 的请求。嗯,这里要注意:条件键必须全局唯一,比如 aws:SourceIp 是通用的,s3:x-amz-server-side-encryption 是 S3 专属的。
避坑指南:我曾见过有人用 StringEquals 判断 IP,结果 IP 是字符串比较,忽略了 CIDR 范围,导致权限失效。记住:IP 范围必须用 IpAddress 或 NotIpAddress。
一张图看懂策略结构
下面我把整个 Statement 的骨架画出来,你照着写就不会漏字段了。
实战:把六个元素拼在一起
来看一个完整的策略例子。这个策略只允许用户从公司内网 IP 访问 S3 的 my-bucket 桶内对象,且必须使用 HTTPS。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": "arn:aws:s3:::my-bucket/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "10.0.0.0/8"
},
"Bool": {
"aws:SecureTransport": "true"
}
}
}
]
}
经验之谈:我刚开始时总把 Condition 写成列表,结果 AWS 直接报错。Condition 里每个条件运算符只能出现一次,但可以包含多个条件键。比如同时限制 IP 和 MFA:
"Condition": {
"IpAddress": { "aws:SourceIp": "10.0.0.0/8" },
"Bool": { "aws:MultiFactorAuthPresent": "true" }
}
六个字段的常见错误
| 字段 | 常见错误 | 正确做法 |
|---|---|---|
| Version | 写错日期 | 固定 2012-10-17 |
| Effect | 拼写成 allow(小写) |
首字母大写:Allow |
| Action | 漏掉服务名前缀 | 完整格式如 s3:ListBucket |
| Resource | 桶和对象 ARN 混淆 | 桶: arn:aws:s3:::bucket,对象: arn:aws:s3:::bucket/* |
| Condition | 条件键用错 | 查文档确认全局键或服务专属键 |
提醒:我见过有人把 Condition 放在 Statement 外面,结果 JSON 格式虽然没错,但条件完全不生效。Condition 必须是 Statement 的子元素,别放错层级。
好,到这,IAM 策略的六大元素你就全掌握了。写策略时对照这张图,基本不会漏字段。记住最关键的一条:Deny 优先,最小权限,条件收窄。这九个字能帮你避开90%的权限事故。