AWS Identity & Access Management · Deep Dive

IAM 权限层级详解:从 Organization 到一条策略语句

以 AWS 官方文档为准,讲清三层问题:① 权限体系有哪些层级;② 给一个"服务账号"(workload identity)正确授权要给什么;③ Management account 与跨账户 assume role 到底是什么关系。含可交互的策略求值模拟器。

01权限层级:请求要穿过多少层门

自上而下每一层都只能做「收紧」,不能放大权限 —— 这是整个 IAM 的核心设计。

Root User
账户级最高凭证 · 日常禁用
SCP / RCP · Organizations 层
只收紧 · 不授予 · org-wide 天花板
OU 继承层
SCP 沿组织树向下继承
Account 成员账户
隔离边界 · 计费边界
Federation / Identity Provider
外部身份换临时角色凭证
Principal:User / Group / Role
identity policy + trust policy + boundary
👆 点击任意一层,查看该层的官方定义与要点。
一句话记住层级方向:请求先看「有没有人明确允许」(默认全拒绝),再逐层过「天花板」—— boundary、SCP、RCP、session policy 必须全都放行;任何一处 explicit deny 一票否决。

02九种策略类型:谁贴在谁身上

AWS 支持 9 类策略。按「贴在身份上」vs「贴在资源上」vs「贴在边界/组织上」分类理解,比按字母背更牢。

① Identity-based(贴在身份)

挂在 IAM 用户 / 组 / 角色上,规定这个身份能做什么。最常用。

  • AWS 托管策略:AWS 官方维护,如 AmazonS3ReadOnlyAccess
  • 客户托管策略:自己写、可复用的 JSON
  • Inline 策略:一对一死贴某个身份,不共享

② Resource-based(贴在资源)

挂在资源本身,规定哪个主体能动我。最常见是 S3 bucket policy。

  • S3 Bucket Policy
  • IAM Role Trust Policy(也是资源策略的一种,决定谁能 assume 这个 role)
  • KMS Key Policy、Lambda resource policy、SQS policy 等

⚠️ 跨账户访问:被访问账户的资源策略和请求方身份的 identity policy 必须同时允许。

③ 边界 / 组织 / 端点

  • Permissions boundary:挂在身份上的「最大权限天花板」,不授权,只封顶
  • SCP:Organizations 层天花板,约束组织内身份
  • RCP:Organizations 层资源天花板,约束资源
  • VPC endpoint policy:经 VPC 端点访问时的额外边界

④ 会话 / 共享 / ACL

  • Session policy:assume role / federation 时临时叠加,进一步收窄本次会话
  • RAM share:跨账户共享资源时的访问附文
  • ACL(访问控制列表):S3 / VPC 的旧式子网级控制,粗粒度、少用
关键区分:Allow 类策略(identity / resource / session)是「授予」;boundary / SCP / RCP 是「天花板」—— 它们从不授予权限,只决定授予的上限。一条常见误区:以为挂了 SCP 就有了权限,其实没有。

03策略求值模拟器 ▶ 自己点着玩

AWS 的官方求值顺序固定不变。下方按真实逻辑实现:默认拒绝 → 任一 Explicit Deny 即否决 → 各天花板必须放行 → 任一 Explicit Allow 即通过。试着勾选不同组合看结论。

求值顺序(官方)

① 默认所有请求隐式拒绝。② 检查所有策略:只要出现一条 Explicit Deny,立即否决。③ 若存在 Permissions Boundary / SCP / RCP / Session Policy 中任意一种,它们必须全部放行,否则隐式拒绝。④ 若有一条 Explicit Allow(identity 或 resource 策略),请求通过。

04给「服务账号」正确授权要给什么

这里的「服务账号」= 一个非人主体(CI/CD pipeline、后端服务、定时任务)需要访问 AWS。AWS 的官方答案很明确:用 Role(角色),不是 User,并通过 federation 或交叉扮演拿临时凭证。

A. 工作负载在本账户内(EC2/ECS/Lambda)

用 IAM Role + 实例/任务角色:

  • 创建 Role,permissions policy = 它实际需要的动作(最小权限)
  • trust policy 信任 ec2.amazonaws.com / ecs-tasks.amazonaws.com / lambda.amazonaws.com
  • 把 Role 挂到实例/任务/函数上,AWS 自动注入临时凭证,不用存密钥

B. 工作负载在外部(GitHub Actions / 其他云)

