使用 Cloud KMS 密钥保护数据

默认情况下,BigQuery 会加密静态存储的客户内容。BigQuery 为您处理和管理此默认加密,您无需进行任何其他操作。首先,系统会使用“数据加密密钥”(DEK) 对 BigQuery 表中的数据进行加密。然后,通过 KEK(密钥加密密钥)来对 DEK 进行加密(这称为信封加密)。KEK 不用于直接加密您的数据,而是用于对 Google 用来加密您数据的 DEK 进行加密。如需了解详情,请参阅密钥管理

如果您想自行控制加密,可为 BigQuery 使用客户管理式加密密钥 (CMEK)。这样您就可以在 Cloud KMS 中控制和管理用于保护数据的 KEK,而不是让 Google 进行管理。本主题将提供有关这一用法的详细信息。

详细了解 Google Cloud Platform 上的加密选项

准备工作

  1. 了解数据集查询

  2. 确定您要在相同的 GCP 项目中运行 BigQuery 和 Cloud KMS,还是在不同的项目中运行。为了方便说明,本文的示例将采用下列惯例:

    • [PROJECT_ID] 是运行 BigQuery 的项目的 ID
    • [PROJECT_NUMBER] 是运行 BigQuery 的项目的编号
    • [KMS_PROJECT_ID] 是运行 Cloud KMS 的项目的 ID(即使该项目就是运行 BigQuery 的同一个项目)
    要了解 GCP 项目 ID 和项目编号,请参阅识别项目

  3. 新项目中会自动启用 BigQuery。如果您使用现有项目来运行 BigQuery,请启用 BigQuery API

  4. 对于运行 Cloud KMS 的 GCP 项目,请执行以下操作:

    1. 启用 Cloud KMS API
    2. 按照创建密钥环和密钥中的说明创建密钥环和密钥。请在与 BigQuery 数据集的位置匹配的位置创建密钥环:
      • 任何多区域数据集都应使用来自匹配位置的多区域密钥环。例如,应使用来自区域 us 的密钥环保护位于区域 US 的数据集,使用来自区域 europe 的密钥环保护位于区域 EU 的数据集。
      • 区域数据集应使用匹配的区域密钥。例如,应使用来自区域 asia-northeast1 的密钥环保护位于区域 asia-northeast1 的数据集。
      • 无法在 global 区域使用 BigQuery。
      如需详细了解 BigQuery 和 Cloud KMS 对应的受支持的位置,请参阅 Cloud 网点

加密规范

用于保护您在 BigQuery 中的数据的 Cloud KMS 密钥是 AES-256 密钥。这类密钥在 BigQuery 中被用作 KEK,其用途是对加密您数据的 DEK 进行加密。

授予加密和解密权限

使用 Google Cloud Platform Console 确定 BigQuery 服务帐号 ID,并为该服务帐号提供相应的角色,以便使用 Cloud KMS 进行加密和解密。

确定服务帐号 ID

经典版界面

  1. 转到 BigQuery 网页界面。

    转到 BigQuery 网页界面

  2. 在导航窗格中,点击项目名称旁边的向下箭头图标 向下箭头图标,然后点击 Customer Managed Encryption

  3. 此时,系统会打开用户对话框,显示需要加密和解密权限的服务帐号:

    服务帐号 ID

  4. 点击 Copy 以将服务帐号 ID 复制到剪贴板,然后点击 OK 以关闭用户对话框。

CLI

您可以将 bq show 命令与 --encryption_service_account 标志结合使用来确定服务帐号 ID:

bq show --encryption_service_account

该命令会显示服务帐号 ID:

                       ServiceAccountID
     -------------------------------------------------------------
      bq-[PROJECT_NUMBER]@bigquery-encryption.iam.gserviceaccount.com

分配加密者/解密者角色

Cloud KMS CryptoKey Encrypter/Decrypter 角色分配给您已复制到剪贴板的 BigQuery 系统服务帐号。该帐号的格式如下:

bq-[PROJECT_NUMBER]@bigquery-encryption.iam.gserviceaccount.com

