顧客管理の Cloud KMS 鍵

BigQuery はデフォルトで、コンテンツを保存時に暗号化します。BigQuery では、こうしたデフォルトの暗号化の処理と管理が自動的に行われるため、ユーザー側での操作は不要です。まず、BigQuery テーブルのデータは、「データ暗号鍵」を使用して暗号化されます。さらに、このデータ暗号鍵が「鍵暗号鍵」で暗号化されます。これはエンベロープ暗号化と呼ばれます。鍵暗号鍵はデータを直接暗号化するのではなく、Google がデータの暗号化に使用するデータ暗号鍵を暗号化するために使用されます。詳細については、Cloud Key Management Service(KMS)をご覧ください。

ユーザー自身で暗号化を制御する場合は、BigQuery の顧客管理の暗号鍵(CMEK)を使用できます。この場合、データを保護する鍵暗号鍵を Google が管理するのではなく、ユーザーが Cloud KMS で制御および管理します。このドキュメントでは、この手法について詳しく説明します。

詳細については、Google Cloud での暗号化オプションをご覧ください。CMEK の利点と制限などの特定の情報については、顧客管理の暗号鍵をご覧ください。

始める前に

  • BigQuery マネージド ストレージに存在するすべてのデータアセットは CMEK をサポートします。CMEK で暗号化されたデータが格納されている Cloud Storage などの外部データソースに保存されているデータに対してクエリを実行する場合、データの暗号化は Cloud Storage によって管理されます。たとえば、BigLake テーブルでは、Cloud Storage の CMEK で暗号化されたデータがサポートされています。

    BigQuery と BigLake テーブルは、顧客指定の暗号鍵(CSEK)をサポートしていません。

  • BigQuery と Cloud KMS を同じ Google Cloud プロジェクトで実行するか、別のプロジェクトで実行するかを決定します。以下の説明では次の表記方法を用います。

    • PROJECT_ID: BigQuery を実行するプロジェクトのプロジェクト ID
    • PROJECT_NUMBER: BigQuery を実行するプロジェクトのプロジェクト番号
    • KMS_PROJECT_ID: Cloud KMS を実行するプロジェクトのプロジェクト ID(BigQuery を実行するプロジェクトと同じプロジェクトの場合でも)
    Google Cloud プロジェクト ID とプロジェクト番号については、プロジェクトの識別をご覧ください。

  • 新しいプロジェクトでは、BigQuery が自動的に有効になります。既存のプロジェクトを使用して BigQuery を実行する場合は、BigQuery API を有効化します。

  • Cloud KMS を実行する Google Cloud プロジェクトでは、以下の操作を行います。

    1. Cloud Key Management Service API を有効にします
    2. キーリングと鍵の作成の説明に沿って、キーリングと鍵を作成します。キーリングは、BigQuery データセットのロケーションと一致するロケーションで作成します。
      • マルチリージョン データセットでは、一致するロケーションからのマルチリージョンのキーリングを使用する必要があります。たとえば、リージョン US 内のデータセットはリージョン us のキーリングで保護する必要があり、リージョン EU 内のデータセットはリージョン europe のキーリングで保護する必要があります。
      • リージョン データセットでは、一致するリージョンの鍵を使用する必要があります。たとえば、リージョン asia-northeast1 内のデータセットはリージョン asia-northeast1 のキーリングで保護する必要があります。
      • BigQuery では global リージョンの使用をサポートしていません。
      BigQuery と Cloud KMS がサポートされるロケーションの詳細については、クラウドのロケーションをご覧ください。

復号の呼び出しは、CMEK で暗号化されたテーブルへのクエリごとに 1 回、Cloud KMS を使用して実行されます。詳細については、Cloud KMS の料金をご覧ください。

暗号化仕様

BigQuery でデータを保護するために使用される Cloud KMS 鍵は、AES-256 鍵です。これらの鍵は、BigQuery で鍵暗号鍵として使用され、データを暗号化するデータ暗号鍵を暗号化します。

暗号化と復号の権限を付与する

CMEK 鍵で BigQuery データを保護するには、その鍵を使用して暗号化と復号を行う権限を BigQuery サービス アカウントに付与します。Cloud KMS 暗号鍵の暗号化 / 復号のロールによってこの権限を付与できます。

サービス アカウントが作成されていることを確認し、Google Cloud コンソールを使用して BigQuery サービス アカウント ID を確認します。次に、Cloud KMS を使用した暗号化と復号に必要なロールをサービス アカウントに付与します。

サービス アカウントの作成をトリガーする

BigQuery サービス アカウントは、プロジェクトの作成時には作成されません。サービス アカウントの作成をトリガーするには、そのサービス アカウントを使用するコマンド(bq show --encryption_service_account コマンドなど)を入力するか、projects.getServiceAccount API メソッドを呼び出します。次に例を示します。

bq show --encryption_service_account --project_id=PROJECT_ID

サービス アカウント ID を特定する

BigQuery サービス アカウント ID の形式を次に示します。

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

次の方法により、プロジェクトの BigQuery サービス アカウント ID が特定できます。

コンソール

  1. Google Cloud コンソールの [ダッシュボード] ページに移動します。

    [ダッシュボード] ページに移動する

  2. ページ上部の [選択元] プルダウン リストをクリックします。表示される [選択元] ウィンドウで、プロジェクトを選択します。

  3. プロジェクト ID とプロジェクト番号はどちらも、プロジェクト ダッシュボードの [プロジェクト情報] カードに表示されます。

    プロジェクト情報カード

  4. 次の文字列で、PROJECT_NUMBER をプロジェクト番号に置き換えたものが、BigQuery サービス アカウント ID になります。

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

