了解允许政策

您可以使用附加到资源的允许政策(也称为 Identity and Access Management (IAM) 政策)授予对 Google Cloud 资源的访问权限。每个资源只能附加一项允许政策。允许政策可控制对资源本身以及从允许政策沿用的的任何后代资源的访问权限。

此页面显示 JSON 格式的允许政策。您还可以使用 Google Cloud CLI 检索 YAML 格式的政策。

政策结构

允许政策是角色绑定和元数据的集合。角色绑定指定了应为资源授予的访问权限。它将一个或多个主账号与单个 IAM 角色以及任何用于更改角色授予方式和时间的上下文特定条件进行关联或绑定。。元数据包含有关允许政策的详细信息(例如 etag 和版本),便于政策管理

每个角色绑定可包括以下字段:

  • 一个或多个主账号,也称为成员或身份。主账号有多种类型的,包括用户账号、服务账号、Google 群组和网域。如需查看受支持的主账号类型的完整列表,请参阅主账号标识符
  • 角色是命名的权限集合,提供对 Google Cloud 资源执行操作的权限。
  • 条件,是一种可选逻辑表达式,可根据请求的相关属性(例如其来源或目标资源)进一步限制角色绑定。条件通常用于控制是否根据请求的上下文授予访问权限。

    如果角色绑定包含条件,则称为条件角色绑定。

    某些 Google Cloud 服务不接受允许政策中的条件。如需查看接受条件的服务和资源类型的列表,请参阅接受条件角色绑定的资源类型

对主账号访问权限的更改具有最终一致性。这意味着访问权限更改需要一段时间才能传播到整个系统。如需了解访问权限更改传播的平均时间,请参阅访问权限更改传播

主账号限制

每项允许政策最多可以包含 1500 个主账号。对于此限制而言,IAM 会统计允许政策的角色绑定中每个主账号的所有出现次数,以及允许政策从数据访问审核日志中排除的主账号。而不会去除重复出现在多个绑定中的主账号。例如,如果允许政策仅包含主账号 group:my-group@example.com 的角色绑定,并且此主账号出现在 50 个角色绑定中,则您可以向允许政策中的角色绑定添加另外 1,450 个主账号。

允许政策中最多有 250 个主账号可以是网域和 Google 群组。对于此限制而言,网域和 Google 群组的计数方式如下:

  • 对于网域,IAM 会统计允许政策的角色绑定中每个网域的所有出现次数。它不会删除重复出现在多个角色绑定中的网域。例如,如果允许政策仅包含一个网域 (domain:example.com),并且该网域在允许政策中出现 10 次,则您可以在达到限制之前再添加 240 个网域。
  • 对于 Google 群组,无论每个唯一群组在允许政策中出现多少次,该群组都只统计一次。例如,如果允许政策仅包含一个群组 (group:my-group@example.com),并且该群组在允许政策中出现 10 次,则您可以在达到限制之前再添加 249 个唯一群组。

如果您使用 IAM Conditions,或者为具有异常长的标识符的多个主账号授予角色,则 IAM 可能允许的允许政策中的主账号较少。

政策元数据

允许政策的元数据包括以下字段:

  • etag 字段,用于并发控制并确保以一致的方式更新允许政策。如需了解详情,请参阅本页中的在政策中使用 ETag
  • version 字段,用于指定给定允许政策的架构版本。如需了解详情,请参阅本页中的政策版本

对于组织、文件夹、项目和结算账号,允许政策还可以包含 auditConfig 字段,用于指定为每个服务生成审核日志的活动类型。如需了解如何配置允许政策的这一部分,请参阅配置数据访问审核日志

在政策中使用 ETag

当多个系统尝试同时写入同一个允许政策时,存在这些系统可能会覆盖彼此的更改的风险。存在该风险是因为使用读取-修改-写入模式更新允许政策,这涉及多个操作:

  1. 读取现有允许政策
  2. 修改允许政策
  3. 写入整个允许政策

如果系统 A 读取允许政策,而系统 B 立即写入该政策的更新版本,则系统 A 将不会知道系统 B 所做的更改。当系统 A 写入自己对允许政策的更改时,系统 B 的更改可能会丢失。

