Skip to main content

Déploiement du Vault

#

Déploiement HashiCorp Vault avec Podman Rootless

##

Architecture

Architecture

    - **Système**

  • Système : AlmaLinux (RHEL-based)
    -
  • **
  • Container Engine**Engine : Podman (rootless)
    -
  • **Stockage**
  • Stockage : Raft (backend intégré HA)
    -
  • **Sécurité**
  • Sécurité : SELinux activé
    -
  • **
  • Reverse Proxy**Proxy : Nginx avec Let's Encrypt

  • ---

##


Déploiement - Guide Complet

###

1. Préparation des volumes
```bash

# 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
```bash

# 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
```bash

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
```bash

# Vérifier les logs
podman logs vault

# Vérifier le statut
podman ps
```

###

5. Initialiser Vault
```bash

# 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
```bash

# À chaque démarrage du conteneur
vault operator unseal <UNSEAL_KEY>

# Vérifier le statut
vault status
```

###

7. Configuration de l'authentification AppRole
```bash

# 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
```bash

# 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
```bash

# 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)
```bash

# Créer le fichier de configuration Nginx
sudo nano /etc/nginx/conf.d/vault.conf
```
```nginx
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";
      }
}
```
```bash

# Tester la configuration Nginx
sudo nginx -t

# Recharger Nginx
sudo systemctl reload nginx
```

###

11. Expansion du certificat Let's Encrypt
```bash

# 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
```bash

# 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)
```bash

# 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
```bash

# 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`

run

**Problème**Problème : Les options `-v`v placées après l'image étaient interprétées comme arguments du conteneur.

**Solution**Solution : Placer tous les arguments AVANT le nom de l'image.
```bash

# ❌ 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**Problème
```

Error: lsetxattr(label=system_u:object_r:container_file_t:s0) /var/lib/vault: operation not permitted
```

**Cause**Cause : En Podman rootless, impossible de relabeler des dossiers dans `/var/lib/` (appartiennent à root).

**Solutions**Solutions :

**Option A - Volumes nommés (recommandé)** :
```bash

podman volume create vault_data
podman run -v vault_data:/vault/file ...
# SELinux géré automatiquement
```

**Option B - Bind mount avec relabeling manuel**manuel :
```bash

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**Problème : Fichiers créés avec des UIDs étranges (524287, 525287).

**Cause**Cause : Podman rootless mappe les UIDs du conteneur vers un range d'UIDs sur l'hôte.

**Explication**Explication :
```bash

# Vérifier le mapping
cat /etc/subuid | grep username
# username:524288:65536

# UID conteneur 999 → UID hôte 524288 + 999 = 525287
```

**Solution**Solution : Normal et voulu pour l'isolation. Utiliser `podman unshare`unshare si besoin d'interagir :
```bash

podman unshare ls -lah /path/to/volume
```

---

###


4. Vault nécessite `cluster_addr`cluster_addr avec Raft

Problème :

**Problème** :
```

Error: Cluster address must be set when using raft storage
```

**Solution**Solution : Configuration Raft complète obligatoire :
```hcl

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**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 :

**Problème** :
```

Error: http: server gave HTTP response to HTTPS client
```

**Cause**Cause : `VAULT_ADDR`VAULT_ADDR par défaut en HTTPS mais Vault configuré en HTTP (`tls_disable = true`true).

**Solution**Solution :
```bash

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 :

**Problème** :
```

Error reading auth/approle/role/admin/role-id: permission denied
```

**Cause**Cause : Tentative de lecture sans être authentifié.

**Solution**Solution :
```bash

# 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**Problème : Création d'une auth method sur `auth/admin/` au lieu d'utiliser `auth/approle/`.

**Solution**Solution :
```bash

# ❌ 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**correct : `auth/approle/role/<role_name>`

---


###

8. UI Web - Scroll bloqué

**Problème**Problème : Impossible de scroller dans l'interface web Vault.

**Solutions**Solutions :
```javascript

// DevTools Console (F12)
document.body.style.overflow = 'auto';
```

Ou :
-

  • Changer de navigateur (Firefox ↔ Chrome)
    -
  • Zoom out (Ctrl + -)
    -
  • Utiliser le CLI (plus efficace de toute façon)

  • ---

###


9. AppRole non visible dans l'UI de login

**Problème**Problème : Seule l'option "Token" apparaît dans l'UI de connexion.

**Solution**Solution : Activer la visibilité de l'auth method :
```bash

vault write sys/auth/approle/tune listing_visibility="unauth"
```

**Alternative**Alternative : Utiliser le token généré par AppRole via CLI :
```bash

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 :

**Problème** :
```

cannot load certificate: Permission denied
```

**Cause**Cause : Après renouvellement Certbot, les nouveaux fichiers ont le mauvais contexte SELinux.

**Solution**Solution :
```bash

# 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
```bash

export VAULT_ADDR='http://127.0.0.1:8200'
vault operator unseal <UNSEAL_KEY>
```

###

Vérifier le statut
```bash

vault status
podman logs vault
podman ps -a
```

###

Backup des données Vault
```bash

# 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
```bash

# Générer un nouveau SecretID
vault write -f -field=secret_id auth/approle/role/admin/secret-id
```

###

Gestion des logs
```bash

# 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é**
    -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**
    -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

  • ---

##


Ressources

-