TLS-Gate: Der Login steht ΓΌber dem Modul (Handout fΓΌr die Crew)
native & lokal β lesbar β mΓΆglich oder nicht. Nicht verhandelbar.
Von: Branko β OZMAI, Crew
Stand: 12. Oktober 2026
Typ: EXTERNAL_SOURCE (Inbox-Regel Β§3, keine automatische Geltung, kein Brain-Status)
Charakter: NACHTRAG zu 2026-10-12_TLS-GATE-V3-16-0-NETBOX-ZUGAENGE-IM-WEB-UND-LIVE-TEST-SEEDS-NACHTRAG_BRANKO.md. Ersetzt nichts. Dieser Eintrag erklΓ€rt das Γkosystem der Crew, er meldet keinen neuen Code.
Anlass: Branko, 12.10.: Die Crew hat verstanden, warum es kein βneues Toolβ gibt. GewΓΌnscht ist eine ErklΓ€rung ohne Folien, als ASCII in einer .md, fΓΌr Γ€ltere Kolleginnen und Kollegen. Branko: β3FA β¦ nur wenn 2FA sich bewiesen hat!β
Quelle: Repo TLS-Gate-Mock-Pipeline docs/LOGIN_UEBER_DEM_MODUL.md (dc7ba38). Code-Stand v3.16.0 (b9a33fa), native_php/. Werte und Regeln stammen aus src/Auth/Auth.php, src/Catalog/Bookings.php, src/Audit/Audit.php, src/Http/SslController.php und database/schema.sql. Lesen im Terminal mit glow <datei>, alle Bilder hΓΆchstens 80 Spalten.
Belege: Die Bilder beschreiben gebauten und getesteten Code (VM-Suiten vom 12.10. grΓΌn, siehe VorgΓ€nger-Eintrag). Die zwei Audit-Zeilen im Bild sind ausgedacht. NIS2, DSGVO, CA und DNS sind als Bezug genannt, nicht als KonformitΓ€t. Eine PrΓΌfung gab es nicht.
Legende: β real/gebaut Β· π§ͺ gebaut, getestet, nicht live Β· π spezifiziert Β· β¬ OPEN Β· β UNKNOWN
Der Leitsatz
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β NATIVE PHP, SQL und Bash. Kein Framework, kein β
β Cloud-Dienst, kein Paketmanager zur Laufzeit. β
β β
β LOKAL LΓ€uft auf der eigenen Node. Login, Gruppen, β
β Buchungen und Audit gehen auch ohne Internet. β
β β
β LESBAR Jede Regel steht im Code, mit Fehlercode. β
β Jede Tabelle in einer .sql-Datei. Kein Zauber. β
β β
β MΓGLICH Die Antwort ist ja oder nein, mit Grund im β
β ODER NICHT Audit. Es gibt kein "vielleicht". β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Warum kein βneues Toolβ? Ein Tool beantwortet eine Frage, zum Beispiel βZertifikat bestellenβ. Davor stehen aber immer dieselben Fragen: Wer bist du, zu wem gehΓΆrst du, was darfst du, und wo steht das? Wenn jedes Tool sie selbst beantwortet, gibt es fΓΌnf Logins, fΓΌnf Rechtemodelle und fΓΌnf Logs. Bei uns beantwortet der Login sie einmal. Die Module (SSL, Katalog, NetBox, Bestand) fragen nur noch nach.
Mensch
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LOGIN Passwort + TOTP Β· Gruppe Β· Rolle Β· Audit β β klΓ€rt
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β fragt nur noch: "darf diese Rolle das hier?"
βΌ
βββββββββββ βββββββββββ βββββββββββ βββββββββββ βββββββββββ
β SSL- β β Katalog β βDashboardβ β NetBox- β β Bestand β β tun
β Konsole β βBuchungenβ β β β Spiegel β βRegistrarβ
βββββββββββ βββββββββββ βββββββββββ βββββββββββ βββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β audit_log nur anhΓ€ngen Β· nie Γ€ndern Β· nie lΓΆschen β β belegt
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
1. Was klΓ€rt der Login?
E-Mail + Passwort βββΊ Konto aktiv? βββΊ nicht gesperrt? βββΊ Passwort ok?
β
ββββββββββββββββββββββββββββββββββββββββββββββ
βΌ
TOTP schon eingerichtet?
β β
ja nein
βΌ βΌ
6-stelliger Code QR-Code zeigen, erst der erste
aus der App gΓΌltige Code schaltet TOTP scharf
β β
ββββββββββ¬ββββββββββββ
βΌ
Sitzung mit Gruppe + Rolle β auth.login ok
| Frage | Antwort im Code β |
|---|---|
| Bist du es? | Passwort (Argon2id, 15 bis 128 Zeichen) und TOTP (RFC 6238). Zwei Faktoren. |
| Wie lange gilt das? | 30 Minuten ohne AktivitΓ€t, hΓΆchstens 12 Stunden (Auth::IDLE_TIMEOUT, ABSOLUTE_TIMEOUT). |
| Was bei Raten? | 5 Fehlversuche je Konto β 15 Minuten gesperrt. 10 je IP in 15 Minuten β IP blockiert. |
| VerrΓ€t die Meldung etwas? | Nein. Immer dieselbe Meldung: βAnmeldung fehlgeschlagen oder Konto vorΓΌbergehend gesperrt.β |
| Kann man einen Code zweimal nutzen? | Nein, ein benutzter Code ist gesperrt (Replay-Schutz). |
| Cookie und Formulare | Cookie __Host-, SameSite=Strict, CSRF-Token auf jedem Formular, strikte CSP ohne Inline-Skripte. |
| Und ohne DB? | Die Seite antwortet mit 503. Sie lΓ€sst niemanden βzur Notβ herein (fail closed). |
MFA-Modus je Gruppe (groups.mfa_policy):
code klassisch: einmal QR, danach nur noch der Code aus der App
qr bei jedem Passwort-Login ein neues QR
β wer das Passwort kennt, sieht das QR β kein echter 2. Faktor
gedacht fΓΌr reine Login-Produkte, nicht fΓΌr Root/SSL-Gruppen
Und 3FA? π
3FA erst, wenn 2FA sich bewiesen hat. (Branko, 12.10.)
Faktor 1 Wissen Passwort β
gebaut
Faktor 2 Besitz TOTP-App β
gebaut
Faktor 3 Verhalten Erkennung/Bewegung im π Idee, nicht gebaut
Nullfeld (Logging, Muster)
Der dritte Faktor baut auf dem auf, was das Audit schon heute aufzeichnet (Abschnitt 4). Er kommt erst, wenn die Crew mit 2FA im Alltag arbeitet und das Audit zeigt, dass es trΓ€gt. Vorher wΓ€re er Rauschen auf einem ungeprΓΌften Fundament.
2. Was klΓ€ren Gruppe, Rolle und ZugehΓΆrigkeit?
ββ Gruppe (groups) βββββββββββββββββββββββββββββββββββββββββββ
β slug Β· Name Β· Typ: eigen | reseller Β· MFA-Modus β
β β
β ββ Konto (users) βββ ββ Konto βββββββ ββ Konto βββββββ β
β β admin β β user β β readonly β β
β ββββββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β
β SOAP-ZugΓ€nge Β· NetBox-ZugΓ€nge Β· Freigaben Β· Buchungen β
β (alles gehΓΆrt genau einer Gruppe) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
β keine Sicht in eine andere Gruppe:
eine fremde ID heiΓt "unbekannt", nicht "verboten"
(verrΓ€t nicht einmal, dass es sie gibt)
Jedes Konto gehΓΆrt zu genau einer Gruppe (users.group_id, Pflichtfeld). Die Gruppe ist die Grenze: SOAP-ZugΓ€nge, NetBox-ZugΓ€nge, Freigaben und Buchungen hΓ€ngen an ihr.
Die Rolle ist eine Leiter. Jede Stufe darf alles, was die Stufen darunter dΓΌrfen:
4 admin ββββββββ Benutzer, Gruppen, Katalog, Freigaben,
fΓΌr andere buchen, Kontobindung NetBox
3 group_admin ββββββ ZugΓ€nge (SOAP, NetBox) der EIGENEN Gruppe
2 user ββββ bestellen, verlΓ€ngern, Authcode, Besitzer-
daten, eigene ZusΓ€tze buchen und beenden
1 readonly ββ nur lesen: Liste, Details, DCV, Cross-Check
| PrΓΌfung | Wo | Ergebnis bei Nein |
|---|---|---|
| Mindestrolle fΓΌr die Seite | Auth::requireLogin($min) |
403 + auth.forbidden im Audit |
| Mindestrolle je SSL-Aktion | SslController::ACTION_ROLES |
ssl.<aktion> denied mit need |
SSL nur fΓΌr Gruppentyp eigen |
Auth::sslAllowed() |
Reseller sehen die Konsole nicht |
| Datensatz der eigenen Gruppe | jede Abfrage mit group_id |
βUnbekannter Zugangβ + denied |
Werkzeuge in bin/ |
Guard: nur root/sudo oder Besitzer der Instanz |
Exit 3, nichts geschrieben |
Kurz: Die Gruppe sagt, wo du bist. Die Rolle sagt, was du dort darfst.
3. Wie hΓ€ngen Produkte und Zusatzleistungen am Login?
Vier Schritte, und jeder hat einen anderen Verantwortlichen:
KATALOG FREIGABE BUCHUNG AKTIVIERUNG
(fΓΌr alle) (je Gruppe) (je Person) (durch Inhaber)
products βββΊ group_products βββΊ user_products βββΊ state: active
+ categories aktiv, ab wann, Grundprodukt offered β active
Preisreferenz + ZusΓ€tze nur der Inhaber
admin admin admin / user Inhaber
Bucht ein User selbst, ist die Buchung sofort active.
Bucht der Admin fΓΌr ihn, wartet sie als offered auf ihn.
Eine Buchung ist ein Baum, der an einem Login hΓ€ngt:
user01@gruppe (Login)
β
βββ VM Small #proxmox β Grundprodukt: braucht einen Anker
β anker: netbox:101 (welches GerΓ€t?), bucht nur der admin
β β
β βββ Backup #addon β Zusatz: hΓ€ngt am Grundprodukt
β βββ Monitoring #addon derselben Person
β βββ SSL #hosting
β
βββ Server #baremetal
anker: mac:02:AA:BB:CC:DD:01
Beenden: erst die ZusΓ€tze, dann das Grundprodukt.
Regel β
(src/Catalog/Bookings.php) |
Code im Audit |
|---|---|
readonly bucht nichts |
rolle |
| Ein User bucht nur fΓΌr sich, ein Admin nur in seiner Gruppe | nur_fuer_sich, fremde_gruppe |
| Ohne aktive Freigabe der Gruppe keine Buchung | keine_freigabe, noch_nicht_verfuegbar |
| Grundprodukt nur mit Anker und nur durch den Admin | anker_fehlt, nur_admin_grundprodukt |
| Zusatz nur unter einem eigenen, laufenden Grundprodukt | parent_fehlt, parent_ungueltig |
Admin-Dienste (Achse access) nur fΓΌr Rolle admin |
nur_admin |
| Preis nur bei Kategorien mit Preisart βpricedβ | kein_preis_erlaubt |
| Anker auf ein NetBox-GerΓ€t ohne Kontobindung (Regel b) | kein_kontobezug |
| Aktivieren nur durch den Inhaber | nur_inhaber |
| Im Dashboard nur ZusΓ€tze beenden | nur_zusatz |
Wer sieht was? Die Systemakte (sot_ref, z. B. der NetBox-Link) sieht nur der Inhaber, nicht einmal der Admin der Gruppe. Preis und SchΓ€tzung sehen der Inhaber und der Admin der Gruppe.
Wo kommen CA und DNS ins Spiel? Der Anker verbindet die Buchung mit einem echten GerΓ€t in NetBox. An diesem GerΓ€t hΓ€ngt spΓ€ter das GerΓ€tezertifikat der eigenen CA (nur der GerΓ€tename steht darin, keine MAC). Gekaufte SSL-Zertifikate laufen ΓΌber den Registrar, die Domain wird per DNS bestΓ€tigt. β Die Node-CA ist nicht in native_php. Sie lΓ€uft auf der Ansible-Node, ihr Ort fΓΌr die ozm-Knoten ist offen.
4. Was landet im Audit-Log?
audit_log
βββββββ¬βββββββββββββββ¬ββββββ¬ββββββ¬ββββββββββββββ¬βββββββββ¬βββββββ¬ββββββββββββ
β id β ts (UTC) β userβgroupβ action β result β ip β ctx (JSON)β
βββββββΌβββββββββββββββΌββββββΌββββββΌββββββββββββββΌβββββββββΌβββββββΌββββββββββββ€
β 412 β 10-12 17:02Z β 7 β 3 β auth.login β ok β 10.β¦ β role β
β 413 β 10-12 17:03Z β 7 β 3 β booking.add β denied β 10.β¦ β reason: β
β β β β β β β β keine_frβ¦ β
βββββββ΄βββββββββββββββ΄ββββββ΄ββββββ΄ββββββββββββββ΄βββββββββ΄βββββββ΄ββββββββββββ
(Beispielzeilen, ausgedacht, gekΓΌrzt)
UPDATE β Trigger: "audit_log ist append-only"
DELETE β Trigger: "audit_log ist append-only"
Was hineinkommt β , nach Bereich:
auth.* login (ok, fail mit Grund, blocked_ip) Β· password Β· mfa
mfa_enroll Β· mfa_rotate Β· logout Β· session_timeout
session_revoked Β· account_locked Β· forbidden (Seite ohne Recht)
admin.* user_add Β· user_role Β· user_enable Β· user_passwd Β· user_unlock
user_reset_mfa Β· group_add Β· group_mfa
ssl.* jede Aktion der Konsole: requested Β· denied Β· Ergebnis
mit Rohantwort des Registrars und Pflicht-Grund beim Bestellen
booking.* offer Β· add Β· activate Β· end (auch jede Ablehnung)
catalog.* product_/category_ add Β· edit Β· active Β· delete
link Β· unlink Β· withdraw
(beim LΓΆschen steht der gelΓΆschte Datensatz drin)
web.*/cli.* SOAP- und NetBox-ZugΓ€nge: add Β· replace Β· test Β· delete
Kontobindung Β· netbox_view Β· netbox_sync Β· inventory_sync
migrate Β· key_rotate Β· user_* am Terminal (mit echtem Akteur)
module.denied Modul ohne Berechtigung aufgerufen
Wo der Registrar oder NetBox beteiligt ist, steht dazu der Code-Stand (ctx.build, Commit), also welcher Stand gelaufen ist und nicht nur welche Version.
Was nie hineinkommt β : PasswΓΆrter, TOTP-Secrets, SOAP-Zugangsdaten, NetBox-Token, private SchlΓΌssel, die Systemakte.
Was bewusst drinsteht und wichtig ist β: E-Mail-Adresse und IP. Das sind personenbezogene Daten (DSGVO). Weil das Log nur anhΓ€ngt, gibt es heute keine LΓΆschfrist. Wie lange die Daten bleiben und wer das Log lesen darf (heute nur admin ΓΌber auditlog.php), muss die Crew festlegen.
Auf einen Blick
βββββββββββββββββ¬βββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββ
β Frage β beantwortet durch β Beleg β
βββββββββββββββββΌβββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββ€
β Wer? β Login: Passwort + TOTP β auth.login β
β Wo? β Gruppe β group_id in jeder Zeile β
β Was darf er? β Rolle (1 bis 4) β auth.forbidden / denied β
β Was hat er? β Buchungsbaum mit Anker β booking.* β
β Woran? β GerΓ€t in NetBox (Anker) β netbox:<id> / mac / wg β
β Was geschah? β audit_log, nur anhΓ€ngen β Trigger gegen UPDATE/DELETEβ
β Welcher Code? β Commit-Stempel β ctx.build β
βββββββββββββββββ΄βββββββββββββββββββββββββββββββ΄βββββββββββββββββββββββββββββ
Bezug zu NIS2, DSGVO, CA und DNS
Es geht hier um Bezug, nicht um KonformitΓ€t. Eine PrΓΌfung hat nicht stattgefunden.
- NIS2 (Art. 21 Abs. 2 lit. j: Multi-Faktor-Authentisierung): 2FA ist Pflicht fΓΌr jedes Konto, Sperren und Audit sind gebaut. Die Grundlage steht im Kopf von
src/Auth/Auth.php. - DSGVO: Datensparsamkeit (Export ohne E-Mail, Systemakte nur fΓΌr den Inhaber). β Offen ist die LΓΆschfrist des Audits.
- CA: Die eigene CA stellt nur fΓΌr GerΓ€te aus, die NetBox kennt, und nur an Konten mit Kontobindung. Der private SchlΓΌssel bleibt auf dem GerΓ€t.
- DNS: Eine Domain gilt erst als bestΓ€tigt, wenn der Registrar oder das DNS es zeigt. Eine Selbstmeldung reicht nie.
Offen β
- LΓΆschfrist und Leserechte fΓΌr das Audit (DSGVO).
- 3FA: welche Muster, ab wann, und wer entscheidet, dass 2FA βbewiesenβ ist.
- Ort der Node-CA fΓΌr die ozm-Knoten.
- RZ-NetBox ohne Tenants: Wie wird ein GerΓ€t einer Gruppe zugeordnet?
Quellen im Repo: native_php/src/Auth/Auth.php, src/Catalog/Bookings.php, src/Audit/Audit.php, src/Http/SslController.php, database/schema.sql. AusfΓΌhrlich: docs/ARCHITEKTUR.md, docs/SECURITY.md, docs/DESIGN_KATALOG_BUCHUNGEN.md, docs/DESIGN_NETBOX_CONNECTOR.md.