diff --git a/scripts/appliquer_proxmox_fw.py b/scripts/appliquer_proxmox_fw.py index ebb09ce..abdfcc1 100644 --- a/scripts/appliquer_proxmox_fw.py +++ b/scripts/appliquer_proxmox_fw.py @@ -80,7 +80,9 @@ def _regle_cle(r: dict) -> tuple: str(r.get("action") or "").upper(), str(r.get("source") or ""), str(r.get("proto") or ""), - str(r.get("dport") or "")) + str(r.get("dport") or ""), + # Le devis dit `icmp_type`, l'API de Proxmox rend `icmp-type`. + str(r.get("icmp_type") or r.get("icmp-type") or "")) def _prefixes_retires() -> tuple[str, ...]: @@ -260,7 +262,8 @@ def appliquer(api: Cluster, p: dict) -> int: for r in g["regles"]: corps = {"type": str(r.get("sens", "in")).lower(), "action": r["action"], "enable": 1, "comment": str(r.get("via") or g.get("role", ""))[:100]} - for cle, champ in (("source", "source"), ("proto", "proto"), ("dport", "dport")): + for cle, champ in (("source", "source"), ("proto", "proto"), ("dport", "dport"), + ("icmp_type", "icmp-type")): if r.get(cle): corps[champ] = r[cle] _fait(api(f"/cluster/firewall/groups/{n}", "POST", corps), f"regle de {n}") diff --git a/scripts/devis_proxmox_fw.py b/scripts/devis_proxmox_fw.py index 207e640..3e5b68b 100644 --- a/scripts/devis_proxmox_fw.py +++ b/scripts/devis_proxmox_fw.py @@ -116,6 +116,21 @@ def _ports(fl: dict) -> list[str]: return fixes +def _cibles(fl: dict) -> list[dict]: + """Ce qu'une regle vise : un port TCP/UDP, ou un TYPE ICMP. + + L'ICMP N'A PAS DE PORT (2026-09-28). Un flux `protocole: icmp` porte son type dans + `port` (`echo-request`). `_ports` ne garde que les nombres : le type etait range parmi + les « ports derives » et le flux SAUTE. Le ping de supervision, pourtant declare par + `serveur_debian`, n'a donc jamais eu de regle ; la premiere VM passee en `REJECT` est + devenue « morte » pour Icinga (100 % de pertes) tout en servant parfaitement. + """ + if str(fl.get("protocole", "tcp")).lower() == "icmp": + p = fl["port"] + return [{"proto": "icmp", "icmp_type": str(t)} for t in (p if isinstance(p, list) else [p])] + return [{"proto": fl.get("protocole", "tcp"), "dport": port} for port in _ports(fl)] + + def construire(tenants: list[tuple[str, str, dict]]) -> dict: """Le devis, en structure. Un bloc par tenant federe.""" flux_par_role = charger_flux() @@ -201,11 +216,11 @@ def construire(tenants: list[tuple[str, str, dict]]) -> dict: if not admin_de(nom): continue utilises.add(cle) - for port in _ports(fl): + for cible in _cibles(fl): regles.append({ "action": "ACCEPT", "sens": "IN", "source": f"+{cle}", "via": "administration", - "proto": fl.get("protocole", "tcp"), "dport": port, + **cible, "raison": fl.get("raison", ""), }) continue @@ -217,12 +232,11 @@ def construire(tenants: list[tuple[str, str, dict]]) -> dict: utilises.add(cle) else: source, via = ",".join(srcs_pair), pair - for port in _ports(fl): + for cible in _cibles(fl): regles.append({ "action": "ACCEPT", "sens": "IN", "source": source, "via": via, - "proto": fl.get("protocole", "tcp"), - "dport": port, + **cible, "raison": fl.get("raison", ""), }) # GARDE ANTI-LOCKOUT. Le plan de gestion du tenant est resolu en