Halaman ini menjelaskan cara menggunakan kunci enkripsi yang dikelola pelanggan (CMEK) untuk Spanner.
Untuk mempelajari CMEK lebih lanjut, lihat Kunci enkripsi yang dikelola pelanggan (CMEK).
Membuat database yang mendukung CMEK
Buat kunci di Cloud Key Management Service (Cloud KMS). Spanner mendukung:
Kunci tersebut harus berada di lokasi yang sama dengan instance Spanner Anda. Misalnya, jika konfigurasi instance Spanner Anda adalah
us-west1
, lokasi key ring Anda juga harusus-west1
.Tidak semua konfigurasi instance multi-region Spanner memiliki lokasi key ring yang sesuai di Cloud KMS. Anda tidak akan dapat membuat database yang mendukung CMEK di instance Spanner tersebut.
Jika sudah memiliki kunci Cloud KMS di lokasi yang benar, Anda dapat melewati langkah ini.
Untuk informasi selengkapnya, lihat resource berikut:
Beri Spanner akses ke kunci tersebut.
- Di Cloud Shell, buat dan tampilkan akun layanan yang dikelola Google,
Di Cloud Shell, buat dan tampilkan akun layanan yang dikelola Google, atau tampilkan jika akun tersebut sudah ada:
gcloud beta services identity create --service=spanner.googleapis.com \ --project=my-spanner-project
Jika Anda diminta untuk menginstal komponen Perintah gcloud Beta, ketik
Y
. Setelah penginstalan, perintah akan otomatis dimulai ulang.Perintah gcloud services identity membuat atau mendapatkan akun layanan yang dikelola Google khusus yang dapat digunakan Spanner untuk mengakses kunci Cloud KMS atas nama Anda.
ID akun layanan memiliki format seperti alamat email:
Service identity created: service-xxx@gcp-sa-spanner.iam.gserviceaccount.com
Berikan peran
cloudkms.cryptoKeyEncrypterDecrypter
ke akun layanan tersebut:gcloud kms keys add-iam-policy-binding my-kms-key \ --location my-kms-key-location \ --keyring my-kms-key-ring \ --project=my-kms-project \ --member serviceAccount:service-xxx@gcp-sa-spanner.iam.gserviceaccount.com \ --role roles/cloudkms.cryptoKeyEncrypterDecrypter
Anda akan melihat:
Updated IAM policy for key [my-kms-key]
Peran ini memastikan akun layanan memiliki izin untuk mengenkripsi dan mendekripsi dengan kunci Cloud KMS. Untuk mengetahui informasi selengkapnya, lihat Izin dan Peran Cloud KMS.
Buat database dan tentukan kunci Cloud KMS Anda.
Konsol
1. Buka halaman Instance Spanner di Konsol Google Cloud.
2. Klik nama instance untuk membuat database.
3. Klik Buat database dan isi kolom yang wajib diisi.
4. Klik Tampilkan opsi enkripsi.
5. Pilih Gunakan kunci enkripsi yang dikelola pelanggan (CMEK).
6. Pilih kunci dari menu drop-down.
Daftar kunci dibatasi untuk project Google Cloud saat ini. Untuk menggunakan kunci dari project Google Cloud lain, buat database menggunakan gcloud, bukan Konsol Google Cloud.
Setelah database dibuat, Anda dapat memverifikasi bahwa database tersebut telah mendukung CMEK dengan melihat halaman Database details.
gcloud
gcloud spanner databases create example-db \ --project=my-spanner-project \ --instance=my-spanner-instance \ --ddl="CREATE TABLE Users (Id INT64 NOT NULL, FirstName STRING(100) NOT NULL, LastName STRING(100) NOT NULL,) PRIMARY KEY (Id)" \ --kms-project=my-kms-project \ --kms-location=my-kms-key-location \ --kms-keyring=my-kms-key-ring \ --kms-key=my-kms-key
Untuk memverifikasi bahwa database mendukung CMEK:
gcloud spanner databases describe example-db \ --project=my-spanner-project \ --instance=my-spanner-instance
Database yang mendukung CMEK menyertakan kolom untuk
encryptionConfig
, seperti ditunjukkan dalam contoh berikut:encryptionConfig: kmsKeyName:projects/my-kms-project/locations/eur5/keyRings/my-kms-key-ring/cryptoKeys/my-kms-key name: projects/my-spanner-project/instances/my-instance/databases/my-db state: READY
C#
using Google.Cloud.Spanner.Admin.Database.V1; using Google.Cloud.Spanner.Common.V1; using System; using System.Threading.Tasks; public class CreateDatabaseWithEncryptionKeyAsyncSample { public async Task<Database> CreateDatabaseWithEncryptionKeyAsync(string projectId, string instanceId, string databaseId, CryptoKeyName kmsKeyName) { // Create a DatabaseAdminClient instance that can be used to execute a // CreateDatabaseRequest with custom encryption configuration options. DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.Create(); // Define create table statement for table #1. var createSingersTable = @"CREATE TABLE Singers ( SingerId INT64 NOT NULL, FirstName STRING(1024), LastName STRING(1024), ComposerInfo BYTES(MAX) ) PRIMARY KEY (SingerId)"; // Define create table statement for table #2. var createAlbumsTable = @"CREATE TABLE Albums ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, AlbumTitle STRING(MAX) ) PRIMARY KEY (SingerId, AlbumId), INTERLEAVE IN PARENT Singers ON DELETE CASCADE"; // Create the CreateDatabase request with encryption configuration and execute it. var request = new CreateDatabaseRequest { ParentAsInstanceName = InstanceName.FromProjectInstance(projectId, instanceId), CreateStatement = $"CREATE DATABASE `{databaseId}`", ExtraStatements = { createSingersTable, createAlbumsTable }, EncryptionConfig = new EncryptionConfig { KmsKeyNameAsCryptoKeyName = kmsKeyName, }, }; var operation = await databaseAdminClient.CreateDatabaseAsync(request); // Wait until the operation has finished. Console.WriteLine("Waiting for the operation to finish."); var completedResponse = await operation.PollUntilCompletedAsync(); if (completedResponse.IsFaulted) { Console.WriteLine($"Error while creating database: {completedResponse.Exception}"); throw completedResponse.Exception; } var database = completedResponse.Result; Console.WriteLine($"Database {database.Name} created with encryption key {database.EncryptionConfig.KmsKeyName}"); return database; } }
C++
Go
Java
Node.js
PHP
Python
Ruby
# project_id = "Your Google Cloud project ID" # instance_id = "Your Spanner instance ID" # database_id = "Your Spanner database ID" # kms_key_name = "Database eencryption KMS key" require "google/cloud/spanner" spanner = Google::Cloud::Spanner.new project: project_id instance = spanner.instance instance_id job = instance.create_database database_id, statements: [ "CREATE TABLE Singers ( SingerId INT64 NOT NULL, FirstName STRING(1024), LastName STRING(1024), SingerInfo BYTES(MAX) ) PRIMARY KEY (SingerId)", "CREATE TABLE Albums ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, AlbumTitle STRING(MAX) ) PRIMARY KEY (SingerId, AlbumId), INTERLEAVE IN PARENT Singers ON DELETE CASCADE" ], encryption_config: { kms_key_name: kms_key_name } puts "Waiting for create database operation to complete" job.wait_until_done! database = job.database puts "Database #{database.database_id} created with encryption key #{database.encryption_config.kms_key_name}"
Lihat versi kunci yang digunakan
Informasi tentang versi kunci berasal dari kolom encryption_info
database.
Saat versi kunci database berubah, perubahan tersebut tidak segera diterapkan
ke encryption_info
. Mungkin ada penundaan sebelum perubahan diterapkan di kolom info.
Konsol
Informasi enkripsi ditampilkan di halaman Database details.
gcloud
Dapatkan encryption_info
database dengan memanggil
databases describe
atau
databases list
. Contoh:
gcloud spanner databases describe example-db \
--project=my-spanner-project \
--instance=my-spanner-instance
Berikut output-nya:
name: projects/my-project/instances/test-instance/databases/example-db
encryptionConfig:
kmsKeyName: projects/google.com:cloud-spanner-demo/locations/us-central1/keyRings/cmek_demo/cryptoKeys/backup-key
encryptionInfo:
encryptionType: CUSTOMER_MANAGED_ENCRYPTION
Nonaktifkan kunci
Nonaktifkan versi kunci yang digunakan dengan mengikuti petunjuk ini untuk setiap versi kunci.
Tunggu hingga perubahan tersebut diterapkan. Proses penonaktifan kunci dapat memerlukan waktu hingga 3 jam.
Pastikan data tidak lagi dapat diakses:
gcloud spanner databases execute-sql example-db \ --project=my-spanner-project \ --instance=my-spanner-instance \ --sql='SELECT * FROM Users'
Anda akan melihat error berikut:
KMS key required by the Spanner resource is not accessible.
Aktifkan kunci
Aktifkan versi kunci yang digunakan oleh database dengan mengikuti petunjuk ini untuk setiap versi kunci.
Tunggu hingga perubahan tersebut diterapkan. Diperlukan waktu hingga 3 jam untuk menerapkan kunci.
Pastikan bahwa data dapat diakses:
gcloud spanner databases execute-sql example-db \ --project=my-spanner-project \ --instance=my-spanner-instance \ --sql='SELECT * FROM Users'
Jika perubahan telah diterapkan, perintah akan berhasil dijalankan.
Mencadangkan database
Secara default, cadangan yang dibuat dari database menggunakan konfigurasi enkripsi yang sama dengan database itu sendiri. Secara opsional, Anda dapat menentukan konfigurasi enkripsi yang berbeda untuk cadangan.
Untuk membuat cadangan:
Konsol
Buka halaman Database details di Cloud Console.
Pada tab Pencadangan/Pemulihan, klik Buat.
Masukkan nama cadangan dan pilih tanggal habis masa berlaku.
Pilih Use a customer-managed encryption key (CMEK) dan pilih kunci dari menu drop-down.
Klik Create.
Tabel Cadangan menampilkan informasi enkripsi untuk setiap cadangan.
gcloud
gcloud spanner backups create my-backup \
--project=my-spanner-project \
--instance=my-spanner-instance \
--database=example-db \
--retention-period=1y --async
Untuk memastikan bahwa cadangan yang dibuat dienkripsi CMEK:
gcloud spanner backups describe my-backup \
--project=my-spanner-project \
--instance=my-spanner-instance
C#
using Google.Cloud.Spanner.Admin.Database.V1;
using Google.Cloud.Spanner.Common.V1;
using Google.Protobuf.WellKnownTypes;
using System;
using System.Threading.Tasks;
public class CreateBackupWithEncryptionKeyAsyncSample
{
public async Task<Backup> CreateBackupWithEncryptionKeyAsync(string projectId, string instanceId, string databaseId, string backupId, CryptoKeyName kmsKeyName)
{
// Create a DatabaseAdminClient instance.
DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.Create();
// Create the CreateBackupRequest with encryption configuration.
CreateBackupRequest request = new CreateBackupRequest
{
ParentAsInstanceName = InstanceName.FromProjectInstance(projectId, instanceId),
BackupId = backupId,
Backup = new Backup
{
DatabaseAsDatabaseName = DatabaseName.FromProjectInstanceDatabase(projectId, instanceId, databaseId),
ExpireTime = DateTime.UtcNow.AddDays(14).ToTimestamp(),
},
EncryptionConfig = new CreateBackupEncryptionConfig
{
EncryptionType = CreateBackupEncryptionConfig.Types.EncryptionType.CustomerManagedEncryption,
KmsKeyNameAsCryptoKeyName = kmsKeyName,
},
};
// Execute the CreateBackup request.
var operation = await databaseAdminClient.CreateBackupAsync(request);
Console.WriteLine("Waiting for the operation to finish.");
// Poll until the returned long-running operation is complete.
var completedResponse = await operation.PollUntilCompletedAsync();
if (completedResponse.IsFaulted)
{
Console.WriteLine($"Error while creating backup: {completedResponse.Exception}");
throw completedResponse.Exception;
}
var backup = completedResponse.Result;
Console.WriteLine($"Backup {backup.Name} of size {backup.SizeBytes} bytes " +
$"was created at {backup.CreateTime} " +
$"using encryption key {kmsKeyName}");
return backup;
}
}
C++
Go
Java
Node.js
PHP
Python
Ruby
# project_id = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"
# backup_id = "Your Spanner backup ID"
# kms_key_name = "Your backup encryption database KMS key"
require "google/cloud/spanner"
spanner = Google::Cloud::Spanner.new project: project_id
client = spanner.client instance_id, database_id
instance = spanner.instance instance_id
database = instance.database database_id
expire_time = Time.now + 14 * 24 * 3600 # 14 days from now
encryption_config = {
encryption_type: :CUSTOMER_MANAGED_ENCRYPTION,
kms_key_name: kms_key_name
}
job = database.create_backup backup_id, expire_time, version_time: version_time, encryption_config: encryption_config
puts "Backup operation in progress"
job.wait_until_done!
backup = instance.backup backup_id
puts "Backup #{backup.backup_id} of size #{backup.size_in_bytes} bytes was created at #{backup.create_time} using encryption key #{kms_key_name}"
Memulihkan dari cadangan
Secara default, database yang dipulihkan dari cadangan menggunakan konfigurasi enkripsi yang sama dengan cadangan itu sendiri, tetapi Anda dapat mengganti perilaku ini dengan menentukan konfigurasi enkripsi yang berbeda untuk database yang dipulihkan. Jika cadangan dilindungi oleh CMEK, versi kunci yang digunakan untuk membuat cadangan harus tersedia agar dapat didekripsi.
Untuk memulihkan database:
Konsol
Buka halaman Instance details di Cloud Console.
Di tab Cadangkan/Pulihkan, pilih cadangan, lalu klik Pulihkan.
Pilih instance yang akan dipulihkan, lalu beri nama database yang dipulihkan.
Jika Anda ingin menggunakan CMEK dengan database yang dipulihkan, pilih Use a customer-managed encryption key (CMEK), lalu pilih kunci dari menu drop-down.
gcloud
gcloud spanner databases restore --async \
--project=my-spanner-project \
--destination-instance=destination-instance \
--destination-database=example-db-restored \
--source-instance=my-spanner-instance \
--source-backup=my-backup
Pastikan database yang dipulihkan dienkripsi CMEK:
gcloud spanner databases describe example-db-restored \
--project=my-spanner-project \
--instance=destination-instance
Untuk informasi selengkapnya, lihat Memulihkan database dari cadangan.
C#
using Google.Cloud.Spanner.Admin.Database.V1;
using Google.Cloud.Spanner.Common.V1;
using System;
using System.Threading.Tasks;
public class RestoreDatabaseWithEncryptionAsyncSample
{
public async Task<Database> RestoreDatabaseWithEncryptionAsync(string projectId, string instanceId, string databaseId, string backupId, CryptoKeyName kmsKeyName)
{
// Create a DatabaseAdminClient instance.
DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.Create();
// Create the RestoreDatabaseRequest with encryption configuration.
RestoreDatabaseRequest request = new RestoreDatabaseRequest
{
ParentAsInstanceName = InstanceName.FromProjectInstance(projectId, instanceId),
DatabaseId = databaseId,
BackupAsBackupName = BackupName.FromProjectInstanceBackup(projectId, instanceId, backupId),
EncryptionConfig = new RestoreDatabaseEncryptionConfig
{
EncryptionType = RestoreDatabaseEncryptionConfig.Types.EncryptionType.CustomerManagedEncryption,
KmsKeyNameAsCryptoKeyName = kmsKeyName,
}
};
// Execute the RestoreDatabase request.
var operation = await databaseAdminClient.RestoreDatabaseAsync(request);
Console.WriteLine("Waiting for the operation to finish.");
// Poll until the returned long-running operation is complete.
var completedResponse = await operation.PollUntilCompletedAsync();
if (completedResponse.IsFaulted)
{
Console.WriteLine($"Error while restoring database: {completedResponse.Exception}");
throw completedResponse.Exception;
}
var database = completedResponse.Result;
var restoreInfo = database.RestoreInfo;
Console.WriteLine($"Database {restoreInfo.BackupInfo.SourceDatabase} " +
$"restored to {database.Name} " +
$"from backup {restoreInfo.BackupInfo.Backup} " +
$"using encryption key {database.EncryptionConfig.KmsKeyName}");
return database;
}
}
C++
Go
Java
Node.js
PHP
Python
Ruby
# project_id = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID of where to restore"
# backup_id = "Your Spanner backup ID"
# kms_key_name = "Your backup encryption database KMS key"
require "google/cloud/spanner"
spanner = Google::Cloud::Spanner.new project: project_id
instance = spanner.instance instance_id
backup = instance.backup backup_id
encryption_config = {
encryption_type: :CUSTOMER_MANAGED_ENCRYPTION,
kms_key_name: kms_key_name
}
job = backup.restore database_id, encryption_config: encryption_config
puts "Waiting for restore backup operation to complete"
job.wait_until_done!
database = job.database
restore_info = database.restore_info
puts "Database #{restore_info.backup_info.source_database_id} was restored to #{database.database_id} from backup #{restore_info.backup_info.backup_id} using encryption key #{database.encryption_config.kms_key_name}"
Melihat log audit untuk kunci Cloud KMS
Pastikan logging diaktifkan untuk Cloud KMS API di project Anda.
Buka Logs Explorer di Cloud Console.
Batasi entri log ke kunci Cloud KMS Anda dengan menambahkan baris berikut ke Builder kueri:
resource.type="cloudkms_cryptokey" resource.labels.location="my-kms-key-location" resource.labels.key_ring_id="my-kms-key-ring" resource.labels.crypto_key_id="my-kms-key"
Dalam operasi normal, tindakan enkripsi dan dekripsi dicatat ke dalam log dengan tingkat keparahan
INFO
. Entri ini dicatat ke dalam log saat zona di instance Spanner Anda mengkueri kunci Cloud KMS setiap 5 menit sekali.Jika Spanner gagal mengakses kunci, operasinya akan dicatat ke dalam log sebagai
ERROR
.