Set-OPS-Public/docs/audit
Daniel Allaire 3b1d9b6660 SDN : make devis-sdn — zone, VNets et sous-réseaux dérivés du seed (D-43/44, P30)
Ajouter un tenant implique 1 zone EVPN + 6 VNets + 6 sous-réseaux sur le cluster.
Aucun générateur ne les produisait : dernière lacune dans un dépôt où tout dérive.
26 objets pour les deux tenants, VNI = 1000 + index×10 + zone, sous-réseau et
passerelle par les mêmes fonctions que l'inventaire.

Nommage, en deux temps. D'abord VRF0017 / v1174, alignés sur ce que le cluster
portait — réflexe inverse du bon : cette convention venait d'une création à la
main et ne disait pas de quel tenant il s'agissait. Forme retenue : t<index> pour
la zone, t<index><zone abrégée> pour le VNet (t17, t17serv). C'est le préfixe que
le pare-feu Proxmox utilisait déjà (t17-cli-metrique), donc un seul schéma dans
tout le dépôt. Abréviation = 4 premières lettres du libellé, accents retirés.

Pas de tiret entre index et zone, contrairement aux IPSets : t245-serv ferait 9
caractères, t245serv en fait 8 — la forme reste uniforme jusqu'au dernier index.

Contrainte cadrante : zones ET VNets sont limités à 8 caractères par Proxmox.
sdn-evpn.md annonçait chez17-services-infra (21) : il aurait été refusé à
l'application. P30 refuse tout dépassement et toute collision de nom, de VNI ou
de sous-réseau. Éprouvé aux bornes et par sabotage.

Vérification la plus forte : avant renommage, la dérivation reproduisait à
l'identique les deux zones créées à la main — nom, VNI de VRF, MTU, contrôleur.

voute.py saisir : le pendant de la génération. On génère un secret dont le dépôt
est la source, on saisit celui dont un tiers est la source — inventer une clé
d'API OPNsense donnerait une valeur refusée à la première requête, avec P18 au
vert sur une voûte inutilisable. Sans écho, double confirmation, rien sur la
ligne de commande.

Reste ouvert : aucun nœud de sortie déclaré. Le devis émet un marqueur, pas une
valeur plausible. Deux points à trancher — le nœud de sortie route selon sa
propre table (défaut actuel : 192.168.11.254, pas la frontière), et l'entrée
n'est pas redondante puisqu'elle dépend d'une route statique d'OPNsense vers un
seul nœud.

D-45 : l'affinité de VM attend Proxmox 9 (cluster en 8.4.19), tenue à la main.

30 preuves OK.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 11:06:42 -04:00
..
affirmations.md SDN : make devis-sdn — zone, VNets et sous-réseaux dérivés du seed (D-43/44, P30) 2026-08-04 11:06:42 -04:00
plan-de-recette.md Plan de recette (P22) : le pendant manuel de make prouver 2026-07-23 15:49:16 -04:00
preuve-2026-07-20.md Preuve complète (16/16) + détail P16 lisible 2026-07-20 20:47:36 -04:00
preuve-2026-07-22.md Trois preuves qui regardent au-dela d'une seule instance + champ liens/websocket au GUI 2026-07-22 21:32:42 -04:00
preuve-2026-07-23.md Créer une instance depuis un modèle (CLI + GUI) 2026-07-23 14:13:36 -04:00
preuve-2026-08-01.md client_pki : l'empreinte du root CA n'est pas un secret de voûte 2026-08-01 22:37:27 -04:00
preuve-2026-08-02.md modèles : l'underlay devient modélisable, et P17 le valide 2026-08-02 17:11:18 -04:00
preuve-2026-08-03.md SDN : make devis-sdn — zone, VNets et sous-réseaux dérivés du seed (D-43/44, P30) 2026-08-04 11:06:42 -04:00
protocole-operateur-independant.md Protocole d'épreuve de l'opérateur indépendant (AFF-002) 2026-07-21 09:46:21 -04:00
README.md Underlay : fabric physique cluster-global (mgmt/iSCSI/Ceph) + preuve P23 2026-07-24 14:56:38 -04:00

Audit de conformité — mode d'emploi

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 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 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

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 P15 (inventaire Ansible complet, ansible-inventory --list) déchiffre le group_vars de l'instance. Sans ANSIBLE_VAULT_PASSWORD_FILE, 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 :

export ANSIBLE_VAULT_PASSWORD_FILE=~/.config/setops-vault-pass
make prouver

Ce que couvre make prouver

# 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.)