In questa pagina viene descritto come utilizzare le chiavi di crittografia gestite dal cliente (CMEK) per Spanner.
Per scoprire di più su CMEK, vedi Chiavi di crittografia gestite dal cliente (CMEK).
Crea un database abilitato per CMEK
Creare una chiave in Cloud Key Management Service (Cloud KMS). Cloud Spanner supporta:
La chiave deve trovarsi nella stessa località dell'istanza di Cloud Spanner. Ad esempio, se la configurazione dell'istanza di Spanner è
us-west1
, anche la posizione del keyring deve essereus-west1
.Non tutte le configurazioni di istanze a più aree geografiche di Cloud Spanner hanno una località del keyring corrispondente in Cloud KMS. Non potrai creare database abilitati CMEK in queste istanze Spanner.
Se hai già una chiave Cloud KMS nella posizione corretta, puoi saltare questo passaggio.
Per saperne di più, consulta le seguenti risorse:
Concedi a Spanner l'accesso alla chiave.
In Cloud Shell, crea e visualizza l'account di servizio gestito da Google oppure visualizzalo se l'account esiste già:
gcloud beta services identity create --service=spanner.googleapis.com \ --project=my-spanner-project
Se ti viene chiesto di installare il componente gcloud Beta Commands, digita
Y
. Dopo l'installazione, il comando viene riavviato automaticamente.Il comando gcloud services identity crea o ottiene l'account di servizio gestito da Google speciale che Spanner può utilizzare per accedere alla chiave Cloud KMS per tuo conto.
L'ID dell'account di servizio ha il formato di un indirizzo email:
Service identity created: service-xxx@gcp-sa-spanner.iam.gserviceaccount.com
Concedi il ruolo
cloudkms.cryptoKeyEncrypterDecrypter
all'account di servizio: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
Vedrai:
Updated IAM policy for key [my-kms-key]
Questo ruolo garantisce che l'account di servizio sia autorizzato sia a criptare che a decriptare con la chiave Cloud KMS. Per ulteriori informazioni, consulta Autorizzazioni e ruoli di Cloud KMS.
Crea il database e specifica la chiave Cloud KMS.
Console
1. Vai alla pagina Istanze Cloud Spanner nella console Google Cloud.
2. Fai clic sul nome dell'istanza in cui creare il database.
3. Fai clic su Crea database e compila i campi obbligatori.
4. Fai clic su Mostra opzioni di crittografia.
5. Seleziona Utilizza una chiave di crittografia gestita dal cliente (CMEK).
6. Seleziona la chiave dall'elenco a discesa.
L'elenco delle chiavi è limitato al progetto Google Cloud attuale. Per utilizzare una chiave da un progetto Google Cloud diverso, crea il database utilizzando gcloud anziché la console Google Cloud.
Dopo aver creato il database, puoi verificare che sia abilitato per CMEK visualizzando la pagina Dettagli database.
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
Per verificare che un database sia abilitato per CMEK:
gcloud spanner databases describe example-db \ --project=my-spanner-project \ --instance=my-spanner-instance
I database abilitati per CMEK includono un campo per
encryptionConfig
, come mostrato in questo esempio: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
Nodo
PHP
use Google\Cloud\Spanner\SpannerClient; /** * Creates an encrypted database with tables for sample data. * Example: * ``` * create_database_with_encryption_key($instanceId, $databaseId, $kmsKeyName); * ``` * * @param string $instanceId The Spanner instance ID. * @param string $databaseId The Spanner database ID. * @param string $kmsKeyName The KMS key used for encryption. */ function create_database_with_encryption_key($instanceId, $databaseId, $kmsKeyName) { $spanner = new SpannerClient(); $instance = $spanner->instance($instanceId); if (!$instance->exists()) { throw new \LogicException("Instance $instanceId does not exist"); } $operation = $instance->createDatabase($databaseId, [ '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" ], 'encryptionConfig' => ['kmsKeyName' => $kmsKeyName] ]); print('Waiting for operation to complete...' . PHP_EOL); $operation->pollUntilComplete(); $database = $instance->database($databaseId); printf( 'Created database %s on instance %s with encryption key %s' . PHP_EOL, $databaseId, $instanceId, $database->info()['encryptionConfig']['kmsKeyName'] ); }
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}"
Visualizza le versioni della chiave in uso
Le informazioni sulle versioni delle chiavi provengono dal campo encryption_info
del database.
Quando la versione della chiave di un database cambia, la modifica non viene propagata immediatamente a encryption_info
. Potrebbe verificarsi un ritardo prima che la modifica venga applicata nel campo delle informazioni.
Console
Le informazioni sulla crittografia vengono visualizzate nella pagina Dettagli database.
gcloud
Ricevi un encryption_info
di database chiamando
databases describe
o
databases list
. Ad esempio:
gcloud spanner databases describe example-db \
--project=my-spanner-project \
--instance=my-spanner-instance
Ecco l'output:
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
Disattiva la chiave
Disattiva le versioni della chiave in uso seguendo queste istruzioni per ciascuna versione della chiave.
Attendi che la modifica venga applicata. La disattivazione di una chiave può richiedere fino a 3 ore per la propagazione.
Verifica che i dati non siano più accessibili:
gcloud spanner databases execute-sql example-db \ --project=my-spanner-project \ --instance=my-spanner-instance \ --sql='SELECT * FROM Users'
Verrà visualizzato il seguente errore:
KMS key required by the Spanner resource is not accessible.
Abilita la chiave
Abilita le versioni delle chiavi utilizzate dal database seguendo queste istruzioni per ogni versione della chiave.
Attendi che la modifica venga applicata. La propagazione di una chiave può richiedere fino a 3 ore.
Verifica che i dati siano accessibili:
gcloud spanner databases execute-sql example-db \ --project=my-spanner-project \ --instance=my-spanner-instance \ --sql='SELECT * FROM Users'
Se la modifica ha avuto effetto, il comando verrà eseguito correttamente.
Esegui il backup di un database
Per impostazione predefinita, i backup creati da un database utilizzano la stessa configurazione della crittografia del database stesso. Facoltativamente, puoi specificare una configurazione di crittografia diversa per un backup.
Per creare un backup:
Console
Vai alla pagina Dettagli database in Cloud Console.
Nella scheda Backup/Ripristino, fai clic su Crea.
Inserisci un nome per il backup e seleziona una data di scadenza.
Seleziona Utilizza una chiave di crittografia gestita dal cliente (CMEK) e scegli una chiave dall'elenco a discesa.
Fai clic su Crea.
La tabella Backup mostra le informazioni di crittografia relative a ogni backup.
gcloud
gcloud spanner backups create my-backup \
--project=my-spanner-project \
--instance=my-spanner-instance \
--database=example-db \
--retention-period=1y --async
Per verificare che il backup creato sia criptato con 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
Nodo
PHP
use Google\Cloud\Spanner\Admin\Database\V1\CreateBackupEncryptionConfig;
use Google\Cloud\Spanner\Backup;
use Google\Cloud\Spanner\SpannerClient;
/**
* Create an encrypted backup.
* Example:
* ```
* create_backup_with_encryption_key($instanceId, $databaseId, $backupId, $kmsKeyName);
* ```
*
* @param string $instanceId The Spanner instance ID.
* @param string $databaseId The Spanner database ID.
* @param string $backupId The Spanner backup ID.
* @param string $kmsKeyName The KMS key used for encryption.
*/
function create_backup_with_encryption_key($instanceId, $databaseId, $backupId, $kmsKeyName)
{
$spanner = new SpannerClient();
$instance = $spanner->instance($instanceId);
$database = $instance->database($databaseId);
$expireTime = new \DateTime('+14 days');
$backup = $instance->backup($backupId);
$operation = $backup->create($database->name(), $expireTime, [
'encryptionConfig' => [
'kmsKeyName' => $kmsKeyName,
'encryptionType' => CreateBackupEncryptionConfig\EncryptionType::CUSTOMER_MANAGED_ENCRYPTION
]
]);
print('Waiting for operation to complete...' . PHP_EOL);
$operation->pollUntilComplete();
$backup->reload();
$ready = ($backup->state() == Backup::STATE_READY);
if ($ready) {
print('Backup is ready!' . PHP_EOL);
$info = $backup->info();
printf(
'Backup %s of size %d bytes was created at %s using encryption key %s' . PHP_EOL,
basename($info['name']), $info['sizeBytes'], $info['createTime'], $kmsKeyName);
} else {
print('Backup is not ready!' . PHP_EOL);
}
}
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}"
Ripristina da un backup
Per impostazione predefinita, i database ripristinati da un backup utilizzano la stessa configurazione della crittografia del backup stesso, ma puoi ignorare questo comportamento specificando una configurazione di crittografia diversa per il database ripristinato. Se il backup è protetto da CMEK, deve essere disponibile la versione della chiave utilizzata per creare il backup in modo che possa essere decriptata.
Per ripristinare un database:
Console
Vai alla pagina Dettagli istanza nella console Cloud.
Nella scheda Backup/Ripristino, seleziona un backup e fai clic su Ripristina.
Seleziona l'istanza da ripristinare e assegna un nome al database ripristinato.
Se vuoi utilizzare CMEK con il database ripristinato, seleziona Utilizza una chiave di crittografia gestita dal cliente (CMEK) e seleziona una chiave dall'elenco a discesa.
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
Verifica che il database ripristinato sia criptato con CMEK:
gcloud spanner databases describe example-db-restored \
--project=my-spanner-project \
--instance=destination-instance
Per ulteriori informazioni, vedi Ripristino di un database da un backup.
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
Nodo
PHP
use Google\Cloud\Spanner\Admin\Database\V1\RestoreDatabaseEncryptionConfig;
use Google\Cloud\Spanner\SpannerClient;
/**
* Restore a database from a backup.
* Example:
* ```
* restore_backup_with_encryption_key($instanceId, $databaseId, $backupId, $kmsKeyName);
* ```
* @param string $instanceId The Spanner instance ID.
* @param string $databaseId The Spanner database ID.
* @param string $backupId The Spanner backup ID.
* @param string $kmsKeyName The KMS key used for encryption.
*/
function restore_backup_with_encryption_key($instanceId, $databaseId, $backupId, $kmsKeyName)
{
$spanner = new SpannerClient();
$instance = $spanner->instance($instanceId);
$database = $instance->database($databaseId);
$backup = $instance->backup($backupId);
$operation = $database->restore($backup->name(), [
'encryptionConfig' => [
'kmsKeyName' => $kmsKeyName,
'encryptionType' => RestoreDatabaseEncryptionConfig\EncryptionType::CUSTOMER_MANAGED_ENCRYPTION
]
]);
// Wait for restore operation to complete.
$operation->pollUntilComplete();
// Newly created database has restore information.
$database->reload();
$restoreInfo = $database->info()['restoreInfo'];
$sourceDatabase = $restoreInfo['backupInfo']['sourceDatabase'];
$sourceBackup = $restoreInfo['backupInfo']['backup'];
$encryptionConfig = $database->info()['encryptionConfig'];
printf(
"Database %s restored from backup %s using encryption key %s" . PHP_EOL,
$sourceDatabase, $sourceBackup, $encryptionConfig['kmsKeyName']);
}
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}"
Visualizza audit log per la chiave Cloud KMS
Assicurati che il logging sia abilitato per l'API Cloud KMS nel tuo progetto.
Vai a Esplora log in Cloud Console.
Limita le voci di log alla chiave Cloud KMS aggiungendo le seguenti righe a Query Builder:
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"
Durante il normale funzionamento, le azioni di crittografia e decriptazione vengono registrate con gravità
INFO
. Queste voci vengono registrate come zone nell'istanza di Spanner eseguendo il polling della chiave Cloud KMS ogni 5 minuti circa.Se Spanner non riesce ad accedere alla chiave, le operazioni vengono registrate come
ERROR
.