Files
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

5.2 KiB

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

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.