Wazuh: Über 100 Millionen AWS-CloudTrail-Events verlustfrei importieren – Performance, Backpressure und Bulk-Indexierung

Einleitung

Die Integration von AWS CloudTrail in Wazuh ermöglicht es, Aktivitäten innerhalb einer AWS-Umgebung zentral zu überwachen, sicherheitsrelevante API-Aufrufe zu erkennen und Cloud-Ereignisse für spätere Untersuchungen verfügbar zu machen.

Während die kontinuierliche Verarbeitung neuer CloudTrail-Ereignisse in vielen Umgebungen problemlos funktioniert, stellt der nachträgliche Import großer historischer Datenmengen besondere Anforderungen an die Wazuh-Architektur.

Bereits ein einzelner AWS-Account in einer Region kann mehrere Millionen CloudTrail-Ereignisse pro Tag erzeugen. Sollen diese Ereignisse über mehrere Wochen vollständig in Wazuh verfügbar gemacht werden, entstehen schnell Datenbestände mit mehr als 100 Millionen Einträgen.

Dabei müssen zwei unterschiedliche Anforderungen berücksichtigt werden:

  • Vollständige Datenverfügbarkeit: Jedes CloudTrail-Ereignis muss für Audits, Compliance-Anforderungen und forensische Untersuchungen durchsuchbar bleiben.
  • Effiziente Sicherheitserkennung: Sicherheitsrelevante Ereignisse sollen durch die Wazuh-Regelengine analysiert werden, ohne dass die Verarbeitung großer Datenmengen zu überlaufenden Queues und verworfenen Events führt.

Dieser Artikel erläutert die technischen Ursachen von Performance-Engpässen beim CloudTrail-Backfill, zeigt konkrete Optimierungsmöglichkeiten für Wazuh 4.11 und stellt eine skalierbare Architektur für den verlustarmen beziehungsweise kontrolliert verlustfreien Import großer historischer Datenbestände vor.

1. Ausgangslage / Problemstellung

In der betrachteten Umgebung wird Wazuh 4.11.2 als Cluster mit zwei Manager-Nodes betrieben.

Die Infrastruktur besteht aus einem Master und einem Worker. AWS CloudTrail liefert die Ereignisdaten als komprimierte Dateien in einen S3-Bucket.

Ein eigenes Importskript lädt diese Dateien herunter, extrahiert die enthaltenen CloudTrail-Records und schreibt jeden Datensatz als einzelne JSON-Zeile in eine lokale Logdatei.

Wazuh liest diese Datei anschließend über eine <localfile>-Konfiguration ein.

Technische Rahmenbedingungen

KomponenteKonfiguration
Wazuh-Version4.11.2
Manager-Cluster2 Nodes (Master und Worker)
DatenquelleAWS CloudTrail über Amazon S3
Historischer ZeitraumCa. 30 Tage
Komprimiertes DatenvolumenCa. 50 GB
EreignisaufkommenCa. 3,4 Mio. Events pro Tag in einem Account/einer Region
GesamtdatenmengeÜber 100 Mio. Events
Beobachteter DurchsatzCa. 1.750 EPS pro Node
Verworfene EreignisseÜber 231.000, weiter steigend
Im Dashboard sichtbare AlertsCa. 2,1 Mio.

EPS steht für Events per Second und beschreibt die Anzahl der Ereignisse, die eine Komponente pro Sekunde verarbeitet.

Bestehende Logcollector-Konfiguration

Eine vereinfachte Konfiguration für das Einlesen der JSON-Dateien sieht folgendermaßen aus:

<localfile>
  <log_format>json</log_format>
  <location>/var/log/cloudtrail/import.json</location>
</localfile>

Das Importskript erzeugt dabei eine JSON-Zeile pro CloudTrail-Ereignis.

Ein wichtiger Unterschied zur standardmäßigen AWS-S3-Integration besteht darin, dass der Importprozess die S3-Dateien eigenständig verwaltet.

Hintergrund ist die Anforderung, auch verspätet eintreffende CloudTrail-Dateien zuverlässig zu erfassen. Ein ausschließlich auf Checkpoints basierender Import kann je nach Implementierung und Konfiguration problematisch sein, wenn ältere Objekte erst nachträglich im Bucket erscheinen.

Warum werden alle CloudTrail-Ereignisse zu Alerts?

Die CloudTrail-Ereignisse werden über die vorhandenen AWS-Regeln verarbeitet, insbesondere über die Regel-IDs 80200 und 80202.

Normalerweise begrenzen zusätzliche Bedingungen, beispielsweise die Lookup-Liste aws-eventnames, welche Ereignisse tatsächlich einen Alert erzeugen.

In der beschriebenen Umgebung wurde diese Einschränkung entfernt.

Das Ergebnis:

Jedes eingelesene CloudTrail-Ereignis durchläuft die Regelengine und erzeugt einen Alert.

Damit wird die Wazuh-Alert-Pipeline nicht mehr ausschließlich für Sicherheitserkennungen verwendet, sondern gleichzeitig als allgemeiner Datenspeicher für sämtliche CloudTrail-Ereignisse.

Diese Architekturentscheidung ist der zentrale Ausgangspunkt des Performance-Problems.

2. Technische Analyse

2.1 Wie CloudTrail-Ereignisse durch Wazuh verarbeitet werden

Beim dateibasierten Import durchlaufen die Ereignisse mehrere Komponenten.

AWS CloudTrail / S3

Komprimierte historische JSON-Dateien

Importskript + Logdatei

JSON Lines, ein Event pro Zeile

Wazuh Logcollector

Einlesen und Weitergabe an den Manager

Wazuh Analysis Engine (analysisd)

Event-Queue

JSON-Decoding

Rule-Matching

Alert-Erzeugung und Ausgabe-Queue

alerts.json → Filebeat → Wazuh Indexer

Indexierung in wazuh-alerts-*

Jede Stufe benötigt Rechenleistung, Speicher oder I/O-Kapazität.

Gerade CloudTrail-Ereignisse sind vergleichsweise aufwendig zu verarbeiten. Sie bestehen häufig aus umfangreichen, verschachtelten JSON-Strukturen mit variablen Feldern wie requestParameters und responseElements.

Zusätzlich können einzelne API-Aufrufe große Arrays oder umfangreiche Metadaten enthalten.

Wenn jedes dieser Ereignisse einen Alert erzeugt, entstehen mehrere potenzielle Engpässe.

2.2 Decoding als Performance-Limit

Die JSON-Decodierung muss die Ereignisstruktur interpretieren und die Felder für die nachgelagerte Regelverarbeitung bereitstellen.

Bei mehreren Millionen Events pro Tag kann dieser Schritt erhebliche CPU-Ressourcen beanspruchen.

Ein wichtiger Indikator ist:

event_queue_usage

Dieser Wert wird in der Statusdatei der Analysis Engine erfasst:

/var/ossec/var/run/wazuh-analysisd.state

Ein Wert nahe 1.0 zeigt an, dass die betreffende Queue nahezu vollständig ausgelastet ist.

Steigt gleichzeitig der Zähler events_dropped, kann die Pipeline die eingehenden Ereignisse nicht mehr zuverlässig aufnehmen.

2.3 Rule-Matching als weiterer Engpass

Nach der Decodierung werden die Ereignisse gegen die aktiven Wazuh-Regeln geprüft.

Die hierfür relevante Auslastung lässt sich unter anderem anhand von

rule_matching_queue_usage

beobachten.

Wie viele Events verarbeitet werden können, hängt unter anderem von folgenden Faktoren ab:

  • Anzahl und Komplexität der Regeln
  • Anzahl verfügbarer CPU-Kerne
  • Größe und Struktur der JSON-Ereignisse
  • Anzahl der Rule-Matching-Threads
  • Häufigkeit zusätzlicher Listenabfragen und Regelkorrelationen

Die beobachteten 1.500 bis 2.000 EPS pro Node sind unter diesen Bedingungen plausibel. Sie stellen jedoch weder eine allgemeine Wazuh-Leistungsgrenze noch einen garantierten Benchmark dar.

2.4 Alert-Ausgabe und Indexierung

Wenn jedes CloudTrail-Ereignis einen Alert erzeugt, muss Wazuh auch jeden dieser Alerts in die Ausgabe schreiben.

Der übliche Datenfluss lautet:

analysisd
   |
   v
alerts.json
   |
   v
Filebeat
   |
   v
Wazuh Indexer
   |
   v
wazuh-alerts-4.x-*

Die Auslastung der internen Alert-Queue wird über

alerts_queue_usage

beobachtet.

Dabei muss zwischen zwei Situationen unterschieden werden:

Situation A: Die Analysis Engine ist überlastet.

Die internen Queues laufen voll. Neue Ereignisse können nicht mehr aufgenommen werden und events_dropped steigt.

Situation B: Die Indexierung ist zu langsam.

Wazuh schreibt Alerts weiterhin in alerts.json, während Filebeat diese langsamer zum Indexer transportiert.

In diesem Fall kann sich ein Rückstand auf der Festplatte aufbauen.

Ein langsamer Indexer verursacht deshalb nicht automatisch events_dropped innerhalb von analysisd. Er kann allerdings zu wachsenden Logdateien, hohem Speicherplatzbedarf und weiteren Betriebsproblemen führen.

Beide Situationen müssen getrennt überwacht werden.

2.5 Warum ein zweiter Manager nicht automatisch den Durchsatz verdoppelt

Ein Wazuh-Cluster verteilt lokal eingelesene Dateien nicht automatisch zwischen Master und Worker.

Wird das Importskript ausschließlich auf dem Master ausgeführt und liest nur dessen Logcollector die erzeugte Datei, verarbeitet der Worker diese Daten nicht.

Die zusätzliche Manager-Kapazität bleibt damit für diesen Import ungenutzt.

Für eine horizontale Verteilung müssen die CloudTrail-Dateien beziehungsweise Ereignisse gezielt auf beide Nodes aufgeteilt werden.

Bei vergleichbarer Hardware und ähnlicher Auslastung kann das den Gesamtdurchsatz deutlich erhöhen.

Die Skalierung bleibt jedoch abhängig von gemeinsam genutzten Komponenten wie Indexer, Storage und Netzwerk.

3. Lösung / Best Practices

