From c4e440dc1d88222a3cb043b8983be1c4002a33b6 Mon Sep 17 00:00:00 2001 From: Thore Cimbal Date: Fri, 21 Aug 2026 12:00:00 +0000 Subject: [PATCH] docs: slices 2 to 4 for #0106, and the handover checklist The four rules, the derived target set and the deletion of orphaned reports are built and checked as far as they can be without the host. What remains is a deploy, and the first three items of its checklist are numbers already known by hand: 24 missing, 2 orphaned, coverage near 0.52. If those disagree the derivation is wrong. Slice 4 records the more useful failure. Its test first rebuilt the loop instead of loading it, which would have stayed green while the shipped file was broken. Loading the real function exposed within a single run that the script set its paths unconditionally and ignored the environment. --- docs/design/2026-08-21-cve-ziele-ableiten.md | 90 ++++++++++++++++++++ docs/ledger/2026-08-21-cve-ziele-ableiten.md | 10 +++ 2 files changed, 100 insertions(+) diff --git a/docs/design/2026-08-21-cve-ziele-ableiten.md b/docs/design/2026-08-21-cve-ziele-ableiten.md index cf1f073..117f46a 100644 --- a/docs/design/2026-08-21-cve-ziele-ableiten.md +++ b/docs/design/2026-08-21-cve-ziele-ableiten.md @@ -509,3 +509,93 @@ damit beim Umschalten in Slice 3 kein Neustart-Rennen entsteht. Zahl. `cve_targets_missing` muss **24** ergeben, `cve_targets_orphaned` **2**, `cve_target_coverage_ratio` **≈ 0,52** — die Werte der Handmessung. Weicht sie ab, ist die Herleitung falsch. + +### Slice 2 — durchgeführt, Commit `b989987` · Status: **DONE** + +**Abweichung von Gate 3: vier Regeln statt drei.** Die vierte +(`CveTargetsNoneDesired`) deckt einen Fall ab, den die anderen drei **nicht +sehen**: Alle Quellen antworten sauber, aber leer. Dann ist `missing` 0 (leere +Soll-Menge), die Frische-Stempel sind aktuell — und es wird nichts mehr +gescannt. `test_targets.py` führt genau diesen Fall bereits als *„leere Menge +ist NICHT dasselbe wie Erfolg"*; die Regel gehört dazu. + +**Erste Regeltests in diesem Stack überhaupt** (`prometheus/alerts_test.yml`). +Je Regel ein Fall, in dem sie feuern **muss**, und einer, in dem sie schweigen +**muss** — sonst ließe sich eine Regel, die immer feuert, von einer richtigen +nicht unterscheiden. `promtool check rules`: 20 Regeln, `promtool test rules`: +SUCCESS. + +**Zwei Sabotagen belegen, dass die Tests beißen:** +- Schwelle von `CveTargetSourceStale` auf `999999999` → der erwartete Alarm + bleibt aus, Test rot. +- Karenz `for: 6h` bei `CveTargetsMissing` entfernt → Alarm feuert bei 5 h, wo + der Test Stille verlangt, Test rot. + +Die Karenz ist damit nachweislich tragend und keine Zierde: Eine volle Runde +über ~65 Images dauert, nach einem Ausrollen ist die Lücke vorübergehend echt. + +**Dashboard:** Deckung und ungeprüfte Images in die zwei freien Plätze der +obersten Reihe, Quellen-Frische als Balken **unten** angehängt — kein +bestehendes Panel verschiebt sich. Geprüft: JSON lesbar, IDs eindeutig, keine +doppelt belegte Position. + +### Slice 3 — durchgeführt, Commit `386b65a` · Status: **DONE** + +`images.txt` ist **gelöscht** — Kriterium 1 erfüllt. Der Scanner liest +`/targets/targets.txt`. + +Ohne brauchbare Liste tut die Schleife nichts und versucht es nach **einer +Minute** erneut statt nach 24 Stunden: Nach einem Ausrollen schreibt der +Exporter die Datei erst beim nächsten Scrape. Belegt mit gestelltem Trivy: ohne +Liste ausgesetzt, leere Liste ausgesetzt, mit Liste genau die zwei Einträge +gescannt und die Kopfzeile ignoriert. + +### Slice 4 — durchgeführt, Commit `07875ba` · Status: **DONE** + +Berichte ohne Ziel werden entfernt — **nur** gegen eine erfolgreich gelesene +Liste. Der Fall vom 2026-08-20 (`threadnet-web:v0.3.0` meldet HIGH-CVEs, obwohl +das Image nirgends läuft) ist als eigener Testfall geführt. + +⚠️ **Der Test hat sich erst selbst als wertlos entlarvt.** Die erste Fassung +**baute** die Schleifenlogik nach, statt sie zu prüfen — und wäre grün +geblieben, während die ausgelieferte Datei kaputt ist. Nach dem Umbau auf +*Laden* der echten `runde()` (Ladewache `SCAN_LOOP_NUR_LADEN`) fiel binnen eines +Laufs auf, dass `scan-loop.sh` seine Pfade **fest** setzte und die Umgebung +ignorierte. Ein nachgebauter Test prüft den Nachbau. + +⚠️ **Zwei eigene Fehler, hier behoben:** +1. Der Treiber lautete `runde || sleep A && sleep B`. Das gruppiert + links-assoziativ zu `(runde || sleep A) && sleep B` — bei fehlender Liste + hätte er die Wartezeit **und danach das volle Tagesintervall** geschlafen, + also genau das, was die kurze Wartezeit verhindern soll. +2. Pfade fest verdrahtet, obwohl der Exporter sie längst aus der Umgebung nimmt. + +**Gegenprobe:** Wache entfernt → „Berichte unberührt" fällt von **2 auf 0**, der +gesamte Bestand wäre gelöscht. Der Test fängt es. + +### Übergabe — was der Ausrollende prüfen muss + +Vor der Übergabe belegt (ohne Host): `py_compile` sauber · **21** Python- +Zusicherungen grün · **13** Shell-Zusicherungen grün · `sh -n` beide · +`docker compose config` grün · `promtool check rules` 20 Regeln · +`promtool test rules` SUCCESS. + +⚠️ **`docker compose up -d` genügt nicht** (AAR 2026-08-01, Befund 2): +`--force-recreate` für `cve-exporter` und `cve-scan`, und die Konfiguration +**im Container** prüfen, nicht auf der Platte. + +| # | Prüfung | Erwartet | +|---|---|---| +| 1 | `cve_targets_missing` **vor** der ersten neuen Runde | **24** — die Handmessung | +| 2 | `cve_targets_orphaned` vorher | **2** | +| 3 | `cve_target_coverage_ratio` vorher | **≈ 0,52** | +| 4 | `docker exec cve-scan cat /targets/targets.txt \| wc -l` | ~65 | +| 5 | Nach einer vollen Runde: `missing` / `orphaned` | **0** / **0** | +| 6 | `threadnet-web:v0.6.0` hat einen Bericht | ja | +| 7 | `threadnet-web:v0.3.0` hat **keinen** mehr | ja | +| 8 | Zahl der Meldungen im Security-Raum in der ersten Runde | **gemessen notieren** (erwartet ≤ 65, gestern waren es 12) | +| 9 | Dauer der ersten vollen Runde | **gemessen notieren** | +| 10 | `cve_target_source_stale` je Quelle | < 3600 | + +**Weicht 1–3 ab, ist die Herleitung falsch — nicht die Handmessung überholt.** +Dann nicht weiterfahren, sondern den Unterschied ausmessen. diff --git a/docs/ledger/2026-08-21-cve-ziele-ableiten.md b/docs/ledger/2026-08-21-cve-ziele-ableiten.md index dc5fcd2..28f349c 100644 --- a/docs/ledger/2026-08-21-cve-ziele-ableiten.md +++ b/docs/ledger/2026-08-21-cve-ziele-ableiten.md @@ -23,6 +23,9 @@ related: | slice | commit | status | note | |---|---|---|---| +| 4 | 07875ba | DONE | Berichte ausgefallener Ziele entfernt; Test laedt die echte runde() statt sie nachzubauen. | +| 3 | 386b65a | DONE | Scanner liest die abgeleitete Menge, images.txt geloescht (Kriterium 1). | +| 2 | b989987 | DONE | Vier Regeln statt drei; erste Regeltests im Stack, zwei Sabotagen belegen sie. | | 1 | 27770b6 | DONE_WITH_CONCERNS | Herleitung + Metriken, nur beobachtend; Abnahme (24/2/0,52) erst nach dem Ausrollen messbar. | ## Ladder @@ -73,3 +76,10 @@ von `v0.8.0` statt `v0.10.0`) — der Test korrigierte meinen Denkfehler, nicht den Code. Und der erste Compose-Eingriff ging von falscher Einruckung aus; die `assert`-Zeile davor hat verhindert, dass eine halb angewandte Aenderung geschrieben wurde. Beide Male war die Kontrolle billiger als der Schaden. + +**Der Test von Slice 4 war zuerst wertlos, und das war lehrreich.** Er baute die +Schleifenlogik NACH, statt sie zu laden - und waere gruen geblieben, waehrend +die ausgelieferte Datei kaputt ist. Nach dem Umbau auf Laden der echten +`runde()` fiel binnen eines Laufs auf, dass `scan-loop.sh` seine Pfade fest +setzte und die Umgebung ignorierte. Wer eine Nachbildung prueft, prueft die +Nachbildung.