为了帮助避免此问题,Identity and Access Management (IAM) 支持通过在允许政策中使用 etag 字段来实现并发控制。每项允许政策都包含一个 etag 字段,每次更新允许政策时,此字段的值都会更改。如果允许政策包含 etag 字段,但没有角色绑定,则该允许政策不会授予任何 IAM 角色。

etag 字段包含一个值,例如 BwUjMhCsNvY=。更新允许政策时,请务必在更新后的允许政策中添加 etag 字段。如果允许政策在检索后被修改,etag 值将会不一致且更新将会失败。对于 REST API,您会收到 HTTP 状态代码 409 Conflict,且响应正文类似于以下内容:

{
  "error": {
    "code": 409,
    "message": "There were concurrent policy changes. Please retry the whole read-modify-write with exponential backoff.",
    "status": "ABORTED"
  }
}

如果您收到此错误,请重试一系列操作:重新读取允许政策、根据需要进行修改,然后写入更新后的允许政策。您应在用于管理允许政策的任何工具中使用指数退避算法自动重试

示例:简单政策

请考虑以下允许政策,它将一个主账号绑定到一个角色:

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

在上例中,jie@example.com 被授予了 Owner 基本角色,但不受任何条件限制。此角色可为 jie@example.com 授予几乎不受限的访问权限。

示例:包含多个角色绑定的政策

请考虑以下允许政策,它包含多个角色绑定。每个绑定授予的角色各不相同:

{
  "bindings": [
    {
      "members": [
        "user:jie@example.com"
      ],
      "role": "roles/resourcemanager.organizationAdmin"
    },
    {
      "members": [
        "user:raha@example.com",
        "user:jie@example.com"
      ],
      "role": "roles/resourcemanager.projectCreator"
    }
  ],
  "etag": "BwUjMhCsNvY=",
  "version": 1
}

在上述示例中,Jie (jie@example.com) 在第一个角色绑定中获得了 Organization Admin 预定义角色 (roles/resourcemanager.organizationAdmin)。此角色包含组织、文件夹和限定项目操作的权限。在第二个角色绑定中,Jie 和 Raha (raha@example.com) 都通过 Project Creator 角色 (roles/resourcemanager.projectCreator) 获得了创建项目的能力。这些角色绑定合在一起,向 Jie 和 Raha 授予了精确的访问权限,而 Jie 被授予了比 Raha 更多的访问权限。

示例:包含条件角色绑定的政策

请考虑以下允许政策,它将主账号绑定到一个预定义角色,并使用条件表达式限制角色绑定:

{
  "bindings": [
    {
      "members": [
        "group:prod-dev@example.com",
        "serviceAccount:prod-dev-example@appspot.gserviceaccount.com"
      ],
      "role": "roles/appengine.deployer",
      "condition": {
          "title": "Expires_July_1_2022",
          "description": "Expires on July 1, 2022",
          "expression":
            "request.time < timestamp('2022-07-01T00:00:00.000Z')"
      }
    }
  ],
  "etag": "BwWKmjvelug=",
  "version": 3
}

在此示例中,version 字段设置为 3,因为允许政策包含条件表达式。允许政策中的角色绑定是有条件的:其将角色授予 Google 群组 prod-dev@example.com 和服务账号 prod-dev-example@appspot.gserviceaccount.com,但仅限于 2022 年 7 月 1 日之前。

如需详细了解每个允许政策版本支持的功能,请参阅本页面上的政策版本

示例:包含条件和无条件角色绑定的政策

请考虑以下允许政策,它包含针对同一角色的条件和无条件角色绑定:

{
  "bindings": [
    {
      "members": [
        "serviceAccount:prod-dev-example@appspot.gserviceaccount.com"
       ],
       "role": "roles/appengine.deployer"
    },
    {
      "members": [
        "group:prod-dev@example.com",
        "serviceAccount:prod-dev-example@appspot.gserviceaccount.com"
      ],
      "role": "roles/appengine.deployer",
      "condition": {
        "title": "Expires_July_1_2022",
        "description": "Expires on July 1, 2022",
        "expression":
          "request.time < timestamp('2022-07-01T00:00:00.000Z')"
      }
    }
  ],
  "etag": "BwWKmjvelug=",
  "version": 3
}

在本示例中,服务账号 serviceAccount:prod-dev-example@appspot.gserviceaccount.com 包含在针对同一角色的两个角色绑定中。第一个角色绑定没有条件。第二个角色绑定具有条件,该条件仅在 2022 年 7 月 1 日前授予角色。

实际上,此允许政策始终会向服务账号授予角色。在 IAM 中,条件角色绑定不会覆盖无条件的角色绑定。如果某主账号已绑定到角色,且角色绑定不包含条件,则此主账号始终具有该角色。将此主账号添加到同一角色的条件角色绑定将不起作用。

相反,Google 群组 group:prod-dev@example.com 仅包含在条件角色绑定中。因此,它仅在 2022 年 7 月 1 日之前具有该角色。

示例:可将角色绑定到已删除主账号的政策

考虑以下允许政策。此允许政策将角色绑定到用户 donald@example.com,而该用户的账号已被删除。因此,该用户的标识符现在具有 deleted: 前缀:

{
  "bindings": [
    {
      "members": [
        "deleted:user:donald@example.com?uid=123456789012345678901"
      ],
      "role": "roles/owner"
    }
  ],
  "etag": "BwUjMhCsNvY=",
  "version": 1
}

如果您创建了一个名为 donald@example.com 的新用户,则已删除的用户的允许政策角色绑定不会应用于新用户。此行为可防止新用户沿用为已删除的用户授予的角色。如果要为新用户授予角色,请将新用户添加到允许政策的角色绑定中,如本页面上的包含已删除的主账号的政策所示。

此外,用户名现在包含前缀 deleted: 和后缀 ?uid=numeric-id,其中 numeric-id 是已删除用户的唯一数字 ID。在本示例中,允许政策显示的是标识符 deleted:user:donald@example.com?uid=123456789012345678901,而不是 user:donald@example.com

服务账号和群组与用户具有相同的行为。如果您删除服务账号或群组,然后查看包含主账号的政策,则已删除的主账号名称的前缀为 deleted:,后缀为 ?uid=numeric-id

默认政策

所有接受允许政策的资源均使用默认允许政策创建。大多数资源的默认允许政策为空。但是,某些资源的默认允许政策自动包含某些角色绑定。例如,当您创建新项目时,该项目的允许政策自动拥有可为您在项目上授予 Owner 角色 (roles/owner) 的角色绑定。

这些角色绑定是由系统创建的,因此用户无需拥有资源的 getIamPolicysetIamPolicy 权限即可创建角色绑定。

如需了解某资源是否使用允许政策创建,请参阅该资源的文档。

政策沿用和资源层次结构

Google Cloud 资源分层整理,其中组织节点是层次结构中的根节点,其次是文件夹(可选),然后是项目。其他资源大部分是在项目之下创建和管理的。除组织以外,每项资源有且仅有一个父项。组织作为层次结构中的根节点,没有父项。如需了解详情,请参阅资源层次结构主题。

在设置允许政策时,请务必考虑资源层次结构。在层次结构中的较高级层(例如在组织级层、文件夹级层或项目级层)设置允许政策时,所授予的访问权限范围包括关联了此允许政策的资源级层及该级层中的所有资源。例如,在组织级层设置的允许政策适用于组织和组织中的所有资源。同样,在项目级层设置的允许政策适用于项目和项目中的所有资源。

“政策沿用”一词描述了允许政策如何应用于资源层次结构相应级层下的资源。“有效政策”一词描述了如何为资源沿用资源层次结构中的所有父级允许政策。它是以下各项的联合:

  • 对资源设置的允许政策
  • 对层次结构中资源的所有祖先资源级层设置的允许政策

每个影响资源的有效允许政策的新角色绑定(沿用自父级资源)都会进行独立评估。如果任何更高级层的角色绑定授予了对请求的访问权限,则会授予针对该资源请求的特定访问权限。

如果任何级层的资源沿用的允许政策引入了新的角色绑定,则访问权限授予范围会扩大。

示例:政策沿用

如需了解允许政策沿用,请考虑这样一个场景:您在资源层次结构中的两个不同级层为用户 Raha 授予两个不同的 IAM 角色。

如需在组织级层为 Raha 授予角色,请在组织中设置以下允许政策

{
  "bindings": [
    {
      "members": [
        "user:raha@example.com"
      ],
      "role": "roles/storage.objectViewer"
    }
  ],
  "etag": "BwUjMhCsNvY=",
  "version": 1
}

此允许政策会为 Raha 授予 Storage Object Viewer 角色 (roles/storage.objectViewer),该角色具有对项目和 Cloud Storage 对象的 getlist 权限。由于您在组织中设置允许政策,因此 Raha 可以将这些权限用于组织中的所有项目和所有 Cloud Storage 对象。

如需在项目级层为 Raha 授予角色,请在项目 myproject-123设置以下允许政策

{
  "bindings": [
    {
      "members": [
        "user:raha@example.com"
      ],
      "role": "roles/storage.objectCreator"
    }
  ],
  "etag": "BwUjMhCsNvY=",
  "version": 1
}

此允许政策会为 Raha 授予 Storage Object Creator 角色 (roles/storage.objectCreator),该角色允许创建 Cloud Storage 对象。由于您在 myproject-123 中设置允许政策,因此 Raha 只能在 myproject-123 中创建 Cloud Storage 对象。

现在有两个角色绑定为 Raha 授予了对 myproject-123 下的目标 Cloud Storage 对象的访问权限,接下来以下允许政策适用:

  • 组织级层的允许政策会授予列出和获取组织下的所有 Cloud Storage 对象的权限。
  • 项目级层的允许政策(针对项目 myproject-123)会授予在该项目内创建对象的权限。

下表总结了 Raha 的有效政策:

在组织级层通过“storage.objectViewer”角色获得的权限 在“myproject-123”级层通过“storage.objectCreator”角色获得的权限 Raha 在“myproject-123”级层的有效授权范围
resourcemanager.projects.get
resourcemanager.projects.list
storage.objects.get
storage.objects.list
resourcemanager.projects.get
resourcemanager.projects.list
storage.objects.create
resourcemanager.projects.get
resourcemanager.projects.list
storage.objects.get
storage.objects.list
storage.objects.create

政策版本

随着时间的推移,IAM 可能会增加将在允许政策架构中大幅添加或更改字段的新功能。为避免破坏依赖于允许政策结构一致性的现有集成,新的允许政策架构版本中引入了此类更改。

如果您是首次与 IAM 集成,我们建议使用目前提供的最新允许政策架构版本。下面我们将探讨不同的可用版本及其各自的用法。 此外,还将介绍如何指定所需的版本并引导您完成一些问题排查方案。

现有的所有允许政策都将 version 字段指定为允许政策元数据的一部分。请参考下面突出显示的部分:

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

此字段指定了允许政策的语法架构版本。允许政策的每个版本都包含可供角色绑定使用的特定语法架构。新版本可能包含不受早期版本支持的较新语法架构的角色绑定。此字段只能用于控制允许政策的语法架构。

有效的政策版本

允许政策可以使用以下允许政策版本:

版本 说明
1 政策的 IAM 语法架构的第一个版本。支持将一个角色绑定至一个或多个主账号。不支持条件角色绑定。
2 留待内部使用。
3 在角色绑定中引入 condition 字段,该字段通过基于上下文和基于特性的规则限制角色绑定。如需了解详情,请参阅 IAM Conditions 概览

在获取政策时指定政策版本

对于 REST API 和客户端库,在获取允许政策时,我们建议您在请求中指定允许政策版本。如果请求指定允许政策版本,则 IAM 会假定调用者知道该允许政策版本中的功能,并且可以正确处理。

如果请求未指定允许政策版本,则 IAM 会假定调用者需要版本 1 允许政策。