Für große historische CloudTrail-Datenbestände empfiehlt sich eine Trennung zwischen vollständiger Archivierung und sicherheitsrelevanter Regelverarbeitung.

3.1 Empfohlene Architektur: Archivdaten und Security Alerts trennen

Die effizienteste Architektur besteht aus zwei getrennten Verarbeitungspfaden.

AWS CloudTrail in S3

Historische CloudTrail-Dateien

Import- und Validierungsschicht

Deduplizierung, Vollständigkeitsprüfung, Normalisierung

Archiv-Pipeline

Bulk API

wazuh-archives-*

Vollständige Suchhistorie

Security-Pipeline

Wazuh analysisd

wazuh-alerts-*

Regelbasierte Alerts

Diese Trennung bietet mehrere Vorteile:

  1. Sämtliche historischen Ereignisse bleiben im Archiv durchsuchbar.
  2. Die Wazuh-Regelengine muss nicht jedes unkritische Ereignis verarbeiten.
  3. Das Alert-Volumen sinkt erheblich.
  4. Die Indexierung kann unabhängig von der Analysis Engine skaliert werden.
  5. Sicherheitsdashboards enthalten weiterhin echte regelbasierte Alerts.

Wichtig ist allerdings: Eine direkte Bulk-Indexierung ersetzt keine historische Regelauswertung.

Falls sämtliche Ereignisse nachträglich durch Wazuh-Regeln analysiert werden müssen, ist eine separate, kontrollierte Replay-Pipeline erforderlich.

3.2 Historische CloudTrail-Daten über die Bulk API importieren

Für die vollständige Archivierung können die CloudTrail-Ereignisse direkt in den Wazuh Indexer geschrieben werden.

Dafür eignet sich die Bulk API des zugrunde liegenden OpenSearch-Indexers.

Als Ziel können beispielsweise folgende Indizes verwendet werden:

wazuh-archives-4.x-2026.10.01
wazuh-archives-4.x-2026.10.02
wazuh-archives-4.x-2026.10.03

Die Datumsangaben sind Beispiele. Für historische Daten sollte eine konsistente Zuordnung anhand des CloudTrail-Ereigniszeitpunkts erfolgen.

Die vorhandene Wazuh-Indexvorlage kann sowohl für Alert- als auch für Archive-Indizes relevante Mappings bereitstellen. Vor dem Import muss allerdings geprüft werden, welche Templates tatsächlich im Ziel-Indexer installiert sind und welche Indexmuster sie abdecken.

Dokumentstruktur für den Archivimport

Ein vereinfachtes archiviertes Ereignis könnte folgendermaßen aussehen:

{
  "timestamp": "2026-10-01T12:30:00Z",
  "agent": {
    "id": "000",
    "name": "wazuh-manager"
  },
  "manager": {
    "name": "wazuh-manager"
  },
  "decoder": {
    "name": "json"
  },
  "location": "s3://cloudtrail-bucket/example.json.gz",
  "data": {
    "aws": {
      "source": "cloudtrail",
      "eventName": "DescribeInstances",
      "eventSource": "ec2.amazonaws.com",
      "awsRegion": "eu-central-1",
      "eventID": "example-event-id"
    }
  }
}

Die Felder agent, manager, decoder und location dienen dabei der Kompatibilität mit der Wazuh-Datenstruktur.

Der Inhalt unter data.aws repräsentiert das ursprüngliche CloudTrail-Ereignis. Im produktiven Import sollte der vollständige Datensatz erhalten bleiben.

Das Feld timestamp wird aus eventTime übernommen und in ein für den Indexer geeignetes Datumsformat gebracht.

Die konkrete Struktur sollte mit echten, durch Wazuh erzeugten Archivdokumenten verglichen werden. Besonders wichtig ist die Übereinstimmung von Feldtypen und Feldnamen.

Beispiel für eine Bulk-Anfrage

Die Bulk API verwendet das NDJSON-Format. Jede Indexoperation besteht aus einer Metadatenzeile und einer Dokumentzeile.

{"index":{"_index":"wazuh-archives-4.x-2026.10.01"}}
{"timestamp":"2026-10-01T12:30:00Z","data":{"aws":{"source":"cloudtrail","eventName":"DescribeInstances"}}}
{"index":{"_index":"wazuh-archives-4.x-2026.10.01"}}
{"timestamp":"2026-10-01T12:30:01Z","data":{"aws":{"source":"cloudtrail","eventName":"ListBuckets"}}}

Die vollständige Dokumentstruktur wurde hier aus Gründen der Übersichtlichkeit verkürzt.

Die Daten können beispielsweise über folgenden Aufruf übertragen werden:

curl --fail-with-body \
  --cacert /etc/wazuh-indexer/certs/root-ca.pem \
  -u "$INDEXER_USER:$INDEXER_PASSWORD" \
  -H "Content-Type: application/x-ndjson" \
  --data-binary @cloudtrail-bulk.ndjson \
  "https://INDEXER_HOST:9200/_bulk"

Der Pfad zum CA-Zertifikat und die Zugangsdaten müssen an die eigene Umgebung angepasst werden.

