Lesson 5 — Réseau privé et protection des données

CMEK avec Cloud KMS et résidence des données

5 min read

This content is not translated yet. Showing the original version.

CMEK avec Cloud KMS et résidence des données

Chiffrement par défaut ou CMEK ?

Google Cloud chiffre toujours les données au repos, avec des clés gérées par Google. CMEK (Customer-Managed Encryption Keys) remplace ces clés par une clé qui vit dans votre Cloud KMS (Key Management Service) :

Clés Google (défaut)CMEK
Qui crée et fait tourner la cléGooglevous (rotation planifiée)
Révoquer l'accès aux donnéesimpossible côté clientdésactiver la version de clé : données illisibles
Preuve pour un auditengagement contractueljournaux d'audit KMS de chaque utilisation
Localisation de la clégérée par Googlevous choisissez (europe-west1)
Coûtinclusquelques centimes par clé et par mois + opérations (voir la grille KMS)

Qui chiffre vraiment ?

Ce n'est pas votre application qui appelle KMS : ce sont les agents de service (comptes gérés par Google, un par service et par projet) de Cloud Storage et de Vertex AI. Ce sont eux qui reçoivent roles/cloudkms.cryptoKeyEncrypterDecrypter, sur la clé, pas sur le projet.

flowchart LR
  APP["Assistant (compte lab-archi-ia-app)"] -->|"lit un objet"| GCS["Cloud Storage"]
  GCS -->|"agent service-N@gs-project-accounts"| KMS["Clé lab-archi-ia-cmek (europe-west1)"]
  VX["Vertex AI"] -->|"agent service-N@gcp-sa-aiplatform"| KMS
  SEC["Équipe sécurité"] -->|"rotation, désactivation"| KMS
  KMS -.-> AUD["Journaux d'audit KMS"]
files/data_protection.tf (extrait)
resource "google_kms_key_ring" "ai" {
  name     = "${var.prefix}-keyring"
  location = var.region # la clé vit dans la même région que les données
}

resource "google_kms_crypto_key" "ai" {
  name            = "${var.prefix}-cmek"
  key_ring        = google_kms_key_ring.ai.id
  rotation_period = var.kms_rotation_period # 7776000s = 90 jours
}

resource "google_kms_crypto_key_iam_member" "agents" {
  for_each      = toset([local.vertex_agent, local.storage_agent])
  crypto_key_id = google_kms_crypto_key.ai.id
  role          = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
  member        = each.value
}

Les noms des agents se déduisent du numéro de projet (data.google_project.this.number) :

ServiceAgent de service
Cloud Storageservice-NUMERO@gs-project-accounts.iam.gserviceaccount.com
Vertex AIservice-NUMERO@gcp-sa-aiplatform.iam.gserviceaccount.com
IAPservice-NUMERO@gcp-sa-iap.iam.gserviceaccount.com

Le bucket chiffré, dans l'UE

files/data_protection.tf (extrait)
resource "google_storage_bucket" "kb" {
  name                        = "${var.prefix}-kb-${local.number}"
  location                    = upper(var.region)      # EUROPE-WEST1
  uniform_bucket_level_access = true                   # pas d'ACL objet par objet
  public_access_prevention    = "enforced"             # impossible à rendre public

  encryption {
    default_kms_key_name = google_kms_crypto_key.ai.id
  }
  depends_on = [google_kms_crypto_key_iam_member.agents] # l'agent doit avoir le droit AVANT
}

Pour les ressources Vertex AI elles-mêmes (corpus RAG, index, jeux de données, endpoints), on passe la même clé dans encryption_spec.kms_key_name : c'est la sortie cmek_key du module. Gemini Enterprise a sa propre configuration CMEK, détaillée dans le socle de sécurité Gemini Enterprise.

Quel compte doit recevoir roles/cloudkms.cryptoKeyEncrypterDecrypter pour que le bucket chiffré par CMEK fonctionne ?

Résidence et rotation : ce qu'il faut savoir

  • La clé doit être dans une localisation compatible avec la ressource : clé europe-west1 pour un bucket europe-west1. Une clé global ne chiffre pas un bucket régional.
  • La rotation crée une nouvelle version primaire ; les anciennes données restent lisibles avec les anciennes versions, qu'il ne faut pas détruire.
  • Détruire une clé (ou toutes ses versions) rend les données définitivement illisibles. En production, prevent_destroy = true et une contrainte d'organisation qui impose un délai de destruction.

La sécurité désactive la version primaire de la clé CMEK pendant un incident. Quel est l'effet sur le bucket ?

Exercice

Écrivez la ressource Terraform d'un jeu de données BigQuery (google_bigquery_dataset) qui stockera les journaux de conversation de l'assistant, en europe-west1, chiffré avec la clé du module. Quel agent de service devra recevoir le rôle KMS ?

Voir la solution
resource "google_bigquery_dataset" "conversations" {
  dataset_id = "lab_archi_ia_conversations"
  location   = var.region
  default_table_expiration_ms = 90 * 24 * 3600 * 1000 # 90 jours : minimisation

  default_encryption_configuration {
    kms_key_name = google_kms_crypto_key.ai.id
  }
  depends_on = [google_kms_crypto_key_iam_member.agents]
}

L'agent BigQuery bq-NUMERO@bigquery-encryption.iam.gserviceaccount.com doit être ajouté à la liste for_each de google_kms_crypto_key_iam_member.agents. L'expiration des tables applique une durée de conservation, exigence RGPD fréquente pour des conversations.

Résultat obtenu

terraform plan réel le 2026-10-15 (extrait de la couche données ; numéro de projet masqué) :

  # google_kms_crypto_key.ai will be created
  # google_kms_crypto_key_iam_member.agents["serviceAccount:service-NUMERO@gcp-sa-aiplatform.iam.gserviceaccount.com"] will be created
  # google_kms_crypto_key_iam_member.agents["serviceAccount:service-NUMERO@gs-project-accounts.iam.gserviceaccount.com"] will be created
  # google_kms_key_ring.ai will be created
  # google_storage_bucket.kb will be created
  # google_storage_bucket_iam_member.app_reads_kb will be created

Je sais faire

  • Expliquer ce que CMEK apporte, et ce qu'il n'apporte pas
  • Autoriser les bons agents de service sur une clé, et seulement eux
  • Créer un bucket UE, privé, chiffré CMEK
  • Passer la clé aux ressources Vertex AI et BigQuery
Next