This commit is contained in:
@@ -1,22 +1,57 @@
|
||||
# SIEM Backend – Metadata-first Variante
|
||||
# SIEM Backend – Compact Metadata Variante
|
||||
|
||||
## Warum die Datenbank bisher wächst
|
||||
## Ursache des erneuten Datenbankwachstums
|
||||
|
||||
Die ursprüngliche Implementierung speichert jedes Windows-Event zweimal: als breite normalisierte Zeile in `event_logs` und zusätzlich als vollständiges XML in `event_log_raw`. Außerdem enthielt die Partitionswartung einen Tabellennamenfehler (`event_logs_raw` statt `event_log_raw`). Der Wartungslauf brach deshalb ab, bevor alte Partitionen gelöscht wurden. Auch `event_count_buckets` und `ueba_context_buckets` waren nicht partitioniert und konnten unbegrenzt wachsen.
|
||||
Die vorherige „Metadata-first“-Variante hatte noch einen entscheidenden Fehler: `insertBatch()` schrieb weiterhin **jedes einzelne Event** in `event_logs`. Zusätzlich war der Schlüssel von `event_occurrences` zu fein (u. a. Benutzer, IP, Workstation, Status und FailureReason), sodass diese Tabelle je nach Eventquelle fast wieder Event-Kardinalität erreichen konnte.
|
||||
|
||||
Bei 19,2 Mio. Events in zwei Tagen entspricht der Eingang im Mittel rund 9,6 Mio. Events/Tag bzw. 111 Events/Sekunde. Für eine MariaDB ist diese Eventrate als reine Aggregatlast unkritisch; problematisch war die Speicherung und spätere Abfrage nahezu jeder Einzelzeile.
|
||||
|
||||
## Neues Speichermodell
|
||||
|
||||
- `event_logs`: kurzlebige Hot-Daten für Regeln, die eine genaue Reihenfolge einzelner Events benötigen. Standard: 72 Stunden.
|
||||
- `event_occurrences`: langfristige Metadaten-Aggregate pro Zeit-Bucket, Host, Channel, Event-ID, Benutzer, IP und Workstation. Enthält `cnt`, `first_event_ts` und `last_event_ts`. Standard: 180 Tage.
|
||||
- `event_catalog`: kleine, dauerhafte Landkarte des ersten und letzten Auftretens jeder Event-ID pro Host und Channel.
|
||||
- `event_log_raw`: optionales Raw-XML. Standardmäßig deaktiviert; bei Aktivierung nur 24 Stunden Aufbewahrung.
|
||||
- `event_count_buckets` und `ueba_context_buckets`: jetzt partitioniert und automatisch bereinigt.
|
||||
- `event_count_buckets`: **universeller Primärspeicher für alle Events**. Eine Zeile pro 5-Minuten-Bucket, Host, Channel und Event-ID mit `cnt`, erstem und letztem Auftreten.
|
||||
- `event_catalog`: dauerhafte kleine Landkarte pro Host/Channel/Event-ID.
|
||||
- `event_occurrences`: nur noch **ausgewählte Security-Kontexte** (z. B. 4624, 4625, 4672, 4740). Benutzer/IP/Workstation werden nur dort gespeichert, wo sie für Detection/Forensik benötigt werden.
|
||||
- `event_logs`: Full-Event-Hotstore ist jetzt standardmäßig **aus** (`STORE_EVENT_ROWS=false`).
|
||||
- `event_log_raw`: Raw-XML ist standardmäßig **aus** (`STORE_RAW_XML=false`). Raw-XML impliziert technisch Full-Event-Zeilen und sollte nur für kurze gezielte Forensik aktiviert werden.
|
||||
|
||||
Für einen User-Lockout (typischerweise Security Event 4740) kann die Anwendung damit direkt beantworten: wann er zuerst/zuletzt im Bucket auftrat, auf welchem Host, für welchen Benutzer und wie oft. Das vollständige XML ist dafür nicht erforderlich. `CallerComputerName` wird dabei als Gerät/Workstation übernommen.
|
||||
Für einen Lockout (Security 4740) bleiben damit beispielsweise Event-ID, Host, Zielbenutzer, CallerComputer/Workstation, Anzahl sowie erstes/letztes Auftreten erhalten. Status-/Failure-Text, Source-IP und Subject-Machine-Account werden bei 4740 bewusst nicht zur Dimensionsbildung verwendet.
|
||||
|
||||
## Produktionskonfiguration
|
||||
|
||||
```env
|
||||
STORE_EVENT_ROWS=false
|
||||
STORE_RAW_XML=false
|
||||
METADATA_CONTEXT_EVENT_IDS=4624,4625,4648,4672,4720,4726,4728,4732,4740,4756,4768,4769,4771,4776
|
||||
BASELINE_WINDOW=5m
|
||||
METADATA_BUCKET=5m
|
||||
EVENT_RETENTION=6h
|
||||
RAW_RETENTION=6h
|
||||
METADATA_RETENTION=720h
|
||||
PARTITION_MAINTENANCE_ENABLED=true
|
||||
```
|
||||
|
||||
`EVENT_RETENTION` und `RAW_RETENTION` spielen im empfohlenen Modus keine Rolle, weil diese Tabellen nicht mehr beschrieben werden. Sie begrenzen lediglich die Datenmenge, falls Full-Event-/Raw-Speicherung bewusst aktiviert wird.
|
||||
|
||||
## UI und Detection
|
||||
|
||||
`/ui` liest die 24h-Eventzahl und die letzten Events jetzt ausschließlich aus `event_count_buckets`. Ungefilterte Eventseiten erhalten außerdem automatisch ein 24h-Zeitfenster. Damit berührt die Startseite weder `event_logs` noch die detaillierte Kontexttabelle.
|
||||
|
||||
Failed-Logon-Spikes und Reboot-Spikes verwenden die universellen Counter. Password-Spray, Success-after-Failures, neue Source-IP und UEBA verwenden die kompakte Security-Kontexttabelle. Dynamische Regeln auf `hostname`, `channel`, `event_id`, `target_user`, `subject_user`, `src_ip` und `workstation` funktionieren ohne Full-Event-Store. Regeln auf `msg` oder `process_name` benötigen weiterhin `STORE_EVENT_ROWS=true` und werden ansonsten bewusst übersprungen und geloggt.
|
||||
|
||||
## Bestehende Installation retten
|
||||
|
||||
1. Datenbank-Snapshot/Backup erstellen und Ingest kurz stoppen.
|
||||
2. Neues Backend deployen und sicherstellen, dass `STORE_EVENT_ROWS=false` sowie `STORE_RAW_XML=false` gesetzt sind.
|
||||
3. `deploy/mariadb/migrations/004-compact-storage.sql` ausführen.
|
||||
4. Backend starten und im Log die Zeile `storage mode: store_event_rows=false store_raw_xml=false ...` prüfen.
|
||||
5. Erst danach `deploy/mariadb/emergency-compact-cleanup.sql` ausführen. Das Script leert `event_logs`, `event_log_raw` und die alte hochkardinale `event_occurrences`-Historie. `event_count_buckets`, `event_catalog`, Detections und Baselines bleiben erhalten.
|
||||
6. Mit `deploy/mariadb/cardinality-diagnostics.sql` prüfen, wie viele reale Events eine Aggregatzeile repräsentiert.
|
||||
|
||||
Der Cleanup ist bewusst nicht Bestandteil der normalen Migration, da er historische Full-Event-/Kontextdaten löscht.
|
||||
|
||||
## Bevorzugtes Metadaten-Ingest
|
||||
|
||||
Bestehende Collector dürfen weiterhin `msg` mit XML senden. Neue oder angepasste Collector können stattdessen direkt ein `meta`-Objekt senden; dann muss das Backend das XML weder speichern noch parsen:
|
||||
Collector können weiterhin XML senden, besser ist aber das strukturierte `meta`-Objekt. Das Backend extrahiert daraus nur die für die jeweilige Event-ID benötigten Dimensionen.
|
||||
|
||||
```json
|
||||
[
|
||||
@@ -28,7 +63,6 @@ Bestehende Collector dürfen weiterhin `msg` mit XML senden. Neue oder angepasst
|
||||
"ts": "2026-07-18T12:34:56Z",
|
||||
"meta": {
|
||||
"target_user": "alice",
|
||||
"subject_user": "DC01$",
|
||||
"device": "CLIENT-42",
|
||||
"provider": "Microsoft-Windows-Security-Auditing"
|
||||
}
|
||||
@@ -36,38 +70,19 @@ Bestehende Collector dürfen weiterhin `msg` mit XML senden. Neue oder angepasst
|
||||
]
|
||||
```
|
||||
|
||||
Mindestens `msg` oder `meta` ist erforderlich. Für Regeln, die auf `msg`/Volltext prüfen, muss Raw-XML weiterhin vom Collector geliefert werden; im reinen Metadatenmodus sollten solche Regeln auf strukturierte Felder umgestellt werden.
|
||||
|
||||
## Wichtige Einstellungen
|
||||
|
||||
```env
|
||||
STORE_RAW_XML=false
|
||||
METADATA_BUCKET=1m
|
||||
EVENT_RETENTION=72h
|
||||
RAW_RETENTION=24h
|
||||
METADATA_RETENTION=4320h
|
||||
PARTITION_MAINTENANCE_ENABLED=true
|
||||
```
|
||||
|
||||
`METADATA_BUCKET=1m` ist ein guter Ausgangspunkt. Bei sehr hohen Raten kann auf `5m` erhöht werden; dadurch sinkt die Zeilenzahl weiter, die zeitliche Auflösung wird aber gröber.
|
||||
|
||||
## Bestehende Installation migrieren
|
||||
|
||||
1. Datenbank sichern und Ingest vorübergehend stoppen.
|
||||
2. `deploy/mariadb/migrations/002-metadata-first.sql` in einem Wartungsfenster ausführen. Das Script wärmt `event_catalog` aus den kleineren Baseline-Buckets vor, damit bekannte Event-IDs nicht als neu alarmiert werden. Die beiden `ALTER TABLE ... PARTITION BY`-Operationen können große Tabellen neu aufbauen und sperren.
|
||||
3. Neue Umgebungsvariablen aus `dot_env` übernehmen.
|
||||
4. Backend aktualisieren und starten.
|
||||
5. Im Log kontrollieren, dass `partition maintenance completed` erscheint. Die frühere Meldung zur nicht vorhandenen Tabelle `event_logs_raw` darf nicht mehr auftreten.
|
||||
6. Nach Ablauf von `EVENT_RETENTION` prüfen, ob alte `event_logs`-Partitionen verschwinden. Raw-XML kann nach erfolgreicher Validierung separat gelöscht oder durch die kurze `RAW_RETENTION` automatisch entfernt werden. `event_occurrences` wird nicht rückwirkend aus der alten Volltabelle aufgebaut; die langfristige Metadatenhistorie beginnt mit dem neuen Backend.
|
||||
|
||||
## Datenbankwahl
|
||||
|
||||
MariaDB bleibt für dieses Modell sinnvoll: Die Abfragen sind überwiegend zeitbasierte Filter, gruppierte Zähler und kleine relationale Dimensionen. Ein Wechsel zu ClickHouse oder OpenSearch lohnt sich erst, wenn trotz Aggregation sehr hohe Eventraten, ad-hoc Volltextsuchen oder jahrelange Rohdatenhaltung erforderlich sind. Für die hier beschriebene Metadatenanforderung wäre ein sofortiger Engine-Wechsel zusätzlicher Betriebsaufwand ohne zwingenden Nutzen.
|
||||
MariaDB bleibt für dieses Modell sinnvoll. Der entscheidende Punkt ist, dass die Datenbank nicht mehr als Roh-Event-Store verwendet wird. Die langfristige Last besteht nun überwiegend aus Upserts auf Zeit-Buckets und kleinen relationalen Dimensionen. Ein Wechsel zu ClickHouse wäre erst dann sinnvoll, wenn sehr große Rohdatenmengen oder breite Ad-hoc-Analysen ausdrücklich wieder Teil des Ziels werden.
|
||||
|
||||
---
|
||||
|
||||
# SIEM-lite Admin-Handbuch: Anlernphase, manuelle Bewertung und Lerneffekt
|
||||
|
||||
> **Architekturhinweis:** Das folgende ältere Handbuch enthält an einigen Stellen
|
||||
> noch SQL-/Tabellenbeispiele aus der Full-Event-Architektur. Für Speichermodell,
|
||||
> Performance und aktuelle Detection-Datenquellen ist ausschließlich der Abschnitt
|
||||
> „Compact Metadata Variante“ oben maßgeblich.
|
||||
|
||||
Stand: 2026-04-27
|
||||
Zielgruppe: Administratoren ohne SIEM-/SOC-Vorerfahrung
|
||||
Projekt: `siem-backend` / `SIEM-lite Security Operations`
|
||||
|
||||
Reference in New Issue
Block a user