# Jumphost Gateway — Implementierung Umsetzung des Konzepts `Jumphost_Konzept.md` (v0.2): browserbasiertes SSH/RDP-Gateway mit TOTP-Pflicht, Gruppen-/Hostgruppen-RBAC, manipulationssicherem Audit-Log, SQLite/Python-Backend, browserbasierter Admin-Oberflaeche und Ansible-Deployment (mit/ohne nginx, mehrere TLS-Modi). ## Verzeichnisstruktur ``` app/ Backend (FastAPI, Python 3.11+) security/ Crypto, Passwoerter, TOTP, Sessions, Audit-Hash-Chain, AV-Scan, API-Tokens auth/ Login-Flow, RBAC-/Token-Dependencies admin/ Admin-API (User/Gruppen/Hosts/Hostgruppen/Rollen/SSH-Keys/API-Tokens) catalog/ Sicht fuer normale Nutzer (direkt und ueber Gruppen zugewiesene Hosts) ssh_proxy/ SSH-Terminal-WebSocket + SFTP-Filetransfer rdp_proxy/ Guacamole-Protokoll-Tunnel zu guacd recordings/ Hash-verkettete Session-Aufzeichnung db/ SQLite-Migrationen (0001-0005, laufen automatisch beim Start) static/, templates/ Frontend (Vanilla JS, xterm.js, guacamole-common-js, Admin-Oberflaeche, API-Doku) scripts/ Betriebs-/Hilfsskripte (Admin anlegen, Assets bauen) ansible/ Deployment (Rollen, systemd-Unit-Templates) tests/ pytest-Suite ``` ## Lokale Entwicklung / Ausprobieren ```bash python3 -m venv .venv && source .venv/bin/activate pip install -r requirements-dev.txt bash scripts/fetch_frontend_assets.sh # vendored xterm.js / guacamole-common-js export JUMPHOST_ENV=development export JUMPHOST_DATA_DIR=/tmp/jumphost-dev export JUMPHOST_DEV_KEK=$(python3 -c "import secrets;print(secrets.token_hex(32))") export JUMPHOST_DEV_SESSION_SECRET=$(python3 -c "import secrets;print(secrets.token_hex(32))") uvicorn app.main:app --reload --port 8000 python scripts/create_admin.py --username admin # in zweitem Terminal ``` Danach `http://127.0.0.1:8000/` oeffnen, anmelden, TOTP einrichten (QR-Code scannen). Auf dem Dashboard erscheint fuer Admin-Konten oben rechts der Link **"Admin-Bereich"** (`/admin`) — darueber lassen sich Benutzer, Benutzergruppen, Hostgruppen/Hosts/SSH-Keys/RDP-Zugangsdaten, Rollenzuweisungen (direkt und gruppenweise) sowie API-Tokens vollstaendig ueber die Oberflaeche anlegen und verwalten; ein manueller Umweg ueber die rohe JSON-API ist dafuer nicht mehr noetig. Fuer RDP muss zusaetzlich ein laufender `guacd` erreichbar sein (siehe `JUMPHOST_GUACD_HOST`/`_PORT`). Die SQLite-Migrationen 0004 (`user_groups`) und 0005 (`api_tokens`) werden beim naechsten Start automatisch angewendet (`app/db.py`, `_apply_migrations`) — kein manueller Migrationsschritt noetig, auch nicht bei einem bestehenden Datenbestand. ## Admin-Oberflaeche, Gruppen-RBAC, API-Tokens und API-Dokumentation In dieser Session wurde die bis dahin nur per JSON-API bedienbare Verwaltung um eine vollstaendige, CSP-konforme Web-Oberflaeche unter `/admin` erweitert (`templates/admin.html`, `static/js/admin.js`), erreichbar nur fuer Admin- Konten. Tabs: Benutzer, Benutzergruppen, Hosts & Verbindungen (inkl. Connection-Anlage: Hostgruppe, Host, SSH-Key bzw. RDP-Zugangsdaten in einem Formular), Rollen, API-Tokens, Audit-Log. **Gruppen-RBAC (Migration `0004_user_groups.sql`)**: Neu sind *Benutzergruppen* (`user_groups`/`user_group_members`) als Teams von Personen, unabhaengig von den bestehenden *Hostgruppen* (Server-Gruppen). Eine Rolle kann einer Benutzergruppe auf eine Hostgruppe gewaehrt werden (`group_hostgroup_roles`) — das ist das "Sharen einer Verbindung mit einer Gruppe". Es gilt **volle Rollen-Vererbung**: jedes Mitglied einer Gruppe hat automatisch alle Rollen, die dieser Gruppe gewaehrt wurden, zusaetzlich zu seinen individuell zugewiesenen (`user_hostgroup_roles`, unveraendert bestehen geblieben). `app/rbac.py::user_has_role()` prueft dafuer beide Zuweisungswege (UNION-Query); `app/catalog/routes.py` (Host-Liste fuer normale Nutzer) beruecksichtigt beide ebenso. **API-Tokens (Migration `0005_api_tokens.sql`, `app/security/api_tokens.py`)**: Jeder Admin kann unter dem Tab "API-Tokens" persoenliche Tokens erzeugen (`Authorization: Bearer `), mit granularen **Read/Write-Scopes pro Ressource** (z. B. `hosts:ro`, `hosts:rw`, `users:ro`, `groups:rw`, ... vollstaendige Liste unter `GET /admin/scopes`). Tokens werden nur gehasht gespeichert (Klartext ist nur einmal direkt nach dem Anlegen sichtbar) und koennen jederzeit widerrufen werden. `app/auth/deps.py::require_admin_or_scope()` akzeptiert entweder eine gueltige Admin-Session (Cookie, wie bisher) oder einen Token mit passendem Scope — **niemals beides vermischt**: sobald ein `Authorization`-Header vorhanden ist, wird ausschliesslich er geprueft, ein evtl. noch gueltiges Session-Cookie wird dabei ignoriert. Aus Gruenden der Rechte-Eskalation sind die Token-Verwaltungs-Endpunkte selbst (`/admin/tokens/*`) bewusst **nicht** per Token nutzbar, sondern ausschliesslich per Admin-Session (`require_global_admin`) — ein geleaktes Token kann also nie weitere Tokens anlegen, auflisten oder widerrufen. Tokens sind ausschliesslich fuer die Management-API vorgesehen; SSH-/RDP-/SFTP-Sitzungen bleiben Session-Cookie-authentifiziert. **API-Dokumentation (`/docs`, `/openapi.json`)**: Nur fuer eingeloggte Admins sichtbar (`Depends(require_global_admin)` auf beiden Routen in `app/main.py`) — das bestehende Haertungskonzept, `/docs`/`/redoc`/`/openapi` nicht oeffentlich per FastAPI-Default auszuliefern (`docs_url=None, redoc_url=None, openapi_url=None`), bleibt unangetastet. Die Ansicht selbst (`templates/api_docs.html`, `static/js/api-docs.js`) ist bewusst **kein** vendored/CDN-bezogenes Swagger-UI-Bundle, sondern ein selbstgebauter, CSP-konformer Viewer ohne jede Laufzeit-Abhaengigkeit zu Drittanbietern: er liest `/openapi.json` per `fetch()` (`credentials: "same-origin"`) und rendert Endpunkte gruppiert nach Tag, ausschliesslich per `document.createElement`/`textContent` (kein `innerHTML`, keine Inline- Styles/-Scripts, siehe `tests/test_csp_compliance.py`). ## Tests ```bash pytest -q ``` 46 Tests (vorher 27) decken ab: Argon2id/TOTP-Grundfunktionen, Audit-Hash-Chain (inkl. Manipulationserkennung und Trigger-Durchsetzung), RBAC-Logik inkl. Ablaufdaten, den vollstaendigen Login-Flow (Passwort -> TOTP-Enrollment -> Session-Cookie -> geschuetzte Endpunkte) gegen die echte FastAPI-App, 17 dedizierte Security-/Pentest-Tests (`tests/test_pentest_security.py`), 5 CSP-Regressionstests (`tests/test_csp_compliance.py`, inkl. `/admin` und `/docs`) sowie 14 neue Tests zu Gruppen-RBAC-Vererbung, Admin-Oberflaeche und API-Tokens (`tests/test_admin_groups_tokens.py`): Rollen-Vererbung ueber Gruppenmitgliedschaft, dass Gruppenrollen NICHT auf Nicht-Mitglieder wirken, Admin-only-Durchsetzung fuer alle neuen Endpunkte, Token-Scope-Durchsetzung (read/write/implizites read-bei-write/widerrufen/abgelaufen/unbekannter Scope), dass ein Token niemals andere Tokens verwalten kann (Rechte- Eskalationsschutz), sowie Admin-Gating von `/docs` und `/openapi.json`. Details, Vorgehen und Ergebnisse der urspruenglichen 27 Tests: siehe `Pentest_Report.md`. > **Hinweis:** Die 19 in dieser Session neu hinzugekommenen Tests (5 CSP + > 14 Admin/Gruppen/Token) konnten in der verwendeten Cloud-Sandbox nicht > mit `pytest -q` ausgefuehrt werden, da diese Sandbox keinen Netzwerkzugriff > auf PyPI hat und `fastapi`/`aiosqlite` dort nicht vorinstalliert sind. > Stattdessen wurden alle neuen/gaenderten SQL-Queries gegen eine echte > `sqlite3`-Instanz mit allen 5 Migrationen (inkl. der beiden neuen) manuell > durchgespielt, `app/security/api_tokens.py` und die neuen Pydantic-Schemas > direkt importiert und mit echten Assertions verifiziert, und alle > geaenderten Python-/JS-Dateien mit `py_compile`/`node --check` auf > Syntaxfehler geprueft. Bitte `pytest -q` lokal ausfuehren und Ergebnis > melden. Manuell zusaetzlich verifiziert (siehe Entwicklungs-Log dieser Session): Server-Start, Static-/Template-Auslieferung, Security-Header, vollstaendiger Login+TOTP-Flow per curl, Admin-CRUD (Hostgruppe/Host anlegen), Audit-Log- Chain-Verifikation per `/admin/audit-log/verify`. ## Security-Tests & Haertungs-Nachweis - **SAST**: `bandit -r app -c .bandit.yml` sowie `pip-audit` (Dependency-CVE- Scan) liefen zu Beginn dieser Implementierung sauber durch (0 Findings, 0 bekannte Schwachstellen) — Details inkl. vorher/nachher-Tabellen und der dabei gefundenen und gefixten Starlette-Regression in `Pentest_Report.md`. Fuer die in dieser Session neu hinzugekommenen Dateien (Admin-Oberflaeche, Gruppen-RBAC, API-Tokens) steht ein erneuter `bandit`/`pip-audit`-Lauf noch aus (keine neuen Fremdabhaengigkeiten hinzugekommen). - **DAST**: `tests/test_pentest_security.py` (17 Tests) sowie `tests/test_admin_groups_tokens.py` (14 Tests, s.o.) simulieren konkrete Angriffsmuster gegen die laufende ASGI-App. - **OS-Haertung (CIS/STIG)**: die `ansible/roles/os_hardening`-Rolle wurde in einer frueheren Session um ~10 zusaetzliche Task-Dateien vertieft (Kernel-Module, sysctl, PAM/Passwort-Policy, erweiterte auditd-Regeln, AIDE, rkhunter, Banner, cron/at-Restriktion, Dateirechte/sudo-Logging, SSHD-Haertung). Vollstaendiges Mapping auf CIS-Controls inkl. bewusst nicht automatisierter Punkte (mit Begruendung, z.B. Partitionslayout, Bootloader-Passwort, Volltextverschluesselung, physische Sicherheit) und bekannter Einschraenkungen: `ansible/roles/os_hardening/CIS_STIG_MAPPING.md`. - Abhaengigkeiten sind in `requirements.txt`/`requirements-dev.txt` exakt auf gegen `pip-audit` gepruefte Versionen gepinnt (u.a. fastapi 0.141.1, starlette 1.6.0, cryptography 50.0.0) — bewusste Reproduzierbarkeits-/ Haertungsmassnahme, siehe `Pentest_Report.md` Abschnitt 2. ## Deployment ```bash cd ansible cp inventory/production.ini.example inventory/production.ini # anpassen cp inventory/group_vars/jumphost_with_nginx.yml.example inventory/group_vars/jumphost_with_nginx.yml ansible-vault encrypt inventory/group_vars/vault.yml # vorher aus vault.yml.example befuellen ansible-playbook -i inventory/production.ini site.yml --ask-vault-pass ``` `enable_nginx_proxy` und `tls_mode` (`internal_pki` / `external_reverse_proxy` / `acme_public`) steuern Proxy- und TLS-Verhalten, siehe Konzept Kap. 7.2/7.2a und `ansible/inventory/group_vars/all.yml`. `ansible-playbook site.yml --syntax-check` laeuft sauber durch (in einer frueheren Session verifiziert); ein voller `--check`-Lauf gegen eine echte Testumgebung (inkl. `apt`, `systemd`, `guacd`-Paketverfuegbarkeit auf der Zieldistribution) steht noch aus. Ein Neustart des Dienstes (`systemctl restart jumphost`) reicht aus, damit die Migrationen 0004/0005 angewendet werden. ## Was bewusst noch offen ist Diese Implementierung ist ein funktionsfaehiges, getestetes und in einer frueheren Session per SAST+DAST geprueftes Grundgeruest, aber weiterhin **kein fertig auditiertes Produktivsystem**. Der vollstaendige Befund inkl. Methodik, Vorgehen und Restrisikobewertung steht in `Pentest_Report.md` — die dortige Abschnitt-4-Tabelle ("Restrisiko / vor Produktivbetrieb noch zu tun") ist die massgebliche, aktuelle Fassung dieser Liste. Kurzfassung: 1. **Echter Netzwerk-Penetrationstest** gegen eine laufende Instanz (Portscan, TLS-Konfiguration live, Session-Isolation unter Last, Guacamole-Protokoll-Fuzzing) — in dieser Sandbox ohne Netzwerkzugriff auf ein reales Zielsystem nicht durchfuehrbar. Was stattdessen gemacht wurde: SAST (bandit, pip-audit) und ein DAST-Testlauf gegen die App im Prozess (17+14 Security-/Admin-Tests, siehe `Pentest_Report.md` bzw. oben). 2. **RDP/guacd-Integrationstest gegen echte Zielsysteme** — die Guacamole-Protokoll-Implementierung (`app/rdp_proxy/guacd_client.py`) wurde gegen die Protokollspezifikation implementiert und die Handshake-Logik lokal auf Korrektheit der Kodierung geprueft, aber NICHT gegen einen laufenden `guacd` + FreeRDP + Windows-Ziel end-to-end getestet (keine RDP-Zielumgebung in dieser Sitzung verfuegbar). Parameter-Namen/-Reihenfolge sollten gegen die tatsaechlich eingesetzte guacd-Version verifiziert werden. 3. **Ansible-Rollout gegen ein reales Zielsystem** (`--check`-Dry-Run und echter Rollout in einer Staging-Umgebung) — bisher nur `ansible-playbook site.yml --syntax-check` sowie YAML-/Jinja2-Parsing verifiziert, siehe `ansible/roles/os_hardening/CIS_STIG_MAPPING.md`. 4. **OpenSCAP-Compliance-Scan** (`oscap xccdf eval`) gegen das zutreffende CIS/STIG-Profil — die `os_hardening`-Rolle wurde in einer frueheren Session um ca. 10 Task-Dateien vertieft (siehe CIS_STIG_MAPPING.md fuer das vollstaendige Mapping inkl. bewusst nicht automatisierter Punkte), ersetzt aber keinen zertifizierten Benchmark-Scan. 5. **Verteiltes Rate-Limiting** — der aktuelle Login-Rate-Limiter ist In-Memory/Single-Process (siehe `app/security/rate_limit.py`); bei horizontaler Skalierung durch einen geteilten Store ersetzen. 6. **fail2ban-Filter** setzt strukturierte Access-Logs mit `client_ip=`-Feld voraus, die die App aktuell nicht schreibt — vor Produktivbetrieb ein Access-Log-Middleware ergaenzen oder auf das Audit-Log umstellen. 7. **CSRF**: SameSite=Strict-Cookies mindern das Risiko bereits deutlich; ein expliziter CSRF-Token fuer zustandsaendernde JSON-Requests ist als zusaetzliche Haertungsstufe vorgesehen, aber noch nicht implementiert. 8. Alle in Konzept Kap. 12 genannten Erweiterungen (LDAP/AD, WebAuthn, PostgreSQL-Migrationspfad, Just-in-Time-Zugriff, HA) sind noch nicht umgesetzt. 9. **Social Engineering / physische Sicherheit / Lastest (DoS)** wurden nicht getestet — ausserhalb des Scopes eines Code-/Konfigurations-Reviews in dieser Sandbox-Umgebung. 10. **API-Token-Rotation/-Ablaufrichtlinien**: Tokens koennen zwar mit optionalem Ablaufdatum erzeugt und jederzeit widerrufen werden, aber es gibt noch keine erzwungene maximale Laufzeit, keine automatische Benachrichtigung vor Ablauf und keine "Token zuletzt benutzt vor X Tagen -> automatisch deaktivieren"-Routine. 11. Ein erneuter `bandit`/`pip-audit`-Lauf ueber die in dieser Session neu hinzugekommenen Dateien (Admin-Oberflaeche, Gruppen-RBAC, API-Tokens) steht noch aus (siehe oben).