Aller au contenu

Chiffrement RDS / Aurora avec clés KMS gérées client — le piège que vous ne pouvez pas inverser

Le chiffrement au repos est fixé au moment de la création et ne peut pas être changé. Les clés KMS gérées client donnent la traçabilité d'audit et la capacité de révoquer. La rotation de clé est automatique mais ne re-chiffre pas les données. Le partage de snapshots inter-comptes exige une key policy précise. La configuration réelle et le bloc de confiance qui doit s'aligner.

La revue de conformité demande « est-ce que vos bases sont chiffrées au repos ? » et la réponse est oui — RDS l’active par défaut avec la clé gérée AWS aws/rds. La question suivante est « avec une clé gérée client ? » et la réponse est non, parce que l’instance originale a été créée il y a deux ans quand personne ne pensait à la garde des clés KMS. La question suivante est « peut-on déplacer les données existantes vers une clé gérée client ? » et la réponse honnête est « pas in-place ». Le statut de chiffrement sur RDS est fixé à la création de l’instance et ne peut pas être changé — il n’y a pas de modify-db-instance qui bascule ça. Le contournement est snapshot, copie avec une nouvelle clé KMS, et restauration. La bonne réponse est d’utiliser une clé gérée client dès le départ.

Ce qui se passe

RDS et Aurora chiffrent le volume de stockage, les sauvegardes automatisées, les snapshots et les read replicas avec une clé KMS choisie à la création. Trois choses à comprendre :

Le flag de chiffrement est immuable. StorageEncrypted: false ne peut pas devenir true sur une instance qui tourne. Pareil dans l’autre sens — une instance chiffrée ne peut pas être rendue non chiffrée. Le seul chemin pour changer le statut de chiffrement est snapshot → copie-avec-clé-différente → restauration-depuis-copie. C’est une opération de plusieurs heures pour de grosses bases et qui implique un downtime de bascule.

La clé KMS est liée à l’instance. Chaque instance RDS chiffrée a une seule clé KMS associée. Read replicas, sauvegardes automatisées et snapshots l’héritent (avec une subtilité — voir inter-régions ci-dessous). Vous pouvez changer la clé en passant par le même chemin snapshot → copie → restauration, mais pas in-place.

La rotation de clé KMS est automatique, mais elle ne re-chiffre pas les données. Quand l’auto-rotation de clé gérée AWS ou gérée client est activée, KMS génère une nouvelle version de clé chaque année. La nouvelle version est utilisée pour les nouveaux chiffrements. Le ciphertext existant reste chiffré avec la version antérieure, que KMS garde pour le déchiffrer. « Tourner la clé » ne veut pas dire « toutes les données sont re-chiffrées avec la nouvelle version ». Cette distinction compte pour les cadres de conformité qui demandent des preuves de re-cryptage.

Le choix entre clé gérée client (CMK) et clé gérée AWS (aws/rds) compte pour trois raisons opérationnelles :

  • Traçabilité d’audit. CloudTrail enregistre chaque appel Encrypt et Decrypt contre votre CMK. Les appels à la clé gérée AWS apparaissent aussi, mais ils sont plus bruyants et plus difficiles à filtrer.
  • Révocabilité. Une CMK peut être désactivée ou planifiée pour suppression. Désactiver la clé rend la base incapable de faire de l’I/O — l’instance arrête de fonctionner. C’est désirable dans certains scénarios de réponse à incident (l’équipe juridique demande « gelez les données ») et désastreux dans d’autres (quelqu’un désactive accidentellement la clé). La clé gérée AWS ne peut pas être désactivée par vous.
  • Partage inter-comptes. Partager un snapshot vers un autre compte AWS exige une CMK avec une key policy qui accorde l’accès à l’autre compte. La clé gérée AWS ne peut pas être partagée entre comptes — le snapshot reste dans le compte source.

Les CMK coûtent des frais mensuels modestes par clé plus des frais d’API par usage. Le coût est négligeable pour des charges de production ; ne le laissez pas piloter la décision.

L’histoire inter-régions a sa propre bizarrerie. Un snapshot chiffré avec une CMK région-source ne peut pas être copié tel quel vers une autre région. L’opération de copie exige que vous spécifiiez une CMK région-destination, et KMS re-chiffre l’enveloppe des données durant la copie. La CMK destination peut être une CMK dans la région destination qui accorde l’accès au compte source (typique), ou une CMK multi-régions (fonctionnalité AWS plus récente, la même clé logique avec des réplicas dans plusieurs régions).

Comment vérifier

Vérifiez le statut de chiffrement actuel :

aws rds describe-db-instances \
  --db-instance-identifier prod-db-1 \
  --query 'DBInstances[].[DBInstanceIdentifier,StorageEncrypted,KmsKeyId]' \
  --output table

Si StorageEncrypted est false, l’instance n’est pas chiffrée au repos. Il n’y a pas de correctif in-place — voir le plan de migration plus bas.

Si StorageEncrypted est true et KmsKeyId se termine par :key/aws/rds (ou montre l’alias alias/aws/rds), elle utilise la clé gérée AWS. Pour vérifier la clé :

aws kms describe-key --key-id <KmsKeyId> \
  --query 'KeyMetadata.[KeyManager,Description,KeyState,Origin]' \
  --output table

KeyManager est AWS pour gérée AWS et CUSTOMER pour gérée client.

Vérifiez le statut de rotation de la clé :

aws kms get-key-rotation-status --key-id <KmsKeyId>

KeyRotationEnabled: true veut dire que l’auto-rotation annuelle est active. Si la valeur est false, la clé n’a pas tourné automatiquement depuis sa création. Activez-la à moins d’avoir une raison spécifique de ne pas le faire :

aws kms enable-key-rotation --key-id <KmsKeyId>

Pour le partage de snapshot inter-comptes, regardez la key policy :

aws kms get-key-policy --key-id <KmsKeyId> --policy-name default \
  --query 'Policy' --output text | jq .

Une key policy qui permet à un autre compte d’utiliser la clé a un statement comme :

{
  "Sid": "AllowExternalAccountToUseKey",
  "Effect": "Allow",
  "Principal": {"AWS": "arn:aws:iam::OTHER-ACCOUNT-ID:root"},
  "Action": [
    "kms:Decrypt",
    "kms:CreateGrant",
    "kms:DescribeKey"
  ],
  "Resource": "*"
}

Sans ce statement, le partage de snapshot vers l’autre compte échoue avec une erreur vague « access denied ».

La correction

Trois scénarios, chacun avec son runbook.

Scénario 1 : Nouvelle instance avec CMK dès le départ

Le bon chemin. Créez d’abord la CMK :

aws kms create-key \
  --description "RDS encryption key for prod-db-1" \
  --tags TagKey=Project,TagValue=production-platform

# La sortie inclut KeyId ; sauvegardez-le.

aws kms create-alias \
  --alias-name alias/rds-prod-db-1 \
  --target-key-id <KeyId>

aws kms enable-key-rotation --key-id <KeyId>

Utilisez une key policy qui permet à RDS d’utiliser la clé et à votre rôle ops de la gérer :

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "EnableRootPermissions",
      "Effect": "Allow",
      "Principal": {"AWS": "arn:aws:iam::123456789012:root"},
      "Action": "kms:*",
      "Resource": "*"
    },
    {
      "Sid": "AllowRDSToUseTheKey",
      "Effect": "Allow",
      "Principal": {"Service": "rds.amazonaws.com"},
      "Action": [
        "kms:Decrypt",
        "kms:DescribeKey",
        "kms:Encrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:CreateGrant"
      ],
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "kms:ViaService": "rds.us-east-1.amazonaws.com",
          "kms:CallerAccount": "123456789012"
        }
      }
    }
  ]
}

La condition kms:ViaService restreint la clé à un usage par RDS dans cette région, ce qui empêche le mauvais usage inter-services. La condition kms:CallerAccount met une ceinture et des bretelles au compte.

Créez la base avec la CMK :

aws rds create-db-instance \
  --db-instance-identifier prod-db-1 \
  --engine postgres \
  --engine-version 15.5 \
  --db-instance-class db.r6g.xlarge \
  --master-username postgres \
  --master-user-password REDACTED \
  --allocated-storage 100 \
  --storage-encrypted \
  --kms-key-id alias/rds-prod-db-1 \
  --vpc-security-group-ids sg-db \
  --db-subnet-group-name prod-db-subnets \
  --multi-az \
  --backup-retention-period 14 \
  --no-publicly-accessible

Scénario 2 : Migrer une instance non chiffrée existante vers CMK

L’instance est StorageEncrypted: false. La conversion directe n’est pas possible. La migration :

# 1. Prendre un snapshot final de l'instance non chiffrée.
aws rds create-db-snapshot \
  --db-snapshot-identifier prod-db-1-pre-encryption \
  --db-instance-identifier prod-db-1

# 2. Copier le snapshot, en appliquant le chiffrement avec la nouvelle CMK.
aws rds copy-db-snapshot \
  --source-db-snapshot-identifier prod-db-1-pre-encryption \
  --target-db-snapshot-identifier prod-db-1-encrypted \
  --kms-key-id alias/rds-prod-db-1

# 3. Restaurer le snapshot chiffré vers une nouvelle instance.
aws rds restore-db-snapshot \
  --db-instance-identifier prod-db-1-new \
  --db-snapshot-identifier prod-db-1-encrypted \
  --db-instance-class db.r6g.xlarge \
  --multi-az \
  --vpc-security-group-ids sg-db \
  --db-subnet-group-name prod-db-subnets

# 4. Après vérification, basculer l'application vers la nouvelle instance,
#    renommer l'ancienne en dehors du chemin, renommer la nouvelle en place.

La bascule exige du downtime applicatif — le snapshot est au point-dans-le-temps-du-snapshot, donc toute écriture après le snapshot doit être rejouée (en utilisant la réplication logique Postgres ou une brève fenêtre de verrou). Pour une petite base, toute la bascule fait 5–15 minutes ; pour une base multi-TB, une fenêtre de rattrapage par réplication logique est nécessaire.

Scénario 3 : Partage de snapshot inter-comptes avec CMK

L’autre compte a besoin d’une copie du snapshot pour des fins de DR ou de conformité. Les étapes :

# 1. Mettre à jour la key policy source pour autoriser le compte destination.
aws kms put-key-policy \
  --key-id alias/rds-prod-db-1 \
  --policy-name default \
  --policy file://updated-key-policy.json

# Où updated-key-policy.json ajoute le statement compte-destination :
# {
#   "Sid": "AllowDRAccount",
#   "Effect": "Allow",
#   "Principal": {"AWS": "arn:aws:iam::DR-ACCOUNT:root"},
#   "Action": ["kms:Decrypt","kms:CreateGrant","kms:DescribeKey"],
#   "Resource": "*"
# }

# 2. Partager le snapshot.
aws rds modify-db-snapshot-attribute \
  --db-snapshot-identifier prod-db-1-encrypted-snap \
  --attribute-name restore \
  --values-to-add DR-ACCOUNT-ID

# 3. Dans le compte DR, copier le snapshot (re-chiffrement avec une CMK du compte DR).
# Cette étape se fait dans le compte DR.
aws rds copy-db-snapshot \
  --source-db-snapshot-identifier arn:aws:rds:us-east-1:SOURCE-ACCOUNT:snapshot:prod-db-1-encrypted-snap \
  --target-db-snapshot-identifier prod-db-1-dr-copy \
  --kms-key-id alias/rds-dr-key

Trois choses qui mordent durant le travail sur le chiffrement :

La condition « kms:GrantIsForAWSResource ». Certaines opérations RDS exigent des grants KMS. La key policy doit permettre kms:CreateGrant avec la condition kms:GrantIsForAWSResource: true. Sans ça, la copie automatisée de snapshots inter-régions échoue silencieusement.

Les clés de chiffrement de replica diffèrent. Un read replica inter-régions ou un snapshot inter-régions utilise une clé région-destination. La CMK région-source ne fonctionne pas dans une autre région. Construisez d’abord la CMK région-destination, référencez-la explicitement.

Désactiver une clé en usage est une vraie panne. Une CMK dont une instance RDS dépend, si elle est désactivée ou planifiée pour suppression, fait perdre à l’instance l’accès à son stockage en quelques minutes. La base passe dans un état où lectures et écritures échouent. CloudTrail attrape l’événement de désactivation, mais la récupération exige de réactiver la clé. Gardez l’autorité de suppression de CMK strictement scopée — l’équipe d’opérations ne devrait pas être à un clic de tuer une base.

La stratégie chiffrement-et-clé est une des rares décisions RDS qui est véritablement difficile à inverser à bon marché. Choisissez la posture CMK à la création de l’instance, documentez la key policy, et mettez des garde-fous sur la suppression de clé. Re-chiffrer après coup est possible mais opérationnellement coûteux.


Stack Harbor conçoit et opère les topologies RDS / Aurora en production dans le cadre de Gestion AWS et de la couche Environnements infogérés. Si votre posture base de données se résume à « case Multi-AZ cochée + espoir », commencez par une consultation d’infrastructure.