Stay organized with collectionsSave and categorize content based on your preferences.
Customer-managed Cloud KMS keys
By default, BigQueryencrypts your content stored at rest.
BigQuery handles and manages this default encryption for you
without any additional actions on your part. First, data in a
BigQuery table is encrypted using adata encryption key. Then,
those data encryption keys are encrypted withkey encryption keys, which is
known asenvelope encryption. Key encryption
keys don't directly encrypt your data but are used to encrypt the data
encryption keys that Google uses to encrypt your data.
If you want to control encryption yourself, you can use customer-managed
encryption keys (CMEK) for BigQuery. Instead of Google owning and
managing the key encryption keys that protect your data, you control and manage
key encryption keys inCloud KMS. This document provides
details about this technique.
All data assets residing in BigQuery managed storage support
CMEK. However, if you are also querying data stored in anexternal data sourcesuch as Cloud Storage that has CMEK-encrypted
data, then the data encryption is managed byCloud Storage.
For example, BigLake tables support data encrypted with CMEK in
Cloud Storage.
BigQuery andBigLake tablesdon't support Customer-Supplied Encryption Keys (CSEK).
Decide whether you are going to run BigQuery and
Cloud KMS in the same Google Cloud project, or in different
projects. For documentation example purposes, the following convention is used:
PROJECT_ID: the project ID of the project running
BigQuery
PROJECT_NUMBER: the project number of the project
running BigQuery
KMS_PROJECT_ID: the project ID of the project
running Cloud KMS (even if this is the same project running
BigQuery)
For information about Google Cloud project IDs and project numbers, seeIdentifying projects.
BigQuery is automatically enabled in new projects. If you are
using a pre-existing project to run BigQuery,enable the BigQuery API.
A decryption call is performed using Cloud KMS once per query to a
CMEK-encrypted table. For more information, seeCloud KMS pricing.
Encryption specification
Cloud KMS keys used to protect your data in BigQuery are
AES-256 keys. These keys are used as key encryption keys in
BigQuery, in that they encrypt the data encryption keys that
encrypt your data.
Manual or automated key creation
You can either create your CMEK keys manually or use Cloud KMS Autokey
(Preview). Autokey simplifies creating and
managing your CMEK keys by automating provisioning and assignment. With
Autokey, you don't need to provision key rings, keys, and service
accounts ahead of time. Instead, they are generated on demand as part of
BigQuery resource creation. For more information, see theAutokey overview.
Manually create key ring and key
For the Google Cloud project that runs Cloud KMS, create a key ring
and a key as described inCreating key rings and keys. Create the key ring in a
location that matches the location of your BigQuery dataset:
Any multi-regional dataset should use a multi-regional key ring from a
matching location. For examples, a dataset in regionUSshould be
protected with a key ring from regionus, and a dataset in regionEUshould be protected with a key ring from regioneurope.
Regional datasets should use matching regional keys. For example,
a dataset in regionasia-northeast1should be protected with a key
ring from regionasia-northeast1.
You can't use theglobalregion when configuring CMEK for
BigQuery in the Google Cloud console. However, you can
use theglobalregion when configuring CMEK for
BigQuery by using the bq command-line tool or GoogleSQL.
For more information about the supported locations for BigQuery
and Cloud KMS, seeCloud locations.
Grant encryption and decryption permission
To protect your BigQuery data with a CMEK key, grant the
BigQuery service account permission to encrypt and decrypt using
that key. TheCloud KMS CryptoKey Encrypter/Decrypterrole grants this permission.
Make sure your service account has been created, and then use the
Google Cloud console
to determine the BigQuery service
account ID. Next, provide the service account with the appropriate role to
encrypt
and decrypt using Cloud KMS.
Trigger creation of your service account
Your BigQuery service account is not initially created when you
create a project. To trigger the creation of your service
account, enter a command that uses it, such as thebq show --encryption_service_accountcommand, or call theprojects.getServiceAccountAPI method. For example:
bq show --encryption_service_account --project_id=PROJECT_ID
Assign the Cloud KMS CryptoKey Encrypter/Decrypterroleto the
BigQuery system service account that you copied to your
clipboard. This account is of the form:
Click the name of the key ring that contains the key.
Click the checkbox for the encryption key to which you want to add the
role. ThePermissionstab opens.
ClickAdd member.
Enter the email address of the service account,bq-PROJECT_NUMBER@bigquery-encryption.iam.gserviceaccount.com.
If the service account is already on the members list, it has
existing roles. Click the current role drop-down list for thebq-PROJECT_NUMBER@bigquery-encryption.iam.gserviceaccount.comservice account.
Click the drop-down list forSelect a role, clickCloud KMS, and
then click theCloud KMS CryptoKey Encrypter/Decrypterrole.
ClickSaveto apply the role to thebq-PROJECT_NUMBER@bigquery-encryption.iam.gserviceaccount.comservice
account.
gcloud
You can use the Google Cloud CLI to assign the role:
In theExplorerpanel, expand your project and select a dataset.
Expand themore_vertActionsoption and clickOpen.
In the details panel, clickCreate tableadd_box.
On theCreate tablepage, fill in the information needed tocreate an empty table with a schema definition.
Before you clickCreate Table, set the encryption type and specify the
Cloud KMS key to use with the table:
ClickAdvanced options.
ClickCustomer-managed key.
Select the key. If the key you want to use is not listed, enter theresource IDfor the key.
In the query editor, enter the following statement:
CREATE TABLEDATASET_ID.TABLE_ID(
name STRING, value INT64
)OPTIONS(
kms_key_name
= 'projects/KMS_PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY');
You can use the bq command-line tool with the--destination_kms_keyflag
to create the table. The--destination_kms_keyflag specifies theresource IDof the key to use with the table.
Set the default Google Cloud project
where you want to apply your Terraform configurations.
You only need to run this command once per project, and you can run it in any directory.
export GOOGLE_CLOUD_PROJECT=PROJECT_ID
Environment variables are overridden if you set explicit values in the Terraform
configuration file.
Prepare the directory
Each Terraform configuration file must have its own directory (also
called aroot module).
InCloud Shell, create a directory and a new
file within that directory. The filename must have the.tfextension—for examplemain.tf. In this
tutorial, the file is referred to asmain.tf.
mkdirDIRECTORY&& cdDIRECTORY&& touch main.tf
If you are following a tutorial, you can copy the sample code in each section or step.
Copy the sample code into the newly createdmain.tf.
Optionally, copy the code from GitHub. This is recommended
when the Terraform snippet is part of an end-to-end solution.
Review and modify the sample parameters to apply to your environment.
Save your changes.
Initialize Terraform. You only need to do this once per directory.
terraform init
Optionally, to use the latest Google provider version, include the-upgradeoption:
terraform init -upgrade
Apply the changes
Review the configuration and verify that the resources that Terraform is going to create or
update match your expectations:
terraform plan
Make corrections to the configuration as necessary.
Apply the Terraform configuration by running the following command and enteringyesat the prompt:
terraform apply
Wait until Terraform displays the "Apply complete!" message.
Open your Google Cloud projectto view
the results. In the Google Cloud console, navigate to your resources in the UI to make sure
that Terraform has created or updated them.
from google.cloud import bigquery
client = bigquery.Client()
# TODO(dev): Change table_id to the full name of the table you want to create.
table_id = "your-project.your_dataset.your_table_name"
# 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/your-project/locations/us/keyRings/test/cryptoKeys/test"
table = bigquery.Table(table_id)
table.encryption_configuration = bigquery.EncryptionConfiguration(
kms_key_name=kms_key_name
)
table = client.create_table(table) # API request
print(f"Created {table_id}.")
print(f"Key: {table.encryption_configuration.kms_key_name}.")
Query a table protected by a Cloud KMS key
No special arrangements are required to query a table protected by
Cloud KMS. BigQuery stores the name of the key used to
encrypt the table content and uses that key when a table protected by
Cloud KMS is queried.
All existing tools, the BigQuery console, and the bq command-line tool run
the same way as with default-encrypted tables, as long as
BigQuery has access to the Cloud KMS key used to encrypt
the table content.
Protect query results with a Cloud KMS key
By default, query results are stored in a temporary table encrypted with a
Google-owned and Google-managed key. If the project already has adefault key,
the key is applied to the temporary (default) query results table. To use a
Cloud KMS key to encrypt your query results instead, select one of the
following options:
Console
Open the BigQuery page in the Google Cloud console.
Enter a valid GoogleSQL query in the query text area.
ClickMore, clickQuery settings, then clickAdvanced options.
SelectCustomer-managed encryption.
Select the key. If the key you want to use is not listed, enter theresource IDfor the key.
ClickSave.
ClickRun.
bq
Specify the flag--destination_kms_keyto protect the destination table or
query results (if using a temporary table) with your Cloud KMS key.
The--destination_kms_keyflag specifies theresource IDof the key to use with the destination or
resulting table.
Optionally use the--destination_tableflag to specify the destination for
query results. If--destination_tableis not used, the query results are
written to a temporary table.
To query a table:
bq query \
--destination_table=DATASET_ID.TABLE_ID\
--destination_kms_key projects/KMS_PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY\
"SELECT name,count FROMDATASET_ID.TABLE_IDWHERE gender = 'M' ORDER BY count DESC LIMIT 6"
import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.EncryptionConfiguration;
import com.google.cloud.bigquery.QueryJobConfiguration;
import com.google.cloud.bigquery.TableResult;
// Sample to query on destination table with encryption key
public class QueryDestinationTableCMEK {
public static void runQueryDestinationTableCMEK() {
// TODO(developer): Replace these variables before running the sample.
String datasetName = "MY_DATASET_NAME";
String tableName = "MY_TABLE_NAME";
String kmsKeyName = "MY_KMS_KEY_NAME";
String query =
String.format("SELECT stringField, booleanField FROM %s.%s", datasetName, tableName);
EncryptionConfiguration encryption =
EncryptionConfiguration.newBuilder().setKmsKeyName(kmsKeyName).build();
queryDestinationTableCMEK(query, encryption);
}
public static void queryDestinationTableCMEK(String query, EncryptionConfiguration encryption) {
try {
// Initialize client that will be used to send requests. This client only needs to be created
// once, and can be reused for multiple requests.
BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();
QueryJobConfiguration config =
QueryJobConfiguration.newBuilder(query)
// Set the encryption key to use for the destination.
.setDestinationEncryptionConfiguration(encryption)
.build();
TableResult results = bigquery.query(config);
results
.iterateAll()
.forEach(row -> row.forEach(val -> System.out.printf("%s,", val.toString())));
System.out.println("Query performed successfully with encryption key.");
} catch (BigQueryException | InterruptedException e) {
System.out.println("Query not performed \n" + e.toString());
}
}
}
from google.cloud import bigquery
# Construct a BigQuery client object.
client = bigquery.Client()
# TODO(developer): Set table_id to the ID of the destination table.
# table_id = "your-project.your_dataset.your_table_name"
# Set the encryption key to use for the destination.
# TODO(developer): Replace this key with a key you have created in KMS.
# kms_key_name = "projects/{}/locations/{}/keyRings/{}/cryptoKeys/{}".format(
# your-project, location, your-ring, your-key
# )
job_config = bigquery.QueryJobConfig(
destination=table_id,
destination_encryption_configuration=bigquery.EncryptionConfiguration(
kms_key_name=kms_key_name
),
)
# Start the query, passing in the extra configuration.
query_job = client.query(
"SELECT 17 AS my_col;", job_config=job_config
) # Make an API request.
query_job.result() # Wait for the job to complete.
table = client.get_table(table_id) # Make an API request.
if table.encryption_configuration.kms_key_name == kms_key_name:
print("The destination table is written using the encryption configuration")
Load a table protected by Cloud KMS
To load a data file into a table that is protected by Cloud KMS:
Console
Protect a load job destination table with a customer-managed encryption key
by specifying the key when you load the table.
Open the BigQuery page in the Google Cloud console.
import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.EncryptionConfiguration;
import com.google.cloud.bigquery.FormatOptions;
import com.google.cloud.bigquery.Job;
import com.google.cloud.bigquery.JobInfo;
import com.google.cloud.bigquery.LoadJobConfiguration;
import com.google.cloud.bigquery.TableId;
// Sample to load JSON data with configuration key from Cloud Storage into a new BigQuery table
public class LoadJsonFromGCSCMEK {
public static void runLoadJsonFromGCSCMEK() {
// TODO(developer): Replace these variables before running the sample.
String datasetName = "MY_DATASET_NAME";
String tableName = "MY_TABLE_NAME";
String kmsKeyName = "MY_KMS_KEY_NAME";
String sourceUri = "gs://cloud-samples-data/bigquery/us-states/us-states.json";
// i.e. projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{cryptoKey}
EncryptionConfiguration encryption =
EncryptionConfiguration.newBuilder().setKmsKeyName(kmsKeyName).build();
loadJsonFromGCSCMEK(datasetName, tableName, sourceUri, encryption);
}
public static void loadJsonFromGCSCMEK(
String datasetName, String tableName, String sourceUri, EncryptionConfiguration encryption) {
try {
// Initialize client that will be used to send requests. This client only needs to be created
// once, and can be reused for multiple requests.
BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();
TableId tableId = TableId.of(datasetName, tableName);
LoadJobConfiguration loadConfig =
LoadJobConfiguration.newBuilder(tableId, sourceUri)
// Set the encryption key to use for the destination.
.setDestinationEncryptionConfiguration(encryption)
.setFormatOptions(FormatOptions.json())
.setAutodetect(true)
.build();
// Load data from a GCS JSON file into the table
Job job = bigquery.create(JobInfo.of(loadConfig));
// Blocks until this load table job completes its execution, either failing or succeeding.
job = job.waitFor();
if (job.isDone()) {
System.out.println("Table loaded succesfully from GCS with configuration key");
} else {
System.out.println(
"BigQuery was unable to load into the table due to an error:"
+ job.getStatus().getError());
}
} catch (BigQueryException | InterruptedException e) {
System.out.println("Column not added during load append \n" + e.toString());
}
}
}
from google.cloud import bigquery
# Construct a BigQuery client object.
client = bigquery.Client()
# TODO(developer): Set table_id to the ID of the table to create.
# table_id = "your-project.your_dataset.your_table_name
# 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", "test", "test"
# )
job_config = bigquery.LoadJobConfig(
autodetect=True,
source_format=bigquery.SourceFormat.NEWLINE_DELIMITED_JSON,
destination_encryption_configuration=bigquery.EncryptionConfiguration(
kms_key_name=kms_key_name
),
)
uri = "gs://cloud-samples-data/bigquery/us-states/us-states.json"
load_job = client.load_table_from_uri(
uri,
table_id,
location="US", # Must match the destination dataset location.
job_config=job_config,
) # Make an API request.
assert load_job.job_type == "load"
load_job.result() # Waits for the job to complete.
assert load_job.state == "DONE"
table = client.get_table(table_id)
if table.encryption_configuration.kms_key_name == kms_key_name:
print("A table loaded with encryption configuration key")
Stream into a table protected by Cloud KMS
You can stream data into your CMEK-protected BigQuery table
without specifying any additional parameters. Note that this data is encrypted
using your Cloud KMS key in the buffer as well as in the final
location. Before using streaming with a CMEK table, review the requirements onkey availability and accessibility.
Change a table from default encryption to Cloud KMS protection
bq
You can use thebq cpcommand with the--destination_kms_keyflag
to copy a table protected by default encryption into a new table, or into
the original table, protected by Cloud KMS. The--destination_kms_keyflag specifies theresource IDof the key to use with the destination table.
To copy a table that has default encryption to a new table that has
Cloud KMS protection:
If you want to change a table from Cloud KMS protection to default
encryption, copy the file to itself by runningbq cpwithout using the--destination_kms_keyflag.
import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.CopyJobConfiguration;
import com.google.cloud.bigquery.EncryptionConfiguration;
import com.google.cloud.bigquery.Job;
import com.google.cloud.bigquery.JobInfo;
import com.google.cloud.bigquery.TableId;
// Sample to copy a cmek table
public class CopyTableCMEK {
public static void runCopyTableCMEK() {
// TODO(developer): Replace these variables before running the sample.
String destinationDatasetName = "MY_DESTINATION_DATASET_NAME";
String destinationTableId = "MY_DESTINATION_TABLE_NAME";
String sourceDatasetName = "MY_SOURCE_DATASET_NAME";
String sourceTableId = "MY_SOURCE_TABLE_NAME";
String kmsKeyName = "MY_KMS_KEY_NAME";
EncryptionConfiguration encryption =
EncryptionConfiguration.newBuilder().setKmsKeyName(kmsKeyName).build();
copyTableCMEK(
sourceDatasetName, sourceTableId, destinationDatasetName, destinationTableId, encryption);
}
public static void copyTableCMEK(
String sourceDatasetName,
String sourceTableId,
String destinationDatasetName,
String destinationTableId,
EncryptionConfiguration encryption) {
try {
// Initialize client that will be used to send requests. This client only needs to be created
// once, and can be reused for multiple requests.
BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();
TableId sourceTable = TableId.of(sourceDatasetName, sourceTableId);
TableId destinationTable = TableId.of(destinationDatasetName, destinationTableId);
// For more information on CopyJobConfiguration see:
// https://googleapis.dev/java/google-cloud-clients/latest/com/google/cloud/bigquery/JobConfiguration.html
CopyJobConfiguration configuration =
CopyJobConfiguration.newBuilder(destinationTable, sourceTable)
.setDestinationEncryptionConfiguration(encryption)
.build();
// For more information on Job see:
// https://googleapis.dev/java/google-cloud-clients/latest/index.html?com/google/cloud/bigquery/package-summary.html
Job job = bigquery.create(JobInfo.of(configuration));
// Blocks until this job completes its execution, either failing or succeeding.
Job completedJob = job.waitFor();
if (completedJob == null) {
System.out.println("Job not executed since it no longer exists.");
return;
} else if (completedJob.getStatus().getError() != null) {
System.out.println(
"BigQuery was unable to copy table due to an error: \n" + job.getStatus().getError());
return;
}
System.out.println("Table cmek copied successfully.");
} catch (BigQueryException | InterruptedException e) {
System.out.println("Table cmek copying job was interrupted. \n" + e.toString());
}
}
}
from google.cloud import bigquery
# Construct a BigQuery client object.
client = bigquery.Client()
# TODO(developer): Set dest_table_id to the ID of the destination table.
# dest_table_id = "your-project.your_dataset.your_table_name"
# TODO(developer): Set orig_table_id to the ID of the original table.
# orig_table_id = "your-project.your_dataset.your_table_name"
# Set the encryption key to use for the destination.
# TODO(developer): Replace this key with a key you have created in KMS.
# kms_key_name = "projects/{}/locations/{}/keyRings/{}/cryptoKeys/{}".format(
# your-project, location, your-ring, your-key
# )
job_config = bigquery.CopyJobConfig(
destination_encryption_configuration=bigquery.EncryptionConfiguration(
kms_key_name=kms_key_name
)
)
job = client.copy_table(orig_table_id, dest_table_id, job_config=job_config)
job.result() # Wait for the job to complete.
dest_table = client.get_table(dest_table_id) # Make an API request.
if dest_table.encryption_configuration.kms_key_name == kms_key_name:
print("A copy of the table created")
Determine if a table is protected by Cloud KMS
In the Google Cloud console, click the blue arrow to
the left of your dataset to expand it, or double-click the dataset name. This
displays the tables and views in the dataset.
Click the table name.
ClickDetails. TheTable Detailspage displays the table's
description and table information.
If the table is protected by Cloud KMS, theCustomer-Managed
Encryption Keyfield displays the key resource ID.
For each of the keys you've created or that protect your tables, you can see
what resources that key protects with key usage tracking. For more information,
seeView key usage.
Change the Cloud KMS key for a BigQuery table
To change the Cloud KMS key of an existing CMEK-protected table, you
can run anALTER TABLEquery, use the API, or use the bq command-line tool.
There are two ways to modify the Cloud KMS key using the API and the
bq command-line tool:updateorcp.
If you useupdate, you can change the Cloud KMS key used for a
CMEK-protected table.
If you usecp, you can change the Cloud KMS key used for a
CMEK-protected table, change a table from default encryption to CMEK-protection,
or change a table from CMEK-protection to default encryption.
An advantage ofupdateis it is faster thancpand it lets you usetable decorators.
You can use thebq cpcommand with the--destination_kms_keyflag
to change the key for a table protected by Cloud KMS. The--destination_kms_keyflag specifies theresource IDof the key to use with the table.
import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.EncryptionConfiguration;
import com.google.cloud.bigquery.Table;
import com.google.cloud.bigquery.TableId;
// Sample to update a cmek table
public class UpdateTableCMEK {
public static void runUpdateTableCMEK() {
// TODO(developer): Replace these variables before running the sample.
String datasetName = "MY_DATASET_NAME";
String tableName = "MY_TABLE_NAME";
String kmsKeyName = "MY_KEY_NAME";
// Set a new encryption key to use for the destination.
// i.e. projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{cryptoKey}
EncryptionConfiguration encryption =
EncryptionConfiguration.newBuilder().setKmsKeyName(kmsKeyName).build();
updateTableCMEK(datasetName, tableName, encryption);
}
public static void updateTableCMEK(
String datasetName, String tableName, EncryptionConfiguration encryption) {
try {
// Initialize client that will be used to send requests. This client only needs to be created
// once, and can be reused for multiple requests.
BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();
Table table = bigquery.getTable(TableId.of(datasetName, tableName));
bigquery.update(table.toBuilder().setEncryptionConfiguration(encryption).build());
System.out.println("Table cmek updated successfully");
} catch (BigQueryException e) {
System.out.println("Table cmek was not updated. \n" + e.toString());
}
}
}
# 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/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
Set a dataset default key
You can set a dataset-wide default Cloud KMS key that applies to all
newly created tables within the dataset, unless a different Cloud KMS
key is specified when you create the table. The default key does not apply to
existing tables. Changing the default key does not modify any existing tables
and applies only to new tables created after the change.
You can apply, change, or remove a dataset default key by
You can set project-default Cloud KMS keys that apply to all
query results and newly created tables in the project for that location, unless
you specify a different Cloud KMS key. The default key does not apply
to existing tables. Changing the default key does not modify any existing tables
and applies only to new tables created after the change.
SQL
Use theALTER PROJECT SET OPTIONSstatementto update thedefault_kms_key_namefield for a project. You can find the
resource name for the key on the Cloud KMS page.
In the Google Cloud console, go to theBigQuerypage.
In the query editor, enter the following statement:
ALTER PROJECTPROJECT_IDSETOPTIONS(region-<var>LOCATION</var>.default_kms_key_name= 'projects/KMS_PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY');
BigQuery ML supports CMEK. Along with the default encryption provided
by BigQuery, you can use your own Cloud Key Management Service keys for encrypting
machine learning models, including imported TensorFlow models.
Create an encrypted model with a Cloud KMS key
To create an encrypted model, use theCREATE MODELstatementand specifyKMS_KEY_NAMEin the training options:
CREATE MODEL my_dataset.my_model
OPTIONS(
model_type='linear_reg',
input_label_cols=['your_label'],
kms_key_name='projects/my_project/locations/my_location/keyRings/my_ring/cryptoKeys/my_key')
AS SELECT * FROM my_dataset.my_data
The same syntax also applies to imported TensorFlow models:
CREATE MODEL my_dataset.my_model
OPTIONS(
model_type='tensorflow',
path='gs://bucket/path/to/saved_model/*',
kms_key_name='projects/my_project/locations/my_location/keyRings/my_ring/cryptoKeys/my_key')
AS SELECT * FROM my_dataset.my_data
Limitations
Customer-managed encryption keys have the following restrictions when
encrypting machine learning models:
Globalregion CMEK keys are not supported for the following
types of models:
Globalregion CMEK keys and multi-region CMEK keys, for exampleEUorUS, are not supported when creatingAutoML Tables models.
Change a model from default encryption to Cloud KMS protection
You can use thebq cpcommandwith the--destination_kms_keyflag to copy a model protected by default
encryption into a new model that is protected by Cloud KMS.
Alternatively, you can use thebq cpcommand with the-fflag to overwrite a
model protected by default encryption and update it to use Cloud KMS
protection instead. The--destination_kms_keyflag specifies theresource IDof the key to use with the destination model.
To copy a model that has default encryption to a new model that has
Cloud KMS protection:
Use thebq showcommandto see if a model is protected by Cloud KMS key. The
encryption key is in thekmsKeyNamefield.
bq show -m my_dataset.my_model
You can also use the Google Cloud console to find the Cloud KMS
key for an encrypted model. CMEK information is in theCustomer-managed keyfield in theModel Detailssection of the model'sDetailspane.
Change the Cloud KMS key for an encrypted model
Use thebq updatecommandwith
the--destination_kms_keyflag to change the key for a model protected by
Cloud KMS:
If you have a default Cloud KMS key set at the project or dataset level,
BigQuery ML automatically uses this key when creating models.
Use theCREATE MODELstatement to specify a different key to encrypt the model
if you don't want to use the default key.
Use BigQuery ML functions with encrypted models
You can use all BigQuery ML functions with an encrypted model
without specifying an encryption key.
Use CMEK to protect BigQuery Connection API
For Cloud SQL connections, you can protect your BigQuery Connection API credentials using CMEK.
You can remove BigQuery's access to the Cloud KMS key at
any time, by revoking the Identity and Access Management (IAM) permission for that key.
If BigQuery loses access to the Cloud KMS key, the user
experience can suffer significantly and data loss can occur:
Data in these CMEK-protected tables can no longer be accessed:query,cp,extract, andtabledata.listwill all fail.
No new data can be added to these CMEK-protected tables.
After access is granted back, the performance of queries to these tables
can be degraded for multiple days.
Control CMEK use with organization policy
BigQuery integrates with CMEKorganization policy constraintsto let you specify encryption compliance requirements for
BigQuery resources in your organization.
This integration lets you do the following:
Require CMEKs for all BigQuery resources in a project.
Restrict which Cloud KMS keys can be used to protect resources in a
project.
Require CMEKs for all resources
A common policy is to require CMEKs to be used to protect all resources in a
specific set of projects. You can use theconstraints/gcp.restrictNonCmekServicesconstraint to enforce this policy in
BigQuery.
If set, this organization policy causes all resource creation requests without a
specified Cloud KMS key to fail.
After you set this policy, it applies only to new resources in the project. Any
existing resources without Cloud KMS keys set continue to exist and are
accessible without issue.
To verify that the policy is successfully applied, you can try to create a table
in the project. The process fails unless you specify a Cloud KMS
key.
This policy also applies to query results tables in the project. You can specify
aproject default keyso users don't have to manually
specify a key each time they execute a query in the project.
Restrict Cloud KMS keys for a BigQuery project
You can use theconstraints/gcp.restrictCmekCryptoKeyProjectsconstraint to
restrict the Cloud KMS keys that you can use to protect a resource in a
BigQuery project.
You might specify a rule - for example, "For all BigQuery
resources in projects/my-company-data-project, Cloud KMS keys used in
this project must come from projects/my-company-central-keys OR
projects/team-specific-keys."
To verify that the policy is successfully applied, you can try to create a table
using a Cloud KMS key from a different project. The process will fail.
Limitations of organization policies
There are limitations associated with setting an organization policy.
Propagation delay
After you set or update an organization policy, it can take up to 15 minutes
for the new policy to take effect. BigQuery caches policies in
order to not negatively affect query and table creation latency.
Required permissions to set an organization policy
The permission to set or update the organization policy might be difficult to
acquire for testing purposes. You must be granted theOrganization Policy Administrator role,
which can only be granted at the organization level (rather than the project or
folder level).
Although the role must be granted at the organization level, it is still
possible to specify a policy that only applies to a specific project
or folder.
Impact of Cloud KMS key rotation
BigQuery doesn't automatically rotate a table encryption key when
the Cloud KMS key associated with the table is rotated. All data in the
existing tables continue to be protected by the key version with which they were
created.
Any newly-created tables use the primary key version at the time of their
creation.
To update a table to use the most recent key version, change the table to a
different Cloud KMS key and then back to the original.
Impact on Cloud KMS billing
When you create or truncate a CMEK-protected table, BigQuery
generates an intermediate key-encryption key which is then encrypted with the
specified Cloud KMS key.
For billing purposes, this means that neither your calls to Cloud KMS
nor their associated costs scale with the table size. For CMEK-protected tables,
You can expect one call to Cloud KMScryptoKeys.encryptfor each table creation or truncation and one call to Cloud KMScryptoKeys.decryptfor each table involved in a query. These methods both belong to the category ofKey operations: Cryptographiclisted inCloud KMS Pricing.
Either reading from or writing to an existing CMEK-protected table invokes
Cloud KMScryptoKeys.decryptbecause the intermediate key must be
decrypted.
Limitations
BigQuery access to the Cloud KMS key
A Cloud KMS key is considered available and accessible by
BigQuery under the following conditions:
The BigQuery service account has encrypt and decrypt
permissions on the key
The following sections describe impact to streaming inserts and long-term
inaccessible data when a key is inaccessible.
Impact to streaming inserts
The Cloud KMS key must be available and accessible for at least 24
consecutive hours in the 48-hour period following a streaming insertion request.
If the key is not available and accessible, the streamed data might not be fully
persisted and can be lost. For more information about streaming inserts, seeStreaming data into BigQuery.
Impact to long-term inaccessible data
As BigQuery provides managed storage, long-term inaccessible data
is not compatible with BigQuery's architecture. If the
Cloud KMS key of a given BigQuery table is not available
and not accessible for 60 consecutive days, BigQuery might choose
to delete the table and its associated data. At least 7 days before the
data is deleted, BigQuery sends an email to the email address
associated with the billing account.
Using external data sources
If you are querying data stored in anexternal data sourcesuch as Cloud Storage that has CMEK-encrypted
data, then the data encryption is managed byCloud Storage.
For example, BigLake tables support data encrypted with CMEK in
Cloud Storage.
BigQuery andBigLake tablesdon't support Customer-Supplied Encryption Keys (CSEK).
Switching between CMEK-protected and default encryption
You cannot switch a table in place between default encryptions and CMEK
encryption. To switch encryption,copy the
tablewith destination encryption
information set or use aSELECT *query to select the table into itself withWRITE_TRUNCATEdisposition.
Using table decorators
If you protect a table with Cloud KMS and then replace the data in the
table by using the valueWRITE_TRUNCATEfor aload,cp, orqueryoperation, thenrange decoratorsdon't work across the encryption change boundary. You can still use table
decorators, including range decorators, to query the data before or after the
boundary, or query the snapshot at a point in time.
Wildcard table queries
CMEK-protected tables cannot be queried with awildcard
suffix.
Editions support
CMEK support for BigQuery is only available for
BigQuery Enterprise Plus and BigQuery On-Demand.
BigQuery customers of legacy flat-rate reservations prior to July
5, 2023, retain all existing support for CMEK in the Enterprise tier.
With customer-managed encryption keys, specifying permissions repeatedly is not
required. As long as the BigQuery service account has permission
to use the Cloud KMS key to encrypt and decrypt, anyone with permission
to the BigQuery table can access the data, even if they
don't have direct access to the Cloud KMS key.
Which service account is used?
The BigQuery service account associated with the
Google Cloud project of the table is used to decrypt that table's data.
The BigQuery service accounts are unique for each project. For a
job that writes data into a Cloud KMS-protected anonymous table, the
job's project's service account is used.
As an example, consider three CMEK-protected tables:table1,table2, andtable3. To query data from{project1.table1, project2.table2}with
destination table{project3.table3}:
Use theproject1service account forproject1.table1
Use theproject2service account forproject2.table2
Use theproject3service account forproject3.table3
In what ways can BigQuery use my Cloud KMS key?
BigQuery uses the Cloud KMS key to decrypt data in
response to a user query, for example,tabledata.listorjobs.insert.
BigQuery can also use the key for data maintenance and storage
optimization tasks, like data conversion into a read-optimized format.
What cryptography libraries are used?
BigQuery relies on Cloud KMS for CMEK functionality.
Cloud KMS usesTinkfor
encryption.
How to get more help?
If you have questions that are not answered here, seeBigQuery support.
Troubleshooting errors
The following describes common errors and recommended mitigations.
Error
Recommendation
Please grant Cloud KMS CryptoKey Encrypter/Decrypter role
The BigQuery service account associated with your project
doesn't have sufficient IAM permission to operate on the
specified Cloud KMS key. Follow the instructions in the error orin this documentationto grant the proper
IAM permission.
Existing table encryption settings do not match encryption settings
specified in the request
This can occur in scenarios where the destination table has encryption
settings that don't match the encryption settings in your request. As
mitigation, use write dispositionTRUNCATEto replace the table,
or specify a different destination table.
This region is not supported
The region of the Cloud KMS key does not match the region of the
BigQuery dataset of the destination table. As a mitigation,
select a key in a region that matches your dataset, or load into a dataset
that matches the key region.
Your administrator requires that you specify an encryption key for queries
in projectPROJECT_ID.