使用 Identity-Aware Proxy 设置情境感知访问权限

本指南介绍了如何使用访问权限级别Identity and Access Management (IAM) 条件框架扩展 Identity-Aware Proxy (IAP) 访问权限政策。使用访问权限级别,您可以根据 IP 地址和最终用户设备属性限制对资源的访问。使用 IAM 条件,您可以根据网址主机、路径、日期和时间限制访问权限。

例如,根据政策配置,您的敏感应用可以执行以下操作:

  • 向使用公司网络中的可信公司设备的所有员工授予访问权限。
  • 远程访问群组中使用任何网络中具有安全密码和最新补丁程序级别的可信公司设备的员工授予访问权限。
  • 仅向特权访问群组中网址路径以 /admin 开头的员工授予访问权限。

准备工作

在开始之前,您需要做好以下准备:

  • 拥有一个要向其添加个人或组访问权限的受 IAP 保护的应用。
  • 要向其授予访问权限的用户名或群组名。

设置访问权限级别

要根据 IP 地址最终用户设备属性限制访问权限,您需要创建访问权限级别。如需了解如何创建访问权限级别,请参阅 Access Context Manager 指南。IAP 会使用访问权限级别名称将访问权限级别与受 IAP 保护的应用关联。

创建服务帐号

要使用访问权限级别并使用 API 更新 IAM 政策,您需要为项目提供一个经过身份验证的服务帐号。

  1. 在部署了您的应用的项目中,创建一个新的服务帐号
  2. 通过使用 gcloud auth activate-service-account 对新服务帐号进行身份验证。

下载凭据文件

您必须下载新服务帐号的 JSON 凭据文件,才能使用 API 更新 IAM 政策。要下载 JSON 凭据文件,请执行以下操作:

  1. 转到“服务帐号”页面
    转到“服务帐号”页面

  2. 点击您的服务帐号的电子邮件地址。

  3. 点击修改

  4. 点击创建密钥

  5. 选择 JSON 作为密钥类型。

  6. 点击创建并关闭出现的确认窗口,以创建新的密钥。

您的 JSON 凭据文件现已下载完毕。

修改 IAM 政策

受 IAP 保护的应用具有将 IAP 角色绑定到该应用的 IAM 政策。

向 IAM 政策添加 IAM 条件绑定后,您可以根据请求属性进一步限制对资源的访问。具体请求属性如下:

  • 访问权限级别
  • 网址主机/路径
  • 日期/时间

请注意,与 IAM 条件绑定中指定的 request.hostrequest.path 不同,请求值必须准确无误。例如,如果您限制对以 /internal admin 开头的路径的访问,转到 /internal%20admin 可以绕过此限制。如需详细了解主机名和路径条件,请参阅使用主机名和路径条件

要在您的 IAM 政策中添加和修改条件绑定,请按照下述流程操作。

控制台

如需使用 Cloud Console 添加条件绑定,请执行以下操作:

  1. 转到 IAP 管理页面

    转到 IAP 管理页面

  2. 选中要更新 IAM 权限的资源旁的复选框。

  3. 在右侧的信息面板上,点击添加成员

  4. 新成员框中,输入要为其分配角色的成员。

  5. 选择角色下拉列表中,选择 IAP-secured Web App User 角色,并指定成员需要满足什么访问权限级别条件才可以访问资源。

    • 要指定现有访问权限级别,请从访问权限级别下拉列表中进行选择。要查看现有访问权限级别,您需要选择 IAP-secured Web App User 角色,并且具备组织级权限。您必须拥有以下角色之一:
      • Access Context Manager Admin
      • Access Context Manager 编辑者
      • Access Context Manager Reader
    • 如需创建和管理访问权限级别,请使用 Access Context Manager
  6. 要为成员添加更多角色,请点击添加其他角色

  7. 添加完角色后,点击保存

    现在,您已经为资源添加了一个条件绑定。

