ci : toute demande de fusion touchant Terraform est validée et auditée, sans Azure (#72) #242

Merged
marvin merged 1 commit from justine/72-garde-terraform into develop 2026-09-09 12:57:57 +00:00
Member

Ce que ça change

Deux tâches de plus dans Intégration — terraform (fmt, validate, tflint) et checkov — qui valident et auditent infra/terraform/ sans jamais joindre Azure : init -backend=false, aucun secret, aucune variable ARM_*. Elles sont
dans ci.yml plutôt que dans un workflow filtré par on.paths, parce qu'un workflow filtré ne démarre pas, n'écrit donc aucun statut, et laisserait un contrôle requis « en attente » pour toujours sur les demandes de fusion qui
ne touchent pas Terraform : ici elles tombent sous le joker Intégration / * déjà déclaré, et bloquent vraiment.

Closes #72

Preuve

$ terraform fmt -check -recursive -diff infra/terraform && echo OK
OK
$ terraform -chdir=infra/terraform init -backend=false -input=false # sans az login
Terraform has been successfully initialized!
$ terraform -chdir=infra/terraform validate
Success! The configuration is valid.
$ tflint --chdir=infra/terraform && echo OK
OK
$ checkov --directory infra/terraform --config-file infra/terraform/.checkov.yml --compact
Passed checks: 2, Failed checks: 0, Skipped checks: 0

$ tests/ci/test-garde-terraform.sh # la chaîne mord-elle encore ?
ok terraform fmt refuse le fichier mal formaté (code 3)
ok terraform fmt nomme le fichier en cause
ok checkov refuse la ressource fautive (code 1)
ok checkov nomme CKV_AZURE_59, la règle sur l'accès public au stockage
2 garde(s) éprouvée(s) : le fichier fautif est bien refusé.

$ tests/ci/test-hygiene-workflows.sh | tail -4
ok chacun des 6 jobs de la CI rend un résumé
ok les 36 noms de contrôle complétés correspondent tous à un contrôle réellement rapporté
ok chaque banc shell sous tests/ci est joué par ci.yml
Les workflows sont lisibles, épinglés, à privilège minimal et s'expliquent d'eux-mêmes.

actionlint, shellcheck, zizmor et yamllint sont propres sur ci.yml. Le journal d'un passage rouge puis vert sur la forge est à ajouter ici une fois la branche poussée.

Relecture

  • Un pair a relu et laissé un commentaire, même court
  • Ses remarques sont traitées, ou une réponse explique pourquoi elles ne le sont pas

Ce qui suit le code

  • docs/runbooks/ mis à jour, un geste d'exploitation a changé — ci.md, section « Terraform et sécurité IaC », et le tableau des tâches passé de quatre à six

Où regarder en priorité

Pas de section infra/terraform/ ci-dessus, et c'est voulu : cette demande n'ajoute aucun .tf. Les trois fichiers posés sous infra/terraform/ (.checkov.yml, .tflint.hcl, requirements-ci.txt) sont de la configuration d'outillage
— rien à plan, rien à apply, aucune ressource Azure touchée.

Trois points où un second avis aide :

  1. Le coût. Les deux tâches tournent sur chaque demande de fusion, y compris purement front, puisqu'elles ne sont plus filtrées. ~1 min chacune, fournisseur azurerm mis en cache sur la clé du lock — mais l'exécuteur est
    unique, donc ça s'ajoute à la file. C'est le prix du blocage réel, à valider.
  2. L'exception CKV2_AZURE_21 dans infra/terraform/.checkov.yml, la seule du fichier : le motif écrit tient-il ? (ce dépôt ne gère aucun compte de stockage, celui qui porte le conteneur d'archive ayant été créé hors Terraform
    par bootstrap.sh au #67).
  3. tests/ci/fixtures/terraform-fautif/mauvais.tf est fautif à dessein et ne doit jamais être corrigé. Le banc échoue si la chaîne le laisse passer — c'est ce qui distingue « rien n'a été signalé » de « l'outil n'a rien ouvert
    ».
## Ce que ça change Deux tâches de plus dans Intégration — terraform (fmt, validate, tflint) et checkov — qui valident et auditent infra/terraform/ sans jamais joindre Azure : init -backend=false, aucun secret, aucune variable ARM_*. Elles sont dans ci.yml plutôt que dans un workflow filtré par on.paths, parce qu'un workflow filtré ne démarre pas, n'écrit donc aucun statut, et laisserait un contrôle requis « en attente » pour toujours sur les demandes de fusion qui ne touchent pas Terraform : ici elles tombent sous le joker Intégration / * déjà déclaré, et bloquent vraiment. Closes #72 ## Preuve $ terraform fmt -check -recursive -diff infra/terraform && echo OK OK $ terraform -chdir=infra/terraform init -backend=false -input=false # sans az login Terraform has been successfully initialized! $ terraform -chdir=infra/terraform validate Success! The configuration is valid. $ tflint --chdir=infra/terraform && echo OK OK $ checkov --directory infra/terraform --config-file infra/terraform/.checkov.yml --compact Passed checks: 2, Failed checks: 0, Skipped checks: 0 $ tests/ci/test-garde-terraform.sh # la chaîne mord-elle encore ? ok terraform fmt refuse le fichier mal formaté (code 3) ok terraform fmt nomme le fichier en cause ok checkov refuse la ressource fautive (code 1) ok checkov nomme CKV_AZURE_59, la règle sur l'accès public au stockage 2 garde(s) éprouvée(s) : le fichier fautif est bien refusé. $ tests/ci/test-hygiene-workflows.sh | tail -4 ok chacun des 6 jobs de la CI rend un résumé ok les 36 noms de contrôle complétés correspondent tous à un contrôle réellement rapporté ok chaque banc shell sous tests/ci est joué par ci.yml Les workflows sont lisibles, épinglés, à privilège minimal et s'expliquent d'eux-mêmes. actionlint, shellcheck, zizmor et yamllint sont propres sur ci.yml. Le journal d'un passage rouge puis vert sur la forge est à ajouter ici une fois la branche poussée. ## Relecture - [ ] Un pair a relu et laissé un commentaire, même court - [ ] Ses remarques sont traitées, ou une réponse explique pourquoi elles ne le sont pas ## Ce qui suit le code - [x] docs/runbooks/ mis à jour, un geste d'exploitation a changé — ci.md, section « Terraform et sécurité IaC », et le tableau des tâches passé de quatre à six ## Où regarder en priorité Pas de section infra/terraform/ ci-dessus, et c'est voulu : cette demande n'ajoute aucun .tf. Les trois fichiers posés sous infra/terraform/ (.checkov.yml, .tflint.hcl, requirements-ci.txt) sont de la configuration d'outillage — rien à plan, rien à apply, aucune ressource Azure touchée. Trois points où un second avis aide : 1. Le coût. Les deux tâches tournent sur chaque demande de fusion, y compris purement front, puisqu'elles ne sont plus filtrées. ~1 min chacune, fournisseur azurerm mis en cache sur la clé du lock — mais l'exécuteur est unique, donc ça s'ajoute à la file. C'est le prix du blocage réel, à valider. 2. L'exception CKV2_AZURE_21 dans infra/terraform/.checkov.yml, la seule du fichier : le motif écrit tient-il ? (ce dépôt ne gère aucun compte de stockage, celui qui porte le conteneur d'archive ayant été créé hors Terraform par bootstrap.sh au #67). 3. tests/ci/fixtures/terraform-fautif/mauvais.tf est fautif à dessein et ne doit jamais être corrigé. Le banc échoue si la chaîne le laisse passer — c'est ce qui distingue « rien n'a été signalé » de « l'outil n'a rien ouvert ».
ci : toute demande de fusion touchant Terraform est validée et auditée, sans Azure (#72)
All checks were successful
Intégration / Contrôles statiques du dépôt (pull_request) Successful in 9s
Intégration / Terraform — format, validité et lint (pull_request) Successful in 28s
Intégration / Tableau de bord — dépendances, tests et construction (pull_request) Successful in 46s
Intégration / Workflows — lint et audit de sécurité (pull_request) Successful in 22s
Intégration / Checkov — audit de la configuration (pull_request) Successful in 49s
Infra Ansible / Playbooks Ansible valides (pull_request) Successful in 2m13s
Intégration / Python — qualité, tests et dépendances (pull_request) Successful in 5m50s
ed0c86bf88
Deux tâches de plus dans « Intégration », aux outillages sans recouvrement :

  - terraform : `fmt -check -recursive`, `init -backend=false`, `validate`, `tflint` ;
  - checkov : audit de la configuration, rapport JUnit en artefact.

DANS ci.yml, ET NON DANS UN WORKFLOW FILTRÉ À PART. Le ticket demandait « un job
filtré sur infra/terraform/** », et le travail a d'abord pris cette forme. Elle
et le blocage réel s'excluent, pour la raison écrite en tête de ci.yml : un
contrôle obligatoire attend un statut, le statut n'est écrit que si le workflow
démarre, et `on.paths` agit avant le démarrage. Sur une demande de fusion qui ne
touche pas Terraform, un requis « Infra Terraform / * » resterait « en attente »
pour toujours. Rapatriées ici, les deux tâches tombent sous le joker
« Intégration / * » déjà déclaré dans la protection des branches : rien à
configurer sur la forge, et une faute Terraform empêche vraiment la fusion.

La contrepartie est assumée : elles tournent sur chaque demande de fusion, comme
Ruff, mypy et npm audit, qui n'ont jamais regardé non plus ce que la demande
changeait. Le fournisseur azurerm est mis en cache sur la clé du lock pour que ce
prix reste de l'ordre de la minute. Chaque tâche se désiste proprement si
infra/terraform disparaît, et le dit dans son tableau de synthèse.

AUCUN SECRET, AUCUNE VARIABLE ARM_*. `terraform init` est joué en
`-backend=false` : le bloc backend azurerm réclamerait un jeton dès
l'initialisation, alors que `validate` n'a besoin que du schéma du fournisseur,
qui vient du registre public. N'importe quel membre obtient donc un verdict sur
l'infrastructure sans rôle sur l'abonnement école.

Terraform 1.16.1 et TFLint 0.64.0 épinglés par version ET par somme de contrôle,
checkov 3.3.16 par un requirements-ci.txt versionné. Un téléchargement échoué
avertit et dit ce qui n'a PAS été contrôlé ; une somme différente bloque. Même
doctrine qu'actionlint.

Bloquant dès la première exécution : le ticket demandait « informatif avant le
jour 5, bloquant après », et le jour 5 était le vendredi 4 septembre. La bascule
CHECKOV_BLOQUANT reste, pour checkov seul, parce que c'est lui qui porte le
risque de faux positifs — et la tourner exige une demande de fusion.

Les exceptions vivent dans infra/terraform/.checkov.yml, une par ligne, motif
écrit au-dessus. Une seule aujourd'hui, CKV2_AZURE_21 : ce dépôt ne gère aucun
compte de stockage, celui qui porte le conteneur d'archive ayant été créé hors
Terraform par bootstrap.sh (#67).

LA GARDE. Un contrôle vert ne prouve pas qu'il regarde.
tests/ci/test-garde-terraform.sh rejoue fmt et checkov — avec le vrai fichier
d'exceptions — sur un fichier volontairement mal formaté et volontairement
dangereux (`allow_blob_public_access = true`), et échoue si celui-ci passe. La
preuve demandée par le ticket est ainsi rejouée à chaque exécution au lieu
d'avoir été faite une fois dans une demande de fusion d'essai que personne ne
rouvrira. Elle rougit aussi le jour où une exception devient trop large. Le banc
tourne dans les deux tâches, chacune n'ayant qu'un des deux outils, et annonce
celui qui lui manque plutôt que de se taire.

Mesuré, pas supposé, sur l'état du dépôt au 09/09 : fmt, init -backend=false,
validate, tflint (preset `all`) et checkov passent ; le fichier fautif est refusé
par les deux gardes, checkov nommant CKV_AZURE_59 ; actionlint, shellcheck,
yamllint et zizmor sont propres sur ci.yml ; le banc d'hygiène compte six tâches,
six résumés et trente-six noms de contrôle qui correspondent tous.

Manuel d'exploitation : docs/runbooks/ci.md, section « Terraform et sécurité
IaC », et le tableau des tâches passé de quatre à six.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cc9tidxhXLh4pyLxVar8es
justine self-assigned this 2026-09-09 11:38:50 +00:00
olivier approved these changes 2026-09-09 11:50:44 +00:00
olivier left a comment

Relu, rien de bloquant : approuvé.

Relecture volontairement resserrée sur le bloquant et le critique (fin de projet).

Ce que j'ai vérifié, pas seulement lu

  • La prémisse de la demande tient, et c'est le point qui comptait. La protection de branche déclare bien Intégration / * comme seul contrôle requis, sur develop et sur main : les deux tâches rapatriées bloquent réellement, sans rien à configurer sur la forge. L'argument « workflow filtré = contrôle en attente pour toujours » est donc juste, et le choix de les mettre dans ci.yml est le bon.
  • CI verte 6/6 sur ed0c86b, en une seule exécution (n° 658, aucune relance) — le statut n'est pas dans le cas où l'API raconte l'état d'avant. Les tâches Terraform (2 min 47) et Checkov (3 min 47) ont donc réellement téléchargé, vérifié les sommes de contrôle et joué leurs bancs.
  • tests/ci/test-hygiene-workflows.sh rejoué sur la branche : passe, dont « les 36 noms de contrôle complétés correspondent tous à un contrôle réellement rapporté » et « chaque banc shell sous tests/ci est joué par ci.yml ».
  • shellcheck propre sur le nouveau banc, enregistré 100755.
  • Le banc mord : terraform fmt sort en code 3 et nomme mauvais.tf. terraform fmt -check -recursive infra/terraform est propre.
  • required_version = ">= 1.9" accepte bien le 1.16.1 épinglé, et -backend=false écarte le bloc backend "azurerm" — aucun contact Azure, conforme à ce qu'annonce la demande.
  • Sécurité : aucun secret, aucune interpolation ${{ }} venant d'une entrée non maîtrisée dans les run:, actions épinglées par SHA sur exactement les mêmes pins que le reste du fichier, persist-credentials: false.

Sur les trois points où tu demandais un second avis : le coût est assumé et documenté, l'exception CKV2_AZURE_21 est vérifiable dans le dépôt (le compte de stockage n'est effectivement pas géré ici, seul le conteneur l'est), et la consigne sur la fixture est claire — le commentaire en tête du fichier suffit.

Trois remarques non bloquantes, pour plus tard

  1. La commande checkov de la chaîne n'est pas celle de la « Preuve ». La section montre checkov --directory ... --config-file ... --compact, sans --output junitxml --output-file-path console,rapport-checkov.xml. Si checkov traite ce chemin comme un répertoire plutôt que comme un fichier, l'artefact repart vide en silence — if-no-files-found: ignore et continue-on-error: true étouffent le cas. Un coup d'œil au contenu de l'artefact du passage 658 lève le doute en une minute.
  2. Le banc du format est consigné missing quand le téléchargement de Terraform échoue, alors que la doctrine de l'étape est « avertir et nommer ce qui n'a pas été contrôlé ». Purement cosmétique — render ne fait jamais rougir la tâche — mais warned dirait la vérité, comme les deux autres contrôles juste au-dessus.
  3. mypy dans le commentaire de CHECKOV_BLOQUANT (et dans la même phrase du runbook) : ça se lit comme un report de copie, la bascule décrite porte sur checkov.

Rien de tout cela ne justifie de retenir la fusion.

Relu, rien de bloquant : **approuvé**. Relecture volontairement resserrée sur le bloquant et le critique (fin de projet). ## Ce que j'ai vérifié, pas seulement lu - **La prémisse de la demande tient**, et c'est le point qui comptait. La protection de branche déclare bien `Intégration / *` comme seul contrôle requis, sur `develop` **et** sur `main` : les deux tâches rapatriées bloquent réellement, sans rien à configurer sur la forge. L'argument « workflow filtré = contrôle en attente pour toujours » est donc juste, et le choix de les mettre dans `ci.yml` est le bon. - **CI verte 6/6 sur `ed0c86b`, en une seule exécution** (n° 658, aucune relance) — le statut n'est pas dans le cas où l'API raconte l'état d'avant. Les tâches `Terraform` (2 min 47) et `Checkov` (3 min 47) ont donc réellement téléchargé, vérifié les sommes de contrôle et joué leurs bancs. - `tests/ci/test-hygiene-workflows.sh` rejoué sur la branche : passe, dont « les 36 noms de contrôle complétés correspondent tous à un contrôle réellement rapporté » et « chaque banc shell sous `tests/ci` est joué par `ci.yml` ». - `shellcheck` propre sur le nouveau banc, enregistré `100755`. - Le banc mord : `terraform fmt` sort en code 3 et nomme `mauvais.tf`. `terraform fmt -check -recursive infra/terraform` est propre. - `required_version = ">= 1.9"` accepte bien le `1.16.1` épinglé, et `-backend=false` écarte le bloc `backend "azurerm"` — aucun contact Azure, conforme à ce qu'annonce la demande. - Sécurité : aucun secret, aucune interpolation `${{ }}` venant d'une entrée non maîtrisée dans les `run:`, actions épinglées par SHA sur exactement les mêmes pins que le reste du fichier, `persist-credentials: false`. Sur les trois points où tu demandais un second avis : le coût est assumé et documenté, l'exception `CKV2_AZURE_21` est vérifiable dans le dépôt (le compte de stockage n'est effectivement pas géré ici, seul le conteneur l'est), et la consigne sur la fixture est claire — le commentaire en tête du fichier suffit. ## Trois remarques non bloquantes, pour plus tard 1. **La commande checkov de la chaîne n'est pas celle de la « Preuve ».** La section montre `checkov --directory ... --config-file ... --compact`, sans `--output junitxml --output-file-path console,rapport-checkov.xml`. Si checkov traite ce chemin comme un répertoire plutôt que comme un fichier, l'artefact repart vide en silence — `if-no-files-found: ignore` et `continue-on-error: true` étouffent le cas. Un coup d'œil au contenu de l'artefact du passage 658 lève le doute en une minute. 2. **Le banc du format est consigné `missing` quand le téléchargement de Terraform échoue**, alors que la doctrine de l'étape est « avertir et nommer ce qui n'a pas été contrôlé ». Purement cosmétique — `render` ne fait jamais rougir la tâche — mais `warned` dirait la vérité, comme les deux autres contrôles juste au-dessus. 3. **`mypy` dans le commentaire de `CHECKOV_BLOQUANT`** (et dans la même phrase du runbook) : ça se lit comme un report de copie, la bascule décrite porte sur checkov. Rien de tout cela ne justifie de retenir la fusion.
marvin merged commit b5667d6cd4 into develop 2026-09-09 12:57:57 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
g2/enervision!242
No description provided.