在获取允许政策时,IAM 会检查请求中的允许政策版本,或者如果请求未指定版本,则检查默认版本。IAM 还会检查该允许政策中是否存在版本 1 允许政策不支持的字段。它会使用此信息来确定要发送的响应类型:

  • 如果允许政策不包含任何条件,则 IAM 始终会返回版本 1 允许政策,无论请求中的版本号如何。
  • 如果允许政策包含条件,并且调用者请求了版本 3 允许政策,则 IAM 会返回包含这些条件的版本 3 允许政策。如需查看示例,请参阅本页面上的场景 1
  • 如果允许政策包含条件,并且调用者请求了版本 1 允许政策或未指定版本,则 IAM 会返回版本 1 允许政策。

    对于包含条件的角色绑定,IAM 会将字符串 _withcond_ 附加到角色名称,后跟哈希值;例如,roles/iam.serviceAccountAdmin_withcond_2b17cc25d2cd9e2c54d8。条件本身不存在。如需查看示例,请参阅本页面上的场景 2

场景 1:完全支持 IAM Conditions 的政策版本

假设您调用以下 REST API 方法来获取项目的允许政策:

POST https://cloudresourcemanager.googleapis.com/v1/projects/project-id:getIamPolicy

请求正文包含以下文本:

{
  "options": {
    "requestedPolicyVersion": 3
  }
}

响应包含项目的允许政策。如果允许政策至少包含一个条件角色绑定,则其 version 字段会设置为 3

{
  "bindings": [
    {
      "members": [
        "user:user@example.com"
      ],
      "role": "roles/iam.securityReviewer",
      "condition": {
          "title": "Expires_July_1_2022",
          "description": "Expires on July 1, 2022",
          "expression": "request.time < timestamp('2022-07-01T00:00:00.000Z')"
      }
    }
  ],
  "etag": "BwWKmjvelug=",
  "version": 3
}

如果允许政策不包含条件角色绑定,即使请求指定的版本为 3,其 version 字段也会设置为 1

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

场景 2:有限支持 IAM Conditions 的政策版本

假设您调用以下 REST API 方法来获取项目的允许政策:

POST https://cloudresourcemanager.googleapis.com/v1/projects/project-id:getIamPolicy

请求正文为空,它不会指定版本号。因此,IAM 使用默认允许政策版本 1

该允许政策包含条件角色绑定。由于允许政策版本为 1,因此条件不会出现在响应中。为了表示角色绑定使用了条件,IAM 会将字符串 _withcond_ 附加到角色名称,后跟哈希值:

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

在设置政策时指定政策版本

设置允许政策时,我们建议在请求中指定允许政策版本。如果请求指定允许政策版本,则 IAM 会假定调用者知道该允许政策版本中的功能,并且可以正确处理。

如果请求未指定允许政策版本,则 IAM 只接受可以出现在版本 1 允许政策中的字段。作为最佳实践,请勿更改版本 1 允许政策中的条件角色绑定;因为该允许政策不会显示每个角色绑定的条件,您不知道实际授予角色绑定的时间和位置。您应该获取允许政策的版本 3 表示法(这会显示每个角色绑定的条件),并使用该表示法来更新角色绑定。

场景:请求和响应中的政策版本

假设您使用 REST API 来获取允许政策,并在请求中指定版本 3。响应包含以下允许政策,该政策使用版本 3

{
  "bindings": [
    {
      "members": [
        "user:raha@example.com"
      ],
      "role": "roles/storage.admin",
      "condition": {
          "title": "Weekday_access",
          "description": "Monday thru Friday access only in America/Chicago",
          "expression": "request.time.getDayOfWeek('America/Chicago') >= 1 && request.time.getDayOfWeek('America/Chicago') <= 5"
      }
    }
  ],
  "etag": "BwUjMhCsNvY=",
  "version": 3
}

您决定 raha@example.com 整周都应具有 Storage Admin 角色 roles/storage.admin,而不仅仅是在工作日。您可以从角色绑定中移除该条件,然后发送 REST API 请求来设置允许政策;再一次在请求中指定版本 3

{
  "bindings": [
    {
      "members": [
        "user:raha@example.com"
      ],
      "role": "roles/storage.admin"
    }
  ],
  "etag": "BwUjMhCsNvY=",
  "version": 3
}

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

