Skip to content

fix(sécurité): la solution de référence, chiffrée par ansible-vault - #74

Merged
stephrobert merged 2 commits into
mainfrom
fix/solution-chiffree
Oct 19, 2026
Merged

stephrobert merged 2 commits into
mainfrom
fix/solution-chiffree

Conversation

@stephrobert

Copy link
Copy Markdown
Owner

Le défaut

Le workflow de fondations-premier-workflow était commité en clair dans un dépôt public : l'apprenant qui clone avait la réponse sous la main.

meta.yml le déclarait, et motivait le choix par le fait qu'un workflow chiffré « ne se relirait pas ». C'était vrai des outils du dépôt, pas une fatalité : deux lecteurs consommaient le fichier en clair, et il suffisait de leur apprendre à déchiffrer.

Les deux lecteurs, et pourquoi le second était le plus important

Lecteur Ce qu'il fait Effet du chiffrement sans adaptation
scripts/valider-labs.py pose la solution sur le répertoire de travail l'erreur parle de YAML invalide, pas de chiffrement
tests/test_solutions_exemplaires.py vérifie que la solution épingle ses actions sur un SHA et déclare ses permissions garde ses 15 verts sans plus aucun uses: à examiner

Le second cas est précisément le défaut que ce dépôt traque chez les autres, et son propre test_le_depot_a_des_workflows_a_controler existe pour cette raison : « un glob qui ne trouve rien produit zéro cas paramétré, donc zéro échec possible ». Le chiffrement aurait créé la même cécité un cran plus bas, sans vider la liste.

Les trois lectures de ce test passent donc par scripts/lecture_solution.py, qui déchiffre et lève quand il ne peut pas, plutôt que de rendre une chaîne vide.

Contrôles joués, sur le comportement

  • Le déchiffrement rend l'original à l'octet près (SHA256 avant/après).
  • Le contrôle voit les 62 lignes du workflow et ses 2 uses: épinglés, donc il porte bien sur un workflow : 15 tests passed n'auraient rien prouvé seuls.
  • Sans le secret, la lecture lève et les tests se déclarent non joués.
  • dsoxlab validate-structure est vert, actionlint propre.

Le coût, assumé et écrit

Le rejeu « 0 avant, 100 après » ne se joue plus en CI. Le cycle a besoin du clair, et .vault-pass n'est pas sur la forge, comme dans aucun catalogue de la collection (ansible l'exclut même de ses archives de release). Les deux étapes concernées se déclarent non jouées par un avertissement visible, au lieu de passer pour un succès ou de rendre un rouge permanent qui finirait désactivé.

L'opposabilité de validation-labs.json ne tient donc plus à cette CI mais à la campagne locale qui l'a produit, ce qui est la situation des onze autres catalogues. L'autre voie, confier .vault-pass à un secret de dépôt, a été écartée en connaissance : elle aurait gardé le rejeu au prix de mettre sur la forge le secret qu'aucun catalogue n'y met.

meta.yml ne porte plus solutions: plaintext ; le paragraphe qui le motivait a été remplacé par ce que coûte le chiffrement, écrit sur place plutôt que redécouvert.

Au passage

.gitignore ne mentionnait pas .vault-pass. Le secret vit hors de git par construction : 48 octets d'aléa, mode 600.

L'historique garde la solution en clair : ce commit la retire de l'arbre, pas du passé.

CHANGELOG EN et FR, bump en 0.2.2, uv.lock rafraîchi.

🤖 Generated with Claude Code

stephrobert and others added 2 commits October 19, 2026 15:56
Le workflow de `fondations-premier-workflow` était commité en clair dans un
dépôt public : l'apprenant qui clone avait la réponse sous la main.

`meta.yml` déclarait `solutions: plaintext` et motivait ce choix par le fait
qu'un workflow chiffré « ne se relirait pas ». C'était vrai des OUTILS du
dépôt, pas une fatalité : deux lecteurs lisaient le fichier en clair, et il
suffisait de leur apprendre à déchiffrer.

`scripts/valider-labs.py` pose la solution par-dessus le répertoire de
travail : il la déchiffre à la pose, sinon l'erreur parlerait de YAML invalide
et non de chiffrement. `tests/test_solutions_exemplaires.py` contrôle que la
solution épingle ses actions sur un SHA et déclare ses `permissions` : ses
trois lectures déchiffrent. Sans cette seconde adaptation, il aurait gardé ses
quinze verts en n'ayant plus aucun `uses:` à examiner, ce qui est précisément
le défaut que ce dépôt traque chez les autres.

Vérifié sur le comportement : le contrôle voit les 62 lignes du workflow et
ses 2 `uses:` épinglés ; sans le secret, la lecture lève et les tests se
déclarent non joués. `validate-structure` est vert et les 15 tests passent.

Le rejeu « 0 avant, 100 après » ne se joue plus en CI, et c'est le coût assumé
du chiffrement : le cycle a besoin du clair, et `.vault-pass` n'est pas sur la
forge, comme dans aucun catalogue de la collection. Les deux étapes se
déclarent non jouées par un avertissement visible. L'opposabilité du relevé ne
tient donc plus à cette CI mais à la campagne locale qui l'a produit. L'autre
voie, confier le secret au dépôt GitHub, a été écartée en connaissance.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Un troisième lecteur que mon inventaire avait manqué, et c'est la CI qui l'a
trouvé : actionlint et zizmor analysent « le dépôt ET les solutions », par
`scripts/hooks/cibles-workflows.sh`. Sur un fichier chiffré, actionlint rend
« "on" section is missing » et « "jobs" section is missing » : un échec qui ne
parle pas de chiffrement et qu'on ne peut pas corriger côté workflow.

J'avais cherché les lecteurs dans `scripts/` et `tests/`, pas dans les
workflows ni les hooks. Le bon périmètre était tout ce qui NOMME un chemin de
solution, et c'est ce que ce correctif couvre : les trois appelants passent par
le même script, donc un seul endroit à reprendre.

Un répertoire de solution dont tous les workflows sont chiffrés est désormais
écarté, et l'avertissement part sur STDERR : stdout est la liste des cibles, un
message y deviendrait un chemin à analyser.

Ce qui reste couvert, et par quoi : l'exemplarité des solutions (actions
épinglées sur un SHA, bloc `permissions` déclaré) est contrôlée par
`tests/test_solutions_exemplaires.py`, qui déchiffre. C'est là que vit la
valeur pédagogique du contrôle. La syntaxe du workflow de solution est, elle,
éprouvée autrement et mieux : le cycle local le fait jouer par `act`.

Vérifié localement : actionlint analyse les 6 workflows du dépôt et sort en 0,
zizmor ne rend aucune trouvaille, et le script annonce le répertoire écarté.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@stephrobert
stephrobert merged commit 56c8ca5 into main Oct 19, 2026
7 checks passed
@stephrobert
stephrobert deleted the fix/solution-chiffree branch October 19, 2026 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant