1. 简介
在此 Codelab 中,您将学习如何使用 VPC Service Controls 保护 BigQuery API。此 Codelab 一开始便没有受服务边界保护的 API 服务,该服务允许对公共数据集运行查询,并将结果保存在项目表中。该查询在一个项目中运行,表(保存结果的位置)在另一个项目中创建,这模拟了一种设置,在这种设置下,数据可以存储在一个项目中,但需要使用其他项目进行访问。
接下来,我们将引入一个服务边界来保护数据项目。您将学习如何使用入站规则和出站规则解决观察到的违规问题,以及如何添加访问权限级别以使用内部 IP 地址限制访问权限。此 Codelab 的目标是:
- 了解如何使用入站规则和出站规则分别解决入站和出站违规问题。
- 了解发生特定违规问题的原因。
- 分析已应用的违规问题修复的范围。
- 通过利用相应选项(使用访问权限级别允许来自 VPC 网络中内部 IP 地址的流量)来修改修复(入站 / 出站规则),以更改其范围。
2. 资源设置和要求
准备工作
在此 Codelab 中,我们假定您已经知道以下内容:
- 运行 BigQuery 查询的基础知识:您可以参阅此 Codelab,了解如何在 BigQuery 中查询维基百科数据集
- 如何创建和管理文件夹
- 如何在文件夹中创建项目或移动文件夹中的现有项目
- 如何创建分区访问权限政策
- 如何创建和配置服务边界
- 如何在日志中查找违反安全政策的行为
设置
我们的初始设置设计如下:
- Google Cloud 组织。
- 组织下的文件夹。在此 Codelab 中,我们将其命名为
codelab-folder
。 - 两个 Google Cloud 项目置于同一文件夹
codelab-folder
下。在此 Codelab 中,我们将其称为project-1
和project-2
- 如果您还没有文件夹和已创建的项目,请在 Google Cloud 控制台中的组织下创建一个文件夹,然后在已创建的文件夹下创建两个新项目。
- 所需的权限:
- 用于管理文件夹的 IAM 角色:在文件夹级别分配
- 用于管理项目的 IAM 角色:在项目级分配
- 配置 VPC Service Controls 所需的 IAM 角色:在组织级别分配
- 用于管理 BigQuery 的 IAM 角色:在项目级分配
- 用于管理 Compute Engine 实例的 IAM 角色:在项目级分配
- 两个项目(
project-2
和project-1
)的结算账号。
创建常规服务边界
在此 Codelab 中,我们将使用保护 project-1
的常规服务边界。
- 创建常规边界
perimeter-1
,并添加project-1
。
创建 Compute Engine VM
在此 Codelab 中,我们将在 project-2
(位于 us-central1
)中使用 1 个 Compute Engine 实例,并使用名为 default
的默认 VPC 网络。
- 您可以参阅相关文档,了解如何通过公共映像创建 Compute Engine 实例。
费用
您需要在 Google Cloud 控制台中启用结算功能,才能使用云资源/API。我们建议您关停已使用的资源,以免产生超出此 Codelab 范围的结算费用。Google Cloud 新用户有资格加入 300 美元的免费试用计划。
产生费用的资源是 BigQuery 和 Compute Engine 实例。您可以使用 BigQuery 价格计算器和 Compute Engine 价格计算器来估算费用。
3. 访问 BigQuery 时不受 VPC Service Controls 限制
在 project-1
中查询公共数据集并保存结果
- 通过访问 BigQuery Studio 页面,访问
project-2
和project-1
,以验证您是否能够访问 BigQuery API。您应该能够做到这一点,因为即使project-1
位于服务边界内,该边界尚未保护任何服务。 - 从
project-2
运行以下查询,以查询公共数据集。
SELECT name, SUM(number) AS total
FROM `bigquery-public-data.usa_names.usa_1910_2013`
GROUP BY name
ORDER BY total DESC
LIMIT 10;
对公共数据集运行查询后(仍在 project-2
中):
- 点击保存结果,然后选择 BigQuery 表。(请参见下面的屏幕截图)。
- 选择
project-1
作为目标项目。 - 将该数据集命名为
codelab_dataset
。(除非使用现有数据集,否则请选择新建数据集)。 - 将表命名为:
codelab-table
。 - 点击保存。
从 project-2
执行查询后,公共数据集数据已成功存储在 project-1
中。
从 project-2
保存在 project-1
中的查询数据集
在 BigQuery Studio 中保留 project-2
的同时,运行以下查询以从中选择数据:
- 项目:
project-1
- 数据集:
codelab_dataset
- 表:
codelab-table
SELECT name, total
FROM `project-1.codelab_dataset.codelab-table`
ORDER BY total DESC
LIMIT 10;
查询应成功运行,因为 project-2
和 project-1
均未限制使用 BigQuery。只要用户具有适当的 IAM 权限,就可以随时随地访问 BigQuery。
此图说明了主账号查询 BigQuery 数据集的过程。每个 BigQuery 查询都会启动一个 BigQuery 作业,然后该作业会执行实际操作(在本例中为检索数据)。当从公共数据集和单独的 Google Cloud 项目查询时,展示通过 Compute Engine 实例和互联网具有主账号访问权限。查询数据的过程 (
GetData
) 已成功完成,没有被 VPC Service Controls 阻止。
4. 在源数据集项目中保护 BigQuery API
修改边界 perimeter-1
的配置,并限制 BigQuery API 服务并将受保护的资源设为 project-1
。
验证服务边界的强制执行情况
在 BigQuery Studio 中,像上一步一样,通过 project-2
运行以下查询:
SELECT name, total
FROM `project-1.codelab_dataset.codelab-table`
ORDER BY total DESC
LIMIT 10;
将发生 VPC Service Controls RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER
违规行为
违规行为审核日志将位于 project-1
中,因为这是发生跨越边界的违规行为。您可以使用观察到的 vpcServiceControlsUniqueId
(将 VPC_SC_DENIAL_UNIQUE_ID
替换为观察到的唯一 ID)过滤日志。
severity=ERROR
resource.type="audited_resource"
protoPayload.metadata.@type="type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
protoPayload.metadata.vpcServiceControlsUniqueId="[*VPC_SC_DENIAL_UNIQUE_ID*]"
违规行为是存在以下行为的egressViolations
:
principalEmail
:[运行查询的用户账号]callerIp
:[运行查询的用户代理的 IP 地址]
"egressViolations": [
{
"targetResource": "projects/project-2",
"sourceType": "Resource",
"source": "projects/project-1",
"servicePerimeter": "accessPolicies/REDACTED/servicePerimeters/perimeter-1",
"targetResourcePermissions": [ "bigquery.jobs.create"]
} ],
5. 解决违规问题以创建 BigQuery 作业
此图说明了主账号从
project-2
针对 project-1
中的数据集运行查询。由于服务边界 perimeter-1
保护了 BigQuery API,通过运行查询的项目 (project-2
) 中的数据集项目 (project-1
) 创建 BigQuery 作业的操作将失败,并且存在 VPC Service Controls 出站流量违规。有了边界后,任何 BigQuery API 请求都不能从 project-1
向边界外发起,也不能在边界外向受保护的项目发起;除非得到服务边界配置允许
根据以下信息创建出站流量规则,即可解决出站流量违规问题:
- 来源 (FROM):即用户电子邮件地址和上下文(如调用方 IP 地址、设备状态、位置等)
- 目的地 (TO):即目标资源、服务和方法或权限。
如需解决观察到的出站流量违规问题,请创建一条出站流量规则,以允许在 BigQuery 服务上运行查询 (user@example.com
) 的用户账号和 bigquery.jobs.create
方法/ 权限将流量传输到 targetResource (project-2
)。
已配置的出站规则的预期行为:
- 发件人 |身份:只有指定的身份
user@example.com
可以跨越边界。 - 收件人 |projects:仅当目标是指定的项目
project-2
时,指定的身份才能跨边界边界。 - 收件人 |服务:仅当 API 调用针对的是指定服务和方法时,指定的身份才能向指定项目发起边界外的流量。否则,例如,如果他们尝试受服务边界保护的其他服务,操作将被阻止,因为不允许其他服务。
测试修复:出站规则
出站规则设置完毕后,运行相同的查询。
SELECT name, total
FROM `project-1.codelab_dataset.codelab-table`
ORDER BY total DESC
LIMIT 10;
系统将再次发生违规行为,这次是违反 NO_MATCHING_ACCESS_LEVEL
入站流量政策。在目标项目和方法方面,新的违规行为与第一种不同。
新的违规行为是
principalEmail
:[运行查询的用户账号]callerIp
:[运行查询的用户代理的 IP 地址]
ingressViolations: [
0: {
servicePerimeter: "accessPolicies/REDACTED/servicePerimeters/perimeter-1"
targetResource: "projects/project-1"
targetResourcePermissions: [0: "bigquery.tables.getData"]}
]
bigquery.tables.getData
方法的违规行为是由于 BigQuery 作业发起的 API 调用尝试从 BigQuery 表获取数据的。
6. 解决违规问题以获取 BigQuery 表数据
入站规则修复了入站流量违规问题,同时精确控制允许谁跨越服务边界以及允许的访问上下文,例如来源/ 目标项目及其可以访问的 API 方法。
入站流量违规问题通过配置了如下的入站流量规则加以解决:
- 来源 (FROM):即用户电子邮件地址和上下文(如调用方 IP 地址、设备状态、位置等)
- 目的地 (TO):即目标资源、服务和方法或权限。
该入站规则将允许指定用户以指定服务和方法向project-1
传入的流量。
已配置的入站流量规则的预期行为:
- 发件人 |身份:只有指定的身份
user@example.com
可以跨越边界。 - 收件人 |projects:仅当目标为指定的项目
project-1
时,指定的身份才能跨边界边界。 - 收件人 |服务:仅当 API 调用针对的是 BigQuery API 和指定方法
bigquery.tables.getData
时,指定的身份才能在边界内发起流量。
因此,执行相同查询的操作应能正常运行,而不会出现 VPC Service Controls 违规行为。
我们已成功限制 project-1
中的 BigQuery API,使其只能由 user@example.com
使用,而不能由 user2@example.com
使用。
此图说明了两个不同的主账号如何尝试查询同一数据集。VPC Service Controls 拒绝
user2@example.com
(蓝色虚线)访问,因为它们不允许通过服务边界配置从或向 project-1
运行 BigQuery 操作。user@example.com
(绿色实线)进行的访问已成功,因为 VPC Service Controls 配置允许它们执行从 project-1
到 project-1
的操作。
7. 根据内部 IP 地址限制服务边界允许的流量
当前配置使指定用户能够从任意位置在 project-1
中对 BigQuery 运行查询;在互联网的任何位置,前提是他们拥有查询数据的 IAM 权限,并且只要他们使用自己的账号。从安全角度来看,这意味着如果账号被盗用,获得该账号访问权限的任何个人都可以访问 BigQuery 数据,而不会受到任何额外限制。
通过利用入站和出站规则中的访问权限级别来指定用户情境,可以实施进一步的限制。例如,您可以允许基于来源 IP 的访问权限,并结合先前配置的入站规则以调用方身份授予访问权限。通过来源 IP 访问这两个公共 IP CIDR 范围都是可行的,前提是用户客户端已分配有公共 IP;如果用户客户端从 Google Cloud 项目运行,则可以使用内部 IP 地址访问。
使用内部 IP 地址访问条件创建访问权限级别
在同一范围化访问权限政策文件夹下,打开 Access Context Manager 页面以创建访问权限级别。
- 在 Access Context Manager 页面上,选择创建访问权限级别。
- 在“新建访问权限级别”窗格中,执行以下操作:
- 提供标题:您可以使用
codelab-al
。 - 在“条件”部分,点击 IP 子网。
- 选择专用 IP 标签页,然后点击选择 VPC 网络。
- 在添加 VPC 网络窗格中,您可以浏览并找到
default
网络,也可以手动输入完整网络名称(格式为//compute.googleapis.com/projects/project-2/global/networks/default
)。 - 点击添加 VPC 网络。
- 点击选择 IP 子网。
- 选择虚拟机实例所在的区域。在此 Codelab 中,网址是
us-central1
。 - 点击保存。
- 提供标题:您可以使用
我们创建了一个访问权限级别,但仍未对任何边界或入站/出站政策强制执行该访问权限级别。
向入站规则添加访问权限级别
为了强制也根据访问权限级别验证入站流量规则允许的用户,您必须在入站流量规则中配置访问权限级别。授予查询数据访问权限的入站流量规则位于 perimeter-1
中。更改入站规则,将来源定义为访问权限级别 codelab-al
。
测试新配置
在 Ingress 规则中添加访问权限级别后,除非从 VPC 网络 default
中的客户端针对项目 project-2
执行同一 BigQuery 查询,否则此查询将失败。如需验证此行为,请在端点设备连接到互联网的情况下通过 Google Cloud 控制台执行查询。查询将失败终止,并出现入站流量违规的迹象。
可以从位于 project-2
的 VPC 网络 default
运行同一查询。同样,使用 VPC 网络 default
从位于 project-2
的 Compute Engine 实例执行相同的 BigQuery 查询也会失败。这是因为入站流量规则仍配置为仅允许主账号 user@example.com
。但是,虚拟机使用的是 Compute Engine 默认服务账号。
如需从 project-2
中的 Compute Engine 实例成功运行同一命令,请确保:
- 虚拟机具有使用 BigQuery API 的访问权限范围。为此,您可以选择允许所有 Cloud API 的全面访问权限作为虚拟机访问权限范围。
- 附加到虚拟机的服务账号需要拥有 IAM 权限才能执行以下操作:
- 在“
project-2
”中创建 BigQuery 作业 - 从位于
project-1
的 BigQuery 表中获取 BigQuery 数据
- 在“
- 入站和出站规则需要允许使用默认的 Compute Engine 服务账号。
现在,我们需要在入站规则(允许从 BigQuery 表获取数据)和出站规则(允许创建 BigQuery 作业)中添加 Compute Engine 默认服务账号。
从 default
VPC 网络的 project-2
中的 Compute Engine 实例,运行以下 bq query 命令:
bq query --nouse_legacy_sql \
'SELECT name, total
FROM `project-1.codelab_dataset.codelab-table`
ORDER BY total DESC
LIMIT 10;'
根据当前配置,只有在以下情况下,BigQuery 命令才会成功运行:
- 使用
project-2
中的默认 VPC 网络在虚拟机上运行,以及 - 位于指定的
us-central1
区域(IP 子网),并且 - 使用服务边界中配置的默认 Compute Engine 服务账号运行。
如果从其他位置运行 BigQuery 命令查询,将会失败,包括:
- 如果在使用
project-2
中的默认 VPC 网络但位于与访问权限级别中添加的子网不同的区域的虚拟机上运行,或者 - 如果由用户
user@example.com
通过互联网上的用户客户端运行。
此图展示了同一主账号
user@example.com
从互联网和 Compute Engine 实例这两个不同位置发起的访问。VPC Service Controls 禁止直接从互联网访问 BigQuery(蓝色虚线),而允许通过虚拟机访问(绿色实线),同时模拟 Compute Engine 默认服务账号。之所以允许访问,是因为服务边界配置为允许从内部 IP 地址访问受保护的资源。
8. 清理
虽然不使用 VPC Service Controls 时无需单独付费,但最佳做法是清理本实验室中使用的设置。您还可以删除虚拟机实例和 BigQuery 数据集或 Google Cloud 项目,以免产生费用。删除 Cloud 项目后,系统即会停止对该项目中使用的所有资源计费。
- 如需删除虚拟机实例,请完成以下步骤:
- 在 Google Cloud 控制台中,转到虚拟机实例页面。
- 选中虚拟机实例名称左侧的复选框,选择删除,然后再次点击删除进行确认。
- 如需删除服务边界,请完成以下步骤:
- 在 Google Cloud 控制台中,选择安全,然后在访问权限政策范围限定的级别(在本例中为文件夹级别)选择 VPC Service Controls。
- 在 VPC Service Controls 页面中,在与要删除的边界对应的表行中,点击删除。
- 如需删除访问权限级别,请完成以下步骤:
- 在 Google Cloud 控制台中,打开“文件夹”范围内的 Access Context Manager 页面。
- 在网格中,找到您要删除的访问权限级别对应的行,选择三点状菜单,然后选择删除。
- 如需关停项目,请完成以下步骤:
- 在 Google Cloud 控制台中,前往 IAM 和要删除的项目的“管理设置”页面。
- 在 IAM &管理员设置页面,选择关停。
- 输入项目 ID,然后选择仍然关停。
9. 恭喜!
在此 Codelab 中,您创建了一个 VPC Service Controls 边界,实施该边界并对其进行问题排查。
了解详情
您还可以探索以下场景:
- 在项目受 VPC Service Controls 保护后,对公共数据集运行相同的查询。
- 在
project-1
所在的边界中添加project-2
。 - 将
project-2
添加到自己的边界内,并将project-1
保留在当前边界内。 - 运行查询以更新表中的数据,而不仅仅是检索数据。
许可
此作品已获得 Creative Commons Attribution 2.0 通用许可授权。