Sägetstrasse 18, 3123 Belp, Switzerland +41 79 173 36 84 info@ict.technology

      HashiCorp Vault Deep Dive – Partie 2b : Travail pratique avec le Key/Value Secrets Engine

      La Key/Value Secrets Engine fait partie intégrante de presque toute implémentation de Vault. Il constitue la base du stockage sécurisé des secrets statiques et est, en pratique, utilisé bien plus fréquemment que de nombreux Secrets Engines dynamiques.

      Après l’introduction théorique dans la partie 2a, nous abordons dans cet article le travail concret avec le Secrets Engine KV. Nous montrons comment écrire, lire, mettre à jour et supprimer des secrets, et analysons de manière pratique les différences entre les versions 1 et 2 de KV. L’accent est mis sur les commandes pertinentes en production, les écueils réalistes et des recommandations concrètes pour le quotidien opérationnel, c’est pourquoi je vous transmets ces connaissances sous forme de tutoriel mêlé à une fiche mémo.

      La commande vault kv : votre boîte à outils du quotidien

      L’interaction avec le Secrets Engine KV se fait via la commande vault kv. Cette commande abstrait en interne les différences entre les versions, mais indique clairement dans sa sortie s’il s’agit d’un Secrets Engine v1 ou v2. Les sous-commandes de base se répartissent en deux groupes :

      Opérations de base (disponibles dans KV v1 et v2) :

      • put : écrire ou mettre à jour des secrets
      • get : lire des secrets
      • delete : supprimer des secrets (pas nécessairement de manière définitive)
      • list : afficher tous les chemins disponibles

      Opérations avancées (uniquement KV v2) :

      • patch : mettre à jour des clés spécifiques sans écraser les autres
      • rollback : revenir à une version spécifique
      • undelete : restaurer des versions supprimées
      • destroy : supprimer définitivement des versions

      Ces commandes avancées ne sont disponibles qu’avec KV v2 car elles s’appuient sur les métadonnées stockées en interne. L’ancienne v1 ne prend pas encore en charge les métadonnées.

      Écrire des secrets avec put : simple, mais avec des pièges

      La commande d’écriture vault kv put est la méthode centrale pour écrire des secrets dans le Secrets Engine KV :


      vault kv put <chemin> <clé>=<valeur> [<clé>=<valeur>...]

      Un exemple simple : commençons par activer les Secrets Engines :


      $ vault secrets enable kv
      Success! Enabled the kv secrets engine at: kv/
      $
      $ vault secrets enable -path=kvv2 kv-v2
      Success! Enabled the kv-v2 secrets engine at: kvv2/

      La commande suivante enregistre ensuite le secret sous le chemin kv/app/db avec la clé pass et la valeur 123. La sortie varie selon la version utilisée :

      KV Version 1 :


      $ vault kv put kv/app/db pass=123
      Success! Data written to: kv/app/db
      $

      KV Version 2 :


      $ vault kv put kvv2/app/db pass=123
      == Secret Path ==
      kvv2/data/app/db
      
      ======= Metadata =======
      Key                Value
      ---                -----
      created_time       2025-07-01T10:52:07.551872783Z
      custom_metadata    <nil>
      deletion_time      n/a
      destroyed          false
      version            1
      $ 

      La version 2 fournit des métadonnées, telles que la date de création et la version actuelle.

      Remarque importante : avec KV v2, l’enregistrement a lieu dans un chemin interne avec le préfixe supplémentaire /data/. Cela est particulièrement important lors de l’utilisation directe de l’API, car cela signifie qu’on ne peut pas migrer simplement de v1 vers v2 sans adapter le cas échéant les scripts et applications concernés !

      Enregistrer plusieurs paires Key/Value en une seule fois

      Une commande put unique peut enregistrer autant de clés que souhaité :


      $ vault kv put kv/app/db pass=123 user=admin api=myapisecret
      Success! Data written to: kv/app/db
      $ vault kv put kvv2/app/db pass=123 user=admin api=myapisecret
      == Secret Path ==
      kvv2/data/app/db
      
      ======= Metadata =======
      Key                Value
      ---                -----
      created_time       2025-07-01T10:56:04.624145825Z
      custom_metadata    <nil>
      deletion_time      n/a
      destroyed          false
      version            2
      [rramge@ol9 terraform-vault-kv]$ 

      En pratique, cela permet d’économiser des commandes, mais n’oubliez pas : le contenu entier au chemin indiqué est remplacé. En cas de doute, procédez clé par clé pour améliorer la lisibilité des scripts et réduire le risque d’erreur - ou utilisez des fichiers comme montré dans la section suivante.

      Importer des secrets à partir de fichiers JSON

      Pour les environnements automatisés ou les structures de secrets complexes, il est recommandé d’utiliser des fichiers pour saisir plusieurs paires Key/Value :


      $ vault kv put kv/app/db @secrets.json

      Contenu exemple du fichier secrets.json :


      {
        "pass": "123",
        "user": "admin",
        "api": "myapisecret"
      }

      Différence importante entre put et patch

      De nombreux utilisateurs de Vault commettent tôt une erreur aux conséquences importantes : ils utilisent put pour mettre à jour des valeurs individuelles.

      Dans KV v1 et v2, cela entraîne toujours la suppression de toutes les données existantes du secret si elles ne sont pas présentes dans la nouvelle commande put.

      Exemple :


      # État initial
      $ vault kv put kv/app/db pass=123 user=admin api=myoldapisecret
      Success! Data written to: kv/app/db
      $
      # Mise à jour de la clé API, par erreur via "put" $ vault kv put kv/app/db pass=123 user=admin api=myoldapisecret
      Success! Data written to: kv/app/db
      $
      # Résultat : seul "api" est conservé $ vault kv get kv/app/db
      === Data ===
      Key Value
      --- -----
      api mynewapisecret
      $


      Les clés user et pass sont donc perdues.

      vault kv put était la mauvaise commande pour conserver les clés user et pass existantes. En effet, seul patch empêche leur suppression. Nous reviendrons sur ce point plus bas. Retenez pour l’instant que put est destructif :

      Important : Une commande vault kv put remplace toujours toutes les données au chemin spécifié. Il ne s’agit pas d’une opération de fusion !

      Lire des secrets avec get : un coup d'œil dans le stockage

      Avec vault kv get, vous récupérez des secrets. Par défaut, la version la plus récente est toujours affichée.

      Par exemple, cette commande affiche :


      vault kv get kv/app/db

      Avec KV v1 :


      $ vault kv get kv/app/db
      ==== Data ====
      Key Value
      --- -----
      api myapisecret
      pass 123
      user admin
      $

      Avec KV v2 :


      $ vault kv get kvv2/app/db
      == Secret Path ==
      kvv2/data/app/db
      ======= Metadata =======
      Key Value
      --- -----
      created_time 2025-07-01T10:56:04.624145825Z
      custom_metadata <nil>
      deletion_time n/a
      destroyed false
      version 2
      ==== Data ====
      Key Value
      --- -----
      api myapisecret
      pass 123
      user admin
      $

      Remarque : Ici aussi, le chemin /data/ est visible dans KV v2. Si vous analysez cette sortie dans des scripts ou des applications, vous devez en tenir compte.

      Sortie JSON pour les scripts et l’automatisation

      Avec -format=json, vous obtenez des données lisibles par machine :


      $ vault kv get -format=json kv/app/db
      {
        "request_id": "7de43863-d7c4-837f-b59c-4b5e546a1d65",
        "lease_id": "",
        "lease_duration": 2764800,
        "renewable": false,
        "data": {
          "api": "myapisecret",
          "pass": "123",
          "user": "admin"
        },
        "warnings": null,
        "mount_type": "kv"
      }
      $ 
      

      Vous pouvez combiner cela avec jq :


      $ vault kv get -format=json kv/app/db | jq -r '.data.api'
      myapisecret
      $ 
      

      Astuce pro : vous pouvez définir le format de sortie par défaut sur JSON de manière permanente via la variable d’environnement VAULT_FORMAT :


      export VAULT_FORMAT=json

       

      Récupérer des versions spécifiques d’un secret avec -version

      Le comportement de lecture de get est assez simple à comprendre, mais il faut d’abord connaître les différences. Les règles suivantes s’appliquent :

      • Une commande get normale renvoie toujours la dernière version.
      • Pour les secrets supprimés (KV v2), vous obtenez des métadonnées, mais aucune donnée.
      • Des versions spécifiques peuvent être récupérées avec --version=X (également uniquement avec KV v2).

      Exemple de récupération d’une version spécifique d’un secret :


        $ vault kv get --version=1 kvv2/app/db
        == Secret Path ==
        kvv2/data/app/db
        
        ======= Metadata =======
        Key                Value
        ---                -----
        created_time       2025-07-01T10:52:07.551872783Z
        custom_metadata    <nil>
        deletion_time      n/a
        destroyed          false
        version            1
        
        ==== Data ====
        Key     Value
        ---     -----
        pass    123
        $ vault kv get --version=2 kvv2/app/db
        == Secret Path ==
        kvv2/data/app/db
        
        ======= Metadata =======
        Key                Value
        ---                -----
        created_time       2025-07-01T10:56:04.624145825Z
        custom_metadata    <nil>
        deletion_time      n/a
        destroyed          false
        version            2
        
        ==== Data ====
        Key     Value
        ---     -----
        api     myapisecret
        pass    123
        user    admin
        $ 

        Je l’ai déjà dit plusieurs fois, mais il ne faut pas se lasser de le répéter : La gestion de versions des secrets n’est disponible que dans KV v2. Cela signifie également que seul le Secrets Engine KV v2 permet une inspection ciblée de l’historique d’un secret donné.  Cela peut être très important pour les audits ultérieurs, par exemple pour prouver si et à quelle fréquence des secrets ont réellement été renouvelés.

        Mises à jour ciblées et restauration de secrets

        patch : Mettre à jour précisément la bonne clé

        Plus haut dans cet article, nous avons déjà clairement souligné que la commande put écrase entièrement les secrets existants et risque donc de supprimer des données présentes.  Utilisez donc patch pour modifier précisément des valeurs spécifiques à l’intérieur d’un secret.

        Dans KV v1, cela ne fonctionne pas à cause de l’absence de métadonnées :


        $ vault kv patch kv/app/db user=dbadmin
        KV engine mount must be version 2 for patch support
        $

        Dans KV v2, en revanche, cela fonctionne :


        $ vault kv patch kvv2/app/db user=dbadmin
        == Secret Path ==
        kvv2/data/app/db
        
        ======= Metadata =======
        Key                Value
        ---                -----
        created_time       2025-07-01T11:07:50.365256138Z
        custom_metadata    <nil>
        deletion_time      n/a
        destroyed          false
        version            3
        $ 

        Résultat : seule la clé user est mise à jour, le reste du secret reste inchangé.

        rollback : Revenir en toute sécurité à une version antérieure

        Un secret enregistré par erreur ? Vous avez utilisé vault kv put par inadvertance ? Aucun problème avec KV v2. Si vous avez écrasé des données accidentellement, KV v2 vous permet de revenir à une version antérieure grâce à la commande rollback :


        $ vault kv get kvv2/app/db
        == Secret Path ==
        kvv2/data/app/db
        
        ======= Metadata =======
        Key                Value
        ---                -----
        created_time       2025-07-01T11:07:50.365256138Z
        custom_metadata    <nil>
        deletion_time      n/a
        destroyed          false
        version            3
        
        ==== Data ====
        Key     Value
        ---     -----
        api     myapisecret
        pass    123
        user    dbadmin
        $
        $ vault kv rollback -version=2 kvv2/app/db
        Key                Value
        ---                -----
        created_time       2025-07-01T11:10:44.341592593Z
        custom_metadata    <nil>
        deletion_time      n/a
        destroyed          false
        version            4
        $ 

        Cela crée une nouvelle version contenant les données de la version spécifiée. Dans notre exemple :

        • La version 2 contient les données d’origine
        • La version 3 était la tentative de mise à jour erronée
        • La version 4 est le résultat du rollback

        Astuce pro : Le système ne revient donc pas au moment de la création de la version 2, mais crée une nouvelle version avec les données de la version 2. L’historique reste donc intact.

        Suppression des données : delete vs. destroy

        Il est impératif de retenir que la commande delete agit différemment dans KV v1 et v2.

        KV v1 : Suppression définitive (hard delete)

        Avec le Secrets Engine KV v1, la commande delete supprime les données de manière irréversible :


        $ vault kv delete kv/app/db
        Success! Data deleted (if it existed) at: kv/app/db
        $ 
        $ vault kv get kv/app/db
        No value found at kv/app/db
        $ 

        Les données sont donc supprimées sans possibilité de retour. Une restauration ne peut se faire qu’en réinjectant un snapshot Vault.

        KV v2 : Suppression logique (soft delete)

        Avec KV v2, une suppression via delete est seulement logique :


        $ vault kv delete kvv2/app/db
        Success! Data deleted (if it existed) at: kvv2/data/app/db
        $
        $ vault kv get kvv2/app/db
        == Secret Path ==
        kvv2/data/app/db
        ======= Metadata =======
        Key Value
        --- -----
        created_time 2025-07-01T11:10:44.341592593Z
        custom_metadata <nil>
        deletion_time 2025-07-01T11:13:33.705332433Z
        destroyed false
        version 4
        $

        Les données ne sont plus visibles, mais elles existent toujours dans le système. Les métadonnées, en revanche, sont toujours présentes - notez ici la nouvelle valeur du champ deletion_time, qui auparavant était n/a.

        Les secrets supprimés logiquement peuvent être restaurés avec undelete ou définitivement supprimés avec destroy.

        undelete : Restaurer des versions supprimées

        Si une suppression a été effectuée par erreur :


        $ vault kv undelete -versions=4 kvv2/app/db
        Success! Data written to: kvv2/undelete/app/db
        $ 
        $ vault kv get kvv2/app/db
        == Secret Path ==
        kvv2/data/app/db
        
        ======= Metadata =======
        Key                Value
        ---                -----
        created_time       2025-07-01T11:10:44.341592593Z
        custom_metadata    <nil>
        deletion_time      n/a
        destroyed          false
        version            4
        
        ==== Data ====
        Key     Value
        ---     -----
        api     myapisecret
        pass    123
        user    admin
        $ 

        Les données sont de nouveau accessibles. À condition qu’aucun destroy n’ait été exécuté entre-temps.

        destroy : Suppression définitive de versions spécifiques

        Important : destroy est irréversible - même undelete et rollback ne fonctionneront plus. À utiliser uniquement si vous êtes sûr, et ne jamais le confondre avec delete !

        Après exécution, aucune restauration n’est possible :


        $ vault kv destroy -versions=2 kvv2/app/db
        Success! Data written to: kvv2/destroy/app/db
        $ 

        Vous pouvez aussi supprimer plusieurs versions en une seule commande :


        $ vault kv destroy -versions=1,3,4 kvv2/app/db
        Success! Data written to: kvv2/destroy/app/db
        $ 
        

        Après un destroy, le champ destroyed affiche la valeur true :


        $ vault kv get kvv2/app/db
        == Secret Path ==
        kvv2/data/app/db
        
        ======= Metadata =======
        Key                Value
        ---                -----
        created_time       2025-07-01T11:10:44.341592593Z
        custom_metadata    <nil>
        deletion_time      n/a
        destroyed          true
        version            4
        
        $ 

        Ce champ est principalement destiné aux audits. Un rollback ou undelete est alors exclu, et cela constitue une preuve qu’un destroy a bien été effectué.

        Conseils pratiques pour votre quotidien et votre stratégie KV

        1. Utiliser le contrôle de version

        Vérifiez régulièrement quelle version de KV vous utilisez :


        $ vault secrets list --detailed | grep kv
        kv/           kv           kv_11a18e23           system         system     false             replicated     false        false                      map[]             n/a                                                        4a479e06-6b44-e721-bbff-5ab3df0b7134    n/a        v0.21.0+builtin          n/a               supported
        kvv2/         kv           kv_be4ef9a0           system         system     false             replicated     false        false                      map[version:2]    n/a                                                        390c2b5f-45cd-6774-ae17-3d643d951401    n/a        v0.21.0+builtin          n/a               supported
        $ 
        

        Cherchez version:2 dans la colonne Options (l’avant-dernière colonne).

        2. Utiliser des chemins structurés

        Établissez une convention de nommage cohérente pour les chemins dans votre Secret Engine, par exemple :


        apps/
          └── payment-service/
              ├── prod/
              │   ├── db-credentials
              │   └── api-keys
              └── dev/
                  ├── db-credentials
                  └── api-keys

        3. patch au lieu de put

        Pour les mises à jour de valeurs individuelles, utilisez toujours patch au lieu de put, afin d’éviter toute perte de données.

        4. Sortie JSON pour les workflows automatisés

        Dans les scripts, utilisez systématiquement :


        vault kv get -format=json kv/app/db | jq -r '.data.password'

        5. Définir une stratégie de rollback

        Documentez les versions importantes et préparez des procédures de rollback. Par exemple :


        # Sauvegarder la version actuelle
        $ CURRENT_VERSION=$(vault kv get -format=json kvv2/app/db | jq -r '.data.metadata.version')
        $ echo $CURRENT_VERSION
        
        # En cas de problème : rollback
        $ vault kv rollback --version=$((CURRENT_VERSION-1)) kvv2/app/db

        Éviter les erreurs courantes

        1. L’erreur "write is not merge"

        Le problème le plus fréquent : écrasement involontaire de données avec put au lieu de patch.

        2. Confusion des chemins dans KV v2

        Gardez à l’esprit :

        • Différences de chemins dues à la casse dans KV v2
        • KV v2 insère automatiquement /data/ dans le chemin interne. La CLI gère cela en arrière-plan, mais pour les appels API directs, vous devez en tenir compte.

        3. Confusion entre delete et destroy

        • delete = suppression logique (restaurable) avec KV v2, suppression définitive avec KV v1
        • destroy = suppression définitive (irrécupérable) avec KV v2

        4. Pas de remise à zéro des numéros de version après un delete

        Les numéros de version dans KV v2 sont incrémentaux et ne sont jamais réinitialisés, même après un delete.

        Conclusion

        Le Secrets Engine Key/Value est facile à expliquer, mais son utilisation pratique regorge de subtilités. Le Secrets Engine est facile à expliquer, mais son utilisation pratique regorge de subtilités. Une compréhension solide du versionnement, des commandes et de leurs effets secondaires est essentielle pour garantir un fonctionnement stable et sécurisé.

        Celui qui utilise put avec discernement, patch pour les modifications ciblées, et qui maîtrise rollback en cas de problème, a une bonne maîtrise de l’outil KV Engine. Et celui qui évite destroy tant que ce n’est pas strictement nécessaire s’épargne bien des ennuis et conserve une voie de retour en cas d’erreur.

        À retenir dans la pratique : dans KV v2, presque tout est récupérable - sauf après un destroy.

        Profitez de cette sécurité, mais concevez malgré tout vos processus avec prévoyance.