Console

  1. 打开 GCP Console 中的安全页面。

    打开“安全加密密钥”页面

  2. 选择您的项目并点击继续

  3. 确定要向其添加角色的加密密钥。

    • 如果 bq-[PROJECT_NUMBER]@bigquery-encryption.iam.gserviceaccount.com 服务帐号不在成员列表中,则表明还没有为该帐号分配任何角色。点击添加成员,然后输入服务帐号的电子邮件地址 bq-[PROJECT_NUMBER]@bigquery-encryption.iam.gserviceaccount.com
    • 如果该服务帐号已经在成员列表中,则表明它具有现有角色。点击 bq-[PROJECT_NUMBER]@bigquery-encryption.iam.gserviceaccount.com 服务帐号的当前角色下拉列表。
  4. 点击角色下拉列表,点击 Cloud KMS,然后点击 Cloud KMS CryptoKey Encrypter/Decrypter 角色。

  5. 点击添加保存,将角色应用于 bq-[PROJECT_NUMBER]@bigquery-encryption.iam.gserviceaccount.com 服务帐号。

CLI

您可以使用 gcloud 命令行工具来分配角色:

gcloud kms keys add-iam-policy-binding \
--project=[KMS_PROJECT_ID] \
--member serviceAccount:bq-[PROJECT_NUMBER]@bigquery-encryption.iam.gserviceaccount.com \
--role roles/cloudkms.cryptoKeyEncrypterDecrypter \
--location=[KMS_KEY_LOCATION] \
--keyring=[KMS_KEY_RING] \
[KMS_KEY]

[KMS_PROJECT_ID] 替换为运行 Cloud KMS 的 GCP 项目的 ID,将 [PROJECT_NUMBER] 替换为运行 BigQuery 的 GCP 项目的编号(而非项目 ID),并将 [KMS_KEY_LOCATION][KMS_KEY_RING][KMS_KEY] 分别替换为 Cloud KMS 密钥的位置、密钥环和密钥名称。

创建受 Cloud KMS 保护的表

创建受 Cloud KMS 保护的空表

要创建受 Cloud KMS 保护的表,请执行以下操作:

经典版界面

  1. 点击 BigQuery 网页界面中数据集名称旁边的向下箭头图标 向下箭头图标,然后点击 Create new table

  2. Create table 页面上,填写创建具有架构定义的空表所需的信息。在您点击 Create table 之前,请设置加密类型并指定要用于表的 Cloud KMS 密钥:

    1. 点击 Encryption Type 下拉列表,并选择 Customer-Managed Encryption
    2. 对于 Customer-Managed Encryption Key,输入密钥的资源 ID。此密钥的格式如下:
      projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY]
      
      如需了解如何检索密钥资源 ID,请参阅密钥资源 ID
  3. 点击创建表

CLI

您可以将 bq 命令行工具与 --destination_kms_key 标志结合使用来创建表。--destination_kms_key 标志可指定要用于表的密钥的资源 ID。此密钥的格式如下:

projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY]
如需了解如何检索密钥资源 ID,请参阅密钥资源 ID。 要创建具有架构的空表,请使用以下命令:
bq mk --schema name:string,value:integer -t \
--destination_kms_key projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY] \
mydataset.newtable

或者,您可以使用 DDL 语句:

bq query --use_legacy_sql=false "
  CREATE TABLE mydataset.newtable (name STRING, value INT64)
  OPTIONS(
    kms_key_name='projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY]'
  )
"

要基于查询创建表,请使用以下命令:

bq query --destination_table=mydataset.newtable \
--destination_kms_key projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY] \
"SELECT name,count FROM mydataset.babynames WHERE gender = 'M' ORDER BY count DESC LIMIT 6"

如需详细了解 bq 命令行工具,请参阅 bq 命令行工具

Go

// To run this sample, you will need to create (or reuse) a context and
// an instance of the bigquery client.  For example:
// import "cloud.google.com/go/bigquery"
// ctx := context.Background()
// client, err := bigquery.NewClient(ctx, "your-project-id")
tableRef := client.Dataset(datasetID).Table(tableID)
meta := &bigquery.TableMetadata{
	EncryptionConfig: &bigquery.EncryptionConfig{
		// TODO: Replace this key with a key you have created in Cloud KMS.
		KMSKeyName: "projects/cloud-samples-tests/locations/us-central1/keyRings/test/cryptoKeys/test",
	},
}
if err := tableRef.Create(ctx, meta); err != nil {
	return err
}

Python

在创建表之前,通过将 Table.encryption_configuration 属性设置为 EncryptionConfiguration 对象,从而使用客户管理的加密密钥 (CMEK) 来保护新表。

# from google.cloud import bigquery
# client = bigquery.Client()
# dataset_id = 'my_dataset'

table_ref = client.dataset(dataset_id).table('my_table')
table = bigquery.Table(table_ref)

# Set the encryption key to use for the table.
# TODO: Replace this key with a key you have created in Cloud KMS.
kms_key_name = 'projects/{}/locations/{}/keyRings/{}/cryptoKeys/{}'.format(
    'cloud-samples-tests', 'us-central1', 'test', 'test')
table.encryption_configuration = bigquery.EncryptionConfiguration(
    kms_key_name=kms_key_name)

table = client.create_table(table)  # API request

assert table.encryption_configuration.kms_key_name == kms_key_name

查询受 Cloud KMS 密钥保护的表

查询受 Cloud KMS 保护的表无需特殊操作安排。BigQuery 会存储用于加密表内容的密钥的名称,并在受 Cloud KMS 保护的表被查询时使用该密钥。

只要 BigQuery 有权访问用于加密表内容的 Cloud KMS 密钥,所有现有工具、BigQuery 控制台和 bq 命令行界面的工作方式都将与采用默认加密方式的表相同。

使用 Cloud KMS 密钥保护查询结果

网页界面

  1. 点击 BigQuery 网页界面中的 Compose query 按钮。

  2. New Query 文本区域中输入有效的 BigQuery SQL 查询。

  3. 点击 Encryption Type,然后选择 Customer-Managed Encryption

  4. 对于 Customer-Managed Encryption Key,输入密钥的资源 ID。此密钥的格式如下:

    projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY]
    
    要了解如何检索密钥资源 ID,请参阅密钥资源 ID

  5. 点击 RunQuery

命令行

指定标志 --destination_kms_key 以使用 Cloud KMS 密钥保护目标表或查询结果(如果使用临时表)。--destination_kms_key 标志可指定要用于目标表或生成的表的密钥的资源 ID。此密钥的格式如下:

projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY]
如需了解如何检索密钥资源 ID,请参阅 [密钥资源 ID](/kms/docs/object-hierarchy#key_resource_id)。您也可以选择使用“--destination_table”标志来为查询结果指定目标表。如果未使用“--destination_table”,查询结果将写入临时表中。要查询表,请使用以下命令:
bq query \
--destination_table=mydataset.newtable \
--destination_kms_key projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY] \
"SELECT name,count FROM mydataset.babynames WHERE gender = 'M' ORDER BY count DESC LIMIT 6"

如需详细了解 bq 命令行工具,请参阅 bq 命令行工具

Go

q := client.Query("SELECT 17 as my_col")
q.Location = "US" // Location must match the dataset(s) referenced in query.
q.QueryConfig.Dst = client.Dataset(destDatasetID).Table(destTableID)
q.DestinationEncryptionConfig = &bigquery.EncryptionConfig{
	// TODO: Replace this key with a key you have created in Cloud KMS.
	KMSKeyName: "projects/cloud-samples-tests/locations/us-central1/keyRings/test/cryptoKeys/test",
}
return runAndRead(ctx, client, q)
job, err := q.Run(ctx)
if err != nil {
	return err
}
status, err := job.Wait(ctx)
if err != nil {
	return err
}
if err := status.Err(); err != nil {
	return err
}
it, err := job.Read(ctx)
for {
	var row []bigquery.Value
	err := it.Next(&row)
	if err == iterator.Done {
		break
	}
	if err != nil {
		return err
	}
	fmt.Println(row)
}

Python

通过将 QueryJobConfig.destination_encryption_configuration 属性设置为 EncryptionConfiguration 来使用客户管理的加密密钥 (CMEK) 保护查询的目标表,然后再运行查询。

# from google.cloud import bigquery
# client = bigquery.Client()

job_config = bigquery.QueryJobConfig()

# Set the destination table. Here, dataset_id is a string, such as:
# dataset_id = 'your_dataset_id'
table_ref = client.dataset(dataset_id).table('your_table_id')
job_config.destination = table_ref

# Set the encryption key to use for the destination.
# TODO: Replace this key with a key you have created in KMS.
kms_key_name = 'projects/{}/locations/{}/keyRings/{}/cryptoKeys/{}'.format(
    'cloud-samples-tests', 'us-central1', 'test', 'test')
encryption_config = bigquery.EncryptionConfiguration(
    kms_key_name=kms_key_name)
job_config.destination_encryption_configuration = encryption_config

# Start the query, passing in the extra configuration.
query_job = client.query(
    'SELECT 17 AS my_col;',
    # Location must match that of the dataset(s) referenced in the query
    # and of the destination table.
    location='US',
    job_config=job_config)  # API request - starts the query
query_job.result()

# The destination table is written using the encryption configuration.
table = client.get_table(table_ref)
assert table.encryption_configuration.kms_key_name == kms_key_name

加载受 Cloud KMS 保护的表

要将数据文件加载到受 Cloud KMS 保护的表中,请使用以下方式:

Go

// To run this sample, you will need to create (or reuse) a context and
// an instance of the bigquery client.  For example:
// import "cloud.google.com/go/bigquery"
// ctx := context.Background()
// client, err := bigquery.NewClient(ctx, "your-project-id")
gcsRef := bigquery.NewGCSReference("gs://cloud-samples-data/bigquery/us-states/us-states.json")
gcsRef.SourceFormat = bigquery.JSON
gcsRef.AutoDetect = true
loader := client.Dataset(datasetID).Table(tableID).LoaderFrom(gcsRef)
loader.WriteDisposition = bigquery.WriteEmpty
loader.DestinationEncryptionConfig = &bigquery.EncryptionConfig{
	// TODO: Replace this key with a key you have created in KMS.
	KMSKeyName: "projects/cloud-samples-tests/locations/us-central1/keyRings/test/cryptoKeys/test",
}

job, err := loader.Run(ctx)
if err != nil {
	return err
}
status, err := job.Wait(ctx)
if err != nil {
	return err
}

if status.Err() != nil {
	return fmt.Errorf("Job completed with error: %v", status.Err())
}

Python

通过将 LoadJobConfig.destination_encryption_configuration 属性设置为 EncryptionConfiguration 来使用客户管理的加密密钥 (CMEK) 保护加载作业的目标表,然后再加载表。

# from google.cloud import bigquery
# client = bigquery.Client()
# dataset_id = 'my_dataset'

dataset_ref = client.dataset(dataset_id)
job_config = bigquery.LoadJobConfig()
job_config.autodetect = True
job_config.source_format = bigquery.SourceFormat.NEWLINE_DELIMITED_JSON

# Set the encryption key to use for the destination.
# TODO: Replace this key with a key you have created in KMS.
kms_key_name = 'projects/{}/locations/{}/keyRings/{}/cryptoKeys/{}'.format(
    'cloud-samples-tests', 'us-central1', 'test', 'test')
encryption_config = bigquery.EncryptionConfiguration(
    kms_key_name=kms_key_name)
job_config.destination_encryption_configuration = encryption_config
uri = 'gs://cloud-samples-data/bigquery/us-states/us-states.json'

load_job = client.load_table_from_uri(
    uri,
    dataset_ref.table('us_states'),
    location='US',  # Location must match that of the destination dataset.
    job_config=job_config)  # API request

assert load_job.job_type == 'load'

load_job.result()  # Waits for table load to complete.

assert load_job.state == 'DONE'
table = client.get_table(dataset_ref.table('us_states'))
assert table.encryption_configuration.kms_key_name == kms_key_name

将数据流式插入受 Cloud KMS 保护的表

您可以将数据流式插入到受 CMEK 保护的 BigQuery 表中,而无需指定任何其他参数。请注意,系统将使用 Cloud KMS 密钥对缓冲区和最终位置中的此类数据进行加密。在将数据流式插入到 CMEK 表之前,请先查看密钥可用性和可访问性上所述的要求。

要详细了解流式插入,请参阅将数据流式插入到 BigQuery 中