bq

bq show コマンドに --encryption_service_account フラグを指定して、サービス アカウント ID を確認します。

bq show --encryption_service_account

このコマンドを実行すると、サービス アカウント ID が表示されます。

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

暗号化 / 復号の役割を割り当てる

クリップボードにコピーした BigQuery システムのサービス アカウントに Cloud KMS 暗号鍵の暗号化 / 復号のロールを割り当てます。このアカウントの形式は次のとおりです。

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

コンソール

  1. Google Cloud コンソールで、[暗号鍵] ページを開きます。

    [暗号鍵] ページを開く

  2. 鍵を含むキーリングの名前をクリックします。

  3. ロールを追加する暗号鍵のチェックボックスをクリックします。[権限] タブが開きます。

  4. [メンバーを追加] をクリックします。

  5. サービス アカウントのメールアドレス(bq-PROJECT_NUMBER@bigquery-encryption.iam.gserviceaccount.com)を入力します。

    • このサービス アカウントがすでにメンバーリストに含まれている場合、サービス アカウントには既存のロールがあります。bq-PROJECT_NUMBER@bigquery-encryption.iam.gserviceaccount.com サービス アカウントの現在のロールのプルダウン リストをクリックします。
  6. [ロールを選択] プルダウン リストをクリックし、[Cloud KMS] をクリックして、[Cloud KMS 暗号鍵の暗号化 / 復号] ロールをクリックします。

  7. [保存] をクリックして、bq-PROJECT_NUMBER@bigquery-encryption.iam.gserviceaccount.com サービス アカウントにロールを適用します。

gcloud

ロールの割り当てには、Google Cloud CLI を使用できます。

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 を実行している Google Cloud プロジェクトの ID
  • PROJECT_NUMBER: BigQuery を実行している Google Cloud プロジェクトのプロジェクト番号(プロジェクト ID ではありません)
  • KMS_KEY_LOCATION: Cloud KMS 鍵のロケーション名
  • KMS_KEY_RING: Cloud KMS 鍵のキーリング名
  • KMS_KEY: Cloud KMS 鍵の名前。

鍵のリソース ID

CMEK を使用するには、例に示すように、Cloud KMS 鍵のリソース ID が必要です。この鍵は次の形式で、大文字と小文字は区別されます。

projects/KMS_PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY

鍵のリソース ID を取得する

  1. Google Cloud コンソールで、[暗号鍵] ページを開きます。

    [暗号鍵] ページを開く

  2. 鍵を含むキーリングの名前をクリックします。

  3. リソース ID を取得したい鍵について、その他アイコン をクリックします。

  4. [リソース名をコピーする] をクリックします。鍵のリソース ID がクリップボードにコピーされます。リソース ID は、リソース名とも呼ばれます。

Cloud KMS で保護されるテーブルを作成する

Cloud KMS で保護されるテーブルを作成するには、以下のようにします。

コンソール

  1. Google Cloud コンソールで [BigQuery] ページを開きます。

    [BigQuery] ページに移動

  2. [エクスプローラ] パネルでプロジェクトを開いて、データセットを選択します。

  3. アクション オプションを開いて、[開く] をクリックします。

  4. 詳細パネルで [テーブルを作成] をクリックします。

  5. [テーブルの作成] ページで、スキーマ定義を持つ空のテーブルを作成するために必要な情報を入力します。[テーブルを作成] をクリックする前に、暗号化の種類を設定し、テーブルで使用する Cloud KMS 鍵を指定します。

    1. [詳細オプション] をクリックします。
    2. [お客様が管理する鍵] をクリックします。
    3. 鍵を選択します。使用する鍵がリストにない場合は、鍵のリソース ID を入力します。
  6. [テーブルを作成] をクリックします。

SQL

kms_key_name オプション付きで CREATE TABLE ステートメントを使用します。

  1. Google Cloud コンソールで [BigQuery] ページに移動します。

    [BigQuery] に移動

  2. クエリエディタで次のステートメントを入力します。

    CREATE TABLE DATASET_ID.TABLE_ID (
      name STRING, value INT64
    ) OPTIONS (
        kms_key_name
          = 'projects/KMS_PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY');
    

  3. [実行] をクリックします。

クエリの実行方法については、インタラクティブ クエリの実行をご覧ください。

bq

bq コマンドライン ツールで --destination_kms_key フラグを指定してテーブルを作成できます。--destination_kms_key フラグでは、テーブルで使用する鍵のリソース ID を指定します。

スキーマを使用して空のテーブルを作成するには、次のコマンドを実行します。

bq mk --schema name:string,value:integer -t \
--destination_kms_key projects/KMS_PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY \
DATASET_ID.TABLE_ID

クエリからテーブルを作成するには、次のコマンドを実行します。

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 FROM DATASET_ID.TABLE_ID WHERE gender = 'M' ORDER BY count DESC LIMIT 6"

bq コマンドライン ツールの詳細については、bq コマンドライン ツールの使用をご覧ください。

Go

このサンプルを試す前に、クライアント ライブラリを使用した BigQuery クイックスタートGo の手順に沿って設定を行ってください。詳細については、BigQuery Go API のリファレンス ドキュメントをご覧ください。

BigQuery に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。

import (
	"context"
	"fmt"

	"cloud.google.com/go/bigquery"
)

