#!/usr/bin/env python3 """Relais local : reçoit le webhook JSON d'Alertmanager, le transforme en notification ntfy. Géré par Ansible (rôle supervision) — ne pas modifier à la main. N'écoute que sur 127.0.0.1 : jamais exposé en dehors du serveur. L'URL ntfy (avec le topic) est un secret : lue depuis {{ supervision_fichier_webhook }} à chaque notification, jamais mise en cache, jamais journalisée. """ import http.server import json import urllib.request FICHIER_WEBHOOK = "{{ supervision_fichier_webhook }}" ADRESSE = ("127.0.0.1", {{ supervision_port_relais }}) def lire_url_ntfy(): with open(FICHIER_WEBHOOK, encoding="utf-8") as f: return f.read().strip() class Gestionnaire(http.server.BaseHTTPRequestHandler): def do_POST(self): longueur = int(self.headers.get("Content-Length", 0)) corps = self.rfile.read(longueur) try: charge = json.loads(corps) except ValueError: self.send_response(400) self.end_headers() return try: url_ntfy = lire_url_ntfy() except OSError: self.send_response(500) self.end_headers() return for alerte in charge.get("alerts", []): statut = alerte.get("status", "inconnu") nom = alerte.get("labels", {}).get("alertname", "?") resume = ( alerte.get("annotations", {}).get("description") or alerte.get("annotations", {}).get("summary") or nom ) titre = f"[{statut.upper()}] {nom}" requete = urllib.request.Request( url_ntfy, data=resume.encode("utf-8"), method="POST", headers={ "Title": titre, "Priority": "high" if statut == "firing" else "default", }, ) try: urllib.request.urlopen(requete, timeout=5) except Exception: pass # ne bloque jamais Alertmanager ; vérifier manuellement en cas de doute self.send_response(200) self.end_headers() def log_message(self, format, *args): # silencieux : rien de secret à tracer non plus pass if __name__ == "__main__": serveur = http.server.HTTPServer(ADRESSE, Gestionnaire) serveur.serve_forever()