Wazuh Dashboard zeigt „No data“, obwohl Indizes gefüllt sind: TLS-Zertifikatskette, mTLS-Policy und Saved Objects als Root Cause (Wazuh 4.14.1)

Einleitung

Wenn Wazuh Dashboard in Modulen wie Threat Hunting, Vulnerabilities und Inventory „No data“ anzeigt, obwohl die zugehörigen wazuh-states-*-Indizes im Indexer nachweislich Dokumente enthalten, liegt das Problem fast nie an der Datenerhebung. In der Praxis sind es typischerweise Kommunikations- und Integrationsprobleme zwischen Dashboard ↔ Indexer (OpenSearch) und Dashboard ↔ Wazuh API – besonders häufig im Kontext von TLS-Zertifikaten, Zertifikatsketten und ClientAuth/mTLS. Dieser Beitrag verdichtet den Fall zu einer belastbaren Troubleshooting- und Fix-Strategie.


Ausgangslage / Problemstellung

Umgebung (wie im Thread):

  • Installation: All-in-One
  • Wazuh Dashboard: 4.14.1
  • Wazuh Indexer (OpenSearch-basiert): 7.10.2
  • Single-Node-Cluster, Cluster-Health GREEN, Shards aktiv
  • Dashboard per HTTPS auf Port 443 erreichbar
  • Indizes existieren und sind gefüllt, z. B.
    • wazuh-states-vulnerabilities-<node> (Tausende Dokumente)
    • wazuh-states-inventory-packages-<node> (Tausende Dokumente)
  • Nicht funktional im UI: Threat Hunting, Vulnerabilities, Inventory → „No data“
  • Zusätzlich: Saved Objects (Searches/Visualizations/Dashboards) sind leer (API _find liefert total: 0)

Zentraler Hinweis aus den Logs und Tests:

  • Dashboard-Logs zeigen wiederholt TLS-Fehler wie ERR_SSL_SSLV3_ALERT_CERTIFICATE_UNKNOWN
  • openssl s_client vom Dashboard-Host zum Indexer meldet u. a.:
    • unable to get local issuer certificate
    • unable to verify the first certificate

Damit ist die entscheidende Aussage: Daten sind da, aber Dashboard kann sie nicht zuverlässig „konsumieren“ (TLS-Handshake/Trust bricht).


Technische Analyse

1) Warum „Indices haben Daten“ und „Dashboard zeigt No data“ gleichzeitig möglich ist

Direkte OpenSearch-API-Queries (curl -k ... https://localhost:9200/<index>/_count) belegen lediglich:

  • Indexer läuft
  • Indizes existieren
  • Daten können abgefragt werden – für genau diesen Client/Request-Pfad

Das Dashboard hingegen nutzt einen eigenen TLS-Client (Node/OpenSearch-Dashboards Runtime) und zusätzlich plugin-spezifische Requests. Wenn dort Trust/CA-Kette oder ClientAuth-Anforderungen nicht stimmen, kann das Dashboard:

  • keine oder nur sporadische Abfragen ausführen,
  • Requests in Teilpfaden failen (z. B. Saved Objects, Plugin-APIs, Hintergrundjobs),
  • UI-Module als „leer“ darstellen, obwohl Indizes gefüllt sind.

2) „certificate_unknown“ deutet häufig auf mTLS/Client-Zertifikate oder untrusted CA hin

Der Fehler sslv3 alert certificate unknown kommt typischerweise zustande, wenn die Gegenseite (Server) ein Zertifikat nicht akzeptiert. Das passiert z. B. bei:

  • Untrusted CA / fehlende Intermediate-CA (unvollständige Kette)
  • mTLS aktiviert (Server erwartet ein Client-Zertifikat; Dashboard liefert keines oder falsches)
  • Zertifikat passt nicht zu Hostname/IP (SAN fehlt), was je nach Library/Setting ebenfalls zu Hard-Fails führen kann

