Files
insight-updater/PROMPT.md
T
B0rbor4d cc4c3fcecb Hub-and-Spoke Umbau: Multi-Tenant Zentrale + Satellite-Agent
- Backend: Customer/Satellite Models, customer_id auf Server/Job/Audit
- Satellite-API: heartbeat, poll (atomares Claiming), logs, result,
  scan-result, health-report - Auth via X-Api-Key (SHA-256 gehasht)
- Job-Queue: pending/claimed/running/success/failed + Stale-Janitor
- Batch-Trigger: ein Job pro Server, Satellite arbeitet sequenziell ab
- Credentials bleiben lokal: nur symbolische credential_ref zentral
- Neues Paket satellite/: Pull-Loop, WinRM/SSH/CAU/Scanner, PyInstaller-tauglich
- Frontend: Kunden-Switcher, Satelliten-View, Polling statt WebSocket
- Entfernt: WebSocket/Socket.io, Redis, zentrale Credentials, JobRunner
- Docs: README/AGENTS/PROMPT auf neue Architektur aktualisiert
2026-08-07 03:42:06 +00:00

113 lines
5.2 KiB
Markdown

# Insight Updater - Project Prompt
## Overview
Zentrale, mandantenfaehige Update-Orchestrierung fuer Kundennetzwerke (MSP-Modell).
Hub-and-Spoke: eine zentrale Instanz (Docker, bei Insight-IT) plus schlanke
Satelliten pro Kunde (eine Binary, kein Docker beim Kunden noetig). Satelliten pollen
Jobs von der Zentrale, fuehren Updates lokal im Kundennetz aus und melden Ergebnisse
zurueck. Dashboard zeigt alles nach Kunde sortiert.
## Target Stack
- **Zentrale Backend**: FastAPI + Python 3.11+, SQLAlchemy + SQLite/PostgreSQL, structlog
- **Zentrale Frontend**: Vue 3 + TypeScript + Vite, Pinia, Tailwind CSS
- **Satellite**: Python 3.11+, pywinrm, asyncssh, httpx, PyInstaller One-File-Binary
- **Infra**: Docker Compose (nur Zentrale), Traefik Labels
- **CI/CD**: Gitea Actions / Woodpecker CI fuer Build + Deploy auf monitoring (10.0.2.105)
## Architektur-Entscheidungen
- **Pull-Modell**: Satelliten pollen (default 30s). Keine eingehenden Verbindungen beim
Kunden, kein VPN, keine Firewall-Ausnahmen - nur ausgehend 443 zur Zentrale.
- **Keine Live-Daten**: Log-Batches statt WebSocket. Dashboard refresht alle 10s.
- **Credentials lokal**: WinRM/SSH-Zugangsdaten nur auf dem Satellite (credentials.yaml).
Zentral gibt es nur symbolische `credential_ref`-Namen.
- **Netz-Orchestrierung**: 1-2 Satelliten pro Kunde steuern alle Server des Kunden,
aehnlich wie CAU einen Cluster steuert. Batch-Trigger legt pro Server einen Job an,
der Satellite arbeitet sie sequenziell ab.
- **Job-Claiming atomar**: zwei Satelliten eines Kunden bekommen nie denselben Job.
## Core Features
1. **Kunden + Satelliten** - CRUD, API-Key einmalig angezeigt, rotierbar
2. **Server-Inventar pro Kunde** - manuell oder per Netzwerk-Scan (Auto-Discovery)
3. **Job-Queue** - pending/claimed/running/success/failed/cancelled + Stale-Janitor
4. **Windows Update** - WinRM, Microsoft.Update.Session, optional Reboot
5. **Linux Update** - apt/dnf/yum via SSH mit sudo, optional Reboot
6. **CAU** - Invoke-CauRun auf Failover-Clustern
7. **Netzwerk-Scan** - Ping + Port 5985/22, legt Hosts zentral als Server an
8. **Audit-Log** - strukturiert, pro Kunde filterbar
## Non-Goals
- Kein WSUS/SCCM-Ersatz, keine Approval-Workflows
- Kein Live-Streaming (bewusst: Pull + Batches)
- Kein RBAC ueber admin/user hinaus
- Keine zentral gespeicherten Kunden-Credentials
## Success Criteria
- Kunde anlegen -> Satellite anlegen -> API-Key einmalig angezeigt
- Satellite startet -> erscheint als "online" im Dashboard (Heartbeat)
- Netzwerk-Scan -> gefundene Hosts im Inventar (discovered_by_scan)
- Update triggern -> Satellite claimed Job -> Logs + Ergebnis im Dashboard
- Batch: "Alle Server updaten" -> ein Job pro Server, sequenzielle Abarbeitung
- Zwei Satelliten eines Kunden: kein Job doppelt
- Satellite offline waehrend Job -> Janitor markiert Job nach Timeout als failed
- `docker compose up -d` -> Zentrale healthy in <5 min
## Verification Commands
```bash
curl -f http://localhost:8000/health
curl -f http://localhost:3000/
docker compose ps
```
## Deployment Target
- **Host**: monitoring.insight.local (10.0.2.105)
- **User**: b0rbor4d (sudo via Vaultwarden)
- **Docker**: Podman/Docker Compose v2
- **Reverse Proxy**: Traefik (labels on compose services)
- **Erreichbarkeit**: HTTPS 443 von Kundenstandorten aus (ausgehend)
- **Git Remote**: ssh://git@gitea.insight-it.de:2222/b0rbor4d/insight-updater.git
## Security
- Dashboard: JWT RS256, kurze Expiry
- Satelliten: API-Key (ius_...), SHA-256 gehasht in DB, Prefix fuer Anzeige
- Keine Kunden-Credentials in der zentralen DB
- Audit-Log: append-only
- TLS: Traefik + LetsEncrypt
## Project Structure
```
~/projects/insight-updater/
├── backend/ # Zentrale API
│ ├── app/
│ │ ├── api/routes/ # auth, customers, satellites, servers, updates, audit, satellite_api
│ │ ├── core/ # config, security, db, logging, exceptions
│ │ ├── models/ # Customer, Satellite, Server, UpdateJob, UpdateLog, AuditLog, User
│ │ ├── schemas/ # Pydantic
│ │ ├── services/ # audit, janitor
│ │ └── main.py
│ ├── Dockerfile
│ └── pyproject.toml
├── frontend/ # Dashboard
│ ├── src/
│ │ ├── views/ # Dashboard, Customers, Satellites, Servers, Updates, Audit, Login
│ │ ├── stores/ # auth, customers, satellites, servers, updates
│ │ └── components/ # AppLayout (mit Kunden-Switcher)
│ ├── Dockerfile
│ └── package.json
├── satellite/ # Remote-Agent
│ ├── satellite/
│ │ ├── runner.py # Main-Loop
│ │ ├── client.py # Zentral-API-Client
│ │ ├── config.py # config.yaml + credentials.yaml
│ │ ├── winrm_exec.py, ssh_exec.py, cau_exec.py, scanner.py
│ ├── config.example.yaml
│ ├── credentials.example.yaml
│ └── pyproject.toml
├── docker-compose.yml
├── docker-compose.prod.yml
└── .env.example
```
## Environment Variables
Zentrale siehe `.env.example`: SECRET_KEY, DATABASE_URL, JWT-Keys, LDAP-Stub.
Satellite siehe `satellite/config.example.yaml`: central_url, api_key, poll_interval.