第二章:AWS IAM 策略基础 —— 用户、组、角色与策略语法
好,我们直接进入正题。IAM 是 AWS 权限体系的基石,你写每一条策略、配每一个角色,最后都要落回 IAM 的基本概念上。这章我想先帮你把地基打牢,后面讲细粒度策略和 KMS 权限才不会晕。
2.1 三个核心实体:用户、组、角色
说实话,很多新手会把角色和用户搞混。我当年也犯过这个错,给一个 EC2 实例配了用户凭证,结果密钥泄露……那叫一个惨。咱们先看定义:
- IAM 用户:代表一个人或一个应用。有长期凭证(密码 + 访问密钥)。通常用来给同事开控制台登录,或者给 CI/CD 工具调用 API。
- IAM 组:用户容器。把权限附加到组上,用户加入组就继承权限。省事,但也容易权限扩散。
- IAM 角色:没有长期凭证,临时凭证由 STS 颁发。给 AWS 服务(EC2/Lambda)、跨账号访问、联合身份用。
我的一条经验:能用角色就别用用户密钥。我在一次安全审计中发现客户把管理员密钥写死在代码里,差点被合规卡死。后来全改成了角色+STS,干净多了。
2.2 策略语法入门
IAM 策略本质是一个 JSON 文档,结构固定。我们直接看一条最常见的例子:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
五个核心字段:
| 字段 | 说明 | 我踩过的坑 |
|---|---|---|
| Version | 策略版本,必须写 2012-10-17 | 你写错一个字符,整个策略就解析失败 |
| Statement | 数组,可以写多条规则 | 注意是数组,只放一条也要加方括号 |
| Effect | Allow 或 Deny | Deny 优先级比 Allow 高——显式拒绝永远覆盖允许 |
| Action | 一个或多个操作,支持通配符 * | 我曾经写了个 "s3:*" 导致所有人都能删桶……记得收紧 |
| Resource | ARN,也可以用 * | 但别随便用 *,除非你确定要开放全部资源 |
2.3 条件(Condition)—— 策略的灵魂
前面那只是基础策略,真正让权限变细的,是 Condition。为啥这么说?
你想,如果没有条件,"Resource": "*" 就是给所有权限。但有了条件,就能写成:
{
"Effect": "Allow",
"Action": "kms:Decrypt",
"Resource": "*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "10.0.0.0/8"
}
}
}
这就把解密操作限制在内部网段。我在客户那里遇到过一例:他们把 KMS 解密权限直接开放给了一个 IAM 用户,没有加条件,结果员工从家里 VPN 解密了敏感数据……后来加上了 VPC SourceVpce 条件,才算堵住。
常用条件键:aws:SourceIp、aws:RequestedRegion、kms:ViaService、aws:MultiFactorAuthPresent。其中 kms:ViaService 是第七章的重点,先记个印象。
2.4 四种策略类型
别以为就一种策略类型。实际你写策略时,要区分它挂在哪里:
- 身份策略:直接挂用户/组/角色。最常见。
- 资源策略:挂到 S3 桶、KMS 密钥等资源上。可以跨账号。
- 权限边界:限制用户能获得的最大权限,不能越界。
- 服务控制策略(SCP):组织级别限制,控制整个 OU 下的所有账号。
这些类型之间是叠加和优先级关系。我画了张图帮你理清流程:
注意图上的两个关键点:显式 Deny 优先级最高,其次权限边界会砍掉超出范围的操作,最后才是身份和资源策略里的 Allow。别以为写了个 Allow 就万事大吉——如果 SCP 里 Deny 了,你无论如何也通不过。
2.5 策略生效逻辑
我习惯用一个口诀记:「拒绝优先,边界收口,Allow 放行,无 Allow 默认 Deny。」
- 显式允许(Allow)—直接放行,但必须没有被显式拒绝。
- 显式拒绝(Deny)—无论其他策略是什么,直接拒绝。
- 隐式拒绝—没有任何 Allow,默认 Deny。
我曾经摔过的跟头:给一个 S3 桶写了两条策略,一条 Allow 列出桶,另一条 Deny DeleteObject。结果因为 Deny 写成了 "Action": "s3:DeleteObject",忘了加星号,导致只有精确匹配的操作被拒绝,而 s3:DeleteObjectVersion 漏掉了……经过教训,现在我习惯在 Deny 里用 "Action": "s3:DeleteObject*" 通配。
2.6 实战:写一条最小权限策略
假设你有一个分析工作负载,只需要从 S3 读取日志文件,然后用 KMS 解密。应该怎么写?
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::log-bucket",
"arn:aws:s3:::log-bucket/*"
]
},
{
"Effect": "Allow",
"Action": "kms:Decrypt",
"Resource": "*",
"Condition": {
"ForAnyValue:StringLike": {
"kms:ViaService": "s3.*.amazonaws.com"
}
}
}
]
}
这里用了 kms:ViaService 条件,意思是你只能用 KMS 解密通过 S3 发起的请求。这样即使用户拿到了密钥权限,也没法直接调用 KMS API 批量解密。这种细粒度的条件,就是咱们这门课要深入讲的内容。
2.7 本章小结
记住三个实体、一个 JSON 五字段、条件决定细粒度、四种策略类型。后面的章节我们会反复用到这些东西。尤其条件部分,你会看到它怎么配合 KMS 的上下文密钥策略做更精细的控制。今天先把框架搭好。