Aller au contenu
Infrastructure as Code medium

Playbooks mixtes : main.yml + vault.yml par groupe avec convention vault_*

11 min de lecture

Logo Ansible

La meilleure structure pour un projet Ansible mature : pour chaque groupe d’inventaire, deux fichiers côte à côte — main.yml qui contient les variables publiques (port, version, environnement) et vault.yml qui contient uniquement les secrets (chiffré complet). Ansible les fusionne automatiquement, et la convention vault_* rend la sensibilité visible dans le code.

À la fin, vous saurez structurer un group_vars/ industriel, garder des diffs Git lisibles sur les variables publiques, et limiter le périmètre du mot de passe vault aux modifications réellement sensibles.

  • Pattern group_vars/<groupe>/main.yml + vault.yml : structure et règles de fusion.
  • Convention de nommage vault_* pour distinguer visuellement une variable sensible.
  • Fusion automatique par Ansible : les deux fichiers forment un seul namespace.
  • Diff Git : pourquoi cette structure produit des diffs lisibles.
  • Lecture sans déchiffrer : qui peut lire main.yml sans avoir le mot de passe vault.
  • Rotation localisée : ne rote que les vault.yml du groupe concerné.
inventory/
├── hosts.yml
└── group_vars/
├── all/
│ ├── main.yml ← variables publiques partagées (clair)
│ └── vault.yml ← secrets partagés (CHIFFRÉ COMPLET)
├── webservers/
│ ├── main.yml ← config publique webservers (clair)
│ └── vault.yml ← secrets webservers (CHIFFRÉ COMPLET)
└── dbservers/
├── main.yml
└── vault.yml

Règle d’or : pour un groupe donné, Ansible fusionne automatiquement tous les fichiers YAML présents dans group_vars/<groupe>/. Un host de webservers voit donc :

  • les variables de all/main.yml + all/vault.yml (héritage)
  • les variables de webservers/main.yml + webservers/vault.yml (spécifique)

Convention : préfixer les variables vault par vault_* (ex: vault_admin_token, vault_db_password, vault_web_secret). Permet un coup d’œil rapide pour repérer les valeurs sensibles dans tout le code.

Pourquoi pas un seul fichier complètement chiffré

Section intitulée « Pourquoi pas un seul fichier complètement chiffré »

Trois inconvénients du fichier unique chiffré :

  • Diffs Git illisibles : modifier http_port: 808080 produit un blob hex aléatoire de 200 lignes. Impossible à reviewer.
  • Périmètre vault élargi : ajouter une variable publique demande le mot de passe.
  • Lecture en revue : impossible de comprendre la config sans déchiffrer.

Le pattern mixte résout les trois en mettant la frontière claire/chiffré au niveau du fichier, pas au niveau de la variable.

Fenêtre de terminal
cd labs/vault/playbooks-mixtes/
mkdir -p inventory/group_vars/all
mkdir -p inventory/group_vars/webservers
# all/main.yml — variables PUBLIQUES partagées
cat > inventory/group_vars/all/main.yml <<'EOF'
deployment_environment: lab80
EOF
# webservers/main.yml — config publique
cat > inventory/group_vars/webservers/main.yml <<'EOF'
http_port: 80
worker_count: 4
EOF

Ces fichiers restent en clair. On peut les cat, les diff, les commiter sans souci.

Fenêtre de terminal
# all/vault.yml — secrets PARTAGÉS
cat > inventory/group_vars/all/vault.yml <<'EOF'
vault_admin_token: "lab80-admin-token-2026"
EOF
# webservers/vault.yml — secrets WEBSERVERS
cat > inventory/group_vars/webservers/vault.yml <<'EOF'
vault_web_secret: "web_secret_lab80_xyz"
vault_web_db_password: "WebDbPassLab80!"
EOF

Pour l’instant non chiffrés. On va les chiffrer dans l’étape suivante.

Convention vault_* : toutes les variables sensibles sont préfixées. Un grep rapide (grep -r "vault_" .) liste tous les secrets utilisés dans le projet.

Fenêtre de terminal
ansible-vault encrypt \
inventory/group_vars/all/vault.yml \
inventory/group_vars/webservers/vault.yml \
--vault-password-file=.vault_password

Vérifier :

Fenêtre de terminal
head -1 inventory/group_vars/all/vault.yml
# → $ANSIBLE_VAULT;1.1;AES256
head -1 inventory/group_vars/webservers/main.yml
# → http_port: 80 (clair, intact)

Le playbook ne fait aucune distinction entre variables claires et chiffrées. Ansible s’occupe de tout.