Der openssl s_client Output „unable to get local issuer certificate“ und „unable to verify the first certificate“ ist ein klassisches Signal: Die Zertifikatskette ist nicht vollständig vertrauenswürdig aus Sicht des Clients (Dashboard-Host) – entweder weil die CA-Datei nicht stimmt oder weil der Server kein vollständiges Chain-Zertifikat präsentiert.

3) Saved Objects „leer“: nicht zwingend „Plugin fehlt“, sondern „Plugin kann nicht initialisieren“

Der Reflex „Saved Objects fehlen im Dateisystem“ ist nachvollziehbar, greift aber häufig zu kurz:

  • Das Plugin ist installiert (Plugin-Liste zeigt wazuh@4.14.1-02 etc.).
  • Saved Objects werden nicht immer als „sichtbares Verzeichnis“ erwartet; sie können als Assets im Plugin-Paket liegen und beim Start/Init via API importiert werden.
  • Wenn TLS/Authentisierung in genau diesem Init-Pfad scheitert, bleiben Saved Objects leer – und die UI wirkt „nackt“/unvollständig.

4) Multitenancy/„Tenant“-Header: kann zusätzlich irritieren, ist hier aber sekundär

Im Thread ist opensearch_security.multitenancy.enabled: false gesetzt. Das reduziert Tenant-Komplexität (nur ein Space), dennoch kann es zu Missverständnissen kommen, wenn Requests Tenant-Header tragen oder UI/Plugin tenant-basiert denkt. Entscheidend bleibt aber: Ohne stabile TLS-Verbindung sind Tenant-Fragen nur Nebengeräusche.


Lösung / Best Practices

Die nachhaltige Lösung ist: TLS sauber machen (Kette, SAN, optional mTLS), dann Saved Objects/Module neu initialisieren.

Schritt 1: Zertifikatskette zwischen Dashboard und Indexer korrekt herstellen

Ziel: openssl s_client -connect <indexer>:9200 -showcerts darf nicht mehr mit „unable to verify …“ enden (zumindest nicht, wenn du mit der richtigen CA prüfst).

Prüfpunkte:

  1. Server präsentiert vollständige Kette
    • Das Indexer-HTTP-Zertifikat sollte idealerweise die Chain liefern (Server-Zertifikat + Intermediates).
    • Wenn du eine eigene PKI nutzt: sicherstellen, dass das Zertifikat, das der Indexer ausliefert, die Kette korrekt abbildet.
  2. CA-Bundle auf Dashboard-Seite ist vollständig
    • /etc/wazuh-dashboard/certs/root-ca.pem muss die korrekte Root-CA enthalten – und falls relevant auch Intermediate-CAs (als Bundle).
    • Ein häufiger Fehler: root-ca.pem enthält nicht die CA, die das Indexer-Zertifikat tatsächlich signiert hat (oder es fehlen Intermediates).
  3. Hostname/SAN konsistent
    • In der Konfiguration steht opensearch.hosts: ["https://127.0.0.1:9200"].
    • Das Indexer-Zertifikat muss SAN=127.0.0.1 oder SAN=localhost enthalten, abhängig davon, wie du verbindest.
    • Best Practice: https://localhost:9200 verwenden und Zertifikat mit SAN=localhost (und ggf. zusätzlich 127.0.0.1) ausstellen.

Schritt 2: mTLS-ClientAuth im Indexer prüfen (und ggf. entschärfen)

Wenn der Indexer auf der HTTP-Schicht Client-Zertifikate fordert, scheitert das Dashboard ohne korrekt konfiguriertes Client-Zertifikat.

Prüfe im Indexer (typisch in opensearch.yml / Security-Konfig):

  • Ist HTTP ClientAuth auf REQUIRE oder OPTIONAL gesetzt?
  • Erwartet der Indexer ein Client-Zertifikat, das gegen eine bestimmte CA validiert wird?

Best Practice-Entscheidung:

  • Einfach/robust: kein mTLS zwischen Dashboard und lokalem Indexer (nur serverseitiges TLS + Basic Auth), wenn die Kommunikation lokal/vertrauenswürdig segmentiert ist.
  • Strenger: mTLS aktiv lassen, dann aber Dashboard mit Client-Zertifikat + Key ausstatten und CA-Trust sauber konfigurieren.

