Un secret Kubernetes stocké nativement dans etcd n’est pas chiffré. Il est simplement encodé en base64, ce qui revient à le cacher derrière un rideau transparent. Quiconque a accès à l’API server ou à une sauvegarde etcd peut le lire en clair en quelques secondes. C’est exactement pour combler cette faille que des milliers d’équipes déploient HashiCorp Vault devant leurs clusters de production. Depuis le rachat de HashiCorp par IBM et le passage à la version 2.0 en avril 2026, l’outil a changé de visage : nouveau modèle de support, fédération d’identité sans identifiants statiques, et une cadence de correctifs de sécurité plus soutenue. Ce tutoriel vous montre comment installer Vault 2.1.1 sur un cluster Kubernetes, connecter l’authentification native du cluster, injecter des secrets dans vos pods et générer des identifiants de base de données qui expirent automatiquement. Treize étapes, environ 90 minutes, et un projet complet à la fin pour vérifier que tout fonctionne. L’exercice vise en priorité les équipes plateforme qui gèrent déjà un cluster de cloud computing en production en Europe et qui doivent démontrer, face à un auditeur ou à un client, que les mots de passe de base de données ne dorment pas en clair quelque part dans un manifeste YAML.

Pourquoi les Secrets Kubernetes Natifs Ne Suffisent Pas

Le mécanisme Secret de Kubernetes a été pensé pour découpler la configuration sensible du code, pas pour protéger cette configuration contre un attaquant qui a déjà un pied dans le cluster. Par défaut, les objets Secret sont stockés dans etcd sans chiffrement au repos, sauf si l’administrateur active explicitement un Encryption Provider. Même avec ce chiffrement activé, toute personne disposant du droit RBAC get sur les secrets d’un namespace peut les lire intégralement, sans granularité plus fine, sans rotation automatique et sans piste d’audit détaillée sur qui a consulté quoi et quand.

Notre tutoriel sur les Secrets Kubernetes natifs détaille la configuration de base à connaître avant d’aller plus loin. Vault résout trois problèmes que Kubernetes ne traite pas nativement. D’abord, il génère des identifiants dynamiques : au lieu d’un mot de passe PostgreSQL fixe partagé par toute l’équipe, chaque pod reçoit un identifiant unique avec une durée de vie limitée, révoqué automatiquement à son expiration. Ensuite, il centralise la politique d’accès avec des règles granulaires par chemin, par méthode HTTP et par identité. Enfin, il journalise chaque lecture de secret dans un log d’audit exploitable, ce qui devient indispensable pour répondre aux exigences du Cyber Resilience Act ou de NIS2 en matière de traçabilité.

Vault 2.0 : le Tournant Post-IBM pour la Gestion des Secrets

Vault 2.0, sorti le 13 avril 2026, marque le premier changement de version majeure du produit depuis le lancement de la version 1.0 en 2018. HashiCorp, racheté par IBM, a basculé Vault sur le modèle de support IBM Support Cycle-2, qui garantit au minimum deux ans de support standard par version majeure. La nouveauté la plus structurante reste la fédération d’identité de charge de travail (Workload Identity Federation), qui permet à Vault de s’authentifier auprès d’AWS, Azure ou GCP sans identifiants statiques de longue durée, un point que ce tutoriel exploite plus loin pour durcir la configuration en production.

La branche 2.1, elle, a fait sortir de bêta le support natif des workflows agentiques le 1er septembre 2026 avec la version 2.1.0, suivie le 16 septembre 2026 par un correctif 2.1.1 qui referme plusieurs bugs d’interface et une dépendance vulnérable (dompurify). Un peu plus tôt dans le cycle, Vault a aussi corrigé la CVE-2026-39829 en limitant la taille des clés RSA du moteur SSH à 8192 bits. C’est la version que ce guide installe : Vault 2.1.1, la plus récente disponible au moment de la rédaction.

Le support des workflows agentiques mérite un mot d’explication pour une audience sécurité. Il ne s’agit pas d’exposer Vault directement à un agent IA sans contrôle, mais d’un registre dédié qui permet de délivrer des jetons à portée limitée et de courte durée à des identités automatisées, avec des politiques de type “ceiling policy” qui plafonnent les droits qu’un agent peut jamais obtenir, quelle que soit la politique qui lui est attribuée par erreur. Ce garde-fou répond directement à une inquiétude montante : des agents IA qui accèdent à des secrets d’infrastructure sans limite claire de ce qu’ils peuvent lire ou modifier.

