README and all guides under docs/ are now in German, with German anchors for the cross references. Code and configuration blocks are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
108 lines
4.3 KiB
Markdown
108 lines
4.3 KiB
Markdown
# Entwicklung
|
||
|
||
## Aufbau
|
||
|
||
```
|
||
app/webui/ Flask-Anwendung (Paket "webui")
|
||
app.py Routen, Sicherheits-Header, Protokoll
|
||
auth.py Anmeldung lokal / OIDC / Proxy, Login-Sperre
|
||
backend.py SSH zu den Agenten, GeoIP, Loki
|
||
cli.py serve, hash-password, keygen, keyscan, check
|
||
config.py Einstellungen aus der Umgebung, hosts.yaml
|
||
i18n.py, locales/ Übersetzungen (eine JSON-Datei pro Sprache)
|
||
templates/, static/ (static/world.svg: Weltkarte, Natural Earth)
|
||
agent/ f2b-webctl, install.sh, uninstall.sh
|
||
docker/Dockerfile Produktions-Image
|
||
examples/ docker-compose.yaml, .env.example, hosts.yaml.example
|
||
dev/testbed/ Weboberfläche + zwei fail2ban-Hosts in Docker
|
||
tests/smoke_test.py Tests der Weboberfläche ohne Docker/SSH
|
||
```
|
||
|
||
## Smoke-Test (ohne Docker)
|
||
|
||
```bash
|
||
python3 -m venv .venv
|
||
.venv/bin/pip install -r requirements.txt
|
||
.venv/bin/python tests/smoke_test.py
|
||
```
|
||
|
||
Die Agenten werden simuliert. Abgedeckt: Anmeldung, Login-Sperre, CSRF-/Origin-Prüfung,
|
||
Übersetzungen, Prüfung beim Sperren/Entsperren, Protokoll, Proxy-Modus, Prüfung der
|
||
Konfiguration, SSH-Befehlszeile, Log-Injection.
|
||
|
||
## Testbed (Docker)
|
||
|
||
`dev/testbed` startet die Weboberfläche und zwei Debian-Hosts mit sshd und fail2ban
|
||
(Dummy-Banactions – es wird nichts gesperrt). Die Agenten werden beim Containerstart mit
|
||
`agent/install.sh` installiert:
|
||
|
||
| Host | Agent-Einrichtung |
|
||
|---|---|
|
||
| `agent1` | Benutzer `f2bweb` + sudo, `--from` auf das Testbed-Netz, zusätzliche geschützte IP |
|
||
| `agent2` | Benutzer `root`, Schlüssel in `authorized_keys2`, manuelles Jail namens `blocklist` |
|
||
|
||
```bash
|
||
cd dev/testbed
|
||
printf 'DEFAULT_LANG=en\nAUTH_MODE=local\nAUTH_USER=admin\nCACHE_SECONDS=5\n' > .env
|
||
docker compose build
|
||
docker compose run --rm -it webui hash-password >> .env
|
||
docker compose run --rm webui keygen
|
||
docker compose run --rm -T --entrypoint sh webui -c 'cat > /data/hosts.yaml' < hosts.yaml
|
||
docker compose up -d agent1 agent2
|
||
docker compose run --rm webui keyscan --yes
|
||
docker compose run --rm webui check
|
||
docker compose up -d webui # http://127.0.0.1:18080
|
||
docker compose down -v # alles entfernen
|
||
```
|
||
|
||
`hosts.yaml` wird ins Daten-Volume geschrieben, weil Docker Desktop Netzlaufwerke nicht
|
||
einbinden kann. Nach dem Neuanlegen eines Agenten ändert sich sein Host-Schlüssel –
|
||
`keyscan` erneut ausführen.
|
||
|
||
Unter Windows mit Git Bash `docker compose exec … /pfad` mit `MSYS_NO_PATHCONV=1`
|
||
voranstellen, sonst wird der Pfad in einen Windows-Pfad umgeschrieben.
|
||
|
||
## Neue Sprache hinzufügen
|
||
|
||
1. `app/webui/locales/en.json` nach `app/webui/locales/<code>.json` kopieren (z. B. `fr.json`).
|
||
2. `"_name"` auf den Eigennamen der Sprache setzen (`"Français"`) – so erscheint sie im Dropdown.
|
||
3. Die Werte übersetzen; `{Platzhalter}` unverändert lassen. Fehlende Schlüssel fallen auf Englisch zurück.
|
||
4. Smoke-Test ausführen und die Oberfläche prüfen.
|
||
|
||
## Image bauen
|
||
|
||
```bash
|
||
docker build -f docker/Dockerfile --build-arg VERSION=1.0.0 -t fail2ban-webui:1.0.0 .
|
||
# Multi-Arch, wie in der CI
|
||
docker buildx build -f docker/Dockerfile --platform linux/amd64,linux/arm64 \
|
||
--build-arg VERSION=1.0.0 -t git.retronerd.at/schiwagoa/fail2ban-webui:1.0.0 --push .
|
||
```
|
||
|
||
Vor dem Veröffentlichen scannen:
|
||
|
||
```bash
|
||
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy:0.58.1 \
|
||
image --scanners vuln --ignore-unfixed --severity HIGH,CRITICAL fail2ban-webui:1.0.0
|
||
```
|
||
|
||
## Agent-Protokoll
|
||
|
||
Die Weboberfläche führt `ssh … <benutzer>@<host> "<befehl>"` aus; der Agent liest den Befehl
|
||
aus `SSH_ORIGINAL_COMMAND` und gibt genau eine JSON-Zeile aus:
|
||
|
||
```json
|
||
{"ok": true, "host": "web01", "agent_version": "1.0.0", "manual_jail": "manual-block",
|
||
"jails": {"sshd": {"bans": [{"ip": "203.0.113.7", "start": "2026-10-25 10:00:00",
|
||
"bantime": 600, "end": "2026-10-25 10:10:00"}], "total": 42}}}
|
||
```
|
||
|
||
Fehler: `{"ok": false, "error_key": "agent_protected", "error_args": {"ip": "…"}, "error": "English text"}`.
|
||
Die Weboberfläche übersetzt `error_key` mit `locales/*.json` (Schlüssel mit Präfix `agent_`);
|
||
unbekannte Schlüssel zeigen den englischen `error`-Text.
|
||
|
||
## Versionierung
|
||
|
||
- Versionsnummern folgen SemVer und werden beim Bauen gesetzt (Build-Argument `VERSION` →
|
||
`APP_VERSION`); der Agent hat eine eigene `VERSION` in `agent/f2b-webctl`.
|
||
- Jede Änderung kommt in `CHANGELOG.md` unter *Unreleased*.
|