{
  "bindings": [
    {
      "members": [
        "user:raha@example.com"
      ],
      "role": "roles/storage.admin"
    }
  ],
  "etag": "BwWd8I+ZUAQ=",
  "version": 1
}

响应中的允许政策使用版本 1,即使请求指定了版本 3,因为允许政策仅使用版本 1 允许政策支持的字段。

包含已删除主账号的政策

如果允许政策中的角色绑定包含已删除的主账号,并且您为名称相同的新主账号添加了角色绑定,则该角色绑定会始终应用于新主账号。

例如,请考虑此允许政策,其中包含已删除的用户 donald@example.com 和已删除的服务账号 my-service-account@project-id.iam.gserviceaccount.com 的角色绑定。因此,每个主账号的标识符都会具有一个 deleted: 前缀:

{
  "bindings": [
    {
      "members": [
        "deleted:serviceAccount:my-service-account@project-id.iam.gserviceaccount.com?uid=123456789012345678901",
        "deleted:user:donald@example.com?uid=234567890123456789012"
      ],
      "role": "roles/owner"
    }
  ],
  "etag": "BwUjMhCsNvY=",
  "version": 1
}

假设您创建了一个名称也是 donald@example.com 的新用户,并且希望向该新用户授予 Project Creator 角色 (roles/resourcemanager.projectCreator),该角色允许主账号创建 Google Cloud 项目。如需向新用户授予该角色,请更新允许政策,如以下示例所示:

{
  "bindings": [
    {
      "members": [
        "deleted:serviceAccount:my-service-account@project-id.iam.gserviceaccount.com?uid=123456789012345678901",
        "deleted:user:donald@example.com?uid=234567890123456789012"
      ],
      "role": "roles/owner"
    },
    {
      "members": [
        "user:donald@example.com"
      ],
      "role": "roles/resourcemanager.projectCreator"
    }
  ],
  "etag": "BwUjMhCsNvY=",
  "version": 1
}

为了更轻松地审核 IAM 允许政策,您还可以从 Owner 角色的角色绑定中移除已删除的用户:

{
  "bindings": [
    {
      "members": [
        "deleted:serviceAccount:my-service-account@project-id.iam.gserviceaccount.com?uid=123456789012345678901"
      ],
      "role": "roles/owner"
    },
    {
      "members": [
        "user:donald@example.com"
      ],
      "role": "roles/resourcemanager.projectCreator"
    }
  ],
  "etag": "BwUjMhCsNvY=",
  "version": 1
}

政策最佳做法

以下最佳做法适用于拥有众多 Google Cloud 用户的组织:

  • 使用相同的访问配置来管理多个用户账号时,请改用 Google 群组。将每个单独的用户账号添加到群组中,并向群组而非单个用户账号授予预期角色。

  • 在组织级层授予的权限:请仔细考虑哪些主账号在组织级层获得了访问权限。对于大多数组织而言,只有少数特定团队(例如安全和网络团队)应获得资源层次结构中此级层的访问权限。

  • 在文件夹级层授予的权限:请考虑使用文件夹层级来反映组织的运营结构,其中每个父级/子级文件夹均可使用符合业务和运营需求的不同访问权限集进行配置。例如,父级文件夹可能反映了某个部门,其中的一个子级文件夹可能反映资源访问权限和群组操作,另一个子级文件夹可能反映小团队。这两个文件夹都可能包含满足其团队运营需求的项目。以这种方式使用文件夹可以确保访问权限正确分离,同时遵循从父级文件夹和组织沿用的政策。在创建和管理 Google Cloud 资源时,这种做法需要的允许政策维护较少。

  • 在项目级层授予的权限:如有必要,在项目级层授予角色绑定,以遵循最小权限原则。例如,如果主账号需要访问文件夹中 10 个项目中的 3 个项目,您应该分别授予对 3 个项目中的每个项目的访问权限:相比之下,如果您授予了针对文件夹的角色,则主账号将获得他们对其他 7 个项目所不需要的访问权限。

    或者,您可以使用 IAM Conditions 在组织或文件夹级层授予角色,但仅限于部分文件夹或项目的角色。

后续步骤