Auf dieser Seite wird beschrieben, wie Sie vom Kunden verwaltete Verschlüsselungsschlüssel (CMEK) für Spanner verwenden.
Weitere Informationen zu CMEK finden Sie unter Vom Kunden verwaltete Verschlüsselungsschlüssel (CMEK).
CMEK-fähige Datenbank erstellen
Erstellen Sie einen Schlüssel im Cloud Key Management Service (Cloud KMS). Spanner unterstützt:
Der Schlüssel muss sich am selben Speicherort wie die Spanner-Instanz befinden. Wenn die Spanner-Instanzkonfiguration beispielsweise auf
us-west1
festgelegt ist, muss der Speicherort des Schlüsselbunds ebenfallsus-west1
sein.Nicht jede multiregionale Instanzkonfiguration von Spanner hat einen entsprechenden Schlüsselbund-Speicherort in Cloud KMS. Sie können in diesen Spanner-Instanzen keine CMEK-fähigen Datenbanken erstellen.
Wenn Sie bereits einen Cloud KMS-Schlüssel am richtigen Speicherort haben, können Sie diesen Schritt überspringen.
Weitere Informationen finden Sie in den folgenden Ressourcen:
Gewähren Sie Spanner Zugriff auf den Schlüssel.
- Erstellen Sie in Cloud Shell das von Google verwaltete Dienstkonto und rufen Sie es auf.
Erstellen und rufen Sie in Cloud Shell das von Google verwaltete Dienstkonto auf oder rufen Sie es auf, wenn das Konto bereits vorhanden ist:
gcloud beta services identity create --service=spanner.googleapis.com \ --project=my-spanner-project
Wenn Sie aufgefordert werden, die Komponente gcloud Beta Commands zu installieren, geben Sie
Y
ein. Nach der Installation wird der Befehl automatisch neu gestartet.Mit dem Befehl gcloud services Identity wird das spezielle von Google verwaltete Dienstkonto erstellt oder abgerufen, mit dem Spanner in Ihrem Namen auf den Cloud KMS-Schlüssel zugreifen kann.
Die Dienstkonto-ID ist wie eine E-Mail-Adresse formatiert:
Service identity created: service-xxx@gcp-sa-spanner.iam.gserviceaccount.com
Weisen Sie dem Dienstkonto die Rolle
cloudkms.cryptoKeyEncrypterDecrypter
zu: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
Sie sehen dann Folgendes:
Updated IAM policy for key [my-kms-key]
Diese Rolle sorgt dafür, dass das Dienstkonto die Berechtigung zum Verschlüsseln und Entschlüsseln mit dem Cloud KMS-Schlüssel hat. Weitere Informationen finden Sie unter Cloud KMS-Berechtigungen und -Rollen.
Erstellen Sie die Datenbank und geben Sie Ihren Cloud KMS-Schlüssel an.
Console
1. Rufen Sie in der Google Cloud Console die Seite Spanner-Instanzen auf.
2. Klicken Sie auf den Namen der Instanz, in der die Datenbank erstellt werden soll.
3. Klicken Sie auf Datenbank erstellen und füllen Sie die Pflichtfelder aus.
4. Klicken Sie auf Verschlüsselungsoptionen anzeigen.
5. Wählen Sie Vom Kunden verwalteten Verschlüsselungsschlüssel (CMEK) verwenden aus.
6. Wählen Sie Ihren Schlüssel aus der Drop-down-Liste aus.
Die Liste der Schlüssel ist auf das aktuelle Google Cloud-Projekt beschränkt. Wenn Sie einen Schlüssel aus einem anderen Google Cloud-Projekt verwenden möchten, erstellen Sie die Datenbank mit gcloud anstelle der Google Cloud Console.
Nachdem die Datenbank erstellt wurde, können Sie auf der Seite Datenbankdetails prüfen, ob die Datenbank CMEK-fähig ist.
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
So prüfen Sie, ob eine Datenbank CMEK-fähig ist:
gcloud spanner databases describe example-db \ --project=my-spanner-project \ --instance=my-spanner-instance
CMEK-fähige Datenbanken enthalten ein Feld für
encryptionConfig
, wie in diesem Beispiel gezeigt: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++
Einfach loslegen (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}"
Verwendete Schlüsselversionen ansehen
Die Informationen zu Schlüsselversionen stammen aus dem Feld encryption_info
der Datenbank.
Wenn sich die Schlüsselversion einer Datenbank ändert, wird die Änderung nicht sofort in encryption_info
übernommen. Es kann etwas dauern, bis die Änderung im Infofenster übernommen wird.
Console
Die Verschlüsselungsinformationen werden auf der Seite Datenbankdetails angezeigt.
gcloud
Rufen Sie die encryption_info
einer Datenbank durch Aufrufen von databases describe
oder databases list
ab. Beispiel:
gcloud spanner databases describe example-db \
--project=my-spanner-project \
--instance=my-spanner-instance
Hier ist die Ausgabe:
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
Schlüssel deaktivieren
Deaktivieren Sie die verwendeten Schlüsselversionen anhand dieser Anleitung für jede Schlüsselversion.
Warten Sie, bis die Änderung wirksam wird. Nach der Deaktivierung eines Schlüssels kann es bis zu 3 Stunden dauern, bis die Änderungen wirksam werden.
Prüfen Sie, ob die Daten nicht mehr zugänglich sind:
gcloud spanner databases execute-sql example-db \ --project=my-spanner-project \ --instance=my-spanner-instance \ --sql='SELECT * FROM Users'
Der folgende Fehler wird angezeigt:
KMS key required by the Spanner resource is not accessible.
Schlüssel aktivieren
Aktivieren Sie die von der Datenbank verwendeten Schlüsselversionen. Folgen Sie dazu für jede Schlüsselversion dieser Anleitung.
Warten Sie, bis die Änderung wirksam wird. Es kann bis zu 3 Stunden dauern, bis die Aktivierung eines Schlüssels wirksam wird.
Prüfen Sie, ob die Daten zugänglich sind:
gcloud spanner databases execute-sql example-db \ --project=my-spanner-project \ --instance=my-spanner-instance \ --sql='SELECT * FROM Users'
Wenn die Änderung übernommen wurde, wird der Befehl erfolgreich ausgeführt.
Datenbank sichern
Standardmäßig verwenden Sicherungen, die aus einer Datenbank erstellt wurden, dieselbe Verschlüsselungskonfiguration wie die Datenbank selbst. Sie können optional eine andere Verschlüsselungskonfiguration für eine Sicherung angeben.
So erstellen Sie eine Sicherung:
Console
Rufen Sie in der Cloud Console die Seite Datenbankdetails auf.
Klicken Sie auf dem Tab Sicherung/Wiederherstellung auf Erstellen.
Geben Sie einen Sicherungsnamen ein und wählen Sie ein Ablaufdatum aus.
Wählen Sie Vom Kunden verwalteten Verschlüsselungsschlüssel (CMEK) verwenden und dann einen Schlüssel aus der Drop-down-Liste aus.
Klicken Sie auf Erstellen.
Die Tabelle Sicherungen enthält Verschlüsselungsinformationen für jede Sicherung.
gcloud
gcloud spanner backups create my-backup \
--project=my-spanner-project \
--instance=my-spanner-instance \
--database=example-db \
--retention-period=1y --async
So prüfen Sie, ob die erstellte Sicherung CMEK-verschlüsselt ist:
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++
Einfach loslegen (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}"
Aus einer Sicherung wiederherstellen
Datenbanken, die aus einer Sicherung wiederhergestellt werden, verwenden standardmäßig die gleiche Verschlüsselungskonfiguration wie die Sicherung selbst. Sie können dieses Verhalten jedoch überschreiben, indem Sie für die wiederhergestellte Datenbank eine andere Verschlüsselungskonfiguration angeben. Wenn die Sicherung durch CMEK geschützt ist, muss die Schlüsselversion, die zum Erstellen der Sicherung verwendet wurde, verfügbar sein, damit sie entschlüsselt werden kann.
So stellen Sie eine Datenbank wieder her:
Console
Rufen Sie in der Cloud Console die Seite Instanzdetails auf.
Wählen Sie auf dem Tab Sicherung/Wiederherstellung eine Sicherung aus und klicken Sie auf Wiederherstellen.
Wählen Sie die wiederherzustellende Instanz aus und benennen Sie die wiederhergestellte Datenbank.
Wenn Sie CMEK mit der wiederhergestellten Datenbank verwenden möchten, wählen Sie Vom Kunden verwalteten Verschlüsselungsschlüssel (CMEK) verwenden und dann einen Schlüssel aus der Drop-down-Liste aus.
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
Prüfen Sie, ob die wiederhergestellte Datenbank CMEK-verschlüsselt ist:
gcloud spanner databases describe example-db-restored \
--project=my-spanner-project \
--instance=destination-instance
Weitere Informationen finden Sie unter Datenbank aus einer Sicherung wiederherstellen.
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++
Einfach loslegen (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}"
Audit-Logs für den Cloud KMS-Schlüssel ansehen
Achten Sie darauf, dass für die Cloud KMS API in Ihrem Projekt Logging aktiviert ist.
Rufen Sie in der Cloud Console den Log-Explorer auf.
Begrenzen Sie die Logeinträge auf Ihren Cloud KMS-Schlüssel. Fügen Sie dazu dem Query Builder die folgenden Zeilen hinzu:
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"
Im Normalbetrieb werden Verschlüsselungs- und Entschlüsselungsaktionen mit dem Schweregrad
INFO
protokolliert. Diese Einträge werden protokolliert, wenn die Zonen in Ihrer Spanner-Instanz den Cloud KMS-Schlüssel etwa alle 5 Minuten abfragen.Wenn Spanner nicht auf den Schlüssel zugreifen kann, werden die Vorgänge als
ERROR
protokolliert.