En esta página, se describe cómo usar claves de encriptación creadas de forma manual y administradas por el cliente (CMEK) para Spanner.
Para obtener más información sobre las CMEK, consulta Claves de encriptación administradas por el cliente (CMEK).
Crea una base de datos habilitada con CMEK
Crea una clave en Cloud Key Management Service (Cloud KMS). Spanner es compatible con lo siguiente:
La clave debe estar en la misma ubicación que tu instancia de Spanner. Por ejemplo, si la configuración de tu instancia de Spanner es
us-west1
, la ubicación del llavero de claves también debe serus-west1
.No todas las configuraciones de instancias multirregionales de Spanner tienen una ubicación de llavero de claves correspondiente en Cloud KMS. No podrás crear bases de datos habilitadas para CMEK en esas instancias de Spanner.
Si ya tienes una clave de Cloud KMS en la ubicación correcta, puedes omitir este paso.
Para obtener más información, consulta los siguientes recursos:
Otorga a Spanner acceso a la clave.
En Cloud Shell, crea y muestra el agente de servicio o muéstralo si la cuenta ya existe:
gcloud beta services identity create --service=spanner.googleapis.com \ --project=my_spanner_project
Si se te solicita que instales el componente Comandos Beta de gcloud, escribe
Y
. Después de la instalación, el comando se reinicia de forma automática.El identidad de los servicios de gcloud crea u obtiene agente de servicio que Spanner puede usar para acceder a la clave de Cloud KMS en tu nombre.
El ID de la cuenta de servicio tiene el formato de una dirección de correo electrónico:
Service identity created: service-xxx@gcp-sa-spanner.iam.gserviceaccount.com
Otorga el rol
cloudkms.cryptoKeyEncrypterDecrypter
a la cuenta de servicio: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
Verás lo siguiente:
Updated IAM policy for key [my-kms-key]
Este rol garantiza que la cuenta de servicio tenga permiso para encriptar y desencriptar con la clave de Cloud KMS. Para obtener más información, consulta Permisos y roles de Cloud KMS.
Crea la base de datos y especifica tu clave de Cloud KMS.
Console
1. Ve a la página Instancias de Spanner en la consola de Google Cloud.
2. Haz clic en el nombre de la instancia en la que deseas crear la base de datos.
3. Haz clic en Crear base de datos y completa los campos obligatorios.
4. Haz clic en Mostrar opciones de encriptación.
5. Selecciona Usar una clave de encriptación administrada por el cliente (CMEK).
6. Selecciona tu clave de la lista desplegable.
La lista de claves se limita al proyecto actual de Google Cloud. Para usar una clave de otro proyecto de Google Cloud, crea con gcloud en vez de la consola de Google Cloud.
Una vez creada la base de datos, puedes verificar que esté Habilitadas para CMEK en la página Detalles de la base de datos.
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
Para verificar que una base de datos tenga habilitadas las CMEK, sigue estos pasos:
gcloud spanner databases describe example_db \ --project=my_spanner_project \ --instance=my_spanner_instance
Las bases de datos habilitadas para CMEK incluyen un campo para
encryptionConfig
, como se muestra en este ejemplo: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}"
Cómo ver las versiones de claves en uso
La información sobre las versiones de claves proviene del campo encryption_info
de la base de datos.
Cuando cambia la versión de clave de una base de datos, el cambio no se propaga de inmediato a encryption_info
. Puede haber una demora antes de que el cambio se refleje en
el campo de información.
Console
La información de encriptación se muestra en la página Detalles de la base de datos.
gcloud
Para obtener el encryption_info
de una base de datos, llama a databases describe
o databases list
. Por ejemplo:
gcloud spanner databases describe example_db \
--project=my_spanner_project \
--instance=my_spanner_instance
Esta es la salida:
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
Inhabilita la clave
Sigue estas instrucciones para cada versión de clave y, luego, inhabilita las versiones de clave que estén en uso.
Espera a que se aplique el cambio. La inhabilitación de una clave puede tardar hasta 3 horas en propagarse.
Confirma que ya no se pueda acceder a los datos:
gcloud spanner databases execute-sql example_db \ --project=my_spanner_project \ --instance=my_spanner_instance \ --sql='SELECT * FROM Users'
Verás el siguiente error:
KMS key required by the Spanner resource is not accessible.
Habilitar la clave
Habilita las versiones de clave que usa la base de datos de la siguiente manera: estas instrucciones para cada clave versión.
Espera a que se aplique el cambio. La habilitación de una clave puede tardar hasta 3 horas en propagarse.
Confirma que se pueda acceder a los datos:
gcloud spanner databases execute-sql example_db \ --project=my_spanner_project \ --instance=my_spanner_instance \ --sql='SELECT * FROM Users'
Si el cambio se aplicó, el comando se ejecutará correctamente.
Crea una copia de seguridad de una base de datos
De forma predeterminada, las copias de seguridad creadas a partir de una base de datos usan la misma configuración de encriptación que la base de datos en sí. De forma opcional, puedes especificar una configuración de encriptación diferente para una copia de seguridad.
Para crear una copia de seguridad, haz lo siguiente:
Console
Ve a la página Detalles de la base de datos en la consola de Google Cloud.
En la pestaña Backup/Restore, haz clic en Create.
Ingresa un nombre para la copia de seguridad y selecciona una fecha de vencimiento.
Selecciona Usar una clave de encriptación administrada por el cliente (CMEK) y elige una clave de la lista desplegable.
Haz clic en Crear.
La tabla Copias de seguridad muestra la información de encriptación de cada copia de seguridad.
gcloud
gcloud spanner backups create my_backup \
--project=my_spanner_project \
--instance=my_spanner_instance \
--database=example_db \
--retention-period=1y \
--encryption-type=customer_managed_encryption \
--kms-project=my_kms_project \
--kms-location=my_kms_key_location \
--kms-keyring=my_kms_key_ring \
--kms-key=my_kms_key
--async
Para verificar que la copia de seguridad creada esté encriptada con CMEK, haz lo siguiente:
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}"
Restablecer copia de seguridad
De forma predeterminada, las bases de datos que se restablecen a partir de una copia de seguridad usan el mismo configuración de encriptación que la copia de seguridad en sí, pero puedes anular este comportamiento especificando una configuración de encriptación diferente para la base de datos restablecida. Si la copia de seguridad está protegida por CMEK, la versión de clave que se usó para crearla debe estar disponible para que se pueda desencriptar.
Para restablecer una base de datos, sigue estos pasos:
Console
Ve a la página Detalles de instancias en la consola de Cloud.
En la pestaña Backup/Restore, selecciona una copia de seguridad y haz clic en Restore.
Selecciona la instancia que se restablecerá y asígnale un nombre a la base de datos restablecida.
Si deseas usar CMEK con la base de datos restaurada, selecciona Usar una clave de encriptación administrada por el cliente (CMEK) y elige una clave de la lista desplegable.
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 que la base de datos restablecida esté encriptada con CMEK:
gcloud spanner databases describe example_db_restored \
--project=my_spanner_project \
--instance=destination_instance
Para obtener más información, consulta Cómo restablecer una base de datos a partir de una copia de seguridad.
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}"
Visualiza los registros de auditoría de la clave de Cloud KMS
Asegúrate de que el registro está habilitado para la API de Cloud KMS en tu proyecto.
Ve al Explorador de registros en la consola de Cloud.
Para limitar las entradas de registro a tu clave de Cloud KMS, agrega lo siguiente: líneas al Compilador de consultas:
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"
En las operaciones normales, las acciones de encriptación y desencriptación se registran con la gravedad
INFO
. Estas entradas se registran a medida que las zonas de tu instancia de Spanner sondean la clave de Cloud KMS aproximadamente cada 5 minutos.Si Spanner no puede acceder a la clave, las operaciones se registran como
ERROR