Schritt 3: Dashboard-Konfiguration konsolidieren (keine „halben“ TLS-Setups)

Im Thread ist opensearch.ssl.verificationMode: none gesetzt, gleichzeitig aber opensearch.ssl.certificateAuthorities konfiguriert. Das ist operativ oft ein „Zwischenzustand“, der Fehlerbilder verschleiert.

Empfehlung:

  • Für einen sauberen Betrieb: verificationMode: full oder mindestens certificate (je nach Hostname/SAN-Situation) und eine korrekte CA-Kette.
  • verificationMode: none nur als sehr kurzfristiger Debug-Schritt – nicht als Endzustand, weil du damit echte Trust-Probleme überdeckst (und manche TLS-Probleme wie ClientAuth trotzdem nicht löst).

Schritt 4: Wazuh API TLS/Trust ebenfalls prüfen

Das Plugin zeigt auf:

  • https://localhost:55000 (Wazuh API)

Wenn Dashboard der API ebenfalls nicht traut oder die API ein Zertifikat ohne passende Chain/SAN liefert, können Module ebenfalls „leer“ wirken (vor allem Status-/Inventar-Workflows, die API-Calls benötigen).

Prüfe analog:

  • openssl s_client -connect localhost:55000 -showcerts
  • CA-Vertrauen (Dashboard-Host) und Zertifikatskette

Schritt 5: Nach TLS-Fix Saved Objects / Assets neu laden (ohne Neuinstallation-„Blindflug“)

Wenn TLS stabil ist, kommen Saved Objects in der Regel wieder, entweder weil:

  • Plugin-Initialisierung wieder erfolgreich läuft, oder
  • du die Objekte gezielt neu importierst.

Best Practice für reproduzierbaren Betrieb:

  • Dashboard stoppen → Cache/State nicht unkontrolliert löschen, sondern gezielt prüfen, ob es eine definierte Asset-Import-Mechanik des Plugins gibt (je nach Paket/Version).
  • Dashboard starten und Logs auf erfolgreiche Plugin-Init prüfen (keine TLS-Alerts, keine Auth-Fehler, keine Saved Objects Errors).

Lessons Learned / Best Practices

  • „Index enthält Daten“ beweist nicht, dass Dashboard die Module rendern kann. Entscheidend ist die vollständige Request-Kette inkl. TLS/Trust.
  • TLS-Kette schlägt alles: fehlende Intermediate-CAs sind einer der häufigsten Gründe für „UI leer, Daten da“.
  • mTLS ist eine häufige versteckte Ursache für certificate_unknown – besonders wenn Sicherheitsrichtlinien oder Hardening nachträglich geändert wurden.
  • SAN/Hostname-Konsistenz ist Pflicht, insbesondere wenn du 127.0.0.1 statt localhost verwendest.
  • Vermeide Dauerbetrieb mit verificationMode: none: Das kaschiert Ursachen und erzeugt schwer reproduzierbare Fehlerbilder.

Fazit

In diesem Fehlerbild ist nicht die Datenerhebung das Problem, sondern die sichere Kommunikation: Dashboard kann aufgrund einer defekten/inkompletten Zertifikatskette und/oder mTLS-ClientAuth-Anforderungen nicht zuverlässig mit Indexer/API sprechen. Das führt dazu, dass Module „No data“ zeigen und Saved Objects nicht geladen/initialisiert werden. Sobald du TLS (Chain + SAN + ggf. ClientAuth) konsistent reparierst, normalisieren sich die Wazuh-Module typischerweise ohne invasive Neuinstallationen – und die UI füllt sich wieder.

Mehr zu Wazuh …
https://wazuh.com/?utm_source=ambassadors&utm_medium=referral&utm_campaign=ambassadors+program

Mehr zum Wazuh Ambassador Program …
https://wazuh.com/ambassadors-program/?utm_source=ambassadors&utm_medium=referral&utm_campaign=ambassadors+program

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