Add first-run admin setup and independent password and API token rotation

This commit is contained in:
Mikei386
2026-09-28 15:02:41 +02:00
parent e86e540ae4
commit 9f3a13e45f
20 changed files with 651 additions and 76 deletions
+128
View File
@@ -0,0 +1,128 @@
# Zugang und API · Athena Deck 0.3
## Ersteinrichtung
Beim ersten Öffnen der lokalen Oberfläche legt der Betreiber zwei getrennte
Zugangsdaten fest:
1. **Oberflächenkennwort**: 16–256 Zeichen, ein Administratorzugang.
2. **API-Token**: 32–256 Zeichen aus Buchstaben, Ziffern, Bindestrich/Unterstrich.
„Sicheren Token erzeugen“ erzeugt mit dem Browser-Zufallsgenerator 32 zufällige
Bytes, dargestellt als Hexwert mit `ad_`-Präfix. Alternativ eigenen Token einsetzen.
Kennwort und Token dürfen nicht identisch sein. Der Token kann während der Eingabe
angezeigt/kopiert werden. **Vor dem Speichern im Passwortmanager sichern.** Ein
vorhandener Token ist anschließend nicht abrufbar; bei Verlust einen neuen setzen.
Auf HTTP-Adressen kann die Browser-Zwischenablage gesperrt sein. Dann „Token anzeigen“
verwenden und manuell kopieren. Im ersten Schritt wird noch keine Sitzung erzeugt:
nach dem Einrichten mit dem gewählten Kennwort anmelden.
Lokaler Zustand: `.state/auth.json`, Verzeichnis 0700, Datei 0600, in Git und
Docker-Builds ausgeschlossen. Es gibt keine voreingestellten oder vom Agenten
festgelegten Zugangsdaten. Auch die Mac-Verwaltungsoberfläche verlangt jetzt die
Ersteinrichtung und Anmeldung. Status, Hardware und Steuerung sind davor gesperrt.
Der Ersteinrichtungs-Endpunkt ist einmalig und nur in der Loopback-Instanz aktiv.
Die optionale Athena-Serverinstallation erhält in ihrem Installationsformular
**eigene** Zugangsdaten (Kennwort und API-Token). Diese gelten für die Server-Instanz,
nicht für die Mac-Instanz. Die Server-Anwendung wird bereits provisioniert gestartet;
es gibt keinen ungeschützten Fernzugriff, mit dem ein beliebiger Besucher den
Server beanspruchen könnte. Ein vorhandener 0.2-Kennwortstand bleibt lesbar;
API-Zugriff ist dort zunächst deaktiviert, bis ein Token eingerichtet wird.
Bestehende Server-Container werden durch diese Codeänderung nicht automatisch aktualisiert.
## Einstellungen → Zugang & API
- **Kennwort ändern:** aktuelles Kennwort, neues Kennwort und Wiederholung eingeben.
Nach erfolgreicher Speicherung sind alle Browser-Sitzungen ungültig. Erneut mit
dem neuen Kennwort anmelden. Der API-Token bleibt gültig.
- **API-Token ändern:** aktuelles Oberflächenkennwort bestätigen und neuen Token
einsetzen oder erzeugen. Nach Speicherung wird der alte Token sofort abgewiesen.
Browser-Sitzungen bleiben gültig. API-Clients müssen den neuen Token erhalten.
- **Abmelden:** beendet die aktuelle Sitzung serverseitig.
Die Einstellungsseite benennt die gerade verwaltete Instanz (Mac oder Athena).
Es gibt zunächst **einen Administrator**, keine Benutzernamen, weiteren Benutzer,
Rollen, persönlichen Tokens oder Passwort-zurücksetzen-per-E-Mail.
## Browser und API sind getrennt
Die Oberfläche verwendet acht Stunden gültige HttpOnly-/SameSite=Strict-Cookies.
Mutationen im Browser benötigen zusätzlich `X-Athena-Deck: 1` und einen passenden
Origin. Kennwortprüfung und sensible Änderungen sind auf zehn Versuche pro Minute
und Instanz begrenzt. Zugangsdaten werden niemals in Querystrings übertragen.
API-Clients verwenden `Authorization: Bearer <API-TOKEN>`. Aktuell erlaubt sind:
| Methode | Endpunkt |
|---|---|
| GET | `/api/v1/status` |
| GET | `/api/v1/hardware` |
| GET | `/api/v1/demo` |
| POST | `/api/v1/demo/start` |
| POST | `/api/v1/demo/stop` |
API-Clients brauchen weder Cookie noch Browser-CSRF-Header. Ein vorhandener
Authorization-Header wird ausdrücklich geprüft; ein ungültiger Token wird nicht
über ein zusätzliches gültiges Browser-Cookie umgangen. Der API-Token erlaubt
**keine** Zugangsdaten-, WireGuard-, Installations- oder sonstigen Admin-Aktionen.
Beispiel (Platzhalter ersetzen):
```sh
curl -H 'Authorization: Bearer <API-TOKEN>' http://127.0.0.1:8108/api/v1/status
```
Die späteren Modell-/Inferenz-Endpunkte existieren noch nicht. Ihre Autorisierung
muss beim Ergänzen explizit an die Token-Prüfung angeschlossen werden. Es wird kein
produktiver Router-Token verändert. Der WireGuard-Zugriffsmodus gilt weiterhin vor
der Authentifizierung: ein gültiger Token umgeht keine gesperrte LAN-/Tunnelroute.
## Speicherung und Serverbetrieb
Kennwörter: PBKDF2-HMAC-SHA256 mit 600.000 Iterationen und individuellem Salt.
API-Tokens: ausschließlich SHA-256-Prüfwert (bei generierten Tokens 256 Bit Zufall).
Keine Klartext-Speicherung von Kennwort oder Token. Statusantworten enthalten nur
Einrichtungsstatus und Änderungszeiten, keine Hashes, Kennwörter oder Tokenwerte.
Lokale Schreibvorgänge sind atomar; bei fehlgeschlagenem Schreiben bleibt der alte
Stand gültig. Die lokale Anwendung serialisiert Einrichtung und Änderungen. Im
Servercontainer persistiert der Root-Helper Änderungen unter `/data/auth.json` über
eine fest definierte RPC-Schnittstelle; der Webprozess bleibt unprivilegiert.
Versionsprüfung verhindert das Überschreiben inzwischen geänderter Zugangsdaten.
Der Webprozess liest den aktuellen Stand bei der Autorisierung. Es gibt keinen
veralteten Credential-Snapshot in Umgebungsvariablen. Neustarts erhalten geänderte
Zugangsdaten und verwerfen Sitzungen.
Die Netzwerkschicht leitet Authorization gezielt weiter, vertraut jedoch weiterhin
keinen vom Client gesetzten Ingress-Headern. Kein CORS-Zugriff, kein Docker-Socket im
Webprozess. Die bestehende Transportgrenze bleibt: lokale Nutzung über Loopback,
Server über WireGuard/SSH; der direkte LAN-Zugang bietet derzeit HTTP, kein HTTPS.
## API für die Oberfläche
| Methode / Endpunkt | Inhalt / Verhalten |
|---|---|
| GET `/api/v1/auth/status` | Öffentlich nur initialized/authenticated; angemeldet zusätzlich Zeiten und Tokenstatus |
| POST `/api/v1/auth/setup` | password, api_token; einmalige lokale Einrichtung |
| POST `/api/v1/login` | password; setzt Sitzungscookie |
| POST `/api/v1/logout` | aktuelle Sitzung beenden |
| POST `/api/v1/auth/password` | current_password, new_password; Sitzung erforderlich |
| POST `/api/v1/auth/token` | current_password, new_token; Sitzung erforderlich |
| POST `/api/v1/network/install` | password, api_token für die neue Server-Instanz; lokale Admin-Sitzung erforderlich |
Keine generische Benutzerverwaltung oder API für das Auslesen der Geheimnisse.
## Verifikation
26 lokale Tests: Ersteinrichtung, parallele Einrichtung, fehlende Anmeldung,
Kennwort-/Tokenwechsel, alte und neue Credentials, alle Sitzungen, Token-Rechte,
Logout, Legacy-Stand, Dateirechte, fehlgeschlagenes Schreiben, keine Klartexte in
der Persistenz, vorhandene Demo-/WireGuard-Regressionsprüfungen.
Zusätzlich echte Tests in zwei kurzlebigen Docker-Containern auf Athena:
Token durch Proxy, gesperrte Admin-Endpunkte, beide Rotationen, alte Credentials
abgewiesen, neue Credentials nach Container-Neustart gültig. WireGuard-Handshake,
Ingress-Sperren und Rückfallverhalten weiterhin erfolgreich. Keine Host-Ports
für Tests veröffentlicht; Testcontainer und Test-Secrets entfernt. Startzeiten
aller zuvor vorhandenen Container unverändert.