HashiCorp Vault vs Secrets Kubernetes Natifs : le Comparatif

Avant de se lancer dans l’installation, il vaut mieux comprendre précisément ce que Vault apporte par rapport à l’objet Secret natif de Kubernetes. Le tableau suivant résume les écarts fonctionnels observés en usage courant.

CritèreSecrets Kubernetes natifsHashiCorp Vault
Chiffrement au reposDésactivé par défaut, base64 uniquementChiffré nativement (AES-256-GCM via le backend de stockage)
Identifiants dynamiquesNon, valeurs statiquesOui, génération à la demande avec TTL
Rotation automatiqueManuelle uniquementAutomatique selon la politique définie
Journal d’audit détailléLimité aux événements API KubernetesLog d’audit dédié par requête
Granularité des politiquesRBAC par namespace/verbePolitiques par chemin, méthode et identité
Multi-cloud / multi-clusterNon, propre à chaque clusterOui, instance centralisée partagée
Coût opérationnelFaible, aucun composant à gérerPlus élevé, nécessite exploitation dédiée

Ce comparatif ne veut pas dire qu’il faut abandonner les Secrets natifs. Vault s’intègre justement avec eux via le Vault Secrets Operator, qui synchronise les valeurs stockées dans Vault vers de vrais objets Secret Kubernetes, combinant la sécurité de Vault et la simplicité d’usage attendue par les développeurs.

Dans la pratique, l’adoption se fait rarement d’un seul coup sur l’ensemble d’un cluster. La plupart des équipes commencent par migrer les secrets les plus sensibles, typiquement les identifiants de base de données et les clés d’API tierces, avant d’étendre progressivement la couverture aux configurations moins critiques. Cette approche incrémentale limite le risque d’interruption de service et laisse le temps à l’équipe plateforme de roder ses procédures de sauvegarde et de restauration avant que Vault ne devienne un point de passage obligé pour toute la production.

Architecture : Comment Vault S’Intègre à un Cluster Kubernetes

Vault tourne comme n’importe quel StatefulSet dans le cluster, généralement en mode haute disponibilité avec trois ou cinq répliques qui partagent un même état via le protocole Raft intégré (Integrated Storage). Un seul pod détient le rôle de leader à un instant donné, les autres suivent en tant que standby et prennent le relais automatiquement en cas de panne. Les applications ne parlent jamais directement à etcd ou à un backend de stockage tiers : elles interrogent l’API HTTP de Vault, qui vérifie l’identité de l’appelant via la méthode d’authentification Kubernetes avant de renvoyer un secret.

Toutes les données écrites dans Vault, y compris dans le stockage Raft local à chaque pod, restent chiffrées au repos avec une clé de chiffrement qui n’existe jamais en clair sur disque. Cette clé de chiffrement est elle-même protégée par une clé maîtresse, reconstituée uniquement au démarrage grâce au partage de secret de Shamir : la clé maîtresse est fractionnée en plusieurs parts, et un quorum de ces parts (trois sur cinq dans ce tutoriel) est nécessaire pour la reconstituer. Tant que ce quorum n’est pas atteint, Vault reste scellé et refuse de servir la moindre requête, même à un administrateur disposant du root token. C’est cette conception qui empêche un attaquant ayant simplement copié le disque d’un pod Vault de récupérer les secrets sans posséder également les clés de descellement.

Trois mécanismes permettent de faire transiter un secret de Vault vers un pod applicatif. Le Vault Agent Injector ajoute un conteneur sidecar chargé de récupérer et de rafraîchir les secrets sur un volume partagé. Le CSI Provider monte les secrets directement via un volume CSI éphémère, sans sidecar supplémentaire. Le Vault Secrets Operator (VSO) synchronise quant à lui les secrets Vault vers de véritables objets Secret Kubernetes, surveillés en continu. Ce tutoriel couvre l’Agent Injector en détail, puis le VSO pour les cas où l’application ne peut pas être modifiée pour lire un fichier monté.

Le choix entre ces trois mécanismes dépend surtout de la contrainte opérationnelle dominante. Une équipe qui gère des centaines de microservices et surveille de près la densité de pods par nœud évitera d’empiler un sidecar sur chaque déploiement, et préférera le CSI Provider ou le VSO. Une équipe qui migre progressivement une flotte d’applications historiques, incapables de lire un secret Vault sans passer par un objet Secret Kubernetes classique, s’appuiera d’abord sur le VSO avant d’envisager une réécriture plus profonde. Il n’existe pas de méthode universellement supérieure : chaque projet de migration vers Vault commence par un inventaire des contraintes techniques réelles, pas par un choix théorique.

