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 »Pour lire la chaîne, le SNI, les dates de validité et le code de vérification d'un certificat émis, le guide diagnostic TLS avec openssl détaille chaque commande openssl.
# 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