Le secrets engine KV (Key-Value) est le plus utilisé dans Vault. Il stocke des paires clé/valeur comme des mots de passe, clés API ou tokens. La version KV v2 ajoute le versioning : chaque modification crée une nouvelle version, permettant de récupérer ou restaurer des valeurs précédentes.
Ce guide couvre toutes les opérations sur les secrets KV v2, du stockage basique au contrôle de concurrence avec Check-and-Set.
Prérequis
Section intitulée « Prérequis »- Vault installé et démarré (mode dev ou production)
- Variables d’environnement configurées (
VAULT_ADDR,VAULT_TOKEN)
Comprendre KV v1 vs KV v2
Section intitulée « Comprendre KV v1 vs KV v2 »Vault propose deux versions du secrets engine KV :
| Aspect | KV v1 | KV v2 |
|---|---|---|
| Versioning | Non | Oui (conserve les versions) |
| Soft delete | Non | Oui (récupérable) |
| Check-and-Set | Non | Oui (évite les écrasements) |
| Métadonnées | Basiques | Complètes (timestamps, custom) |
| Cas d’usage | Legacy, très haute performance | Standard, recommandé |
Activer KV v2 (production)
Section intitulée « Activer KV v2 (production) »# Activer KV v2 sur le path "secret/"vault secrets enable -path=secret kv-v2
# Vérifier l'activationvault secrets list | grep secretStocker un secret
Section intitulée « Stocker un secret »La commande vault kv put crée ou met à jour un secret.
Syntaxe de base
Section intitulée « Syntaxe de base »# Forme classique : path completvault kv put secret/chemin/du/secret clé1="valeur1" clé2="valeur2"
# Forme avec -mount (plus explicite)vault kv put -mount=secret chemin/du/secret clé1="valeur1" clé2="valeur2"Exemple concret
Section intitulée « Exemple concret »Imaginons une application web qui a besoin de se connecter à une base de données PostgreSQL :
vault kv put -mount=secret apps/webapp/database \ host="db.example.com" \ port="5432" \ username="webapp_user" \ password="SuperSecret123!"Sortie :
===== Secret Path =====secret/data/apps/webapp/database
======= Metadata =======Key Value--- -----created_time 2026-03-16T13:32:40.176016777Zcustom_metadata <nil>deletion_time n/adestroyed falseversion 1Comprendre les chemins API (path réel vs logique)
Section intitulée « Comprendre les chemins API (path réel vs logique) »Vous écrivez sur secret/apps/webapp/database, mais Vault stocke sur
secret/data/apps/webapp/database. Pourquoi ?
KV v2 utilise des sous-chemins API pour séparer les opérations :
| Opération | Chemin API | Exemple |
|---|---|---|
| Données (CRUD) | secret/data/... | secret/data/apps/webapp/database |
| Métadonnées | secret/metadata/... | secret/metadata/apps/webapp/database |
| Suppression (versions) | secret/delete/... | secret/delete/apps/webapp/database |
| Restauration | secret/undelete/... | secret/undelete/apps/webapp/database |
| Destruction | secret/destroy/... | secret/destroy/apps/webapp/database |
La CLI masque cette complexité, mais vous la verrez dans :
- les policies Vault (capabilities sur
secret/data/*) - l’API HTTP directe
- les intégrations tierces (Terraform, Kubernetes operator…)
Écrire des valeurs depuis un fichier
Section intitulée « Écrire des valeurs depuis un fichier »Vault accepte plusieurs formats d’entrée. Pour des secrets complexes, vous pouvez lire depuis un fichier.
Option 1 : Paires clé=valeur depuis stdin
# stdin avec le préfixe @- (tiret = stdin)echo '{"api_key":"sk-abc123","api_secret":"secret-xyz789"}' | \ vault kv put -mount=secret apps/webapp/api-config -Le contenu JSON est interprété comme plusieurs paires clé=valeur. Vault
stockera deux champs : api_key et api_secret.
Option 2 : Stocker un blob entier
Si vous voulez stocker un fichier entier (certificat, clé privée) comme une seule valeur :
vault kv put -mount=secret apps/webapp/tls-cert \ cert="$(cat server.crt)" \ key="$(cat server.key)"Option 3 : Fichier JSON avec @
# Le fichier doit contenir un objet JSON avec les paires clé-valeurcat > creds.json << 'EOF'{ "username": "admin", "password": "secret123"}EOF
vault kv put -mount=secret apps/webapp/creds @creds.json
# Nettoyerrm creds.jsonCette commande crée un secret avec deux champs : username et password.
Lire un secret
Section intitulée « Lire un secret »Lecture simple
Section intitulée « Lecture simple »vault kv get -mount=secret apps/webapp/databaseSortie :
===== Secret Path =====secret/data/apps/webapp/database
======= Metadata =======Key Value--- -----created_time 2026-03-16T13:32:40.176016777Zcustom_metadata <nil>deletion_time n/adestroyed falseversion 1
====== Data ======Key Value--- -----host db.example.compassword SuperSecret123!port 5432username webapp_userExtraire une valeur spécifique
Section intitulée « Extraire une valeur spécifique »Pour l’intégration dans des scripts, extrayez une seule valeur :
# Extraire le mot de passevault kv get -mount=secret -field=password apps/webapp/database# SuperSecret123!Format JSON
Section intitulée « Format JSON »Pour le parsing automatisé, utilisez le format JSON :
vault kv get -mount=secret -format=json apps/webapp/database | \ jq -r '.data.data.password'# SuperSecret123!Éviter les écrasements avec Check-and-Set
Section intitulée « Éviter les écrasements avec Check-and-Set »Quand plusieurs processus écrivent sur le même secret, il y a un risque d’écrasement silencieux. Check-and-Set (CAS) résout ce problème.
Le problème
Section intitulée « Le problème »Sans CAS, si deux processus modifient le même secret en parallèle :
- Processus A lit la version 5
- Processus B lit la version 5
- Processus A écrit → version 6
- Processus B écrit → version 7, écrasant les changements de A
La solution : -cas
Section intitulée « La solution : -cas »L’option -cas=<version> impose que l’écriture ne réussisse que si la
version courante correspond :
# Écrire seulement si la version actuelle est 2vault kv put -mount=secret -cas=2 apps/webapp/database \ password="NewSecurePassword!"Si un autre processus a modifié le secret entre-temps :
Error writing data to secret/data/apps/webapp/database: Error making API request.
Code: 400. Errors:* check-and-set parameter did not match the current versionCréer seulement si n’existe pas
Section intitulée « Créer seulement si n’existe pas »-cas=0 crée le secret uniquement s’il n’existe pas :
# Échoue si le secret existe déjàvault kv put -mount=secret -cas=0 apps/webapp/new-secret \ api_key="sk-newkey123"Forcer CAS au niveau métadonnées
Section intitulée « Forcer CAS au niveau métadonnées »Vous pouvez imposer l’usage de CAS pour tous les écrivains :
# Toute écriture sans -cas échoueravault kv metadata put -mount=secret -cas-required=true apps/webapp/databaseTentative d’écriture sans CAS :
Error writing data to secret/data/apps/webapp/database: Error making API request.
Code: 400. Errors:* check-and-set parameter required for this callVersioning
Section intitulée « Versioning »Chaque modification d’un secret crée une nouvelle version. C’est l’un des avantages majeurs de KV v2.
Mettre à jour un secret
Section intitulée « Mettre à jour un secret »Quand vous modifiez un secret, la version incrémente automatiquement :
# Mise à jour du mot de passe (crée version 2)vault kv put -mount=secret apps/webapp/database \ host="db.example.com" \ port="5432" \ username="webapp_user" \ password="NewPassword456!"Sortie :
...version 2Lire une version spécifique
Section intitulée « Lire une version spécifique »Vous pouvez récupérer n’importe quelle version antérieure :
# Lire la version 1 (ancien mot de passe)vault kv get -mount=secret -version=1 apps/webapp/databaseVoir l’historique des versions
Section intitulée « Voir l’historique des versions »vault kv metadata get -mount=secret apps/webapp/databaseSortie (extrait) :
======= Metadata =======Key Value--- -----cas_required falsecreated_time 2026-03-16T13:32:40.176016777Zcurrent_version 2delete_version_after 0smax_versions 0oldest_version 0updated_time 2026-03-16T13:45:12.234567890Z
====== Version 1 ======Key Value--- -----created_time 2026-03-16T13:32:40.176016777Zdeletion_time n/adestroyed false
====== Version 2 ======Key Value--- -----created_time 2026-03-16T13:45:12.234567890Zdeletion_time n/adestroyed falseRevenir à une version antérieure
Section intitulée « Revenir à une version antérieure »Si une mise à jour pose problème, vous pouvez “rollback” :
# Restaurer la version 1 comme nouvelle version (crée version 3)vault kv rollback -mount=secret -version=1 apps/webapp/databaseSupprimer des secrets
Section intitulée « Supprimer des secrets »KV v2 distingue plusieurs niveaux de suppression. Le modèle mental :
| Action | Effet | Réversible ? |
|---|---|---|
delete | Masque la version (soft delete) | ✅ Oui (undelete) |
undelete | Rend la version visible à nouveau | — |
destroy | Supprime les données de la version | ❌ Non |
metadata delete | Supprime tout : versions + métadonnées | ❌ Non |
Delete (soft delete)
Section intitulée « Delete (soft delete) »Marque la version comme supprimée mais conserve les données :
vault kv delete -mount=secret apps/webapp/databaseLes données ne sont plus accessibles par un get normal :
vault kv get -mount=secret apps/webapp/database# Affiche uniquement les métadonnées, pas les donnéesUndelete (restauration)
Section intitulée « Undelete (restauration) »Annule un soft delete :
# Restaurer la version 2vault kv undelete -mount=secret -versions=2 apps/webapp/databaseLes données sont à nouveau accessibles.
Destroy (suppression définitive des données)
Section intitulée « Destroy (suppression définitive des données) »Supprime définitivement les données d’une ou plusieurs versions :
# Supprimer définitivement les versions 1 et 2vault kv destroy -mount=secret -versions=1,2 apps/webapp/databaseSupprimer l’objet secret entier
Section intitulée « Supprimer l’objet secret entier »Pour supprimer complètement un secret (toutes versions + métadonnées) :
vault kv metadata delete -mount=secret apps/webapp/databaseCette commande supprime tout : le secret n’existe plus dans Vault.
Organiser vos secrets pour les policies
Section intitulée « Organiser vos secrets pour les policies »Une bonne organisation facilite la gestion des policies et la maintenance. La structure de vos chemins détermine directement vos policies de sécurité.
Structure recommandée
Section intitulée « Structure recommandée »secret/├── apps/ # Secrets applicatifs│ ├── webapp/│ │ ├── database # Credentials DB│ │ ├── api-keys # Clés API tierces│ │ └── config # Config sensible│ └── mobile-app/│ └── firebase├── infra/ # Secrets infrastructure│ ├── aws/│ │ └── credentials│ └── docker-registry/│ └── credentials└── teams/ # Secrets par équipe ├── dev/ └── ops/Pourquoi cette structure ?
Section intitulée « Pourquoi cette structure ? »Cette hiérarchie permet d’écrire des policies précises sans wildcards trop larges :
# Policy pour l'application webapp (lecture seule)path "secret/data/apps/webapp/*" { capabilities = ["read"]}
# Policy pour l'équipe ops (lecture/écriture sur infra)path "secret/data/infra/*" { capabilities = ["create", "update", "read", "delete"]}
path "secret/metadata/infra/*" { capabilities = ["list", "read"]}Critères d’organisation
Section intitulée « Critères d’organisation »| Critère | Exemple de chemin | Avantage |
|---|---|---|
| Par application | secret/apps/webapp/... | Isolation par service |
| Par environnement | secret/prod/..., secret/dev/... | Séparation prod/dev |
| Par équipe | secret/teams/backend/... | Ownership clair |
| Par type | secret/databases/..., secret/api-keys/... | Gestion transverse |
Combinez ces critères selon votre contexte :
secret/prod/apps/webapp/database ou secret/apps/webapp/prod/database.
Lister les secrets
Section intitulée « Lister les secrets »# Lister les secrets sous un cheminvault kv list -mount=secret apps/Sortie :
Keys----webapp/mobile-app/Métadonnées personnalisées
Section intitulée « Métadonnées personnalisées »Ajoutez des métadonnées pour documenter vos secrets :
vault kv metadata put -mount=secret \ -custom-metadata="owner=team-backend" \ -custom-metadata="environment=production" \ -custom-metadata="rotation=90days" \ apps/webapp/databaseLimiter les versions conservées
Section intitulée « Limiter les versions conservées »Par défaut, Vault conserve toutes les versions. Cela peut poser problème :
- Croissance du stockage
- Conservation d’anciennes valeurs sensibles plus longtemps que nécessaire
Limitez avec -max-versions :
# Conserver uniquement les 10 dernières versionsvault kv metadata put -mount=secret -max-versions=10 apps/webapp/databaseSuppression automatique après soft delete
Section intitulée « Suppression automatique après soft delete »Configurez un délai avant suppression définitive des versions soft-deleted :
# Supprimer définitivement 24h après un deletevault kv metadata put -mount=secret -delete-version-after=24h apps/webapp/databaseConsommation par les applications
Section intitulée « Consommation par les applications »Ce guide montre la gestion via CLI. En production, vos applications consomment les secrets via d’autres méthodes :
| Méthode | Usage typique |
|---|---|
| API HTTP | Intégration directe dans le code |
| Agent + templates | Injection dans fichiers de config |
| CSI driver | Montage comme volume Kubernetes |
| Vault Secrets Operator | Synchronisation vers Secrets K8s |
Ce que KV v2 ne fait pas
Section intitulée « Ce que KV v2 ne fait pas »KV v2 améliore énormément la gestion des secrets statiques, mais il a des limites structurelles :
| Capacité | KV v2 | Alternative Vault |
|---|---|---|
| Générer des secrets dynamiques | ❌ | Database, AWS, Azure… |
| Rotation automatique côté cible | ❌ | Database secrets engine |
| Chiffrement de données applicatives | ❌ | Transit |
| Certificats X.509 | ❌ | PKI |
| Clés SSH signées | ❌ | SSH secrets engine |
Règle simple : si vous pouvez éviter un secret statique, faites-le.
- Base de données → Database secrets engine (credentials éphémères)
- Cloud provider → AWS/Azure/GCP secrets engine
- Certificats → PKI secrets engine
- SSH → SSH secrets engine avec certificats
KV v2 reste indispensable pour :
- Clés API tierces (imposées par le fournisseur)
- Secrets legacy (systèmes non intégrables)
- Tokens partagés (Slack webhooks, API tokens…)
- Bootstrap secrets (premiers credentials pour accéder au reste)
Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Solution |
|---|---|---|
no value found at secret/data/... | Secret inexistant ou supprimé | Vérifier le path, utiliser undelete |
permission denied | Policy insuffisante | Vérifier les capabilities read, list sur secret/data/... |
check-and-set parameter did not match | Écriture concurrente | Relire la version actuelle, utiliser -cas=<version> |
check-and-set parameter required | cas-required=true sur la clé | Ajouter -cas=<version> à la commande |
| Version non trouvée | Version détruite | Vérifier avec metadata get |
| Versions anciennes inaccessibles | max-versions atteint | Augmenter la limite ou accepter la perte |
À retenir
Section intitulée « À retenir »- KV v2 est le standard pour les secrets statiques — préférez les secrets dynamiques quand c’est possible
- Check-and-Set (
-cas) évite les écrasements concurrents — activez-cas-requiredsur les secrets critiques - La CLI masque les chemins API — vos policies doivent cibler
secret/data/*etsecret/metadata/* delete= soft delete récupérable,destroy= définitif,metadata delete= suppression totale- Organisez vos secrets pour faciliter les policies : par application/environnement/équipe
- Les métadonnées personnalisées documentent mais ne déclenchent rien
- Limitez les versions avec
-max-versionspour éviter la croissance infinie et la rétention excessive