From ece250ae491df58afdd7e7807e6c442bcca55324 Mon Sep 17 00:00:00 2001 From: Daniel Allaire Date: Mon, 3 Aug 2026 11:50:50 -0400 Subject: [PATCH] =?UTF-8?q?pare-feu=20Proxmox=20:=20un=20seul=20sch=C3=A9m?= =?UTF-8?q?a=20de=20nommage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Les IPSets portaient l'étiquette longue (`chez17_serveur_postgresql`), les groupes l'index court (`t17-srv-postgresql`) : deux conventions dans un même document. Tout porte maintenant `t-` et la même forme abrégée. La troncature reste propre à chaque objet — Proxmox est large sur les IPSets, étroit sur les groupes. Un nom peut être entier d'un côté et abrégé de l'autre ; chacun respecte sa contrainte, le préfixe reste commun. Vérifié : aucune collision d'IPSet, et tout renvoi `+X` d'une règle pointe vers un IPSet existant — 58 IPSets, 34 groupes, aucun orphelin. Preuves : 25 OK, 0 échec. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 12 ++++++++++++ scripts/devis_proxmox_fw.py | 29 ++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 446dc64..178ca6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,18 @@ Le préfixe porte maintenant l'**index** (`t17-`) plutôt que l'étiquette (`che rend la troncature bien plus rare, et une garde **échoue** sur toute collision plutôt que d'émettre un devis pareil. Exercée. +### Unifié — un seul schéma de nommage dans le devis +Les IPSets portaient l'étiquette longue (`chez17_serveur_postgresql`), les groupes l'index +court (`t17-srv-postgresql`) : deux conventions à lire dans un même document. Tout porte +désormais le préfixe `t-` et la même forme abrégée de rôle. + +La troncature reste **propre à chaque objet** : Proxmox est large sur les IPSets, étroit +(18 caractères) sur les groupes. Un nom peut donc être entier d'un côté et abrégé de l'autre — +chacun respecte sa contrainte, et le préfixe reste commun. + +Vérifié : aucune collision d'IPSet, et **tout renvoi `+X` d'une règle pointe vers un IPSet qui +existe** — 58 IPSets, 34 groupes, aucun orphelin. + ### Corrigé — l'affectation variait selon l'état du tenant Elle partait de `hotes_actifs`, avec un repli sur « tous » quand il n'y en avait aucun. Deux tenants donnaient donc deux comportements : Technolibre listait ses 14 VM (zéro actif → repli), diff --git a/scripts/devis_proxmox_fw.py b/scripts/devis_proxmox_fw.py index 6684877..f123fcf 100644 --- a/scripts/devis_proxmox_fw.py +++ b/scripts/devis_proxmox_fw.py @@ -44,13 +44,25 @@ from resoudre_flux import ( # noqa: E402 from devis_reseau import admin_de, decouvrir, inventaire_de, prefixe # noqa: E402 -def nom_ipset(role: str, etiquette: str) -> str: - return f"{etiquette}_{role}".lower() - - LONGUEUR_MAX_GROUPE = 18 # limite de Proxmox pour un nom de groupe de securite +def _role_court(role: str) -> str: + """Forme abregee d'un role, commune aux IPSets et aux groupes.""" + return role.replace("serveur_", "srv-").replace("client_", "cli-").replace("_", "-") + + +def nom_ipset(role: str, index: int) -> str: + """Nom d'IPSet. MEME prefixe que les groupes — `t17-` — pour qu'un seul schema de + nommage se lise dans tout le devis. + + Pas de troncature ici : Proxmox est large sur les IPSets, etroit sur les groupes. + Un nom peut donc etre entier cote IPSet et abrege cote groupe ; chacun respecte sa + contrainte, et le prefixe reste commun. + """ + return f"t{index}-{_role_court(role)}".lower() + + def nom_groupe(role: str, index: int) -> str: """Nom de groupe de securite, sous la limite de 18 caracteres de Proxmox. @@ -58,8 +70,7 @@ def nom_groupe(role: str, index: int) -> str: `chez17-`, ce qui laisse trois caracteres de plus au role et rend la troncature beaucoup plus rare. Les groupes sont a l'echelle du datacenter, d'ou le prefixe. """ - court = role.replace("serveur_", "srv-").replace("client_", "cli-").replace("_", "-") - return f"t{index}-{court}".lower()[:LONGUEUR_MAX_GROUPE] + return f"t{index}-{_role_court(role)}".lower()[:LONGUEUR_MAX_GROUPE] def _verifier_unicite(noms: list[str], tenant: str) -> None: @@ -106,7 +117,7 @@ def construire(tenants: list[tuple[str, str, dict]]) -> dict: continue membres = sorted({ips[h] for h in _hotes_du_groupe(data, groupe) if h in ips}) if membres: - ipsets[nom_ipset(groupe, etiquette)] = { + ipsets[nom_ipset(groupe, n["index"])] = { "role": groupe, "membres": membres, } @@ -131,8 +142,8 @@ def construire(tenants: list[tuple[str, str, dict]]) -> dict: sans_source.append(f"{groupe}:{','.join(_ports(fl))}") continue # Source par IPSet quand le pair est UN role : une seule liste a tenir. - source = (f"+{nom_ipset(pairs[0], etiquette)}" - if len(pairs) == 1 and nom_ipset(pairs[0], etiquette) in ipsets + source = (f"+{nom_ipset(pairs[0], n['index'])}" + if len(pairs) == 1 and nom_ipset(pairs[0], n["index"]) in ipsets else ",".join(srcs)) for port in _ports(fl): regles.append({