Sicherheits-Härtung und Bugfixes

This commit is contained in:
Patrick Asmus
2026-10-11 17:39:03 +02:00
parent c3f68ace96
commit 65b0b5ac0f
25 changed files with 2577 additions and 686 deletions
+56 -8
View File
@@ -2,6 +2,8 @@
Alle Funktionen des Web-UI sind auch per REST-API verfügbar. Basis-URL: `http://<host>:8484`
Die interaktive API-Dokumentation (Swagger-UI unter `/docs`) ist standardmäßig deaktiviert und kann mit der Umgebungsvariable `ENABLE_API_DOCS=1` eingeschaltet werden.
## Endpunkte
### System
@@ -9,8 +11,8 @@ Alle Funktionen des Web-UI sind auch per REST-API verfügbar. Basis-URL: `http:/
| Methode | Pfad | Beschreibung |
|---------|------|-------------|
| `GET` | `/api/health` | Health Check (kein Auth nötig) |
| `GET` | `/api/config` | Konfiguration lesen |
| `PUT` | `/api/config` | Konfiguration speichern |
| `GET` | `/api/config` | Konfiguration lesen (ohne Secrets) |
| `PUT` | `/api/config` | Konfiguration speichern (siehe [Konfiguration](#konfiguration)) |
### Jobs
@@ -20,8 +22,8 @@ Alle Funktionen des Web-UI sind auch per REST-API verfügbar. Basis-URL: `http:/
| `POST` | `/api/jobs` | Neuen Job erstellen |
| `GET` | `/api/jobs/:id` | Job-Details abrufen |
| `PUT` | `/api/jobs/:id` | Job aktualisieren |
| `DELETE` | `/api/jobs/:id` | Job löschen |
| `POST` | `/api/jobs/:id/record` | Job-Aufnahme starten |
| `DELETE` | `/api/jobs/:id` | Job löschen (nicht während einer laufenden Aufnahme → 400) |
| `POST` | `/api/jobs/:id/record` | Job-Aufnahme starten (läuft bereits → 409) |
### Senderbibliothek
@@ -31,7 +33,7 @@ Alle Funktionen des Web-UI sind auch per REST-API verfügbar. Basis-URL: `http:/
| `POST` | `/api/stations` | Neuen Sender erstellen |
| `GET` | `/api/stations/:id` | Sender-Details abrufen |
| `PUT` | `/api/stations/:id` | Sender aktualisieren |
| `DELETE` | `/api/stations/:id` | Sender löschen |
| `DELETE` | `/api/stations/:id` | Sender löschen (verknüpfte Jobs werden gelöst) |
### Schnellaufnahme
@@ -48,6 +50,8 @@ Alle Funktionen des Web-UI sind auch per REST-API verfügbar. Basis-URL: `http:/
}
```
Erlaubte URL-Schemata: `http`, `https`, `rtmp`, `rtmps`, `rtsp`, `rtsps`. Für Job-Felder gelten dieselben Prüfungen wie im Web-UI (siehe [Jobs](jobs.md#validierung)).
### Aufnahmen
| Methode | Pfad | Beschreibung |
@@ -55,7 +59,7 @@ Alle Funktionen des Web-UI sind auch per REST-API verfügbar. Basis-URL: `http:/
| `GET` | `/api/recordings` | Alle Aufnahmen (Parameter: `active_only`, `limit`) |
| `GET` | `/api/recordings/:id` | Aufnahme-Status |
| `POST` | `/api/recordings/:id/stop` | Aufnahme stoppen |
| `POST` | `/api/recordings/:id/extend?minutes=30` | Aufnahme verlängern |
| `POST` | `/api/recordings/:id/extend?minutes=30` | Aufnahme verlängern (`minutes` 1–1440; bei unbegrenzter Aufnahme → 400) |
| `POST` | `/api/recordings/:id/unlimited` | Zeitlimit entfernen |
### Logs
@@ -64,12 +68,56 @@ Alle Funktionen des Web-UI sind auch per REST-API verfügbar. Basis-URL: `http:/
|---------|------|-------------|
| `GET` | `/api/logs` | Protokoll (Parameter: `limit`, `level`) |
Zeitstempel in API-Antworten sind UTC mit Offset, z.B. `2026-10-11T14:30:00+00:00`.
## Konfiguration
`GET /api/config` liefert keine Secrets. Stattdessen zeigen boolesche Felder an, ob ein Wert gesetzt ist:
| Feld | Bedeutung |
|------|-----------|
| `auth.password_set` | Passwort ist gesetzt |
| `ntfy.token_set` | NTFY-Token ist gesetzt |
| `plik.api_key_set` | Plik-API-Key ist gesetzt |
Regeln für `PUT /api/config`:
- Secret-Felder (`auth.password`, `ntfy.token`, `plik.api_key`) weglassen = unverändert
- Leerer String `""` = Secret entfernen (nicht beim Passwort)
- `auth.enabled: true` erfordert ein Passwort (mind. 8 Zeichen)
- `download_path` muss innerhalb von `RECORDING_ROOTS` liegen
- Unbekannte Schlüssel → 422
- Der Abschnitt `server` kann nicht über die API geändert werden
```bash
curl -u admin:passwort -X PUT http://localhost:8484/api/config -H "Content-Type: application/json" -d '{"ntfy": {"url": "https://ntfy.sh/mein-topic", "events": "start,error"}}'
```
## Authentifizierung
Bei aktiviertem Auth wird Basic Authentication verwendet:
Bei aktiviertem Auth (Standard bei Neuinstallationen) wird Basic Authentication verwendet:
```bash
curl -u admin:passwort http://localhost:8484/api/jobs
```
Der Health-Endpunkt (`/api/health`) ist immer ohne Auth erreichbar.
- Der Health-Endpunkt (`/api/health`) ist immer ohne Auth erreichbar.
- Nach 10 fehlgeschlagenen Logins innerhalb von 5 Minuten antwortet der Server für diese IP bis zum Ende des Zeitfensters mit 429.
## Browser-Zugriff
CORS ist nicht aktiviert. Schreibende Requests (`POST`, `PUT`, `DELETE`) mit fremdem `Origin` werden mit 403 abgewiesen. Die API ist damit aus Skripten/curl (ohne `Origin`-Header) und aus dem eigenen Web-UI nutzbar, nicht aber von fremden Webseiten.
## Fehlercodes
Fehler werden als JSON mit Feld `detail` zurückgegeben.
| Code | Bedeutung |
|------|-----------|
| `400` | Ungültige Anfrage, Meldung auf Deutsch (z.B. nicht erlaubte ffmpeg-Argumente, unzulässiger Pfad) |
| `401` | Anmeldung erforderlich oder fehlgeschlagen |
| `403` | Cross-Site-Request abgewiesen |
| `404` | Objekt nicht gefunden |
| `409` | Konflikt, z.B. Job nimmt bereits auf |
| `422` | Validierungsfehler (ungültige Felder, unbekannte Schlüssel) |
| `429` | Zu viele fehlgeschlagene Logins |