Déploiement du Vault
Déploiement HashiCorp Vault avec Podman Rootless
Architecture
- Système : AlmaLinux (RHEL-based)
- Container Engine : Podman (rootless)
- Stockage : Raft (backend intégré HA)
- Sécurité : SELinux activé
- Reverse Proxy : Nginx avec Let's Encrypt
Déploiement - Guide Complet
1. Préparation des volumes
# Créer les volumes nommés (recommandé pour Podman rootless)
podman volume create vault_config
podman volume create vault_data
2. Créer le fichier de configuration Vault
# Monter temporairement le volume config
podman volume mount vault_config
# Créer vault.hcl
cat > $(podman volume mount vault_config)/vault.hcl << 'EOF'
disable_cache = true
disable_mlock = true
ui = true
max_lease_ttl = "2h"
default_lease_ttl = "20m"
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = true
}
storage "raft" {
path = "/vault/file"
node_id = "vault-1"
}
api_addr = "http://127.0.0.1:8200"
cluster_addr = "https://127.0.0.1:8201"
EOF
# Démonter le volume
podman volume unmount vault_config
3. Démarrer le conteneur Vault
podman run -d \
--name vault \
-p 8200:8200 \
-p 8201:8201 \
--cap-add=IPC_LOCK \
-v vault_config:/vault/config \
-v vault_data:/vault/file \
docker.io/hashicorp/vault server
4. Vérifier le démarrage
# Vérifier les logs
podman logs vault
# Vérifier le statut
podman ps
5. Initialiser Vault
# Définir l'adresse Vault
export VAULT_ADDR='http://127.0.0.1:8200'
# Initialiser avec 1 clé (configuration single-admin)
vault operator init -key-shares=1 -key-threshold=1
# ⚠️ IMPORTANT : Sauvegarder immédiatement dans un password manager :
# - Unseal Key
# - Initial Root Token
6. Unsealer Vault
# À chaque démarrage du conteneur
vault operator unseal <UNSEAL_KEY>
# Vérifier le statut
vault status
7. Configuration de l'authentification AppRole
# Login avec le root token
vault login <ROOT_TOKEN>
# Activer AppRole
vault auth enable approle
# Créer la policy admin
vault policy write admin - << 'EOF'
path "*" {
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}
EOF
# Créer le rôle AppRole
vault write auth/approle/role/admin \
token_policies="admin" \
token_ttl=1h \
token_max_ttl=4h
8. Récupérer les credentials AppRole
# Récupérer le RoleID (permanent)
ROLE_ID=$(vault read -field=role_id auth/approle/role/admin/role-id)
echo "RoleID: $ROLE_ID"
# Générer un SecretID (temporaire, à regénérer)
SECRET_ID=$(vault write -f -field=secret_id auth/approle/role/admin/secret-id)
echo "SecretID: $SECRET_ID"
# Sauvegarder le RoleID
echo "$ROLE_ID" > ~/.vault-role-id
9. Login avec AppRole
# Login et récupération du token
vault write auth/approle/login \
role_id="$ROLE_ID" \
secret_id="$SECRET_ID"
# Ou directement exporter le token
export VAULT_TOKEN=$(vault write -field=token auth/approle/login \
role_id="$ROLE_ID" \
secret_id="$SECRET_ID")
10. Configuration Nginx (Reverse Proxy avec SSL)
# Créer le fichier de configuration Nginx
sudo nano /etc/nginx/conf.d/vault.conf
upstream vault_backend {
server 127.0.0.1:8200;
}
server {
listen 80;
server_name vault.example.com;
# Redirection HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name vault.example.com;
# Certificats SSL Let's Encrypt
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Configuration SSL moderne
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Headers de sécurité
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
# Proxy vers Vault
location / {
proxy_pass http://vault_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support (pour l'UI)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
# Tester la configuration Nginx
sudo nginx -t
# Recharger Nginx
sudo systemctl reload nginx
11. Expansion du certificat Let's Encrypt
# Ajouter le sous-domaine vault au certificat existant
sudo certbot certonly --nginx \
-d example.com \
-d www.example.com \
-d vault.example.com \
--expand
# Vérifier le renouvellement automatique
sudo certbot renew --dry-run
12. Gestion SELinux pour les certificats
# Restaurer le contexte SELinux correct
sudo restorecon -Rv /etc/letsencrypt
# Rendre la configuration permanente
sudo semanage fcontext -a -t httpd_sys_content_t "/etc/letsencrypt(/.*)?"
sudo restorecon -Rv /etc/letsencrypt
13. Service Systemd (optionnel - pour auto-start)
# Générer le fichier systemd
podman generate systemd --new --name vault > ~/.config/systemd/user/vault.service
# Activer au démarrage
systemctl --user enable vault.service
systemctl --user start vault.service
# Activer le linger (conteneur démarre même si user pas connecté)
sudo loginctl enable-linger $USER
14. Script de login rapide
# Créer un script de connexion
cat > ~/vault-login.sh << 'EOF'
#!/bin/bash
export VAULT_ADDR='http://127.0.0.1:8200'
ROLE_ID=$(cat ~/.vault-role-id)
SECRET_ID=$(vault write -f -field=secret_id auth/approle/role/admin/secret-id)
export VAULT_TOKEN=$(vault write -field=token auth/approle/login \
role_id="$ROLE_ID" \
secret_id="$SECRET_ID")
echo "✅ Logged in to Vault"
vault token lookup
EOF
chmod +x ~/vault-login.sh
# Utilisation
source ~/vault-login.sh
Problèmes Rencontrés et Solutions
1. Ordre des arguments dans podman run
Problème : Les options -v placées après l'image étaient interprétées comme arguments du conteneur.
Solution : Placer tous les arguments AVANT le nom de l'image.
# ❌ Incorrect
podman run -d --name vault image -v /path:/path
# ✅ Correct
podman run -d --name vault -v /path:/path image
2. Permissions SELinux avec bind mounts
Problème :
Error: lsetxattr(label=system_u:object_r:container_file_t:s0) /var/lib/vault: operation not permitted
Cause : En Podman rootless, impossible de relabeler des dossiers dans /var/lib/ (appartiennent à root).
Solutions :
Option A - Volumes nommés (recommandé) :
podman volume create vault_data
podman run -v vault_data:/vault/file ...
# SELinux géré automatiquement
Option B - Bind mount avec relabeling manuel :
sudo chown -R $(id -u):$(id -g) /var/lib/vault
sudo chcon -R -t container_file_t /var/lib/vault
sudo semanage fcontext -a -t container_file_t "/var/lib/vault(/.*)?"
podman run -v /var/lib/vault:/vault/file ... # Sans :Z
3. User namespace et UID mapping
Problème : Fichiers créés avec des UIDs étranges (524287, 525287).
Cause : Podman rootless mappe les UIDs du conteneur vers un range d'UIDs sur l'hôte.
Explication :
# Vérifier le mapping
cat /etc/subuid | grep username
# username:524288:65536
# UID conteneur 999 → UID hôte 524288 + 999 = 525287
Solution : Normal et voulu pour l'isolation. Utiliser podman unshare si besoin d'interagir :
podman unshare ls -lah /path/to/volume
4. Vault nécessite cluster_addr avec Raft
Problème :
Error: Cluster address must be set when using raft storage
Solution : Configuration Raft complète obligatoire :
storage "raft" {
path = "/vault/file"
node_id = "vault-1"
}
api_addr = "http://127.0.0.1:8200"
cluster_addr = "https://127.0.0.1:8201" # Port 8201 pour le cluster
Note :
- Port 8200 = API/UI
- Port 8201 = Communication inter-nœuds (même en single-node)
5. HTTPS vs HTTP - Erreur de connexion
Problème :
Error: http: server gave HTTP response to HTTPS client
Cause : VAULT_ADDR par défaut en HTTPS mais Vault configuré en HTTP (tls_disable = true).
Solution :
export VAULT_ADDR='http://127.0.0.1:8200'
# Ou ajouter au .bashrc
echo 'export VAULT_ADDR="http://127.0.0.1:8200"' >> ~/.bashrc
6. Permission denied - Authentification manquante
Problème :
Error reading auth/approle/role/admin/role-id: permission denied
Cause : Tentative de lecture sans être authentifié.
Solution :
# Se connecter d'abord
vault login <ROOT_TOKEN>
# Puis exécuter la commande
vault read auth/approle/role/admin/role-id
7. Confusion entre auth method path et role path
Problème : Création d'une auth method sur auth/admin/ au lieu d'utiliser auth/approle/.
Solution :
# ❌ Incorrect - Création d'une nouvelle auth method
vault auth enable -path=admin approle
# ✅ Correct - Utiliser l'auth method standard
vault auth enable approle
vault write auth/approle/role/admin ...
Path correct : auth/approle/role/<role_name>
8. UI Web - Scroll bloqué
Problème : Impossible de scroller dans l'interface web Vault.
Solutions :
// DevTools Console (F12)
document.body.style.overflow = 'auto';
Ou :
9. AppRole non visible dans l'UI de login
Problème : Seule l'option "Token" apparaît dans l'UI de connexion.
Solution : Activer la visibilité de l'auth method :
vault write sys/auth/approle/tune listing_visibility="unauth"
Alternative : Utiliser le token généré par AppRole via CLI :
TOKEN=$(vault write -field=token auth/approle/login role_id="..." secret_id="...")
# Login UI avec ce token
10. Certificats Let's Encrypt et SELinux
Problème :
cannot load certificate: Permission denied
Cause : Après renouvellement Certbot, les nouveaux fichiers ont le mauvais contexte SELinux.
Solution :
# Quick fix
sudo restorecon -Rv /etc/letsencrypt
# Permanent fix
sudo semanage fcontext -a -t httpd_sys_content_t "/etc/letsencrypt(/.*)?"
sudo restorecon -Rv /etc/letsencrypt
# Tester Nginx
sudo nginx -t
Commandes de Maintenance
Unseal après redémarrage
export VAULT_ADDR='http://127.0.0.1:8200'
vault operator unseal <UNSEAL_KEY>
Vérifier le statut
vault status
podman logs vault
podman ps -a
Backup des données Vault
# Backup du volume
podman volume export vault_data > vault_data_backup.tar
# Ou copie directe
cp -r ~/.local/share/containers/storage/volumes/vault_data/_data /backup/vault/
Rotation du SecretID AppRole
# Générer un nouveau SecretID
vault write -f -field=secret_id auth/approle/role/admin/secret-id
Gestion des logs
# Voir les logs
podman logs vault
# Suivre les logs en temps réel
podman logs -f vault
# Dernières 100 lignes
podman logs --tail 100 vault
Concepts Clés
Raft Storage
- Backend de stockage HA intégré
- Algorithme de consensus distribué
- Permet plusieurs nœuds Vault synchronisés
- Pas besoin de base externe (Consul, MySQL, etc.)
- Recommandé par HashiCorp
AppRole Authentication
- Méthode d'auth pour machines/applications
- RoleID : identifiant permanent du rôle
- SecretID : credential temporaire/éphémère
- Idéal pour automation, CI/CD, scripts
- Plus secure que userpass pour l'automation
Unseal/Seal
- Vault démarre "sealed" (verrouillé)
- Données chiffrées, inaccessibles
- Unseal = déverrouiller avec la clé
- Nécessaire après chaque redémarrage
- Protège contre le vol de disque
Podman Rootless
- Conteneurs sans privilèges root
- User namespaces pour isolation
- Meilleure sécurité que Docker classique
- Compatible avec SELinux