// createTableWithCMEK demonstrates creating a table protected with a customer managed encryption key.
func createTableWithCMEK(projectID, datasetID, tableID string) error {
	// projectID := "my-project-id"
	// datasetID := "mydatasetid"
	// tableID := "mytableid"
	ctx := context.Background()

	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	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/keyRings/test/cryptoKeys/test",
		},
	}
	if err := tableRef.Create(ctx, meta); err != nil {
		return err
	}
	return nil
}

Java

このサンプルを試す前に、クライアント ライブラリを使用した BigQuery クイックスタートJava の手順に沿って設定を行ってください。詳細については、BigQuery Java API のリファレンス ドキュメントをご覧ください。

BigQuery に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。

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.Field;
import com.google.cloud.bigquery.Schema;
import com.google.cloud.bigquery.StandardSQLTypeName;
import com.google.cloud.bigquery.StandardTableDefinition;
import com.google.cloud.bigquery.TableDefinition;
import com.google.cloud.bigquery.TableId;
import com.google.cloud.bigquery.TableInfo;

// Sample to create a cmek table
public class CreateTableCMEK {

  public static void runCreateTableCMEK() {
    // TODO(developer): Replace these variables before running the sample.
    String datasetName = "MY_DATASET_NAME";
    String tableName = "MY_TABLE_NAME";
    String kmsKeyName = "MY_KEY_NAME";
    Schema schema =
        Schema.of(
            Field.of("stringField", StandardSQLTypeName.STRING),
            Field.of("booleanField", StandardSQLTypeName.BOOL));
    // i.e. projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{cryptoKey}
    EncryptionConfiguration encryption =
        EncryptionConfiguration.newBuilder().setKmsKeyName(kmsKeyName).build();
    createTableCMEK(datasetName, tableName, schema, encryption);
  }

  public static void createTableCMEK(
      String datasetName, String tableName, Schema schema, EncryptionConfiguration configuration) {
    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);
      TableDefinition tableDefinition = StandardTableDefinition.of(schema);
      TableInfo tableInfo =
          TableInfo.newBuilder(tableId, tableDefinition)
              .setEncryptionConfiguration(configuration)
              .build();

      bigquery.create(tableInfo);
      System.out.println("Table cmek created successfully");
    } catch (BigQueryException e) {
      System.out.println("Table cmek was not created. \n" + e.toString());
    }
  }
}

Python

このサンプルを試す前に、クライアント ライブラリを使用した BigQuery クイックスタートPython の手順に沿って設定を行ってください。詳細については、BigQuery Python API のリファレンス ドキュメントをご覧ください。

BigQuery に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。

新しいテーブルを顧客管理の暗号鍵で保護するには、Table.encryption_configuration プロパティを EncryptionConfiguration オブジェクトに設定してからテーブルを作成します。
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}.")

Cloud KMS 鍵で保護されたテーブルのクエリ

Cloud KMS で保護されたテーブルをクエリするために、特別な準備は必要ありません。テーブルのコンテンツの暗号化に使用された鍵の名前が BigQuery に保存され、Cloud KMS で保護されたテーブルに対してクエリが行われるとその鍵が使用されます。

保護されたテーブルのコンテンツの暗号化に使用された Cloud KMS 鍵に BigQuery がアクセスできる限り、既存のすべてのツール、BigQuery コンソール、bq コマンドライン ツールはデフォルトの暗号化されたテーブルの場合と同様に振る舞います。

Cloud KMS 鍵を使用したクエリ結果の保護

デフォルトでは、クエリ結果は、Google が管理する鍵で暗号化された一時テーブルに保存されます。Cloud KMS 鍵を使用してクエリ結果を暗号化するには、次のいずれかのオプションを選択します。

コンソール

  1. Google Cloud コンソールで [BigQuery] ページを開きます。

    [BigQuery] ページに移動

  2. [クエリを新規作成] をクリックします。

  3. クエリのテキスト領域に、有効な GoogleSQL クエリを入力します。

  4. [その他] をクリックし、[クエリの設定] をクリックして、[詳細オプション] をクリックします。

  5. [顧客管理の暗号化] を選択します。

  6. 鍵を選択します。使用する鍵がリストにない場合は、鍵のリソース ID を入力します。

  7. [保存] をクリックします。

  8. [実行] をクリックします。

bq

Cloud KMS 鍵を使用して宛先テーブルやクエリ結果(一時テーブルを使用している場合)を保護するには、--destination_kms_key フラグを指定します。--destination_kms_key フラグで、宛先または結果テーブルで使用する鍵のリソース ID を指定します。

--destination_table フラグを使用して、クエリ結果の宛先を指定することもできます。--destination_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 FROM DATASET_ID.TABLE_ID WHERE gender = 'M' ORDER BY count DESC LIMIT 6"

bq コマンドライン ツールの詳細については、bq コマンドライン ツールの使用をご覧ください。

Go

import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/bigquery"
	"google.golang.org/api/iterator"
)

// queryWithDestinationCMEK demonstrates saving query results to a destination table and protecting those results
// by specifying a customer managed encryption key.
func queryWithDestinationCMEK(w io.Writer, projectID, dstDatasetID, dstTableID string) error {
	// projectID := "my-project-id"
	// datasetID := "mydataset"
	// tableID := "mytable"
	ctx := context.Background()
	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	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(dstDatasetID).Table(dstTableID)
	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",
	}
	// Run the query and print results when the query job is completed.
	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.Fprintln(w, row)
	}
	return nil
}

Java

このサンプルを試す前に、クライアント ライブラリを使用した BigQuery クイックスタートJava の手順に沿って設定を行ってください。詳細については、BigQuery Java API のリファレンス ドキュメントをご覧ください。