如需移除条件绑定,请执行以下操作:

  1. 转到 IAP 管理页面

    转到 IAP 管理页面

  2. 选中要从中移除成员 IAM 角色的资源旁的复选框。

  3. 在右侧信息面板角色/成员下方,点击要为该成员移除的角色。

  4. 点击该成员旁边的移除

  5. 在显示的移除此成员的角色对话框中,点击移除。如需在选定资源上移除该成员的所有非继承角色,请选中相应复选框,然后点击移除

gcloud

目前,您只能使用 gcloud 工具设置项目级条件绑定。

如需设置条件绑定,请按照以下流程修改项目的 policy.yaml 文件:

  1. 使用以下 gcloud 命令打开应用的 IAM 政策:

    gcloud projects get-iam-policy PROJECT_ID > policy.yaml

  2. 修改 policy.yaml 文件以指定以下内容:

    • 要应用 IAM 条件的用户和组。
    • iap.httpsResourceAccessor 角色会授予他们访问资源的权限。
    • IAM 条件。

      以下代码段展示了仅指定了一个属性的 IAM 条件。如果用户和群组符合 ACCESS_LEVEL_NAME 访问权限级别要求,并且资源网址路径以 / 开头,此条件即会向其授予相应访问权限。

      ...
      - members:
      - group:EXAMPLE_GROUP@GOOGLE.COM
      - user:EXAMPLE_USER@GOOGLE.COM
      role: roles/iap.httpsResourceAccessor
      condition:
          expression: "accessPolicies/ORGANIZATION_NUMBER/accessLevels/ACCESS_LEVEL_NAME" in
                       request.auth.access_levels && request.path.startsWith("/")
          title: CONDITION_TITLE
      ...

  3. 使用 set-iam-policy 命令将政策绑定到应用。

    gcloud projects set-iam-policy PROJECT_ID policy.yaml

您的 IAM 政策现已包含条件绑定。

API

如需修改应用的 policy.json 文件,请根据应用类型按照以下相应流程操作。如需详细了解如何使用 IAM API 管理访问权限政策,请参阅管理对受 IAP 保护的资源的访问权限

在执行以下应用专用的 API 步骤之前,请先完成下述操作:

  1. 根据您的服务帐号下载凭据文件
  2. 导出以下变量。

    export PROJECT_NUM=PROJECT_NUMBER
    export IAP_BASE_URL=https://iap.googleapis.com/v1beta1/projects/${PROJECT_NUMBER}/iap_web
    # Replace with the path to your local service account's downloaded JSON file
    export JSON_CREDS=EXAMPLE.IAM.GSERVICEACCOUNT.COM.JSON
    # Replace POLICY_FILE.JSON with the name of JSON file to use for setIamPolicy
    export JSON_NEW_POLICY=POLICY_FILE.JSON
    

  3. 运行以下命令,以使用 Oauth2l 将服务帐号凭据 JSON 文件转换为 OAuth 访问令牌。

    oauth2l header --json ${JSON_CREDS} cloud-platform

  4. 如果这是您第一次运行上述命令,请在系统提示时执行以下操作:

    1. 点击显示的链接并复制代码,以获取验证码。
    2. 将验证码粘贴到您的应用提示中。
    3. 复制返回的不记名令牌。
    4. 导出分配有返回的不记名令牌的新变量。
      export CLOUD_OAUTH_TOKEN=AUTHORIZATION_BEARER_TOKEN
  5. 如果您之前运行过此命令,请导出以下变量。

    export CLOUD_OAUTH_TOKEN ="$(oauth2l header --json ${JSON_CREDS} cloud-platform)"

