了解政策

Google Cloud 资源的访问权限控制受 IAM 政策管理。IAM 政策已关联到资源。政策通过政策沿用管理对资源本身以及任何子资源的访问权限。

本主题提供了 IAM 政策的 JSON 示例,不过也支持 YAML。

政策结构

政策是绑定、审核配置和元数据的统称。绑定指定了应如何授予对资源的访问权限。它将一个或多个成员与单个角色以及任何用于更改角色授予方式和时间的上下文特定条件进行关联(绑定)AuditConfig 字段指定了有关应如何审核访问尝试的配置数据。元数据包含政策的其他相关信息(例如 ETag 和版本),便于政策管理。各部分的说明如下:

  • 绑定列表。每个绑定都包含以下字段:
    • 成员也称为身份或主帐号,它可以是用户帐号、服务帐号、Google 群组或网域。
    • 角色是一组命名的权限,可授予对 Google Cloud 资源执行操作的权限。
    • 条件是一种逻辑表达式,可根据请求的特性(例如其来源、目标资源等)进一步限制角色绑定。条件通常用于控制是否根据请求的上下文授予访问权限。
  • AuditConfig 字段,用于配置政策的审核日志记录。
  • 元数据,它包括以下字段:
    • etag 字段,用于并发控制并确保以一致的方式更新政策。
    • version 字段,用于指定给定政策的架构版本。有关 version 字段的用法,请详见政策版本部分。

IAM 政策中的角色绑定是指角色和一系列成员的组合。如果角色绑定还包含条件,则称为条件角色绑定。

在政策中使用 ETag

当多个系统同时尝试写入同一个 IAM 政策时,这些系统可能会覆盖彼此的更改。出现该风险是因为更新 IAM 政策涉及多个操作:

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

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

为了帮助避免此问题,Identity and Access Management (IAM) 支持通过在政策中使用 etag 字段来实现并发控制。每次更新政策时,此字段的值都会更改。

无论何时需要更新政策,都务必在写入更新后的政策时包含 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"
  }
}

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

如需了解如何使用“读取-修改-写入”模式更新政策,请参阅授予、更改和撤消访问权限

示例:简单政策

请思考下列示例政策,它将一名成员绑定到一个角色:

{
  "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:divya@example.com",
        "user:jie@example.com"
      ],
      "role": "roles/resourcemanager.projectCreator"
    }
  ],
  "etag": "BwUjMhCsNvY=",
  "version": 1
}

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

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

设想以下 IAM 政策,它将成员绑定到一个预定义角色,并使用条件表达式限制角色绑定:

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

在本示例中,version 字段设置为 3,因为政策包含条件表达式。政策中的绑定是条件角色绑定;它将角色授予 Google 群组 prod-dev@example.com 和服务帐号 prod-dev-example@appspot.gserviceaccount.com,但在 2020 年 7 月 1 日后失效。

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

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

设想以下 IAM 政策,它包含针对同一角色的条件和无条件角色绑定:

{
  "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_2020",
        "description": "Expires on July 1, 2020",
        "expression":
          "request.time < timestamp('2020-07-01T00:00:00.000Z')"
      }
    }
  ],
  "etag": "BwWKmjvelug=",
  "version": 3
}

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

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

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

示例:可将角色绑定到已删除成员的政策

请参考以下政策示例。此政策可将角色绑定到用户 donald@example.com,而该用户的帐号已被删除:

{
  "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

政策限制

IAM 政策存在以下限制:

  • 在资源层次结构的相应级层支持 IAM 政策的每项 Google Cloud 资源最多可以有一个政策。例如,组织、文件夹、项目或单个资源(Compute Engine 磁盘、映像等)。
  • 每项 IAM 政策最多可以包含 1500 个 members。在这些成员中,最多有 250 个成员可以是 Google 群组。

    IAM 会统计政策绑定中每个成员的所有出现次数。但不会删除重复出现在多个绑定中的成员。例如,如果成员 user:alice@example.com 出现在 50 个绑定中,则该政策的所有绑定中只能再添加 1450 个成员。

  • 一般而言,在调用 setIamPolicy() 或更新 Cloud Console 中的角色绑定后,对政策所作的任何更改都将在 60 秒内生效。但在某些情况下,政策更改可能需要长达 7 分钟才能在整个系统中完全传播。

  • 某些 Google Cloud 服务目前不支持资源级层政策的条件角色绑定,即使资源的名称、类型或 Google Cloud 可以在条件角色绑定中使用也一样。例如,在某些情况下,可以对项目(而不是资源本身)设置条件角色绑定的政策,以限制对服务资源的访问权限。如需了解详情,请参阅 IAM Conditions 特性参考文档

政策沿用和资源层次结构

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

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

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

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

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

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

示例:政策沿用

要了解政策沿用,请参考在组织级层设置的下列示例政策:

组织级层政策

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

Storage Object Viewer 角色 (roles/storage.objectViewer) 包含对项目和 Cloud Storage 对象的 getlist 权限。在组织级层进行设置时,此角色绑定应用于组织中的各个级层,包括所有项目以及这些项目中的所有 Cloud Storage 对象。

为了进一步说明政策沿用,请查看在 myproject-123 级层进一步设置政策时会出现什么情况:

项目级层的政策

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

在上面的示例中,Storage Object Creator 角色 (roles/storage.objectCreator) 授予了 Divya 在 myproject-123 级层创建 Cloud Storage 对象的权限。现在有两个角色绑定向 Divya 授予了在 myproject-123 级层访问目标 Cloud Storage 对象的权限,以下政策适用:

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

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

在组织级层通过“storage.objectViewer”角色获得的权限 在“myproject-123”级层通过“storage.objectCreator”角色获得的权限 Divya 在“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 集成,我们建议使用当前可用的最新架构政策版本。下面我们将探讨不同的可用版本及其各自的用法。此外,还将介绍如何指定所需的版本并引导您完成一些问题排查方案。

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

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

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

有效的政策版本

IAM 政策可以使用以下政策版本:

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

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

对于 REST API 和客户端库,如果您获取 IAM 政策,我们建议您在请求中指定政策版本。如果请求指定政策版本,则 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 方法来获取项目的 IAM 政策:

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

请求正文包含以下文本:

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

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

{
  "bindings": [
    {
      "members": [
        "user:user@example.com"
      ],
      "role": "roles/iam.securityReviewer",
      "condition": {
          "title": "Expires_July_1_2020",
          "description": "Expires on July 1, 2020",
          "expression": "request.time < timestamp('2020-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 方法来获取项目的 IAM 政策:

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 会假定调用者知道该政策版本中的功能,并能正确处理。

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

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

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

{
  "bindings": [
    {
      "members": [
        "user:divya@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
}

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

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

响应中包含更新后的政策:

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

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

政策版本的客户端库支持

Google Cloud 的某些客户端库仅支持版本 1 政策。如果您的客户端库不支持更高版本的政策,则无法使用仅在更高版本中提供的功能。例如,IAM Conditions 需要支持政策版本 3

如果使用版本 1 政策中不提供的 IAM 功能,例如 IAM Conditions,请使用支持该政策版本的客户端库,并在请求中正确设置它。

IAM 的以下 Google API 客户端库支持政策版本 3

语言 支持政策版本 3 的版本
C# Google.Apis >=v1.41.1
Go google-api-go-client >=v0.10.0
Java
Node.js googleapis >=v43.0.0
PHP google/apiclient >=v2.4.0
Python google-api-python-client >=v1.7.11
Ruby google-api-client >=v0.31.0

您可以使用这些客户端库管理针对以下服务的资源的版本 3 IAM 政策:

  • IAM
  • Cloud KMS
  • Cloud Storage
  • Compute Engine
  • Resource Manager

其他客户端库,包括 Google Cloud 客户端库,仅支持版本 1 政策。

政策版本的 gcloud 支持

如果使用 gcloud 工具管理 IAM 政策,请确保您使用的是版本 263.0.0 或更高版本。早期版本仅支持版本 1 政策。

如需检查 gcloud 工具的版本号,请运行 gcloud version。如需更新到最新版本,请运行 gcloud components update

包含已删除成员的政策

如果政策中的绑定包含已删除的成员,并且您为具有相同名称的新成员添加绑定,则该绑定将始终应用于新成员。

例如,请考虑此政策,其中包含已删除用户 donald@example.com 和已删除服务帐号 my-service-account@project-id.iam.gserviceaccount.com 的绑定:

{
  "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 资源时,这种做法需要的政策维护更少。

  • 在项目级层授予的权限:仅根据特定组或单个精确权限的需要在项目级层授予角色绑定。为了便于管理(特别是在具有多个项目时),强烈建议尽可能在文件夹级层设置政策。

后续步骤