将表从默认加密方式改为受 Cloud KMS 保护

命令行

您可以将 bq cp 命令与 --destination_kms_key 标志结合使用,将受默认加密方式保护的表复制到受 Cloud KMS 保护的新表或原表中。--destination_kms_key 标志可指定要用于目标表的密钥的资源 ID。此密钥的格式如下:

projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY]

如需了解如何检索密钥资源 ID,请参阅密钥资源 ID

要将采用默认加密方式的表复制到受 Cloud KMS 保护的新表,请使用以下命令:

bq cp \
--destination_kms_key projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY] \
sourceDataset.sourceTableId destinationDataset.destinationTableId

要将采用默认加密方式的表复制到受 Cloud KMS 保护的相同表,请使用以下命令:

bq cp -f \
--destination_kms_key projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY] \
sourceDataset.sourceTableId sourceDataset.sourceTableId

如果您要将表从受 Cloud KMS 保护更改为采用默认加密方式,请通过运行 bq cp 将文件复制到其自身,而不使用 --destination_kms_key 标志。

如需详细了解 bq 命令行工具,请参阅 bq 命令行工具

Go

// To run this sample, you will need to create (or reuse) a context and
// an instance of the bigquery client.  For example:
// import "cloud.google.com/go/bigquery"
// ctx := context.Background()
// client, err := bigquery.NewClient(ctx, "your-project-id")
srcTable := client.DatasetInProject("bigquery-public-data", "samples").Table("shakespeare")
copier := client.Dataset(datasetID).Table(tableID).CopierFrom(srcTable)
copier.DestinationEncryptionConfig = &bigquery.EncryptionConfig{
	// TODO: Replace this key with a key you have created in Cloud KMS.
	KMSKeyName: "projects/cloud-samples-tests/locations/us-central1/keyRings/test/cryptoKeys/test",
}
job, err := copier.Run(ctx)
if err != nil {
	return err
}
status, err := job.Wait(ctx)
if err != nil {
	return err
}
if err := status.Err(); err != nil {
	return err
}

Python

通过将 QueryJobConfig.destination_encryption_configuration 属性设置为 EncryptionConfiguration 来使用客户管理的加密密钥 (CMEK) 保护表副本的目标,然后再复制表。

# from google.cloud import bigquery
# client = bigquery.Client()

source_dataset = bigquery.DatasetReference(
    'bigquery-public-data', 'samples')
source_table_ref = source_dataset.table('shakespeare')

# dataset_id = 'my_dataset'
dest_dataset_ref = client.dataset(dataset_id)
dest_table_ref = dest_dataset_ref.table('destination_table')

# Set the encryption key to use for the destination.
# TODO: Replace this key with a key you have created in KMS.
kms_key_name = 'projects/{}/locations/{}/keyRings/{}/cryptoKeys/{}'.format(
    'cloud-samples-tests', 'us-central1', 'test', 'test')
encryption_config = bigquery.EncryptionConfiguration(
    kms_key_name=kms_key_name)
job_config = bigquery.CopyJobConfig()
job_config.destination_encryption_configuration = encryption_config

job = client.copy_table(
    source_table_ref,
    dest_table_ref,
    # Location must match that of the source and destination tables.
    location='US',
    job_config=job_config)  # API request
job.result()  # Waits for job to complete.

assert job.state == 'DONE'
dest_table = client.get_table(dest_table_ref)
assert dest_table.encryption_configuration.kms_key_name == kms_key_name

确定表是否受 Cloud KMS 保护

  1. 在 BigQuery 网页界面中,点击数据集左侧的蓝色箭头以展开该数据集,或双击数据集名称。这将显示数据集中的表和视图。

  2. 点击表名称。

  3. 点击 DetailsTable Details 页面会显示表说明和表信息。

  4. 如果表受 Cloud KMS 保护,则 Customer-Managed Encryption Key 字段将显示密钥资源 ID。

    受保护的表

更改 BigQuery 表的 Cloud KMS 密钥

