Gestion des secrets - 05 - HashiCorp Vault : le couteau suisse du secret management

HashiCorp Vault pour les devs : installation, premiers secrets, politiques d'acces et intégration avec Docker et CI/CD.

05 - HashiCorp Vault : le couteau suisse du secret management

Ce que tu vas apprendre

  • Ce que Vault fait (et ne fait pas mieux que les alternatives cloud)
  • Démarrer en mode dev et stocker tes premiers secrets
  • Politiques d'acces, méthodes d'auth et intégration Docker/CI

Prerequisites

Docker installe pour le mode dev. Connaissance de base du chiffrement.


Vault, c'est quoi exactement

HashiCorp Vault est un outil open source de gestion de secrets. Contrairement a Google Secret Manager ou AWS Secrets Manager qui sont des services cloud manages, Vault tu l'heberges toi-meme. Sur ton serveur, ton cluster, ou ta machine de dev.

Ce qui le distingue des autres solutions, c'est l'etendue des fonctionnalités. Vault gere :

  • Les secrets statiques (clé API, mot de passe, comme un .env mais en mieux)
  • Les secrets dynamiques (il généré des credentials de base de donnees temporaires a la demande)
  • Le chiffrement as a service (ton app lui envoie des donnees, il les chiffre et les renvoie, sans exposer la clé)
  • La gestion PKI (il peut etre ta propre autorite de certificats TLS)

Pour un projet comme paltemps.fr, c'est clairement overkill. Mais si tu geres 15 microservices avec chacun leur base de donnees, 8 développeurs et des obligations de compliance, Vault commence a avoir du sens.

Mode dev : 5 minutes pour tester

Le mode dev lance Vault en mémoire, sans persistance, avec un token root pre-configure. Parfait pour tester, inutilisable en production.

bash# Avec Docker
docker run --rm -p 8200:8200 hashicorp/vault server -dev

# Ou avec le binaire
vault server -dev

Dans un autre terminal :

bashexport VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN='hvs.xxx'  # Affiche dans les logs du serveur

# Stocker des secrets
vault kv put secret/paltemps \
  ANTHROPIC_KEY=sk-ant-api03-xxxx \
  SMTP_PASS=monmotdepasse \
  ADMIN_PASSWORD=admin123

# Lire tout
vault kv get secret/paltemps

# Lire un champ specifique
vault kv get -field=ANTHROPIC_KEY secret/paltemps

Le moteur secret/ est un KV (key-value) store version 2 par défaut. Chaque put créé une nouvelle version, et tu peux revenir aux versions précédentes :

bash# Voir la version 1
vault kv get -version=1 secret/paltemps

# Lister les versions
vault kv metadata get secret/paltemps

Politiques d'acces

La ou Vault brille, c'est le contrôle d'acces granulaire. Tu définis des politiques (policies) en HCL qui specifient qui peut lire quoi :

hcl# paltemps-readonly.hcl
path "secret/data/paltemps" {
  capabilities = ["read"]
}

path "secret/data/paltemps/smtp" {
  capabilities = ["read"]
}
bash# Creer la politique
vault policy write paltemps-readonly paltemps-readonly.hcl

# Creer un token avec cette politique
vault token create -policy=paltemps-readonly -ttl=24h

Le token généré ne peut que lire les secrets sous secret/paltemps. Pas écrire, pas supprimer, pas acceder aux secrets d'un autre projet. C'est l'inverse du .env ou tout est accessible d'un coup.

Méthodes d'authentification

En mode dev, on utilise un token root. En vrai, tu veux des méthodes d'auth adaptees a chaque usage :

AppRole pour les applications et le CI/CD. C'est la méthode la plus courante en automatisation. L'app recoit un role_id (public) et un secret_id (confidentiel, a usage unique) :

bash# Activer AppRole
vault auth enable approle

# Creer un role pour paltemps
vault write auth/approle/role/paltemps \
  policies=paltemps-readonly \
  token_ttl=1h \
  token_max_ttl=4h