Prérequis et Versions Nécessaires

Voici l’environnement exact utilisé pour ce tutoriel. Les commandes ont été testées avec ces versions précises : des versions plus anciennes de Helm ou de Kubernetes peuvent provoquer des erreurs de compatibilité de CRD.

ComposantVersion utiliséeRôle
Kubernetes1.30 ou supérieurCluster cible (EKS, GKE, AKS ou local)
Helm3.15 ou supérieurDéploiement des charts Vault et VSO
kubectlAlignée sur la version du clusterAdministration du cluster
vault-helm (chart)0.34.1Déploiement du serveur Vault
Vault (image du serveur)2.1.1Moteur de secrets et de politiques
vault-secrets-operator (chart)1.6.0Synchronisation Vault vers Secrets Kubernetes
CLI vault2.1.1 (alignée sur le serveur)Administration en ligne de commande

Prévoyez aussi un cluster avec au moins trois nœuds si vous testez le mode haute disponibilité, et des droits cluster-admin le temps de l’installation (vous pourrez restreindre ces droits ensuite). Un espace disque persistant (StorageClass avec provisioning dynamique) est requis pour le stockage Raft de Vault.

Ce tutoriel fonctionne aussi bien sur un cluster managé (EKS, GKE, AKS) que sur un cluster local monté avec kind ou minikube, à condition que le provisioning de volumes persistants soit configuré. Sur un cluster local, réduisez le nombre de répliques Vault à une seule instance pour économiser des ressources, en sachant que ce choix supprime la tolérance de panne offerte par le mode haute disponibilité et ne convient donc qu’à un usage de démonstration.

Étapes 1 à 3 : Installer Vault sur Kubernetes avec Helm

Étape 1 : Créer le namespace et ajouter le dépôt Helm

Isolez Vault dans son propre namespace pour appliquer des politiques réseau strictes plus tard. Si vous découvrez Helm pour la première fois, notre tutoriel Helm sur Kubernetes couvre les bases du gestionnaire de paquets utilisé ici.

kubectl create namespace vault
helm repo add hashicorp https://helm.releases.hashicorp.com
helm repo update
helm search repo hashicorp/vault --versions | head -5

Étape 2 : Rédiger le fichier values.yaml pour le mode HA

Le mode haute disponibilité avec stockage Raft intégré élimine la dépendance à un backend externe comme Consul.

server:
  image:
    tag: "2.1.1"
  ha:
    enabled: true
    replicas: 3
    raft:
      enabled: true
      setNodeId: true
  auditStorage:
    enabled: true
    size: 5Gi
  resources:
    requests:
      memory: 256Mi
      cpu: 250m
    limits:
      memory: 512Mi
      cpu: 500m

injector:
  enabled: true
  image:
    tag: "1.5.1"

ui:
  enabled: true

Étape 3 : Déployer Vault avec Helm

helm install vault hashicorp/vault \
  --namespace vault \
  --version 0.34.1 \
  -f values.yaml

kubectl get pods -n vault -w

Les pods vault-0, vault-1 et vault-2 apparaissent avec le statut Running mais 0/1 prêt : c’est normal, Vault démarre scellé (sealed) tant qu’il n’a pas été initialisé.

Étapes 4 à 6 : Initialiser, Désceller et Configurer Vault

Étape 4 : Initialiser Vault et sécuriser les clés de descellement

kubectl exec -n vault vault-0 -- vault operator init \
  -key-shares=5 \
  -key-threshold=3 \
  -format=json > vault-init.json

cat vault-init.json | jq -r '.unseal_keys_b64[]'
cat vault-init.json | jq -r '.root_token'

Cette commande génère cinq clés de descellement, dont trois suffisent pour reconstituer la clé maîtresse. Ne stockez jamais vault-init.json dans un dépôt Git : chiffrez-le immédiatement avec une solution comme GPG ou un coffre-fort externe, puis supprimez le fichier local.

Étape 5 : Désceller chaque pod Vault

for pod in vault-0 vault-1 vault-2; do
  kubectl exec -n vault $pod -- vault operator unseal 
  kubectl exec -n vault $pod -- vault operator unseal 
  kubectl exec -n vault $pod -- vault operator unseal 
done

kubectl get pods -n vault

