Rechtesystem-Lücke schließen: Live-Log war nur @login_required statt admin-geschützt

Vollständiges Audit aller Routen gegen das Rechtesystem durchgeführt. Die
Nav-Sichtbarkeit stufte "Live" (Live-Log) bereits korrekt als admin-only ein
(_nav_key_visible: logs_live -> user.is_admin), die zugehörigen Routen
/logs und /get_log prüften das aber nie tatsächlich — nur @login_required.
Jeder eingeloggte Benutzer, unabhängig von seinen Gruppen-Rechten, konnte
das Live-Log damit direkt per URL aufrufen, obwohl die Sidebar es korrekt
ausblendete.

- /logs: fehlende is_admin-Prüfung ergänzt (Flash + Redirect, konsistent zu
  activity_log()/users()/groups()/settings()).
- /get_log: fehlende is_admin-Prüfung ergänzt (403, da per AJAX abgerufen).

Alle anderen neu hinzugekommenen Seiten (Benutzer, Gruppen, Systemein-
stellungen, Im-/Export, Änderungslog, Jetzt-prüfen-Trigger) waren bereits
korrekt und bewusst exklusiv auf is_admin geprüft — dort gibt es keine
sinnvolle granularere Rechte-Stufe unterhalb von Admin (Gruppenverwaltung
steuert das Rechtesystem selbst, Systemeinstellungen/Import-Export/manuelle
Prüfung wirken global). Zugangsdaten bleiben bewusst an switches.*-Rechte
gekoppelt (bestehende, dokumentierte Design-Entscheidung). README um eine
Übersicht ergänzt, welche Bereiche bewusst ohne granulare Rechte auskommen
und warum.

Mit Testbenutzer ohne jede Gruppenzugehörigkeit verifiziert: /logs liefert
jetzt 302 (Redirect), /get_log liefert 403 statt beide zuvor 200.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-10 16:01:39 +02:00
co-authored by Claude Sonnet 5
parent c4f682b5de
commit 52b14b8ef7
2 changed files with 16 additions and 0 deletions
+5
View File
@@ -1626,6 +1626,8 @@ def _ssh_terminal_inner(ws):
@app.route("/get_log")
@login_required
def get_log():
if not current_user.is_admin:
return "Keine Berechtigung.", 403
latest_log = _latest_log_file()
if not latest_log:
return "Keine Logfiles gefunden."
@@ -1645,6 +1647,9 @@ def get_log():
@app.route("/logs")
@login_required
def logs():
if not current_user.is_admin:
flash("Nur Admins dürfen das Live-Log einsehen.", "danger")
return redirect(url_for("index"))
interval = int(get_setting("interval", 5))
latest_log = _latest_log_file()