用 OIDC 联邦免密钥:

  • 在 IAM 建 Identity Provider(如 token.actions.githubusercontent.com)
  • 建 Role,trust policy 用 StringEquals 限定 repo:你的org/你的repo + sub
  • 工作流跑 AssumeRoleWithWebIdentity 换临时凭证

C. 确实需要「长期密钥」的兼容场景(应尽量避免)

仅当无法用角色时才退而求其次:建 IAM User + access key,只挂 programmatic access,绝不开放控制台;用 Group 或 customer-managed policy 绑权限;强制 rotation;开 key 的 last-used 监控。但官方立场是:优先 Role,User 是例外。

一个最小可用的「读 S3 桶」服务角色示例

# 1) 角色信任策略:允许 ECS 任务扮演我
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "Service": "ecs-tasks.amazonaws.com" },
    "Action": "sts:AssumeRole"
  }]
}
# 2) 角色权限策略:只允许它读指定的桶(最小权限)
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": ["s3:GetObject", "s3:ListBucket"],
    "Resource": [
      "arn:aws:s3:::my-app-data",
      "arn:aws:s3:::my-app-data/*"
    ]
  }]
}
给服务账号授权的三步清单:① 选主体形态(角色优先,OIDC 联邦免密钥);② 写 permissions policy 精确到 Action+Resource(拒绝 "Action":"*" 除非临时调试);③ 写 trust policy 精确到 Principal,必要时加 ExternalId 或 Condition 防混淆代理人攻击(confused deputy)。

05Management account 与「assume account」

你提到的 management account 与 assume account,对应 AWS Organizations 的真实概念:management account(管理账户) 与 member account(成员账户)+ assume role 跨账户访问。

Management (payer) account —— 组织根账户

创建 AWS Organizations 的那个账户,也叫 payer / root account。它:

  • 拥有组织的最高控制力(创建/邀请账户、挂 SCP、开 Consolidated Billing)
  • 默认不被自己组织的 SCP 约束 —— 这正是它和成员账户的关键区别,所以要特别保护好
  • 最佳实践:management account 只放组织管理用途,不要跑业务 workload

成员账户 + AssumeRole —— 「assume 到另一个账户」

多账户架构下,每个环境/团队是独立 member account。当你说「assume 到某账户」,流程是:

  1. 目标账户里有一个 Role,其 trust policy 允许你的来源主体(可以是另一账户的根、某 user、或某 role)扮演它
  2. 你用 sts:AssumeRole(CLI: aws sts assume-role --role-arn ...)换到一组临时凭证
  3. 用这组临时凭证,以目标账户内该 Role 的 permissions policy 为准去操作

跨账户访问成立的两个硬条件:目标账户的资源/信任策略允许你 且 你来源账户的 identity policy 允许你发起 AssumeRole。任一缺失都失败。

常见模式:部署账号 assume 进生产账号

# 生产账户中的 Role(prod-deployer)trust policy:
# 允许「部署账户 123456789012」里的 Role 扮演我
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "AWS": "arn:aws:iam::123456789012:role/deploy-bot" },
    "Action": "sts:AssumeRole",
    "Condition": { "StringEquals": { "sts:ExternalId": "a-secret-only-we-know" } }
  }]
}
区别一句话:Management account 是「组织的总闸」,管所有成员账户;assume role 是「借道」—— 临时借用另一个账户里某个角色的身份去干活。两者不是同一维度:一个讲组织层级,一个讲跨账户动作。

06实操清单:拿去照着做

把前面四节浓缩成可执行的检查项。

架构层

  • 用 Organizations 多账户:management 只管组织,业务进 member account
  • SCP 设组织级红线(禁 region、禁关 CloudTrail、禁删保护)
  • Root user 启用 MFA、锁死、日常不用

服务账号层

  • 用 Role 不用 User;能 OIDC 联邦就不发密钥
  • permissions policy 精确到 Action+Resource(最小权限)
  • trust policy 限定 Principal,敏感场景加 ExternalId / Condition

跨账户层

  • 目标账户 Role 的 trust 允许来源主体
  • 来源身份的 identity policy 允许 AssumeRole
  • prefer 角色链而非共享长期密钥

审计层

  • CloudTrail 全账户开;Access Analyzer 找对外暴露
  • IAM Access Advisor 定期回收未用权限
  • 权限变更走代码评审,不手工点
资料来源:AWS 官方 IAM User Guide —— How IAM works / Policies and permissions / Policy evaluation logic / Access permissions required / IAM roles terms。本页所有规则均对照上述文档撰写,无任何编造。