BigQuery に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。

新しいテーブルを顧客管理の暗号鍵で保護するには、Table.encryption_configuration プロパティを EncryptionConfiguration オブジェクトに設定してからテーブルを作成します。
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());
    }
  }
}

Python

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")

Cloud KMS で保護されているテーブルを読み込む

Cloud KMS で保護されているテーブルを読み込むには:

Console

読み込みジョブの抽出先テーブルを顧客管理の暗号鍵で保護するには、テーブルの読み込み時に鍵を指定します。

  1. Google Cloud コンソールで [BigQuery] ページを開きます。

    [BigQuery] ページに移動

  2. [エクスプローラ] パネルでプロジェクトを開いて、データセットを選択します。

  3. 詳細パネルで「テーブルを作成」をクリックします。

  4. テーブルの読み込みに使用するオプションを入力します。「テーブルを作成」をクリックする前に [詳細オプション] をクリックします。

  5. [暗号化] で、[お客様が管理する鍵] を選択します。

  6. [お客様が管理する鍵の選択] プルダウン リストをクリックして、使用する鍵を選択します。使用可能な鍵が表示されない場合は、鍵のリソース ID を入力します。

    詳細オプション

  7. [テーブルを作成] をクリックします。

bq

読み込みジョブの宛先テーブルを顧客管理の暗号鍵で保護するには、--destination_kms_key フラグを設定します。

bq --location=LOCATION load \
--autodetect \
--source_format=FORMAT \
--destination_kms_key projects/KMS_PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY \
DATASET.TABLE \
path_to_source
例:
bq load \
--autodetect \
--source_format=NEWLINE_DELIMITED_JSON \
--destination_kms_key projects/KMS_PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY \
test2.table4 \
gs://cloud-samples-data/bigquery/us-states/us-states.json

Go

import (
	"context"
	"fmt"

	"cloud.google.com/go/bigquery"
)

// importJSONWithCMEK demonstrates loading newline-delimited JSON from Cloud Storage,
// and protecting the data with a customer-managed encryption key.
func importJSONWithCMEK(projectID, datasetID, tableID string) error {
	// projectID := "my-project-id"
	// datasetID := "mydataset"
	// tableID := "mytable"
	ctx := context.Background()
	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	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())
	}

	return nil
}

Java

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());
    }
  }
}

Python

読み込みジョブの抽出先テーブルを顧客管理の暗号鍵で保護するには、LoadJobConfig.destination_encryption_configuration プロパティを EncryptionConfiguration に設定してからテーブルを読み込みます。

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")

Cloud KMS で保護されているテーブルにストリーミングする

追加のパラメータを指定しなくても、CMEK で保護されている BigQuery テーブルにデータをストリーミングできます。このデータは、最終ロケーションだけでなくバッファ内でも Cloud KMS 鍵を使用して暗号化されます。CMEK テーブルでストリーミングを使用する前に、鍵の使用可能性とアクセス可能性に関する要件を確認してください。

ストリーミングの詳細については、BigQuery へのデータのストリーミングをご覧ください。

テーブルをデフォルトの暗号化から Cloud KMS 保護に変更する

bq

デフォルトの暗号化で保護されているテーブルを、Cloud KMS で保護された新しいテーブルや、元のテーブルにコピーするには、--destination_kms_key フラグを指定した bq cp コマンドを使用します。--destination_kms_key フラグによって、宛先テーブルで使用する鍵のリソース ID を指定します。

デフォルトの暗号化が使用されているテーブルを Cloud KMS で保護された新しいテーブルにコピーするには、次のコマンドを実行します。

bq cp \
--destination_kms_key projects/KMS_PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY \
SOURCE_DATASET_ID.SOURCE_TABLE_ID DESTINATION_DATASET_ID.DESTINATION_TABLE_ID

デフォルトの暗号化が使用されているテーブルを Cloud KMS で保護して同じテーブルにコピーする場合は、次のコマンドを実行します。

bq cp -f \
--destination_kms_key projects/KMS_PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY \
DATASET_ID.TABLE_ID DATASET_ID.TABLE_ID

テーブルを Cloud KMS 保護からデフォルトの暗号化に変更する場合は、--destination_kms_key フラグを使用せずに bq cp を実行して、ファイルをそれ自体にコピーします。

bq コマンドライン ツールの詳細については、bq コマンドライン ツールの使用をご覧ください。

Go

import (
	"context"
	"fmt"

	"cloud.google.com/go/bigquery"
)

// copyTableWithCMEK demonstrates creating a copy of a table and ensuring the copied data is
// protected with a customer managed encryption key.
func copyTableWithCMEK(projectID, datasetID, tableID string) error {
	// projectID := "my-project-id"
	// datasetID := "mydataset"
	// tableID := "mytable"
	ctx := context.Background()
	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	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
	}
	return nil
}

Java

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());
    }
  }
}

Python

このサンプルを試す前に、クライアント ライブラリを使用した BigQuery クイックスタートPython の手順に沿って設定を行ってください。詳細については、BigQuery Python API のリファレンス ドキュメントをご覧ください。

BigQuery に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。

テーブルのコピー先を顧客管理の暗号鍵で保護するには、QueryJobConfig.destination_encryption_configuration プロパティの値を EncryptionConfiguration に設定してからテーブルをコピーします。

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")