Für produktive Imports sollte der Bulk-Prozess zusätzlich:

  • Kleine bis mittelgroße Batches statt einer einzigen riesigen Anfrage verwenden.
  • Die Antwort jeder Bulk-Anfrage auf errors und einzelne fehlgeschlagene Operationen prüfen.
  • Temporäre Fehler mit begrenzten Wiederholungsversuchen und Backoff behandeln.
  • Bereits erfolgreich importierte Ereignisse bei einem Neustart nicht erneut duplizieren.
  • Fortschritt und Fehler dauerhaft protokollieren.

Eine HTTP-200-Antwort allein bedeutet bei der Bulk API nicht, dass sämtliche Dokumente erfolgreich indexiert wurden.

Deduplizierung über CloudTrail-Event-IDs

Für einen wiederholbaren Import kann aus CloudTrail-Metadaten eine deterministische Dokument-ID erzeugt werden.

Beispielsweise:

AWS-Account-ID + Region + CloudTrail-eventID

Bei geeigneter Identitätsstrategie lassen sich wiederholte Imports idempotent gestalten.

Die gewählte ID muss die tatsächliche Eindeutigkeit innerhalb des Datenbestands gewährleisten. Bei mehreren Accounts und Regionen sollte deshalb nicht ausschließlich die eventID ohne zusätzlichen Kontext verwendet werden.

3.3 Mapping-Konflikte bei CloudTrail vermeiden

CloudTrail-Ereignisse enthalten zahlreiche dynamische JSON-Felder.

Besonders kritisch sind:

requestParameters
responseElements
additionalEventData

Diese Felder können abhängig vom jeweiligen AWS-Service unterschiedliche Strukturen besitzen.

Beispielsweise kann ein Feld bei einem Ereignis ein Objekt enthalten und bei einem anderen Ereignis einen einfachen String oder null.

Bei der Indexierung können dadurch Mapping-Konflikte entstehen.

Zusätzlich kann die Anzahl dynamischer Felder die konfigurierte Grenze für Index-Mappings überschreiten.

Ein häufig relevanter Parameter ist:

index.mapping.total_fields.limit

Die konkrete Grenze hängt vom eingesetzten Template und der Indexkonfiguration ab.

Eine mögliche Lösung besteht darin, besonders dynamische JSON-Bereiche mit einem geeigneten OpenSearch-Feldtyp wie flat_object abzubilden, sofern die eingesetzte Indexer-Version diesen unterstützt.

Alternativ können solche Bereiche als serialisierte JSON-Strings gespeichert werden.

Dabei ist zu beachten, dass sich die Suchmöglichkeiten unterscheiden: Ein serialisierter JSON-String bietet nicht dieselben strukturierten Feldabfragen wie ein vollständig indexiertes JSON-Objekt.

Eine Mapping-Anpassung sollte deshalb vor dem Bulk-Import in einer Testumgebung validiert werden.

3.4 Bulk-Indexierung temporär beschleunigen

Während eines kontrollierten historischen Imports kann die Indexer-Konfiguration vorübergehend angepasst werden.

Beispielsweise:

{
  "index": {
    "refresh_interval": "-1",
    "number_of_replicas": 0
  }
}

Die Einstellung refresh_interval: -1 deaktiviert die automatische Aktualisierung der Suchsicht während des Imports.

Dadurch kann der Indexer größere Datenmengen effizienter verarbeiten.

number_of_replicas: 0 deaktiviert zusätzliche Replikate und reduziert den Schreibaufwand.

Achtung: Ohne Replikate besteht während des Imports keine zusätzliche Redundanz auf Indexebene. Ein Node-Ausfall kann dadurch erhebliche Auswirkungen haben.

Diese Einstellung sollte nur verwendet werden, wenn die Quelldaten zuverlässig erhalten bleiben und ein erneuter Import möglich ist.

Nach Abschluss des Imports müssen die ursprünglichen Einstellungen wiederhergestellt und der Zustand der Indizes überprüft werden.

3.5 Nur sicherheitsrelevante Ereignisse durch Wazuh analysieren

Für den Security-Pfad sollte die zuvor entfernte Filterlogik wiederhergestellt werden.

Dazu gehört beispielsweise die Verwendung der AWS-Eventnamen-Liste:

aws-eventnames

Alternativ kann eine eigene, dokumentierte Auswahl sicherheitsrelevanter CloudTrail-Ereignisse implementiert werden.

Typische Kandidaten sind:

  • ConsoleLogin
  • CreateAccessKey
  • DeleteTrail
  • StopLogging
  • PutBucketPolicy
  • AttachUserPolicy
  • AuthorizeSecurityGroupIngress

Diese Auswahl ist nicht abschließend. Welche Ereignisse sicherheitsrelevant sind, hängt vom Bedrohungsmodell und den eingesetzten AWS-Services ab.

Wichtig ist außerdem, dass eine reine Eventnamen-Filterung nicht sämtliche verdächtigen Aktivitäten erkennt. Viele Angriffe bestehen aus einer Kombination zunächst unauffälliger API-Aufrufe.

Deshalb sollten die vorhandenen Wazuh-Regeln und ihre Abhängigkeiten geprüft werden, bevor Filterbedingungen verändert werden.

Die so erzeugten Security Alerts werden regulär in

