En esta página, se describe cómo usar claves de encriptación 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 admite 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 de tu 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 la cuenta de servicio administrada por Google.
En Cloud Shell, crea y muestra la cuenta de servicio administrada por Google o muéstrala 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 comando gcloud services Identity crea o obtiene la cuenta de servicio administrada por Google especial 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]
Esta función garantiza que la cuenta de servicio tenga permiso para encriptar y desencriptar contenido con la clave de Cloud KMS. Para obtener más información, consulta Permisos y funciones 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 en 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 la base de datos con gcloud en lugar de la consola de Google Cloud.
Una vez que se crea la base de datos, puedes verificar que la base de datos esté habilitada para CMEK. Para ello, consulta 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 esté habilitada con CMEK, sigue estos pasos:
gcloud spanner databases describe example-db \ --project=my-spanner-project \ --instance=my-spanner-instance
Las bases de datos habilitadas con 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
Rita
# 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}"
Visualiza 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
. Es posible que haya 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 a 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
Inhabilitar la clave
Sigue estas instrucciones para cada versión de clave a fin de inhabilitar 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 puede 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
Sigue estas instrucciones para cada versión de clave a fin de habilitar las versiones de claves que usa la base de datos.
Espera a que se aplique el cambio. La habilitación de una clave puede tardar hasta 3 horas en propagarse.
Confirma que los datos son accesibles:
gcloud spanner databases execute-sql example-db \ --project=my-spanner-project \ --instance=my-spanner-instance \ --sql='SELECT * FROM Users'
Si el cambio surtió efecto, 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. De manera 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 Cloud.
En la pestaña Copia de seguridad/restablecimiento, haz clic en Crear.
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.
En la tabla Copias de seguridad, se 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 --async
Para verificar que la copia de seguridad creada esté encriptada con CMEK, sigue estos pasos:
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
Rita
# 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 la misma configuración de encriptación que la copia de seguridad en sí, pero puedes anular este comportamiento si especificas 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 la instancia en la consola de Cloud.
En la pestaña Copia de seguridad/restablecimiento, selecciona una copia de seguridad y haz clic en Restablecer.
Selecciona la instancia que deseas restablecer y asígnale un nombre a la base de datos restablecida.
Si deseas usar CMEK con la base de datos restablecida, selecciona Usar una clave de encriptación administrada por el cliente (CMEK) y selecciona 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 Restablece 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
Rita
# 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}"
Ver 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 las siguientes 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 operaciones normales, las acciones de encriptación y desencriptación se registran con gravedad
INFO
. Estas entradas se registran como las zonas de tu instancia de Spanner que consultan la clave de Cloud KMS cada 5 minutos.Si Spanner no puede acceder a la clave, las operaciones se registran como
ERROR
.