App Engine

  1. 导出以下 App Engine 变量:

    # The APP_ID is usually the project ID
    export GAE_APP_ID=APP_ID
    export GAE_BASE_URL=${IAP_BASE_URL}/appengine-${GAE_APP_ID}

  2. 使用 getIamPolicy 方法获取 App Engine 应用的 IAM 政策。最后的空数据位将 curl 请求转换为 POST,而不是 GET。

    curl -i -H "${CLOUD_OAUTH_TOKEN}" ${GAE_BASE_URL}/:getIamPolicy \
         -d ''
    

  3. 将 IAM 条件绑定添加到 IAM 政策 JSON 文件。以下是经过修改的 policy.json 文件的示例,该文件会将 iap.httpsResourceAccessor 角色绑定到两个用户,并为他们授予对受 IAP 保护的资源的访问权限。只有在符合 ACCESS_LEVEL_NAME 访问权限级别要求,并且资源网址路径以 / 开头时,添加 IAM 条件才会向这些用户授予对资源的访问权限。每个绑定只能有一个条件。

    policy.json 文件示例

    {
    "policy": {
    "bindings": [
    {
      "role": "roles/iap.httpsResourceAccessor",
      "members": [
          "group:EXAMPLE_GROUP@GOOGLE.COM",
          "user:EXAMPLE_USER@GOOGLE.COM"
      ],
      "condition": {
        "expression": ""accessPolicies/ORGANIZATION_NUMBER/accessLevels/ACCESS_LEVEL_NAME" in request.auth.access_levels && request.path.startsWith("/")",
        "title": "CONDITION_NAME"
      }
    }
    ]
    }
    }

  4. 使用 setIamPolicy 方法设置新的 policy.json 文件。

    curl -i -H "${CLOUD_OAUTH_TOKEN}" ${GAE_BASE_URL}:setIamPolicy \
         -d @${JSON_NEW_POLICY}

App Engine 服务和版本

您还可以更新 App Engine 服务、所有版本或特定服务版本的 IAM 政策。要更新特定服务版本的 Cloud IAM 政策,请执行以下操作:

  1. 导出以下附加变量。
    export GAE_SERVICE=SERVICE_NAME
    export GAE_VERSION=VERSION_NAME
    
  2. 更新导出的 GAE_BASE_URL 变量。
    export GAE_BASE_URL=${IAP_BASE_URL}/appengine-${GAE_APP_ID}/services/${GAE_SERVICE}/versions/${GAE_VERSION}
  3. 使用上面显示的 getIamPolicysetIamPolicy 命令获取并设置版本的 IAM 政策。

GKE 和 Compute Engine

  1. 导出后端服务的项目 ID。

    export BACKEND_SERVICE_NAME=BACKEND_SERVICE_NAME

  2. 使用 getIamPolicy 方法获取 Compute Engine 应用的 IAM 政策。最后的空数据位将 curl 请求转换为 POST,而不是 GET。

    curl -i -H "${CLOUD_OAUTH_TOKEN}" ${IAP_BASE_URL}/compute/services/${BACKEND_SERVICE_NAME}:getIamPolicy \
         -d ''

  3. 将 IAM 条件绑定添加到 IAM 政策 JSON 文件。以下是经过修改的 policy.json 文件的示例,该文件会将 iap.httpsResourceAccessor 角色绑定到两个用户,并为他们授予对受 IAP 保护的资源的访问权限。只有在符合 ACCESS_LEVEL_NAME 访问权限级别要求,并且资源网址路径以 / 开头时,添加 IAM 条件才会向这些用户授予对资源的访问权限。每个绑定只能有一个条件。


    policy.json 文件示例

    {
    "policy": {
    "bindings": [
    {
    "role": "roles/iap.httpsResourceAccessor",
    "members": [
      "group":EXAMPLE_GROUP@GOOGLE.COM,
      "user:EXAMPLE_USER@GOOGLE.COM"
    ],
    "condition": {
      "expression": ""accessPolicies/ORGANIZATION_NUMBER/accessLevels/ACCESS_LEVEL_NAME" in request.auth.access_levels && request.path.startsWith("/")",
      "title": "CONDITION_NAME"
    }
    }
    ]
    }
    }

  4. 使用 setIamPolicy 方法设置新的 policy.json 文件。

    curl -i -H "Content-Type:application/json" \
         -H "$(oauth2l header --json ${JSON_CREDS} cloud-platform)" \
         ${IAP_BASE_URL}/compute/services/${BACKEND_SERVICE_NAME}:setIamPolicy \
         -d @${JSON_NEW_POLICY}

使用主机名和路径条件

