diff --git a/scripts/devis_reseau.py b/scripts/devis_reseau.py index fb0041e..57d3043 100644 --- a/scripts/devis_reseau.py +++ b/scripts/devis_reseau.py @@ -477,8 +477,15 @@ def admin_de(nom_instance: str) -> list[str]: data = yaml.safe_load(fichier.read_text(encoding="utf-8")) or {} if isinstance(data, dict) and data.get("nftables_admin_ssh"): src = data["nftables_admin_ssh"] - return [str(s) for s in src] if isinstance(src, list) else [str(src)] - return [] + recus = [str(s) for s in src] if isinstance(src, list) else [str(src)] + return sorted(set(recus) | set(_tunnel_de(nom_instance))) + return sorted(set(_tunnel_de(nom_instance))) + + +def _tunnel_de(nom_instance: str) -> list[str]: + """Le tunnel du locataire : MEME derivation que nftables (`tunnel_admin_de`).""" + from inventory_rules import tunnel_admin_de + return tunnel_admin_de(DOSSIER_INSTANCES / nom_instance) def admin_tous_tenants() -> list[str]: diff --git a/scripts/inventory_rules.py b/scripts/inventory_rules.py index 562ce6c..e801704 100644 --- a/scripts/inventory_rules.py +++ b/scripts/inventory_rules.py @@ -751,6 +751,28 @@ def reseau_vpn_locataire(index: int) -> str: return f"10.{int(index)}.29.0/24" +def tunnel_admin_de(base: Path) -> list[str]: + """Le reseau du tunnel d'administration d'UN locataire (dossier `base`), ou []. + + UNE SEULE DERIVATION, DEUX CONSOMMATEURS (2026-09-28). nftables (dans les VM) et le + pare-feu de Proxmox (devant elles) doivent admettre les MEMES sources d'administration. + nftables ajoutait ce tunnel a l'intrant `nftables_admin_ssh` ; le devis Proxmox, lui, + ne lisait que l'intrant. Filtre par Proxmox, Technolibre refusait donc le SSH venu de + son propre tunnel, que ses machines, elles, acceptaient. + + AUCUN PAIR ACTIF, AUCUNE SOURCE : ouvrir le SSH a un tunnel que personne n'emprunte + n'apporterait rien, sinon une porte. + """ + try: + pairs = charger_acces(base / "plan" / "acces.yml").get("acces_admin_vpn") or {} + index = charger_nomenclature(base / "plan" / "nomenclature.yml").get("index") + except (OSError, ValueError): + return [] + actifs = [n for n, c in pairs.items() + if isinstance(c, dict) and str(c.get("etat", "present")) == "present"] + return [reseau_vpn_locataire(index)] if (actifs and index is not None) else [] + + def port_vpn_locataire(index: int) -> int: return 52000 + int(index) diff --git a/scripts/resoudre_flux.py b/scripts/resoudre_flux.py index 647caca..a6bb20f 100644 --- a/scripts/resoudre_flux.py +++ b/scripts/resoudre_flux.py @@ -238,16 +238,8 @@ def _tunnel_admin_locataire() -> list[str]: AUCUN PAIR, AUCUNE SOURCE : declarer un reseau que personne n'emprunte ouvrirait le SSH de toutes ses machines a un tunnel qui n'existe pas. """ - from inventory_rules import charger_acces, charger_nomenclature, reseau_vpn_locataire - base = INSTANCE - try: - pairs = charger_acces(base / "plan" / "acces.yml").get("acces_admin_vpn") or {} - index = charger_nomenclature(base / "plan" / "nomenclature.yml").get("index") - except (OSError, ValueError): - return [] - actifs = [n for n, c in pairs.items() - if isinstance(c, dict) and str(c.get("etat", "present")) == "present"] - return [reseau_vpn_locataire(index)] if (actifs and index is not None) else [] + from inventory_rules import tunnel_admin_de + return tunnel_admin_de(INSTANCE) def _ip_par_hote(data: dict) -> dict[str, str]: