# TODO-Liste ## Offen - [ ] Ziel: Bereitstellung einer schlanken Web-UI, die Ansible-Playbooks per CLI startet. - [ ] Authentifizierung erfolgt ausschließlich via extern gepflegter .htpasswd. - [ ] SSH-Keys werden nur abgelegt und referenziert; Berechtigungen bleiben bei Ops. - [ ] Keine Reverse-Proxy/TLS-Komponente im MVP; Service lauscht direkt auf Port 8000. - [ ] Hochgeladene Artefakte: ZIP/TAR. - [ ] Geplante Erweiterung: Automatisches Host-Onboarding (Strict Ops-First Policy) nach MVP-Release, abgestimmt mit [`webapp/entwicklung/architektur.md`](webapp/entwicklung/architektur.md:1) und [`webapp/entwicklung/api_endpoints.md`](webapp/entwicklung/api_endpoints.md:1). - [ ] Container-Basisimage finalisieren, Port 8000 exponieren. - [ ] Ordnerstruktur für Uploads, temporäre Runs und SSH-Key-Ablage anlegen. - [ ] Integration der Webserver-Basic-Auth (Übernahme REMOTE_USER, Fehlermeldungen). - [ ] Dokumentation für Ops zur Pflege der .htpasswd erstellen. - [ ] Datei-Uploads (ZIP/TAR) inkl. Validierung implementieren. - [ ] Playbook-Metadaten persistieren laut [`schema.sql`](webapp/entwicklung/schema.sql:1). - [ ] CLI-Executor: Wrapper für ansible-playbook inkl. Parameteraufbereitung. - [ ] Run-Verwaltung (Status, Logpfade) bauen. - [ ] Read-only-API zur SSH-Key-Liste implementieren. - [ ] API-Endpunkte gemäß [`api_endpoints.md`](webapp/entwicklung/api_endpoints.md:1) fertigstellen. - [ ] Funktionale Tests für Upload, Run-Start, Statuspolling. - [ ] CLI-Aufruf unter verschiedenen Inventaren/Variablen validieren. - [ ] Security-Checks: Keine Speicherung sensitiver Daten, Log-Redaktion. - [ ] Belastungstest der Upload/Polling-Flows (einfacher Load-Test). - [ ] Container-Image Review (kein TLS, nur HTTP). - [ ] Build-/Release-Pipeline konfigurieren (Container Registry). - [ ] Deployment-Checkliste erstellen (Port 8000, externe TLS-Schicht durch Ops). - [ ] Monitoring-Anbindung (Basis: Health Endpoint, Log-Verfügbarkeit). - [ ] Go-Live-Freigabe und Übergabe an Ops inkl. Betriebsdokumentation. - [ ] Architektur- und Security-Review abschließen; Spezifikation finalisieren (Strict Ops-First Policy, siehe [`webapp/entwicklung/architektur.md`](webapp/entwicklung/architektur.md:1)). - [ ] Datenbankmigrationen und Service-Layer implementieren (Hosts, Onboard-Jobs, Key-Metadaten) gemäß [`webapp/entwicklung/schema.sql`](webapp/entwicklung/schema.sql:1). - [ ] Backend: Onboarding-Service & Job-Runner (Key-Erzeugung, Fingerprint-Prüfung, sudo-Tasks) plus API-Endpunkte & Rate-Limits laut [`webapp/entwicklung/api_endpoints.md`](webapp/entwicklung/api_endpoints.md:1). - [ ] UI/UX: Onboarding-Formular, Status-Detailansicht, Ops-Approval-Dashboard inkl. Log-Viewer. - [ ] QA & Security: Integrationstests, Sudo-/SSH-Härtung, Pen-Test light, Memory-Handling-Checks (keine Persistenz von Passwort/Secret). - [ ] Ops Enablement: Prozesse für known_hosts-Sync, Runbooks, Alerting, Eskalationspfade; Schulung der Ops-Gruppe. - [ ] Staging-Dryrun mit realistischem Host; Post-Mortem + Go/No-Go Entscheidung. - [ ] Abhängigkeiten: Abschluss Phase 1–3, verfügbare Ops-Ressourcen für Fingerprint-Freigaben und Sicherheitstests. - [ ] Integrierter Reverse-Proxy/TLS-Termination. - [ ] Erweiterter Credential-Store oder Secrets-Management. - [ ] Rollenbasierte Zugriffssteuerung jenseits .htpasswd. - [ ] UI-Verbesserungen für Run-Output (Streaming, Filter). - [ ] Automatisierte Key-Rotation inklusive Berechtigungsupdates. - [ ] Self-Service Ops Workflow für Re-Onboarding/Key-Rotation (Erweiterung der Onboarding-Plattform). - [ ] Keine; Onboarding-Policy (Strict Ops-First) und Sicherheitsvorgaben abgestimmt. - [ ] HTTP-Basic wird extern via .htpasswd gepflegt; Webserver setzt Auth und ggf. REMOTE_USER. - [ ] Die Applikation verifiziert keine internen Benutzer, erwartet ggf. REMOTE_USER zur Audit-Zuordnung. - [ ] Beschreibung: Simple Health-Check. - [ ] Antwort: 200 OK. - [ ] Beschreibung: Liste aller hochgeladenen Playbooks (Metadaten). - [ ] Query: ?limit=&offset=. - [ ] Antwort: JSON Array [{id,name,filename,uploaded_by,uploaded_at}]. - [ ] Beschreibung: Upload eines ZIP/TAR mit Playbook(s). - [ ] Konsumiert: multipart/form-data file=.... - [ ] Validierung: MIME und Dateiendung (zip,tar,tgz), Größenlimit. - [ ] Antwort: 201 Created + Metadaten. - [ ] Beschreibung: Metadaten zu einem Playbook. - [ ] Antwort: JSON. - [ ] Beschreibung: Startet einen Run via systemweiter ansible-playbook CLI. Keine Nutzung von ansible-runner. - [ ] Body: optional JSON {inventory: string, extra_vars: object, tags: [string], become: bool}. - [ ] Behaviour: Prozess wird vom Service gestartet; stdout/stderr werden in temporäre Dateien geschrieben. - [ ] Antwort: 202 Accepted {run_id}. - [ ] Beschreibung: Statusabfrage (queued,running,success,failed). - [ ] Antwort: JSON {run_id,status,exit_code,started_at,finished_at}. - [ ] Beschreibung: Holt vollständiges stdout/stderr des Runs (Text/stream). - [ ] Antwort: text/plain (oder chunked). - [ ] Beschreibung: Listet referenzierbare SSH-Keys (nur lesend). - [ ] Antwort: JSON [{key_id,filename,description}]. - [ ] Beschreibung: Zugriff auf Run-Logs / Audit-Einträge (keine sensiblen Daten). - [ ] Antwort: JSON. - [ ] Die Applikation führt keine Änderung an SSH-Keys oder .htpasswd durch. - [ ] Alle schreibenden Betriebsaufgaben (Permissions, Key-Rollout, TLS) sind außerhalb des MVP-Scopes. - [ ] Auth via vorhandene HTTP-Basic/.htpasswd-Integration; Webserver stellt REMOTE_USER zur Verfügung. - [ ] Ops-spezifische Endpoints (z. B. Approve) erfordern REMOTE_USER ∈ Ops-Gruppe (Ops-Policy). - [ ] Transport: Produktion erfordert TLS (Ops-Deployment-Voraussetzung). - [ ] POST /onboard/requests. - [ ] GET /onboard/requests. - [ ] GET /onboard/requests/{id}/status. - [ ] POST /onboard/requests/{id}/approve. - [ ] POST /onboard/requests/{id}/cancel. - [ ] GET /onboard/jobs. - [ ] GET /onboard/keys. - [ ] GET /onboard/requests/{id}/logs. - [ ] Zweck: Erstellt eine Onboarding-Anfrage / startet ein Onboarding-Job (sofern Pre-Checks erfolgreich sind). - [ ] Auth: REMOTE_USER (any authenticated user). - [ ] Konsumiert: application/json. - [ ] Payload: { "host": "192.0.2.10", "port": 22, "login_user": "ubuntu", "login_password": "secret", "desired_user": "ansible", "generate_key": true, "public_key": null, "description": "Kurzinfo", "options": { "force_approve": false } }. - [ ] Verhalten: - [ ] Validierung von Pflichtfeldern. - [ ] Erzeugt Onboard-Request und Onboard-Job, reply enthält { "job_id": "...", "status": "created" }. - [ ] Wenn Fingerprint nicht mit Ops known_hosts übereinstimmt, wird status = "awaiting_approval". - [ ] Antwort: 201 Created { "job_id": "uuid", "status": "created" | "awaiting_approval" | "queued" }. - [ ] Fehlercodes: - [ ] 400 Bad Request (Validierungsfehler). - [ ] 401 Unauthorized. - [ ] 429 Too Many Requests (Rate-Limit pro User/Host). - [ ] Zweck: Listet Onboarding-Requests (nur Metadaten). - [ ] Query: ?limit=&offset=&status=. - [ ] Antwort: JSON Array [{job_id, host, requested_by, status, created_at, fingerprint_sha256?}]. - [ ] Zweck: Statusabfrage für einen Request. - [ ] Antwort: { "job_id": "...", "host": "...", "status": "created|queued|running|awaiting_approval|approved|onboarded|failed|cancelled", "retries": 0, "started_at": "...", "finished_at": "...", "error_message": "kurze Fehlerdiagnose (sensitivitäts-gefiltert)" }. - [ ] Zweck: Ops-Endpoint zur Freigabe eines abweichenden Host-Fingerprints. - [ ] Auth: REMOTE_USER muss Ops sein (Server-Side check). - [ ] Payload: { "approve": true, "operator_note": "Fingerprint validiert via call", "operator_id": "ops-username" }. - [ ] Verhalten: Wenn genehmigt, Job wird zur Fortsetzung freigegeben; Audit-Eintrag mit operator_id erzeugt. - [ ] Antwort: 200 OK { "job_id": "...", "status": "approved" }. - [ ] Fehler: 403 Forbidden (wenn nicht Ops), 404 Not Found. - [ ] Zweck: Bricht laufenden/queued Onboarding-Job ab (z. B. User Abbruch). - [ ] Auth: Requester oder Ops. - [ ] Antwort: 200 OK { "job_id": "...", "status": "cancelled" }. - [ ] Zweck: Admin/Operator Sicht auf Onboard-Jobs (Metadaten). - [ ] Filters: status, requested_by, host. - [ ] Antwort: Array von job-Metadaten (keine sensitiven Inhalte). - [ ] Zweck: Listet erzeugte Public-Keys (Metadaten only). - [ ] Antwort: [{ "key_id": "...", "host_id": "...", "public_key_fingerprint": "...", "created_at": "..." }]. - [ ] Zweck: Liefert redigierte Logs des Onboarding-Jobs (Ausgaben, Schritte). - [ ] Sicherheits-Hinweis: Logs sind gesäubert; keine Passwörter oder private Key-Material enthalten. - [ ] Antwort: text/plain oder JSON { "lines":[ ... ] }. - [ ] Login-Password darf niemals geloggt werden; im API-Server mittelbar nur in-memory übergeben. - [ ] API darf niemals privaten Schlüssel in Responses zurückliefern. - [ ] Alle Endpoints, die sensible Ablaufsteuerung erlauben (approve, cancel), müssen REMOTE_USER-Checks durchführen. - [ ] Rate-Limits: Schutz gegen bruteforce / DOS. - [ ] Input-Sanitization: host/username dürfen keine Shell-Injection ermöglichen; SSH-Interaktionen erfolgen kontrolliert. - [ ] Audit: Jeder state-wechsel (created, awaiting_approval, approved, onboarded, failed, cancelled) schreibt ein Metadaten-Audit (siehe [`webapp/entwicklung/schema.sql`](webapp/entwicklung/schema.sql:1) Anpassungen). - [ ] UI-Form "Host Onboarding" ↟ POST /onboard/requests. - [ ] UI-Ops Dashboard ↟ GET /onboard/requests?status=awaiting_approval. - [ ] UI-Ops Approve Button ↟ POST /onboard/requests/{id}/approve. - [ ] UI-User Status Polling ↟ GET /onboard/requests/{id}/status. - [ ] UI-Logs ↟ GET /onboard/requests/{id}/logs. - [ ] Schritt 1: User sendet POST /onboard/requests mit login_password. - [ ] Schritt 2: API antwortet job_id. - [ ] Schritt 3: Onboarding Service führt Pre-Check aus; bei Fingerprint-Mismatch → awaiting_approval. - [ ] Schritt 4: Ops Approver ruft POST /onboard/requests/{id}/approve → Service fährt fort. - [ ] Schritt 5: Job schreibt audit_logs und setzt Host Status auf onboarded oder failed. - [ ] Architektur: [`webapp/entwicklung/architektur.md`](webapp/entwicklung/architektur.md:1). - [ ] DB Schema: [`webapp/entwicklung/schema.sql`](webapp/entwicklung/schema.sql:1). - [ ] Roadmap: [`webapp/entwicklung/roadmap.md`](webapp/entwicklung/roadmap.md:1). ## Erledigt *(noch keine Einträge)*