3. IAM策略语言与表达

在IAM自动化治理中,策略语言是“把治理意图翻译成机器可执行规则”的载体。无论面对云平台、Kubernetes、API网关还是内部权限系统,策略语言通常都围绕四个核心要素展开:主体(谁发起请求)、资源(操作什么对象)、动作(执行什么操作)、条件(在什么环境下允许或拒绝)。理解这些要素如何组合、如何判定效果、如何确定优先级,是后续实现策略即代码(Policy as Code)的基础。

一、策略的基本结构:从“五元组”到可执行规则

一个典型的IAM策略可以抽象为如下结构:

{
  "version": "2024-01-01",
  "statement": [
    {
      "sid": "AllowReadOnlyForDev",
      "effect": "Allow",
      "principal": "group:developers",
      "action": ["s3:GetObject", "s3:ListBucket"],
      "resource": ["arn:aws:s3:::dev-bucket/*"],
      "condition": {
        "StringEquals": { "aws:RequestedRegion": "cn-north-1" },
        "Bool": { "aws:SecureTransport": "true" }
      }
    }
  ]
}

这段示例中,principal 指定主体,action 与 resource 限定操作范围,condition 增加环境约束,effect 决定最终是允许还是拒绝。实际平台可能使用JSON、YAML、Rego、Cedar等不同语法,但结构逻辑高度相似。策略语言的设计目标不是“写得像自然语言”,而是让规则可解析、可校验、可版本化、可自动化执行。

二、条件:让策略从“静态授权”走向“上下文感知”

条件表达式是策略语言中最具表达力的部分。它允许策略根据请求上下文动态判断,例如:

  • 时间条件:仅允许工作日 09:00–18:00 访问敏感数据;
  • 网络条件:仅允许来自企业内网或指定VPC的请求;
  • 标签条件:仅当资源标签 env=prod 且主体标签 team=payment 时放行;
  • MFA条件:执行删除操作必须已通过多因素认证;
  • 加密条件:仅允许通过TLS加密通道访问对象存储。

条件通常由操作符(如 StringEquals、IpAddress、Bool、DateGreaterThan)和键值对组成。多个条件之间默认是“与”关系,即全部满足才生效;同一操作符内多个值通常是“或”关系。理解这一点非常关键,否则容易写出“看似严格、实际宽松”的策略。

三、效果与优先级:Allow、Deny 与显式拒绝

策略效果通常只有两种:Allow 和 Deny。但多个策略同时命中时,最终判定并非简单“少数服从多数”。主流IAM系统的判定逻辑可以概括为:

  1. 默认拒绝:没有任何策略允许时,请求被拒绝;
  2. 显式拒绝优先:只要有一条策略显式 Deny,无论其他策略是否允许,最终都拒绝;
  3. 允许需要至少一条 Allow 命中,且不存在任何 Deny 命中。

因此,显式拒绝是最高优先级。在治理实践中,常用显式拒绝来设置“安全底线”,例如禁止关闭审计日志、禁止公开暴露存储桶、禁止创建无MFA的管理员。允许策略则用于日常授权。优先级不是靠策略书写顺序决定的,而是由效果类型和条件匹配共同决定。

IAM策略判定流程:条件匹配 → 效果合并 → 优先级裁决 访问请求 主体 + 动作 + 资源 + 上下文 策略集合 Allow策略 / Deny策略 条件表达式逐条匹配 条件匹配 时间 / 网络 / 标签 / MFA 全部满足才命中 效果合并与优先级裁决 显式 Deny > Allow > 默认 Deny 拒绝访问 存在显式Deny或未命中Allow 允许访问 至少一条Allow命中且无Deny 策略书写顺序不影响优先级;效果类型与条件匹配结果共同决定最终判定

四、策略即代码:从控制台点击到版本化治理

策略即代码(Policy as Code,PaC)的核心思想是:把策略当作软件资产来管理。策略不再只存在于云控制台的点击配置中,而是以文本文件形式存放在Git仓库,经过代码评审、自动化测试、流水线发布和版本回滚。其基本范式包括:

  • 声明式描述:用JSON、YAML、Rego、Cedar等语言声明“期望状态”,而非编写命令式脚本;
  • 版本控制:策略变更走Pull Request,保留提交历史、评审记录和责任人;
  • 自动化校验:在CI阶段用策略测试框架验证语法、逻辑冲突和合规基线;
  • 持续部署:通过流水线将策略推送到IAM系统、Kubernetes准入控制器或API网关;
  • 漂移检测:定期比对实际策略与仓库期望状态,发现并纠正手工变更。

以Rego为例,一条“禁止公开S3桶”的策略可以写成:

package iam.governance

deny[msg] {
  input.action == "s3:PutBucketAcl"
  input.resource.acl == "public-read"
  msg := "禁止将S3桶ACL设置为public-read"
}

在CI中,可以用 opa test 对策略进行单元测试,输入模拟请求,断言期望的允许或拒绝结果。只有测试通过,策略才允许合并并发布。这样,策略变更就从“人工操作”变成了“可验证的工程交付”。

五、实践中的关键判断:如何避免策略冲突与过度授权

在真实治理场景中,策略冲突和过度授权是最常见的两类问题。判断依据可以归纳为三点:

  1. 是否存在显式Deny覆盖了业务必需的Allow:例如安全基线禁止所有 s3:*,但数据团队需要 s3:GetObject,此时应细化Deny范围,而不是简单放开;
  2. 条件是否真正收窄了权限:如果条件键写错、操作符用错,策略可能比预期更宽松;
  3. 策略是否可测试、可回滚:无法在CI中验证的策略,不应直接进入生产环境。
教学示例参数说明: 上文中的策略片段、Rego代码和判定流程均为教学示例,用于说明策略语言的结构与判定逻辑,不代表任何特定云厂商的完整生产配置。实际使用时需结合目标平台的策略语法、条件键和测试工具进行调整。

掌握策略结构、条件、效果与优先级之后,下一步就是把这些规则组织成可维护、可审计、可自动化的策略体系。策略即代码不是单纯换一种写法,而是把IAM治理从“人工配置”推进到“工程化交付”的关键一步。