3. SCP与权限边界实战

服务控制策略(Service Control Policy,SCP)是 AWS Organizations 中作用于成员账号的权限护栏。它本身不授予任何权限,只负责在账号根、OU 或账号层级上划定“允许的最大权限集合”。真正让某个 IAM 主体获得操作能力的,仍然是身份策略(Identity-based Policy)。因此理解 SCP 的关键在于:最终有效权限 = SCP 允许范围 ∩ IAM 身份策略允许范围 − 显式拒绝。本节围绕网络服务、区域与资源类型三类典型限制,编写可落地的 SCP,并用 IAM 策略验证多账号治理效果。

一、SCP 的作用位置与生效逻辑

SCP 只能附加到组织根、OU 或成员账号,不能附加到 IAM 用户、角色或组。一个成员账号的 SCP 生效集合,是从根到该账号路径上所有 SCP 的交集。例如根上有一条“禁止所有区域外操作”的 SCP,某 OU 上有一条“禁止删除 VPC”的 SCP,则该 OU 下账号同时受两条约束。默认情况下,组织根会带有一条 FullAWSAccess 策略,它允许一切,因此新账号在未附加限制前不受额外约束。

SCP 的语法与 IAM 策略一致,包含 Version、Statement、Effect、Action、Resource、Condition。区别在于 SCP 中的 Resource 通常写 "*",因为 SCP 不针对具体资源实例做精细授权,而是控制“能不能调用某类 API”。

二、限制网络服务:只允许受控的 VPC 与网络 API

多账号环境中,网络服务是最容易失控的部分:成员账号可能自行创建 VPC、对等连接、Transit Gateway 挂载或开放安全组。治理思路是“白名单式放行 + 显式拒绝高风险动作”。下面这条 SCP 允许常规的 VPC 读取与受控创建,但拒绝删除 VPC、修改路由表和创建对等连接:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowNetworkReadAndControlledCreate",
      "Effect": "Allow",
      "Action": [
        "ec2:Describe*",
        "ec2:CreateVpc",
        "ec2:CreateSubnet",
        "ec2:CreateTags"
      ],
      "Resource": "*"
    },
    {
      "Sid": "DenyRiskyNetworkOps",
      "Effect": "Deny",
      "Action": [
        "ec2:DeleteVpc",
        "ec2:CreateVpcPeeringConnection",
        "ec2:ModifyRouteTable",
        "ec2:CreateTransitGatewayVpcAttachment"
      ],
      "Resource": "*"
    }
  ]
}

注意:SCP 中一旦出现 Deny,即使 IAM 身份策略允许,操作也会被拒绝。因此上例中成员账号的 IAM 角色即便拥有 ec2:*,也无法删除 VPC 或建立对等连接。这就是“护栏”与“授权”分离的价值。

三、限制区域:用 aws:RequestedRegion 锁定部署范围

区域限制是成本与合规治理的常用手段。通过条件键 aws:RequestedRegion,可以只允许在指定区域调用 API。下面这条 SCP 仅允许在 cn-north-1 与 cn-northwest-1 两个区域操作,其余区域一律拒绝:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyOutsideApprovedRegions",
      "Effect": "Deny",
      "Action": "*",
      "Resource": "*",
      "Condition": {
        "StringNotEquals": {
          "aws:RequestedRegion": [
            "cn-north-1",
            "cn-northwest-1"
          ]
        }
      }
    }
  ]
}

需要特别说明:全局服务(如 IAM、Organizations、CloudFront、Route 53)的请求区域通常表现为 us-east-1 或空值,直接套用上述策略可能误伤这些服务。稳妥做法是在条件中排除全局服务,或使用 NotAction 列出不受区域限制的服务。例如把 Action 改为 NotAction 并列出 iam:*、organizations:*、 等,可避免治理策略破坏账号基础功能。

四、限制资源类型:用标签与资源 ARN 约束创建行为

