Architektur¶
Übersicht¶
Vesana ist ein push-basiertes Monitoring-System: Agents und Collectors verbinden sich von außen zum Server und schicken Check-Ergebnisse rein. Der Server hat keine ausgehende Verbindung zu den überwachten Maschinen.
flowchart LR
subgraph "Im Kundennetz"
A[Agent auf Servern] -->|HTTPS POST| EXIT[outbound 443]
C[Collector VM] -->|HTTPS POST| EXIT
end
subgraph "Vesana-Server"
EXIT --> R[Receiver]
R --> RS[(Redis Stream)]
RS --> W1[Worker 0]
RS --> W2[Worker 1]
RS --> W3[Worker N]
W1 --> DB[(Postgres + TimescaleDB)]
W2 --> DB
W3 --> DB
DB --> API[REST API]
API --> FE[React Frontend]
API --> M[Mobile App]
end
Komponenten¶
Receiver¶
- FastAPI-Service, der Agent- und Collector-Pakete entgegennimmt
- Authentifiziert per
X-API-Key(Collector) oderX-Agent-Token(Agent) - Validiert das Schema, schreibt sofort in den Redis Stream — keine Logik, kein DB-Zugriff
- Ziel: möglichst kurze Latenz, möglichst hohe Durchsatzrate
Redis Stream¶
- Backpressure-fähige Eingangs-Queue (
XADD/XREADGROUP) - Mehrere Worker konsumieren parallel
- Bei vollem Stream lehnt der Receiver ab (
noeviction-Policy) — kein stilles Drop
Worker¶
- Liest Messages, holt Host-/Service-Kontext aus der DB
- Wendet Profile-Check-Effective-Config an, normalisiert Werte
- Schreibt Check-Ergebnisse in
check_results(Hypertable) - Aktualisiert
current_status(Hot-Table mitfillfactor=80) - Triggert Alert-Auswertung, Notification-Versand, AI-Analyse-Cache-Invalidierung
API¶
- FastAPI mit JWT-Auth, Tenant-Scope automatisch über ORM-Filter
- Endpoints: Hosts, Services, Profile, Discoveries, Alerts, Reports, Wiki, AI, Admin
- Background-Tasks: Downtime-Watcher, Dead-Collector-Watcher, Anomaly-Baselines, Auto-Purge, Tester-Phone-Home
- Distributed Locking via Redis — bei mehreren API-Replicas läuft jeder Watcher nur einmal
Frontend¶
- React 18 + TypeScript + Vite
- Themed via CSS-Variablen (20 Themes × dark/light)
- Lazy-Loaded ECharts für Charts, Lazy-Loaded ReactMarkdown für Wiki
Agent (Go)¶
- Single-Binary, statisch gelinkt (
CGO_ENABLED=0), ~6.5 MB - Holt Config alle 5 Minuten, führt Checks lokal aus
- Auto-Update beim Config-Refresh wenn Server eine neuere Version meldet
Collector (Go)¶
- Single-Binary, läuft im Kundennetz auf einer Linux-VM
- Führt Remote-Checks aus: SNMP, Ping, SSH, HTTP, Discovery (nmap)
- Holt Config alle 60 Sekunden, schickt Ergebnisse + Discovery-Resultate an Server
Mobile-App¶
- React Native + Expo, Android-APK
- Eigener API-Client, Push-Token-Registration via FCM
- Tap auf Push → Deep-Link zur Host-Detail-Seite
Multi-Tenant-Isolation¶
Tenants sind die zentrale Trennlinie. Jede DB-Tabelle mit Kunden-Daten hat eine tenant_id-Spalte. Auf ORM-Ebene erzwingt apply_tenant_filter() (api/app/auth.py) die Filterung — wer eine Query ohne Tenant-Scope absetzt, kriegt einen Runtime-Error.
Super-Admins haben Tenant-Scope null und sehen alles. Normale Nutzer sind an einen Tenant gebunden, mit optionalem Cross-Tenant-Read in Custom-Roles.
flowchart TB
subgraph Super-Admin
SA[user.tenant_scope = null] --> ALLES[(alle Tenants)]
end
subgraph Tenant A
UA[user.tenant_id = A] --> A[(Hosts/Alerts A)]
end
subgraph Tenant B
UB[user.tenant_id = B] --> B[(Hosts/Alerts B)]
end
Sicherheits-Architektur¶
Vier Säulen:
1 Verschlüsselung sensibler Felder¶
shared/encryption.py bietet encrypt_field() / decrypt_field() (AES-256-GCM). Verschlüsselt werden u. a. SNMP-Communities, SSH-Passwörter. Schlüssel: FIELD_ENCRYPTION_KEY (Base64url, 32 Bytes). Der Server hält Plaintext nur kurz im RAM.
Details: Sicherheit → Verschlüsselung.
2 Token-basierte Authentifizierung¶
| Token | Format | Speicherung | Wer benutzt |
|---|---|---|---|
| User-JWT | RS256 | Browser/Mobile lokal | Endbenutzer-Login |
| Agent-Token | vesana_agent_ + 32 url-safe Base64 |
SHA256-Hash in agent_tokens.token_hash |
Agent zum Receiver |
| API-Key | Custom-Prefix + 32 Bytes | SHA256-Hash in api_keys.key_hash |
Collector zum Receiver |
Plaintext wird nie in der DB gespeichert — nur Hashes. Keys sind genau einmal sichtbar (beim Erzeugen).
3 Rate-Limiting¶
Login-Endpoint und 2FA-Verify sind per IP auf 10 req/min gedeckelt (slowapi). Zweck: Brute-Force gegen schwache Passwörter und 2FA-Codes verlangsamen.
4 Distributed Locking¶
Mehrere API-Replicas? downtime_expiry_watcher, dead_collector_watcher etc. laufen nur einmal — Redis-Locks mit 55 s Timeout sorgen dafür.
Sub-Systeme¶
Profile + Checks¶
Zweistufiges Modell. Hosts haben ein Profil (z. B. „APC Smart-UPS"). Profile haben Profile-Checks (z. B. „Battery Voltage"). host_services sind Instanzen pro Host mit optionalen Overrides.
Details: Profile & Checks.
Policies (v2)¶
Deklaratives Regelsystem für „auf diese Hosts diese Configs". JsonLogic-Subset, Form-Builder, AI-Generator. Macht Bulk-Konfiguration ohne SSH-Schlepperei.
Wiki + AI¶
Eigene Wissensbasis (Markdown, FTS, pgvector). AI greift via RAG ins Wiki, fällt auf Web-Suche zurück, kennzeichnet Quellen.
Auto-Discovery¶
Collector scannt Netzwerk per nmap. SNMP-sysOID matcht auf Profile. Bei Auto-Match wird das Profil als Vorschlag übernommen.
NSCA-Empfänger¶
Optionaler Receiver auf Port 5667. Nimmt Pakete von send_nsca-Clients an. Migrations-Pfad für Nagios-Bestände.
Performance-Modell¶
Auf Self-Hosting-Defaults (1 Worker, 256 MB shared_buffers): ~960 checks/s sustained, p95 ≤ 150 ms, 0 Errors über 30-Min-Soak. Skalierungs-Hebel: Administration → Skalierung.
Anschluss¶
- Status- und State-Modell — wie Check-Ergebnisse zu Status werden
- Profile & Checks — das wichtigste Konzept
- Glossar — wenn ein Begriff unklar ist