使用RAM Policy约束云上操作

利用阿里云访问控制(RAM)的策略(Policy)的条件(Condition)和拒绝(Deny)机制,将安全规范和合规要求转化为可被云平台自动强制执行的安全基线。通过这种方式,可以从源头上约束不安全的云资源创建和配置行为,例如禁止为ECS实例分配公网IP、强制使用密钥对登录、限制安全组开放高危端口等,从而构建一个默认安全的云环境。

安全风险

标准的RAM权限策略通常采用允许(Allow)模式,即授予“可以做什么”的权限,例如,允许创建ECS实例 ecs:RunInstances

{
  "Version": "1",
  "Statement": [
    {
      "Effect": "Allow",  #允许
      "Resource": "acs:ecs:*:*:instance/*", #资源范围
      "Action": [   #OpenAPI操作
        "ecs:RunInstances"
        ]
    }
}

这种模式虽然直观,但却隐藏着风险:它授予了权限范围内的“完全自由”。可能会导致创建出不符合安全规范的资源,例如:

  • 暴露攻击面:作为一台本应仅对内服务的数据库服务器,错误地绑定了弹性公网IP(EIP)。

  • 使用弱凭证:创建ECS实例时,仍然选择使用易被暴力破解的密码登录方式。

  • 违反合规性:创建资源时未使用经过安全加固的公司标准镜像。

最佳实践

核心原理

在允许的基础上,增加一层带有条件的拒绝(Deny)策略:

  1. 优先处理拒绝:RAM在评估一个操作请求时,会检查所有相关的策略。任何一条Deny策略的规则被匹配,该操作就会被立即拒绝,无论是否存在其他Allow策略。

  2. 精确条件约束:Deny策略可以绑定一个Condition(条件)块。只有当用户的操作行为同时满足Action(操作)、Resource(资源)和Condition(条件)时,Deny才会生效。

例如,创建实例(ecs:RunInstances)时,对于任何实例资源(acs:ecs:*:*:instance/*),只要绑定了公网IP("ecs:AssociatePublicIpAddress": "true"),则拒绝操作("Effect": "Deny")。

{
  "Version": "1",
  "Statement": [
    {
      "Effect": "Deny",  #拒绝
      "Resource": "acs:ecs:*:*:instance/*", #资源范围
      "Action": [   #OpenAPI操作
        "ecs:RunInstances"
      ],
      "Condition": {  #条件规则
        "Bool": {
            "ecs:AssociatePublicIpAddress": "true"   #条件关键字断言
        }
      }
    }
}

这种“Allow + Deny with Condition”的组合,先授予一个相对宽泛的允许(Allow)操作权限,再像设置安全护栏一样,精确地拒绝(Deny)其中不符合安全基线的特定行为。例如,“允许创建ECS实例,但如果创建时试图绑定公网IP,则拒绝此次操作”。这使得安全策略不仅是规范,更是可被平台强制执行的纪律。

操作步骤

被约束的主体必须同时拥有一个允许其操作的Allow策略(如AliyunECSFullAccess)和我们创建的Deny策略。当用户操作时,Allow策略使其有权尝试,而Deny策略则作为安全审查员,拒绝掉任何违规的尝试。以下步骤将指导如何创建并实施一套基于RAM Policy的安全基线。

  1. 确定需要约束的关键操作和条件

    首先,识别出希望强制执行的安全规则,并找到对应的RAM ActionCondition Key。Condition Key是云服务API暴露给RAM用于判断的参数。可在具体服务的API文档中找到它们。例如,创建ECS实例(ecs:RunInstances)这个Action,可以在RunInstances文档的“授权信息”部分找到所有支持的Condition Key。

  2. 编写带条件的Deny权限策略

    1. 登录RAM控制台,在左侧导航栏,选择权限管理 > 权限策略

    2. 在权限策略页面,单击创建权限策略

    3. 创建权限策略页面,单击脚本编辑页签。输入以下权限策略内容,然后单击确定

      以下是一些经过验证的常用权限策略示例:

      示例1:禁止创建ECS实例时绑定公网IP

      {
        "Version": "1",
        "Statement": [
          {
            "Effect": "Deny",
            "Action": "ecs:RunInstances",
            "Resource": "acs:ecs:*:*:instance/*",
            "Condition": {
              "Bool": {
                "ecs:AssociatePublicIpAddress": "true"
              }
            }
          }
        ]
      }

      示例2:强制创建ECS实例时使用SSH密钥对登录

      "Null": {"ecs:KeyPairName": "true"}的含义是,如果ecs:KeyPairName这个参数为空(即用户没有选择密钥对),则条件成立,拒绝(Deny)生效。

      {
          "Version": "1",
          "Statement": [
              {
                  "Action": "ecs:RunInstances",
                  "Effect": "Deny",
                  "Resource": "acs:ecs:*:*:instance/*",
                  "Condition": {
                      "Null": {
                          "ecs:KeyPairName": "true"
                      }
                  }
              }
          ]
      }

      示例3:禁止安全组规则向公共互联网(0.0.0.0/0)开放高危端口

      {
          "Version": "1",
          "Statement": [
              {
                  "Action": "ecs:AuthorizeSecurityGroup",
                  "Effect": "Deny",
                  "Resource": "acs:ecs:*:*:securitygroup/*",
                  "Condition": {
                      "StringEquals": {
                          "ecs:SourceCidrIp": "0.0.0.0/0"
                      },
                      "ForAnyValue:StringEquals": {
                          "ecs:PortRange": [
                              "22/22",
                              "3389/3389",
                              "3306/3306",
                              "6379/6379",
                              "27017/27017"
                          ]
                      }
                  }
              }
          ]
      }

      说明:ForAnyValue:StringEquals表示只要用户试图开放的端口范围与列表中的任何一个匹配,条件即成立。

    4. 输入策略名称备注,单击确定,完成安全验证。

  3. 绑定权限策略

    创建好策略后,将其附加到希望约束的RAM用户、用户组或角色上。

    1. 登录RAM控制台,在左侧导航栏,选择身份管理 > 用户

    2. 用户页面,单击目标RAM用户操作列的添加权限

    3. 新增授权面板,选择权限策略后,单击确认新增授权