Nesta página, descrevemos como usar chaves de criptografia gerenciadas pelo cliente criadas manualmente (CMEK) para o Spanner.
Para saber mais sobre CMEK, consulte Chaves de criptografia gerenciadas pelo cliente (CMEK).
Criar um banco de dados ativado para CMEK
Crie uma chave no Cloud Key Management Service (Cloud KMS). Spanner suporta:
A chave precisa estar no mesmo local que sua instância do Spanner. Por exemplo, se a configuração da instância do Spanner for
us-west1
, o local do keyring também precisará serus-west1
.Nem toda configuração de instância multirregional do Spanner tem um local de chaves correspondente no Cloud KMS. Não será possível criar bancos de dados ativados para CMEK nessas instâncias do Spanner.
Se você já tiver uma chave do Cloud KMS no local correto, pule esta etapa.
Para saber mais, acesse os recursos a seguir:
Conceda ao Spanner acesso à chave.
No Cloud Shell, crie e exiba o agente de serviço ou exiba-o se a conta já existir:
gcloud beta services identity create --service=spanner.googleapis.com \ --project=my_spanner_project
Se aparecer uma solicitação para instalar o componente gcloud Beta Commands, digite
Y
. Após a instalação, o comando é reiniciado automaticamente.O comando gcloud services identity cria ou recebe o agente de serviço que o Spanner pode usar para acessar a chave do Cloud KMS em seu nome.
O ID da conta de serviço é formatado como um endereço de e-mail:
Service identity created: service-xxx@gcp-sa-spanner.iam.gserviceaccount.com
Conceder o papel
cloudkms.cryptoKeyEncrypterDecrypter
ao serviço conta: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
Você vai encontrar:
Updated IAM policy for key [my-kms-key]
Esse papel garante que a conta de serviço tenha permissão para criptografar e descriptografar com a chave do Cloud KMS. Para mais informações, consulte Permissões e papéis do Cloud KMS.
Crie o banco de dados e especifique sua chave do Cloud KMS.
Console
1. Acesse a página Instâncias do Spanner no console do Google Cloud.
2. Clique no nome da instância em que o banco de dados será criado.
3. Clique em Criar banco de dados e preencha os campos obrigatórios.
4. Clique em Mostrar opções de criptografia.
5. Selecione Usar uma chave de criptografia gerenciada pelo cliente (CMEK).
6. Selecione a chave na lista suspensa.
A lista de chaves é limitada ao projeto atual do Google Cloud. Para usar uma chave de um projeto diferente do Google Cloud, crie o banco de dados usando o gcloud em vez do console do Google Cloud.
Depois que o banco de dados for criado, você poderá verificar se ele está habilitado para o CMK acessando a página Detalhes do banco de dados.
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 se um banco de dados está ativado para CMEK:
gcloud spanner databases describe example_db \ --project=my_spanner_project \ --instance=my_spanner_instance
Os bancos de dados ativados para CMEK incluem um campo para
encryptionConfig
, conforme mostrado neste exemplo: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}"
Conferir as versões da chave em uso
As informações sobre versões de chave são do campo encryption_info
do banco de dados.
Quando a versão da chave de um banco de dados muda, a mudança não é imediatamente propagada
para encryption_info
. Pode levar algum tempo até que a mudança seja refletida no
campo de informações.
Console
As informações de criptografia são exibidas na página Detalhes do banco de dados.
gcloud
Para acessar o encryption_info
de um banco de dados, chame
databases describe
ou
databases list
. Exemplo:
gcloud spanner databases describe example_db \
--project=my_spanner_project \
--instance=my_spanner_instance
Esta é a saída:
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
Desativar a chave
Desative as versões de chave em uso seguindo estas instruções para cada versão.
Aguarde a mudança entrar em vigor. Desativar uma chave pode demorar até três horas para propagar.
Confirme se os dados não podem mais ser acessados:
gcloud spanner databases execute-sql example_db \ --project=my_spanner_project \ --instance=my_spanner_instance \ --sql='SELECT * FROM Users'
O seguinte erro será exibido:
KMS key required by the Spanner resource is not accessible.
Ativar a chave
Ative as versões de chave que estão em uso pelo banco de dados seguindo estas instruções para cada versão de chave.
Aguarde a mudança ser aplicada. A ativação de uma chave pode levar até três horas para ser propagada.
Confirme se os dados podem ser acessados:
gcloud spanner databases execute-sql example_db \ --project=my_spanner_project \ --instance=my_spanner_instance \ --sql='SELECT * FROM Users'
Se a alteração entrar em vigor, o comando será executado com sucesso.
Fazer backup de um banco de dados
Por padrão, os backups criados a partir de um banco de dados usam a mesma configuração de criptografia como o próprio banco de dados. Você pode especificar uma configuração de criptografia diferente para um backup.
Para criar um backup, faça o seguinte:
Console
Acesse a página Detalhes do banco de dados no console do Google Cloud.
Na guia Backup/Restaurar, clique em Criar.
Insira um nome e selecione uma data de expiração.
Selecione Usar uma chave de criptografia gerenciada pelo cliente (CMEK) e escolha uma chave na lista suspensa.
Clique em Criar.
A tabela Backups exibe as informações de criptografia de cada backup.
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 se o backup criado está criptografado com 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}"
Restaurar a partir de um backup
Por padrão, os bancos de dados restaurados de um backup usam a mesma configuração de criptografia do backup, mas é possível substituir esse comportamento especificando uma configuração de criptografia diferente para o banco de dados restaurado. Se o backup estiver protegido pela CMEK, a versão da chave usada para criar o backup precisará estar disponível para que possa ser descriptografada.
Para restaurar um banco de dados:
Console
Acesse a página Detalhes da instância no Console do Cloud.
Na guia Backup/Restaurar, selecione um backup e clique em Restaurar.
Selecione a instância a ser restaurada e nomeie o banco de dados restaurado.
Se você quiser usar a CMEK com o banco de dados restaurado, selecione Usar uma chave de criptografia gerenciada pelo cliente (CMEK) e selecionar uma chave de na lista suspensa.
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
Verifique se o banco de dados restaurado está criptografado com CMEK:
gcloud spanner databases describe example_db_restored \
--project=my_spanner_project \
--instance=destination_instance
Para mais informações, consulte Como restaurar um banco de dados de um 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
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}"
Ver os registros de auditoria da chave do Cloud KMS
Certifique-se de que a geração de registros está ativada para a API Cloud KMS no projeto.
Acesse o Explorador de registros no console do Cloud:
Limite as entradas de registro na chave do Cloud KMS adicionando as seguintes linhas ao criador 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"
Em operações normais, as ações de criptografia e descriptografia são registradas com
INFO
gravidade. Essas entradas são registradas quando as zonas na sua instância do Spanner consultam a chave do Cloud KMS a cada cinco minutos.Se o Spanner não conseguir acessar a chave, as operações serão registradas como
ERROR
.