administration : nftables et Proxmox admettent les memes sources

Le devis Proxmox ne lisait que nftables_admin_ssh ; nftables y ajoutait le
tunnel du locataire. Filtre par Proxmox, Technolibre refusait le SSH de son
propre tunnel. Une derivation, tunnel_admin_de, pour les deux.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Daniel Allaire 2026-09-28 15:39:37 -04:00
parent 8804d67dbf
commit 67fd3ab6b7
3 changed files with 33 additions and 12 deletions

View file

@ -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]:

View file

@ -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)

View file

@ -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]: