[MEDIUM] CVE-Meldeweg v2: Metriken, Grafana-Dashboard, Alerts in eigenen Matrix-Raum #47

Closed
opened 2026-08-01 08:09:38 +00:00 by sorb · 4 comments
Owner

Entscheidung sorb (2026-08-01): Die reine Artifact-Ablage der Trivy-Funde (#31) ist ungenügend. Zielbild:

  1. Eigener Matrix-Raum für CVE-/Release-Meldungen: !YRJvcEbVXtRlUIkNld:axion1337.chat (angelegt), Absender bleibt der bestehende @alerts-Bot — kein zweiter Bot (beantwortet CFGMON-13). Bot einladen (Raum ist restricted, Join wurde abgelehnt) — sorb.
  2. CVEs als MetrikenGrafana-Dashboard + Prometheus-Alertregeln → Alertmanager → Matrix. Damit laufen CVE-Warnungen über denselben Alarmweg wie alles andere (Historie, Silences, Dashboards inklusive).

Architektur-Vorschlag (zur Diskussion):

  • Scan-Ort wandert von der Lab-CI nach CFGMON: Trivy als Compose-Service/Cron im monitoring-Stack (--format json → kleiner Stdlib-Konverter → Prometheus-Textfile/Pushgateway-los via Remote-Write auf localhost:9090). Begründung: Metriken, Prometheus und Grafana wohnen dort; die Lab-CI bleibt fürs schnelle „Report als Artifact" beim Release-Build. Alternativ: Lab-CI pusht Metriken — scheitert aber an CFGMON-03 (9090 wird gerade zugezogen) und koppelt Prod-Monitoring an Lab-Verfügbarkeit.
  • Metrik-Schema: trivy_image_vulnerabilities{image,severity} (Gauge) + trivy_scan_timestamp{image}; Alertregel z. B. trivy_image_vulnerabilities{severity="CRITICAL"} > 0 → severity=critical, HIGH > 0 → warning mit for: 24h (Rauschdämpfung).
  • Raum-Routing: matrix-alerts-Receiver bekommt Label-basiertes Routing (room-Label im Alert → Ziel-Raum, Default = Alerts-Raum); Alertmanager-Route setzt room: cve für Trivy-Alerts. Kleiner, sauberer Eingriff im bestehenden Stdlib-Receiver.
  • release-watch (Advisory-Notizen, #22) zieht in denselben CVE-Raum um — Env dafür ist vorbereitet (MATRIX_RELEASE_ROOM_ID, Fallback Alerts-Raum).

Abgrenzung SBOM (Frage sorb, dokumentiert auch im Script): release-watch lebt von einer handgepflegten Repo-Liste — de facto ein Mini-SBOM auf Repo-Granularität, ohne Versions-/Dependency-Wissen. Trivy dagegen erzeugt sein SBOM selbst aus den Images (OS-Pakete + Sprach-Dependencies) — dort ist nichts zu pflegen. Beide ergänzen sich: Trivy = „was IST verwundbar in dem, was wir ausliefern", release-watch = „Upstream hat etwas veröffentlicht, das uns betreffen könnte".

Verweise: #31 (Scan existiert), #22 (release-watch), CFGMON-13 im Backlog (Absender-Design — durch Punkt 1 entschieden).

Entscheidung sorb (2026-08-01): Die reine Artifact-Ablage der Trivy-Funde (#31) ist **ungenügend**. Zielbild: 1. **Eigener Matrix-Raum für CVE-/Release-Meldungen**: `!YRJvcEbVXtRlUIkNld:axion1337.chat` (angelegt), Absender bleibt der bestehende `@alerts`-Bot — kein zweiter Bot (beantwortet CFGMON-13). ⬜ **Bot einladen** (Raum ist restricted, Join wurde abgelehnt) — sorb. 2. **CVEs als Metriken** → **Grafana-Dashboard** + **Prometheus-Alertregeln** → Alertmanager → Matrix. Damit laufen CVE-Warnungen über denselben Alarmweg wie alles andere (Historie, Silences, Dashboards inklusive). **Architektur-Vorschlag (zur Diskussion):** - **Scan-Ort wandert von der Lab-CI nach CFGMON**: Trivy als Compose-Service/Cron im monitoring-Stack (`--format json` → kleiner Stdlib-Konverter → Prometheus-Textfile/Pushgateway-los via Remote-Write auf localhost:9090). Begründung: Metriken, Prometheus und Grafana wohnen dort; die Lab-CI bleibt fürs schnelle „Report als Artifact" beim Release-Build. Alternativ: Lab-CI pusht Metriken — scheitert aber an CFGMON-03 (9090 wird gerade zugezogen) und koppelt Prod-Monitoring an Lab-Verfügbarkeit. - **Metrik-Schema**: `trivy_image_vulnerabilities{image,severity}` (Gauge) + `trivy_scan_timestamp{image}`; Alertregel z. B. `trivy_image_vulnerabilities{severity="CRITICAL"} > 0` → severity=critical, `HIGH > 0` → warning mit `for: 24h` (Rauschdämpfung). - **Raum-Routing**: matrix-alerts-Receiver bekommt Label-basiertes Routing (`room`-Label im Alert → Ziel-Raum, Default = Alerts-Raum); Alertmanager-Route setzt `room: cve` für Trivy-Alerts. Kleiner, sauberer Eingriff im bestehenden Stdlib-Receiver. - **release-watch** (Advisory-Notizen, #22) zieht in denselben CVE-Raum um — Env dafür ist vorbereitet (`MATRIX_RELEASE_ROOM_ID`, Fallback Alerts-Raum). **Abgrenzung SBOM** (Frage sorb, dokumentiert auch im Script): `release-watch` lebt von einer **handgepflegten Repo-Liste** — de facto ein Mini-SBOM auf Repo-Granularität, ohne Versions-/Dependency-Wissen. **Trivy dagegen erzeugt sein SBOM selbst aus den Images** (OS-Pakete + Sprach-Dependencies) — dort ist nichts zu pflegen. Beide ergänzen sich: Trivy = „was IST verwundbar in dem, was wir ausliefern", release-watch = „Upstream hat etwas veröffentlicht, das uns betreffen könnte". Verweise: #31 (Scan existiert), #22 (release-watch), CFGMON-13 im Backlog (Absender-Design — durch Punkt 1 entschieden).
Author
Owner

Erweiterung (2026-08-01, Fragenkatalog sorb) — Host-Scanning, SBOM, Tool-Überschneidungen, Alert-Pflichtfelder:

Womit scannen wir Host-Pakete (außerhalb von Containern)?

Empfehlung: dasselbe Trivy, anderer Modus. trivy rootfs / (bzw. trivy fs) scannt die dpkg-Datenbank + Sprach-Dependencies eines Hosts direkt — gleiche Findings-Struktur, gleiche Severity-Logik, gleicher Konverter in die Metrik-Pipeline wie bei Images. Kein zweites Tool, kein zweites Format. Umsetzung: kleiner systemd-Timer pro Host (CFGMON, MATRIX, GAME, Overmind) der trivy rootfs --format json erzeugt; Ergebnis-Upload zum Konverter auf CFGMON (privates Netz) oder lokale Textfile-Metrik für den bestehenden node-exporter (--collector.textfile.directory — MATRIX/CFGMON haben beide schon einen laufen). Alternative Grype/Syft ist gleichwertig, brächte aber ein zweites Toolset ohne Mehrwert.

Brauchen die Hosts eine SBOM? Automatisch aktuell?

Ja — aber als generiertes Artefakt, nicht als gepflegtes Dokument. Die Wahrheit liegt in dpkg/apt; die SBOM ist ein Export davon: trivy rootfs --format cyclonedx --output host-$(hostname).cdx.json / im selben Timer-Lauf. Damit ist „automatisch aktuell halten" trivial gelöst (jede Scan-Runde = frische SBOM). Ablage-Vorschlag: pro Host nach CFGMON schieben (privates Netz) — dann kann Trivy dort auch offline gegen die SBOM rescannen (neue CVE-Feeds gegen alten Stand, ohne Host-Zugriff), was den „Zeitstrahl" unten sauber füttert. Kein Handpflege-Anteil — im Gegensatz zur release-watch-Repo-Liste (siehe SBOM-Abgrenzung oben).

Überschneidung mit Backlog-Tools?

Tool (Issue) Zweck Überschneidung mit CVE-Scanning?
CrowdSec (#29) Log-basierte Angriffs-Erkennung + IP-Bouncer Keine — erkennt laufende Angriffe, nicht verwundbare Pakete. Komplementär.
Falco (#30) Syscall-Anomalien zur Laufzeit Keine — Runtime-Verhalten, nicht Inventar.
Lynis (#28) Host-Konfigurations-Audit (Hardening-Score) Gering — prüft Einstellungen, nicht CVEs. Ergänzt sich; keine Doppelung.
auditd (#26) Forensik/Datei-Integrität Keine.

Fazit: Kein Backlog-Tool deckt Host-CVE-Scanning ab — Trivy-rootfs füllt eine echte Lücke. Einziger Konsolidierungs-Kandidat wäre Wazuh (SCA+Vuln+FIM in einem), das wäre aber ein Schwergewicht, das #26/#28/#29 gleichzeitig ersetzen würde — nur relevant, falls die Einzeltools zur Last werden.

Alert-/Dashboard-Pflichtfelder (Vorgabe sorb) → Metrik-Schema

Jeder Alert muss tragen: CVE-ID, Mitigation, Zeitstrahl (erstmals gesehen/geschlossen), Ort (Host), Typ (Image vs. Host-Paket). Konsequenz fürs Schema (ersetzt den einfachen Zähler-Vorschlag oben):

trivy_vuln_info{cve, severity, target, target_type="image|host", host, pkg, installed, fixed_version} = 1
trivy_vuln_first_seen_timestamp{cve, target} = <unix-ts>   # vom Konverter persistiert
trivy_last_scan_timestamp{target} = <unix-ts>              # Scan-Frische ueberwachen!
  • CVE-ID + Mitigation in der Alert-Annotation: {{ $labels.cve }}, Link https://nvd.nist.gov/vuln/detail/{{ $labels.cve }}, „Fix: Update {{ $labels.pkg }} → {{ $labels.fixed_version }}" (leer = noch kein Fix verfügbar → eigene Alert-Klasse „unfixed").
  • Zeitstrahl: first_seen aus der Konverter-State-Datei; „geschlossen" = Serie verschwindet → Grafana State-Timeline-Panel über trivy_vuln_info, resolved- kommt wie gehabt über send_resolved.
  • Ort/Typ: Labels host + target_type — Alertmanager-Route gruppiert nach cve, host.
  • Kardinalität im Blick: nur HIGH/CRITICAL als Einzelserien, MEDIUM/LOW nur als Summen-Gauge.
  • Dashboard-Struktur: oben Summen je Severity/Host, Mitte Tabelle offener CVEs (Spalten = genau die Pflichtfelder), unten State-Timeline pro Host + „Scan-Alter"-Panel (Alert wenn time() - trivy_last_scan_timestamp > 2d — ein Scanner, der still stirbt, ist sonst unsichtbar).

Statusnotiz: @alerts ist dem Security-Raum beigetreten und Senderecht ist verifiziert (Begrüßungsnachricht 2026-08-01 11:04, Event bestätigt); release-watch läuft seit heute Vormittag auf CFGMON gegen diesen Raum.

**Erweiterung (2026-08-01, Fragenkatalog sorb) — Host-Scanning, SBOM, Tool-Überschneidungen, Alert-Pflichtfelder:** ## Womit scannen wir Host-Pakete (außerhalb von Containern)? **Empfehlung: dasselbe Trivy, anderer Modus.** `trivy rootfs /` (bzw. `trivy fs`) scannt die dpkg-Datenbank + Sprach-Dependencies eines Hosts direkt — gleiche Findings-Struktur, gleiche Severity-Logik, gleicher Konverter in die Metrik-Pipeline wie bei Images. Kein zweites Tool, kein zweites Format. Umsetzung: kleiner systemd-Timer pro Host (CFGMON, MATRIX, GAME, Overmind) der `trivy rootfs --format json` erzeugt; Ergebnis-Upload zum Konverter auf CFGMON (privates Netz) oder lokale Textfile-Metrik für den bestehenden node-exporter (`--collector.textfile.directory` — MATRIX/CFGMON haben beide schon einen laufen). Alternative Grype/Syft ist gleichwertig, brächte aber ein zweites Toolset ohne Mehrwert. ## Brauchen die Hosts eine SBOM? Automatisch aktuell? **Ja — aber als generiertes Artefakt, nicht als gepflegtes Dokument.** Die Wahrheit liegt in dpkg/apt; die SBOM ist ein Export davon: `trivy rootfs --format cyclonedx --output host-$(hostname).cdx.json /` im selben Timer-Lauf. Damit ist „automatisch aktuell halten" trivial gelöst (jede Scan-Runde = frische SBOM). Ablage-Vorschlag: pro Host nach CFGMON schieben (privates Netz) — dann kann Trivy dort auch **offline gegen die SBOM** rescannen (neue CVE-Feeds gegen alten Stand, ohne Host-Zugriff), was den „Zeitstrahl" unten sauber füttert. Kein Handpflege-Anteil — im Gegensatz zur release-watch-Repo-Liste (siehe SBOM-Abgrenzung oben). ## Überschneidung mit Backlog-Tools? | Tool (Issue) | Zweck | Überschneidung mit CVE-Scanning? | |---|---|---| | CrowdSec (#29) | Log-basierte Angriffs-Erkennung + IP-Bouncer | **Keine** — erkennt laufende Angriffe, nicht verwundbare Pakete. Komplementär. | | Falco (#30) | Syscall-Anomalien zur Laufzeit | **Keine** — Runtime-Verhalten, nicht Inventar. | | Lynis (#28) | Host-**Konfigurations**-Audit (Hardening-Score) | **Gering** — prüft Einstellungen, nicht CVEs. Ergänzt sich; keine Doppelung. | | auditd (#26) | Forensik/Datei-Integrität | **Keine.** | **Fazit:** Kein Backlog-Tool deckt Host-CVE-Scanning ab — Trivy-rootfs füllt eine echte Lücke. Einziger Konsolidierungs-Kandidat wäre Wazuh (SCA+Vuln+FIM in einem), das wäre aber ein Schwergewicht, das #26/#28/#29 gleichzeitig ersetzen würde — nur relevant, falls die Einzeltools zur Last werden. ## Alert-/Dashboard-Pflichtfelder (Vorgabe sorb) → Metrik-Schema Jeder Alert muss tragen: **CVE-ID, Mitigation, Zeitstrahl (erstmals gesehen/geschlossen), Ort (Host), Typ (Image vs. Host-Paket)**. Konsequenz fürs Schema (ersetzt den einfachen Zähler-Vorschlag oben): ``` trivy_vuln_info{cve, severity, target, target_type="image|host", host, pkg, installed, fixed_version} = 1 trivy_vuln_first_seen_timestamp{cve, target} = <unix-ts> # vom Konverter persistiert trivy_last_scan_timestamp{target} = <unix-ts> # Scan-Frische ueberwachen! ``` - **CVE-ID + Mitigation** in der Alert-Annotation: `{{ $labels.cve }}`, Link `https://nvd.nist.gov/vuln/detail/{{ $labels.cve }}`, „Fix: Update {{ $labels.pkg }} → {{ $labels.fixed_version }}" (leer = noch kein Fix verfügbar → eigene Alert-Klasse „unfixed"). - **Zeitstrahl**: first_seen aus der Konverter-State-Datei; „geschlossen" = Serie verschwindet → Grafana State-Timeline-Panel über `trivy_vuln_info`, resolved-✅ kommt wie gehabt über send_resolved. - **Ort/Typ**: Labels `host` + `target_type` — Alertmanager-Route gruppiert nach `cve, host`. - Kardinalität im Blick: nur HIGH/CRITICAL als Einzelserien, MEDIUM/LOW nur als Summen-Gauge. - Dashboard-Struktur: oben Summen je Severity/Host, Mitte Tabelle offener CVEs (Spalten = genau die Pflichtfelder), unten State-Timeline pro Host + „Scan-Alter"-Panel (Alert wenn `time() - trivy_last_scan_timestamp > 2d` — ein Scanner, der still stirbt, ist sonst unsichtbar). Statusnotiz: `@alerts` ist dem Security-Raum beigetreten und **Senderecht ist verifiziert** (Begrüßungsnachricht 2026-08-01 11:04, Event bestätigt); release-watch läuft seit heute Vormittag auf CFGMON gegen diesen Raum.
Author
Owner

Umsetzung v1 gebaut (2026-08-01, Commits b6007c5 + cdfadc0 in threadnet-operating) — deploybereit:

  • cve-scan: Trivy 0.58.2 als Compose-Service, scannt alle 24 h die 29 real deployten Images (frische Cluster-Inventur; inkl. Nebenfund coturn/coturn:latest ungepinnt — Kandidat für die Cleanup-Liste #39)
  • cve-exporter: Stdlib-Exporter mit persistentem first_seen-State — Schema exakt nach den Pflichtfeldern (CVE-ID, Fix-Version, Zeitstrahl, Host, Typ)
  • 3 Alertregeln (promtool SUCCESS): CRITICAL sofort, HIGH mit 24-h-Dämpfung, Scan-Frische-Wächter; alle mit room: security
  • matrix-alerts: Label-basiertes Raum-Routing (MATRIX_ROOM_SECURITY → Security-Raum; Edits folgen dem gespeicherten Raum)
  • Grafana: neuer Ordner „Security" mit Dashboard cve-overview — Severity-Stats, CVE-Tabelle (NVD-Link je CVE, Fix-Version, Erstmals-gesehen), Zeitstrahl je Target, Verlauf

Deploy (sorb, CFGMON): cd /opt/threadnet-operating && git pull && cd monitoring && docker compose up -d — der erste Scan-Durchlauf zieht die Trivy-DB und braucht ein paar Minuten pro Image; danach füllen sich /metrics, Dashboard und (bei Funden) der Security-Raum von selbst. UNGETESTET bis dahin.

Ausbaustufen offen: Host-rootfs-Scans per systemd-Timer (Konzept oben), MEDIUM/LOW nur als Summen (bewusst), Images-Liste bei Stack-Änderungen nachziehen (cve/images.txt).

**Umsetzung v1 gebaut** (2026-08-01, Commits `b6007c5` + `cdfadc0` in threadnet-operating) — deploybereit: - **cve-scan**: Trivy 0.58.2 als Compose-Service, scannt alle 24 h die **29 real deployten Images** (frische Cluster-Inventur; inkl. Nebenfund `coturn/coturn:latest` ungepinnt — Kandidat für die Cleanup-Liste #39) - **cve-exporter**: Stdlib-Exporter mit persistentem first_seen-State — Schema exakt nach den Pflichtfeldern (CVE-ID, Fix-Version, Zeitstrahl, Host, Typ) - **3 Alertregeln** (`promtool` SUCCESS): CRITICAL sofort, HIGH mit 24-h-Dämpfung, Scan-Frische-Wächter; alle mit `room: security` - **matrix-alerts**: Label-basiertes Raum-Routing (`MATRIX_ROOM_SECURITY` → Security-Raum; Edits folgen dem gespeicherten Raum) - **Grafana**: neuer Ordner „Security" mit Dashboard `cve-overview` — Severity-Stats, CVE-Tabelle (NVD-Link je CVE, Fix-Version, Erstmals-gesehen), Zeitstrahl je Target, Verlauf **Deploy (sorb, CFGMON):** `cd /opt/threadnet-operating && git pull && cd monitoring && docker compose up -d` — der erste Scan-Durchlauf zieht die Trivy-DB und braucht ein paar Minuten pro Image; danach füllen sich /metrics, Dashboard und (bei Funden) der Security-Raum von selbst. **UNGETESTET bis dahin.** **Ausbaustufen offen:** Host-rootfs-Scans per systemd-Timer (Konzept oben), MEDIUM/LOW nur als Summen (bewusst), Images-Liste bei Stack-Änderungen nachziehen (`cve/images.txt`).
Author
Owner

Deploy-Stand 2026-08-01, CFGMON. Stack ist live (2b715ca), mit einer Einschraenkung.

Live und verifiziert:

  • cve-scan scannt die 29 Images, erster Durchlauf lief waehrend des Deploys
  • cve-exporter liefert Metriken, Prometheus-Target cve_exporter ist up
  • Regelgruppe axion-cve mit 3 Regeln geladen
  • Grafana-Ordner Security mit dem CVE-Dashboard provisioniert (dank cdfadc0)
  • Exporter-Last: 0,4 s pro Scrape fuer 29 Reports, ~3100 Zeilen -- unkritisch
  • Private Registry rohana.axion1337.de zieht anonym, Trivy braucht dort keine Credentials

Nicht live: die Alarm-Zustellung. room="security" routet vorerst auf einen Null-Receiver, sonst haette der erste Scan-Durchlauf den Security-Raum geflutet -- bei 14 von 29 Images bereits 59 CRITICAL und 445 HIGH, eine Matrix-Nachricht pro Alarm, mit anschliessender Retry-Schleife durch ein State-Problem im Receiver. Analyse und Weg zum Scharfschalten: #51

Beim Deploy ausserdem aufgefallen, unabhaengig von dieser Pipeline: #52 -- docker compose up -d aktiviert geaenderte Configs nicht, das Deploy-Kommando aus der Beschreibung reicht nicht aus.

Nebenfund bestaetigt: coturn/coturn:latest ist das einzige ungepinnte Image.

**Deploy-Stand 2026-08-01, CFGMON.** Stack ist live (`2b715ca`), mit einer Einschraenkung. Live und verifiziert: - `cve-scan` scannt die 29 Images, erster Durchlauf lief waehrend des Deploys - `cve-exporter` liefert Metriken, Prometheus-Target `cve_exporter` ist `up` - Regelgruppe `axion-cve` mit 3 Regeln geladen - Grafana-Ordner **Security** mit dem CVE-Dashboard provisioniert (dank `cdfadc0`) - Exporter-Last: 0,4 s pro Scrape fuer 29 Reports, ~3100 Zeilen -- unkritisch - Private Registry `rohana.axion1337.de` zieht anonym, Trivy braucht dort keine Credentials **Nicht live: die Alarm-Zustellung.** `room="security"` routet vorerst auf einen Null-Receiver, sonst haette der erste Scan-Durchlauf den Security-Raum geflutet -- bei 14 von 29 Images bereits 59 CRITICAL und 445 HIGH, eine Matrix-Nachricht pro Alarm, mit anschliessender Retry-Schleife durch ein State-Problem im Receiver. Analyse und Weg zum Scharfschalten: #51 Beim Deploy ausserdem aufgefallen, unabhaengig von dieser Pipeline: #52 -- `docker compose up -d` aktiviert geaenderte Configs nicht, das Deploy-Kommando aus der Beschreibung reicht nicht aus. Nebenfund bestaetigt: `coturn/coturn:latest` ist das einzige ungepinnte Image.
Author
Owner

Migriert nach git.lab: axion1337.chat/axion1337.chat-gitops#45 (nur im Lab bzw. via VPN erreichbar — das Lab ist seit 2026-08-01 die Quelle der Wahrheit, siehe gitops#48). Weiterarbeit dort; dieses Gitea-Issue bleibt als Verweis stehen.

**Migriert nach git.lab**: [axion1337.chat/axion1337.chat-gitops#45](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/45) (nur im Lab bzw. via VPN erreichbar — das Lab ist seit 2026-08-01 die Quelle der Wahrheit, siehe gitops#48). Weiterarbeit dort; dieses Gitea-Issue bleibt als Verweis stehen.
sorb closed this issue 2026-08-01 14:26:13 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sorb/axion1337.chat-gitops#47