Some checks failed
verifier / verifier (push) Has been cancelled
La revision a commence par un balayage par motifs — chemins morts, cibles make absentes, comptes derives. Il a trouve une trentaine d ecarts et rate presque tout le reste : un motif ne voit que ce qui s exprime en motif. make hote-planifier en est l exemple. La cible EXISTE, donc le controle passait au vert. C est une cible depreciee qui refuse et sort en 2, recommandee par AGENTS.md, et qui contredit la REGLE D OR du meme fichier trois ecrans plus haut. Il fallait lire pour la voir. 74 documents lus un par un. 66 corriges, 8 exacts. CE QUI ETAIT FRANCHEMENT FAUX AGENTS.md, la source d autorite, annoncait la flotte pas encore executee contre des VM reelles. Elle a ete rasee et remontee depuis zero trois fois. ecosysteme-chezlepro.md, le document montre a un client, portait la meme phrase : il se sous-vendait gravement. courriel-conception.md s ouvrait sur aucun role n est encore ecrit, au-dessus de son propre paragraphe 1 qui les nomme. autorisation.md se terminait sur rien n est construit alors qu il rapporte des mesures datees du role en fonctionnement. hebergeur-exploitation.md disait rien n est fait d un depot qui existe. filiation-emancipation.md se contredisait a deux ecrans de distance. DES MODELES DECRITS D APRES UN MONDE ANTERIEUR Le resolveur : cinq documents decrivaient un Unbound par VM en opt-in, trois le donnaient en exemple d integration FACULTATIVE — il est universel depuis le 2026-08-24. L adressage de nomenclature-vm.md : reseau unique, VLAN 11-15, VMID a cinq chiffres. Le nommage SDN de sdn-evpn.md contre le code : c est le wiki qui avait raison. CE QUI CASSE AU PREMIER ESSAI Le nom du gabarit dore etait faux a quatre endroits, dont la procedure qui le FABRIQUE et le critere R2 de l epreuve d operateur independant. preparer-un-site-hebergeur.md avertissait qu une VM faite a la main serait detruite : raser derive du plan, il ne la detruira jamais — le risque est l inverse. Un mot de passe d essai en clair dans un depot public. DEUX PREUVES ETENDUES, ET UNE QUI SE TROMPAIT ELLE-MEME P57 couvre les groupes : elle a signale aussitot 29 groupes annonces au-dessus d un tableau qui en cite 40. P29 confronte le tableau de authentification.md aux declarations reelles : 12 annonces, 21 reels. Et P57 imposait un chiffre faux — 56 preuves alors que le depot en porte 57, la conditionnelle vivant hors de tout comptage. Un garde-fou qui fait respecter une erreur ajoute l assurance a l erreur. CE QUI RESTE, ET QU AUCUNE PREUVE NE TIENT Deux comptes trouves a la main. Et une lacune reelle : rien ne garde les meta/acces.yml — ni qu un service web-sso en porte un, ni que le groupe qu il nomme existe. P29 tient les positions d authentification, personne ne tient les habilitations. make prouver : CONFORME, 56 OK, 0 echec, 1 saute. 0 lien mort. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
116 lines
7.9 KiB
Markdown
116 lines
7.9 KiB
Markdown
# Audit de conformité — mode d'emploi
|
||
|
||
> **Pour qui :** le **mainteneur** — comment le dispositif de preuve fonctionne, et comment l'étendre.
|
||
|
||
Ce dossier contient le dispositif qui garde Set-OPS **honnête** : il ne doit jamais
|
||
affirmer plus que ce qu'il prouve.
|
||
|
||
## Les pièces
|
||
|
||
| Fichier | Rôle |
|
||
|---|---|
|
||
| [`affirmations.md`](affirmations.md) | **Le registre** : chaque affirmation publique du dépôt (README, AGENTS, QUICKSTART, docs, wiki, aide `make`, GUI) tracée vers une commande de preuve et un statut (✅/🟡/❌/⚪), plus le **journal des traitements** (ce qui a été corrigé, quand, comment). |
|
||
| `scripts/prouver.py` | **Le harnais** : un orchestrateur mince qui **rejoue** les preuves automatisables du registre en appelant l'outillage existant (les mêmes scripts que `make verifier`). Il ne réimplémente aucune validation. |
|
||
| `preuve-AAAA-MM-JJ.md` | **La pièce justificative** : le rapport horodaté produit par `make prouver`. Rejouable et présentable (audit, certification, revue). |
|
||
| [`protocole-operateur-independant.md`](protocole-operateur-independant.md) | **L'épreuve humaine** : le protocole qui met AFF-002 (« exploitable sans IA ») à l'épreuve d'un sysadmin qui n'est pas l'auteur. Aucune commande locale ne peut prouver cette affirmation ; produit un rapport `operateur-independant-AAAA-MM-JJ.md`. |
|
||
|
||
## Produire une preuve
|
||
|
||
```bash
|
||
make prouver
|
||
```
|
||
|
||
Cela exécute chaque preuve et écrit `docs/audit/preuve-<date>.md`. La commande **sort en
|
||
erreur (rc≠0)** si une preuve automatisable échoue — utilisable en garde-fou (CI locale,
|
||
pré-commit). Une preuve **SAUTÉE** (⚪) n'est pas un échec.
|
||
|
||
### Prérequis Vault
|
||
|
||
La preuve **`P16`** (inventaire Ansible complet, `ansible-inventory --list`) déchiffre le
|
||
`group_vars` de l'instance. Sans la clé de la voûte, elle est **automatiquement sautée** (⚪)
|
||
avec la mention du prérequis — le reste du harnais reste vert, car les validateurs Python
|
||
lisent le plan et l'inventaire directement, sans secret.
|
||
|
||
Pour l'inclure, il suffit que la clé de l'instance soit en place ; il n'y a **rien à
|
||
exporter** (une voûte, une clé — `scripts/voutes.py` la trouve par convention de nommage) :
|
||
|
||
```bash
|
||
python3 scripts/voutes.py etat # la clé de cette instance est-elle là ?
|
||
make prouver
|
||
```
|
||
|
||
*(Ce paragraphe désignait `P15` et un `ANSIBLE_VAULT_PASSWORD_FILE` unique jusqu'au
|
||
2026-09-06 : ni l'un ni l'autre n'était juste.)*
|
||
|
||
## Ce que couvre `make prouver`
|
||
|
||
> **Ce tableau est un EXTRAIT, pas l'inventaire.** Il s'arrête à `P23` et le dépôt porte
|
||
> **57 preuves** (`P01`–`P57`, sans trou). La liste complète et à jour est produite par le
|
||
> harnais lui-même, jamais recopiée :
|
||
>
|
||
> ```bash
|
||
> make prouver # écrit docs/audit/preuve-<date>.md : chaque preuve, son verdict
|
||
> grep -oE '"id": "P[0-9]+", "titre": "[^"]+"' scripts/prouver.py # la source
|
||
> ```
|
||
>
|
||
> On garde l'extrait parce qu'il **explique** les premières preuves, celles qui fondent le
|
||
> reste. On ne le complète pas : un tableau de 57 lignes recopié à la main aurait dérivé
|
||
> avant d'être fini — c'est exactement ce qui est arrivé à celui-ci.
|
||
|
||
| # | Preuve | Ce qu'elle établit |
|
||
|---|---|---|
|
||
| P01 | Lint (`ansible-lint`) | 0 violation, profil `production`. |
|
||
| P02 | Tests unitaires | `inventory_host` — cas nominal + refus. |
|
||
| P03 | Diff-vide du plan | l'inventaire est **généré** depuis le plan (diff vide). |
|
||
| P04 | Groupes ↔ playbooks | chaque groupe opérationnel a son playbook homonyme. |
|
||
| P05 | Dépendances de groupes | graphe cohérent, aucune entrée orpheline. |
|
||
| P06 | Validateurs de registres | serveurs / applications / bases / domaines valides. |
|
||
| P07 | GUI | `node --check` du JS du GUI. |
|
||
| P08 | Orchestration | couches + graphe : aucun cycle, aucune arête en arrière. |
|
||
| P09 | Flux réseau | schéma + matrice d'audit cohérents. |
|
||
| P10 | Handlers ↔ notify | tout `notify` pointe vers un handler du même rôle. |
|
||
| P11 | Syntaxe | `--syntax-check` de tous les playbooks (via `make syntaxe`). |
|
||
| P12 | Runbooks cités | les fichiers `docs/` référencés existent. |
|
||
| P13 | Invariants structurels | LICENSE, socle en forme dossier, pas de couches parallèles, SSH clé-only, nftables désactivé par défaut. |
|
||
| P14 | Chemins d'inventaire | aucun `instance/inventories/lab/group_vars` codé en dur. |
|
||
| P15 | Modèle public `socle` | ses registres (domaines/serveurs/applications/bases) valident. |
|
||
| P16 | Inventaire Ansible (voûte) | `ansible-inventory --list` — sauté sans mot de passe Vault. |
|
||
| P17 | **Tous** les modèles d'instance | chaque modèle découvert valide (pas seulement `socle`). `SETOPS_MODELES=../Set-OPS-Modeles` inclut les modèles assemblés privés. |
|
||
| P18 | Gabarit de voûte complet | `vault.yml.example` couvre **exactement** les secrets que le plan exige (rôles actifs + bases + group_vars). |
|
||
| P19 | GUI couvre le plan | tout champ présent dans un plan réel est éditable par le GUI (nomenclature tolérée : le seed `index` est désormais un intrant ; l'adressage est dérivé, donc rien à éditer). |
|
||
| P20 | Adressage dérivé du seed | aucune nomenclature ne **stocke** d'adressage (supernet, sous-réseau, passerelle, VLAN) : tout se dérive du seul `index`. Attrape toute rechute vers l'écriture manuelle. |
|
||
| P21 | Fédération sans collision | aucune paire d'instances **fédérées** ne partage un `index` (mêmes VLAN/VMID sur le trunk). Le garde-fou du multi-instances ; vue avec `make instances`. |
|
||
| P22 | Plan de recette à jour | `docs/audit/plan-de-recette.md` (les 78 gestes manuels, générés des exercices du wiki) est **à jour** — il ne peut pas dériver du wiki. Régénérer : `make plan-recette`. |
|
||
| P23 | Underlay sans collision | la **fabric physique** (`underlay.yml` : mgmt/iSCSI/Ceph, cluster-global) n'empiète pas sur la plage tenant — VLAN < 1000 et sous-réseaux hors des supernets `10.(10+index).0.0/16`. Sautée si `underlay.yml` absent. Vue : `make underlay`. |
|
||
|
||
> **P17, P18, P19 ferment les angles morts du harnais** : il ne vérifiait qu'*une* instance
|
||
> et le seul modèle `socle`. P17 aurait attrapé l'hôte fantôme d'`integral` ; P18, les neuf
|
||
> secrets absents du gabarit Chezlepro ; P19, les champs `liens` / `websocket` que le GUI ne
|
||
> savait pas écrire. Chacune a une CLI dédiée (`scripts/modeles.py`, `voute.py`,
|
||
> `couverture_gui.py`) utilisable seule.
|
||
|
||
Le rapport relie chaque preuve aux **affirmations** qu'elle couvre (colonne « Affirmations »),
|
||
et liste à part les **déclarations d'intention** (⚪ invérifiables localement : AFF-036,
|
||
091, 096, 007) — assumées comme intentions, jamais présentées comme prouvées.
|
||
|
||
## Ajouter une preuve
|
||
|
||
1. Ajouter (ou corriger) l'affirmation dans `affirmations.md` avec sa commande de preuve.
|
||
2. Ajouter une entrée à la liste `PREUVES` de `scripts/prouver.py` : soit une ou plusieurs
|
||
commandes (`cmds`, toutes doivent renvoyer 0), soit une fonction native `func` renvoyant
|
||
`(ok, détail)` pour un invariant simple. Renseigner `refs` avec les ID d'affirmations.
|
||
3. Ne **pas** réimplémenter de logique de validation : appeler l'outillage existant
|
||
(`scripts/*.py`, `ansible-lint`, cibles `make`). Le harnais orchestre, il ne valide pas.
|
||
|
||
## Rapport avec `make verifier`
|
||
|
||
`make verifier` **inclut désormais les preuves** : il enchaîne ses vérifications au fil de
|
||
l'eau (lint, tests, cohérence, syntaxe — arrêt au premier échec) puis termine par
|
||
`python3 scripts/prouver.py --verifier` — les preuves du registre **sans écrire de rapport**
|
||
(pour ne pas écraser la pièce justificative committée). Ainsi, `make verifier` échoue si une
|
||
preuve échoue.
|
||
|
||
`make prouver` (sans `--verifier`) reste le mode **pièce justificative** : il exécute tout,
|
||
**horodate** et **écrit** `docs/audit/preuve-<date>.md`. Les deux réutilisent le même
|
||
outillage. (Quelques vérifications se recouvrent entre les deux étapes — coût assumé : la
|
||
sortie détaillée de `verifier` est conservée, et `prouver` ajoute les preuves manquantes.)
|