Sortie attendue une fois tous les pods déscellés :

NAME       READY   STATUS    RESTARTS   AGE
vault-0    1/1     Running   0          4m
vault-1    1/1     Running   0          4m
vault-2    1/1     Running   0          4m

Étape 6 : Se connecter à Vault et activer le moteur KV v2

kubectl exec -it -n vault vault-0 -- /bin/sh
export VAULT_TOKEN=
vault login $VAULT_TOKEN

vault secrets enable -path=secret kv-v2
vault kv put secret/demo-app/config username="app_user" password="ChangeMe123!"
vault kv get secret/demo-app/config

Étapes 7 à 9 : Authentification Kubernetes et Politiques d’Accès

Étape 7 : Activer la méthode d’authentification Kubernetes

vault auth enable kubernetes

vault write auth/kubernetes/config \
  kubernetes_host="https://kubernetes.default.svc:443"

Vault utilise le compte de service du pod pour valider les jetons de projection (Bound Service Account Token Volume), la méthode recommandée depuis l’abandon des tokens statiques de compte de service dans les versions récentes de Kubernetes. Concrètement, quand un pod tente de s’authentifier, Vault transmet le jeton présenté à l’API TokenReview du cluster, qui confirme ou infirme l’identité du ServiceAccount appelant. Vault ne fait donc jamais confiance à un jeton sur simple présentation : il revalide systématiquement chaque authentification auprès du serveur d’API Kubernetes, ce qui empêche un jeton volé et rejoué en dehors du cluster de fonctionner.

Étape 8 : Créer une politique d’accès en moindre privilège

cat <

Cette politique n'accorde que la lecture, et uniquement sous le chemin secret/data/demo-app/*. Une erreur fréquente à ce stade consiste à écrire secret/* pour aller plus vite : cela expose tous les secrets de tous les projets à cette seule application.

Étape 9 : Lier un ServiceAccount, un namespace et une politique

vault write auth/kubernetes/role/demo-app \
  bound_service_account_names=demo-app-sa \
  bound_service_account_namespaces=default \
  policies=demo-app-policy \
  ttl=1h

Le rôle demo-app n'accepte des jetons que du ServiceAccount demo-app-sa dans le namespace default, avec un jeton Vault dont la durée de vie n'excède pas une heure.

Étapes 10 à 11 : Injecter des Secrets avec le Vault Agent Injector

Étape 10 : Créer le ServiceAccount et annoter le déploiement

kubectl create serviceaccount demo-app-sa

cat < deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: demo-app
  template:
    metadata:
      labels:
        app: demo-app
      annotations:
        vault.hashicorp.com/agent-inject: "true"
        vault.hashicorp.com/role: "demo-app"
        vault.hashicorp.com/agent-inject-secret-config.txt: "secret/data/demo-app/config"
    spec:
      serviceAccountName: demo-app-sa
      containers:
        - name: demo-app
          image: node:20-alpine
          command: ["sleep", "infinity"]
EOF

kubectl apply -f deployment.yaml

Étape 11 : Vérifier que le secret est bien injecté

kubectl get pods -l app=demo-app
POD=$(kubectl get pod -l app=demo-app -o jsonpath="{.items[0].metadata.name}")
kubectl exec $POD -c demo-app -- cat /vault/secrets/config.txt

Sortie attendue :

data: map[password:ChangeMe123! username:app_user]
metadata: map[created_time:2026-09-20T10:14:02.913245Z ...]

Le pod affiche désormais deux conteneurs (2/2 Ready) : votre application et le sidecar vault-agent, qui rafraîchit automatiquement le fichier config.txt tant que le jeton reste valide.

Étapes 12 à 13 : Vault Secrets Operator et Identifiants Dynamiques PostgreSQL

Étape 12 : Déployer le Vault Secrets Operator

Le VSO synchronise les secrets Vault vers de véritables objets Secret Kubernetes, ce qui évite de modifier le code applicatif pour lire un fichier monté par un sidecar. Consultez le tutoriel officiel du Vault Secrets Operator pour le détail des CRD disponibles.

helm install vault-secrets-operator hashicorp/vault-secrets-operator \
  --namespace vault-secrets-operator-system \
  --create-namespace \
  --version 1.6.0

kubectl get pods -n vault-secrets-operator-system

Étape 13 : Activer le moteur de secrets dynamiques PostgreSQL

vault secrets enable database