资源类型限制常用于防止成员账号创建高成本或不合规的资源。例如只允许创建带 CostCenter 标签的 EC2 实例,禁止创建特定实例族:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyUnlabeledEC2",
      "Effect": "Deny",
      "Action": "ec2:RunInstances",
      "Resource": "arn:aws:ec2:*:*:instance/*",
      "Condition": {
        "Null": {
          "aws:RequestTag/CostCenter": "true"
        }
      }
    },
    {
      "Sid": "DenyExpensiveInstanceFamily",
      "Effect": "Deny",
      "Action": "ec2:RunInstances",
      "Resource": "arn:aws:ec2:*:*:instance/*",
      "Condition": {
        "StringLike": {
          "ec2:InstanceType": "p*"
        }
      }
    }
  ]
}

这里 aws:RequestTag/CostCenter 为 true 表示请求中未携带该标签,因此拒绝。第二条用 ec2:InstanceType 条件键匹配 p* 系列,阻止 GPU 实例被随意创建。两条策略叠加后,成员账号只能创建带成本中心标签、且非 p 系列的实例。

SCP 与 IAM 策略叠加后的有效权限判定 组织根 SCP 区域白名单 OU SCP 禁止删除 VPC 账号 SCP 资源标签约束 SCP 允许的最大权限集合 网络 API 白名单 cn-north-1 / cn-northwest-1 带 CostCenter 标签 非 p* 实例族 IAM 身份策略 ec2:RunInstances ec2:CreateVpc ec2:Describe* ∩ 最终有效权限 仅允许受控网络操作 仅限指定区域 仅限合规资源类型 判定规则:SCP 只做“允许范围裁剪”,不授予权限;IAM 策略负责“实际授权”。 任一 SCP 出现 Deny,或请求超出 SCP 允许范围,最终结果均为拒绝。

五、结合 IAM 策略验证治理效果

SCP 写完后必须验证,否则容易“策略看似正确、实际误伤或漏放”。验证分两步:先确认 SCP 是否按预期裁剪权限,再确认 IAM 身份策略在裁剪后仍能完成必要操作。

假设成员账号中有一个角色 NetworkOperator,其身份策略允许 ec2:*。在附加了前述三条 SCP 后,我们期望:

  • 在 cn-north-1 创建带 CostCenter=Net 标签的 t3.medium 实例:应成功。
  • 在 us-east-1 创建任意实例:应被区域 SCP 拒绝。
  • 在 cn-north-1 创建 p3.2xlarge 实例:应被实例族 SCP 拒绝。
  • 删除已有 VPC:应被网络 SCP 拒绝。

验证时可用 IAM Policy Simulator 或直接调用 API 观察返回。例如用 CLI 测试区域限制:

aws ec2 run-instances \
  --image-id ami-xxxxxxxx \
  --instance-type t3.medium \
  --region us-east-1 \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=CostCenter,Value=Net}]'

预期返回 UnauthorizedOperation,错误信息中会提示请求被 SCP 拒绝。若返回成功,说明区域 SCP 未正确附加或条件键写错。再测试标签约束:去掉 --tag-specifications 后在 cn-north-1 执行,应同样被拒绝,提示缺少 CostCenter 标签。

验证 SCP 时,建议先用一个专用测试账号或测试 OU,避免直接在生产 OU 上试错。SCP 变更后通常几秒到几分钟内生效,可结合 CloudTrail 查看 AccessDenied 事件中的 errorMessage,确认是 SCP 拒绝还是 IAM 策略拒绝。

六、多账号治理的落地要点

第一,SCP 要分层设计:根上放全局底线(区域、禁止关闭 CloudTrail),OU 上放业务线约束(网络、资源类型),账号上放个别例外。第二,SCP 与 IAM 职责分离:SCP 由中心治理团队维护,IAM 由账号所有者维护,二者通过“交集”协作。第三,所有 Deny 语句都要写 Sid,便于在 CloudTrail 和错误信息中定位是哪条策略拦截。第四,区域限制务必排除全局服务,否则 IAM、Organizations、Billing 等基础功能会一并失效。第五,每次变更后按“允许用例 + 拒绝用例”成对验证,确保策略既不过松也不过紧。

通过本节的三类 SCP 与 IAM 策略的组合验证,可以看到多账号权限治理的核心并不是“把权限收得越小越好”,而是让 SCP 精确表达组织底线,让 IAM 策略在底线内完成业务授权,最终用可复现的测试用例证明治理效果符合预期。