1. Vue d’ensemble
Les secrets (credentials, tokens, passwords) du projet sever-admin sont centralisés, chiffrés et générés dynamiquement via Ansible Vault. Cette approche garantit une single source of truth : les secrets ne sont jamais en clair dans le repository.
1.1. Architecture : Single Source of Truth
┌─────────────────────────────────────────┐
│ Ansible Vault (vault.yml) │
│ ├─ vault_dev_* (développement) │
│ └─ vault_prod_* (production) │
└─────────────────────────────────────────┘
↓ [Détection environnement]
┌─────────────────────────────────────────┐
│ Ansible Templates (.env.*.j2) │
│ Injecte dynamiquement dev ou prod │
└─────────────────────────────────────────┘
↓ [Génération au runtime]
┌─────────────────────────────────────────┐
│ .env (généré) │
│ ⚠️ Jamais commité │
│ ⚠️ Utilisé par docker-compose │
└─────────────────────────────────────────┘
↓
Containers Docker
(variables d'environnement)
1.2. Avantages
-
Centralisé : Un seul fichier source pour tous les secrets
-
Chiffré :
vault.ymlest chiffré avec Ansible Vault -
Dynamique : Pas de .env statique commité
-
Env-aware : Distinction automatique dev/prod
-
Auditabilité : Historique Git complet (chiffré)
-
Pas de désynchronisation : Les variables Vault sont toujours injectées
2. Structure du Vault
Le fichier ansible/inventory/group_vars/all/vault.yml est organisé par environnement.
Chaque secret existe en deux variantes :
- vault_dev_* pour le développement local (ENV=local)
- vault_prod_* pour la production (ENV=remote)
2.1. Exemple de Structure
# ─────── DEVELOPMENT (local, ENV=local) ───────
# Clarajob DDL (PostgreSQL)
vault_dev_clarajob_ddl_db_name: "clarajobdb"
vault_dev_clarajob_ddl_db_user: "dev"
vault_dev_clarajob_ddl_db_pass: "dev"
# Clarajob MongoDB
vault_dev_clarajob_mongo_db_name: "clarajob_mongodb"
vault_dev_clarajob_mongo_db_user: "dev"
vault_dev_clarajob_mongo_db_pass: "dev"
# Marketisia DDL (PostgreSQL PredictX)
vault_dev_marketisia_ddl_db_name: "marketisiadb"
vault_dev_marketisia_ddl_db_user: "dev"
vault_dev_marketisia_ddl_db_pass: "dev"
# Auth Server DB (PostgreSQL Keycloak)
vault_dev_auth_server_db_name: "auth_server_db"
vault_dev_auth_server_db_user: "dev"
vault_dev_auth_server_db_pass: "dev"
# Keycloak Admin
vault_dev_keycloak_admin: "clarajobcontact@gmail.com"
vault_dev_keycloak_admin_password: "admin_pass"
# GitLab Registry
vault_dev_gitlab_registry_token: "gldt-1SeGhN7-WQ4c3oyerAjW"
# ─────── PRODUCTION (remote, ENV=remote) ───────
# Clarajob DDL (PostgreSQL)
vault_prod_clarajob_ddl_db_name: "clarajobdb"
vault_prod_clarajob_ddl_db_user: "clarajob_admin"
vault_prod_clarajob_ddl_db_pass: "PROD_PASSWORD_SECURE"
# Clarajob MongoDB
vault_prod_clarajob_mongo_db_name: "clarajob_mongodb"
vault_prod_clarajob_mongo_db_user: "clarajob_admin"
vault_prod_clarajob_mongo_db_pass: "PROD_PASSWORD_SECURE"
# Marketisia DDL (PostgreSQL PredictX)
vault_prod_marketisia_ddl_db_name: "marketisiadb"
vault_prod_marketisia_ddl_db_user: "marketisia_admin"
vault_prod_marketisia_ddl_db_pass: "PROD_PASSWORD_SECURE"
# Auth Server DB (PostgreSQL Keycloak)
vault_prod_auth_server_db_name: "auth_server_db"
vault_prod_auth_server_db_user: "auth_server_db_admin"
vault_prod_auth_server_db_pass: "zfN2z[j@X%-"
# Keycloak Admin
vault_prod_keycloak_admin: "clarajobcontact@gmail.com"
vault_prod_keycloak_admin_password: "PROD_KEYCLOAK_PASSWORD"
# GitLab Registry
vault_prod_gitlab_registry_token: "gldt-1SeGhN7-WQ4c3oyerAjW"
3. Comment Ça Marche
3.1. Lors d’un Déploiement
Exemple : make deploy APP=auth_server_db
1. Ansible détecte l'environnement
└─ ENV=remote (production) ou ENV=local (développement)
2. Pre-deploy task génère le .env
├─ Si production → injecte vault_prod_* dans .env
└─ Si local → injecte vault_dev_* dans .env
3. Docker Compose lit le .env généré
└─ Les containers reçoivent les bonnes variables d'env
4. Le .env est généré au runtime, jamais commité
└─ Chaque déploiement = nouveau .env généré depuis Vault
3.2. Exemple Concret
Production (serveur distant)
$ make deploy APP=auth_server_db
# → Détecte ENV=remote (production)
# → Injecte vault_prod_auth_server_db_pass = "zfN2z[j@X%-"
# → Génère .env avec AUTH_SERVER_DB_PASSWORD=zfN2z[j@X%-
# → Docker démarre avec les vrais credentials
# → .env est supprimé ou non commité
Développement (machine locale)
$ ENV=local make deploy APP=auth_server_db
# → Détecte ENV=local (développement)
# → Injecte vault_dev_auth_server_db_pass = "dev"
# → Génère .env avec AUTH_SERVER_DB_PASSWORD=dev
# → Docker démarre avec credentials dev
4. Gestion des Secrets
4.1. Mot de Passe Vault
Le mot de passe qui chiffre vault.yml est stocké en dehors du repo :
~/.vault_sever_admin
chmod 600 ~/.vault_sever_admin
Ce fichier n’est jamais commité. Il est utilisé par Ansible pour déchiffrer vault.yml à la volée.
4.2. Voir les Secrets (Déchiffrement Temporaire)
ansible-vault view ansible/inventory/group_vars/all/vault.yml \
--vault-password-file ~/.vault_sever_admin
4.3. Modifier les Secrets
Méthode 1 : Déchiffrer → Éditer → Rechiffrer (CLI)
# Déchiffrer
ansible-vault decrypt ansible/inventory/group_vars/all/vault.yml \
--vault-password-file ~/.vault_sever_admin
# Éditer avec votre éditeur préféré
vim ansible/inventory/group_vars/all/vault.yml
# Rechiffrer
ansible-vault encrypt ansible/inventory/group_vars/all/vault.yml \
--vault-password-file ~/.vault_sever_admin
Méthode 2 : Ansible Vault Editor (interactif)
# Note: Ne fonctionne que si ~/.vault_sever_admin est accessible
# Cette méthode n'est pas recommandée en CI/CD
# ansible-vault edit ansible/inventory/group_vars/all/vault.yml \
# --vault-password-file ~/.vault_sever_admin
4.4. Changer le Mot de Passe Vault
ansible-vault rekey ansible/inventory/group_vars/all/vault.yml \
--vault-password-file ~/.vault_sever_admin
# Vous serez demandé pour le nouveau mot de passe deux fois
5. Cas d’Usage : Ajouter un Nouveau Secret
Supposons que tu veux ajouter un credential pour une nouvelle base de données Redis.
5.1. Étape 1 : Ajouter au Vault
ansible-vault decrypt ansible/inventory/group_vars/all/vault.yml \
--vault-password-file ~/.vault_sever_admin
Ajouter dans le fichier :
# Redis - Développement
vault_dev_redis_host: "redis"
vault_dev_redis_port: "6379"
vault_dev_redis_password: ""
# Redis - Production
vault_prod_redis_host: "redis.internal"
vault_prod_redis_port: "6379"
vault_prod_redis_password: "PROD_REDIS_PASSWORD"
Puis rechiffrer :
ansible-vault encrypt ansible/inventory/group_vars/all/vault.yml \
--vault-password-file ~/.vault_sever_admin
5.2. Étape 2 : Utiliser dans les Templates Ansible
Ajouter dans ansible/templates/.env.databases.j2 :
# Redis
REDIS_HOST={{ vault_redis_host }}
REDIS_PORT={{ vault_redis_port }}
REDIS_PASSWORD={{ vault_redis_password }}
5.3. Étape 3 : Mettre à Jour le Playbook Deploy
Dans ansible/playbooks/deploy.yml, ajouter une pré-task (ou augmenter la pré-task existante) :
- name: "Générer .env.databases depuis les secrets du vault"
template:
src: "{{ playbook_dir }}/../templates/.env.databases.j2"
dest: "{{ mon_projet_dir }}/.env"
owner: admin
group: admin
mode: '0600'
vars:
vault_redis_host: "{{ vault_prod_redis_host if ansible_environment_type == 'production' else vault_dev_redis_host }}"
vault_redis_port: "{{ vault_prod_redis_port if ansible_environment_type == 'production' else vault_dev_redis_port }}"
vault_redis_password: "{{ vault_prod_redis_password if ansible_environment_type == 'production' else vault_dev_redis_password }}"
no_log: true
5.4. Étape 4 : Utiliser dans docker-compose.yml
services:
redis:
image: redis:7-alpine
ports:
- "${REDIS_PORT}:6379"
environment:
REDIS_PASSWORD: ${REDIS_PASSWORD}
command: redis-server --requirepass ${REDIS_PASSWORD}
5.5. Étape 5 : Tester
# Développement
ENV=local make deploy APP=mon-app
# → REDIS_PASSWORD='' (vide)
# Production
make deploy APP=mon-app
# → REDIS_PASSWORD=PROD_REDIS_PASSWORD
6. Secrets Externalisés (Repo security/env)
En plus du Vault chiffré, les secrets en clair sont stockés dans un repo séparé pour faciliter la collaboration :
/media/multi2/projects/app/security/env/
├── local/server-admin/
│ ├── .env.auth-server.local
│ ├── .env.databases.local
│ └── .env.infra-and-ansible.local
└── prod/server-admin/
├── .env.auth-server.prod
├── .env.databases.prod
└── .env.infra-and-ansible.prod
Purpose : Ce repo security est séparé et sécurisé, il ne contient que les secrets (pas le code applicatif).
|
Note
|
Le repo |
7. Règles de Sécurité
|
Important
|
|
8. Audit Trail & Historique
Le Vault est versionné dans Git (chiffré) — tu peux tracer les modifications :
# Voir l'historique des modifications du vault
git log ansible/inventory/group_vars/all/vault.yml
# Voir ce qui a changé (reste chiffré)
git diff HEAD~1 ansible/inventory/group_vars/all/vault.yml
# Identifier qui a modifié quoi
git log -p --author=ulrich ansible/inventory/group_vars/all/vault.yml
Même chiffré, tu peux identifier : - Qui a changé - Quand - Le message du commit
8.1. Rotation de Password Exemple
Scénario : auth_server_db_pass est compromis
# 1. Changer le password sur le serveur
ssh -i ~/.ssh/serverAdminSSHKeypair.pem admin@18.158.207.98 \
"docker exec auth_server_db psql -U admin -d auth_server_db \
-c \"ALTER ROLE auth_server_db_admin WITH PASSWORD 'new_secure_password';\""
# 2. Mettre à jour le vault
ansible-vault decrypt ansible/inventory/group_vars/all/vault.yml \
--vault-password-file ~/.vault_sever_admin
# Éditer:
# vault_prod_auth_server_db_pass: "new_secure_password"
ansible-vault encrypt ansible/inventory/group_vars/all/vault.yml \
--vault-password-file ~/.vault_sever_admin
# 3. Commiter
git add ansible/inventory/group_vars/all/vault.yml
git commit -m "security: rotate auth_server_db_admin password (CVE-2026-xxxxx)"
# 4. Déployer
make deploy APP=auth_server_db
9. Troubleshooting
9.1. "Decryption failed"
# Vérifier le password file
cat ~/.vault_sever_admin
# Doit contenir le password exact, sans espace ni retour à la ligne
# Sinon, réinitialiser :
echo "CORRECT_PASSWORD" > ~/.vault_sever_admin
chmod 600 ~/.vault_sever_admin
9.2. "vault_prod_* variables not found"
# Vérifier que vault.yml est chiffré
file ansible/inventory/group_vars/all/vault.yml
# Doit afficher: "ASCII text" si bien chiffré
# Si c'est du texte brut, rechiffrer :
ansible-vault encrypt ansible/inventory/group_vars/all/vault.yml \
--vault-password-file ~/.vault_sever_admin
9.3. "Template generation failed"
# Vérifier que les templates existent
ls -la ansible/templates/.env.*.j2
# Vérifier que le playbook utilise les bonnes variables
ansible-vault view ansible/inventory/group_vars/all/vault.yml \
--vault-password-file ~/.vault_sever_admin | grep -E "vault_(dev|prod)_"
10. Templates Ansible Fournis
Le projet inclut 3 templates par défaut :
| Template | Rôle | Variables |
|---|---|---|
|
Auth Server + Keycloak |
|
|
Toutes les BDs |
|
|
Infrastructure |
|
Chaque template injecte dynamiquement les secrets via les variables vault_dev_* ou vault_prod_* selon l’environnement.
11. Intégration CI/CD
11.1. Jenkins
Le credential Jenkins VAULT_PASSWORD_FILE (type: Secret file) contient le mot de passe vault.
// Dans le Jenkinsfile
withCredentials([file(credentialsId: 'VAULT_PASSWORD_FILE', variable: 'VAULT_PASS')]) {
sh '''
cp $VAULT_PASS ~/.vault_sever_admin
chmod 600 ~/.vault_sever_admin
make deploy APP=clarajob-sa
'''
}
11.2. Semaphore / Rundeck
Ces outils n’ont besoin que de l’adresse du Vault password file — Ansible gère le reste.
12. Bonnes Pratiques Résumées
| Pratique | Détail | Fréquence |
|---|---|---|
Rotation de secrets |
Changer les passwords tous les 90 jours |
Trimestriel |
Audit des accès |
Qui a consulté/modifié les secrets |
Après chaque changement |
Backup du vault password |
Sauvegarder |
Une fois, jamais modifier |
Documentation |
Ajouter un commentaire pour chaque nouveau secret |
À chaque ajout |
Test dev/prod |
Tester le déploiement en dev avant prod |
À chaque changement de secret |
13. Ressources Supplémentaires
-
Fichiers mentionnés :
-
ansible/inventory/group_vars/all/vault.yml(chiffré) -
ansible/templates/.env.*.j2 -
ansible/playbooks/deploy.yml -
.gitignore
-
Dernière mise à jour : 2026-08-13 Auteur : DevOps Team