vault write database/config/demo-postgres \
  plugin_name=postgresql-database-plugin \
  allowed_roles="demo-app-role" \
  connection_url="postgresql://{{username}}:{{password}}@postgres.default.svc:5432/appdb?sslmode=disable" \
  username="vault_admin" \
  password="AdminPasswordFromSecretsManager"

vault write database/roles/demo-app-role \
  db_name=demo-postgres \
  creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
  default_ttl="1h" \
  max_ttl="24h"

Chaque lecture de database/creds/demo-app-role crée un nouvel utilisateur PostgreSQL, avec un mot de passe unique et une expiration automatique après une heure. Vault révoque lui-même le compte à l'échéance, sans intervention manuelle.

Ce cycle de vie change fondamentalement la surface d'attaque d'une base de données exposée en interne. Avec un mot de passe statique, un identifiant qui fuit dans un log applicatif ou un fichier de configuration oublié reste valide indéfiniment, jusqu'à ce que quelqu'un pense à le changer. Avec des identifiants dynamiques à durée de vie d'une heure, la fenêtre d'exploitation d'une fuite se referme automatiquement, sans dépendre de la vigilance d'un humain. C'est probablement l'argument le plus convaincant pour justifier l'effort d'exploitation supplémentaire que représente Vault face à un simple objet Secret Kubernetes.

Projet Complet : une API Node.js Alimentée par des Identifiants Vault

Voici un exemple fonctionnel complet qui combine tout ce qui précède : une API Node.js qui lit ses identifiants PostgreSQL dynamiques injectés par le Vault Agent, sans jamais stocker de mot de passe en dur.

// server.js
const fs = require("fs");
const express = require("express");
const { Client } = require("pg");

const app = express();

function readVaultSecret() {
  const raw = fs.readFileSync("/vault/secrets/db-creds.txt", "utf-8");
  const lines = Object.fromEntries(
    raw.split("\n").filter(Boolean).map((l) => l.split(": "))
  );
  return lines;
}

app.get("/health", async (req, res) => {
  const creds = readVaultSecret();
  const client = new Client({
    host: "postgres.default.svc",
    user: creds.username,
    password: creds.password,
    database: "appdb",
  });
  await client.connect();
  const result = await client.query("SELECT 1 AS ok");
  await client.end();
  res.json({ status: "ok", db: result.rows[0] });
});

app.listen(3000, () => console.log("API en écoute sur le port 3000"));
# Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package.json server.js ./
RUN npm install express pg
CMD ["node", "server.js"]
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-api
spec:
  replicas: 2
  selector:
    matchLabels:
      app: demo-api
  template:
    metadata:
      labels:
        app: demo-api
      annotations:
        vault.hashicorp.com/agent-inject: "true"
        vault.hashicorp.com/role: "demo-app"
        vault.hashicorp.com/agent-inject-secret-db-creds.txt: "database/creds/demo-app-role"
        vault.hashicorp.com/agent-inject-template-db-creds.txt: |
          {{- with secret "database/creds/demo-app-role" -}}
          username: {{ .Data.username }}
          password: {{ .Data.password }}
          {{- end -}}
    spec:
      serviceAccountName: demo-app-sa
      containers:
        - name: demo-api
          image: registry.example.com/demo-api:1.0.0
          ports:
            - containerPort: 3000

Déployez avec kubectl apply -f api-deployment.yaml, puis testez avec kubectl port-forward svc/demo-api 3000:3000 et curl localhost:3000/health. La réponse {"status":"ok","db":{"ok":1}} confirme que l'API a récupéré des identifiants PostgreSQL valides directement depuis Vault, sans jamais les avoir codés en dur.

Ce projet reste volontairement minimal pour rester lisible, mais la même structure s'applique à une API en production. Il suffit de remplacer sleep infinity par une vraie image applicative, de pointer connection_url vers la base réelle et d'ajuster les creation_statements aux privilèges strictement nécessaires à chaque service. Le point à retenir : le code applicatif ne connaît jamais le mot de passe à l'avance, il le lit à chaque démarrage depuis un fichier local généré par le sidecar Vault, ce qui rend le déploiement portable d'un environnement à l'autre sans changer une ligne de configuration sensible.

Agent Injector vs CSI Provider vs VSO : Quelle Méthode Choisir

Les trois méthodes d'intégration ne se valent pas selon le contexte. Ce tableau aide à trancher rapidement.

