为授予角色设置限制

在大型组织中,让团队独立管理资源的允许政策会大有帮助。但是,允许主账号授予或撤消所有 IAM 角色会加大安全风险。

您可以使用 Identity and Access Management (IAM) Conditions 和 iam.googleapis.com/modifiedGrantsByRole API 特性对主账号可以授予和撤消的角色设置限制。通过这些限制,您可以创建受限的 IAM 管理员,让他们管理自己团队的允许政策,但只能在您设置的边界内进行管理。

准备工作

所需权限

如需获得为项目、文件夹或组织创建受限 IAM 管理员所需的权限,请让管理员向您授予您要为其创建受限 IAM 管理员的资源(项目、文件夹或组织)的以下 IAM 角色:

  • 如需为项目创建受限 IAM 管理员:Project IAM Admin (roles/resourcemanager.projectIamAdmin)
  • 如需为文件夹创建受限 IAM 管理员:Folder Admin (roles/resourcemanager.folderAdmin)
  • 如需为项目、文件夹或组织创建受限 IAM 管理员:Organization Admin (roles/resourcemanager.organizationAdmin)

如需详细了解如何授予角色,请参阅管理访问权限

这些预定义角色包含为项目、文件夹或组织创建受限 IAM 管理员所需的权限。如需查看所需的确切权限,请展开所需权限部分:

所需权限

为项目、文件夹或组织创建受限 IAM 管理员需要以下权限:

  • 如需为项目创建受限 IAM 管理员:
    • resourcemanager.projects.getIamPolicy
    • resourcemanager.projects.setIamPolicy
  • 如需为文件夹创建受限 IAM 管理员:
    • resourcemanager.folders.getIamPolicy
    • resourcemanager.folders.setIamPolicy
  • 如需为组织创建受限 IAM 管理员:
    • resourcemanager.organizations.getIamPolicy
    • resourcemanager.organizations.setIamPolicy

您也可以使用自定义角色或其他预定义角色来获取这些权限。

常见使用场景

以下部分介绍了如何使用受限的角色授予来启用允许政策的自助管理功能。

创建受限的 IAM 管理员

设想一个场景,您希望允许用户 Fnn (finn@example.com) 充当项目的受限 IAM 管理员。您希望 Finn 只能授予和撤消项目的 App Engine Admin (roles/appengine.appAdmin) 和 App Engine Viewer (roles/appengine.appViewer) 角色。

若要授予这些受限的功能,您需要有条件地向 Finn 授予 Project IAM 管理员角色 (roles/resourcemanager.projectIamAdmin)。 Project Administrator Admin 角色允许 Finn 授予和撤消 IAM 角色,以及 Finn 可以授予和撤消哪些角色限制:

{
  "version": 3,
  "etag": "BwWKmjvelug=",
  "bindings": [
    {
      "members": [
        "user:owner@example.com"
      ],
      "role": "roles/owner"
    },
    {
      "members": [
        "finn@example.com"
      ],
      "role": "roles/resourcemanager.projectIamAdmin",
      "condition": {
        "title": "only_appengine_admin_viewer_roles",
        "description": "Only allows changes to role bindings with the App Engine Admin or Viewer roles",
        "expression":
          "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly(['roles/appengine.appAdmin', 'roles/appengine.appViewer'])"
      }
    }
  ]
}

此条件角色绑定允许 Finn 执行以下操作:

  • 授予项目的 App Engine Admin 和 App Engine Viewer 角色。
  • 撤消项目的 App Engine Admin 和 App Engine Viewer 角色。
  • 为授予 App Engine Admin 和 App Engine Viewer 角色的项目级角色绑定添加、移除或修改条件。
  • 执行 Project IAM Admin 角色允许,但不会修改项目的允许政策的其他操作。例如,Finn 可以使用 projects.getIamPolicy 方法来获取项目的允许政策。

此条件角色绑定不允许 Finn 执行以下任一操作:

  • 修改项目以外的资源的允许政策。
  • 授予 App Engine Admin 或 App Engine Viewer 角色以外的角色。
  • 撤消 App Engine Admin 或 App Engine Viewer 角色以外的角色。
  • 为不授予 App Engine Admin 或 App Engine Viewer 角色的角色绑定添加、移除或修改条件。

