Vault n'est pas qu'un coffre-fort à secrets. Son vrai pouvoir est de servir de courtier d'identité : un workload prouve qui il est, Vault vérifie cette identité, puis délivre un accès temporaire vers une ressource cible.
Ce pattern est au cœur de l'approche zero trust : pas de credentials permanents, des accès basés sur l'identité vérifiée.
Le problème : credentials permanents dans les workloads
Section intitulée « Le problème : credentials permanents dans les workloads »La façon la plus répandue de donner un accès à un pod consiste à lui monter un Secret Kubernetes contenant un mot de passe de base de données. Ce mot de passe ne change pas, il est identique pour toutes les répliques, et il reste valable tant que personne ne le fait tourner à la main. Comprendre pourquoi ce modèle finit toujours par poser problème est le préalable au pattern décrit dans cette page.
Modèle classique
Section intitulée « Modèle classique »Le schéma ci-dessous montre la chaîne habituelle : un secret créé une fois, monté dans le pod, puis présenté tel quel à PostgreSQL. Le credential est permanent et le pod le détient en clair, ce qui a trois conséquences prévisibles.
Ce qui arrive tôt ou tard :
- Le secret fuite (commit Git, log, debug)
- Une compromission d'un pod = accès permanent à la DB
- L'audit montre "app_user a fait X" mais pas quel pod
Vault n'est pas qu'un coffre-fort
Section intitulée « Vault n'est pas qu'un coffre-fort »La vision première de Vault est souvent "un endroit sécurisé pour stocker des secrets". C'est vrai, mais c'est la partie la moins intéressante.
La vraie valeur de Vault :
| Fonction | Description |
|---|---|
| Authentification | Vérifie l'identité du demandeur |
| Autorisation | Vérifie ce qu'il a le droit de demander |
| Émission | Génère un credential temporaire, unique |
| Audit | Trace qui a demandé quoi, quand |
| Révocation | Invalide le credential à tout moment |
Vault transforme une identité prouvée en accès temporaire.
Le pattern identity broker
Section intitulée « Le pattern identity broker »Le courtier d'identité (identity broker) insère Vault entre le workload et la ressource qu'il veut atteindre. Le workload ne s'adresse plus directement à la base de données avec un mot de passe : il s'adresse d'abord à Vault avec sa preuve d'identité de plateforme, et Vault lui remet en échange un credential fabriqué pour lui, valable quelques minutes ou quelques heures.
Le workload ne possède jamais de credential permanent vers la cible. Il possède une identité source (service account K8s, rôle IAM, token OIDC) qui lui permet de prouver qui il est à Vault.
Ce que Vault courtier d'identité change vraiment
Section intitulée « Ce que Vault courtier d'identité change vraiment »Le pattern identity broker diffère fondamentalement de la distribution classique de secrets :
- Le workload ne reçoit pas un secret "par défaut" : il obtient un accès parce qu'il a prouvé qui il est
- Vault devient le point de traduction entre identité source (K8s service account, cloud IAM, token OIDC) et accès cible (credentials base de données, clés cloud, certificats)
- Pas de secret pré-distribué : l'identité source suffit à initier le flux, Vault fait le reste
Flux complet : authentification → identité → accès dynamique
Section intitulée « Flux complet : authentification → identité → accès dynamique »Les huit étapes ci-dessous décrivent un cycle complet, de l'arrivée du pod
jusqu'à la révocation automatique de son credential. Deux moments méritent votre
attention : l'étape 2, où Vault interroge l'API Kubernetes et devient donc
dépendant de sa disponibilité, et l'étape 8, où la révocation est portée par
Vault et non par l'application. Les commandes montrées supposent l'auth
Kubernetes et un secrets engine database déjà configurés.
-
Le workload s'authentifie
Le pod Kubernetes présente son service account token à Vault :
Fenêtre de terminal vault write auth/kubernetes/login \role="my-app" \jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" -
Vault vérifie l'identité
Vault contacte l'API Kubernetes pour valider :
- Le token est-il valide ?
- Le service account correspond-il au rôle Vault configuré ?
- Le namespace est-il autorisé ?
-
Vault associe l'authentification à sa couche Identity
Si valide, Vault associe l'authentification à sa couche Identity via des aliases, et peut exploiter des métadonnées pour appliquer des policies ou tracer l'accès :
- Service account name
- Namespace
- Annotations Kubernetes (si configurées)
-
Vault délivre un token Vault
Le workload reçoit un token Vault avec les policies attachées au rôle.
-
Le workload demande un credential dynamique
Fenêtre de terminal vault read database/creds/app-readonly -
Vault génère et renvoie
- Crée un user PostgreSQL unique
- Retourne username/password avec lease
-
Le workload utilise le credential
Se connecte à PostgreSQL avec ces credentials temporaires.
-
À expiration
Vault révoque le credential (supprime l'user PostgreSQL).
Méthodes d'authentification adaptées au brokering
Section intitulée « Méthodes d'authentification adaptées au brokering »Vault propose une vingtaine de méthodes d'authentification, mais toutes ne
conviennent pas au brokering. Celles qui fonctionnent partagent un point commun :
elles reposent sur une identité que la plateforme délivre elle-même au
workload, sans qu'on ait à déposer un secret au préalable. Les trois familles
ci-dessous couvrent la quasi-totalité des cas ; à l'inverse, une méthode comme
AppRole suppose de distribuer un secret_id, ce qui ramène le problème de
départ.
Kubernetes auth
Section intitulée « Kubernetes auth »Idéal pour : pods dans un cluster K8s.
Le pod prouve son identité via son service account token. Vault contacte l'API Kubernetes pour valider.
# Configurer l'auth Kubernetes dans Vaultvault 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
vault write auth/kubernetes/role/my-app \ bound_service_account_names="my-app-sa" \ bound_service_account_namespaces="production" \ policies="app-policy" \ ttl="1h"Cloud auth (AWS, GCP, Azure)
Section intitulée « Cloud auth (AWS, GCP, Azure) »Idéal pour : VMs, fonctions serverless, workloads cloud.
Le workload prouve son identité via son IAM role (AWS), service account (GCP), ou managed identity (Azure).
# AWS IAM authvault auth enable aws
vault write auth/aws/role/ec2-role \ auth_type="iam" \ bound_iam_principal_arn="arn:aws:iam::123456789012:role/my-ec2-role" \ policies="app-policy" \ ttl="1h"Avantage : pas de secret à distribuer au workload, il utilise son identité cloud native.
OIDC / JWT
Section intitulée « OIDC / JWT »Idéal pour : CI/CD (GitHub Actions, GitLab CI), authentification humaine.
Le workload présente un token JWT signé par un provider OIDC. Vault vérifie la signature et les claims.
vault auth enable jwt
vault write auth/jwt/config \ oidc_discovery_url="https://token.actions.githubusercontent.com" \ bound_issuer="https://token.actions.githubusercontent.com"
vault write auth/jwt/role/github-deploy \ role_type="jwt" \ bound_audiences="https://github.com/my-org" \ bound_claims='{"repository": "my-org/my-repo"}' \ user_claim="actor" \ policies="deploy-policy" \ ttl="15m"Exemple : pod Kubernetes → credentials PostgreSQL
Section intitulée « Exemple : pod Kubernetes → credentials PostgreSQL »Cet exemple assemble les pièces vues plus haut sur un cas complet : côté Vault la configuration du rôle et de la policy, côté cluster l'annotation du pod. Le point à retenir est la jointure entre les deux : c'est le nom du service account qui relie le pod au rôle Vault, et rien d'autre.
Scénario
Section intitulée « Scénario »Un pod order-service dans le namespace production a besoin d'accéder
à PostgreSQL en lecture.
Configuration Vault
Section intitulée « Configuration Vault »Ces quatre commandes s'exécutent une seule fois, avec un token administrateur.
Le default_ttl du rôle base de données fixe la durée de vie des credentials
générés, et max_ttl la limite au-delà de laquelle plus aucun renouvellement
n'est possible : passé ce délai, le workload doit redemander un credential neuf.
# 1. Auth Kubernetes configurée (voir ci-dessus)
# 2. Database secrets configurésvault write database/roles/order-readonly \ db_name="production-postgres" \ creation_statements="..." \ default_ttl="1h" \ max_ttl="4h"
# 3. Policyvault policy write order-service - <<EOFpath "database/creds/order-readonly" { capabilities = ["read"]}EOF
# 4. Rôle Kubernetes lié à la policyvault write auth/kubernetes/role/order-service \ bound_service_account_names="order-service" \ bound_service_account_namespaces="production" \ policies="order-service" \ ttl="1h"Dans le pod
Section intitulée « Dans le pod »Côté cluster, l'application n'a aucun code Vault à embarquer. Le Vault Agent Injector ajoute un conteneur d'initialisation et un sidecar qui s'authentifient, récupèrent le credential et l'écrivent dans un fichier partagé. Tout se pilote par des annotations, ce qui rend le manifeste lisible mais aussi silencieux en cas d'erreur de frappe : une annotation mal orthographiée est simplement ignorée, sans message.
apiVersion: v1kind: Podmetadata: name: order-service annotations: vault.hashicorp.com/agent-inject: "true" vault.hashicorp.com/role: "order-service" vault.hashicorp.com/agent-inject-secret-db: "database/creds/order-readonly" vault.hashicorp.com/agent-inject-template-db: | {{- with secret "database/creds/order-readonly" -}} PGUSER={{ .Data.username }} PGPASSWORD={{ .Data.password }} {{- end }}spec: serviceAccountName: order-service containers: - name: app image: order-service:2.1.0 command: ["source", "/vault/secrets/db", "&&", "./start.sh"]Résultat :
- Le pod démarre avec son service account
- Vault Agent s'authentifie via Kubernetes auth
- Vault génère des credentials PostgreSQL uniques
- Le fichier
/vault/secrets/dbcontient user/pass - L'app utilise ces credentials
- Vault Agent renouvelle automatiquement avant expiration
Exemple : CI/CD → credentials AWS temporaires
Section intitulée « Exemple : CI/CD → credentials AWS temporaires »Le même pattern s'applique hors de Kubernetes, avec une identité fournie cette fois par la forge. GitHub Actions peut émettre un token OIDC décrivant le dépôt, la branche et le workflow en cours ; Vault vérifie ces informations et délivre des credentials AWS temporaires. Résultat : plus aucune clé d'accès AWS stockée dans les secrets du dépôt.
Scénario
Section intitulée « Scénario »Un workflow GitHub Actions doit déployer sur S3.
Configuration Vault
Section intitulée « Configuration Vault »Le credential_type: assumed_role demande à Vault d'appeler AWS STS pour
endosser un rôle existant, plutôt que de créer un utilisateur IAM jetable. Les
bound_claims du rôle JWT sont la véritable barrière de sécurité : sans la
contrainte sur ref, n'importe quelle branche du dépôt, y compris celle d'une
pull request externe, obtiendrait les mêmes droits de déploiement.
# 1. JWT auth pour GitHub Actions (voir ci-dessus)
# 2. AWS secrets configurésvault write aws/roles/github-deploy \ credential_type="assumed_role" \ role_arns="arn:aws:iam::123456789012:role/S3DeployRole" \ default_sts_ttl="15m" \ max_sts_ttl="1h"
# 3. Policyvault policy write github-deploy - <<EOFpath "aws/creds/github-deploy" { capabilities = ["read"]}EOF
# 4. Rôle JWT liévault write auth/jwt/role/github-deploy \ bound_claims='{"repository": "my-org/my-repo", "ref": "refs/heads/main"}' \ policies="github-deploy" \ ttl="15m"Dans le workflow
Section intitulée « Dans le workflow »La permission id-token: write est indispensable : sans elle, GitHub
n'émet aucun token OIDC et l'authentification Vault échoue avant même le premier
appel réseau. Elle est déclarée au niveau du job, le workflow partant de
permissions: {} pour n'accorder aucun droit par défaut aux autres jobs.
permissions: {}
jobs: deploy: runs-on: ubuntu-latest permissions: id-token: write # Nécessaire pour OIDC contents: read
steps: - uses: hashicorp/vault-action@892a26828f195e65540a40b4768ae4571f51ebfc # v4.0.0 with: url: https://vault.example.com method: jwt role: github-deploy jwtGithubAudience: https://github.com/my-org secrets: | aws/creds/github-deploy access_key | AWS_ACCESS_KEY_ID ; aws/creds/github-deploy secret_key | AWS_SECRET_ACCESS_KEY ; aws/creds/github-deploy security_token | AWS_SESSION_TOKEN
- run: aws s3 sync ./dist s3://my-bucketRésultat :
- Le workflow prouve son identité via le token OIDC de GitHub
- Vault vérifie que c'est bien
my-org/my-reposurmain - Vault assume un rôle IAM et retourne des credentials STS
- Le workflow déploie sur S3 avec des credentials valides 15 min
Ce pattern vs distribution classique de secrets
Section intitulée « Ce pattern vs distribution classique de secrets »Le tableau oppose les deux approches ligne par ligne. Lisez-le en séparant deux choses que l'on confond souvent : la complexité de gestion au quotidien, que le brokering réduit fortement, et la complexité de plateforme, qu'il augmente en ajoutant Vault à votre chemin critique. Les quatre dernières lignes portent précisément sur ce basculement.
| Aspect | Distribution classique | Identity brokering |
|---|---|---|
| Secret permanent vers la cible | Oui (dans K8s Secret, env vars) | Non |
| Rotation des credentials | Manuelle, coordination | Automatique par TTL |
| Credential unique par workload | Rarement | Toujours |
| Audit | "app_user a fait X" | "pod order-abc123 a fait X" |
| Compromission | Accès permanent | Accès limité au TTL |
| Complexité initiale | Faible | Moyenne à élevée |
| Complexité de rotation/gestion | Haute (coordination manuelle) | Faible (automatisé) |
| Complexité de plateforme | Faible | Haute (Vault à opérer) |
Limites et considérations
Section intitulée « Limites et considérations »Le pattern déplace le risque plus qu'il ne le supprime : vous n'avez plus de mot de passe permanent qui traîne, mais vous avez un service dont dépend le démarrage de vos applications. Les trois points ci-dessous sont ceux qui reviennent en production, avec les mitigations correspondantes.
Dépendance à Vault
Section intitulée « Dépendance à Vault »Le workload ne peut pas démarrer si Vault est inaccessible. Mitigations :
- Vault en HA
- Cache local (Vault Agent)
- TTL assez longs pour survivre à une panne courte
Chaque demande de credential ajoute un appel réseau. Mitigations :
- Vault Agent avec cache
- TTL suffisants pour éviter trop de renouvellements
- Pooling de connexions côté app
Complexité
Section intitulée « Complexité »Plus complexe qu'un Secret K8s statique. À justifier par :
- Nombre de services
- Exigences de sécurité/audit
- Fréquence de rotation souhaitée
Policies dynamiques basées sur l'identité
Section intitulée « Policies dynamiques basées sur l'identité »Vault ne se contente pas de vérifier l'identité : il peut aussi s'en servir pour construire les permissions à la volée.
Avec les templated policies, vous pouvez exploiter les métadonnées d'alias pour créer des ACL dynamiques :
path "database/creds/{{identity.entity.aliases.auth_kubernetes_*.metadata.service_account_namespace}}-*" { capabilities = ["read"]}Avantages :
- Une seule policy pour plusieurs namespaces
- Isolation automatique : chaque namespace n'accède qu'à ses propres credentials
- Moins de policies à maintenir
Pour aller plus loin : Boundary
Section intitulée « Pour aller plus loin : Boundary »Vault excelle comme courtier d'identité pour secrets dynamiques : le workload reçoit les credentials et gère la connexion lui-même.
Si vous voulez aller plus loin vers un accès interactif sans exposition directe des credentials (SSH, RDP, bases de données), HashiCorp Boundary couvre un autre niveau :
- Brokering : le client reçoit les credentials (ce que fait Vault)
- Credential injection : un worker intermédiaire cache les credentials au client final (ce que fait Boundary)
Boundary complète Vault pour les accès interactifs privilégiés.
À retenir
Section intitulée « À retenir »- Vault = courtier d'identité : transforme une identité prouvée en accès temporaire vers une ressource cible
- Pas de credential permanent vers la cible : le workload conserve une preuve d'identité source (token K8s, OIDC, IAM) mais pas de secret vers la ressource finale
- Couche Identity : Vault associe les authentifications à des entities et aliases, permettant consolidation et policies dynamiques
- Auth native : K8s service account, cloud IAM, OIDC, pas de secret à distribuer au workload
- Credential unique : chaque workload obtient ses propres credentials
- Audit complet : qui (identité source) a demandé quoi (secret) et quand
- TTL courts réduisent le besoin de révocation : mais ne remplacent pas totalement la capacité à révoquer avant expiration
- Compromis plateforme : on gagne en sécurité et gestion, mais Vault devient une dépendance critique à opérer