diff --git a/README.md b/README.md index 5998478..28924d1 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ # TESM-Lizenzserver -Ausgabe und Verwaltung der Lizenzen fuer TESM: Kunde -> Ticket -> Lizenz, -Aktivierung online und offline, Kundenportal, Selbstbedienung, Versand ueber +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 enthaelt genau das, was zum Installieren und Betreiben des -Lizenzservers gebraucht wird** -- nichts darueber hinaus: +**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 Haelfte -packages/tesm-licensing-server Lizenzprotokoll, Serverhaelfte: ausstellen, erneuern, antworten +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 ``` @@ -28,7 +28,7 @@ Die verwaltete Anwendung liegt hier **nicht** mit drin. | Zweig | Inhalt | |---|---| | `main` | dieser Neubau (Version 2.0.0) | -| `SONNET5` | der Stand davor, unveraendert aufbewahrt | +| `SONNET5` | der Stand davor, unverändert aufbewahrt | --- @@ -41,18 +41,18 @@ sudo -u tesm-license tesm-license-admin bootstrap sudo -u tesm-license tesm-license-admin create-admin ``` -**`init-key` erzeugt den Signaturschluessel dieses Servers. Sichern Sie ihn -sofort.** Ohne ihn laesst sich keine ausgestellte Lizenz mehr erneuern, und -Kunden muessten einen Ausstellerwechsel bestaetigen. +**`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, laeuft der Dienst ohne +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` -fuer nginx-Site, logrotate, Zertifikate und Sitzungscookie. +für nginx-Site, logrotate, Zertifikate und Sitzungscookie. ### Aktualisieren @@ -60,7 +60,7 @@ fuer nginx-Site, logrotate, Zertifikate und Sitzungscookie. sudo bash deploy/update.sh --app tesm-license ``` -Vor jedem Update entsteht ein vollstaendiges Backup, danach laeuft ein +Vor jedem Update entsteht ein vollständiges Backup, danach läuft ein Health-Check mit automatischem Rollback. --- @@ -69,16 +69,16 @@ Health-Check mit automatischem Rollback. ```bash sudo -u tesm-license tesm-license-admin status -sudo -u tesm-license tesm-license-admin init-key # Signaturschluessel +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 uebernehmen +sudo -u tesm-license tesm-license-admin migrate-legacy # Altbestand übernehmen ``` `migrate-legacy` liest die SQLite-Datei eines alten Lizenzservers **nur -lesend**, uebernimmt dessen Signaturschluessel und stellt die Lizenzen mit ihrer -restlichen Laufzeit neu aus. Wird der Schluessel nicht uebernommen, muessen -Kunden den Ausstellerwechsel einmal bestaetigen. +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. --- @@ -101,14 +101,14 @@ genau einmal. (`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 Zurueckrollen auf eine aeltere +* Nonce gegen Wiedereinspielung, `seq` gegen das Zurückrollen auf eine ältere Lizenz. * Aussteller wird beim ersten Kontakt gemerkt (TOFU); ein Wechsel muss - ausdruecklich bestaetigt werden. -* Der Fingerabdruck der Maschine enthaelt **keinen** Hostnamen -- Umbenennen - brach im Vorgaenger die Bindung. -* Offline-Aktivierung ueber einen kurzen Code in beide Richtungen; die Lizenz - bleibt auf dem Server als "Aktivierung offen" markiert, bis sie zurueckkommt. + 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. @@ -130,8 +130,8 @@ Entwicklungsrepository, ebenso die Tests. * **Keine doppelte `licensing.py`.** Ein Paket, das beide Anwendungen installieren -- statt zweier Dateien, die byte-identisch bleiben sollen. -* **Kein root fuer die Anwendung.** Ein einziger allowlisted Helfer mit - Argumentpruefung. -* **CSRF-Schutz ueberhaupt.** Der Vorgaenger hatte keinen. -* **Rechte werden serverseitig geprueft**, nicht nur im Template ausgeblendet. +* **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. diff --git a/apps/tesm-license/pyproject.toml b/apps/tesm-license/pyproject.toml index bb86d7e..b25a166 100644 --- a/apps/tesm-license/pyproject.toml +++ b/apps/tesm-license/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "tesm-license" -version = "2.0.0" +version = "2.0.2" description = "TESM-Lizenzserver -- Kunden, Tickets, Lizenzen, Aktivierung" requires-python = ">=3.11" dependencies = [ diff --git a/apps/tesm-license/src/tesm_license/__init__.py b/apps/tesm-license/src/tesm_license/__init__.py index a8262ec..0879abd 100644 --- a/apps/tesm-license/src/tesm_license/__init__.py +++ b/apps/tesm-license/src/tesm_license/__init__.py @@ -23,7 +23,7 @@ from .permissions import PERMISSIONS, ROLE_PRESETS from .schema import LICENSE_MIGRATIONS from .settings_spec import LICENSE_SERVER_SETTINGS -__version__ = "2.0.0" +__version__ = "2.0.2" APP_KEY = "tesm-license" APP_NAME = "TESM-Lizenzserver" diff --git a/apps/tesm-license/src/tesm_license/navigation.py b/apps/tesm-license/src/tesm_license/navigation.py index 8960fba..13ddebb 100644 --- a/apps/tesm-license/src/tesm_license/navigation.py +++ b/apps/tesm-license/src/tesm_license/navigation.py @@ -86,7 +86,7 @@ NAVIGATION = NavTree( ), NavItem( key="logs_audit", - label="Aenderungen", + label="Audit", icon="history", endpoint="logs.audit_view", permissions=("logs_audit.view", "logs_audit.export"), diff --git a/apps/tesm-license/src/tesm_license/templates/license/backup.html b/apps/tesm-license/src/tesm_license/templates/license/backup.html index 237ed10..32eaa7f 100644 --- a/apps/tesm-license/src/tesm_license/templates/license/backup.html +++ b/apps/tesm-license/src/tesm_license/templates/license/backup.html @@ -1,26 +1,26 @@ {% extends "tesm_core/base.html" %} {% from "tesm_core/macros.html" import field, alert, pill %} -{% block page_title %}Sicherung und Uebertragung{% endblock %} -{% block page_sub %}Verschluesselter Export · zweistufiger Import{% endblock %} +{% block page_title %}Sicherung und Übertragung{% endblock %} +{% block page_sub %}Verschlüsselter Export · zweistufiger Import{% endblock %} {% block content %} -{{ alert('Der Export wird mit Argon2id aus Ihrer Passphrase verschluesselt (AES-256-GCM). Ohne -diese Passphrase ist die Datei nicht wiederherstellbar -- es gibt keine Hintertuer.', 'warning', +{{ alert('Der Export wird mit Argon2id aus Ihrer Passphrase verschlüsselt (AES-256-GCM). Ohne +diese Passphrase ist die Datei nicht wiederherstellbar -- es gibt keine Hintertür.', 'warning', 'Passphrase') }} -{{ alert('Der Signaturschluessel (' ~ signing_key_path ~ ') ist bewusst -nicht Teil dieser Sicherung. Er ist der Kern des Vertrauens und gehoert in eine +{{ alert('Der Signaturschlüssel (' ~ signing_key_path ~ ') ist bewusst +nicht Teil dieser Sicherung. Er ist der Kern des Vertrauens und gehört in eine getrennte, bewusst verwahrte Sicherung -- nicht in dieselbe Datei wie die Kundendaten. Ohne ihn -ist nach einer Wiederherstellung keine ausgestellte Lizenz mehr pruefbar.', 'danger', -'Wichtig: Schluessel getrennt sichern') }} +ist nach einer Wiederherstellung keine ausgestellte Lizenz mehr prüfbar.', 'danger', +'Wichtig: Schlüssel getrennt sichern') }}