voute : demander le mot de passe une fois, pas quinze

flotte-creer appelait `make creer-vm` une fois par hote, et chaque appel
ajoutait --ask-vault-pass. Quinze machines = quinze invites, quatre en
parallele, avec la sortie redirigee vers des journaux : l'exploitant est harcele
par des invites qu'il ne voit meme pas.

L'idiome existait DEJA dans deployer-tout, et je ne l'avais pas cherche : ma
premiere correction inventait une seconde facon de manipuler un secret. Deux
resolutions d'une meme question finissent par diverger -- la lecon de P41,
appliquee a un mot de passe.

Les deux cibles partagent maintenant un bloc unique, VAULT_UNE_FOIS.

Et une garde que ma premiere version n'avait pas : `-t 0`. Sans elle, un appel
non interactif restait bloque sur une invite que personne ne lit -- constate en
verifiant ma propre correction, qui a pendu deux minutes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Daniel Allaire 2026-08-24 19:14:08 -04:00
parent 9c173f52ba
commit 85ef6e107e
2 changed files with 63 additions and 12 deletions

View file

@ -1,5 +1,37 @@
# CHANGELOG — Set-OPS
## 2026-08-24 — Quinze invites pour un seul mot de passe
`flotte-creer` appelait `make creer-vm` **une fois par hôte**, et chaque appel ajoutait
`--ask-vault-pass`. Quinze machines, donc quinze invites — **quatre en parallèle**, avec la
sortie redirigée vers des journaux : l'exploitant est harcelé par des invites qu'il ne voit
même pas.
Mesuré en reconstruisant Chezlepro. Ce n'est pas une fatalité de l'outil, c'est une faute
de l'outil.
### L'idiome existait déjà — je ne l'avais pas cherché
`deployer-tout` demande **une seule fois** depuis longtemps, et refuse proprement quand
personne n'est au clavier. Ma première correction inventait une **seconde** façon de
manipuler un secret, à côté de la première.
C'est exactement la faute que P41 combat : deux résolutions d'une même question finissent
par diverger, et pour un secret la divergence ne se remarque qu'après.
Les deux cibles partagent désormais **un seul bloc**, `VAULT_UNE_FOIS` : lecture unique,
fichier `mktemp` en `0600`, `trap` au retrait, et refus explicite en entrée non
interactive.
### Une garde que ma première version n'avait pas
`-t 0` : ne demander que si un humain est au clavier. Sans elle, un appel non interactif —
CI, ordonnanceur, agent — resterait **bloqué sur une invite que personne ne lit**. Je m'en
suis aperçu en vérifiant ma propre correction : la commande a pendu deux minutes.
Vérifié : `flotte-creer` sans mot de passe et sans terminal refuse maintenant en une
ligne, au lieu d'attendre indéfiniment.
## 2026-08-24 — Le dénominateur extrait : `origine` devient un modèle
La hiérarchie se lit maintenant sans ambiguïté :

View file

@ -368,18 +368,7 @@ deployer: _instance-requise ## Deploie un hote, couche par couche, dans l'ordre
printf '%s\n' 'Refus: aucun playbook applicable pour HOTE=$(HOTE).'; \
exit 2; \
fi; \
vault_chiffre="$$(grep -rlsIF '$$ANSIBLE_VAULT' $(dir $(INVENTAIRE_PRODUCTION))group_vars 2>/dev/null | head -1 || true)"; \
if [[ -n "$$vault_chiffre" && -z "$${ANSIBLE_VAULT_PASSWORD_FILE:-}" ]]; then \
if [[ -t 0 ]]; then \
read -r -s -p 'Mot de passe du vault Ansible: ' mdp; echo; \
vf="$$(mktemp)"; printf '%s' "$$mdp" > "$$vf"; chmod 600 "$$vf"; \
export ANSIBLE_VAULT_PASSWORD_FILE="$$vf"; \
trap 'rm -f "$$vf"' EXIT; \
else \
printf '%s\n' 'Refus: vault chiffre detecte mais aucun mot de passe (entree non interactive). Fournir ANSIBLE_VAULT_PASSWORD_FILE ou le champ vault de la GUI.'; \
exit 2; \
fi; \
fi; \
$(VAULT_UNE_FOIS) \
$(MAKE) _verifier-acces-hote LIMITE="$(HOTE)"; \
$(MAKE) _verifier-privileges-hote LIMITE="$(HOTE)"; \
for playbook in $$playbooks; do \
@ -651,6 +640,35 @@ deployer-tout: _instance-requise ## Deploie TOUTE la flotte dans l'ordre des cou
# Un echec n'est pas avale : le code de retour de chaque hote est relu, et la cible sort
# en erreur si l'un d'eux a echoue — sinon `_attendre-flotte` partirait sur une flotte
# incomplete.
# --- LE MOT DE PASSE DE LA VOUTE, DEMANDE UNE SEULE FOIS ----------------------
#
# Deux cibles longues en ont besoin : `deployer-tout` (une invocation ansible) et
# `flotte-creer` (une invocation PAR MACHINE). La seconde redemandait le mot de passe a
# chaque VM — quinze fois sur la reconstruction de Chezlepro, quatre en parallele, avec
# la sortie redirigee vers des journaux : l'exploitant est harcele par des invites qu'il
# ne voit meme pas.
#
# UN SEUL BLOC POUR LES DEUX. Deux facons de manipuler un secret finiraient par diverger,
# et c'est le genre de divergence qu'on ne remarque qu'apres.
#
# `-t 0` : ne demander que si un humain est au clavier. Un appel non interactif refuse
# clairement plutot que de pendre sur une invite que personne ne lit.
define VAULT_UNE_FOIS
vault_chiffre="$$(grep -rlsIF '$$ANSIBLE_VAULT' $(dir $(INVENTAIRE_PRODUCTION))group_vars 2>/dev/null | head -1 || true)"; \
if [[ -n "$$vault_chiffre" && -z "$${ANSIBLE_VAULT_PASSWORD_FILE:-}" ]]; then \
if [[ -t 0 ]]; then \
read -r -s -p 'Mot de passe du vault Ansible (demande une seule fois): ' mdp; echo; \
vf="$$(mktemp)"; printf '%s' "$$mdp" > "$$vf"; chmod 600 "$$vf"; \
export ANSIBLE_VAULT_PASSWORD_FILE="$$vf"; \
trap 'rm -f "$$vf"' EXIT; \
else \
printf '%s\n' 'Refus: vault chiffre detecte mais aucun mot de passe (entree non interactive). Fournir ANSIBLE_VAULT_PASSWORD_FILE ou le champ vault de la GUI.'; \
exit 2; \
fi; \
fi;
endef
flotte-creer: _instance-requise ## Cree les VM manquantes de la flotte depuis le plan — PARALLELE=n
@set -e; \
if [[ "$(CONFIRMER)" != "true" ]]; then \
@ -662,6 +680,7 @@ flotte-creer: _instance-requise ## Cree les VM manquantes de la flotte depuis le
if [[ -z "$$hotes" ]]; then printf '%s\n' 'Refus: aucun hote actif dans le plan.'; exit 2; fi; \
par="$(PARALLELE)"; par="$${par:-4}"; \
tmp="$$(mktemp -d)"; trap 'rm -rf "$$tmp"' EXIT; \
$(VAULT_UNE_FOIS) \
printf 'Creation de %s VM, %s a la fois.\n' "$$(echo $$hotes | wc -w)" "$$par"; \
n=0; \
for h in $$hotes; do \