From add94f2cbdf1262919603e3b885f3cd9f41e8b95 Mon Sep 17 00:00:00 2001 From: Daniel Allaire Date: Tue, 25 Aug 2026 12:11:20 -0400 Subject: [PATCH] =?UTF-8?q?underlay=20:=20un=20SITE=20n'a=20pas=20d'index?= =?UTF-8?q?=20=E2=80=94=20le=20vestige=20est=20retire?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `index: 17` ne disait pas « voici mon adressage » : un site ne derive rien, ses machines vivent sur un reseau de fabric hors de toute derivation. Il disait UNE seule chose — quel supernet de tenant est le mien — pour autoriser un reseau du site a en occuper la bande basse (D-77). Un reste de la coincidence hebergeur<->tenant chez Chezlepro, qui est les deux a la fois ; ailleurs il aurait fallu inventer un index a un hebergeur qui n'heberge pas son propre ecosysteme. L'exception se declare desormais sur le RESEAU qui en a besoin, et elle NOMME le tenant dont elle occupe la bande basse (`bande_basse_de: OPS-Chezlepro`). Plus vrai : un seul reseau est concerne. Plus verifiable : le nom se resout dans le registre `tenants:`, donc une faute de frappe est refusee au lieu de passer. Quatre controles negatifs, tous refuses — tenant inconnu, exception absente, debordement sur la bande des zones, et le mauvais tenant nomme. 42 preuves vertes, les quatre devis du panneau OK. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 30 ++++++++++++++++++++++++++++++ scripts/underlay.py | 33 ++++++++++++++++++++++++++++----- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66c6236..08be3cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,35 @@ # CHANGELOG — Set-OPS +## 2026-08-25 — Un SITE n'a pas d'index : le vestige est retiré + +Le site portait `index: 17`. Ça n'a jamais voulu dire « voici mon adressage » — un site +ne dérive rien, ses machines vivent sur un réseau de fabric (`10.0.3.0/24`), hors de toute +dérivation. Ça voulait dire **une seule chose** : *quel supernet de tenant est le mien*, +pour autoriser un réseau du site à en occuper la bande basse (D-77). + +C'était un reste de la coïncidence hébergeur↔tenant chez Chezlepro, qui est les deux à la +fois. Ailleurs, ça aurait induit en erreur : un hébergeur qui n'héberge pas son propre +écosystème n'a aucun supernet à lui, et devait quand même inventer un index. + +**L'exception se déclare désormais sur le réseau qui en a besoin**, et elle **nomme** le +tenant dont elle occupe la bande basse : + +```yaml +- nom: management + segment_physique: true + bande_basse_de: OPS-Chezlepro + sous_reseau: 10.17.0.0/24 +``` + +Trois gains. C'est **plus vrai** — un seul réseau est concerné, pas le site entier. C'est +**plus lisible** — le lecteur voit pourquoi ce `/24` habite un `/16` qui n'est pas le sien. +Et c'est **vérifiable** : le nom se résout dans le registre `tenants:`, donc une faute de +frappe est refusée au lieu de passer silencieusement. + +Quatre contrôles négatifs, tous refusés : un tenant inconnu, l'exception absente alors que +le chevauchement existe, un débordement sur la bande des zones, et — le cas subtil — le +**mauvais** tenant nommé. + ## 2026-08-25 — Le SITE devient un écosystème complet : PKI, DNS, forge Le site portait **trois services sur les sept** que le modèle `origine` appelle le plus diff --git a/scripts/underlay.py b/scripts/underlay.py index 8f61132..e56131a 100644 --- a/scripts/underlay.py +++ b/scripts/underlay.py @@ -479,9 +479,31 @@ def valider(underlay: dict | None, if tenants_vlans is None or tenants_supernets is None: tenants_vlans, tenants_supernets = _tenants_reperes() t_supernets = [ipaddress.ip_network(s, strict=False) for s in tenants_supernets] - # Sans `index` declare, on ignore quel supernet est le SIEN : on retombe alors sur la - # regle stricte d'avant D-77 (aucun chevauchement), qui reste sure. - idx_site = index_site(underlay) + # UN SITE N'A PAS D'INDEX (2026-08-25). Il en portait un, et c'etait un vestige. + # + # Cette valeur ne disait pas « voici mon adressage » — le site ne derive rien, ses + # machines vivent sur un reseau de fabric. Elle disait une seule chose : « QUEL + # SUPERNET DE TENANT EST LE MIEN », pour autoriser un reseau du site a occuper sa + # bande basse. C'etait un reste de la coincidence hebergeur↔tenant chez Chezlepro, + # qui est a la fois les deux — et qui aurait induit en erreur partout ailleurs. + # + # L'exception se declare desormais SUR LE RESEAU qui en a besoin, et elle NOMME le + # tenant dont elle occupe la bande basse. C'est plus vrai (un seul reseau est + # concerne, pas le site entier) et plus verifiable : le nom se resout dans le registre + # d'allocation, donc une faute de frappe est refusee au lieu de passer. + alloc = allocations(underlay) + + def _supernet_hote(r: dict) -> tuple[ipaddress.IPv4Network | None, str | None]: + """Supernet dont ce reseau occupe la bande basse, et l'erreur s'il n'existe pas.""" + nom_t = str(r.get("bande_basse_de") or "").strip() + if not nom_t: + return None, None + if nom_t not in alloc: + return None, (f"reseau '{r.get('nom', '?')}': `bande_basse_de: {nom_t}` — ce " + f"nom n'est pas dans le registre `tenants:` du site. Sans " + f"allocation connue, on ne peut pas savoir quel supernet il " + f"occupe, ni verifier qu'il reste dans la bande basse.") + return ipaddress.ip_network(supernet_de(alloc[nom_t]), strict=False), None erreurs: list[str] = [] if mode_site: @@ -528,8 +550,9 @@ def valider(underlay: dict | None, # Chevaucher celui d'un AUTRE tenant reste une erreur — c'est ce qui empeche deux # sites de se joindre. Et deborder sur la bande haute de son propre supernet en # est une aussi : on entrerait en collision avec ses propres zones. - mien = ipaddress.ip_network(supernet_de(idx_site), strict=False) \ - if idx_site is not None else None + mien, err_bande = _supernet_hote(r) + if err_bande: + erreurs.append(err_bande) for ts in t_supernets: if not net.overlaps(ts): continue