Le secrets engine Transit offre du chiffrement as a service. Au lieu de gérer vous-même les clés de chiffrement dans votre application, vous envoyez les données à Vault qui les chiffre ou les déchiffre pour vous. Les clés ne quittent jamais Vault.
Ce guide vous montre comment utiliser Transit pour sécuriser vos données applicatives.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Activer le secrets engine Transit et créer une clé de chiffrement
- Chiffrer et déchiffrer des données applicatives via la CLI puis l'API
- Choisir le type de clé adapté à l'opération visée
- Isoler des usages avec la dérivation et le paramètre
context - Faire tourner une clé et migrer les données existantes avec
rewrap
Prérequis
Section intitulée « Prérequis »- Vault installé et démarré
- Variables d'environnement configurées (
VAULT_ADDR,VAULT_TOKEN)
Pourquoi Transit ?
Section intitulée « Pourquoi Transit ? »Imaginons une application qui stocke des données sensibles (numéros de carte, données de santé) dans une base de données. Vous devez les chiffrer, mais :
- Où stocker la clé de chiffrement ? Dans le code ? Une variable ? Un fichier ?
- Comment faire la rotation ? Changer la clé sans re-chiffrer toutes les données ?
- Qui a accès aux clés ? Comment auditer ?
Transit résout ces problèmes :
| Approche traditionnelle | Avec Transit |
|---|---|
| Clé dans le code/config | Clé dans Vault, jamais exposée |
| Rotation complexe (re-chiffrement manuel) | Rotation facilitée (rewrap) |
| Audit difficile | Logs d'audit complets |
| Algorithme à choisir | aes256-gcm96 par défaut |
Ce que Transit ne fait pas
Section intitulée « Ce que Transit ne fait pas »Transit est puissant, mais il a des limites structurelles :
| Capacité | Transit | Alternative |
|---|---|---|
| Conserver le format/longueur des données | ❌ | Transform (FPE) |
| Chiffrer de gros fichiers efficacement | ❌ | GPG, age, KMS cloud |
| Remplacer un KMS plateforme complet | ⚠️ Partiel | AWS KMS, GCP KMS |
| Tokenisation | ❌ | Transform |
Activer Transit
Section intitulée « Activer Transit »Le secrets engine Transit n'est pas activé par défaut :
vault secrets enable transitSortie :
Success! Enabled the transit secrets engine at: transit/Créer une clé de chiffrement
Section intitulée « Créer une clé de chiffrement »Chaque application ou domaine fonctionnel devrait avoir sa propre clé :
vault write -f transit/keys/my-app-keyL'option -f (force) indique qu'on n'envoie pas de données, juste une création.
Sortie :
Key Value--- -----allow_plaintext_backup falseauto_rotate_period 0sdeletion_allowed falsederived falseexportable falseimported_key falsekeys map[1:1773667976]latest_version 1min_available_version 0min_decryption_version 1min_encryption_version 0name my-app-keysupports_decryption truesupports_derivation truesupports_encryption truesupports_signing falsetype aes256-gcm96Choisir le bon type de clé
Section intitulée « Choisir le bon type de clé »Le type de clé se fige à la création et ne peut plus changer : pour passer d'une clé symétrique à une clé de signature, il faut créer une nouvelle clé. Lisez le tableau par colonne, chaque type expose un sous-ensemble d'opérations, et Vault refuse explicitement les autres (message encryption not supported for key type ecdsa-p256, par exemple). Une précision sur la colonne HMAC : l'endpoint transit/hmac/ accepte en réalité tous les types de clés, y compris asymétriques, le tableau signale seulement les usages recommandés.
| Type de clé | Chiffrement | Déchiffrement | Signature | HMAC | Usage typique |
|---|---|---|---|---|---|
aes256-gcm96 | ✅ | ✅ | ❌ | ✅ | Chiffrement symétrique standard |
chacha20-poly1305 | ✅ | ✅ | ❌ | ❌ | Alternative à AES |
rsa-2048 / rsa-4096 | ✅ | ✅ | ✅ | ❌ | Chiffrement asymétrique |
ecdsa-p256 / ecdsa-p384 | ❌ | ❌ | ✅ | ❌ | Signatures uniquement |
ed25519 | ❌ | ❌ | ✅ | ❌ | Signatures EdDSA |
Créer une clé avec un type spécifique
Section intitulée « Créer une clé avec un type spécifique »# Clé RSA pour chiffrement asymétriquevault write transit/keys/my-rsa-key type=rsa-4096
# Clé ECDSA pour signaturesvault write transit/keys/my-signing-key type=ecdsa-p256Chiffrer des données
Section intitulée « Chiffrer des données »Pour chiffrer, envoyez le texte en base64 :
# Chiffrer "données sensibles"vault write transit/encrypt/my-app-key \ plaintext=$(echo -n "données sensibles" | base64)Sortie :
Key Value--- -----ciphertext vault:v1:+SBSxpnGHczUzugypADpd12e/P2p2bT/grzy8whwrwu7Ijt+NpXxI733VF/ER48=key_version 1Le ciphertext retourné est au format vault:v<version>:<données_chiffrées>.
Dans un script
Section intitulée « Dans un script »L'option -field=ciphertext isole la valeur utile du tableau de sortie, ce qui évite d'avoir à découper le résultat avec awk. Deux réflexes s'imposent dans un script réel : ne jamais laisser le secret en clair dans une variable exportée ni dans l'historique du shell, et vérifier le code de retour de vault write avant d'écrire quoi que ce soit en base. Une erreur d'authentification renvoie une chaîne vide, qui s'insérerait silencieusement à la place du chiffré.
#!/bin/bashSECRET="mon_secret_api_key_123"
# ChiffrerENCRYPTED=$(vault write -field=ciphertext transit/encrypt/my-app-key \ plaintext="$(printf '%s' "$SECRET" | base64 -w0)")
echo "Chiffré : $ENCRYPTED"# Stockez $ENCRYPTED dans votre base de donnéesDéchiffrer des données
Section intitulée « Déchiffrer des données »vault write transit/decrypt/my-app-key \ ciphertext="vault:v1:+SBSxpnGHczUzugypADpd12e/P2p2bT/grzy8whwrwu7Ijt+NpXxI733VF/ER48="Sortie :
Key Value--- -----plaintext ZG9ubsOpZXMgc2Vuc2libGVzLe plaintext est en base64. Décodez-le :
vault write -field=plaintext transit/decrypt/my-app-key \ ciphertext="vault:v1:..." | base64 -d# données sensiblesChiffrement par lot (batch)
Section intitulée « Chiffrement par lot (batch) »Pour des volumes importants, Transit supporte le batch via batch_input :
vault write transit/encrypt/my-app-key \ batch_input='[ {"plaintext": "'$(echo -n "secret1" | base64)'"}, {"plaintext": "'$(echo -n "secret2" | base64)'"}, {"plaintext": "'$(echo -n "secret3" | base64)'"} ]'Sortie :
Key Value--- -----batch_results [map[ciphertext:vault:v1:...] map[ciphertext:vault:v1:...] ...]Le batch réduit drastiquement le nombre d'appels réseau et améliore les performances pour les traitements de masse.
Dérivation de clés et contexte
Section intitulée « Dérivation de clés et contexte »La dérivation permet d'isoler cryptographiquement des usages sans
multiplier les clés. Une même clé logique produit des clés effectives
différentes selon le context fourni.
Créer une clé dérivée
Section intitulée « Créer une clé dérivée »derived=true se pose uniquement à la création et ne peut plus être retiré. Le matériel cryptographique reste unique dans Vault, mais chaque context produit une clé effective distincte par dérivation. Résultat concret, un chiffré du tenant A ne peut pas être déchiffré avec le contexte du tenant B, alors qu'une seule clé est administrée et tournée.
vault write transit/keys/multi-tenant-key derived=trueChiffrer avec un contexte
Section intitulée « Chiffrer avec un contexte »Le context s'envoie encodé en base64, exactement comme le plaintext. Choisissez une valeur stable et non ambiguë : c'est elle qui conditionne le déchiffrement, et une chaîne perdue rend les données définitivement illisibles. Un identifiant technique de tenant convient, un libellé commercial susceptible d'être renommé, non.
# Données du tenant Avault write transit/encrypt/multi-tenant-key \ plaintext=$(echo -n "données tenant A" | base64) \ context=$(echo -n "tenant-a" | base64)
# Données du tenant B (même clé, contexte différent)vault write transit/encrypt/multi-tenant-key \ plaintext=$(echo -n "données tenant B" | base64) \ context=$(echo -n "tenant-b" | base64)Déchiffrer avec le bon contexte
Section intitulée « Déchiffrer avec le bon contexte »vault write transit/decrypt/multi-tenant-key \ ciphertext="vault:v1:..." \ context=$(echo -n "tenant-a" | base64)Cas d'usage de la dérivation
Section intitulée « Cas d'usage de la dérivation »Le point commun de ces quatre scénarios : le contexte reprend une frontière d'isolation qui existe déjà dans le modèle de données. C'est le critère de choix. Évitez au contraire un contexte dérivé d'une valeur mutable, comme une adresse e-mail ou un nom de service, qui condamnerait les anciennes données au premier changement.
| Scénario | Contexte |
|---|---|
| Multi-tenant | ID du tenant |
| Par environnement | prod, staging, dev |
| Par type de données | pii, financial, logs |
| Par utilisateur | User ID |
Chiffrement convergent
Section intitulée « Chiffrement convergent »Par défaut, Transit produit un ciphertext différent pour chaque chiffrement du même plaintext (même clé, même données). C'est le comportement le plus sûr.
Le convergent encryption produit un ciphertext identique pour la même combinaison plaintext + context :
vault write transit/keys/convergent-key \ derived=true \ convergent_encryption=trueQuand utiliser le convergent ?
Section intitulée « Quand utiliser le convergent ? »| Cas d'usage | Utilité |
|---|---|
| Déduplication | Détecter les doublons sans déchiffrer |
| Recherche déterministe | Indexer sur des valeurs chiffrées |
| Comparaison | Vérifier l'égalité sans exposer le plaintext |
Rotation de clés
Section intitulée « Rotation de clés »La rotation crée une nouvelle version de la clé. Les anciennes versions restent disponibles pour déchiffrer les données existantes.
Effectuer une rotation
Section intitulée « Effectuer une rotation »vault write -f transit/keys/my-app-key/rotateVérifiez :
vault read transit/keys/my-app-keySortie (extrait) :
keys map[1:1773667976 2:1773668123]latest_version 2Comportement après rotation
Section intitulée « Comportement après rotation »| Opération | Version utilisée |
|---|---|
| Nouveau chiffrement | Toujours la dernière (v2) |
| Déchiffrement v1 | Fonctionne ✅ |
| Déchiffrement v2 | Fonctionne ✅ |
La rotation seule ne migre pas les données existantes. Elles restent chiffrées avec l'ancienne version jusqu'à un rewrap explicite.
Rewrap : migrer les données vers la nouvelle clé
Section intitulée « Rewrap : migrer les données vers la nouvelle clé »Pour que les données existantes bénéficient de la nouvelle version de clé, utilisez rewrap :
vault write transit/rewrap/my-app-key \ ciphertext="vault:v1:..."Sortie :
Key Value--- -----ciphertext vault:v2:... ← Nouvelle versionkey_version 2Stratégie de migration
Section intitulée « Stratégie de migration »-
Rotation : créer la nouvelle version de clé
-
Rewrap progressif : migrer les données en batch via l'application
-
Vérification : s'assurer qu'aucune donnée n'utilise l'ancienne version
-
Restriction : augmenter
min_decryption_versionpour forcer la migration
Configuration avancée
Section intitulée « Configuration avancée »Les trois réglages ci-dessous se posent après coup sur l'endpoint config d'une clé existante, à une exception près, exportable, qui doit être décidé dès la création. Deux d'entre eux sont irréversibles dans les faits : abaisser min_decryption_version ne ressuscite pas les données déjà rendues illisibles, et exportable=true ne se retire jamais.
Rotation automatique
Section intitulée « Rotation automatique »Configurez une rotation périodique automatique :
vault write transit/keys/my-app-key/config auto_rotate_period=720h # 30 joursLimiter les versions utilisables
Section intitulée « Limiter les versions utilisables »Pour forcer la migration vers les nouvelles clés, définissez une version minimale de déchiffrement :
# Refuser le déchiffrement avec les versions < 3vault write transit/keys/my-app-key/config min_decryption_version=3Autoriser l'export de clé
Section intitulée « Autoriser l'export de clé »Par défaut, les clés ne sont jamais exportables. Pour des besoins exceptionnels (migration hors Vault) :
# À faire UNIQUEMENT à la création de la clévault write transit/keys/exportable-key exportable=true allow_plaintext_backup=trueCas d'usage
Section intitulée « Cas d'usage »Transit ne sert pas qu'au chiffrement de champs. Les trois usages suivants reposent tous sur le même principe, le matériel cryptographique reste dans Vault et l'application n'échange que des données et des résultats. Ils diffèrent par l'opération demandée : chiffrement réversible, empreinte d'intégrité, ou signature vérifiable par un tiers.
Chiffrement de colonnes en base
Section intitulée « Chiffrement de colonnes en base »Votre application chiffre certaines colonnes avant insertion :
Les clés de chiffrement n'existent que dans Vault.
Génération de HMAC
Section intitulée « Génération de HMAC »Transit peut générer des signatures HMAC pour valider l'intégrité :
vault write transit/hmac/my-app-key \ input=$(echo -n "données à signer" | base64)Sortie :
Key Value--- -----hmac vault:v1:abc123...Signature avec clés asymétriques
Section intitulée « Signature avec clés asymétriques »Avec une clé RSA ou ECDSA :
# Créer une clé de signaturevault write transit/keys/signing-key type=ecdsa-p256
# Signervault write transit/sign/signing-key \ input=$(echo -n "données à signer" | base64)
# Vérifiervault write transit/verify/signing-key \ input=$(echo -n "données à signer" | base64) \ signature="vault:v1:..."Intégration applicative
Section intitulée « Intégration applicative »En production, intégrez Transit via l'API HTTP ou un SDK.
Exemple API (curl)
Section intitulée « Exemple API (curl) »L'API reprend exactement la structure de la CLI : le chemin transit/encrypt/<clé> devient /v1/transit/encrypt/<clé>, et les paramètres passent en JSON. Le jeton voyage dans l'en-tête X-Vault-Token. En production, ne le passez pas par une variable de shell : les SDK récupèrent le jeton depuis un mécanisme d'authentification (AppRole, Kubernetes, JWT) et le renouvellent automatiquement avant expiration.
curl -s \ --header "X-Vault-Token: $VAULT_TOKEN" \ --request POST \ --data '{"plaintext": "'$(echo -n "secret" | base64)'"}' \ $VAULT_ADDR/v1/transit/encrypt/my-app-key | jqSDKs disponibles
Section intitulée « SDKs disponibles »| Langage | SDK/Client |
|---|---|
| Go | github.com/hashicorp/vault/api |
| Java | Spring Cloud Vault, vault-java-driver |
| Python | hvac |
| Node.js | node-vault |
| Ruby | vault gem |
Performances et dimensionnement
Section intitulée « Performances et dimensionnement »Transit centralise la crypto mais augmente la dépendance applicative à Vault. À considérer :
| Aspect | Impact |
|---|---|
| Latence | Chaque opération = appel réseau à Vault |
| Débit | Vault devient un composant critique haute charge |
| Disponibilité | Si Vault down, pas de chiffrement/déchiffrement |
| Quotas | Vault supporte des rate limits par path |
Recommandations
Section intitulée « Recommandations »Ces quatre leviers agissent sur des points différents de la chaîne, et le premier a l'effet le plus net : passer de mille appels unitaires à un appel batch_input divise la latence cumulée d'un facteur considérable, parce que l'essentiel du coût est le temps réseau, pas le calcul cryptographique. Le cache applicatif, lui, se conçoit avec précaution, il ramène des données en clair en mémoire, ce que Transit cherchait justement à éviter.
- Batch : regroupez les opérations plutôt que des appels unitaires
- Cache applicatif : pour les données déchiffrées fréquemment lues
- Monitoring : surveillez les métriques Vault (latence, throughput)
- HA : cluster Vault en haute disponibilité pour la résilience
Dépannage
Section intitulée « Dépannage »Transit renvoie ses erreurs en HTTP 400 avec un message explicite : lisez-le avant toute chose, il désigne presque toujours la cause exacte. Les libellés de la colonne « Symptôme » sont abrégés, les messages réels de Vault sont plus longs, par exemple invalid ciphertext: could not decode base64, ciphertext or signature version is disallowed by policy (too old) pour un min_decryption_version trop élevé, ou missing 'context' for key derivation sur une clé dérivée. Attention au cas trompeur : cipher: message authentication failed signifie que le chiffré a été produit par une autre clé, pas qu'il est corrompu.
| Symptôme | Cause probable | Solution |
|---|---|---|
invalid ciphertext | Format incorrect | Vérifier le préfixe vault:v1: |
ciphertext was not valid base64 | Données corrompues | Vérifier l'intégrité du ciphertext |
message authentication failed | Mauvaise clé ou données modifiées | Vérifier le nom de clé |
key version not available | min_decryption_version trop élevé | Rewrap les données d'abord |
context required | Clé derived=true sans context | Fournir context= encodé base64 |
unsupported operation | Type de clé incompatible | Vérifier les capacités du type |
À retenir
Section intitulée « À retenir »- Transit = chiffrement as a service, clés jamais exposées
- Toujours encoder en base64 avant d'envoyer à Vault
- Choisir le bon type de clé selon l'opération (chiffrement, signature...)
- Dérivation + context : isoler cryptographiquement sans multiplier les clés
- Rotation ≠ migration : rewrap nécessaire pour les données existantes
- Convergent encryption : déterministe mais révèle l'égalité des plaintexts
- Batch pour les performances, API/SDK pour la production
- Transit ne préserve pas le format, pour cela, voir Transform