playbook.yml
- name: Lab 80 — Playbook mixte
hosts: webservers
become: true
gather_facts: false
tasks:
- name: Pose un fichier qui combine variables claires et chiffrées
ansible.builtin.copy:
dest: /tmp/lab80-mixte.txt
mode: "0600"
content: |
=== Lab 80 — playbook mixte ===
Variables PUBLIQUES (group_vars/<group>/main.yml) :
deployment_environment: {{ deployment_environment }}
http_port: {{ http_port }}
worker_count: {{ worker_count }}
Secrets CHIFFRÉS (group_vars/<group>/vault.yml) :
vault_admin_token starts: {{ vault_admin_token[:5] }}
vault_web_secret starts: {{ vault_web_secret[:5] }}
vault_web_db_password length: {{ vault_web_db_password | length }}
Fenêtre de terminal
ansible-playbook -i inventory/hosts.yml \
--vault-password-file=.vault_password \
playbook.yml

Vérifier côté cible :

Fenêtre de terminal
ssh ansible@web1.lab "sudo cat /tmp/lab80-mixte.txt"

Sortie : 6 variables accessibles transparentement depuis un seul namespace, dont 3 chiffrées et 3 claires. La {{ var }} est strictement la même syntaxe pour les deux.

Modifier le port HTTP :

Fenêtre de terminal
sed -i 's/http_port: 80/http_port: 8080/' inventory/group_vars/webservers/main.yml
git diff

Sortie :

http_port: 80
http_port: 8080

Une ligne diffable, immédiatement compréhensible en revue de code. Avec un fichier unique chiffré, le diff aurait montré un blob hex de 100+ lignes.

Un développeur qui n’a pas le mot de passe vault peut quand même lire :

Fenêtre de terminal
cat inventory/group_vars/webservers/main.yml
# → http_port: 8080
# → worker_count: 4

Il comprend la config, peut proposer des changements sur les variables publiques (worker_count: 8 par exemple), sans accès aux secrets. Le périmètre du mot de passe vault est limité aux personnes qui doivent réellement modifier les secrets.

Compromission suspectée des secrets webservers uniquement ?

Fenêtre de terminal
# Modifier seul vault.yml de webservers, ignorer all/
ansible-vault edit inventory/group_vars/webservers/vault.yml \
--vault-password-file=.vault_password
# (changer les valeurs, sauver)

Aucun toucher à all/vault.yml ni dbservers/vault.yml. La rotation est chirurgicale.

Convention vault_* — pourquoi ce préfixe précis

Section intitulée « Convention vault_* — pourquoi ce préfixe précis »

Trois alternatives ont été essayées par la communauté Ansible :

PréfixeAvantagesInconvénients
vault_*Court, parle à tout Ansible-isteAucun
_secret_*Souligne la sensibilitéUnderscore initial = convention “privé” en Python, prête à confusion
secure_*LisibleTrop générique, déjà utilisé en sysadmin

vault_* est devenu la convention de facto dans la doc officielle Red Hat et la majorité des rôles Galaxy. Le respecter facilite la lecture par d’autres développeurs et la portabilité des rôles.

Que se passe-t-il si la même variable est définie dans main et vault ?

Section intitulée « Que se passe-t-il si la même variable est définie dans main et vault ? »

Ansible suit la précédence standard : le fichier traité en dernier par ordre alphabétique gagne. Avec main.yml et vault.yml, vault.yml gagne car v > m alphabétiquement.

C’est généralement le comportement souhaité : si on définit db_password dans main (placeholder pour debug local) et dans vault (vraie valeur prod), la valeur vault l’emporte.

À tester en cas de doute :

Fenêtre de terminal
ansible -i inventory/hosts.yml all -m debug -a "var=ma_variable" \
--vault-password-file=.vault_password

Le lab vault/playbooks-mixtes du repo ansible-training reproduit ce parcours avec 4 tests pytest qui valident :

  • Les fichiers main.yml sont en clair, vault.yml chiffrés.
  • Les variables claires et chiffrées sont toutes accessibles dans le playbook.
  • La convention vault_* est respectée.
  • Le diff Git sur une variable publique reste lisible.

Suivre : labs/vault/playbooks-mixtes/README.md.

  • Mauvais emplacement de group_vars/ : doit être au même niveau que l’inventaire (inventory/group_vars/), pas à la racine du projet. Sinon Ansible ne charge pas les variables.
  • Oubli de vault_* : un secret nommé db_password (sans préfixe) reste accessible mais on perd la lecture rapide de qui est sensible.
  • Variables dupliquées entre main et vault : techniquement OK (vault gagne), mais source de confusion. Garder une seule définition.
  • group_vars/all/vault.yml non chiffré : oubli classique. Vérifier head -1 inventory/group_vars/*/vault.yml après chaque modification.
  • Pattern <groupe>/main.yml + vault.yml : variables publiques d’un côté, secrets de l’autre.
  • Convention vault_* rend la sensibilité visible dans tout le code (recherche grep).
  • Ansible fusionne automatiquement les deux fichiers — un seul namespace côté playbook.
  • Diffs Git lisibles sur les variables publiques (changements quotidiens).
  • Périmètre vault minimal : seules les personnes qui modifient des secrets ont besoin du mot de passe.
  • Rotation localisée : changer un mot de passe d’un seul groupe sans toucher aux autres.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn