From 89c911ef05bd6f91b48e6641b2936eefeb675bbd Mon Sep 17 00:00:00 2001 From: Daniel Allaire Date: Fri, 28 Aug 2026 16:21:39 -0400 Subject: [PATCH] =?UTF-8?q?journal=20:=20l=20insemination=20aboutit=20?= =?UTF-8?q?=E2=80=94=20un=20runner=20de=20tenant,=20ne=20d=20un=20runner?= =?UTF-8?q?=20de=20site?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on --- CHANGELOG.md | 64 +++++++++++++++++++++++++++++++++ docs/audit/preuve-2026-08-28.md | 11 +++--- 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a9d922..0769496 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,69 @@ # CHANGELOG — Set-OPS +## 2026-08-28 — L'insémination aboutit : un runner de tenant, né d'un runner de site + +**52 preuves.** `ops-01` existe, configurée de bout en bout **par le runner du SITE**, qui +n'a détenu aucun secret de Chezlepro : + +``` +/opt/setops Set-OPS-public OPS-Chezlepro SITE-Chezlepro venv +symlinks (D-80) instance -> OPS-Chezlepro underlay.yml -> SITE-Chezlepro/… +moteur au commit courant +sa paire SSH setops@ops-01.chezlepro.internal +voûte / clé AUCUNE +``` + +**Il s'arrête exactement là où il n'a pas la clé.** Ce n'est pas une règle qu'on lui +impose, c'est un fait : la voûte de Chezlepro ne vit dans aucun dépôt, et son mot de passe +n'est sur aucune de ses machines. L'armer reste le geste d'un humain, depuis **son** poste, +par **son** chemin — le site ne peut pas le faire à sa place, même s'il le voulait. + +### Trois murs, et chacun a nommé une pièce manquante du terrain + +Le socle bloquait sur `apt`, puis `serveur_ops` sur `pip`, puis sur le clonage du génome. +Trois échecs, trois couches du terrain que le SITE doit préparer et qui n'étaient pas +déclarées. + +**`apt`** → la source d'artefacts d'amorçage. Le DNS sortant d'un tenant est fermé par +conception ; un mandataire résout ce que le client ne peut pas résoudre. Aucun flux à +ouvrir : le cache du site acceptait déjà les supernets des tenants. + +**`pip`** → la roue hors-ligne, dernière dépendance qui sortait par elle-même. Les +collections suivaient l'idiome du dépôt depuis longtemps — *le contrôleur télécharge, la +cible n'ouvre rien* — `pip` non. `--no-index` **est** le point : sans lui, la réussite +dépendrait un jour d'un flux que ce tenant n'a pas le droit d'avoir, et une lignée +autonome deviendrait une lignée qui **a l'air** autonome. + +**Le génome** → le marqueur `serveur_forge_site`, qui manquait. Le site rendait deux +services à ses locataires, les paquets et le génome ; seul le premier était déclaré. Une +dépendance écrite chez le consommateur, sans flux chez le fournisseur — invisible, parce +que la garde de matrice ne vérifie que les paires rôle→rôle. + +### Les clés SSH suivent la même règle que les voûtes + +Chaque runner a son jeu de clés ; sa publique vit dans l'`authorized_keys` des machines de +**son** tenant, et d'aucun autre. Le runner du SITE n'entre que sur `ops-01`, par le flux +d'insémination. *Le pouvoir d'entrer se borne au périmètre du runner qui le détient*, comme +le pouvoir d'ouvrir se borne à sa voûte. + +Le véhicule existait déjà — `ssh_baseline_cles_admin`, avec son `etat` par entrée, donc +révocable sur toute la flotte. Chezlepro n'en déclarait aucune parce que son runner +n'existait pas encore. + +### Ce que la mesure a corrigé, deux fois + +`ops-01` est **la seule VM de Chezlepro qui existe** — les quatorze autres ne sont sur +aucun hyperviseur. Mes sondes vers le résolveur, le cache et la PKI du tenant mesuraient +donc une **absence**, que j'ai d'abord lue comme un pare-feu. *Un port muet ressemble à un +refus.* + +Et l'accès que je croyais avoir cassé en appliquant le pare-feu est-ouest : aucune machine +de Chezlepro n'était joignable depuis le poste par ce rebond. `ops-01` l'était parce +qu'elle n'avait **aucun** groupe de pare-feu. Je n'ai pas créé une panne, j'ai retiré une +exception. + +make verifier : vert. make prouver : CONFORME, 52 OK, 0 echec, 0 saute. + ## 2026-08-28 — Nourrir la première machine : le cache du site pendant la jeunesse **52 preuves.** `ops-01` est la première machine de la reconstruction de Chezlepro, et le diff --git a/docs/audit/preuve-2026-08-28.md b/docs/audit/preuve-2026-08-28.md index 1f569d8..006d739 100644 --- a/docs/audit/preuve-2026-08-28.md +++ b/docs/audit/preuve-2026-08-28.md @@ -7,7 +7,7 @@ > [`docs/audit/affirmations.md`](affirmations.md). - **Instance** : `instance` — inventaire `instance/inventories/principal/hosts.yml` -- **Verdict** : ❌ NON CONFORME (51 OK · 1 echec · 0 saute) +- **Verdict** : ✅ CONFORME (52 OK · 0 echec · 0 saute) ## Preuves @@ -44,7 +44,7 @@ | P29 | Authentification : chaque role declare sa position | AFF-111 | ✅ OK | 30 role(s) serveur declares (interne-sans-auth 2, ldap-direct 2, sans-auth-humaine 19, socle-identite 2, web-sso 5) ; 2 lacune(s) nommee(s) : serveur_loki, serv | | P30 | SDN EVPN : zones, VNets et sous-reseaux derives | AFF-112 | ✅ OK | CONFORME : SDN EVPN, 3 zone(s), 15 VNet(s), 15 sous-reseau(x), aucune collision. | | P31 | Documentation : tout ce que le depot FAIT est nomme | — | ✅ OK | 52 scripts expliques et atteignables, 104 cibles make documentees, 62 roles avec README. | -| P32 | Intrants exiges par les roles : tous fournis | — | ✅ OK | CONFORME : 41 exigence(s) de role, toutes satisfaites (129 cle(s) declaree(s) par l'instance). | +| P32 | Intrants exiges par les roles : tous fournis | — | ✅ OK | CONFORME : 41 exigence(s) de role, toutes satisfaites (130 cle(s) declaree(s) par l'instance). | | P33 | Aucune collision de port entre roles co-localises | — | ✅ OK | CONFORME : 33 revendication(s) de port, aucune collision entre roles co-localises (38 groupes). | | P34 | Chaque document declare son lecteur | — | ✅ OK | 42 document(s) declarent leur lecteur (26 genere(s) exempte(s)). | | P35 | Toute application exigeant une base en a une au plan | — | ✅ OK | 5 application(s) exigeant une base l'ont toutes (4 entree(s) au registre). | @@ -55,15 +55,14 @@ | P40 | Parente : l'ecosysteme sait de quoi il descend | — | ✅ OK | Parente coherente : 4 depot(s), tous retrouves, tous porteurs d'un remote. | | P41 | Resolution d'instance : une seule, partagee | — | ✅ OK | Resolution unique : 48 script(s) passent par `inventory_rules`, 3 exemption(s) nommee(s). | | P42 | L'edge porte les noms qu'il publie | — | ✅ OK | 4 edge(s) emettent un certificat portant les noms publies (OPS-Chezlepro-lab/principal, OPS-Chezlepro/principal, OPS-Technolibre/principal, OPS-Patient0/product | -| P43 | Frontiere : le devis voit les machines du site | — | ✅ OK | Devis de la frontiere : 5 machine(s) du plan retrouvees, 57 regle(s) du site. | +| P43 | Frontiere : le devis voit les machines du site | — | ✅ OK | Devis de la frontiere : 5 machine(s) du plan retrouvees, 60 regle(s) du site. | | P44 | Integrations : le serveur avant ses clients | — | ✅ OK | 4 integration(s) appliquent leur serveur avant leurs clients. | | P45 | Pare-feu Proxmox : arme sur les VNet SDN, jamais ailleurs | — | ✅ OK | Le pare-feu Proxmox ne s'arme que sur un VNet SDN (4 cas evalues, dont un qui doit rendre VRAI). | | P46 | Plancher /etc/hosts : un seul role en decide | — | ✅ OK | Un seul maitre du plancher — roles/hosts_statiques/tasks/main.yml : manage_etc_hosts: false ; et le gabarit maitre est pose (roles/hosts_statiques/templates/hos | | P47 | Zones inverses : couvrir l'occupe, et rien de plus | — | ✅ OK | Les zones inverses couvrent l'occupe et rien de plus (5 cas evalues, dont un site a quatre zones et un tenant a une). | -| P48 | La carte d'orientation designe ce qui existe, et compte juste | — | ❌ ECHEC | La carte d'orientation ne dit plus vrai : - - « README de roles » : la carte annonce 61, le depot en compte 62 | +| P48 | La carte d'orientation designe ce qui existe, et compte juste | — | ✅ OK | La carte designe 84 chemin(s) qui existent, et ses 7 chiffres correspondent a la mesure. | | P49 | Registre des flux : la matrice d'audit est a jour | — | ✅ OK | Le registre des flux reproduit exactement ce que les `meta/flux.yml` declarent (113 lignes). | -| P50 | Silences : un refus muet est declare, place en dernier, et motive | — | ✅ OK | 2 silence(s) declare(s), tous en sequence > 1 (la plus haute des 122 regles `pass`), tous non consignes et tous motives. | +| P50 | Silences : un refus muet est declare, place en dernier, et motive | — | ✅ OK | 2 silence(s) declare(s), tous en sequence > 1 (la plus haute des 125 regles `pass`), tous non consignes et tous motives. | | P51 | Collections : toutes declarees, toutes epinglees | — | ✅ OK | 3 collection(s) et 2 bibliotheque(s) Python declarees et epinglees : ansible.posix==1.6.2, community.general==10.3.0, community.postgresql==3.10.2 | | P52 | Materialiser n'exige pas d'entrer dans le tenant | — | ✅ OK | `creer-vm` confirme par l'agent invite (API des hyperviseurs, deja utilisee pour creer), sans exiger d'entrer dans le tenant. |