テーブルが Cloud KMS によって保護されているかどうかを判別する

  1. Google Cloud コンソールで、データセットの左側にある青い矢印をクリックしてそれを開くか、データセット名をダブルクリックします。これにより、データセット内のテーブルとビューが表示されます。

  2. テーブル名をクリックします。

  3. [Details] をクリックします。[テーブル詳細] ページに、テーブルの説明とテーブル情報が表示されます。

  4. テーブルが Cloud KMS によって保護されている場合は、[顧客管理の暗号鍵] フィールドに鍵のリソース ID が表示されます。

    保護されたテーブル

BigQuery テーブルの Cloud KMS 鍵を変更する

CMEK で保護された既存テーブルの Cloud KMS 鍵を変更するには、ALTER TABLE クエリを実行するか、API または bq コマンドライン ツールを使用できます。API と bq コマンドライン ツールを使用して Cloud KMS 鍵を変更するには、updatecp を使用します。

update を使用すると、CMEK 保護のテーブルで使用されている Cloud KMS 鍵を変更できます。

cp を使用する場合は、CMEK 保護のテーブルに使用される Cloud KMS 鍵を変更でき、テーブルをデフォルトの暗号化から CMEK 保護に変更し、またはテーブルを CMEK 保護からデフォルトの暗号化に変更できます。

update のメリットは、cp より高速であること、テーブル デコレータを使用できることです。

SQL

ALTER TABLE SET OPTIONS ステートメントを使用して、テーブルの kms_key_name フィールドを更新します。

  1. Google Cloud コンソールで [BigQuery] ページに移動します。

    [BigQuery] に移動

  2. クエリエディタで次のステートメントを入力します。

    ALTER TABLE DATASET_ID.mytable
    SET OPTIONS (
      kms_key_name
        = 'projects/KMS_PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY');
    

  3. [実行] をクリックします。

クエリの実行方法については、インタラクティブ クエリの実行をご覧ください。

bq

Cloud KMS で保護されているテーブルの鍵を変更するには、--destination_kms_key フラグを指定して bq cp コマンドを使用します。--destination_kms_key フラグで、テーブルで使用する鍵のリソース ID を指定します。

bq update \
--destination_kms_key projects/KMS_PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY \
-t DATASET_ID.TABLE_ID

Go

import (
	"context"
	"fmt"

	"cloud.google.com/go/bigquery"
)

// updateTableChangeCMEK demonstrates how to change the customer managed encryption key that protects a table.
func updateTableChangeCMEK(projectID, datasetID, tableID string) error {
	// projectID := "my-project-id"
	// datasetID := "mydatasetid"
	// tableID := "mytableid"
	ctx := context.Background()

	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	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
	}
	return nil
}

Java

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());
    }
  }
}

Python

テーブルの顧客管理の暗号鍵を変更するには、Table.encryption_configuration プロパティを新しい EncryptionConfiguration オブジェクトに変更してからテーブルを更新します。

# 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

データセットのデフォルト鍵を設定する

データセット全体のデフォルト Cloud KMS 鍵を設定できます。この鍵は、テーブルの作成時に別の Cloud KMS 鍵を指定しない限り、データセットに新しく作成されたすべてのテーブルに適用されます。デフォルト鍵は、既存のテーブルには適用されません。デフォルト鍵を変更しても、既存のテーブルは変更されません。この鍵は、変更後に作成された新しいテーブルにのみ適用されます。

データセットのデフォルト鍵は、次の方法で適用、変更または削除できます。

  • datasets.insert または datasets.patch メソッドを呼び出すときに、EncryptionConfiguration.kmsKeyName フィールドにデフォルト鍵を指定する

  • bq mk --dataset コマンドを実行するときに --default_kms_key フラグでデフォルト鍵を指定する

    bq mk \
    --default_kms_key projects/KMS_PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY \
    --dataset DATASET_ID
    
    bq update \
    --default_kms_key projects/KMS_PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY \
    --dataset DATASET_ID
    

プロジェクトのデフォルト鍵を設定する

別の Cloud KMS 鍵を指定しない限り、プロジェクト内のすべてのデフォルト Cloud KMS 鍵を設定できます。この鍵は、プロジェクト内のすべてのクエリの結果と新しく作成されたテーブルに適用されます。デフォルト鍵は、既存のテーブルには適用されません。デフォルト鍵を変更しても、既存のテーブルは変更されません。この鍵は、変更後に作成された新しいテーブルにのみ適用されます。

SQL

ALTER PROJECT SET OPTIONS ステートメントを使用して、プロジェクトの default_kms_key_name フィールドを更新します。鍵のリソース名は Cloud KMS ページに表示されます。

  1. Google Cloud コンソールで [BigQuery] ページに移動します。

    [BigQuery] に移動

  2. クエリエディタで次のステートメントを入力します。

    ALTER PROJECT PROJECT_ID
    SET OPTIONS (
      region-us.default_kms_key_name
        = 'projects/KMS_PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY');
    

  3. [実行] をクリックします。

クエリの実行方法については、インタラクティブ クエリの実行をご覧ください。

bq

bq コマンドを使用して ALTER PROJECT SET OPTIONS ステートメントを実行し、プロジェクトの default_kms_key_name フィールドを更新できます。

bq query --nouse_legacy_sql \
  'ALTER PROJECT PROJECT_ID
  SET OPTIONS (
  `region-us.default_kms_key_name`
    ="projects/KMS_PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY");'

CMEK を使用して BigQuery ML モデルを保護する

BigQuery ML は CMEK をサポートしています。BigQuery が提供するデフォルトの暗号化に加え、独自の Cloud Key Management Service 鍵を使用して、インポートした TensorFlow モデルなど、ML モデルを暗号化できます。

Cloud KMS 鍵を使用して暗号化されたモデルを作成する

