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

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

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

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

准备工作

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

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

设置访问权限级别

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

IAP 不支持使用作用域政策。访问权限级别必须在组织访问权限政策中设置。如需了解详情,请参阅创建访问权限政策

修改 IAM 政策

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

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

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

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

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

控制台

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

  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 查看者
    • 要创建和管理访问权限级别,请使用 Access Context Manager
  6. 要为主账号添加更多角色,请点击添加其他角色

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

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

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

  1. 转到 IAP 管理页面

    转到 IAP 管理页面

  2. 选中要从中移除主账号 IAM 角色的资源旁的复选框。

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

  4. 点击主账号旁边的移除

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

gcloud

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

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

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

    gcloud iap web get-iam-policy PROJECT_ID > policy.yaml

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

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

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

    bindings:
    ...
      - 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 iap web set-iam-policy --project PROJECT_ID policy.yaml

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

API

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

在执行以下特定于应用的 API 步骤之前,请导出以下变量:

 export PROJECT_NUM=PROJECT_NUMBER
 export IAP_BASE_URL=https://iap.googleapis.com/v1/projects/${PROJECT_NUM}/iap_web
 # Replace POLICY_FILE.JSON with the name of JSON file to use for setIamPolicy
 export JSON_NEW_POLICY=POLICY_FILE.JSON
 

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 "Authentication: Bearer $(gcloud auth print-access-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 "Authentication: Bearer $(gcloud auth print-access-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 "Authentication: Bearer $(gcloud auth print-access-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 "Authentication: Bearer $(gcloud auth print-access-token)" \
         ${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. 前往项目的 Google Cloud 控制台 日志浏览器
    转到“日志”页面
  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 指南。