wazuh-alerts-4.x-*

indexiert.

Historische Rohereignisse verbleiben dagegen in

wazuh-archives-4.x-*

Es sollten keine künstlichen rule.*-Felder hinzugefügt werden, nur damit archivierte Ereignisse wie reguläre Wazuh-Alerts erscheinen.

Das würde die fachliche Aussagekraft der Alert-Daten beeinträchtigen und könnte Auswertungen verfälschen.

3.6 Alternative: Vollständige Verarbeitung über analysisd

Nicht jede Umgebung kann historische CloudTrail-Daten direkt in den Indexer importieren.

Wenn sämtliche Ereignisse tatsächlich durch die Wazuh-Regelengine laufen müssen, kann die bestehende Architektur weiterverwendet werden.

Entscheidend ist dann, den Eingangsdurchsatz kontrolliert unterhalb der dauerhaft verfügbaren Verarbeitungskapazität zu halten.

Analysisd-Queues vergrößern

Die interne Konfiguration kann über folgende Datei angepasst werden:

/var/ossec/etc/local_internal_options.conf

Beispielwerte für eine entsprechend dimensionierte Umgebung:

analysisd.decode_event_queue_size=262144
analysisd.decode_output_queue_size=262144
analysisd.alerts_queue_size=262144

Die Standardwerte und zulässigen Maximalwerte sollten für die tatsächlich eingesetzte Wazuh-Version anhand der Dokumentation und der mitgelieferten Konfiguration überprüft werden.

Größere Queues helfen insbesondere bei kurzfristigen Lastspitzen.

Sie lösen jedoch keinen dauerhaft bestehenden Performance-Engpass.

Wenn beispielsweise kontinuierlich 2.500 EPS eintreffen, der Manager aber nur 1.750 EPS verarbeiten kann, wächst die Warteschlange dauerhaft.

Irgendwann ist auch eine deutlich größere Queue vollständig gefüllt.

Darüber hinaus benötigen größere Queues zusätzlichen Arbeitsspeicher.

Thread-Konfiguration prüfen

Für die Analysis Engine sind unter anderem folgende Parameter relevant:

analysisd.event_threads=0
analysisd.rule_matching_threads=0

Der Wert 0 steht bei diesen Optionen für die automatische Thread-Auswahl.

Eine explizite Konfiguration kann beispielsweise so aussehen:

analysisd.event_threads=8
analysisd.rule_matching_threads=8

Dies sind ausschließlich Beispielwerte für einen Server mit ausreichenden CPU-Ressourcen.

Eine Erhöhung der Thread-Anzahl verbessert den Durchsatz nicht zwangsläufig. Abhängig von CPU-Auslastung, Speicherbandbreite und Synchronisationsaufwand kann eine zu hohe Thread-Anzahl sogar kontraproduktiv sein.

Änderungen sollten daher einzeln vorgenommen und unter reproduzierbarer Last getestet werden.

Nach Änderungen an den internen Optionen ist ein Neustart des Wazuh Managers erforderlich.

3.7 Logcollector-Queue ebenfalls berücksichtigen

Neben den Queues der Analysis Engine besitzt auch der Wazuh Logcollector einen internen Ausgabepuffer.

Ein relevanter Parameter lautet:

logcollector.queue_size=1024

Der Wert 1024 ist hier ein Beispiel, nicht die Empfehlung für jede Umgebung.

Für größere Importlasten kann eine deutliche Erhöhung sinnvoll sein, etwa auf:

logcollector.queue_size=10240

Damit wird die Queue gegenüber dem Beispielwert um den Faktor zehn vergrößert.

Die unterstützte Größenordnung liegt für diese Option bei 128 bis 220.000 Einträgen; die konkrete Unterstützung sollte für die eingesetzte Version geprüft werden.

Auch diese Maßnahme verbessert primär die Pufferfähigkeit und nicht automatisch den dauerhaft möglichen Durchsatz.

Bei einer kontinuierlichen Überlastung muss die Eingangsrate weiterhin reduziert werden.

3.8 EPS-Limits sind keine Garantie für verlustfreie Verarbeitung

Wazuh bietet im globalen Konfigurationsbereich Möglichkeiten zur Begrenzung der Ereignisverarbeitung.

Ein Beispiel für die entsprechende Struktur:

<global>
  <limits>
    <eps>
      <maximum>1500</maximum>
      <timeframe>1</timeframe>
    </eps>
  </limits>
</global>

Diese Einstellung begrenzt die Verarbeitungskapazität entsprechend der konfigurierten Werte.

Sie sollte jedoch nicht mit einem Mechanismus zur garantierten verlustfreien Flusskontrolle verwechselt werden.

Wenn weiterhin mehr Ereignisse eintreffen, als verarbeitet werden dürfen, können sich die Queues füllen.

Sind sie vollständig ausgelastet, können Ereignisse verworfen werden.

Ein EPS-Limit schützt somit vor unkontrollierter Verarbeitungslast, ersetzt aber keine Backpressure zwischen Importskript und Wazuh.

3.9 Importskript mit pv drosseln

Für einen dateibasierten Backfill ist eine kontrollierte Schreibgeschwindigkeit häufig die einfachste Lösung.

