Vault peut agir comme autorité de certification (CA) interne pour émettre des certificats TLS à la demande. Plus de certificats manuels, plus d’oublis de renouvellement : chaque service demande son certificat quand il en a besoin.
Ce guide couvre la création d’une PKI avec CA intermédiaire dans Vault, les
méthodes d’émission (issue vs sign), et le cycle de vie des certificats.
Prérequis
Section intitulée « Prérequis »- Vault installé et démarré
- Accès admin pour configurer le moteur PKI
Architecture PKI recommandée
Section intitulée « Architecture PKI recommandée »Une PKI bien conçue utilise deux niveaux de CA minimum :
| Niveau | Durée typique | Localisation | Usage |
|---|---|---|---|
| Root CA | 10-20 ans | Hors Vault (offline) | Signe uniquement les intermédiaires |
| Intermediate CA | 1-5 ans | Dans Vault (pki_int) | Émet les certificats services |
| Certificats leaf | 30-90 jours | Services | mTLS, HTTPS, API |
Étape 1 : créer la Root CA (démo uniquement)
Section intitulée « Étape 1 : créer la Root CA (démo uniquement) »Activer le moteur PKI pour la Root
Section intitulée « Activer le moteur PKI pour la Root »vault secrets enable -path=pki pkiConfigurer la durée maximale
Section intitulée « Configurer la durée maximale »vault secrets tune -max-lease-ttl=87600h pki87600h = 10 ans. La Root CA doit avoir une longue durée de vie.
Générer le certificat Root
Section intitulée « Générer le certificat Root »vault write -field=certificate pki/root/generate/internal \ common_name="My Organization Root CA" \ issuer_name="root-2026" \ ttl=87600h > root_ca.crtConfigurer les URLs de publication
Section intitulée « Configurer les URLs de publication »vault write pki/config/urls \ issuing_certificates="$VAULT_ADDR/v1/pki/ca" \ crl_distribution_points="$VAULT_ADDR/v1/pki/crl"Étape 2 : créer la CA intermédiaire
Section intitulée « Étape 2 : créer la CA intermédiaire »Activer un second moteur PKI
Section intitulée « Activer un second moteur PKI »vault secrets enable -path=pki_int pkiConfigurer la durée
Section intitulée « Configurer la durée »vault secrets tune -max-lease-ttl=43800h pki_int43800h = 5 ans maximum pour les certificats émis par cette CA.
Générer une CSR (Certificate Signing Request)
Section intitulée « Générer une CSR (Certificate Signing Request) »vault write -format=json pki_int/intermediate/generate/internal \ common_name="My Organization Intermediate CA" \ issuer_name="intermediate-2026" \ | jq -r '.data.csr' > intermediate.csrSigner la CSR avec la Root CA
Section intitulée « Signer la CSR avec la Root CA »vault write -format=json pki/root/sign-intermediate \ issuer_ref="root-2026" \ csr=@intermediate.csr \ format=pem_bundle \ ttl=43800h \ | jq -r '.data.certificate' > intermediate.crtSur votre machine air-gapped avec la Root CA :
# Copier intermediate.csr sur la machine air-gapped# Signer avec openssl ou cfssl selon votre setup
openssl ca -config /path/to/root-ca.conf \ -extensions v3_intermediate_ca \ -days 1825 -notext -md sha256 \ -in intermediate.csr \ -out intermediate.crt
# Copier intermediate.crt de retour vers VaultImporter le certificat signé
Section intitulée « Importer le certificat signé »vault write pki_int/intermediate/set-signed certificate=@intermediate.crtConfigurer les URLs de l’intermédiaire
Section intitulée « Configurer les URLs de l’intermédiaire »vault write pki_int/config/urls \ issuing_certificates="$VAULT_ADDR/v1/pki_int/ca" \ crl_distribution_points="$VAULT_ADDR/v1/pki_int/crl"Multi-issuer et rotation d’autorité
Section intitulée « Multi-issuer et rotation d’autorité »Depuis Vault 1.11+, un même mount PKI peut gérer plusieurs issuers (plusieurs CA). Cela permet :
- Rotation d’autorité : créer un nouvel issuer avant d’expirer l’ancien
- Période de transition : les deux issuers coexistent pendant le sunset
- Révocation par issuer : révoquer un issuer sans toucher aux autres
Lister les issuers
Section intitulée « Lister les issuers »vault list pki_int/issuersDéfinir l’issuer par défaut
Section intitulée « Définir l’issuer par défaut »vault write pki_int/config/issuers default="intermediate-2026"Rotation d’issuer (aperçu)
Section intitulée « Rotation d’issuer (aperçu) »- Générer une nouvelle CSR :
pki_int/intermediate/generate/internal - La faire signer par la Root
- Importer :
pki_int/intermediate/set-signed - Mettre à jour le défaut :
pki_int/config/issuers - Laisser l’ancien issuer le temps que ses certificats expirent
- Supprimer l’ancien issuer si besoin
Étape 3 : créer un rôle d’émission
Section intitulée « Étape 3 : créer un rôle d’émission »Un rôle définit les paramètres des certificats émis : domaines autorisés, durée, type de clé.
vault write pki_int/roles/webserver \ allowed_domains="example.com" \ allow_subdomains=true \ allow_bare_domains=false \ max_ttl=2160h \ ttl=720h \ key_type="rsa" \ key_bits=2048 \ require_cn=true \ allow_ip_sans=false \ allow_localhost=false \ enforce_hostnames=true| Paramètre | Description | Valeur sécurisée |
|---|---|---|
allowed_domains | Domaines autorisés | Un seul domaine par rôle |
allow_subdomains | *.example.com autorisé | Selon besoin |
allow_bare_domains | example.com sans sous-domaine | false en général |
allow_ip_sans | Autoriser les IPs dans SAN | false sauf besoin explicite |
allow_localhost | Autoriser localhost | false en prod |
enforce_hostnames | Valider le format hostname | true toujours |
Rôle pour mTLS interne (TTL court)
Section intitulée « Rôle pour mTLS interne (TTL court) »vault write pki_int/roles/mtls-internal \ allowed_domains="service.internal" \ allow_subdomains=true \ max_ttl=168h \ ttl=72h \ key_type="ec" \ key_bits=256 \ client_flag=true \ server_flag=true \ require_cn=true \ enforce_hostnames=trueissue vs sign : quelle méthode choisir ?
Section intitulée « issue vs sign : quelle méthode choisir ? »Vault PKI propose deux endpoints pour obtenir un certificat :
| Endpoint | Clé privée | Cas d’usage |
|---|---|---|
/issue/<role> | Générée par Vault | Scripts, automation, services simples |
/sign/<role> | Fournie par le client (CSR) | HSM, exigences de conformité, contrôle total |
Méthode issue : Vault génère tout
Section intitulée « Méthode issue : Vault génère tout »vault write pki_int/issue/webserver \ common_name="api.example.com" \ ttl=720hVault génère la clé privée et le certificat. La clé privée est retournée dans la réponse.
Avantages : simple, tout-en-un. Inconvénients : la clé privée transite par Vault et le réseau.
Méthode sign : le client génère la clé
Section intitulée « Méthode sign : le client génère la clé »# 1. Générer une clé et une CSR côté clientopenssl genrsa -out backend.key 2048openssl req -new -key backend.key -out backend.csr \ -subj "/CN=backend.example.com"
# 2. Demander à Vault de signer la CSRvault write -format=json pki_int/sign/webserver \ csr=@backend.csr \ ttl=720h | jq -r '.data.certificate' > backend.crtAvantages : la clé privée ne quitte jamais le serveur cible. Inconvénients : plus complexe, nécessite un workflow de distribution de CSR.
Étape 4 : émettre des certificats
Section intitulée « Étape 4 : émettre des certificats »Certificat simple
Section intitulée « Certificat simple »vault write pki_int/issue/webserver \ common_name="api.example.com" \ ttl=720hSortie :
Key Value--- -----ca_chain [-----BEGIN CERTIFICATE-----...]certificate -----BEGIN CERTIFICATE-----...expiration 1747389600issuing_ca -----BEGIN CERTIFICATE-----...private_key -----BEGIN RSA PRIVATE KEY-----...private_key_type rsaserial_number 5a:c2:1b:4d:7f...Certificat avec SAN multiples
Section intitulée « Certificat avec SAN multiples »vault write pki_int/issue/webserver \ common_name="frontend.example.com" \ alt_names="www.example.com,cdn.example.com" \ ttl=720hEnregistrer dans des fichiers
Section intitulée « Enregistrer dans des fichiers »vault write -format=json pki_int/issue/webserver \ common_name="backend.example.com" \ ttl=720h | tee \ >(jq -r '.data.certificate' > backend.crt) \ >(jq -r '.data.private_key' > backend.key) \ >(jq -r '.data.ca_chain[]' > ca-chain.crt) \ > /dev/null
chmod 600 backend.keychmod 644 backend.crt ca-chain.crtPolicy pour l’émission
Section intitulée « Policy pour l’émission »Limitez qui peut émettre des certificats par rôle :
# Émettre via issue (Vault génère la clé)path "pki_int/issue/webserver" { capabilities = ["create", "update"]}
# Signer une CSR (client génère la clé)path "pki_int/sign/webserver" { capabilities = ["create", "update"]}
# Lire les infos de la CApath "pki_int/cert/ca" { capabilities = ["read"]}vault policy write pki-webserver pki-webserver-policy.hclCRL et URLs de publication
Section intitulée « CRL et URLs de publication »La qualité de votre PKI dépend de la distribution réelle des URLs, pas seulement de leur configuration dans Vault.
Ce que Vault configure
Section intitulée « Ce que Vault configure »vault write pki_int/config/urls \ issuing_certificates="https://vault.example.com/v1/pki_int/ca" \ crl_distribution_points="https://vault.example.com/v1/pki_int/crl"Ce que vous devez garantir
Section intitulée « Ce que vous devez garantir »-
Accessibilité : les URLs doivent être joignables par tous les clients qui valident les certificats (navigateurs, services, reverse proxies)
-
Résolution DNS : le nom
vault.example.comdoit résoudre correctement dans tous les environnements -
TLS valide : ironie, le endpoint doit avoir un certificat valide (bootstrap problem à résoudre)
-
Haute disponibilité : si Vault est down, les validations CRL échouent (selon la politique du client)
Configuration de la CRL
Section intitulée « Configuration de la CRL »# Fréquence de mise à jour de la CRLvault write pki_int/config/crl expiry="72h"Consulter la CRL
Section intitulée « Consulter la CRL »curl -s "https://vault.example.com/v1/pki_int/crl" | \ openssl crl -inform DER -text -nooutCycle de vie des certificats
Section intitulée « Cycle de vie des certificats »Lister les certificats émis
Section intitulée « Lister les certificats émis »vault list pki_int/certsVoir un certificat spécifique
Section intitulée « Voir un certificat spécifique »vault read pki_int/cert/<serial_number>Révoquer un certificat
Section intitulée « Révoquer un certificat »vault write pki_int/revoke serial_number="5a:c2:1b:4d:7f:..."Supprimer les certificats expirés (tidy)
Section intitulée « Supprimer les certificats expirés (tidy) »Vault stocke les métadonnées des certificats émis. Pour nettoyer :
vault write pki_int/tidy \ tidy_cert_store=true \ tidy_revoked_certs=true \ tidy_revoked_cert_issuer_associations=true \ safety_buffer="72h"| Paramètre | Description |
|---|---|
tidy_cert_store | Supprimer les métadonnées des certificats expirés |
tidy_revoked_certs | Supprimer les métadonnées des certificats révoqués expirés |
safety_buffer | Ne pas toucher aux certificats expirés depuis moins de X |
Renouvellement automatique
Section intitulée « Renouvellement automatique »Option 1 : cert-manager (Kubernetes)
Section intitulée « Option 1 : cert-manager (Kubernetes) »Pour les workloads Kubernetes, cert-manager avec le provider Vault est la solution recommandée :
apiVersion: cert-manager.io/v1kind: Issuermetadata: name: vault-issuerspec: vault: # Pour issue (Vault génère la clé) : path "pki_int/issue/webserver" # Pour sign (CSR) : path "pki_int/sign/webserver" path: pki_int/sign/webserver server: https://vault.example.com auth: kubernetes: role: cert-manager mountPath: auth/kubernetesOption 2 : Vault Agent (VM/bare metal)
Section intitulée « Option 2 : Vault Agent (VM/bare metal) »Vault Agent peut gérer le renouvellement automatique :
template { source = "/etc/vault-agent/cert.tpl" destination = "/etc/ssl/certs/myapp/cert.pem" perms = "0644" command = "systemctl reload nginx"}
template { source = "/etc/vault-agent/key.tpl" destination = "/etc/ssl/certs/myapp/key.pem" perms = "0600"}Option 3 : script cron (solution simple)
Section intitulée « Option 3 : script cron (solution simple) »Pour les environnements simples sans Vault Agent :
#!/bin/bashset -e
SERVICE_NAME="myapp"CERT_DIR="/etc/ssl/certs/$SERVICE_NAME"ROLE="webserver"CN="$SERVICE_NAME.example.com"TTL="720h"
mkdir -p "$CERT_DIR"
vault write -format=json "pki_int/issue/$ROLE" \ common_name="$CN" \ ttl="$TTL" | tee \ >(jq -r '.data.certificate' > "$CERT_DIR/cert.pem") \ >(jq -r '.data.private_key' > "$CERT_DIR/key.pem") \ >(jq -r '.data.ca_chain[]' > "$CERT_DIR/ca.pem") \ > /dev/null
chmod 600 "$CERT_DIR/key.pem"systemctl reload nginx
echo "$(date): Certificate renewed for $CN" >> /var/log/cert-renewal.log# Renouveler tous les 25 jours (TTL 30 jours)0 3 */25 * * /opt/scripts/renew-cert.sh >> /var/log/cert-renewal.log 2>&1Ce que Vault PKI ne fait pas tout seul
Section intitulée « Ce que Vault PKI ne fait pas tout seul »| Responsabilité | Vault PKI | Vous |
|---|---|---|
| Générer des certificats | ✅ | — |
| Stocker la clé privée après émission | ❌ | ✅ |
| Distribuer les certificats aux services | ❌ | ✅ |
| Recharger les services (reload nginx, etc.) | ❌ | ✅ |
| Installer la Root CA dans les trust stores | ❌ | ✅ |
| Monitorer les expirations | ❌* | ✅ |
| Garantir la qualité du design PKI | ❌ | ✅ |
*Vault expose des métriques, mais le monitoring est à votre charge.
Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Solution |
|---|---|---|
domain not allowed | CN non autorisé par le rôle | Vérifier allowed_domains du rôle |
TTL exceeds max | TTL demandé > max_ttl du rôle | Réduire le TTL ou augmenter max_ttl |
certificate has expired | Certificat non renouvelé | Vérifier le cron/automation |
unknown authority | CA chain incomplète | Inclure la chaîne complète côté client |
permission denied | Policy manquante | Vérifier les capabilities issue/sign |
unable to fetch CRL | URL CRL inaccessible | Vérifier réseau et DNS |
Debug du certificat
Section intitulée « Debug du certificat »# Voir les dates d'expirationopenssl x509 -in cert.pem -noout -dates
# Voir le CN et SANopenssl x509 -in cert.pem -noout -subject -ext subjectAltName
# Vérifier la chaîne de confianceopenssl verify -CAfile ca-chain.pem cert.pem
# Voir les URLs AIA et CRLopenssl x509 -in cert.pem -noout -text | grep -A2 "Authority Information Access"openssl x509 -in cert.pem -noout -text | grep -A1 "CRL Distribution Points"Bonnes pratiques
Section intitulée « Bonnes pratiques »Architecture
Section intitulée « Architecture »- Root CA hors de Vault : machine air-gapped ou HSM dédié
- Un mount = un niveau :
pkipour la root (si dans Vault),pki_intpour l’intermédiaire - Rotation d’issuer : préparer le nouvel issuer avant expiration de l’ancien
- Un rôle par usage : pas de rôle générique multi-domaines
- TTL courts : 30-90 jours pour les services, 24-72h pour le mTLS
enforce_hostnames=true: toujoursallow_ip_sans=false: sauf besoin explicite documenté
Opérations
Section intitulée « Opérations »- Tidy régulier : nettoyer les certificats expirés/révoqués
- Monitoring : alerter sur les certificats proches de l’expiration
- Audit : tracer toutes les émissions
- Backup : la Root CA est critique, sauvegardez-la séparément
À retenir
Section intitulée « À retenir »- Root CA hors de Vault en production — seule l’intermédiaire est dans Vault
issue: Vault génère clé + cert — simple mais clé en transitsign: client envoie CSR — clé reste locale- Rôles stricts : un rôle par domaine/usage, pas de wildcard global
- URLs accessibles : les CRL et AIA doivent être joignables par les clients
- Multi-issuer : depuis 1.11+, rotation sans interruption possible
- Tidy : nettoyez les métadonnées des certificats expirés
- Vault ≠ distribution : vous restez responsable de l’installation des certificats sur les services