关于此 Codelab
1. 简介
在本实验中,我们将了解如何在将数据从 Cloud Storage 转移到 BigQuery 数据集时,使用 VPC Service Controls 保护 BigQuery Data Transfer Service。然后,我们会保护 Cloud Storage,并重复上述过程,以便将数据从 Cloud Storage 转移到 BigQuery。Cloud Storage 的保护功能会导致 VPC Service Controls 违规,您需要解决此问题才能成功完成转移。最后,我们还保护了 BigQuery,然后尝试在项目之间复制数据集,这也会导致违规问题,需要进行修复。
在本实验中,我们将了解如何分别使用入站规则和出站规则来修正入站和出站违规问题。我们还将使用访问权限级别来修正 BigQuery Data Transfer 入站违规问题。此 Codelab 的目标如下:
- 了解如何针对不同的服务(尤其是 Cloud Storage、BigQuery 和 BigQuery Data Transfer Service)分别使用入站规则和出站规则来修正入站和出站违规问题。
- 了解发生特定违规行为的原因。
2. 资源设置和要求
准备工作
在此 Codelab 中,我们假设您已经了解:
- 如何创建文件夹
- 如何在文件夹中创建项目或将现有项目移至文件夹
- 如何创建范围限定的访问权限政策
- 如何在 Google Cloud 控制台中创建和配置服务边界
- 如何从审核日志中查找违规日志
设置
我们的初始设置如下所示:
- Google Cloud 组织。
- 组织下的文件夹。在此 Codelab 中,我们将其命名为
codelab-folder
。 codelab-folder
文件夹中的两个 Google Cloud 项目。在此 Codelab 中,我们将这两个项目分别称为project-1
和project-2
。- 如果您尚未创建文件夹和项目,请在 Google Cloud 控制台中,在“组织”下创建一个文件夹,然后创建两个新项目。
- 所需权限:用于管理文件夹的 IAM 角色、用于管理项目的 IAM 角色、用于配置 VPC 服务控制功能所需的 IAM 角色、用于管理 BigQuery 的 IAM 角色和用于管理 Cloud Storage 的 IAM 角色。
- 项目
project-1
和project-2
的结算账号。
创建范围限定的政策和常规服务边界
在此 Codelab 中,我们将使用常规服务边界来保护 project-2
。
- 创建范围限定的访问权限政策,其范围限定在文件夹
codelab-folder
级别。在此 Codelab 中,我们假设创建的访问权限政策的 ID 为987654321
。 - 创建常规边界(我们将其称为
perimeter-2
),然后添加项目project-2
。
在边界 perimeter-2
中,限制 BigQuery Data Transfer API
。
创建 Cloud Storage 存储分区和 BigQuery 数据集
在本 Codelab 中,任何 CSV 文件都足以满足需求,无论内容如何。主要限制与共存要求有关,该要求强制执行以下规定:
- 如果您的 BigQuery 数据集位于多区域,则包含您要转移的数据的 Cloud Storage 存储分区必须位于同一多区域或该多区域内的位置
- 如果您的数据集位于某个区域,则 Cloud Storage 存储分区必须位于同一区域。
因此,在本 Codelab 中,我们将确保 Cloud Storage 存储分区和 BigQuery 数据集位于同一区域或多区域中。
在项目 project-1
中创建新的 Cloud Storage 存储分区
如需创建新的 Cloud Storage 存储分区,请按照创建新的存储分区的记录步骤操作。
- 在存储分区名称中,输入符合存储分区名称要求的名称。在此 Codelab 中,我们将该存储分区命名为
codelab-bqtransfer-bucket
。 - 在“数据存储位置”(即存储分区位置)部分,选择将永久存储存储分区数据的位置类型和位置。在此 Codelab 中,我们将使用 us(美国的多个区域)。
创建 CSV 文件
在本地机器上或使用 Cloud Shell,我们可以使用 echo
命令通过以下命令创建示例 CSV 文件 codelab-test-file.csv
:
echo "name,age" > codelab-test-file.csv; \
echo "Alice,10" >> codelab-test-file.csv; \
echo "Bob,20" >> codelab-test-file.csv; \
echo "Carol,30" >> codelab-test-file.csv; \
echo "Dan,40" >> codelab-test-file.csv; \
echo "Eve,50" >> codelab-test-file.csv; \
echo "Frank,60" >> codelab-test-file.csv; \
echo "Grace,70" >> codelab-test-file.csv; \
echo "Heidi,80" >> codelab-test-file.csv;
将 CSV 文件上传到 Cloud Storage 存储分区
创建 CSV 文件后,运行以下命令以将文件对象上传到创建的存储分区:
gcloud storage cp codelab-test-file.csv gs://codelab-bqtransfer-bucket
您可以通过列出存储分区中的对象或运行以下命令来验证文件是否已上传到创建的存储分区:
gcloud storage ls --recursive gs://codelab-bqtransfer-bucket/**
在 project-2
中创建 BigQuery 数据集和表
- 按照这些步骤在项目
project-2
中创建 BigQuery 数据集。 - 按照这些步骤在创建的数据集
codelab_bqtransfer_dataset
下创建 BigQuery 表。- 在来源部分,在基于以下数据源创建表列表中选择空表。
- 在表字段中,输入您要创建的表的名称。在此 Codelab 中,我们使用名称
codelab-bqtransfer-table
。 - 确认表类型字段是否设置为原生表
- 在架构部分,输入架构定义。您可以点击以文本形式修改,然后输入符合创建的 CSV 文件格式的以下架构,以输入架构信息。
[{
"name": "name",
"type": "STRING",
"mode": "NULLABLE",
"description": "The name"
},
{
"name": "age",
"type": "INTEGER",
"mode": "NULLABLE",
"description": "The age"
}]
费用
您需要在项目 project-2
和 project-1
中启用结算功能,才能使用 Cloud 资源/API。我们建议关闭所用资源,以免产生超出此 Codelab 范围的费用。
产生费用的资源是 BigQuery 和 Cloud Storage。您可以在 BigQuery 价格计算器和 Cloud Storage 计算器中查看估算费用。
3. 配置从 Cloud Storage 对象到 BigQuery 表的数据传输
现在,我们将尝试创建一个 Data Transfer Service(位于 project-2
中),以便从 Cloud Storage(位于 project-1
中)转移到 BigQuery(位于 project-2
中),同时让 VPC 服务控制功能保护 project-2
中的 BigQuery Data Transfer Service。仅保护 BigQuery Data Transfer Service(而不保护 BigQuery 和 Cloud Storage)会限制正文仅创建和管理数据传输(例如手动启动数据传输)。
设置从 Cloud Storage 传输数据
如需创建数据传输,请按以下步骤操作:
- 前往
project-2
的 Google Cloud 控制台中的 BigQuery 页面。 - 点击数据传输。
在访问“数据传输作业”页面时调查违规问题
在 Google Cloud 控制台中,我们可以看到 VPC Service Controls 唯一标识符。使用相同的标识符过滤日志并确定违规详情(将 OBSERVED_VPCSC_DENIAL_UNIQUE_ID
替换为观察到的拒绝 ID):
protoPayload.metadata.@type="type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
protoPayload.metadata.vpcServiceControlsUniqueId="OBSERVED_VPCSC_DENIAL_UNIQUE_ID"
观察到的违规行为是 NO_MATCHING_ACCESS_LEVEL
,这是一种入站流量违规行为,详细信息如下所示:
ingressViolations: [
0: {
servicePerimeter: "accessPolicies/987654321/servicePerimeters/perimeter-2"
targetResource: "projects/[PROJECT2_NUMBER]"
}]
violationReason: "NO_MATCHING_ACCESS_LEVEL"
callerIp: "USER_PUBLIC_IP_ADDRESS"
resource: {
labels: {
method: "google.cloud.bigquery.datatransfer.v1.DataTransferService.ListTransferConfigs"
project_id: "project-2"
service: "bigquerydatatransfer.googleapis.com"
}
type: "audited_resource"
}
访问“数据传输”页面会尝试列出任何已配置的数据传输;因此,会违反 ListTransferConfigs
方法。
解决了 bigquerydatatransfer.googleapis.com
服务的违规问题
您可以使用访问权限级别或入站规则来修正入站违规问题。在此 Codelab 中,我们将使用使用被拒绝的用户身份配置的入站规则,该规则允许访问 bigquerydatatransfer.googleapis.com
服务和所有方法。
入站规则生效后,您应该可以顺利访问数据传输页面。
继续设置从 Cloud Storage 传输数据
在前面的步骤中,在“数据传输”页面上(点击“数据传输”后),继续执行以下步骤:
- 点击 + 创建转移作业。
- 在来源类型部分的来源中,选择 Google Cloud Storage。
- 在转移配置名称部分的显示名称中,输入转移作业的名称,例如
Codelab Transfer
。 - 在时间表选项部分中,执行以下操作:
- 选择重复频率,例如 15 分钟。
- 请务必选择立即开始;否则,数据传输将仅在配置的重复频率之后开始
- 在目标设置部分的目标数据集中,选择您创建的用来存储数据的数据集:
codelab_bqtransfer_dataset
- 在数据源详细信息部分中
- 对于 Destination table,输入目标表的名称。目标表必须遵循表命名规则。在此 Codelab 中,我们将使用之前创建的表:
codelab-bqtransfer-table
- 在 Cloud Storage URI 部分,输入 Cloud Storage URI。在本 Codelab 中,我们使用创建的存储分区和文件:
codelab-bqtransfer-bucket/codelab-test-file.csv
- 在写入偏好设置部分,保留
APPEND
(或选择MIRROR
)。 - 请勿选择在转移后删除文件(因为我们会多次重复使用同一文件。不过,您可以使用多个文件,并在转移后删除源文件)
- 在文件格式部分,选择 CSV
- 在转移选项的 CSV 下,输入英文逗号(",") 作为字段分隔符。
- 对于 Destination table,输入目标表的名称。目标表必须遵循表命名规则。在此 Codelab 中,我们将使用之前创建的表:
- 在服务账号菜单中,从与您的 Google Cloud 项目关联的服务账号中选择一个服务账号
- 所选服务账号必须同时拥有托管存储分区的项目(本 Codelab 中的
project-1
)上的 Cloud Storage 的必需权限。 - 在本 Codelab 中,我们将使用在
project-2
中创建的服务账号作为codelab-sa@project-2.iam.gserviceaccount.com
。
- 所选服务账号必须同时拥有托管存储分区的项目(本 Codelab 中的
- 点击保存。
由于我们选择了立即开始作为时间表选项,因此选择保存后,系统会立即开始首次传输。
验证数据传输服务状态
如需验证已配置的数据传输的状态,请执行以下操作:
- 前往 Google Cloud 控制台中的 BigQuery 页面
- 点击数据传输。
- 系统会显示已配置的转移列表
点击 Codelab Transfer
(位于“显示名称”下方),系统会显示到目前为止执行的所有运行作业的列表。
数据传输作业应能成功运行,并且手动触发的数据传输和安排的数据传输都不会违反 VPC Service Controls 政策。请注意,只有手动触发的转移需要入站规则来允许手动发起转移的主账号访问。
4. 手动触发的数据传输的 IP 地址限制
当前配置的入站规则允许配置的身份从任何 IP 地址手动触发数据传输。
通过使用访问权限级别,VPC Service Controls 能够根据特定 API 请求属性限制允许的访问权限,具体而言:
- IP 子网:检查请求是否来自特定 IP 地址。
- 区域:检查请求是否来自特定区域,该区域由 IP 地址的地理位置决定。
- 主账号:检查请求是否来自于特定账号。
- 设备政策:检查请求是否来自符合特定要求的设备。
如需强制验证这些属性以及已配置的入站流量规则,我们必须创建一个允许所需属性的访问权限级别,然后在入站流量规则中将创建的访问权限级别添加为来源。
此图展示了两个正文(
user@example.com
和 user2@example.com
)在三种场景中发起的访问,演示了 VPC Service Controls 如何将来源(入站访问权限级别)和身份属性评估为必须匹配的 AND 条件。
- 当用户 user@example.com 尝试通过访问权限级别允许的 IP 地址进行访问时,系统会允许其访问,因为其 IP 地址和用户账号与入站规则中的配置相符。
- 用户 user@example.com 的 IP 地址与允许的 IP 地址不匹配,因此其访问权限被屏蔽,尽管其账号是入站规则中配置的账号。
- 用户 user2@example.com 在尝试使用允许的 IP 地址进行访问时被屏蔽,因为入站规则不允许其账号进行访问。
创建访问权限级别
如需创建按 IP 地址限制访问权限的访问权限级别,请执行以下操作:
- 在 Google Cloud 控制台中打开 Access Context Manager 页面。
- 如果系统提示,请选择文件夹
codelab-folder
。
- 如果系统提示,请选择文件夹
- 在 Access Context Manager 页面的顶部,点击创建访问权限级别。
- 在新建访问权限级别窗格中,为新访问权限级别指定标题。在此 Codelab 中,我们将其命名为
project_2_al
。 - 在条件部分中,点击 IP 子网前面的 +。
- 在 IP 子网框中,选择公共 IP
- 或者,您也可以选择使用专用 IP 地址在访问权限级别中使用内部 IP 地址。不过,在此 Codelab 中,我们使用的是公共 IP。
- 输入一个或多个格式为 CIDR 块的 IPv4 或 IPv6 范围。
在入站流量规则中添加访问权限级别
在入站规则中,访问权限级别在 sources
字段下引用,该字段是必需字段,如入站规则参考中所述。如需允许面向资源的入站流量,VPC Service Controls 会将 sources
和 identityType
属性评估为 AND 条件。入站规则使用手动触发数据传输的主账号的身份,而不是数据传输配置中指定的服务账号。
使用限制 IP 地址访问权限的配置重新运行转移
如需评估应用的配置的有效性,请使用以下场景再次触发转移:
- 使用入站规则引用的访问权限级别中允许的 IP 地址范围内的 IP 地址。
- 使用配置不允许的 IP 地址
从允许的 IP 地址进行访问应该会成功,而从不允许的 IP 地址进行访问应该会失败,并导致 VPC Service Controls 违规。
如需使用其他 IP 地址进行测试,一种简单的方法是允许在使用 Google Cloud 控制台时分配 IP 地址,然后在使用 Cloud Shell 时进行测试。
在 Cloud Shell 中,运行以下命令,替换 RUN_TIME 和 RESOURCE_NAME,以手动触发传输:
bq mk \
--transfer_run \
--run_time='RUN_TIME' \
RESOURCE_NAME
例如,以下示例命令会立即针对项目 1234567890
中的转移 12345678-90ab-cdef-ghij-klmnopqrstuv
配置运行。
NOW=$(TZ=GMT date +"%Y-%m-%dT%H:%M:%SZ");
bq mk \
--transfer_run \
--run_time=$NOW \
projects/1234567890/locations/us/transferConfigs/12345678-90ab-cdef-ghij-klmnopqrstuv
观察到的输出显示了 VPC Service Controls 违规行为,这符合预期,因为该 IP 地址不受允许。
观察到的违规行为涉及 DataTransferService.StartManualTransferRuns
方法。
ingressViolations: [
0: {
servicePerimeter: "accessPolicies/987654321/servicePerimeters/perimeter-2"
targetResource: "projects/[PROJECT2_NUMBER]"
targetResourcePermissions: [0: "vpcsc.permissions.unavailable"]
}]
violationReason: "RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER"
resource: {
labels: {
method: "google.cloud.bigquery.datatransfer.v1.DataTransferService.StartManualTransferRuns"
project_id: "project-2"
service: "bigquerydatatransfer.googleapis.com"
}
type: "audited_resource"
}
severity: "ERROR"
5. 在保护 Cloud Storage 服务的同时启动数据传输
由于我们要从 Cloud Storage 向 BigQuery 执行转移,因此我们将 Cloud Storage 添加到受 VPC Service Controls 保护的服务中,看看转移能否成功。
在 perimeter-2
配置中,将 Cloud Storage API 和 BigQuery Data Transfer API 添加为受限服务之一。
保护 Cloud Storage API 后,请等待下次安排的数据传输,或按照以下步骤手动触发传输:
- 转到 Google Cloud 控制台中的 BigQuery 页面。
- 点击数据传输。
- 从列表中选择您的转移作业:在此 Codelab 中,我们使用的是 Codelab Transfer 转移
- 点击立即运行转移作业
- 点击确定。
系统会发起另一次转移。您可能需要刷新页面才能看到。这次传输将因违反 VPC Service Controls 政策而失败。
调查 Cloud Storage VPC Service Controls 违规问题
使用转移摘要中显示的 vpcServiceControlsUniqueIdentifier
过滤审核日志。
检测到的违规行为是 RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER
出站流量违规行为,具体详情如下:
- 主账号是指在数据传输服务中配置的服务账号(无论是手动触发还是运行安排的数据传输,被拒绝的主账号都将保持不变)。
- 受影响的服务是 Cloud Storage
- 请求的来源是配置了数据传输服务的项目:
project-2
- 目标项目是 Cloud Storage 对象所在的项目:
project-1
principalEmail: "codelab-sa@project-2.iam.gserviceaccount.com"
egressViolations: [
0: {
servicePerimeter: "accessPolicies/987654321/servicePerimeters/perimeter-2"
source: "projects/[PROJECT2_NUMBER]"
sourceType: "Resource"
targetResource: "projects/[PROJECT1_NUMBER]"
targetResourcePermissions: [0: "storage.objects.get"]
}]
labels: {
method: "google.storage.objects.get"
project_id: "project-2"
service: "storage.googleapis.com"
}
解决 Cloud Storage 出站流量违规问题
如需修正出站流量违规问题,我们必须使用出站规则,允许从被拒绝的服务账号向包含 Cloud Storage 对象的项目发送流量。
修改服务边界 perimeter-2
后,请重复此流程以再次触发转移。转移不会显示错误。
6. 将 BigQuery 数据集从 project-2 复制到 project-1
确认我们可以将数据从 project-1
中的 Cloud Storage 存储分区转移到 project-2
中的 BigQuery 数据集后,我们来从 project-2
向 project-1
复制 BigQuery 数据集;同时,BigQuery API 由 VPC 服务控制保护。
如需创建和复制数据集,我们将使用 bq mk
命令,该命令使用 bq 工具。
在 project-1
中创建目标数据集
在复制数据集之前,必须先创建目标数据集。如需创建目标数据集,我们可以运行以下命令,该命令会在项目 project-1
中创建名为 copied_dataset
的数据集,并将 us
作为位置。
bq mk \
--dataset \
--location=us \
project-1:copied_dataset
使用 VPC Service Controls 保护 project-2
中的 BigQuery 服务
修改边界 perimeter-2
的配置,并将 BigQuery API 添加为受保护服务,以及 BigQuery Data Transfer 和 Cloud Storage 服务。
启动数据集复制
如需复制数据集,请运行以下 bq mk
命令,该命令会将项目 project-2
中的数据集 codelab_bqtransfer_dataset
复制到 project-1
中的数据集 copied_dataset
,并覆盖数据集内容(如果有)。
bq mk \
--transfer_config \
--project_id=project-1 \
--target_dataset=copied_dataset \
--data_source=cross_region_copy \
--display_name='Dataset from project-2 to project-1' \
--params='{
"source_dataset_id":"codelab_bqtransfer_dataset",
"source_project_id":"project-2",
"overwrite_destination_table":"true"
}'
该命令将成功运行;同时,转移配置会成功创建,以启动复制数据集的操作。复制数据集本身将会失败,并会出现 VPC Service Controls 违规问题。
如需查找相应的 VPC Service Controls 违规详情,请使用以下日志查询检查 project-2
(来源数据集项目)中的日志。日志查询会按 BigQuery 服务和要复制的数据集的资源名称 (codelab_bqtransfer_dataset
) 过滤日志。
resource.labels.service="bigquery.googleapis.com"
protoPayload.metadata.resourceNames:"datasets/codelab_bqtransfer_dataset"
观察到的 VPC Service Controls 违规行为是从 project-2
到 project-1
的出站违规行为。
egressViolations: [
0: {
servicePerimeter: "accessPolicies/987654321/servicePerimeters/perimeter-2"
source: "projects/[PROJECT-2-NUMBER]"
sourceType: "Resource"
targetResource: "projects/[PROJECT-1-NUMBER]"
targetResourcePermissions: [
0: "bigquery.transfers.update"
1: "bigquery.transfers.get"
2: "bigquery.jobs.create"
]
}
]
method: "bigquery.tables.getData"
service: "bigquery.googleapis.com"
修正所有 BigQuery 违规问题,然后重新开始数据集复制
如需解决出站流量违规问题,我们需要创建一个允许被拒绝的正文的出站规则。被拒绝的主账号是运行 mk
命令的主账号。
出站规则生效后,在边界网关 perimeter-2
上运行相同的命令即可复制数据集。这次,它应该会成功复制数据集,且不会违反 VPC Service Controls 限制。
7. 清理
虽然在 VPC Service Controls 处于闲置状态时,使用该服务无需另行付费,但最好还是清理本实验中使用的设置。您还可以删除虚拟机实例和/或 Cloud 项目,以避免产生费用。删除 Cloud 项目后,系统会停止对该项目中使用的所有资源计费。
- 如需删除 Cloud Storage 存储分区,请完成以下步骤:
- 在 Google Cloud 控制台中,前往 Cloud Storage 存储分区页面。
- 选中要删除的存储分区对应的复选框,然后点击删除。
- 在出现的叠加窗口中,确认要删除存储分区及其内容。
- 如需删除 BigQuery 数据集,请完成以下步骤:
- 在 Google Cloud 控制台中,前往 BigQuery 页面。
- 在浏览器窗格中,展开您的项目,然后选择数据集。
- 展开三点状菜单,然后点击删除。
- 在删除数据集对话框中,在字段中输入
delete
,然后点击删除。
- 如需删除服务边界,请完成以下步骤:
- 在 Google Cloud 控制台中,选择安全,然后在访问权限政策的范围级别(在本例中为文件夹级别)选择 VPC Service Controls。
- 在 VPC Service Controls 页面上,在与要删除的边界相对应的表行中,选择
Delete Icon
。
- 如需删除访问权限级别,请完成以下步骤:
- 在 Google Cloud 控制台中,在“文件夹”级别打开 Access Context Manager 页面。
- 在网格中,找到您要删除的访问权限级别对应的行,选择三点状菜单,然后选择删除。
- 如需关闭项目,请完成以下步骤:
- 在 Google Cloud 控制台中,前往要删除的项目的“IAM 和管理”设置页面。
- 在“IAM 和管理设置”页面上,选择关停。
- 输入项目 ID,然后选择仍要关停。