Dafür kann das Linux-Werkzeug pv verwendet werden.

Installation unter Debian oder Ubuntu:

sudo apt install pv

Installation auf RPM-basierten Systemen, sofern das Paket in den aktivierten Repositories verfügbar ist:

sudo dnf install pv

Anschließend kann die Ausgabe des Importskripts begrenzt werden:

python3 cloudtrail_import.py \
  | pv --line-mode --rate-limit 500 \
  >> /var/log/cloudtrail/import.json

Die Option --line-mode sorgt dafür, dass die Rate auf Zeilen statt auf Bytes bezogen wird.

Mit --rate-limit 500 wird die Ausgabe auf ungefähr 500 Zeilen pro Sekunde begrenzt.

Wenn jede Zeile genau einem CloudTrail-Ereignis entspricht, entspricht dies ungefähr 500 EPS.

Der Wert liegt deutlich unter dem beobachteten Durchsatz von rund 1.750 EPS pro Node und bietet damit eine größere Sicherheitsreserve.

Die tatsächlich geeignete Rate muss anhand der Auslastung und der beobachteten Drop-Zähler bestimmt werden.

Wichtig: Eine begrenzte Schreibrate ist allein noch kein Beweis für verlustfreie Verarbeitung. Auch Logrotation, Dateihandhabung, Prozessabstürze und die tatsächliche Übernahme durch Wazuh müssen berücksichtigt werden.

3.10 Dynamische Drosselung anhand der Queue-Auslastung

Statt einer festen Schreibrate kann das Importskript die Auslastung der Analysis Engine regelmäßig auswerten.

Dafür eignet sich die Datei:

/var/ossec/var/run/wazuh-analysisd.state

Ein vereinfachtes Python-Beispiel:

