cc4c3fcecb
- 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
113 lines
5.2 KiB
Markdown
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.
|