暗号化されたモデルを作成するには、CREATE MODEL ステートメントを使用し、トレーニング オプションで KMS_KEY_NAME を指定します。

    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

インポートした TensorFlow モデルにも同じ構文が適用されます。

    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

制限事項

顧客管理の暗号鍵には、ML モデルを暗号化する際に次の制限があります。

モデルをデフォルトの暗号化から Cloud KMS 保護に変更する

--destination_kms_key フラグを指定して bq cp コマンドを使用し、デフォルトの暗号化で保護されているモデルを Cloud KMS で保護される新しいモデルにコピーします。または、-f フラグを指定して bq cp コマンドを使用し、デフォルトの暗号化によって保護されているモデルを上書きして、代わりに Cloud KMS 保護を使用するように更新することもできます。--destination_kms_key フラグでは、宛先モデルで使用する鍵のリソース ID を指定します。

デフォルトの暗号化が使用されているモデルを、Cloud KMS で保護された新しいモデルにコピーするには、次のコマンドを実行します。

bq cp \
--destination_kms_key projects/KMS_PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY \
SOURCE_DATASET_ID.SOURCE_MODEL_ID DESTINATION_DATASET_ID.DESTINATION_MODEL_ID

デフォルトの暗号化が使用されているモデルを Cloud KMS で保護されている同じモデルに上書きするには:

bq cp -f \
--destination_kms_key projects/KMS_PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY \
DATASET_ID.MODEL_ID DATASET_ID.MODEL_ID

モデルを Cloud KMS 保護からデフォルトの暗号化に変更するには:

bq cp -f \
DATASET_ID.MODEL_ID DATASET_ID.MODEL_ID

bq コマンドライン ツールの詳細については、bq コマンドライン ツールの使用をご覧ください。

モデルが Cloud KMS によって保護されているかどうかを確かめる

bq show コマンドを使用して、モデルが Cloud KMS 鍵で保護されているかどうかを確認します。暗号鍵は kmsKeyName フィールドにあります。

bq show -m my_dataset.my_model

Google Cloud コンソールを使用して、暗号化されたモデルの Cloud KMS 鍵を確認することもできます。CMEK 情報は、モデルの [詳細] ペインの [モデルの詳細] セクションにある [顧客管理の暗号鍵] フィールドに表示されます。

暗号化されたモデルの Cloud KMS 鍵を変更する

Cloud KMS で保護されているモデルの鍵を変更するには、--destination_kms_key フラグを指定して bq update コマンドを使用します。

bq update --destination_kms_key \
projects/my_project/locations/my_location/keyRings/my_ring/cryptoKeys/my_key \
-t my_dataset.my_model

デフォルトのプロジェクト鍵またはデータセット鍵を使用する

デフォルトの Cloud KMS 鍵をプロジェクト レベルまたはデータセット レベルで設定している場合、BigQuery ML はモデルの作成時にこの鍵を自動的に使用します。デフォルトの鍵を使用しない場合は、CREATE MODEL ステートメントを使用して、モデルを暗号化する別の鍵を指定します。

暗号化されたモデルで BigQuery ML 関数を使用する

暗号鍵を指定せずに、暗号化されたモデルですべての BigQuery ML 関数を使用できます。

Cloud KMS 鍵への BigQuery のアクセス権を削除する

Cloud KMS 鍵への BigQuery のアクセス権は、その鍵の Identity and Access Management(IAM)権限を取り消すことで、いつでも削除できます。

BigQuery が Cloud KMS 鍵へのアクセス権を失うと、ユーザー エクスペリエンスが大幅に低下し、データが失われる可能性があります。

  • その CMEK で保護されているテーブルのデータにアクセスできなくなります。querycpextracttabledata.list はすべて失敗します。

  • その CMEK で保護されているテーブルに新しいデータを追加できません。

  • アクセス権を付与し直した後も、数日間は、そのテーブルへのクエリのパフォーマンスが低下する可能性があります。

組織ポリシーで CMEK の使用を管理する

BigQuery が CMEK の組織ポリシー制約と統合することで、組織内の BigQuery リソースの暗号化コンプライアンス要件を指定できるようになります。

このインテグレーションにより、次のことが可能になります。

  • プロジェクト内のすべての BigQuery リソースに対して CMEK を必須にする。

  • プロジェクト内のリソースの保護に使用できる Cloud KMS 鍵を制限する。

すべてのリソースに対して CMEK を必須にする

一般的なポリシーでは、複数の具体的なプロジェクトで、すべてのリソースを保護するために CMEK を使用する必要があります。BigQuery では、constraints/gcp.restrictNonCmekServices 制約を使用してこのポリシーを適用できます。

この組織のポリシーを設定すると、指定された Cloud KMS 鍵を持たないすべてのリソース作成リクエストは失敗します。

このポリシーを設定すると、それはプロジェクト内の新しいリソースにのみ適用されます。Cloud KMS 鍵が設定されていない既存のリソースは引き続き存在し、問題なくアクセスできます。

コンソール

  1. [組織のポリシー] ページを開きます。

    [組織のポリシー] に移動

  2. [フィルタ] フィールドに「constraints/gcp.restrictNonCmekServices」と入力し、[CMEK を使用せずにリソースを作成できるサービスを制限する] をクリックします。

  3. [ 編集] をクリックします。

  4. [カスタマイズ] を選択して [置換] を選択し、[ルールを追加] をクリックします。

  5. [カスタム] を選択した後、[拒否] をクリックします。

  6. [カスタム値] フィールドに「is:bigquery.googleapis.com」と入力します。

  7. [完了] をクリックし、[保存] をクリックします。

