Gate 4, slice 3: verfahren/, hosts/, vision/ and shared/ moved via git mv - six AARs to docs/aar/ (four harvested by the 2026-08-09 retro, two open), procedures and host knowledge to docs/wiki/ (admin, deployment, architecture, new area vision), the retro protocol and the commit mapping table to docs/sources/ (protokolle/, migration/). New: the wiki index linking every page, and the mirror-topology page carrying the why-two-places reasoning verbatim from the old CLAUDE.md (F-013 preserved). All moved-path references retargeted; the link checker drove the sweep to zero. pruefe_prosa.py added (pattern C+D): SHA citations resolve via repo, mapping table, optional component clones or a curated exemption list (documented dead Gitea-force-push commits, a vendor-repo tag, an Authentik uid that is hex but no git SHA, the external neckbeard reference); wiki task prose without an issue reference errors, with a visible pragma for deliberate checklists; the dead-tracker denylist now covers every mirrored repo's retired Gitea tracker (F-005) - two links re-verified against live GitLab titles and retargeted, five defused into honest historical citations. Verified: validate 0/0, gen_status --check current, drift 0. Demo on the pre-migration state fires 6 findings (3 orphaned SHAs, 3 task blocks); on the current tree exactly the 3 F-004 task blocks remain - they turn green in slice 4 when the issues exist, which is why pruefe_prosa joins CI only then. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
74 lines
4.3 KiB
Markdown
74 lines
4.3 KiB
Markdown
---
|
|
type: aar
|
|
status: harvested
|
|
date: 2026-08-01
|
|
related: []
|
|
---
|
|
|
|
# AAR — CVE-Pipeline `gitops#47`
|
|
|
|
**Datum:** 2026-08-01 · **Host/Stack:** CFGMON, `/opt/threadnet-operating/monitoring`
|
|
**Auftrag:** Deploy eines gebauten, als UNGETESTET übergebenen Stands (Trivy-Scanner,
|
|
Exporter, Alert-Regeln, Grafana-Dashboard)
|
|
|
|
## 1. Ergebnis
|
|
|
|
**Live und verifiziert:** Scanner (29/29 Images gescannt), Exporter, Prometheus-Job
|
|
`cve_exporter`, Regelgruppe `axion-cve`, Grafana-Ordner *Security* mit CVE-Dashboard.
|
|
|
|
**Bewusst nicht live:** die Alarm-Zustellung nach Matrix. `room="security"` routet in
|
|
`alertmanager.yml` auf einen Null-Receiver (Commit `2b715ca` in
|
|
`sorb/threadnet-operating`). Grund siehe Befund 1.
|
|
|
|
## 2. Befunde
|
|
|
|
| # | Befund | Schwere | Status |
|
|
|---|---|---|---|
|
|
| 1 | Eine Matrix-Nachricht pro CVE. 126 CRITICAL landen in **einer** Alertmanager-Gruppe, nach 24 h kommen 1222 HIGH dazu. Dazu steht `save_state()` in `do_POST` hinter der Sende-Schleife: bricht ein Send ab (Synapse rate-limitet nach ~10 mit 429), wird kein State gespeichert, der Receiver antwortet 502, Alertmanager wiederholt die komplette Gruppe — mit leerer Deduplizierung | HIGH | abgefangen, `gitops#51` |
|
|
| 2 | `docker compose up -d` aktiviert geänderte Configs nicht. Einzeldatei-Mounts hängen am Inode, `git pull` benennt um. Prometheus lief nach dem Deploy mit alten Regeln — `promtool` fand 9, Prometheus kannte 6, kein Fehler im Log | MEDIUM | behoben via `--force-recreate`, `gitops#52` |
|
|
| 3 | `TrivyScanStale` kann ein nie erfolgreich gescanntes Image nicht melden — ohne ersten Report existiert keine Serie, an der `time() - trivy_last_scan_timestamp` hängen könnte | LOW | notiert in `gitops#51` |
|
|
| 4 | Der Exporter prunt den First-Seen-State bei **jedem** Scrape. Ein transienter Lesefehler (`except: continue`) löscht die Erstfund-Zeitstempel des Targets dauerhaft | LOW | notiert in `gitops#51` |
|
|
| 5 | Grafana-Provisioning für den Security-Ordner fehlte — das Dashboard wäre nie erschienen | — | vom Autor selbst behoben (`cdfadc0`), bevor ausgerollt wurde |
|
|
|
|
Gemessene Gesamtlage über alle 29 Images: **126 CRITICAL, 1222 HIGH**, 2710 MEDIUM,
|
|
1316 LOW. Spitzenreiter `goauthentik/server:2026.2.3` mit 369 CRITICAL+HIGH.
|
|
|
|
## 3. Verdachtsfälle mit Entwarnung
|
|
|
|
| Vermutung | Messung | Ergebnis |
|
|
|---|---|---|
|
|
| Exporter parst 29 JSONs je Scrape → Timeouts bei 15 s Intervall | `collect()` gegen echte Reports | 0,4 s für 29 Reports, ~3100 Zeilen — unkritisch |
|
|
| Private Registry `rohana.axion1337.de` braucht Credentials für Trivy | Anonymer Pull | zieht anonym, keine Credentials nötig |
|
|
| Zwei down-Targets könnten Folge des Deploys sein | `avg_over_time(up[3h])` | 0.00 — schon 3 h vorher tot, in `hosts/game.md` erfasst |
|
|
|
|
`promtool check rules`, `amtool check-config`, `amtool config routes test`,
|
|
`docker compose config` und `py_compile` liefen alle sauber.
|
|
|
|
## 4. Was die Befunde ermöglicht hat
|
|
|
|
Befund 1 wäre in keinem Lint aufgefallen — der Code ist korrekt, das Problem entsteht
|
|
erst aus der **Datenmenge**, gegen die er läuft. Sichtbar wurde er durch Messen vor dem
|
|
Deploy: Trivy lokal über drei repräsentative Images ergab 27 CRITICAL / 126 HIGH auf 3
|
|
von 29, also die richtige Größenordnung. Die spätere Realität (126 CRITICAL) bestätigte
|
|
die Entscheidung. `amtool config routes test` belegte danach, dass die Stummschaltung
|
|
nur `room=security` trifft und den normalen Alarmweg unangetastet lässt.
|
|
|
|
Befund 2 wurde nur sichtbar, weil die Config **im Container** geprüft wurde
|
|
(`docker exec prometheus grep …`) statt auf der Platte. Auf der Platte sah alles richtig
|
|
aus, `up -d` meldete `Running`, und ein SIGHUP-Reload lud klaglos den alten Inhalt.
|
|
|
|
Diese beiden Punkte sind als Verfahren festgehalten:
|
|
[../deploy-uebergabe.md](../wiki/deployment/deploy-uebergabe.md).
|
|
|
|
## 5. Offen
|
|
|
|
Richtungsentscheidung zu `gitops#51`, bevor die Alarme scharf gehen: entweder
|
|
`matrix-alerts.py` auf eine Sammelnachricht pro Webhook-Batch umbauen (die fünf
|
|
Pflichtfelder je CVE als eine Zeile, bleibt vollständig), oder die Regeln auf
|
|
`count by (target, severity)` aggregieren und die CVE-Details im Dashboard lassen.
|
|
In beiden Fällen zusätzlich: State inkrementell speichern, 429 mit `Retry-After`
|
|
behandeln. Danach die `room="security"`-Route entfernen.
|
|
|
|
Nebenbefund ohne Handlungsbedarf von hier: `coturn/coturn:latest` ist das einzige
|
|
ungepinnte Image (bereits in `gitops#47` notiert).
|