MéthodeAvantage principalLimiteCas d'usage idéal
Vault Agent InjectorRafraîchissement automatique du fichier de secretAjoute un conteneur sidecar par podApplications qui lisent des fichiers de config
CSI ProviderPas de sidecar, montage direct en volumeNe rafraîchit pas toujours en continu selon la configWorkloads sensibles à la consommation de ressources
Vault Secrets Operator (VSO)Compatible avec les objets Secret Kubernetes natifsLe secret existe aussi en clair dans etcd (chiffré si activé)Applications existantes non modifiables

En pratique, beaucoup d'équipes combinent les trois : le VSO pour les applications legacy qui attendent un Secret natif, l'Agent Injector pour les nouveaux services capables de lire un fichier, et le CSI Provider quand le nombre de sidecars devient un problème de densité de pods par nœud. Rien n'empêche de faire cohabiter les trois mécanismes sur un même cluster, à condition de documenter clairement quelle équipe utilise quelle méthode pour éviter qu'un nouvel arrivant ne réinvente une quatrième approche par méconnaissance des choix déjà faits.

Vault Face aux Alternatives : AWS Secrets Manager, Azure Key Vault et External Secrets Operator

Vault n'est pas la seule option pour sortir des Secrets Kubernetes natifs, et il vaut mieux le savoir avant de s'engager dans une migration de plusieurs semaines. AWS Secrets Manager et Azure Key Vault proposent tous deux une gestion centralisée des secrets avec rotation automatique, mais restreinte à l'écosystème de leur fournisseur cloud respectif. Une équipe déjà entièrement sur AWS, sans ambition multi-cloud, tire souvent plus vite parti d'AWS Secrets Manager que d'un déploiement Vault complet, simplement parce que l'intégration IAM est native et qu'il n'y a rien à exploiter soi-même. L'inverse est vrai pour Azure Key Vault sur un socle Azure homogène : notre tutoriel Azure Key Vault détaille cette alternative pas à pas.

Le projet External Secrets Operator (ESO) occupe une position différente : ce n'est pas un coffre-fort de secrets, mais un pont générique qui synchronise des secrets depuis Vault, AWS Secrets Manager, Azure Key Vault ou une dizaine d'autres backends vers de vrais objets Secret Kubernetes. ESO peut ainsi cohabiter avec Vault, exactement comme le VSO présenté plus haut, mais avec l'avantage de ne pas verrouiller l'équipe sur l'écosystème HashiCorp si un changement de fournisseur de secrets devient nécessaire plus tard.

SolutionPortéeIdentifiants dynamiquesMeilleur cas d'usage
HashiCorp VaultMulti-cloud, agnostiqueOui, très étendu (bases de données, cloud, PKI)Environnements hybrides ou multi-cloud
AWS Secrets ManagerÉcosystème AWS uniquementLimité, surtout via Lambda de rotationCharges de travail 100 % AWS
Azure Key VaultÉcosystème Azure uniquementLimité, intégré à Azure ADCharges de travail 100 % Azure
External Secrets OperatorPont universel vers d'autres backendsDépend du backend connectéSynchroniser plusieurs sources de secrets existantes

Le choix se résume rarement à une question purement technique. Une équipe soumise au Cyber Resilience Act ou à des exigences de souveraineté numérique européenne penchera plus facilement vers un déploiement Vault auto-hébergé, dont elle garde le contrôle total, plutôt que vers un service managé chez un hyperscaler américain.

Durcissement, Rotation et Bonnes Pratiques pour la Production

Une installation qui fonctionne en environnement de test n'est pas automatiquement prête pour la production. Voici les ajustements qui font la différence à l'échelle d'un cluster réel.

  • Activer l'audit logging dès le premier jour avec vault audit enable file file_path=/vault/logs/audit.log, faute de quoi les événements passés sont perdus définitivement et aucune investigation rétroactive ne sera possible après un incident.
  • Adopter la fédération d'identité de charge de travail (Workload Identity Federation) introduite avec Vault 2.0 pour authentifier Vault auprès d'AWS, Azure ou GCP sans clé d'accès statique stockée quelque part, ce qui supprime une catégorie entière de secrets à protéger.
  • Isoler Vault avec une NetworkPolicy qui n'autorise que le trafic entrant depuis les namespaces applicatifs légitimes sur le port 8200, plutôt que de laisser le service accessible depuis n'importe quel pod du cluster. Notre tutoriel Cilium Zero Trust détaille la mise en œuvre de ces politiques réseau.
  • Segmenter par namespace Vault (Vault Enterprise) ou par préfixe de chemin (Vault Community) pour qu'une équipe ne puisse jamais lire les secrets d'une autre équipe, même en cas d'erreur de configuration locale.
  • Automatiser la rotation des root tokens et révoquer le token racine initial une fois l'authentification Kubernetes opérationnelle : il ne doit plus jamais servir au quotidien, et sa moindre utilisation devrait déclencher une alerte.
  • Sauvegarder l'état Raft régulièrement avec vault operator raft snapshot save, testé sur un cluster de restauration séparé au moins une fois par trimestre pour vérifier que la sauvegarde est réellement exploitable, pas seulement présente sur disque.