允许用户管理受限的 IAM 管理员

设想一个场景,您希望用户 Lila 为其团队中受限 IAM 管理员。您希望 Lila 只能授予和撤消她负责项目的 Compute Admin 角色 (roles/compute.admin)。但是,您还需要让 Lala 选择其他用户充当受限 IAM 管理员。换句话说,您希望允许 Lila 允许其他用户仅授予和撤消 Compute Admin 角色。

您可能认为此解决方案是授予 Lila 的 Project IAM Admin 角色 (roles/resourcemanager.projectIamAdmin),然后授予她为其他人授予或撤消该角色的权限。但是,如果您授予 Lila Project Admin 角色,她可以从自己的角色中移除此条件,并授予其授予或撤消任何 IAM 角色的权限。

为防止此权限升级,您需要为项目的受限 IAM 管理员创建 Google 群组 iam-compute-admins@example.com。然后,将 Lila 添加到群组中,然后让她成为群组管理员

创建群组后,有条件地为该群组授予 Project IAM Admin 角色 (roles/resourcemanager.projectIamAdmin)。Project IAM Admin 角色允许群组成员授予和撤消 IAM 角色,以及限制角色可以授予和撤消的角色:

{
  "version": 3,
  "etag": "BwWKmjvelug=",
  "bindings": [
    {
      "members": [
        "user:owner@example.com"
      ],
      "role": "roles/owner"
    },
    {
      "members": [
        "iam-compute-admins@example.com"
      ],
      "role": "roles/resourcemanager.projectIamAdmin",
      "condition": {
        "title": "only_compute_admin_role",
        "description": "Only allows changes to role bindings for the Compute Admin role",
        "expression":
          "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly(['roles/compute.admin'])"
      }
    }
  ]
}

作为 iam-compute-admins@example.com 群组的成员,Lila 可以执行以下操作:

  • 通过为角色添加新绑定或将主账号添加到现有角色的现有绑定,为项目授予 Compute Admin 角色。
  • 通过撤消该角色的现有绑定或从现有角色绑定中移除主账号来撤消 Compute Admin 角色。
  • 通过为角色的绑定添加、移除或修改条件来修改 Compute Admin 角色的授予。
  • 执行 Project IAM Admin 角色允许,但不会修改项目的允许政策的其他操作。例如,她可以使用 projects.getIamPolicy 方法来获取项目的允许政策。

作为 iam-compute-admins@example.com 群组的管理员,Lila 通过向 iam-compute-admins@example.com 群组添加 Compute Admin 角色来允许其他用户授予或撤消 Compute Admin 角色。

Lila 无法执行以下操作:

  • 能够授予或撤消其他角色。
  • 修改项目以外的资源的允许政策。
  • 授予除 Compute Admin 角色以外的角色。
  • 撤消除 Compute Admin 角色以外的角色。
  • 为不授予 Compute Admin 角色的角色绑定添加、移除或修改条件。

限制角色授予

以下部分介绍了如何让主账号仅授予或撤消特定角色。

编写条件表达式以限制角色授予

要限制主账号授予角色的能力,请编写条件表达式,指定主账号可以授予或撤消的角色。

为条件表达式使用以下格式:

api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly(roles)

此表达式会执行以下操作:

  • 使用 api.getAttribute() 函数获取 API 属性 iam.googleapis.com/modifiedGrantsByRole

    对于设置资源的允许政策的请求,此特性包含请求修改的绑定中的角色名称。对于其他类型的请求,该特性未定义。在这些情况下,此函数会返回默认值 ([])。

  • 使用 hasOnly() 通用表达式语言 (CEL) 函数定义并实施允许主账号授予或撤消的角色。

    hasOnly() 函数的输入是允许主账号授予或撤消的角色的列表。如果此列表中包含 iam.googleapis.com/modifiedGrantsByRole 特性中的角色,则该函数返回 true。如果它们不相等,则函数会返回 false

    如果 iam.googleapis.com/modifiedGrantsByRole 属性包含默认值 ([]),则该函数返回 true,因为 [] 不包含列表中未包含的任何角色。

要自定义此表达式,请将 roles 替换为主账号允许授予或撤消的角色列表。例如,要仅允许主账号授予或撤消 Pub/Sub Editor(roles/pubsub.editor )和 Pub/Sub Publisher (roles/pubsub.publisher) 角色,请使用值 ['roles/pubsub.editor', 'roles/pubsub.publisher']