gcloud

  gcloud resource-manager org-policies --project=PROJECT_ID \
    deny gcp.restrictNonCmekServices is:bigquery.googleapis.com

ポリシーが正常に適用されていることを確認するために、プロジェクトにテーブルを作成してみることができます。Cloud KMS 鍵を指定しない限り、プロセスは失敗します。

このポリシーは、プロジェクトのクエリ結果のテーブルにも適用されます。プロジェクトのデフォルト鍵を指定すると、ユーザーがプロジェクトでクエリを実行するたびに手動でキーを指定する必要がなくなります。

BigQuery プロジェクトの Cloud KMS 鍵を制限する

BigQuery プロジェクトでは、constraints/gcp.restrictCmekCryptoKeyProjects 制約を使用してリソースの保護に使用できる Cloud KMS 鍵を制限できます。

たとえば、「projects/my-company-data-project のすべての BigQuery リソースに対して、このプロジェクトで使用される Cloud KMS 鍵は projects/my-company-central-keys または projects/team-specific-keys からのものでなければならない」というルールを指定できます。

コンソール

  1. [組織のポリシー] ページを開きます。

    [組織のポリシー] に移動

  2. [フィルタ] フィールドに「constraints/gcp.restrictCmekCryptoKeyProjects」と入力し、[CMEK 用の KMS CryptoKey を提供するプロジェクトを制限する] をクリックします。

  3. [ 編集] をクリックします。

  4. [カスタマイズ] を選択して [置換] を選択し、[ルールを追加] をクリックします。

  5. [カスタム] を選択し、[許可] をクリックします。

  6. [カスタム値] フィールドに「under:projects/<var>KMS_PROJECT_ID</var>」と入力します。

  7. [完了] をクリックし、[保存] をクリックします。

gcloud

  gcloud resource-manager org-policies --project=PROJECT_ID \
    allow gcp.restrictCmekCryptoKeyProjects under:projects/KMS_PROJECT_ID

ポリシーが正常に適用されていることを確認するには、別のプロジェクトの Cloud KMS 鍵を使用してテーブルを作成してみることができます。このプロセスは失敗します。

組織のポリシーの制限事項

組織のポリシーの設定には、関連する制限事項がいくつかあります。

伝播遅延

組織のポリシーを設定または更新してから、新しいポリシーが有効になるまで最大 15 分かかることがあります。BigQuery は、クエリとテーブルの作成レイテンシに悪影響を及ぼさないように、ポリシーをキャッシュに保存します。

組織のポリシーを設定するために必要な権限

組織のポリシーを、テスト目的で設定または更新する権限の取得は難しい場合があります。組織ポリシー管理者ロールが付与されている必要があります。このロールは、プロジェクト レベルやフォルダレベルではなく、組織レベルでのみ付与できます。

そのロールは組織レベルで付与する必要がありますが、特定のプロジェクトやフォルダにのみ適用されるポリシーを指定することもできます。

Cloud KMS 鍵のローテーションによる影響

テーブルに関連付けられている Cloud KMS 鍵のローテーションが行われても、BigQuery がそのテーブルの暗号鍵のローテーションを自動的に行うことはありません。既存のテーブル内のすべてのデータは、作成時に使用された鍵バージョンによって引き続き保護されます。

新しく作成されたテーブルは、作成時にメインの鍵バージョンを使用します。

テーブルを更新して最新の鍵バージョンを使用するには、テーブルを別の Cloud KMS 鍵に変更した後、元の鍵バージョンに戻します。

Cloud KMS 料金への影響

CMEK で保護されたテーブルの作成またはトランケートを行うと、BigQuery は中間の鍵暗号鍵を生成し、この鍵は指定した Cloud KMS 鍵で暗号化されます。

請求に関しては、Cloud KMS の呼び出しも関連する費用もテーブルサイズに合わせてスケーリングされることはありません。CMEK で保護されているテーブルの場合、テーブルの作成またはトランケーションごとに Cloud KMS cryptoKeys.encrypt が 1 回呼び出され、クエリに関連するテーブルごとに Cloud KMS cryptoKeys.decrypt が 1 回呼び出されることが想定されます。これらのメソッドは両方とも、Cloud KMS の料金に記載されている鍵オペレーション: 暗号のカテゴリに属します。

CMEK で保護された既存のテーブルを対象に読み取りまたは書き込みを行うと、中間鍵を復号する必要があるため、Cloud KMS cryptoKeys.decrypt が呼び出されます。

制限事項

Cloud KMS 鍵への BigQuery のアクセス

Cloud KMS 鍵は、次の場合に BigQuery で使用でき、アクセス可能とみなされます。

  • その鍵が有効になっている
  • BigQuery サービス アカウントに、その鍵に対する暗号化および復号の権限がある

以下のセクションでは、鍵にアクセスできない場合のストリーミング挿入と長期間アクセスできないデータへの影響について説明します。

ストリーミング挿入への影響

Cloud KMS 鍵は、ストリーミング挿入リクエスト後の 48 時間で 24 時間以上連続して利用可能かつアクセス可能である必要があります。鍵が利用できず、アクセスもできない場合、ストリーミング データは完全には保持されず、失われる可能性があります。ストリーミング挿入の詳細については、BigQuery へのデータのストリーミングをご覧ください。

長期間アクセスできないデータへの影響

