Die Abmeldung hat weiterhin nicht ausgeloest. Zwei Gruende, beide fuer sich ausreichend: * **save_session** schreibt ``idle_expires_at`` bei jeder Anfrage, die die Sitzung anfasst -- ein neu erzeugtes CSRF-Token genuegt. Die Pruefung in ``open_session`` lief damit ins Leere. Sitzungsdaten werden weiter gespeichert, nur die Fristen bleiben stehen. Dieselbe Stelle benutzte ausserdem ``idle_minutes`` statt der einstellbaren Zeit; bei der Vorgabe von dreissig Minuten fiel das nicht auf. * **Der Kopf allein reicht nicht.** Er setzt voraus, dass der Browser das aktuelle Skript faehrt -- ein Tab, der seit gestern Abend offen ist, faehrt das alte und schickt ihn nicht. Genau dieser Tab ist der Fall, um den es geht. Der Server weiss es ohne Zutun des Browsers: die Endpunkte, die eine Kachel oder ein Protokoll nachlaedt, sind als Aktualisierungsausschnitt gekennzeichnet (``@fragment``) und gelten damit immer als automatisch. ``request.endpoint`` steht in ``open_session`` noch nicht -- Flask oeffnet die Sitzung vor dem Routing --, deshalb sieht die Erkennung dort selbst nach. Dass es auf dem Lizenzserver zuverlaessig funktionierte, war der Hinweis: dort pollt keine Kachel. Dazu ein Kopf ``X-Session-Expired`` fuer Seiten, die auch oeffentlich antworten. Die Statusuebersicht liefert nach dem Ablauf eine 200 mit den oeffentlichen Kacheln -- am Status ist der Verlust der Sitzung also nicht zu erkennen, und der offene Tab zeigte weiter eine Oberflaeche, als sei alles in Ordnung. Jetzt laedt er neu und zeigt die Anmeldemaske. Version 2.0.4. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TESM
Verwaltung von PoE-Geräten und Aruba-Switchen: Inventar, Zustandsüberwachung, Portsteuerung, Neustart (PoE, SSH, RPC), DHCP über Kea, Dateifreigaben, Wartung über SSH, Protokolle, Papierkorb, verschlüsselte Ein- und Ausfuhr und ein SSH-Terminal im Browser.
Dieses Repository enthält genau das, was zum Installieren und Betreiben von TESM gebraucht wird -- nichts darüber hinaus:
apps/tesm die Anwendung
packages/tesm-core gemeinsamer Kern (Anmeldung, Rechte, Sicherung, nginx, ...)
packages/tesm-licensing Lizenzprotokoll, Clientseite
deploy/ install.sh, update.sh, release.sh, systemd, privilegierter Helfer
docs/ Betrieb und Sicherheit
Die Serverhälfte des Lizenzprotokolls (tesm-licensing-server: ausstellen,
erneuern, Antworten signieren) liegt nicht hier. TESM verifiziert Lizenzen
und stellt Anfragen; den Code zum Ausstellen soll ein Client nicht einmal
mitbringen.
| Wo sonst noch | |
|---|---|
| alientim/tesm-license | der Lizenzserver |
| alientim/TESM-DEV | Entwicklung: beide Anwendungen, Tests, Architekturdoku |
Zweige
| Zweig | Inhalt |
|---|---|
main |
dieser Neubau (Version 2.0.0) |
SONNET5 |
der Stand davor, unverändert aufbewahrt |
Installation
sudo bash deploy/install.sh --app tesm --https
sudo -u tesm tesm-admin create-admin
Danach https://<host>/. Ohne --domain entsteht ein selbstsigniertes
Zertifikat; der Browser warnt einmal, die Verbindung ist verschlüsselt.
Mit öffentlichem Namen und Let's Encrypt stattdessen:
sudo bash deploy/install.sh --app tesm --https --domain tesm.firma.de --acme-email it@firma.de
Zielzustand: Port 443 mit TLS, Port 80 leitet dorthin um -- ausser dem ACME-Pfad, der erreichbar bleiben muss, sonst kann Let's Encrypt nie erneuern.
Sitzt ein eigener Reverse Proxy davor, der TLS beendet, läuft TESM ohne
--https schlicht auf Port 80.
Eine zweite Installation zum Testen stört die laufende nicht:
sudo bash deploy/install.sh --app tesm --instance test --port 5100 --http-port 8080
Jede Instanz bekommt eigene Datenbank, eigene Schlüssel, eigene nginx-Site und ein eigenes Sitzungscookie.
Aktualisieren
sudo bash deploy/update.sh --app tesm
Das lädt ein Release, entpackt es und ruft dessen install.sh auf. Vor jedem
Update entsteht ein vollständiges Backup -- unabhängig davon, ob sich das
Schema geändert hat -- und danach läuft ein Health-Check mit automatischem
Rollback.
Betrieb von der Kommandozeile
sudo -u tesm tesm-admin status # Zustand der Installation
sudo -u tesm tesm-admin create-admin # Konto anlegen oder zurücksetzen
sudo -u tesm tesm-admin check-now # Überwachungsdurchlauf sofort
sudo -u tesm tesm-admin housekeeping # Sitzungen und Protokolle aufräumen
sudo -u tesm tesm-admin web-setup --https # nginx und TLS einrichten
Umzug aus dem alten TESM
Ein Export des Vorgängers lässt sich übersetzen und dann über den normalen Import einlesen -- Clients, Switche, Zugangsdaten und die DHCP-Konfiguration:
sudo -u tesm tesm-admin convert-legacy tesm_export_20260813_195455.json --dry-run
--dry-run zeigt nur den Bericht. Ohne die Option entsteht eine Datei im
neuen Format, die unter Verwaltung -> Sicherung eingelesen wird. Der Bericht
nennt ausdrücklich, was nicht übersetzt werden kann (lokale Konten,
Rechte, Verzeichnisdienst, Webserver) -- das ist von Hand nachzuziehen.
Die Passphrase gehört an die verdeckte Eingabeaufforderung. --passphrase
existiert nur für Automatisierung: es schreibt sie in Shell-Historie und
Prozessliste.
Release bauen
git tag -a v2.0.0 -m "TESM 2.0.0" && git push origin v2.0.0
bash deploy/release.sh v2.0.0
Heraus kommt tesm-v2.0.0.tar.gz samt SHA-256. Der Name kommt aus dem
Repository, nicht aus einer festen Zeichenkette.
Dokumentation
| docs/BETRIEB.md | Installation, Update, HTTPS, Sicherung, Fehlersuche |
| docs/SICHERHEIT.md | Anmeldung, Sitzungen, CSRF, Geheimnisse, Rechtetrennung |
Aufbau und Entwurfsentscheidungen stehen in docs/ARCHITEKTUR.md im
Entwicklungsrepository, ebenso die Tests.
Was diese Fassung anders macht
Ein Neubau. Die Fehler des Vorgängers sind bekannt; an den Stellen, an denen sie entstanden sind, steht jetzt ein Kommentar, der erklärt, warum es hier anders gelöst ist. Die wichtigsten:
- Kein root für die Anwendung. Ein einziger allowlisted Helfer mit
Argumentprüfung statt eines Webprozesses als
root. - CSRF-Schutz überhaupt. Der Vorgänger hatte keinen.
- Rechte werden serverseitig geprüft, nicht nur im Template ausgeblendet.
- Die nginx-Site wird bei jedem Lauf inhaltlich verglichen und erneuert. Ein
falscher
alias-Pfad überlebte im Vorgänger jahrelang jedes Update. - Jede erzeugte Konfiguration wird vor dem Übernehmen geprüft -- nginx wie Kea. Eine fehlerhafte Datei fällt beim Schreiben auf, nicht erst beim nächsten Start des Dienstes.
- Kein Hostname im Lizenz-Fingerabdruck. Umbenennen brach die Bindung.
- Zwei Installationen stören sich nicht -- eigener
SITE_KEYfür nginx-Site, netplan, logrotate, Zertifikate und Sitzungscookie. - Verschachtelte Datenbankverbindungen sind ein Fehler, kein Deadlock.