Conseils Avancés : PKI, Transit et Multi-Tenancy

Une fois l'installation de base stabilisée, trois fonctionnalités de Vault méritent d'être explorées pour aller au-delà de la simple substitution des mots de passe statiques. Le moteur PKI transforme Vault en autorité de certification interne : il peut émettre des certificats TLS de courte durée pour le trafic est-ouest entre microservices, avec une révocation automatique à l'expiration plutôt qu'une liste de révocation à maintenir manuellement. C'est une alternative crédible à un maillage de service complet quand l'équipe n'a pas encore les moyens d'exploiter Istio ou Linkerd.

Le moteur Transit, lui, fait de Vault un service de chiffrement à la demande sans jamais exposer la clé de chiffrement à l'application appelante. Une API envoie une donnée en clair à l'endpoint transit/encrypt/ma-cle, reçoit un texte chiffré en retour, et ne détient jamais la clé elle-même. C'est le pattern recommandé pour chiffrer des données sensibles au niveau applicatif (numéros de carte, données de santé) avant de les écrire en base, indépendamment du chiffrement au repos déjà assuré par la base de données.

Enfin, sur les clusters partagés par plusieurs équipes, les namespaces Vault (fonctionnalité Enterprise) ou une convention stricte de préfixes de chemin (en version Community) permettent d'isoler complètement les secrets d'une équipe métier de ceux d'une autre, avec des administrateurs distincts par périmètre. Cette isolation évite qu'une erreur de politique dans un projet secondaire n'expose accidentellement les secrets d'une application critique. Vault ne remplace pas un durcissement plus large du cluster : consultez aussi notre guide de durcissement Kubernetes et containerd pour couvrir les couches en dessous du cluster.

Erreurs Courantes à Éviter