要更改受 CMEK 保护的现有表的 Cloud KMS 密钥,您可以运行 ALTER TABLE 查询、使用 API 或使用 bq 命令行工具。您可以通过以下两种方式来使用 API 和命令行工具修改 Cloud KMS 密钥:updatecp。如果使用 update,您可以更改受 KMS 保护的表所使用的 Cloud KMS 密钥。如果使用 cp,您可以更改受 CMEK 保护的表所使用的 Cloud KMS 密钥、将表从默认加密更改为受 CMEK 保护,还可以将表从受 CMEK 保护更改为默认加密。update 的一个优点是速度比 cp 更快,并且支持使用表修饰器

经典版界面

此密钥的格式如下:

projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY]

如需了解如何检索密钥资源 ID,请参阅密钥资源 ID

  1. 转到 BigQuery 网页界面。

    转到 BigQuery 网页界面

  2. 点击 Compose query

  3. New Query 文本区域中输入 DDL 语句。

     #standardSQL
     ALTER TABLE mydataset.mytable
     SET OPTIONS (
       kms_key_name="projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY]"
     )
     

命令行

您可以将 bq cp 命令与 --destination_kms_key 标志结合使用,以更改受 Cloud KMS 保护的表的密钥。--destination_kms_key 标志可指定要用于表的密钥的资源 ID。此密钥的格式如下:

projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY]

如需了解如何检索密钥资源 ID,请参阅密钥资源 ID

bq update \
--destination_kms_key projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY] \
-t [DATASET_ID].[TABLE_ID]

Go

// To run this sample, you will need to create (or reuse) a context and
// an instance of the bigquery client.  For example:
// import "cloud.google.com/go/bigquery"
// ctx := context.Background()
// client, err := bigquery.NewClient(ctx, "your-project-id")
tableRef := client.Dataset(datasetID).Table(tableID)
meta, err := tableRef.Metadata(ctx)
if err != nil {
	return err
}
update := bigquery.TableMetadataToUpdate{
	EncryptionConfig: &bigquery.EncryptionConfig{
		// TODO: Replace this key with a key you have created in Cloud KMS.
		KMSKeyName: "projects/cloud-samples-tests/locations/us-central1/keyRings/test/cryptoKeys/otherkey",
	},
}
if _, err := tableRef.Update(ctx, update, meta.ETag); err != nil {
	return err
}

Python

通过将 Table.encryption_configuration 属性更改为新的 EncryptionConfiguration 对象来更改表的客户管理的加密密钥 (CMEK),然后再更新表。

# from google.cloud import bigquery
# client = bigquery.Client()

assert table.encryption_configuration.kms_key_name == original_kms_key_name

# Set a new encryption key to use for the destination.
# TODO: Replace this key with a key you have created in KMS.
updated_kms_key_name = (
    'projects/cloud-samples-tests/locations/us-central1/'
    'keyRings/test/cryptoKeys/otherkey')
table.encryption_configuration = bigquery.EncryptionConfiguration(
    kms_key_name=updated_kms_key_name)

table = client.update_table(
    table, ['encryption_configuration'])  # API request

assert table.encryption_configuration.kms_key_name == updated_kms_key_name
assert original_kms_key_name != updated_kms_key_name

撤消 BigQuery 对 Cloud KMS 密钥的访问权限

您可以随时移除 BigQuery 对 Cloud KMS 密钥的访问权限,方法是撤消该密钥的 IAM 权限。

如果 BigQuery 失去对 Cloud KMS 密钥的访问权限,用户体验可能会受到严重影响,并且可能发生数据丢失:

  • 这些受 CMEK 保护的表中的数据将不再可访问 — querycpextracttabledata.list 全部都将失败。

  • 不会再有新数据添加到这些受 CMEK 保护的表中。

  • 即使重新授予访问权限,对这些表所执行的查询的性能也可能在数天内都有所下降。

Cloud KMS 密钥轮替的影响

当与表关联的 Cloud KMS 密钥轮替时,BigQuery 不会自动轮替表加密密钥。现有表继续使用创建时所用的密钥版本。新表将使用当前的密钥版本。

限制

BigQuery 对 Cloud KMS 密钥的访问权限

如果符合以下条件,Cloud KMS 密钥会被视为可由 BigQuery 使用和访问:

  • 密钥已启用
  • BigQuery 服务帐号拥有该密钥的加密和解密权限

以下部分介绍当密钥不可访问时,对流式插入和长期无法访问的数据所造成的影响。

