# TESM-Lizenzserver Ausgabe und Verwaltung der Lizenzen für TESM: Kunde -> Ticket -> Lizenz, Aktivierung online und offline, Kundenportal, Selbstbedienung, Versand über MS Graph und eine Hierarchie aus Unter-Lizenzservern. **Dieses Repository enthält genau das, was zum Installieren und Betreiben des Lizenzservers gebraucht wird** -- nichts darüber hinaus: ``` apps/tesm-license die Anwendung packages/tesm-core gemeinsamer Kern (Anmeldung, Rechte, Sicherung, nginx, ...) packages/tesm-licensing Lizenzprotokoll, gemeinsame Hälfte packages/tesm-licensing-server Lizenzprotokoll, Serverhälfte: ausstellen, erneuern, antworten deploy/ install.sh, update.sh, release.sh, systemd, privilegierter Helfer docs/ Betrieb und Sicherheit ``` Die verwaltete Anwendung liegt hier **nicht** mit drin. | Wo sonst noch | | |---|---| | [alientim/tesm](https://gitea.int.eertmoed.net/alientim/tesm) | TESM selbst | | [alientim/TESM-DEV](https://gitea.int.eertmoed.net/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 ```bash sudo bash deploy/install.sh --app tesm-license --https --domain lizenz.firma.de sudo -u tesm-license tesm-license-admin init-key sudo -u tesm-license tesm-license-admin bootstrap sudo -u tesm-license tesm-license-admin create-admin ``` **`init-key` erzeugt den Signaturschlüssel dieses Servers. Sichern Sie ihn sofort.** Ohne ihn lässt sich keine ausgestellte Lizenz mehr erneuern, und Kunden müssten einen Ausstellerwechsel bestätigen. 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 der Dienst ohne `--https` schlicht auf Port 80. Der Lizenzserver darf neben TESM auf demselben Host laufen; nginx unterscheidet die beiden am Servernamen, und jede Installation hat ihren eigenen `SITE_KEY` für nginx-Site, logrotate, Zertifikate und Sitzungscookie. ### Aktualisieren ```bash sudo bash deploy/update.sh --app tesm-license ``` Vor jedem Update entsteht ein vollständiges Backup, danach läuft ein Health-Check mit automatischem Rollback. --- ## Betrieb von der Kommandozeile ```bash sudo -u tesm-license tesm-license-admin status sudo -u tesm-license tesm-license-admin init-key # Signaturschlüssel sudo -u tesm-license tesm-license-admin bootstrap # Grunddaten sudo -u tesm-license tesm-license-admin create-admin sudo -u tesm-license tesm-license-admin migrate-legacy # Altbestand übernehmen ``` `migrate-legacy` liest die SQLite-Datei eines alten Lizenzservers **nur lesend**, übernimmt dessen Signaturschlüssel und stellt die Lizenzen mit ihrer restlichen Laufzeit neu aus. Wird der Schlüssel nicht übernommen, müssen Kunden den Ausstellerwechsel einmal bestätigen. --- ## Release bauen ```bash git tag -a v2.0.0 -m "TESM-Lizenzserver 2.0.0" && git push origin v2.0.0 bash deploy/release.sh v2.0.0 ``` Heraus kommt `tesm-license-v2.0.0.tar.gz` samt SHA-256. Der Name kommt aus dem Repository -- ein Lizenzserver-Release, das `tesm-...` heisst, verwechselt man genau einmal. --- ## Lizenzprotokoll in Kurzform * Ed25519, getrennte Signaturkontexte je Nachrichtenart (`tesm/license-file/v2\0`) -- eine Signatur aus einem Kontext ist in einem anderen nicht verwendbar. * Kanonisches JSON, damit dieselbe Aussage genau eine Signatur hat. * Nonce gegen Wiedereinspielung, `seq` gegen das Zurückrollen auf eine ältere Lizenz. * Aussteller wird beim ersten Kontakt gemerkt (TOFU); ein Wechsel muss ausdrücklich bestätigt werden. * Der Fingerabdruck der Maschine enthält **keinen** Hostnamen -- Umbenennen brach im Vorgänger die Bindung. * Offline-Aktivierung über einen kurzen Code in beide Richtungen; die Lizenz bleibt auf dem Server als "Aktivierung offen" markiert, bis sie zurückkommt. * Keine Lizenz ohne `master_endpoint`: eine Ausstellung ohne Endpunkt wird abgelehnt statt eine Lizenz zu erzeugen, die sich nie aktivieren kann. --- ## Dokumentation | | | |---|---| | [docs/BETRIEB.md](docs/BETRIEB.md) | Installation, Update, HTTPS, Sicherung, Fehlersuche | | [docs/SICHERHEIT.md](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 * **Keine doppelte `licensing.py`.** Ein Paket, das beide Anwendungen installieren -- statt zweier Dateien, die byte-identisch bleiben sollen. * **Kein root für die Anwendung.** Ein einziger allowlisted Helfer mit Argumentprüfung. * **CSRF-Schutz überhaupt.** Der Vorgänger hatte keinen. * **Rechte werden serverseitig geprüft**, nicht nur im Template ausgeblendet. * **Verschachtelte Datenbankverbindungen sind ein Fehler**, kein Deadlock. --- ## Von einer Installation der Fassung 1.x Eine einzelne Datei genügt -- sie lädt das Release selbst: ```bash curl -fsSLO https://gitea.int.eertmoed.net/alientim/tesm-license/raw/branch/main/deploy/upgrade.sh sudo bash upgrade.sh --app tesm-license ``` Sichert die alte Installation, schaltet sie ab, installiert diese Fassung und übernimmt die Daten. Einzelheiten und was **nicht** mitkommt: [docs/BETRIEB.md](docs/BETRIEB.md).