4. IAM精细权限设计与最小权限落地

在AWS企业数据平台中,IAM是唯一贯穿所有数据服务的安全控制平面。S3、Glue、Athena、Redshift、Kinesis、Lake Formation 的每一次数据访问,最终都要经过 IAM 的授权判定。所谓“最小权限落地”,不是把策略写得越短越好,而是让每个主体在完成既定任务时,只拥有恰好够用的动作与资源范围,并且这种“恰好”可以被验证、被收敛、被持续监控。

一、先分清四种权限载体的作用边界

IAM 中真正决定“能不能做”的,是身份策略(Identity-based Policy)、资源策略(Resource-based Policy)、权限边界(Permissions Boundary)和会话策略(Session Policy)四类载体的交集。理解它们的关系,是精细设计的前提。

  • 身份策略:附加在用户、角色或用户组上,回答“这个主体被允许做什么”。
  • 资源策略:附加在 S3 桶、KMS 密钥、Glue Catalog 等资源上,回答“谁可以访问我”。跨账号访问必须两侧都放行。
  • 权限边界:附加在用户或角色上,只做“上限裁剪”,本身不授予任何权限。它把身份策略的有效权限限制在边界之内。
  • 会话策略:在 AssumeRole 或 GetFederationToken 时传入,进一步收窄本次临时凭证的权限,常用于 STS 临时授权。

最终有效权限 = 身份策略 ∩ 权限边界 ∩ 会话策略,若涉及跨账号或资源策略,还需与资源策略取并集后再与上述交集求交。这个判定顺序决定了:给角色加权限边界后,即使身份策略写了 s3:*,只要边界里没有 s3:DeleteObject,删除操作依然会被拒绝。

IAM 有效权限判定:四类载体的交集与并集 身份策略 Allow s3:GetObject Allow s3:PutObject 权限边界 Allow s3:GetObject (无 PutObject) 会话策略 Allow s3:GetObject (临时收窄) ∩ ∩ 有效权限 仅 s3:GetObject 通过 资源策略(跨账号) S3 / KMS / Glue Catalog 两侧都放行才生效 并集 显式 Deny 优先 任何载体出现 Deny → 最终拒绝 判定顺序:显式 Deny → 资源策略并集 → 身份策略 ∩ 权限边界 ∩ 会话策略 → 默认隐式拒绝 权限边界只裁剪上限,不授予权限;会话策略只收窄,不放大

二、用角色替代长期密钥,是数据平台的基本纪律

数据平台中的计算主体——Glue 作业、Lambda 函数、ECS 任务、EMR 集群、Athena 查询——都应通过 IAM 角色获取临时凭证,而不是在代码或配置里硬编码 Access Key。角色设计的关键是“一职一角色”:Glue ETL 作业角色只应能读写指定 S3 前缀、访问指定 Glue Catalog 数据库和 KMS 密钥,不应附带 s3:* 或 glue:* 通配。

信任策略(Trust Policy)同样需要收窄。例如只允许 glue.amazonaws.com 承担该角色,并可用 aws:SourceAccount 条件键防止混淆代理(Confused Deputy)问题:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"Service": "glue.amazonaws.com"},
    "Action": "sts:AssumeRole",
    "Condition": {
      "StringEquals": {"aws:SourceAccount": "123456789012"},
      "ArnLike": {"aws:SourceArn": "arn:aws:glue:ap-southeast-1:123456789012:catalog"}
    }
  }]
}

三、策略模拟:上线前先验证,而不是靠猜

IAM Policy Simulator 可以在不实际调用 API 的情况下,判断某个主体对某组动作和资源是 allowed 还是 denied。实战中建议按“主体 → 动作 → 资源 ARN → 条件键”四元组构造测试用例。例如验证 Glue 作业角色能否删除生产桶对象:

aws iam simulate-principal-policy \
  --policy-source-arn arn:aws:iam::123456789012:role/GlueETL-Prod \
  --action-names s3:GetObject s3:PutObject s3:DeleteObject \
  --resource-arns arn:aws:s3:::prod-data-lake/raw/orders/2024-06-01.json

预期返回中 s3:GetObject 与 s3:PutObject 为 allowed,s3:DeleteObject 为 implicitDeny。若删除动作返回 allowed,说明策略过宽,需要回到身份策略或权限边界中收紧。模拟结果中的 implicitDeny 与 explicitDeny 要区分对待:前者是“没授权”,后者是“被显式拒绝”,后者往往来自 SCP 或权限边界,排查方向完全不同。

四、IAM Access Analyzer:把“意外可访问”变成可发现的问题

Access Analyzer 通过分析资源策略,识别出允许外部主体(其他账号、匿名、任意组织外主体)访问的资源,并给出发现结果(Finding)。对数据平台而言,最需要关注的是 S3 桶策略、KMS 密钥策略、IAM 角色信任策略和 Glue Catalog 资源策略。

它还能基于 CloudTrail 实际访问日志生成“最小权限策略建议”。例如某 Glue 角色过去 90 天只调用了 s3:GetObject、s3:ListBucket、glue:GetTable,Access Analyzer 会生成一份仅含这些动作的策略模板,供你替换掉原来的宽泛策略。这是从“理论最小”走向“实测最小”的关键一步。

建议为 Access Analyzer 设置组织级或账号级分析器,并把 ACTIVE 状态的 Finding 接入 Security Hub 或 EventBridge,实现新出现的公开访问在分钟级内告警。

五、权限边界在数据平台中的典型用法

权限边界最常见的场景是“允许开发者自助创建角色,但角色权限不能超过平台规定的上限”。做法是:先定义一条边界策略,列出数据平台允许的最大动作集合(如仅 S3、Glue、Athena、KMS 的读操作,禁止 IAM 写操作和删除类动作),再通过 SCP 或 IAM 条件强制要求新建角色必须附加该边界:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "RequireBoundary",
    "Effect": "Deny",
    "Action": ["iam:CreateRole", "iam:PutRolePolicy"],
    "Resource": "*",
    "Condition": {
      "StringNotEquals": {
        "iam:PermissionsBoundary": "arn:aws:iam::123456789012:policy/DataPlatformBoundary"
      }
    }
  }]
}

这样即使开发者给自己附加了 AdministratorAccess,有效权限仍被边界裁剪,无法越权。边界策略本身不授予权限,因此必须同时给角色附加正常的身份策略,否则角色将“什么都做不了”。

六、落地检查清单

检查项判断标准工具
是否存在长期 Access Key数据平台角色应全部使用临时凭证IAM 凭证报告
策略是否含通配动作生产角色不应出现 s3:*、glue:*IAM Access Analyzer 策略校验
信任策略是否收窄含 aws:SourceAccount 或 aws:SourceArn 条件人工审查 + Config 规则
是否存在外部可访问资源无 ACTIVE 状态的公开访问 FindingIAM Access Analyzer
权限边界是否强制新建角色必须附加指定边界SCP + IAM 条件键
策略是否经过模拟验证关键动作有 simulate-principal-policy 记录IAM Policy Simulator

最小权限不是一次性配置,而是一个持续收敛的过程:先用 Access Analyzer 发现过宽权限,用 Policy Simulator 验证收紧后的效果,再用权限边界和 SCP 把上限锁死,最后通过 CloudTrail 与 Access Analyzer 的持续分析确认没有新的越权路径出现。只有把“设计—验证—监控—收敛”串成闭环,IAM 精细权限才真正在数据平台上落地。