84 lines
4 KiB
Python
84 lines
4 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""L'exportateur PostgreSQL sert en TLS, et Prometheus le lit en HTTPS verifie.
|
||
|
|
|
||
|
|
POURQUOI (2026-10-12). Le 9187 etait le seul port de metriques en clair, chez les
|
||
|
|
locataires comme au site — dette inscrite au registre le 2026-09-14. Un seul interrupteur
|
||
|
|
decide des deux bouts : `serveur_postgresql_tls_actif`, que la declaration de l'exportateur
|
||
|
|
nomme (`tls_si`) et que Prometheus lit dans les hostvars de chaque cible.
|
||
|
|
"""
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import base64
|
||
|
|
import sys
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
import jinja2
|
||
|
|
import yaml
|
||
|
|
|
||
|
|
RACINE = Path(__file__).resolve().parents[2]
|
||
|
|
PG = RACINE / "roles/serveur_postgresql"
|
||
|
|
|
||
|
|
|
||
|
|
def rendre_prometheus(tls_par_hote: dict[str, bool]) -> dict:
|
||
|
|
meta = PG / "meta/metriques.yml"
|
||
|
|
# LES FILTRES D'ANSIBLE LUI-MEME (intersect, extract, regex_replace, b64decode...) :
|
||
|
|
# un rendu avec des imitations prouverait les imitations.
|
||
|
|
from ansible.plugins.filter.core import FilterModule as Coeur
|
||
|
|
from ansible.plugins.filter.mathstuff import FilterModule as Maths
|
||
|
|
env = jinja2.Environment(extensions=["jinja2.ext.do"])
|
||
|
|
env.filters.update(Coeur().filters())
|
||
|
|
env.filters.update(Maths().filters())
|
||
|
|
hotes = sorted(tls_par_hote)
|
||
|
|
hostvars = {h: {"ansible_host": f"10.0.0.{i + 1}", "serveur_postgresql_tls_actif": v}
|
||
|
|
for i, (h, v) in enumerate(sorted(tls_par_hote.items()))}
|
||
|
|
rendu = env.from_string((RACINE / "roles/serveur_prometheus/templates/prometheus.yml.j2")
|
||
|
|
.read_text(encoding="utf-8")).render(
|
||
|
|
serveur_prometheus_intervalle="15s", serveur_prometheus_metriques_tls=True,
|
||
|
|
serveur_prometheus_metriques_ca="/etc/step/certs/root_ca.crt",
|
||
|
|
serveur_prometheus_groupe_metriques="client_metrique", serveur_prometheus_port_node=9100,
|
||
|
|
serveur_prometheus_cibles_supplementaires=[],
|
||
|
|
groups={"client_metrique": hotes, "hotes_actifs": hotes, "serveur_postgresql": hotes},
|
||
|
|
hostvars=hostvars,
|
||
|
|
serveur_prometheus_declarations={"results": [{
|
||
|
|
"item": {"path": str(meta)},
|
||
|
|
"content": base64.b64encode(meta.read_bytes()).decode()}]},
|
||
|
|
)
|
||
|
|
return {j["job_name"]: j for j in yaml.safe_load(rendu)["scrape_configs"]}
|
||
|
|
|
||
|
|
|
||
|
|
def main() -> int:
|
||
|
|
echecs: list[str] = []
|
||
|
|
|
||
|
|
expo = (yaml.safe_load((PG / "meta/metriques.yml").read_text(encoding="utf-8")) or {}).get("exportateur") or {}
|
||
|
|
if expo.get("tls_si") != "serveur_postgresql_tls_actif":
|
||
|
|
echecs.append(f"meta/metriques.yml : tls_si = {expo.get('tls_si')!r}, attendu serveur_postgresql_tls_actif")
|
||
|
|
|
||
|
|
flux = yaml.safe_load((PG / "meta/flux.yml").read_text(encoding="utf-8"))["flux"]
|
||
|
|
f9187 = next((f for f in flux if str(f.get("port")) == "9187"), {})
|
||
|
|
if f9187.get("chiffrement") != "tls":
|
||
|
|
echecs.append(f"le registre dit 9187 `{f9187.get('chiffrement')}`, attendu `tls`")
|
||
|
|
|
||
|
|
taches = (PG / "tasks/main.yml").read_text(encoding="utf-8")
|
||
|
|
if "--web.config.file=" not in taches or "serveur_postgresql_exportateur_web_config" not in taches:
|
||
|
|
echecs.append("l'exportateur ne recoit pas `--web.config.file`")
|
||
|
|
if "setops-pg-exportateur-cert-sync" not in taches:
|
||
|
|
echecs.append("l'exportateur n'est pas abonne au renouvellement du certificat")
|
||
|
|
|
||
|
|
jobs = rendre_prometheus({"data-sql-01": True, "data-sql-02": True})
|
||
|
|
pg = jobs.get("postgresql", {})
|
||
|
|
if pg.get("scheme") != "https" or (pg.get("tls_config") or {}).get("ca_file") != "/etc/step/certs/root_ca.crt":
|
||
|
|
echecs.append(f"toutes cibles TLS : job postgresql = {pg}, attendu https + ca_file")
|
||
|
|
jobs = rendre_prometheus({"data-sql-01": True, "data-sql-02": False})
|
||
|
|
if jobs.get("postgresql", {}).get("scheme") == "https":
|
||
|
|
echecs.append("une cible sans TLS : le job ne doit pas passer en https (il la perdrait)")
|
||
|
|
|
||
|
|
for e in echecs:
|
||
|
|
print(f"ECHEC : {e}")
|
||
|
|
if not echecs:
|
||
|
|
print("OK : l'exportateur PostgreSQL sert en TLS ; Prometheus le lit en HTTPS verifie sur le meme interrupteur.")
|
||
|
|
return 1 if echecs else 0
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
raise SystemExit(main())
|