Set-OPS-Public/scripts/verifier_flux_site.py

66 lines
2.6 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""Chaque machine du site a-t-elle ses regles nftables generees, AVANT de deployer ?
POURQUOI (2026-10-13, premier site construit depuis zero). `nftables_baseline` cherche le
jeu de regles DERIVE des flux (`flux-genere/<machine>.nft`, a cote de la carte du site) ;
absent, il pose en silence son GABARIT GENERIQUE, qui ne connait aucun flux reel. Au site de
TechnoLibre, `make flux` n'avait jamais tourne : les neuf machines seraient nees avec un pare-
feu qui refuse leurs propres services, et rien ne l'aurait dit avant le premier refus.
Lit l'inventaire du site (donc `SETOPS_UNDERLAY` s'il est pose) et refuse si une machine
active qui arme son pare-feu n'a pas son fichier. `--inventaire FICHIER` lit un inventaire
deja rendu (JSON de `site_inventaire.py --list`) — c'est ainsi que le test l'eprouve.
"""
from __future__ import annotations
import argparse
import json
import subprocess
import sys
from pathlib import Path
RACINE = Path(__file__).resolve().parents[1]
def manquants(inv: dict) -> list[str]:
hv = (inv.get("_meta") or {}).get("hostvars") or {}
actifs = ((inv.get("hotes_actifs") or {}).get("hosts")) or []
out = []
for h in sorted(actifs):
v = hv.get(h) or {}
if not v.get("nftables_baseline_enabled", False):
continue
f = str(v.get("nftables_baseline_ruleset_genere") or "")
if not f or not Path(f).is_file():
out.append(f"{h} : {f or '(aucun chemin)'}")
return out
def main(argv: list[str]) -> int:
ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
ap.add_argument("--inventaire", default="")
a = ap.parse_args(argv)
if a.inventaire:
inv = json.loads(Path(a.inventaire).read_text(encoding="utf-8"))
else:
r = subprocess.run([sys.executable, str(RACINE / "scripts" / "site_inventaire.py"),
"--list"], capture_output=True, text=True, cwd=RACINE)
if r.returncode != 0:
print("Inventaire du site illisible :\n" + r.stderr.strip()[:400], file=sys.stderr)
return 2
inv = json.loads(r.stdout)
m = manquants(inv)
if m:
print("Refus : ces machines du site n'ont pas leurs regles nftables generees — leur "
"pare-feu retomberait sur le gabarit generique :", file=sys.stderr)
for x in m:
print(f" - {x}", file=sys.stderr)
print("Lancer `make flux` (avec le meme SETOPS_UNDERLAY), puis relancer.", file=sys.stderr)
return 2
print("OK : chaque machine active du site a ses regles nftables generees.")
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))