IAM角色:信任策略与权限策略

好,咱们直接进入正题。IAM角色,说白了就是一个“身份容器”。它本身没有密码,也没有固定的访问密钥。谁能用这个角色?能用它干什么?这是两个完全不同的问题。对应的,就是信任策略和权限策略。

我遇到过不少同学,把这两个策略搞混。结果要么是角色建好了但没人能切换过去,要么是切换过去了但啥也干不了。今天咱们一次把它理清。

核心概念:信任策略 vs 权限策略

先看一个最直白的对比:

维度 信任策略(Trust Policy) 权限策略(Permission Policy)
解决的问题 谁可以用这个角色? 这个角色能用哪些资源?
附加位置 挂载在角色本身的“信任关系”中 作为角色的托管策略或内联策略
核心动作 sts:AssumeRole s3:GetObject, ec2:* 等
主体(Principal) 明确写允许哪些AWS账号、用户、服务 不需要指定Principal(角色本身就是主体)
生效时机 在获取角色临时凭证之前检查 在临时凭证使用的时候检查

这个表基本把区别说清了。我习惯把信任策略比作“门禁系统”——先确认你能不能进这个门;权限策略比作“房间钥匙”——进门后你能开哪些房间的门。

信任策略:谁可以当这个角色?

信任策略是角色定义的一部分。每个角色都必须有一个信任策略(默认是拒绝所有)。它的结构里最关键的字段是 Principal 和 Action: sts:AssumeRole。

来看一个最常见的例子——允许同一个账户下的一个EC2实例来扮演这个角色:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
小提示:跨账户信任时,Principal写的是对方的AWS账户ID或根用户ARN。但记住,光信任策略允许还不够,对方账户还需要在用户/角色的权限策略中显式允许 sts:AssumeRole 指向你这里的角色ARN。这叫双向授权。

为什么会需要双向授权?我曾经踩过这个坑。跨账户配角色时,我在A账户的信任策略里写了B账户的ID,心想这不就通了?但我忘了B账户那边还要给具体的IAM用户分配 sts:AssumeRole 的权限。结果那个用户怎么也切不过来,排查了半天。

权限策略:角色能做什么?

权限策略就是平时大家最熟悉的IAM策略。可以托管,也可以内联。但这里有个关键点:角色的权限策略中不需要写Principal。因为当用户或服务使用 sts:AssumeRole 获取到临时凭证后,这个角色的ARN就已经成为凭证的语境了。权限检查时,AWS自动把角色当作主体。

举个例子,假设我要让这个EC2角色能读取S3中某个桶的对象:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-app-bucket/*"
    }
  ]
}

然后把这个策略附加给角色。完事。

嗯,这里要注意权限策略的作用范围。如果你在信任策略中允许了EC2服务,但权限策略里给的是 s3:* 允许所有桶,那这台EC2实例就真的能访问所有桶。权限边界要自己守好。

两者的协同流程

下面这张图把整个交互过程画出来了。我建议你先顺着箭头走一遍,再回来看后面的文字。

IAM角色信任策略与权限策略工作流程 IAM角色:信任策略与权限策略协同流程 请求者 (用户/EC2/Lambda) 信任策略 检查 Principal + Action 拒绝(返回错误) 权限策略 决定角色能做什么 临时凭证 (AccessKey + ) 资源操作 S3/FB/EC2等 权限策略生效 说明:请求者先过信任策略, 通过后获取临时凭证, 凭证携带角色权限策略 访问资源时由IAM引擎检查。

你看,流程非常清晰:

  1. 请求者发 sts:AssumeRole 请求。
  2. IAM服务读取角色的信任策略,检查Principal和Action。
  3. 如果信任策略不允许,直接拒绝,返回错误。
  4. 如果允许,颁发临时安全凭证(AccessKey + SessionToken)。
  5. 当请求者用这个凭证去调用其他AWS服务时,IAM会基于角色的权限策略做最终授权。
坑你别踩:我曾经见过一个生产事故——角色信任策略只允许 ec2.amazonaws.com,但开发者直接在EC2实例里写死 aws sts assume-role 去获取另一个角色的凭证。注意,EC2服务帮你自动获取凭证,但如果你手动调STS,PassRole权限和信任策略都要重新检查。千万别混用。

实践建议:如何安全搭配?

讲了这么多,我总结几条我个人常用的原则:

  • 信任策略尽量收窄。只给必要的服务或账户。比如EC2就写 ec2.amazonaws.com,Lambda就写 lambda.amazonaws.com,别图省事写 *。
  • 权限策略用最小权限。角色能访问的资源范围越小越好。尤其当角色给EC2实例用时,实例上跑的应用如果被攻破,角色权限就是攻击者的进入门槛。
  • 用条件键加固信任。比如强制要求 aws:SourceAccount 或 aws:SourceArn,避免混淆代理人攻击。这个后面章节会细讲。

一句话总结:信任策略决定“开不开门”,权限策略决定“进门后能去哪”。写角色配置时,这两份策略要分开思考,但最终联调时要一起验证。