La plupart des incidents liés à Vault sur Kubernetes proviennent des mêmes six erreurs, observées régulièrement dans des configurations de production. Elles ont un point commun : chacune part d'un raccourci pris pendant la phase de test, jamais corrigé avant le passage en production.

  • Laisser Vault en mode développeur (vault server -dev) en production : ce mode stocke tout en mémoire, sans persistance ni chiffrement, et se réinitialise au moindre redémarrage. Il génère aussi un root token affiché en clair dans les logs de démarrage, ce qui en fait une porte grande ouverte si le mode dev survit au-delà d'un test local.
  • Écrire des politiques trop larges comme secret/* au lieu de restreindre chaque rôle à son propre préfixe applicatif. Une politique large transforme une compromission d'un seul service en fuite de tous les secrets du cluster.
  • Committer vault-init.json ou le root token dans un dépôt Git, même privé : ce fichier doit être chiffré et stocké hors du contrôle de version, idéalement dans un coffre-fort séparé du cluster qu'il protège.
  • Oublier de lier le rôle Kubernetes à un namespace précis, ce qui permet à n'importe quel ServiceAccount portant le même nom, dans n'importe quel namespace, de s'authentifier avec la même politique.
  • Fixer un TTL de token trop long sur les rôles applicatifs, ce qui annule l'intérêt des identifiants dynamiques à courte durée de vie et redonne à un jeton volé une fenêtre d'exploitation confortable.
  • Ne pas tester le processus de descellement après un redémarrage complet du cluster : sans clés accessibles rapidement, un incident de disponibilité peut durer des heures, le temps de retrouver qui détient quelle part de la clé maîtresse.

Dépannage : les Problèmes Fréquents et Leurs Solutions

Voici les incidents les plus souvent rencontrés lors du déploiement de Vault sur Kubernetes, avec la cause probable et la correction associée.

SymptômeCause probableSolution
Pod vault-0 reste à 0/1 ReadyVault est scellé après le démarrageExécuter vault operator unseal avec trois clés valides
Erreur "connection refused" sur le port 8200NetworkPolicy trop restrictive ou service mal cibléVérifier kubectl get svc -n vault et les règles réseau
"permission denied" à l'authentification KubernetesPolitique non liée au bon rôle ou ServiceAccount incorrectVérifier bound_service_account_names et bound_service_account_namespaces
Le fichier de secret injecté reste videAnnotation d'injection mal formée ou chemin de secret inexistantContrôler la syntaxe des annotations vault.hashicorp.com/agent-inject-secret-*
Le sidecar vault-agent est en CrashLoopBackOffImage du sidecar incompatible avec la version du serveur VaultAligner injector.image.tag sur une version supportée
VaultStaticSecret ne se synchronise jamaisCRD du VSO non installées ou opérateur non démarréVérifier kubectl get pods -n vault-secrets-operator-system
"no matching role" pendant l'authentificationLe rôle Kubernetes référencé dans les annotations n'existe pas côté VaultRecréer le rôle avec vault write auth/kubernetes/role/...
Le token Vault expire trop souventTTL trop court sur le rôle ou la politique d'authentificationAjuster ttl et max_ttl sur le rôle Kubernetes
Impossible de restaurer un snapshot RaftVersion de Vault différente entre la sauvegarde et le cluster cibleRestaurer sur une version identique ou supérieure compatible

Pour la majorité de ces cas, le réflexe le plus rentable reste de consulter les logs du serveur Vault (kubectl logs vault-0 -n vault) avant ceux du sidecar : Vault journalise systématiquement la raison exacte d'un refus d'authentification ou d'une politique insuffisante, alors que le sidecar se contente souvent d'un message générique de connexion échouée.

Questions Fréquentes

Faut-il remplacer complètement les Secrets Kubernetes par Vault ?
Non. Le Vault Secrets Operator permet de garder des objets Secret Kubernetes classiques en façade, tout en les alimentant depuis Vault. La migration peut se faire progressivement, application par application.

Vault fonctionne-t-il sans stockage externe comme Consul ?
Oui. Le stockage Raft intégré (Integrated Storage), utilisé dans ce tutoriel, élimine la dépendance à Consul depuis plusieurs versions majeures et simplifie fortement l'exploitation.

Quelle est la différence entre Vault Community et Vault Enterprise ?
La version Community couvre l'essentiel de ce tutoriel : moteur KV, secrets dynamiques, authentification Kubernetes, moteur PKI et moteur Transit. La version Enterprise ajoute la réplication multi-région, les namespaces isolés, la haute disponibilité active-active entre plusieurs datacenters et certaines fonctionnalités de fédération d'identité avancées. Pour un premier déploiement sur un seul cluster, la version Community suffit largement.

Comment savoir si mon cluster utilise déjà le chiffrement au repos pour etcd ?
Vérifiez la configuration EncryptionConfiguration de l'API server. Sans cette configuration, les objets Secret Kubernetes sont stockés en clair (base64) dans etcd, quel que soit le fournisseur cloud utilisé.

Peut-on utiliser Vault pour gérer des certificats TLS en plus des mots de passe ?
Oui, via le moteur PKI de Vault, qui peut émettre des certificats à courte durée de vie et servir d'autorité de certification interne pour le cluster.

Que se passe-t-il si tous les pods Vault redémarrent en même temps ?
Ils redémarrent scellés. Sans processus de descellement automatisé (via un mécanisme d'auto-unseal cloud comme AWS KMS ou Azure Key Vault), un opérateur humain doit fournir manuellement les clés de descellement, ce qui peut interrompre l'accès aux secrets pendant plusieurs minutes selon la disponibilité de cet opérateur. C'est pourquoi la plupart des déploiements de production configurent l'auto-unseal dès l'installation initiale plutôt que d'attendre un premier incident pour s'en préoccuper.

La CVE-2026-39829 affecte-t-elle cette installation ?
Non, elle est corrigée dans Vault 2.1.1, la version installée dans ce tutoriel. Elle concernait une limite de taille de clé RSA insuffisante dans le moteur de secrets SSH.

Vault ralentit-il les applications qui lisent des secrets à chaque requête ?
Les identifiants dynamiques sont mis en cache localement par le Vault Agent jusqu'à leur expiration. Seule la première lecture, ou le renouvellement, entraîne un appel réseau vers Vault. Pour aller plus loin sur les bonnes pratiques générales de gestion de clés, voir les recommandations du NIST SP 800-57 et les bonnes pratiques officielles Kubernetes sur les secrets.