拒绝政策

通过 Identity and Access Management (IAM) 拒绝政策,您可以设置关于访问 Google Cloud 资源的安全措施。借助拒绝政策,您可以定义拒绝规则,以防止某些主账号使用特定的权限(无论主账号被授予哪些角色)。

本页面简要介绍了拒绝政策和拒绝规则。如需了解如何创建和更新拒绝政策,请参阅拒绝访问资源

拒绝政策的工作原理

拒绝政策由拒绝规则组成。每条拒绝规则指定以下内容:

  • 一组被权限拒绝的主账号
  • 拒绝主账号使用的权限或主账号无法使用的权限
  • 可选:拒绝权限所必须满足的条件

在主账号被拒绝时,无论它们被授予哪些 IAM 角色,都无法执行需要该权限的任何操作。这是因为 IAM 始终会先检查相关拒绝政策,然后再检查相关允许政策。有关详情,请参阅政策评估

如需指定拒绝政策的应用位置,您可以将其附加到项目、文件夹或组织。将拒绝政策附加到以上某项资源时,政策中的主账号便无法使用指定的权限来访问该资源或资源的任何后代

您可以将多个拒绝政策附加到单个资源。这可让您为不同类型的拒绝规则创建单独的拒绝政策。例如,您可以将与合规性相关的拒绝规则放入一个政策中,然后在其他拒绝规则中使用另一个政策。每个拒绝政策都独立于所有其他拒绝政策进行评估。

每个资源最多可以有 500 个拒绝政策。这些拒绝政策总共可包含 500 个拒绝规则。

政策评估

当主账号尝试访问资源时,IAM 会评估所有相关的允许和拒绝政策,以查看主账号是否有权访问该资源。它会按以下顺序评估政策:

  1. IAM 会检查所有相关的拒绝政策,以查看主账号的权限是否被拒绝。相关的拒绝政策是附加到资源的拒绝政策,以及任何继承的拒绝政策

    如果这些拒绝政策中有任何政策阻止主账号使用所需的权限,则 IAM 会阻止他们访问资源。

    如果没有拒绝政策阻止主账号使用所需的权限,则 IAM 会继续下一步。

  2. IAM 会检查所有相关的允许政策,以查看主账号是否具有所需权限。相关的允许政策是附加到资源的允许政策,以及任何继承的允许政策

    如果主账号具有所需的权限,则 IAM 允许它们访问资源。

    如果主账号没有所需的权限,则 IAM 将阻止它们访问资源。

下图展示了此政策评估流程:

拒绝政策继承

拒绝政策类似于允许政策,通过资源层次结构继承。将拒绝政策附加到项目、文件夹或组织时,该政策也将适用于该项目、文件夹或组织内的所有资源。

例如,如果组织的拒绝政策规定主账号无法使用特定权限,则主账号无法对组织中的任何资源使用该权限。即使该组织中的文件夹和项目具有更宽松的拒绝政策,此规则也适用。

同样,如果项目的拒绝政策表示主账号无法使用特定权限,则主账号无法将该权限用于该项目中的任何资源。即使父级组织和文件夹具有更宽松的拒绝政策,此规则也适用。

拒绝条件

拒绝条件指定应用拒绝规则所必须满足的条件。如果条件的评估结果为 true 或无法评估,则会应用拒绝规则,并且主账号无法使用指定的权限。如果条件的评估结果为 false,则不会应用拒绝规则,并且主账号可以使用指定的权限(如果有)。

拒绝条件与 IAM 条件的结构相同。但是,拒绝条件只能识别资源标记函数

如需了解如何编写条件,请参阅 IAM 条件概览

权限组

某些服务允许您拒绝权限组。权限组是与指定模式匹配的权限集。您可以使用权限组来拒绝相关权限集,例如,您可以拒绝单个服务或资源的所有权限。

拒绝政策中支持的权限列出了受支持的权限组。您不能在任何其他权限名称中使用通配符。

权限组的标识符会将权限名称的一个或多个部分替换为通配符字符 (*)。权限组包含与该模式匹配的所有权限。

通配符可以出现在以下位置:

  • SERVICE_FQDN/RESOURCE.*:拒绝指定资源的所有权限。
  • SERVICE_FQDN/.:拒绝指定服务的所有权限。
  • SERVICE_FQDN/*.VERB:拒绝以指定动词结尾的服务的所有权限。

权限组包含当前和未来与指定模式匹配的所有权限。例如,假设您使用权限组 example.googleapis.com/exampleResource.* 来拒绝用户具有 exampleResource 资源类型的所有权限。如果 example.googleapis.com 添加了针对 exampleResource 资源类型的新权限(例如 example.googleapis.com/exampleResource.newPermission),则系统会自动拒绝用户具有新权限。

拒绝政策的结构

拒绝政策是元数据和拒绝规则的集合。拒绝规则会将一组主账号与一组拒绝主账号使用或主账号无法使用的权限相关联。每条规则还可以指定一个条件,用于确定何时拒绝权限。

例如,以下拒绝政策会阻止所有主账号删除项目,除非主账号是 project-admins@example.com 的成员或要删除的项目具有值为 test 的标记。

{
  "name": "policies/cloudresourcemanager.googleapis.com%2Fprojects%2F253519172624/denypolicies/limit-project-deletion",
  "uid": "06ccd2eb-d2a5-5dd1-a746-eaf4c6g3f816",
  "kind": "DenyPolicy",
  "displayName": "Only project admins can delete projects.",
  "etag": "MTc1MTkzMjY0MjUyMTExODMxMDQ=",
  "createTime": "2021-09-07T23:15:35.258319Z",
  "updateTime": "2021-09-07T23:15:35.258319Z",
  "rules": [
    {
      "denyRule": {
        "deniedPrincipals": [
          "principalSet://goog/public:all"
        ],
        "exceptionPrincipals": [
          "principalSet://goog/group/project-admins@example.com"
        ],
        "deniedPermissions": [
          "cloudresourcemanager.googleapis.com/projects.delete"
        ],
        "denialCondition": {
          "title":  "Only for non-test projects",
          "expression": "!resource.matchTag('12345678/env', 'test')"
        }
      }
    }
  ]
}

以下各部分介绍了拒绝政策的元数据和拒绝规则中的字段。

元数据

拒绝政策包含以下元数据:

  • name:拒绝政策的名称。此名称的格式为 policies/ATTACHMENT_POINT/denypolicies/POLICY_ID,其中 ATTACHMENT_POINT 是拒绝政策所附加到的项目、文件夹或组织,POLICY_ID 是拒绝政策的字母数字形式的 ID。
  • uid:由 Google 分配给拒绝政策的唯一 ID。
  • kind:政策类型。拒绝政策的 kind 始终为 DenyPolicy
  • displayName:可选。简单易懂的拒绝政策名称。
  • etag:政策版本的标识符。为防止更新发生冲突,etag 值必须与存储在 IAM 中的值匹配。如果 etag 值不匹配,则请求将会失败。
  • createTime:拒绝政策的创建时间。
  • updateTime:拒绝政策的上次更新时间。

拒绝规则

每条拒绝规则都可能包含以下字段:

  • deniedPrincipals:被权限拒绝的主账号。您可以列出个别主账号和主账号集。个别主账号类型包括用户账号、服务账号以及员工或工作负载身份池中的单个身份。主账号集包括 Google 群组、Cloud Identity 网域、员工或工作负载身份集以及互联网上的所有用户。

    如需查看有效主账号类型和标识符列表,请参阅 IAM v2 API 主账号标识符

  • exceptionPrincipals:可选。获得拒绝规则的豁免的主账号。即使这些主账号列在 deniedPrincipals 中或属于 deniedPrincipals 中列出的某个组,它们也不会被指定的权限拒绝。

    您可以列出个别主账号和主账号集。个别主账号类型包括用户账号、服务账号以及员工或工作负载身份池中的单个身份。主账号集包括 Google 群组、Cloud Identity 网域、员工或工作负载身份集以及互联网上的所有用户。

    如需查看有效主账号类型和标识符列表,请参阅 IAM v2 API 主账号标识符

  • deniedPermissions:指定的主账号无法使用的权限或者已拒绝其使用的权限。这些权限使用 IAM v2 权限格式,这种格式使用完全限定域名 (FQDN) 来标识服务。格式为 SERVICE_FQDN/RESOURCE.ACTION。Google API 使用网域 *.googleapis.com。例如 iam.googleapis.com/roles.delete

    只能拒绝部分权限。如需查看可拒绝的权限的完整列表,请参阅拒绝政策中支持的权限

    在某些情况下,您还可以使用权限组来拒绝权限集。如需了解详情,请参阅权限组

  • denialConditions:可选。影响拒绝规则应用时间的逻辑表达式。如果条件的评估结果为 true 或无法评估,则权限会被拒绝。如果条件的评估结果为 false,则权限不会被拒绝。如需了解详情,请参阅本页上的拒绝条件

常见使用场景

以下是您可能想要使用拒绝政策的常见场景,以及您可以在每种场景中创建的拒绝规则示例。 如需了解如何创建和更新拒绝政策,请参阅拒绝访问资源

集中管理员权限

您可以使用拒绝政策以仅限一组特定的主账号执行某些类型的管理活动。

例如,假设您希望仅限单个中心团队管理贵组织的自定义角色。为此,您需要创建一个拒绝规则,以拒绝所有用户(管理群组中的用户除外)管理自定义角色所需的权限 (custom-role-admins@example.com):

{
  "deniedPrincipals": [
    "principalSet://goog/public:all"
  ],
  "exceptionPrincipals": [
    "principalSet://goog/group/custom-role-admins@example.com"
  ],
  "deniedPermissions": [
    "iam.googleapis.com/roles.create",
    "iam.googleapis.com/roles.delete",
    "iam.googleapis.com/roles.update",
  ]
}

然后,将此拒绝政策附加到您的组织。

现在,只有 custom-role-admins@example.com 群组的成员才能管理自定义角色,即使其他用户具有所需的权限也是如此。

例如,假设 yuri@example.comtal@example.com 都具有 Organization Role Administrator 角色 (roles/iam.organizationRoleAdmin),但是 yuri@example.comcustom-role-admins@example.com 的成员,而 tal@example.com 不是它的成员。使用此拒绝政策时,只有 yuri@example.com 能够创建、删除和更新角色。

创建授权访问例外

您可以使用拒绝政策来拒绝通过继承获得的权限。借助此功能,您可以选择在资源层次结构中的较高级层授予角色,然后根据需要拒绝该角色对个别较低级层资源的权限。

例如,假设您有一个文件夹 Engineering,其中包含多个项目。您希望为群组 eng@example.com 授予 Service Account Key Admin 角色 (roles/iam.serviceAccountKeyAdmin) 的权限,该角色拥有文件夹中几乎所有项目的权限。但是,您不希望该群组能够在文件夹 example-prod 的某个特定项目中创建和删除服务账号密钥。

您可以创建以下拒绝规则,而不是向每个项目授予 Service Account Key Admin 角色,以下拒绝规则会拒绝将 Service Account Key Admin 角色的创建和删除权限授予 eng@example.com 中的主账号:

{
  "deniedPrincipals": [
    "principalSet://goog/group/eng@example.com"
  ],
  "deniedPermissions": [
    "iam.googleapis.com/serviceAccountKeys.create",
    "iam.googleapis.com/serviceAccountKeys.delete"
  ]
}

然后,将此拒绝规则添加到拒绝政策,并将该政策附加到项目 example-prod

将拒绝政策附加到项目后,您可以为 eng@example.com 授予 Service Account Key Admin 角色,该角色拥有 Engineering 文件夹的访问权限,但不允许群组在 example-prod 中创建或删除服务账号密钥。

然后,eng@example.com 的成员能够在所有项目(example-prod 除外)中创建和删除服务账号密钥。例如,如果 izumi@example.comeng@example.com 的成员,则他们可以为 example-devexample-test 中的服务账号创建和删除密钥,但不能为 example-prod 中的服务账号创建和删除密钥。

但是,假设您实际上希望一部分 eng@example.com 能够在 example-prod 中创建和删除服务账号密钥。此部分由群组 eng-prod@example.com 表示。如需允许 eng-prod@example.com 的成员在 example-prod 中创建和删除服务账号密钥,您可以让群组获得拒绝规则的豁免:

{
  "deniedPrincipals": [
    "principalSet://goog/group/eng@example.com"
  ],
  "exceptionPrincipals": [
    "principalSet://goog/group/eng-prod@example.com"
  ],
  "deniedPermissions": [
    "iam.googleapis.com/serviceAccountKeys.create",
    "iam.googleapis.com/serviceAccountKeys.delete"
  ]
}

使用修改后的拒绝政策时,eng-prod@example.com 的成员可以在所有项目(包括 example-prod)中创建和删除服务账号密钥。例如,如果 charlie@example.comeng-prod@example.com 的成员,则他们可以在 example-devexample-testexample-prod 中创建和删除密钥(即使他们也是 eng@example.com 的成员)。

根据标记阻止访问

标记是一种可以关联到组织、文件夹或项目的键值对。您可以使用拒绝政策根据标记拒绝权限,而无需向每个角色授予添加 IAM 条件。

例如,假设您将您的所有项目标记为 devtestprod。您只希望 project-admins@example.com 的成员能够删除标记为 prod 的项目。

如需解决此问题,请创建一条拒绝规则,用于拒绝除 project-admins@example.com 之外的所有人对标记为 prod 的资源的 cloudresourcemanager.googleapis.com/projects.delete 权限:

{
  "displayName": "Only project admins can delete production projects.",
  "rules": [
    {
      "denyRule": {
        "deniedPrincipals": [
          "principalSet://goog/public:all"
        ],
        "exceptionPrincipals": [
          "principalSet://goog/group/project-admins@example.com"
        ],
        "deniedPermissions": [
          "cloudresourcemanager.googleapis.com/projects.delete"
        ],
        "denialCondition": {
          "title":  "Only for prod projects",
          "expression": "resource.matchTag('12345678/env', 'prod')"
        }
      }
    }
  ]
}

然后,将此拒绝规则添加到拒绝政策,并将该政策附加到您的组织。

由于存在此拒绝规则,因此您可以限制主账号的访问权限,而无需为其角色授予添加条件。您可以改为授予包含 cloudresourcemanager.googleapis.com/projects.delete 权限的主账号角色,并依靠拒绝规则来防止 project-admins@example.com 以外的主账号删除任何标记为 prod 的项目。

例如,假设有 bola@example.comkiran@example.com 这两个用户。这两个用户都具有 Project Deleter 角色 (roles/resourcemanager.projectDeleter)。此外,kiran@example.comproject-admins@example.com 的成员。使用此拒绝政策时,bola@example.com 只能删除带有 devtest 标记的项目。kiran@example.com 可以删除所有项目,无论其标记如何。

后续步骤