BigQuery はマネージド ストレージを提供するため、長期間アクセスできないデータは BigQuery のアーキテクチャと互換性がありません。特定の BigQuery テーブルの Cloud KMS 鍵が 60 日間連続して利用不可かつアクセス不可である場合、BigQuery はそのテーブルと関連データを削除することを選択することがあります。データが削除される少なくとも 7 日前までに、BigQuery は請求先アカウントに関連付けられたメールアドレスにメールを送信します。

外部データソースの使用

CMEK で暗号化されたデータが格納されている Cloud Storage などの外部データソースに保存されているデータに対してクエリを実行する場合、データの暗号化は Cloud Storage によって管理されます。たとえば、BigLake テーブルでは、Cloud Storage の CMEK で暗号化されたデータがサポートされています。

BigQuery と BigLake テーブルは、顧客指定の暗号鍵(CSEK)をサポートしていません。

CMEK の暗号化とデフォルトの暗号化の切り替え

デフォルトの暗号化と CMEK の暗号化の間でテーブルを切り替えることはできません。暗号化を切り替えるには、設定された宛先の暗号化情報とともにテーブルをコピーするか、WRITE_TRUNCATE 処理で SELECT * クエリを使用してテーブル自体を選択します。

テーブル デコレータの使用

Cloud KMS でテーブルを保護してから、loadcpquery 演算について値 WRITE_TRUNCATE を使用してテーブルのデータを置き換える場合、範囲デコレータは暗号化の変更境界を越えて動作しません。範囲デコレータなどのテーブル デコレータを使用して、境界前後のデータに対してクエリを実行できます。また、ある時点でスナップショットをクエリすることもできます。

ワイルドカード テーブルクエリ

CMEK で保護されているテーブルをワイルドカード サフィックスでクエリすることはできません。

エディションのサポート

BigQuery に対する CMEK のサポートは、BigQuery Enterprise Plus と BigQuery On-Demand でのみ使用できます。 2023 年 7 月 5 日より前に BigQuery の定額料金の予約をしているお客様は、Enterprise ティアで CMEK の既存のサポートをすべて維持できます。

よくある質問

Cloud KMS 鍵への権限が必要なのは誰ですか?

顧客管理の暗号鍵を使用している場合、権限を繰り返し指定する必要はありません。Cloud KMS 鍵を使用して暗号化と復号を行う権限が BigQuery サービス アカウントにある限り、BigQuery テーブルへのアクセス権限を持つユーザーは、Cloud KMS 鍵への直接アクセス権がないユーザーであっても、データにアクセスできます。

どのサービス アカウントが使用されますか?

テーブルの Google Cloud プロジェクトに関連付けられている BigQuery サービス アカウントが、そのテーブルのデータを復号するために使用されます。BigQuery サービス アカウントはプロジェクトごとに一意です。Cloud KMS で保護されている匿名テーブルにデータを書き込むジョブでは、そのジョブのプロジェクトのサービス アカウントが使用されます。

たとえば、table1table2table3 という CMEK で保護されている 3 つのテーブルについて考えてみます。宛先テーブルを {project3.table3} として {project1.table1, project2.table2} からデータをクエリする場合は、次のようになります。

  • project1.table1 に対しては project1 のサービス アカウントが使用される
  • project2.table2 に対しては project2 のサービス アカウントが使用される
  • project3.table3 に対しては project3 のサービス アカウントが使用される

BigQuery では、どのように Cloud KMS 鍵を使用できますか?

BigQuery は Cloud KMS 鍵を使用して、ユーザークエリに応答してデータを復号します。次に例を示します。tabledata.listまたはjobs.insert

BigQuery では、データを読み取りに最適化された形式に変換するなど、データのメンテナンスやストレージ最適化タスクにもこの鍵を使用できます。

どの暗号ライブラリが使用されていますか?

BigQuery は CMEK 機能を Cloud KMS に依存しています。 Cloud KMS は Tink を暗号化に使用します。

追加のサポートを得る方法

不明な点がある場合は、BigQuery のサポートをご覧ください。

エラーのトラブルシューティング

よくあるエラーと推奨される軽減策について以下に説明します。

エラー 推奨
Please grant Cloud KMS CryptoKey Encrypter/Decrypter role プロジェクトに関連付けられる BigQuery サービス アカウントに、指定した Cloud KMS 鍵を操作するのに十分な IAM 権限がありません。エラー メッセージ内またはこのドキュメントの手順に従って、適切な IAM 権限を付与してください。
Existing table encryption settings do not match encryption settings specified in the request このエラーは、宛先テーブルの暗号化設定がリクエストの暗号化設定と一致しない場合に発生することがあります。軽減策として、書き込み処理 TRUNCATE を使用してテーブルを置き換えるか、別の宛先テーブルを指定します。
This region is not supported Cloud KMS 鍵のリージョンが、宛先テーブルの BigQuery データセットのリージョンと一致していません。軽減策として、データセットに一致するリージョンにある鍵を選択するか、鍵リージョンに一致するデータセットに読み込みます。
管理者からの要請により、プロジェクト PROJECT_ID. 内のクエリには暗号鍵を指定する必要があります。 組織のポリシーでは、リソースの作成やクエリの実行が禁止されています。このポリシーの詳細については、BigQuery プロジェクトのすべてのリソースに対して CMEK を必須にするをご覧ください。
管理者は、プロジェクト KMS_PROJECT_ID の KMS 鍵を使用してプロジェクト PROJECT_ID のリソースを保護することを禁止しています。 組織のポリシーでは、リソースの作成やクエリの実行が禁止されています。このポリシーの詳細については、BigQuery プロジェクトの Cloud KMS 鍵を制限するをご覧ください。