TLS-Gate â Crew-Handout v2
Stand 2026-09-30 · aktuell v3.0.0 (Patch 3.0.1 im RZ-Test, noch ohne Tag) · Details zu allen Ănderungen stehen in CHANGELOG.md.
Hinweis: Dieses Handout beschreibt im Kern den Stand v2.0.0. FĂŒr Mandanten, Bestellzustand, Export und Guard gelten docs/DESIGN_TENANTS.md und CHANGELOG.md.
Auf einen Blick
v1 ist das Werkzeug ohne Login (Stand bis 24.9., lÀuft so in der Test-VM). v2 ist die erste
Version mit Login und Audit, dazu eine Verzeichnisstruktur, die sich sauber auf einen Produktionshost
bringen lÀsst:
- Login-Pflicht: Passwort + 6-stelliger TOTP-Code. Ohne DB bleibt die OberflÀche zu (503).
- Admins haben im Header Benutzer (Konten/Gruppen verwalten) und Audit (wer, wann, was).
- Bestellungen brauchen ein Pflichtfeld Grund/Zweck. Der Grund landet im Audit und geht nicht an die CA.
- Neue Struktur: Nur
public/ist per Web erreichbar. Klassen liegen insrc/, Werkzeuge inbin/. - Deploy-Vorlagen fĂŒr Apache und nginx, mit Hinweisen pro Betriebssystem, liegen in
deploy/. - Die Version steht oben im Seitenkopf (
B.W.A // TLS-GATE // v2.0.0), damit v1 und v2 nicht verwechselt werden.
Was sich fĂŒr euch Ă€ndert
| Vorher (v1) | Jetzt (v2) |
|---|---|
php -S 127.0.0.1:8080 router.php |
bin/serve.sh oder php -S 127.0.0.1:8080 -t public router.php |
./dashboard.sh ⊠|
bin/dashboard.sh ⊠|
php soap_cli.php ⊠|
php bin/soap_cli.php ⊠|
php user_cli.php ⊠|
php bin/user_cli.php ⊠|
./test_auth.sh |
tests/test_auth.sh |
./TLS-doktor.bash |
bin/TLS-doktor.bash |
vhost DocumentRoot /srv/tlsgate |
DocumentRoot /srv/tlsgate/public (bzw. nginx root âŠ/public) |
sample.json per Web abrufbar |
resources/mock/sample.json, nur lokal |
| Doku im Repo-Root | docs/ (README, CHANGELOG, VERSION bleiben im Root) |
Die Web-Adressen bleiben gleich: /, /login.php, /users.php, /auditlog.php.
Verzeichnisse â die Regeln in drei SĂ€tzen
- Seiten gehören nach
public/, Klassen nachsrc/<Modul>/(NamespaceTlsGate\<Modul>),
Werkzeuge nachbin/. - Pfade und Umgebung werden nur ĂŒber
TlsGate\Configaufgelöst. Nichts mit__DIR__ . '/state'in der Fachlogik. - Nichts Geheimes unter
public/. DB, Key und Stammdaten liegen inTLS_GATE_STATE_DIR, produktiv/var/lib/tlsgate.
AusfĂŒhrlich: docs/STRUKTUR.md. Die Case-Falle vom 26.9. (audit.php hat die Klasse Audit.php
ĂŒberschrieben) ist damit strukturell erledigt, weil Klassen und Seiten nie mehr im selben Verzeichnis liegen.
Sicherheit & Leitplanken
- Login: Argon2id, â„ 15 Zeichen. TOTP ist Pflicht fĂŒr alle Rollen, jeder Code gilt nur einmal. Konten
werden nach 5 Fehlversuchen gesperrt, eine IP nach 10. - Verwaltung: nur
admin. Niemand kann sich selbst aussperren, der letzte Admin ist geschĂŒtzt, und es
gibt kein Hard-Delete (disable= Soft-Delete). - Audit: nur anhÀngbar, per DB-Trigger. Jede SSL-Aktion und jede VerwaltungsÀnderung wird mit Benutzer,
Gruppe und IP protokolliert. - Auslieferung: Der Webroot ist
public/, und PHP fĂŒhrt nur existierende Dateien aus.tests/test_auth.sh
prĂŒft per Gegenprobe, dass das alte Layout die DB ausliefern wĂŒrde und das neue nicht.
Warum RFC 6238 â der Anker unter dem 2FA
Der Zwei-Faktor-Schritt steht auf RFC 6238 (TOTP). Das stand bisher nur als Kommentar in
src/Auth/Totp.php:2 â nirgends im Handout, das ansonsten rein die Mechanik beschreibt. Ein Verweis auf
eine Norm ist aber noch keine KonformitÀt: eingelöst ist die Behauptung erst, wenn der Code den
veröffentlichten Testvektoren der Norm antwortet.
tests/test_totp_rfc6238.sh fĂ€hrt genau das â die sechs Appendix-B-Vektoren (Referenz-Seed ASCII
12345678901234567890) gegen den echten Totp::code():
| T (Sekunden) | RFC 6238 (8-stellig) | TLS-Gate (6-stellig) |
|---|---|---|
| 59 | 94287082 | 287082 |
| 1111111109 | 07081804 | 081804 |
| 1111111111 | 14050471 | 050471 |
| 1234567890 | 89005924 | 005924 |
| 2000000000 | 69279037 | 279037 |
| 20000000000 | 65353130 | 353130 |
(6-stellig = n mod 10^6 = die letzten sechs Stellen der RFC-8-Codes.) ZusĂ€tzlich prĂŒft der Test
die verify()-Mechanik: ±1-Schritt-Toleranz, +2 abgelehnt, falscher Code abgelehnt â und der
Kern: ein bereits getroffener Zeitschritt wird ĂŒber step > lastStep monoton verbraucht.
Warum das hier steht und nicht nur im Code: dieser âeinmal gĂŒltig, dann verbraucht"-Schutz ist
kein TOTP-Detail, sondern dasselbe Muster wie der Rest des Stacks â der Audit-Trail ist
append-only (kein UPDATE/DELETE), die Bestellung ist eine Passkante (Grund â audit_log, sonst
rejected). Ein TOTP ist ein zeit-gebundener Beweis: gĂŒltig nur im 30-s-Fenster, danach tot.
RFC 6238 ist die 2011 standardisierte, testvektor-geprĂŒfte Form genau dieser Idee â und damit der
Kontext, den ein rein code-basiertes Handout nicht sieht.
Getestet (v2.0.0, lokal PHP 8.5.10)
tests/test_auth.shâ 66/66: nurpublic/erreichbar (inkl...,%2e%2e,//state), Login,
TOTP-Einrichtung, Replay, CSRF, Rollen, Sperren, Entzug laufender Sessions, Audit nur anhĂ€ngbar, fail closed.tests/test_totp_rfc6238.shâ 11/11: RFC-6238-Vektoren +verify()-Fenster/Replay.tests/test_smoke.shâ 44/44: Vertragsample.json+dashboard.sh.bin/TLS-doktor.bashâ 0 Probleme. Die Warnungen sind bekannt: Key neben DB,state/im Checkout, Web-User_www.- Nicht getestet: die Vorlagen in
deploy/gegen echtes Apache/nginx (apachectl -t/nginx -tauf dem
Zielhost ausfĂŒhren) und ein Klick-Durchlauf im Browser nach dem Umbau.
Bedienung
- Server starten (lokal, http), aus dem eigenen Terminal:
bin/serve.sh # restart | stop | status - Anmelden:
http://127.0.0.1:8080/login.php, E-Mail + Passwort, dann den 6-stelligen Code. - Code holen im Dev, ohne App:
php bin/user_cli.php user code <email> - Verwalten: oben rechts Benutzer oder Audit (Chip SSL bzw. nur Bestellungen).
- Bestellen: Tab Order Certificate. Grund/Zweck ist Pflicht und erscheint danach im Audit.
Produktion / Node
Der Ablauf steht in deploy/README.md. Kurzfassung:
git checkout v3.0.0(oder den Stand, den das RZ-Team freigibt). Webserver-Vorlage ausdeploy/nehmen, root =âŠ/public.- State nach
/var/lib/tlsgatelegen (gehört dem Web-User), WurzelschlĂŒssel nach/etc/tlsgate/root.key,
kein SOAP-Zugang in Pool oder vhost. migrate, den ersten Admin und den SOAP-Zugang (cred add, danncred test) als root/sudo anlegen (CLI-Guard), danach
chown -R <WEBUSER> /var/lib/tlsgate. Ein Aufruf als Web-User wird mit Exit 3 abgelehnt, solange ihm noch nicht alles gehört; danach ist er
Besitzer der Instanz und darf (Grenze:docs/SECURITY.md, CLI-Guard).bin/TLS-doktor.bashmit denselben Pfaden grĂŒn ziehen.- RHEL-Familie: SELinux-Kontexte +
httpd_can_network_connect. Ohne das zeigt die App âSOAP nicht verfĂŒgbarâ (kein stiller Mock mehr).
Die v1-VM bleibt unverÀndert als Referenz stehen, bis v2 auf dem Zielhost lÀuft.
Offen / To-do
- ~~Phase 2~~ erledigt in v2.1.0:
SslController+templates/, strikte CSP. Offen bleibt,users.php/auditlog.phpgenauso umzubauen. - Phase 3:
SslHandlerin SOAP-Gateway, Mock-Quelle und Normalisierung aufteilen,$_POSTraus aus der Klasse. group_admin-Scope: darf nur die eigene Gruppe verwalten (M2/M3).- âGrundâ auch bei VerlĂ€ngern/Authcode? Bisher nur bei Bestellungen Pflicht.
- Leak-Liste fĂŒr Passwörter (
docs/SECURITY.md1c), WebAuthn/Passkeys. - Key-Custody: Key getrennt von der DB ablegen (BWA-AUD-22).