允许的角色列表中最多可包含 10 个值。所有这些值必须是字符串常量。

hasOnly() 语句的逻辑运算符

请勿使用 &&|| 运算符在单个条件中联接多个 hasOnly() 语句。如果您这样做,则授予或撤消多个角色的请求可能会失败,即使主账号可以单独授予或撤消这些角色也是如此。

例如,请考虑以下条件:

api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', [])
    .hasOnly(['roles/pubsub.editor']) ||
api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', [])
    .hasOnly(['roles/pubsub.publisher'])

如果请求授予 roles/pubsub.editor 角色或 roles/pubsub.publisher 角色,则此条件的求值结果为 true;但如果请求同时授予 roles/pubsub.editor 角色和 roles/pubsub.publisher 角色,则此条件的求值结果为 false

使用条件角色绑定限制角色授予

要允许主账号仅授予或撤消某些角色,请使用上一部分中的条件表达式来创建条件角色绑定。然后,向资源的允许政策添加条件角色绑定。

  1. 选择用于表示允许主账号为其授予和撤消角色的角色范围的资源:

    • 如果您希望主账号授予和撤消组织中所有资源的特定角色,请选择组织。
    • 如果要允许主账号授予和撤消文件夹中所有资源的特定角色,请选择一个文件夹。
    • 如果您希望主账号授予和撤消项目中所有资源的特定角色,请选择项目。
  2. 选择一个角色,以允许主账号为您选择的资源类型(项目、文件夹或组织)设置允许政策。为了遵循最小权限原则,请选择以下预定义角色之一:

    • 项目:Project IAM 管理员 (roles/resourcemanager.projectIamAdmin)
    • 文件夹:Folder IAM 管理员 (roles/resourcemanager.folderIamAdmin)
    • 组织:组织管理员 (roles/resourcemanager.organizationAdmin)。

    或者,选择包含 resourcemanager.resource-type.setIamPolicyresourcemanager.resource-type.getIamPolicy 权限的自定义角色,其中 resource-typeprojectfolderorganization

  3. 有条件地向主账号授予您所选的项目、文件夹或组织中的角色。

    系统会应用新政策,并且主账号只能修改您允许的角色的绑定。

    控制台

    1. 在 Google Cloud 控制台中,前往 IAM 页面。

      转到 IAM 页面

    2. 确保您的项目、文件夹或组织的名称显示在页面顶部的资源选择器中。资源选择器会显示您当前正在处理的项目、文件夹或组织。

      如果您没有看到资源名称,请点击资源选择器,然后选择您的资源。

    3. 在主账号列表中,找到要授予和撤消角色的主账号,然后点击 按钮。

    4. 修改权限面板中,选择您之前选择的角色。然后在 IAM 条件(可选)下,点击添加 IAM 条件

    5. 修改条件面板中,输入条件的标题和选填性说明。

    6. 点击条件编辑器标签页,并输入您在编写条件表达式以限制角色授权时编写的表达式。此表达式用于限制主账号可以授予或撤消哪些角色。

      例如,以下条件表达式将限制授予和撤消 Pub/Sub Editor (roles/pubsub.editor) 和 Pub/Sub Publisher (roles/pubsub.publisher) 角色的主账号:

      api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly(['roles/pubsub.editor', 'roles/pubsub.publisher'])
      

      警告:请勿在允许的角色列表中包含以下类型的角色:

      • 有权授予和撤消 IAM 角色的角色(即具有以 setIamPolicy 结尾的权限名称的角色)。
      • 受限 IAM 管理员可修改的自定义角色。例如,如果受限 IAM 管理员还具有角色管理员角色 (roles/iam.roleAdmin) 不允许他们授予或撤消项目级层自定义角色。

      可以授予和撤消此类角色的受限 IAM 管理员可以自行授予和撤消所有 IAM 角色。如需了解详情,请参阅编写条件表达式以限制角色授权

    7. 点击保存以应用条件。

    8. 关闭修改条件面板后,点击修改权限面板中的保存以更新允许政策。

    gcloud

    允许政策是使用读取-修改-写入模式设置的。

    首先,读取资源的允许政策

    执行 get-iam-policy 命令。 此命令会获取资源的当前允许政策。

    命令:

    gcloud resource-type get-iam-policy resource-id --format=json > path
    

    替换以下值:

    • resource-type:您要允许主账号授予或撤消角色的资源类型。请使用以下选项之一:projectsresource-manager foldersorganizations
    • resource-id:您的 Google Cloud 项目、文件夹或组织 ID。
    • path:要将允许政策下载到的文件的路径。

    允许政策以 JSON 格式保存,例如:

    {
      "bindings": [
        {
          "members": [
            "user:project-owner@example.com"
          ],
          "role": "roles/owner"
        }
      ],
      "etag": "BwWKmjvelug=",
      "version": 1
    }
    

    接下来,修改允许政策

    如需让主账号仅针对特定角色修改绑定,请添加突出显示的条件角色绑定:

    {
      "bindings": [
        {
          "members": [
            "user:owner@example.com"
          ],
          "role": "roles/owner"
        },
        {
          "members": [
            "principal"
          ],
          "role": "role",
          "condition": {
            "title": "title",
            "description": "description",
            "expression":
              "expression"
          }
        }
      ],
      "etag": "BwWKmjvelug=",
      "version": 3
    }

    替换以下值:

    • principal:将授予或撤消特定角色的主账号。例如 user:my-user@example.com。如需查看每个主账号类型的格式,请参阅 Binding 参考文档
    • role:您在上述步骤中选择的角色。此角色必须包含所选资源类型的 setIamPolicy 权限。
    • title:简要描述条件的字符串。例如 only_pubsub_roles
    • description:可选。条件的其他说明。例如 Only allows granting/revoking the Pub/Sub editor and publisher roles
    • expression:您在编写条件表达式以限制角色授权时编写的表达式。此表达式用于限制主账号可以授予或撤消哪些角色。

      例如,以下条件表达式将限制授予和撤消 Pub/Sub Editor (roles/pubsub.editor) 和 Pub/Sub Publisher (roles/pubsub.publisher) 角色的主账号:

      api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly(['roles/pubsub.editor', 'roles/pubsub.publisher'])
      

      警告:请勿在允许的角色列表中包含以下类型的角色:

      • 有权授予和撤消 IAM 角色的角色(即具有以 setIamPolicy 结尾的权限名称的角色)。
      • 受限 IAM 管理员可修改的自定义角色。例如,如果受限 IAM 管理员还具有角色管理员角色 (roles/iam.roleAdmin) 不允许他们授予或撤消项目级层自定义角色。

      可以授予和撤消此类角色的受限 IAM 管理员可以自行授予和撤消所有 IAM 角色。如需了解详情,请参阅编写条件表达式以限制角色授权

    最后,写入更新后的允许政策

    通过为资源执行 set-iam-policy 命令来设置新允许政策:

    gcloud resource-type set-iam-policy resource-id path
    

    替换以下值:

    • resource-type:您要允许主账号授予或撤消角色的资源类型。请使用以下选项之一:projectsresource-manager foldersorganizations
    • resource-id:您的 Google Cloud 项目、文件夹或组织 ID。
    • path:指向包含更新后的允许政策的文件的路径。

    系统会应用新允许政策,主账号只能修改您允许的角色的绑定。

    REST

    允许政策是使用读取-修改-写入模式设置的。

    首先,读取资源的允许政策

    Resource Manager API 的 getIamPolicy 方法可获取项目、文件夹或组织的允许政策。

    在使用任何请求数据之前,请先进行以下替换:

    • API_VERSION:要使用的 API 版本。对于项目和组织,请使用 v1。对于文件夹,请使用 v2
    • RESOURCE_TYPE:您要管理其政策的资源类型。使用值 projectsfoldersorganizations
    • RESOURCE_ID:您的 Google Cloud 项目、组织或文件夹 ID。 项目 ID 是字母数字字符串,例如 my-project。文件夹和组织 ID 是数字,例如 123456789012
    • POLICY_VERSION:要返回的政策版本。请求应指定最新的政策版本,即政策版本 3。如需了解详情,请参阅在获取政策时指定政策版本

    HTTP 方法和网址:

    POST https://cloudresourcemanager.googleapis.com/API_VERSION/RESOURCE_TYPE/RESOURCE_ID:getIamPolicy

    请求 JSON 正文:

    {
      "options": {
        "requestedPolicyVersion": POLICY_VERSION
      }
    }
    

    如需发送您的请求,请展开以下选项之一:

    响应包含资源的允许政策。例如:

    {
      "version": 1,
      "etag": "BwWKmjvelug=",
      "bindings": [
        {
          "role": "roles/owner",
          "members": [
            "user:owner@example.com"
          ]
        }
      ]
    }
    

    接下来,修改允许政策

    添加条件角色绑定,使主账号只能授予和撤消某些角色。请务必将 version 字段更改为值 3

    {
      "version": 3,
      "etag": "BwWKmjvelug=",
      "bindings": [
        {
          "members": [
            "user:owner@example.com"
          ],
          "role": "roles/owner"
        },
        {
          "members": [
            "PRINCIPAL"
          ],
          "role": "ROLE",
          "condition": {
            "title": "TITLE",
            "description": "DESCRIPTION",
            "expression":
              "EXPRESSION"
          }
        }
      ]
    }
    • PRINCIPAL:将授予或撤消特定角色的主账号。例如 user:my-user@example.com。如需查看每个主账号类型的格式,请参阅 Binding 参考文档
    • ROLE:您在上述步骤中选择的角色。此角色必须包含所选资源类型的 setIamPolicy 权限。
    • TITLE:简要描述条件的字符串。例如 only_pubsub_roles
    • DESCRIPTION:可选。条件的其他说明。例如 Only allows granting/revoking the Pub/Sub editor and publisher roles
    • EXPRESSION:您在编写条件表达式以限制角色授权时编写的表达式。此表达式用于限制主账号可以授予或撤消哪些角色。

      例如,以下条件表达式将限制授予和撤消 Pub/Sub Editor (roles/pubsub.editor) 和 Pub/Sub Publisher (roles/pubsub.publisher) 角色的主账号:

      api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly(['roles/pubsub.editor', 'roles/pubsub.publisher'])
      

      警告:请勿在允许的角色列表中包含以下类型的角色:

      • 有权授予和撤消 IAM 角色的角色(即具有以 setIamPolicy 结尾的权限名称的角色)。
      • 受限 IAM 管理员可修改的自定义角色。例如,如果受限 IAM 管理员还具有角色管理员角色 (roles/iam.roleAdmin) 不允许他们授予或撤消项目级层自定义角色。

      可以授予和撤消此类角色的受限 IAM 管理员可以自行授予和撤消所有 IAM 角色。如需了解详情,请参阅编写条件表达式以限制角色授权

    最后,写入更新后的允许政策

    Resource Manager API 的 setIamPolicy 方法会将请求中的允许政策设置为项目、文件夹或组织的新允许政策。

    在使用任何请求数据之前,请先进行以下替换:

    • API_VERSION:要使用的 API 版本。对于项目和组织,请使用 v1。对于文件夹,请使用 v2
    • RESOURCE_TYPE:您要管理其政策的资源类型。使用值 projectsfoldersorganizations
    • RESOURCE_ID:您的 Google Cloud 项目、组织或文件夹 ID。 项目 ID 是字母数字字符串,例如 my-project。文件夹和组织 ID 是数字,例如 123456789012
    • POLICY:您要设置的政策的 JSON 格式。如需详细了解政策的格式,请参阅政策参考文档

      例如,要设置上一步中显示的政策,请将 POLICY 替换为以下内容:

      {
        "version": 3,
        "etag": "BwWKmjvelug=",
        "bindings": [
          {
            "members": [
              "user:owner@example.com"
            ],
            "role": "roles/owner"
          },
          {
            "members": [
              "principal"
            ],
            "role": "role",
            "condition": {
              "title": "title",
              "description": "description",
              "expression":
                "expression"
            }
          }
        ]
      }
      

    HTTP 方法和网址:

    POST https://cloudresourcemanager.googleapis.com/API_VERSION/RESOURCE_TYPE/RESOURCE_ID:setIamPolicy

    请求 JSON 正文:

    {
      "policy": POLICY
    }
    

    如需发送您的请求,请展开以下选项之一:

    响应包含更新后的允许政策。

后续步骤