import timeSTATE = "/var/ossec/var/run/wazuh-analysisd.state"def read_state():    values = {}    with open(STATE, encoding="utf-8") as state_file:        for line in state_file:            if "=" not in line or line.startswith("#"):                continue            key, value = line.strip().split("=", 1)            values[key] = value.strip().strip("'\"")    return valuesdef wait_for_capacity():    queues = (        "event_queue_usage",        "rule_matching_queue_usage",        "alerts_queue_usage",    )    while True:        state = read_state()        usages = [            float(state[key])            for key in queues            if key in state        ]        if not usages:            raise RuntimeError(

Die Funktion wait_for_capacity() kann vor dem Schreiben weiterer Ereignis-Batches aufgerufen werden.

Sobald eine überwachte Queue eine Auslastung von mindestens 70 Prozent erreicht, wartet das Skript.

Dabei handelt es sich um ein vereinfachtes Steuerungsverfahren, nicht um eine vollständig implementierte, verlustfreie Backpressure-Lösung.

Für einen produktiven Import sollten zusätzlich folgende Bedingungen erfüllt sein:

  • Ein dauerhaft gespeicherter Import-Checkpoint wird erst nach bestätigter Verarbeitung fortgeschrieben.
  • Fehler beim Lesen der Statusdatei führen nicht dazu, dass unkontrolliert weitergeschrieben wird.
  • events_dropped wird kontinuierlich auf neue Verluste geprüft.
  • Das Skript begrenzt zusätzlich seine maximale Schreibrate.
  • Nach einem Neustart können noch nicht bestätigte Batches erneut verarbeitet werden.

Die Statusdatei wird in der betrachteten Konfiguration standardmäßig in einem Intervall von ungefähr fünf Sekunden aktualisiert.

Daher eignet sich diese Methode eher für eine grobe adaptive Drosselung als für eine millisekundengenaue Regelung.

3.11 CloudTrail-Import auf mehrere Manager verteilen

Soll der vollständige Backfill über die Wazuh-Regelengine laufen, kann eine Aufteilung zwischen Master und Worker sinnvoll sein.

Beispielsweise:

S3 CloudTrail History
        |
        v
  Import Controller
        |
        +-------------------+
        |                   |
        v                   v
  Manager Master       Manager Worker
        |                   |
        v                   v
  Logcollector          Logcollector
        |                   |
        v                   v
    analysisd             analysisd
        |                   |
        +---------+---------+
                  |
                  v
             Wazuh Indexer

Die Verteilung kann beispielsweise anhand von S3-Objektschlüsseln oder deterministischen Hashwerten erfolgen.

Dabei muss sichergestellt werden, dass jedes CloudTrail-Ereignis genau einmal einem Import-Worker zugeordnet wird oder dass Wiederholungen durch Deduplizierung abgefangen werden.

Bei zwei Nodes mit jeweils 1.750 EPS ergibt sich rechnerisch ein maximaler kombinierter Durchsatz von 3.500 EPS.

Dieser Wert gilt allerdings nur, wenn beide Nodes die entsprechende Leistung tatsächlich gleichzeitig erreichen und keine gemeinsame Komponente zum Engpass wird.

3.12 Wie lange dauert ein Backfill von 100 Millionen Events?

Die reine Verarbeitungszeit lässt sich näherungsweise berechnen:

\[ t = \frac{\text{Anzahl Events}}{\text{Events pro Sekunde}} \]

Geschätzte Laufzeit für 100 Millionen Events

1 Node bei 500 EPS

55,6 Std.

1 Node bei 1.400 EPS

19,8 Std.

1 Node bei 1.750 EPS

15,9 Std.

2 Nodes bei je 1.750 EPS

7,9 Std.

Idealisierte Berechnung ohne Import-Overhead, Unterbrechungen, Indexer-Engpässe oder Nachverarbeitung.

Die Zahlen verdeutlichen, dass ein langsamer, kontrollierter Import durchaus praktikabel sein kann.

Für einen produktiven Backfill sollte allerdings zusätzliche Zeit für Validierung, Wiederholungsversuche und eventuelle Performance-Schwankungen eingeplant werden.

4. Lessons Learned / Best Practices

4.1 Vollständigkeit nicht anhand der Alert-Anzahl beurteilen

Eine wichtige Erkenntnis ist, dass die Anzahl der Alerts im Dashboard nicht zwangsläufig der Anzahl der eingelesenen CloudTrail-Ereignisse entspricht.

Dies gilt insbesondere dann, wenn Ereignisse bewusst gefiltert werden oder die Archivierung getrennt von der Regelauswertung erfolgt.

Für einen vollständigen historischen Import sollte deshalb eine unabhängige Vollständigkeitsprüfung implementiert werden.

Geeignete Kontrollgrößen sind:

KontrollgrößeZweck
S3-ObjekteVollständigkeit der Quelldateien
CloudTrail-RecordsTatsächliche Anzahl der Ereignisse
Erfolgreiche Bulk-OperationenBestätigung der Indexierung
Fehlgeschlagene DokumenteErkennung von Mapping- und Importfehlern
Eindeutige Event-IDsKontrolle auf Duplikate
events_droppedErkennung von Verlusten in analysisd
Indexierte DokumenteKontrolle der gespeicherten Daten

Für die Vollständigkeitsprüfung sollte pro Import-Batch eine Bilanz erstellt werden.

Ein erfolgreicher Import liegt erst dann vor, wenn alle erwarteten Ereignisse entweder nachweislich indexiert wurden oder in einer kontrollierten Fehlerliste zur erneuten Verarbeitung stehen.

4.2 Backpressure muss vor der überlasteten Komponente greifen

Die Vergrößerung von Queues kann kurzfristige Lastspitzen abfangen.

Für eine dauerhaft stabile Verarbeitung ist jedoch entscheidend, dass die Datenquelle nicht schneller liefert, als die nachgelagerte Pipeline verarbeiten kann.

Daraus ergibt sich eine wichtige Betriebsregel:

Nicht die maximale Schreibrate des Importskripts bestimmt den Durchsatz, sondern die dauerhaft verfügbare Verarbeitungskapazität der langsamsten Komponente.

Für kontrollierte Backfills empfiehlt sich deshalb eine Kombination aus fester Ratenbegrenzung, Queue-Monitoring und persistenter Fortschrittsverwaltung.

4.3 Agent- und Manager-seitige Verarbeitung unterscheiden

Bei der Wahl der Drosselungsmechanismen muss berücksichtigt werden, wo das Importskript ausgeführt wird.

Läuft es direkt auf dem Wazuh Manager, gelten andere Bedingungen als bei der Übertragung über einen Wazuh Agent.

Agents verfügen über einen eigenen Anti-Flooding-Mechanismus und eine konfigurierbare Ereignispufferung.

Ein Beispiel ist:

<client_buffer>
  <disabled>no</disabled>
  <queue_size>5000</queue_size>
  <events_per_second>500</events_per_second>
</client_buffer>

Diese Konfiguration betrifft die Agent-seitige Ereignisübertragung und ist kein allgemeiner Drosselungsmechanismus für lokal auf dem Manager eingelesene Dateien.

Bei einem Import direkt auf dem Manager sollte die Geschwindigkeit deshalb bereits im Importskript begrenzt werden.

4.4 CloudTrail-Rohdaten für forensische Untersuchungen erhalten

CloudTrail-Daten sind nicht nur für die unmittelbare Angriffserkennung relevant.

Sie werden häufig auch benötigt, um nach einem Sicherheitsvorfall Aktivitäten über längere Zeiträume nachzuvollziehen.

Deshalb sollten folgende Informationen erhalten bleiben:

  • Ursprünglicher Ereigniszeitpunkt (eventTime)
  • AWS-Account und Region
  • Ereignis-ID (eventID)
  • API-Aufruf und AWS-Service
  • Aufrufende Identität (userIdentity)
  • Quell-IP-Adresse (sourceIPAddress)
  • Anfrage- und Antwortparameter
  • Referenz auf die ursprüngliche S3-Datei

Für revisionssichere Anforderungen sollte zusätzlich die Integrität der Originaldaten berücksichtigt werden.

Die Indexierung in Wazuh ersetzt nicht automatisch eine unveränderbare Archivierung, beispielsweise über geeignete S3-Retention- und Integritätsmechanismen.

4.5 Monitoring und Kapazitätsplanung etablieren

Für wiederkehrende CloudTrail-Imports sollten mindestens folgende Komponenten überwacht werden:

Wazuh Manager

  • CPU- und RAM-Auslastung
  • event_queue_usage
  • rule_matching_queue_usage
  • alerts_queue_usage
  • events_dropped
  • Logcollector-Queue und Importfortschritt

Filebeat und Indexer

  • Filebeat-Ausgaberückstand und Übertragungsfehler
  • Indexierungsrate und Bulk-Fehler
  • CPU-, RAM- und Storage-Auslastung
  • Index- und Shard-Größen
  • Clusterzustand
  • Verfügbarer Speicherplatz

Importprozess

  • Verarbeitete S3-Dateien
  • Erfolgreich gelesene CloudTrail-Records
  • Importierte und fehlgeschlagene Dokumente
  • Wiederholungsversuche
  • Letzter bestätigter Checkpoint
  • Zeit seit dem letzten erfolgreichen Import

Gerade bei großen historischen Datenmengen ist eine Kombination aus technischen Performance-Metriken und fachlichen Vollständigkeitskontrollen erforderlich.

4.6 Versionsunterschiede berücksichtigen

Die beschriebenen Maßnahmen beziehen sich auf Wazuh 4.11.2.

Die grundlegenden Konzepte der Queue-Überwachung, der kontrollierten Ereigniszufuhr und der getrennten Archivindexierung sind auch für neuere Wazuh-Versionen relevant.

Allerdings können sich interne Konfigurationsparameter, Standardwerte und Index-Templates zwischen Versionen ändern.

Insbesondere beim Einsatz von Wazuh 4.14 oder neuer sollten sämtliche Parameter und Mapping-Anpassungen vor einer produktiven Übernahme erneut geprüft werden.

5. Fazit

Der Import von mehr als 100 Millionen AWS-CloudTrail-Ereignissen ist grundsätzlich auch mit Wazuh möglich. Entscheidend ist jedoch, welche Aufgaben die einzelnen Komponenten übernehmen sollen.

Wenn jedes CloudTrail-Ereignis durch die Wazuh-Regelengine verarbeitet und als Alert gespeichert wird, entstehen erhebliche Anforderungen an Decoding, Rule-Matching und Alert-Ausgabe.

Größere Queues und zusätzliche Threads können die Verarbeitung stabilisieren, beseitigen aber keine dauerhaft bestehende Überlastung.

Für große historische Datenbestände ist deshalb eine zweigeteilte Architektur besonders sinnvoll:

Vollständige CloudTrail-Historie: Direkte, kontrollierte Bulk-Indexierung in wazuh-archives-*, mit konsistenten Mappings, Deduplizierung und überprüfbarer Vollständigkeit.

Sicherheitsrelevante CloudTrail-Ereignisse: Reguläre Verarbeitung durch die Wazuh-Regelengine und Speicherung in wazuh-alerts-*.

Falls eine vollständige historische Regelauswertung erforderlich ist, sollte stattdessen eine kontrollierte Replay-Pipeline mit Rate-Limiting, Queue-Monitoring und wiederaufnehmbaren Import-Batches verwendet werden.

Die wichtigste Erkenntnis lautet:

Ein erfolgreicher CloudTrail-Backfill wird nicht an der maximalen EPS-Zahl gemessen, sondern daran, ob alle benötigten Ereignisse vollständig, nachvollziehbar und ohne unbemerkten Datenverlust verfügbar gemacht werden.

6. Quellen und weiterführende Dokumentation

Die folgenden Referenzen beziehen sich auf Wazuh 4.11 und die im Artikel beschriebenen Komponenten.

Wazuh – Analysis Engine Statistics

Beschreibung der Statusdatei wazuh-analysisd.state und der Metriken zur Überwachung der internen Verarbeitung.

https://documentation.wazuh.com/4.11/user-manual/reference/statistics-files/wazuh-analysisd-state.html

Wazuh – Internal Configuration

Referenz der internen Konfigurationsparameter, einschließlich Queue-Größen und Thread-Einstellungen.

https://documentation.wazuh.com/4.11/user-manual/reference/internal-options.html

Wazuh – Event Logging

Dokumentation der Ereignisprotokollierung und der Unterscheidung zwischen Alerts und archivierten Ereignissen.

https://documentation.wazuh.com/4.11/user-manual/manager/event-logging.html

Wazuh – Global Configuration

Referenz für globale Manager-Einstellungen und EPS-Begrenzungen.

https://documentation.wazuh.com/4.11/user-manual/reference/ossec-conf/global.html

Wazuh 4.11.2 – Index Template

Indexvorlage zur Prüfung der Feldzuordnungen und Indexmuster für Alerts und Archive.

https://github.com/wazuh/wazuh/blob/v4.11.2/extensions/elasticsearch/7.x/wazuh-template.json

OpenSearch – Bulk API

Technische Dokumentation für die performante Indexierung größerer Datenmengen.

https://docs.opensearch.org/latest/api-reference/document-apis/bulk

OpenSearch – Flat Object

Dokumentation des Feldtyps flat_object für dynamische JSON-Strukturen.

https://docs.opensearch.org/latest/mappings/supported-field-types/flat-object

Mehr zu Wazuh …

Mehr zum Wazuh Ambassador Program …

https://wazuh.slack.com/archives/C0A933R8E/p1792257248573269