Cette page explique comment utiliser des clés de chiffrement gérées par le client (CMEK) pour Spanner.
Pour en savoir plus sur les CMEK, consultez la page Clés de chiffrement gérées par le client (CMEK).
Créer une base de données compatible avec les CMEK
Créez une clé dans Cloud Key Management Service (Cloud KMS). Spanner est compatible avec:
La clé doit se trouver au même emplacement que votre instance Spanner. Par exemple, si la configuration de votre instance Spanner est
us-west1
, l'emplacement de votre trousseau de clés doit également êtreus-west1
.Les configurations d'instances multirégionales Spanner ne disposent pas toutes d'un emplacement de trousseau de clés correspondant dans Cloud KMS. Vous ne pourrez pas créer de bases de données compatibles CMEK dans ces instances Spanner.
Si vous disposez déjà d'une clé Cloud KMS à l'emplacement approprié, vous pouvez ignorer cette étape.
Pour en savoir plus, consultez les ressources suivantes :
Accordez à Spanner l'accès à la clé.
- Dans Cloud Shell, créez et affichez le compte de service géré par Google.
Dans Cloud Shell, créez et affichez le compte de service géré par Google, ou affichez-le si le compte existe déjà:
gcloud beta services identity create --service=spanner.googleapis.com \ --project=my-spanner-project
Si vous êtes invité à installer le composant gcloud Beta Commands, saisissez
Y
. Après l'installation, la commande est automatiquement redémarrée.La commande gcloud services Identity crée ou obtient le compte de service géré par Google spécial que Spanner peut utiliser pour accéder à la clé Cloud KMS en votre nom.
L'ID de compte de service se présente sous la forme d'une adresse e-mail :
Service identity created: service-xxx@gcp-sa-spanner.iam.gserviceaccount.com
Attribuez le rôle
cloudkms.cryptoKeyEncrypterDecrypter
au compte de service: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
Les informations suivantes s'affichent:
Updated IAM policy for key [my-kms-key]
Ce rôle garantit que le compte de service est autorisé à chiffrer et à déchiffrer les données avec la clé Cloud KMS. Pour en savoir plus, consultez la page Autorisations et rôles Cloud KMS.
Créez la base de données et spécifiez votre clé Cloud KMS.
Console
1. Accédez à la page Instances de Spanner dans la console Google Cloud.
2. Cliquez sur le nom de l'instance dans laquelle créer la base de données.
3. Cliquez sur Créer une base de données et remplissez les champs obligatoires.
4. Cliquez sur Afficher les options de chiffrement.
5. Sélectionnez Utiliser une clé de chiffrement gérée par le client (CMEK).
6. Sélectionnez votre clé dans la liste déroulante.
La liste des clés est limitée au projet Google Cloud en cours. Pour utiliser une clé d'un autre projet Google Cloud, créez la base de données à l'aide de gcloud au lieu de la console Google Cloud.
Une fois la base de données créée, vous pouvez vérifier qu'elle est activée par CMEK en consultant la page Détails de la base de données.
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
Pour vérifier qu'une base de données est compatible avec les CMEK:
gcloud spanner databases describe example-db \ --project=my-spanner-project \ --instance=my-spanner-instance
Les bases de données utilisant CMEK incluent un champ pour
encryptionConfig
, comme illustré dans cet exemple: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}"
Afficher les versions de clé en cours d'utilisation
Les informations sur les versions de clé proviennent du champ encryption_info
de la base de données.
Lorsque la version de clé d'une base de données change, la modification n'est pas immédiatement propagée dans encryption_info
. La modification dans le champ d'informations peut prendre un certain temps.
Console
Les informations de chiffrement sont affichées sur la page Détails de la base de données.
gcloud
Obtenez le encryption_info
d'une base de données en appelant databases describe
ou databases list
. Exemple :
gcloud spanner databases describe example-db \
--project=my-spanner-project \
--instance=my-spanner-instance
Voici le résultat :
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
Désactiver la clé
Désactivez la ou les versions de clé utilisées en suivant ces instructions pour chaque version de clé.
Attendez que la modification soit prise en compte. La propagation de la désactivation d'une clé peut prendre jusqu'à trois heures.
Vérifiez que les données ne sont plus accessibles:
gcloud spanner databases execute-sql example-db \ --project=my-spanner-project \ --instance=my-spanner-instance \ --sql='SELECT * FROM Users'
L'erreur suivante s'affiche :
KMS key required by the Spanner resource is not accessible.
Activer la clé
Activez les versions de clé utilisées par la base de données en suivant ces instructions pour chaque version de clé.
Attendez que la modification soit prise en compte. La propagation d'une clé peut prendre jusqu'à trois heures.
Vérifiez que les données sont accessibles:
gcloud spanner databases execute-sql example-db \ --project=my-spanner-project \ --instance=my-spanner-instance \ --sql='SELECT * FROM Users'
Si la modification a été prise en compte, la commande s'exécute correctement.
Sauvegarder une base de données
Par défaut, les sauvegardes créées à partir d'une base de données utilisent la même configuration de chiffrement que la base de données elle-même. Vous pouvez éventuellement spécifier une autre configuration de chiffrement pour une sauvegarde.
Pour créer une sauvegarde, procédez comme suit :
Console
Accédez à la page Détails de la base de données dans la console Cloud.
Dans l'onglet Sauvegarder/Restaurer, cliquez sur Créer.
Saisissez un nom de sauvegarde et sélectionnez une date d'expiration.
Sélectionnez Utiliser une clé de chiffrement gérée par le client (CMEK) et choisissez une clé dans la liste déroulante.
Cliquez sur Créer.
La table Sauvegardes affiche des informations de chiffrement pour chaque sauvegarde.
gcloud
gcloud spanner backups create my-backup \
--project=my-spanner-project \
--instance=my-spanner-instance \
--database=example-db \
--retention-period=1y --async
Pour vérifier que la sauvegarde créée est chiffrée par 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}"
Restaurer à partir d'une sauvegarde
Par défaut, les bases de données restaurées à partir d'une sauvegarde utilisent la même configuration de chiffrement que la sauvegarde elle-même, mais vous pouvez ignorer ce comportement en spécifiant une autre configuration de chiffrement pour la base de données restaurée. Si la sauvegarde est protégée par une clé CMEK, la version de clé utilisée pour créer la sauvegarde doit être disponible pour pouvoir être déchiffrée.
Pour restaurer une base de données, procédez comme suit :
Console
Accédez à la page Détails de l'instance dans la console Cloud.
Dans l'onglet Sauvegarder/Restaurer, sélectionnez une sauvegarde, puis cliquez sur Restaurer.
Sélectionnez l'instance à restaurer et nommez la base de données restaurée.
Si vous souhaitez utiliser une clé CMEK avec la base de données restaurée, sélectionnez Utiliser une clé de chiffrement gérée par le client (CMEK) et choisissez une clé dans la liste déroulante.
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
Vérifiez que la base de données restaurée est chiffrée avec une clé CMEK:
gcloud spanner databases describe example-db-restored \
--project=my-spanner-project \
--instance=destination-instance
Pour en savoir plus, consultez la section Restaurer une base de données à partir d'une sauvegarde.
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}"
Afficher les journaux d'audit pour la clé Cloud KMS
Assurez-vous que la journalisation est activée pour l'API Cloud KMS dans votre projet.
Accédez à l'explorateur de journaux dans Cloud Console :
Limitez les entrées de journal à votre clé Cloud KMS en ajoutant les lignes suivantes au générateur de requêtes:
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 cas d'exploitation normale, les actions de chiffrement et de déchiffrement sont consignées avec le niveau de gravité
INFO
. Ces entrées sont consignées lorsque les zones de votre instance Spanner interrogent la clé Cloud KMS environ toutes les cinq minutes.Si Spanner ne parvient pas à accéder à la clé, les opérations sont consignées en tant que
ERROR
.