对流式插入的影响

在提交流式插入请求后的 48 小时内,必须至少连续 24 个小时可以使用和访问 Cloud KMS 密钥。如果不能使用和访问密钥,流式插入的数据可能会无法完整保留,并且可能会丢失。要详细了解流式插入,请参阅将数据流式插入到 BigQuery 中

对长期无法访问的数据的影响

由于 BigQuery 提供托管式存储空间,因此长期无法访问的数据与 BigQuery 的架构是不兼容的。如果连续 60 天无法使用和访问特定 BigQuery 表的 Cloud KMS 密钥,BigQuery 可能会选择删除该表及其关联的数据。在删除数据之前,BigQuery 会提前至少 7 天向与结算帐号关联的电子邮件地址发送电子邮件。

使用表修饰器

如果您通过为 loadcpquery 操作使用 WRITE_TRUNCATE 这一写入处置方式来替换受 Cloud KMS 保护的表中的数据,则根据快照修饰器时间,您将无法通过表修饰器查询该表。

假设表在时间 T 被替换并且快照修饰器 snapshot_time 对应的时间小于 T,下表显示了您是否可以对 snapshot_time 进行查询:

T 之前的加密类型 T 之后的加密类型 snapshot_time
Cloud KMS 加密 Cloud KMS 加密 无法查询
默认加密 Cloud KMS 加密 可以查询
Cloud KMS 加密 默认加密 无法查询

请注意,当使用范围修饰器时,类似的逻辑也适用于 <time2>

常见问题解答

谁需要 Cloud KMS 密钥的权限?

使用 CMEK 时,您无需重复指定权限。只要 BigQuery 服务帐号有权使用 Cloud KMS 密钥进行加密和解密,任何拥有 BigQuery 表权限的人都可以访问数据(即使无法直接访问 Cloud KMS 密钥)。

使用哪个服务帐号?

与表的 GCP 项目关联的 BigQuery 服务帐号将用于解密该表的数据。BigQuery 服务帐号对每个项目都是唯一的。如果作业将数据写入受 Cloud KMS 保护的匿名表中,则将使用该作业的项目的服务帐号。

例如,假设有三个受 CMEK 保护的表:table1table2table3。要在将 {project3.table3} 用作目标表的情况下查询 {project1.table1, project2.table2} 中的数据,请按照以下指示操作:

  • 对于 project1.table1,使用 project1 服务帐号
  • 对于 project2.table2,使用 project2 服务帐号
  • 对于 project3.table3,使用 project3 服务帐号

BigQuery 可以通过哪些方式使用我的 Cloud KMS 密钥?

BigQuery 将使用 Cloud KMS 密钥来解密数据,以响应用户查询(例如 Tabledata.listjobs.insert)。

BigQuery 还可以将密钥用于数据维护和存储优化任务,例如将数据转换为读优化格式。

如何获取更多帮助?

如果您还有尚未得到解答的其他疑问,请联系 cmek-feedback@google.com、参阅 BigQuery 支持页面或参阅 Cloud KMS 支持页面。

排查错误

下面描述了常见错误和建议的缓解措施。

错误 建议
请授予 Cloud KMS 加密密钥加密者/解密者角色 与项目关联的 BigQuery 服务帐号没有足够的 Cloud IAM 权限,无法对指定的 Cloud KMS 密钥执行操作。请按照错误消息或本文档中的说明进行操作,授予适当的 Cloud IAM 权限。
现有表加密设置与请求中指定的加密设置不匹配 如果目标表的加密设置与请求中的加密设置不匹配,则可能会发生这种情况。作为缓解措施,可使用 TRUNCATE 这一写入处置方式来替换该表,或指定其他目标表。
此区域不受支持 Cloud KMS 密钥的区域与目标表的 BigQuery 数据集的区域不匹配。作为缓解措施,可选择与数据集匹配的区域中的密钥,或加载与密钥区域匹配的数据集。

已知问题

  • BigQuery 客户端库尚不支持用于配置客户管理的加密密钥 (CMEK) 的命令。
此页内容是否有用?请给出您的反馈和评价:

发送以下问题的反馈:

此网页
需要帮助?请访问我们的支持页面