Sécurité
DevOps
Secrets

Gestion des secrets avec HashiCorp Vault en production

15 janvier 2026

3 min de lecture

HashiCorp Vault centralise et sécurise la gestion des secrets : API keys, passwords, certificats TLS. Guide de déploiement en production avec HA et auto-unseal.

Ressources complémentaires

Installation

# Télécharger Vault
wget https://releases.hashicorp.com/vault/1.17.3/vault_1.17.3_linux_amd64.zip
unzip vault_1.17.3_linux_amd64.zip
mv vault /usr/local/bin/

# Créer utilisateur
useradd --system --home /etc/vault.d --shell /bin/false vault

Configuration

# /etc/vault.d/vault.hcl
storage "raft" {
  path = "/opt/vault/data"
  node_id = "vault-1"
}

listener "tcp" {
  address     = "0.0.0.0:8200"
  tls_cert_file = "/etc/vault.d/tls/cert.pem"
  tls_key_file  = "/etc/vault.d/tls/key.pem"
}

api_addr = "https://vault.example.com:8200"
cluster_addr = "https://10.0.1.10:8201"
ui = true

Initialisation

# Init avec 5 clés, seuil de 3
vault operator init -key-shares=5 -key-threshold=3

# Unseal (3 clés différentes)
vault operator unseal <key1>
vault operator unseal <key2>
vault operator unseal <key3>

# Login avec root token
vault login <root_token>

Secrets engines

# KV secrets v2
vault secrets enable -path=secret kv-v2

# Stocker un secret
vault kv put secret/myapp/db \
  username=dbuser \
  password=super_secret

# Lire
vault kv get secret/myapp/db

# Dynamic secrets PostgreSQL
vault secrets enable database

vault write database/config/postgresql \
  plugin_name=postgresql-database-plugin \
  allowed_roles="readonly" \
  connection_url="postgresql://{{username}}:{{password}}@localhost:5432/mydb" \
  username="vault" \
  password="vault_password"

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

# Obtenir des credentials dynamiques (expiration auto)
vault read database/creds/readonly

PKI (certificats TLS)

# Enable PKI
vault secrets enable pki
vault secrets tune -max-lease-ttl=87600h pki

# Générer CA root
vault write -field=certificate pki/root/generate/internal \
  common_name="Example Inc Root CA" \
  ttl=87600h > CA_cert.crt

# Configure CA et CRL
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"

# Créer un role
vault write pki/roles/example-dot-com \
  allowed_domains="example.com" \
  allow_subdomains=true \
  max_ttl="720h"

# Générer un certificat
vault write pki/issue/example-dot-com \
  common_name="app.example.com" \
  ttl="24h"

Policies et authentification

# myapp-policy.hcl
path "secret/data/myapp/*" {
  capabilities = ["read"]
}

path "database/creds/readonly" {
  capabilities = ["read"]
}
# Créer policy
vault policy write myapp myapp-policy.hcl

# AppRole auth
vault auth enable approle

vault write auth/approle/role/myapp \
  token_policies="myapp" \
  token_ttl=1h \
  token_max_ttl=4h

# Obtenir RoleID et SecretID
vault read auth/approle/role/myapp/role-id
vault write -f auth/approle/role/myapp/secret-id

# Login depuis l'app
vault write auth/approle/login \
  role_id="..." \
  secret_id="..."

Auto-unseal avec Cloud KMS

# AWS KMS
seal "awskms" {
  region     = "us-east-1"
  kms_key_id = "alias/vault-unseal-key"
}

# GCP KMS
seal "gcpckms" {
  project     = "my-project"
  region      = "global"
  key_ring    = "vault"
  crypto_key  = "vault-key"
}

Intégration Kubernetes

# Enable K8s auth
vault auth enable kubernetes

vault write auth/kubernetes/config \
  kubernetes_host="https://k8s.example.com:6443" \
  kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
  token_reviewer_jwt=@/var/run/secrets/kubernetes.io/serviceaccount/token

# Policy pour une app
vault write auth/kubernetes/role/myapp \
  bound_service_account_names=myapp \
  bound_service_account_namespaces=production \
  policies=myapp \
  ttl=1h

Pod annotation :

apiVersion: v1
kind: Pod
metadata:
  annotations:
    vault.hashicorp.com/agent-inject: 'true'
    vault.hashicorp.com/role: 'myapp'
    vault.hashicorp.com/agent-inject-secret-db: 'secret/data/myapp/db'
spec:
  serviceAccountName: myapp
Besoin d'aide sur ce sujet ?

Notre équipe d'experts est là pour vous accompagner dans vos projets d'infrastructure et d'infogérance.

Contactez-nous

Articles similaires