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
- Consultez l'installation de Vault
- Découvrez le cluster Vault HA
- Intégrez-le avec Keycloak
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