# Recuperer le role_id
vault read auth/approle/role/paltemps/role-id

# Generer un secret_id
vault write -f auth/approle/role/paltemps/secret-id

Dans ton pipeline GitLab CI, tu stockes role_id et secret_id comme variables CI/CD, et le job les utilise pour s'authentifier auprès de Vault.

OIDC pour les humains. Tu connectes Vault a ton fournisseur d'identité (Google, GitLab, Okta) et les développeurs se connectent avec leur compte habituel. Pas de token a gerer manuellement.

Token pour le debug et l'admin. Genere des tokens temporaires avec des droits limites.

Secrets dynamiques

C'est la fonctionnalité qui justifie Vault pour les grosses équipes. Au lieu de stocker un mot de passe de base de donnees (qui est le meme pour tout le monde et ne change jamais), Vault généré des credentials temporaires a la demande.

bash# Configurer le moteur de secrets PostgreSQL
vault secrets enable database

vault write database/config/paltemps-db \
  plugin_name=postgresql-database-plugin \
  allowed_roles="paltemps-app" \
  connection_url="postgresql://{{username}}:{{password}}@db:5432/paltemps" \
  username="vault-admin" \
  password="vault-admin-password"

vault write database/roles/paltemps-app \
  db_name=paltemps-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"

# Maintenant, chaque demande genere un couple user/pass unique
vault read database/creds/paltemps-app
# username: v-approle-paltemps-xxxx
# password: A1B2-random-generated
# lease_duration: 1h

Chaque app recoit des credentials différents, qui expirent au bout d'une heure. Si un set de credentials fuite, le blast radius est minimal : un seul service, pendant une heure max. Compare ca a un mot de passe partage dans un .env qui ne change jamais.

Intégration Docker avec Vault Agent

Vault Agent est un processus sidecar qui s'authentifié auprès de Vault et écrit les secrets dans des fichiers que ton app peut lire :

hcl# vault-agent-config.hcl
auto_auth {
  method "approle" {
    config = {
      role_id_file_path   = "/vault/role-id"
      secret_id_file_path = "/vault/secret-id"
    }
  }

  sink "file" {
    config = { path = "/vault/token" }
  }
}

template {
  source      = "/vault/templates/env.tpl"
  destination = "/app/.env"
}

Le template :

{{ with secret "secret/data/paltemps" }}
ANTHROPIC_KEY={{ .Data.data.ANTHROPIC_KEY }}
SMTP_PASS={{ .Data.data.SMTP_PASS }}
{{ end }}

Vault Agent se charge de l'authentification, du renouvellement du token, et de la mise à jour du fichier .env quand les secrets changent. Ton app n'a pas besoin de connaître Vault : elle lit toujours un .env, mais le fichier est généré et mis à jour automatiquement.

Mon avis honnete

Vault est puissant. Les secrets dynamiques, le chiffrement as a service, la PKI intégrée, c'est impressionnant. Mais le coût operationnel est réel.

En production, Vault a besoin de :

  • Un backend de stockage (Consul, Raft intégré, PostgreSQL)
  • Un processus d'unseal a chaque redemarrage (ou auto-unseal via un KMS cloud)
  • Des backups réguliers
  • De la supervision (un Vault down = aucune app ne peut lire ses secrets)
  • Des mises à jour et une maintenance régulière

Pour un solo dev avec un VPS, c'est un lance-roquettes pour tuer une mouche. Les variables CI/CD et SOPS + age font le meme travail pour les secrets statiques, sans infra a maintenir.

Pour une équipe de 10+ devs avec des bases de donnees partagees et des exigences de compliance, Vault est justifie. Les secrets dynamiques seuls valent le coût de l'opération.


Navigation : Precedent : 04 - AWS Secrets Manager | Suivant : 06 - SOPS + age


Sources

Retrouve d'autres articles techniques sur paltemps.fr.

Réservez un audit gratuit de 30 minutes. Je vous montre concrètement ce qu'on peut automatiser.