ajoute la supervision : règles d'alerte Prometheus, relais ntfy, Uptime Kuma
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
d21c6ef544
commit
aa31b6112f
12 changed files with 432 additions and 0 deletions
72
ansible/roles/supervision/templates/alertmanager-ntfy.py.j2
Normal file
72
ansible/roles/supervision/templates/alertmanager-ntfy.py.j2
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
#!/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()
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
[Unit]
|
||||
Description=Relais Alertmanager -> ntfy (Syllabus)
|
||||
# Géré par Ansible (rôle supervision) — ne pas modifier à la main.
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/python3 /usr/local/sbin/alertmanager-ntfy.py
|
||||
Restart=on-failure
|
||||
# Durcissement minimal : ce service lit un secret (fichier webhook), pas de
|
||||
# raison qu'il écrive où que ce soit ou touche au reste du système.
|
||||
NoNewPrivileges=true
|
||||
ProtectSystem=strict
|
||||
PrivateTmp=true
|
||||
ReadOnlyPaths=/root/.alertes-webhook
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Loading…
Add table
Add a link
Reference in a new issue