HashiCorp Vault résout l’un des problèmes les plus persistants de l’infrastructure moderne : où stocker et distribuer les secrets en toute sécurité ? Les credentials codés en dur dans les fichiers de configuration, les variables d’environnement commitées dans git et les feuilles de calcul de mots de passe partagés sont responsables d’une part disproportionnée des violations de données. HashiCorp Vault fournit une API unifiée pour la gestion des secrets, la génération de credentials dynamiques, le chiffrement en tant que service et le contrôle d’accès granulaire — le tout avec une piste d’audit complète. Dans ce guide, vous apprendrez comment Vault fonctionne, comment le déployer et comment l’intégrer à Kubernetes et Terraform dans un vrai workflow de production.
Prérequis
- Hôte Linux ou macOS (ou un cluster Kubernetes pour le chemin cloud-native)
- Familiarité de base avec la ligne de commande et la configuration YAML
- Docker (optionnel, pour un serveur de développement rapide)
- Un cluster Kubernetes avec accès
kubectl(pour la section intégration Kubernetes) - Terraform 1.x installé (pour la section fournisseur Terraform)
- La compréhension des certificats TLS est utile mais non requise
Comment fonctionne HashiCorp Vault
Dans son essence, Vault est un processus qui expose une API HTTP. Tout — lire des secrets, s’authentifier, gérer les policies — passe par cette API. Vault stocke ses données dans un backend de stockage (Integrated Storage basé sur Raft est la valeur par défaut recommandée) et chiffre tout au repos à l’aide d’une clé maîtresse qui ne quitte jamais la mémoire.
Au démarrage, Vault est scellé : il détient les données chiffrées mais ne peut pas les déchiffrer car la clé maîtresse est répartie entre plusieurs parts de clés de descellement via le partage de secret de Shamir. Vault devient opérationnel uniquement après que le quorum minimum de parts de clés est fourni. Cette conception signifie que même si quelqu’un vole le backend de stockage, il ne peut lire aucun secret sans les clés de descellement.
Concepts clés
- Moteurs de secrets — plugins qui génèrent ou stockent des secrets. Le moteur KV stocke des paires clé/valeur statiques. Le moteur Database génère des credentials dynamiques. Le moteur PKI émet des certificats X.509.
- Méthodes d’authentification — comment les clients prouvent leur identité à Vault. Les options incluent AppRole (pour les machines), les comptes de service Kubernetes, AWS IAM, LDAP, GitHub et OIDC.
- Policies — fichiers HCL qui accordent un accès en lecture, écriture ou administration à des chemins spécifiques dans Vault.
- Baux et TTL — chaque secret a un bail ; à l’expiration du bail, Vault le révoque. Les applications doivent renouveler ou re-demander les credentials avant l’expiration.
- Dispositifs d’audit — Vault peut écrire chaque requête et réponse dans un fichier journal, syslog ou socket. L’audit est infalsifiable et vérifié cryptographiquement.
Installation et Initialisation de Vault
Pour un déploiement en qualité de production, HashiCorp recommande d’exécuter Vault en mode Haute Disponibilité (HA) avec Integrated Storage sur trois ou cinq nœuds. À des fins d’apprentissage, un serveur de développement unique est suffisant.
Serveur de développement rapide (non destiné à la production) :
vault server -dev
Cela démarre un Vault en mémoire, le descelle automatiquement et affiche un token root. Les données sont perdues à l’arrêt du processus.
Nœud unique de production avec Integrated Storage :
Créez /etc/vault.d/vault.hcl :
ui = true
storage "raft" {
path = "/opt/vault/data"
node_id = "vault-node-1"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/opt/vault/tls/vault.crt"
tls_key_file = "/opt/vault/tls/vault.key"
}
api_addr = "https://vault.example.com:8200"
cluster_addr = "https://vault.example.com:8201"
Démarrez le service, puis initialisez-le :
vault operator init -key-shares=5 -key-threshold=3
Cela génère cinq clés de descellement et un token root. Stockez-les immédiatement dans des emplacements sécurisés séparés — perdre suffisamment de parts de clés signifie perdre définitivement l’accès à toutes vos données. Descèlez avec trois des cinq clés :
vault operator unseal <clé-1>
vault operator unseal <clé-2>
vault operator unseal <clé-3>
Secrets Dynamiques : L’Avantage Fondamental
Les credentials statiques (un mot de passe de base de données qui ne change jamais) sont une responsabilité. S’ils fuient, la fenêtre d’exposition est indéfinie. Les secrets dynamiques ferment cette fenêtre.
Activez le moteur de secrets de base de données et configurez-le pour PostgreSQL :
vault secrets enable database
vault write database/config/myapp-db \
plugin_name=postgresql-database-plugin \
allowed_roles="myapp-role" \
connection_url="postgresql://{{username}}:{{password}}@db.example.com:5432/myapp" \
username="vault" \
password="vault-superuser-password"
vault write database/roles/myapp-role \
db_name=myapp-db \
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"
Désormais, toute application ou job CI possédant la bonne policy Vault peut exécuter :
vault read database/creds/myapp-role
Vault se connecte à PostgreSQL, crée un utilisateur nommé de manière unique et retourne des credentials qui expirent en une heure. À l’expiration du bail (ou lorsque l’application appelle vault lease revoke), Vault supprime l’utilisateur de la base de données. L’application ne détient jamais de mot de passe à longue durée de vie.
Moteur de Secrets PKI pour les Certificats Internes
La gestion manuelle des certificats TLS est sujette aux erreurs et rarement auditée. Le moteur de secrets PKI de Vault agit comme une Autorité de Certification interne, émettant des certificats à courte durée de vie à la demande.
vault secrets enable pki
vault secrets tune -max-lease-ttl=87600h pki
# Générer le CA racine (stocker le cert en externe, hors ligne si possible)
vault write -field=certificate pki/root/generate/internal \
common_name="example.com" \
ttl=87600h > CA_cert.crt
# Configurer les URLs CRL et d'émission
vault write pki/config/urls \
issuing_certificates="https://vault.example.com:8200/v1/pki/ca" \
crl_distribution_points="https://vault.example.com:8200/v1/pki/crl"
# Activer le CA intermédiaire (bonne pratique pour la production)
vault secrets enable -path=pki_int pki
vault write -format=json pki_int/intermediate/generate/internal \
common_name="example.com Intermediate Authority" | jq -r '.data.csr' > pki_int.csr
vault write -format=json pki/root/sign-intermediate csr=@pki_int.csr \
format=pem_bundle ttl="43800h" | jq -r '.data.certificate' > intermediate.cert.pem
vault write pki_int/intermediate/set-signed certificate=@intermediate.cert.pem
# Créer un rôle pour émettre des certificats serveur
vault write pki_int/roles/example-dot-com \
allowed_domains="example.com" \
allow_subdomains=true \
max_ttl="72h"
Tout service ayant besoin d’un certificat TLS en demande un avec :
vault write pki_int/issue/example-dot-com common_name="api.example.com" ttl="24h"
Les certificats valables 24 heures éliminent le risque d’oublier les rotations de certificats.
Intégration Kubernetes avec Vault Agent Injector
Les Secrets Kubernetes sont encodés en base64 et stockés dans etcd. Sans contrôles supplémentaires, tout utilisateur disposant d’un accès kubectl get secret peut les lire. Le Agent Injector de Vault maintient les secrets entièrement hors de Kubernetes.
Installation avec Helm :
helm repo add hashicorp https://helm.releases.hashicorp.com
helm install vault hashicorp/vault \
--set "injector.enabled=true" \
--set "server.dev.enabled=false"
Activez et configurez l’authentification Kubernetes dans Vault :
vault auth enable kubernetes
vault write auth/kubernetes/config \
kubernetes_host="https://kubernetes.default.svc" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Créez une policy et un rôle :
vault policy write myapp - <<EOF
path "secret/data/myapp/*" {
capabilities = ["read"]
}
EOF
vault write auth/kubernetes/role/myapp \
bound_service_account_names=myapp \
bound_service_account_namespaces=production \
policies=myapp \
ttl=1h
Annotez votre pod pour injecter des secrets au moment de l’exécution :
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "myapp"
vault.hashicorp.com/agent-inject-secret-config.env: "secret/data/myapp/config"
vault.hashicorp.com/agent-inject-template-config.env: |
{{- with secret "secret/data/myapp/config" -}}
export DB_PASSWORD="{{ .Data.data.db_password }}"
{{- end }}
Le sidecar Vault Agent s’authentifie, récupère le secret, l’écrit dans un volume partagé en mémoire et le renouvelle avant expiration. L’application lit un fichier — elle ne fait jamais appel à l’API Vault.
Comparaison : Vault vs. Alternatives de Gestion des Secrets
| Fonctionnalité | HashiCorp Vault | AWS Secrets Manager | Azure Key Vault | Kubernetes Secrets |
|---|---|---|---|---|
| Secrets dynamiques | Oui (base de données, cloud, PKI) | Limité (RDS uniquement) | Non | Non |
| Multi-cloud | Oui | AWS uniquement | Azure uniquement | Oui (avec CSI) |
| PKI / CA | CA complet avec CRL | Non | Oui (limité) | Non |
| Journalisation d’audit | Intégrée, infalsifiable | CloudTrail | Azure Monitor | Nécessite un add-on |
| Auto-hébergé | Oui | Non | Non | Oui |
| Coût | Gratuit (Community) | Par secret + appel API | Par opération | Gratuit |
| Natif Kubernetes | Agent Injector / VSO | Driver CSI | Driver CSI | Natif |
| Courbe d’apprentissage | Élevée | Faible | Faible | Très faible |
Vault est le bon choix lorsque vous avez besoin d’une gestion des secrets neutre vis-à-vis des fournisseurs, auditable et avec génération de credentials dynamiques sur plusieurs plateformes. AWS Secrets Manager l’emporte lorsque vous êtes 100% AWS-native et que la simplicité est la priorité.
Scénario Réel : Sécuriser une Application Multi-Niveaux
Vous disposez d’un cluster Kubernetes en production exécutant une API Node.js, une base de données PostgreSQL et un cache Redis. Votre configuration actuelle stocke le mot de passe de la base de données en tant que Secret Kubernetes et le mot de passe Redis dans une ConfigMap. Un audit interne récent a signalé les deux comme des risques de conformité.
Voici la démarche de migration :
- Déployez Vault en mode HA (3 nœuds) à côté du cluster avec Helm. Utilisez Integrated Storage avec un quorum Raft.
- Activez les secrets dynamiques pour PostgreSQL. Supprimez la variable d’environnement statique
PGPASSWORD. Le Vault Agent Injector écrit un nouveau fichier de credentials toutes les 55 minutes (avant l’expiration du TTL d’une heure). - Stockez le mot de passe Redis dans Vault KV v2 à
secret/data/production/redis. Le Agent Injector l’injecte sous la forme/vault/secrets/redis.envsourcé par le script d’entrée de l’application. - Activez PKI pour le TLS interne entre l’API et la base de données. Les certificats tournent toutes les 24 heures automatiquement.
- Configurez la journalisation d’audit pour écrire vers une cible syslog transmise à votre SIEM. Chaque accès aux secrets est désormais tracé avec l’identité du client, l’IP source et l’horodatage.
- Intégrez avec Terraform en utilisant le fournisseur Vault pour gérer les policies et rôles en tant que code, versionné dans votre dépôt d’infrastructure.
Résultat : aucun secret dans etcd Kubernetes, aucun credential statique, piste d’audit complète et rotation automatique — sans modifier une seule ligne de code applicatif.
Pièges et Cas Particuliers
Rescellement après redémarrage. Vault se rescelle à chaque redémarrage de processus. Vous avez besoin d’un mécanisme de descellement automatique en production. Les options sont l’Auto Unseal de HashiCorp (utilisant AWS KMS, GCP Cloud KMS ou Azure Key Vault comme source de clé), ou l’intégration Vault HSM. Planifiez cela avant de déployer en production.
Explosion des baux. Si vous générez des secrets dynamiques pour des milliers de jobs CI éphémères sans jamais les révoquer explicitement, le store de baux de Vault croît sans limite et dégrade finalement les performances. Appelez toujours vault lease revoke à la fin d’un job, ou utilisez Vault Agent qui gère automatiquement le renouvellement et la révocation.
Le token root doit être révoqué. Le token root généré lors de vault operator init dispose d’un accès illimité. Après la configuration initiale, générez un token root limité dans le temps pour les urgences et révoquez l’original : vault token revoke <root-token>.
Performances du backend de stockage. Integrated Storage (Raft) fonctionne bien pour la plupart des charges de travail mais est sensible à la latence d’E/S disque. Sur les VMs cloud, utilisez des volumes SSD. Évitez NFS ou le stockage réseau pour le répertoire de données Raft.
Confusion des namespaces. Les namespaces Vault Enterprise sont des unités d’isolation logique (comme des instances Vault séparées). Vault Community Edition n’a pas de namespaces. Si vous testez avec Enterprise et déployez Community, les chemins qui fonctionnaient auparavant n’existeront pas.
Dérive d’horloge. Plusieurs méthodes d’auth (AWS IAM, Kubernetes, JWT) valident des tokens signés avec un horodatage. Si les horloges du serveur dérivent de plus de quelques secondes, l’authentification échoue silencieusement. Assurez-vous que NTP est configuré sur tous les nœuds Vault.
Résolution de Problèmes
“Error initializing: Post https://127.0.0.1:8200/v1/sys/init: x509: certificate signed by unknown authority”
Définissez VAULT_SKIP_VERIFY=true pour les tests uniquement, ou ajoutez votre certificat CA au magasin de confiance du système et définissez VAULT_CACERT=/path/to/ca.crt.
“Error making API request: Code: 503. Errors: Vault is sealed.”
Vault a redémarré et attend les clés de descellement. Exécutez vault operator unseal avec le nombre requis de parts de clés, ou vérifiez votre configuration Auto Unseal.
Vault Agent ne parvient pas à s’authentifier sur Kubernetes avec “permission denied”
Vérifiez que le nom du ServiceAccount du pod et le namespace correspondent exactement à bound_service_account_names et bound_service_account_namespaces dans le rôle Kubernetes Vault. Vérifiez également que la policy Vault accorde l’accès aux chemins demandés.
“context deadline exceeded” lorsque Vault lit depuis la base de données
Le plugin de base de données ne peut pas atteindre l’hôte de la base de données. Vérifiez la connection_url dans database/config/<name>, la connectivité réseau et les règles de pare-feu entre Vault et la base de données, et assurez-vous que l’utilisateur superuser Vault dispose des privilèges CREATEROLE.
Les secrets ne se mettent pas à jour dans un pod en cours d’exécution après le renouvellement de Vault Agent
Par défaut, Vault Agent restitue les templates dans des fichiers. L’application doit surveiller le fichier pour détecter les changements ou redémarrer pour récupérer les nouveaux credentials. Utilisez le bloc command dans la strophe template de Vault Agent pour déclencher un kill -HUP ou un signal similaire.
Résumé
- HashiCorp Vault est la référence industrielle pour la gestion des secrets neutre vis-à-vis des fournisseurs, auditable, sur les environnements cloud et on-premises.
- Le moteur KV v2 gère les secrets statiques ; les moteurs Database et PKI génèrent des credentials dynamiques et des certificats à courte durée de vie qui se révoquent automatiquement.
- Vault Agent découple votre application de l’API Vault — il gère l’authentification, la récupération des secrets, le rendu des templates, le renouvellement et la révocation.
- L’intégration Kubernetes via le Agent Injector ou le Vault Secrets Operator élimine les Secrets Kubernetes statiques et l’exposition etcd.
- Chaque opération via Vault est capturée dans les journaux d’audit, vous donnant un enregistrement complet et infalsifiable pour la conformité.
- Planifiez l’Auto Unseal dès le premier jour pour éviter les interruptions opérationnelles lors des redémarrages des nœuds Vault.
- Les secrets dynamiques réduisent considérablement le rayon de blast d’une fuite de credentials — un credential de base de données d’une heure est bien moins dangereux qu’un mot de passe valide depuis trois ans.