对您的应用的访问可以通过请求网址的主机名和路径进行保护。例如,如果网址路径以 /admin 开头,则 request.path.startsWith IAM 条件只能用于向特权访问组中的员工授予访问权限。

如需详细了解如何使用主机名和路径条件,请参阅请求属性

字符串规范化

网址具有主机名和路径。例如,网址 https://sheets.google.com/create?query=param 的主机名为 sheets.google.com,路径为 /create

后端可以以不同方式解读主机名和路径。 为了消除歧义,IAP 在检查政策时会将主机名和路径字符串规范化。

如果请求具有非规范化路径,则 IAP 会执行两次政策检查。如果非规范化路径通过政策检查,则 IAP 会将路径规范化,然后执行第二次政策检查。如果非规范化路径和规范化路径都通过政策检查,则授予访问权限。

例如,如果请求具有路径 /internal;some_param/admin,则 IAP 首先对非规范化路径 (/internal) 执行政策检查。如果通过,则 IAP 会对规范化路径 (/internal/admin) 执行第二次政策检查。

主机名

主机名通过以下方式规范化:

  • 移除结尾的点
  • 将字符转为小写
  • 转换为 ASCII

包含非 ASCII 字符的主机名会按照国际化域名编码 (punycode) 进一步规范化。您需要对主机名字符串进行国际化域名编码才能匹配。

如需对主机名字符串进行国际化域名编码,请使用转换器,例如 Punycoder

下面是一些规范化主机名的示例:

  • FOO.com 已规范化为 foo.com
  • café.fr 已规范化为 xn--caf-dma.fr

路径

路径通过以下方式规范化:

  • 移除路径参数
  • 解析相对于其绝对对等项的路径

路径参数包含从 ; 到下一个 / 或路径末尾之间的所有字符。

在路径部分开头包含 ..; 的请求都会被视为无效。例如,/..;bar//bar/..;/ 会返回 HTTP 400: Bad Request 错误。

下面是一些规范化路径的示例:

  • /internal;some_param/admin 已规范化为 /internal/admin
  • /a/../b 已规范化为 /b
  • /bar;param1/baz;baz;param2 已规范化为 /bar/baz

子网域结尾

通过 request.host.endsWith("google.com") 设置的政策将与 sub_domain.google.comtestgoogle.com 都匹配。如果您的目标是将政策限于以 google.com 结尾的所有子网域,请将政策设置为 request.host.endsWith(".google.com")

请注意,如果将政策设置为 request.host.endsWith(".google.com"),则将与 sub_domain.google.com 匹配,但额外的 . 导致不与 google.com 匹配。

Cloud Audit Logs 和访问权限级别

为受 IAP 保护的项目启用 Cloud Audit Logs 使您能够查看已获授权和未获授权的访问请求。如需查看请求及请求者符合的所有访问权限级别,请按照以下流程操作:

  1. 转到项目的 Cloud Console“日志”页面
    转到“日志”页面
  2. 资源选择器下拉列表中,选择一个资源。 受 IAP 保护的 HTTPS 资源位于 GAE 应用GCE 后端服务下。受 IAP 保护的 SSH 和 TCP 资源在 GCE 虚拟机实例下。
  3. 日志类型下拉列表中,选择 data_access
    • 只有在为 IAP 启用 Cloud Audit Logs 后已有流量流向您的资源的情况下,data_access 日志类型才会显示。
  4. 点击以展开要查看的访问所对应的日期和时间。
    • 已获授权的访问带有一个蓝色 i 图标。
    • 未经授权的访问带有一个橙色 !! 图标。
  5. 点击展开相关部分,直到看到 protoPayload > requestMetadata > requestAttributes > auth > accessLevels,以便查看请求者符合的访问权限级别。

请注意,查看某一请求时,您可以看到用户符合的所有访问权限级别,包括该访问并不需要的访问权限级别。查看未经授权的请求时,您无法了解用户不符合的访问权限级别。要确定该信息,需要将资源上的条件与请求中提供的访问权限级别进行对比。

如需详细了解日志,请参阅 Cloud Audit Logs 指南。