diff --git a/STATUS.md b/STATUS.md index 85d50ea..46da002 100644 --- a/STATUS.md +++ b/STATUS.md @@ -2,9 +2,9 @@ -## Issues (48 open, 53 closed) +## Issues (50 open, 53 closed) -Verteilung: M2 16 · M3 4 · M4 11 · M5 16 · M6 1 +Verteilung: M2 16 · M3 4 · M4 11 · M5 18 · M6 1 Bedeutung der Meilensteine: siehe [roadmap.md](roadmap.md). @@ -54,12 +54,13 @@ Bedeutung der Meilensteine: siehe [roadmap.md](roadmap.md). | [0100](docs/issues/0100-threadnet-web-13-asset-pfade-tragen-weiterhin-element-themes-e.md) | low | open | Asset-Pfade tragen weiterhin "element" (themes/element/…) | | [0101](docs/issues/0101-threadnet-call-4-kaputtes-paket-0-19-2-threadnet-6-in-der-regi.md) | low | open | Kaputtes Paket 0.19.2-threadnet.6 in der Registry — Herkunft ungeklärt | -### M5 (16) +### M5 (18) | Issue | Priorität | Status | Title | |---|---|---|---| | [0051](docs/issues/0051-cve-remediation-pass.md) | high | in-progress | CVE-Remediation-Pass: Schwachstellen-Report abarbeiten | | [0065](docs/issues/0065-gitops-25-k3s-api-security-hardening.md) | high | open | K3s API security hardening | +| [0109](docs/issues/0109-der-weg-vom-commit-ins-cluster-meldet-seinen-stillstand-nicht.md) | high | open | Der Weg vom Commit ins Cluster meldet seinen Stillstand nicht | | [0058](docs/issues/0058-gitops-14-web-application-firewall-waf.md) | medium | open | Web Application Firewall (WAF) | | [0059](docs/issues/0059-gitops-16-pod-security-admission-restricted.md) | medium | open | Pod Security Admission (Restricted) | | [0062](docs/issues/0062-gitops-21-renovate-dependabot-for-chart-and-image-updat.md) | medium | open | Renovate/Dependabot for chart and image updates | @@ -71,6 +72,7 @@ Bedeutung der Meilensteine: siehe [roadmap.md](roadmap.md). | [0069](docs/issues/0069-gitops-29-crowdsec-integration.md) | medium | open | CrowdSec integration | | [0070](docs/issues/0070-gitops-30-falco-runtime-monitoring.md) | medium | open | Falco runtime monitoring | | [0107](docs/issues/0107-aktives-konto-ohne-profil-zeile-faellt-nur-durch-beschwerde-auf.md) | medium | open | Ein aktives Konto ohne Profil-Zeile fällt nur durch eine Beschwerde auf | +| [0108](docs/issues/0108-erlaubnisliste-veraltet-still-wenn-das-chart-die-verdrahtung-ver.md) | medium | open | Eine Erlaubnisliste veraltet still, wenn das Chart die Verdrahtung verschiebt | | [0071](docs/issues/0071-gitops-31-trivy-image-scanning-for-cves.md) | low | open | Trivy image scanning for CVEs | | [0089](docs/issues/0089-gitops-58-eigene-images-sind-unsigniert-beim-deploy-pru.md) | low | open | Eigene Images sind unsigniert — beim Deploy prüft nichts die Herkunft | | [0090](docs/issues/0090-gitops-59-kein-kubernetes-audit-log-zugriffe-an-der-api.md) | low | open | Kein Kubernetes-Audit-Log — Zugriffe an der API werden nicht protokolliert | diff --git a/docs/aar/2026-08-21-mas-haproxy-netzregel.md b/docs/aar/2026-08-21-mas-haproxy-netzregel.md index f04a52f..8ae8420 100644 --- a/docs/aar/2026-08-21-mas-haproxy-netzregel.md +++ b/docs/aar/2026-08-21-mas-haproxy-netzregel.md @@ -88,9 +88,11 @@ ruft nach dem Sprung welchen anderen?" war eine `diff`-Zeile entfernt. - [x] `allow-ingress-haproxy` um `matrix-authentication-service` ergänzt (`533fcde`), über gitops, mit dem Grund im Manifest. - [x] Anmeldung wiederhergestellt und belegt: 4× `POST /oauth2/token` 200. -- [ ] **Offen:** Es gibt **keine Prüfung**, die eine Erlaubnisliste gegen die - tatsächliche Verdrahtung hält. Ein Vergleich „welcher Dienst ruft welchen" - gegen die Policies wäre aus dem Rendering ableitbar — gehört als Issue - vorgeschlagen, nicht hier entschieden. -- [ ] **Offen:** Beim nächsten Chart-Sprung gehört „interne Ziele vorher - vergleichen" in die Abnahmeliste, **vor** dem Ausrollen. +- [x] Beide offenen Punkte sind als + [#0108](../issues/0108-erlaubnisliste-veraltet-still-wenn-das-chart-die-verdrahtung-ver.md) + angelegt (M5, sorb am 2026-08-21 zugestimmt): die Abnahme-Zeile vor dem + Ausrollen als sofort wirksamer Teil, der abgeleitete Abgleich als der + eigentliche Befund. +- [ ] **Offen bis #0108 läuft:** Die Abnahme-Zeile „welche internen Ziele haben + sich verschoben?" gilt ab sofort für jeden Chart-Sprung — sie kostet einen + `diff` und braucht kein Werkzeug. diff --git a/docs/aar/2026-08-21-spiegel-ausfall.md b/docs/aar/2026-08-21-spiegel-ausfall.md index 1d063b8..48824fd 100644 --- a/docs/aar/2026-08-21-spiegel-ausfall.md +++ b/docs/aar/2026-08-21-spiegel-ausfall.md @@ -93,11 +93,12 @@ den Cluster gerettet und zugleich verdeckt, dass draußen etwas kaputt war. - [x] Spiegel wieder in Betrieb (leerer Commit `5507f13`), Flux zog nach. - [x] cert-manager in sieben Stufen bis v1.21.1 abgeschlossen, jede Stufe einzeln geprüft. -- [ ] **Offen:** Es gibt **keine Prüfung**, die einen hängenden Push-Spiegel - meldet. Er stand eine Stunde, und aufgefallen ist es nur, weil ich zufällig - in dem Fenster ausrollen wollte. Eine Regel auf `update_status != finished` - oder auf das Alter von `last_successful_update_at` wäre billig — gehört - als Issue vorgeschlagen, nicht hier entschieden. -- [ ] **Offen:** Ebenso wenig meldet etwas, wenn rohanas **öffentlicher** Weg - wegbricht, solange der private trägt. Der CoreDNS-Zeiger macht den Cluster - unempfindlich und damit blind. +- [x] Beide offenen Punkte sind als + [#0109](../issues/0109-der-weg-vom-commit-ins-cluster-meldet-seinen-stillstand-nicht.md) + angelegt (M5, priority high, sorb am 2026-08-21 zugestimmt). + ⚠️ **Anders zugeschnitten als hier vorgeschlagen:** Eine Regel auf + `update_status` hinge an der Verwaltungsoberfläche von git.lab — und die + ist bei uns Infrastruktur auf Zeit. Gemessen wird deshalb am Ende der + Kette: der Abstand zwischen kanonischem Stand und dem, was Flux angewandt + hat. Dieselbe Zahl deckt alle drei Glieder ab und überlebt den Austausch + eines davon. diff --git a/docs/issues/0107-aktives-konto-ohne-profil-zeile-faellt-nur-durch-beschwerde-auf.md b/docs/issues/0107-aktives-konto-ohne-profil-zeile-faellt-nur-durch-beschwerde-auf.md index 5bca590..2a68c1c 100644 --- a/docs/issues/0107-aktives-konto-ohne-profil-zeile-faellt-nur-durch-beschwerde-auf.md +++ b/docs/issues/0107-aktives-konto-ohne-profil-zeile-faellt-nur-durch-beschwerde-auf.md @@ -104,3 +104,25 @@ Konten, die *nie* telefoniert haben; `@clark` hatte 21 Einträge, sämtlich alt. Maßgeblich ist das **Datum des jüngsten** Tokens im Vergleich zu einem gesunden Konto. Wer diese Prüfung baut, sollte das Kürzel im Gedächtnis-Eintrag und im Runbook mitkorrigieren. + +## Nachtrag 2026-08-21: Die Ursache ist seit dem Abend behoben + +Das Weglassen der Profil-Zeile bei der Reaktivierung war **kein dauerhaftes +Synapse-Verhalten, sondern ein Fehler** — eingeschleppt in v1.150.0, behoben in +v1.157.0. Mit dem ESS-Sprung auf 26.8.0 läuft hier seit dem 2026-08-21 abends +**Synapse v1.158**. Der Erzeuger neuer Fälle ist damit weg. + +⚠️ Das ergänzt diesen Text, es widerlegt ihn nicht — und der Abschnitt „Die +Ursache abstellen" oben bleibt als das stehen, was zum Zeitpunkt des Schreibens +richtig war. Was sich ändert, ist die **Dringlichkeit**, nicht der Zweck: + +- Der Fund bleibt sinnvoll für Konten, die **vor** dem Sprung beschädigt wurden. + Sie heilen nicht von selbst; `@clark` fiel vier Tage lang niemandem auf. +- Er bleibt sinnvoll als **Rückfallprüfung**. Der Fehler kam einmal durch ein + Upgrade herein und kann durch ein weiteres wiederkommen — dann wieder + unbemerkt, weil Anmeldung und Chat weiterlaufen. +- Was **entfällt**, ist die Annahme, jeder Verwaltungsvorgang erzeuge laufend + neue Fälle. Die Prüfung ist damit eher Netz als Dauerbedarf. + +Wer sie baut, sollte das im Zuschnitt berücksichtigen: eine tägliche Stichprobe +ist dafür immer noch das richtige Maß, ein aufwendigerer Bau nicht. diff --git a/docs/issues/0108-erlaubnisliste-veraltet-still-wenn-das-chart-die-verdrahtung-ver.md b/docs/issues/0108-erlaubnisliste-veraltet-still-wenn-das-chart-die-verdrahtung-ver.md new file mode 100644 index 0000000..5207165 --- /dev/null +++ b/docs/issues/0108-erlaubnisliste-veraltet-still-wenn-das-chart-die-verdrahtung-ver.md @@ -0,0 +1,108 @@ +--- +type: issue +id: "0108" +status: open +created: 2026-08-21 +milestone: M5 +priority: medium +area: security +host: matrix +projekt: gitops +related: + - "docs/aar/2026-08-21-mas-haproxy-netzregel.md" + - "docs/issues/0088-gitops-56-networkpolicy-ausgehender-verkehr-ist-unbesch.md" + - "docs/adr/0026-pruefziele-werden-abgeleitet-nicht-gepflegt.md" +--- + +# Eine Erlaubnisliste veraltet still, wenn das Chart die Verdrahtung verschiebt + +Unsere NetworkPolicies zählen auf, **welcher Dienst welchen anrufen darf**. Die +Liste ist eine Momentaufnahme der Verdrahtung zu dem Zeitpunkt, an dem sie +geschrieben wurde. Verschiebt ein Chart-Upgrade ein internes Ziel, ist die Liste +falsch — ohne dass sich in unseren Manifesten eine Zeile geändert hätte und ohne +dass irgendetwas es meldet. Unter `default-deny` ist das kein Schönheitsfehler, +sondern ein Ausfall. + +## Einmal eingetreten, am Tag der Regel selbst + +Am 2026-08-21 wurde vormittags `allow-ingress-haproxy` angelegt (#0088), mit drei +erlaubten Quellen: `kube-system`, `draupnir`, `clamav-http-scanner`. Abends hob +ESS von 26.4.0 auf 26.8.0 — und verschob dabei den Synapse-Endpunkt des +Authentifizierungsdienstes vom direkten Dienst `matrix-stack-synapse-main` auf +den haproxy-Dienst `matrix-stack-synapse`. + +MAS stand nicht auf der Liste. Ergebnis: `Connection refused` auf +`upsert_device`, `POST /oauth2/token` → **500**, **keine Anmeldung für niemanden**, +rund zwölf Minuten lang. Hergang und Messung im +[AAR](../aar/2026-08-21-mas-haproxy-netzregel.md). + +⚠️ **Es war vorab sichtbar.** Beide Chart-Fassungen lagen als `helm template`- +Rendering vor und wurden verglichen — aber nur daraufhin, ob *unsere* +Anpassungen überleben. Die Frage „welches interne Ziel ruft nach dem Sprung +welches andere?" stand im selben Rendering und wurde nicht gestellt. + +## Warum ein zweites Mal wahrscheinlich ist + +Der Auslöser ist nichts Außergewöhnliches, sondern der Normalfall: **jedes** +Chart-Upgrade darf interne Ziele verschieben, das ist keine Bruchänderung im +Sinne des Herausgebers. Betroffen sind bei uns alle Namespaces mit +`default-deny` — `matrix`, `authentik`, `monitoring` — und die Liste der +Erlaubnisse wächst mit #0088 weiter. + +Hinzu kommt: **Der Fehler sieht nicht nach seiner Ursache aus.** „Anmeldung +kaputt nach Upgrade" führt zuerst zum Chart, zum Schema, zur Konfiguration — die +Netzregel von vor sechs Stunden ist der letzte Ort, an dem man sucht. Genau +deshalb kostete er beim ersten Mal Zeit, obwohl die Behebung eine Zeile war. + +## Was zu tun ist + +**Zwei Dinge, getrennt zu bewerten — das billige zuerst.** + +### 1. Eine Zeile in der Abnahmeliste, vor dem Ausrollen + +Vor jedem Chart-Sprung gehört gefragt: *welche internen Ziele haben sich +verschoben?* Die Antwort steht in den beiden Renderings, die für den Sprung +ohnehin erzeugt werden. Das kostet einen `diff` und hätte diesen Ausfall +verhindert. Es ist keine Automatisierung, sondern eine Zeile im Vorgehen — +und es ist der Teil, der sofort wirkt. + +### 2. Ein Abgleich, der die Liste gegen die Wirklichkeit hält + +Der eigentliche Befund ist, dass **nichts** die Erlaubnisliste gegen die +tatsächliche Verdrahtung hält. Die Richtung dafür steht bereits fest, sie ist +dieselbe wie bei den CVE-Prüfzielen: **ableiten statt pflegen** +([ADR-0026](../adr/0026-pruefziele-werden-abgeleitet-nicht-gepflegt.md)). +Aus dem Rendering ist herleitbar, welcher Dienst welchen internen Namen anruft +— das sind konfigurierte Endpunkte in ConfigMaps, Secrets und Env-Variablen. +Diese abgeleitete Menge gegen die Policies zu halten, ergibt zwei Zahlen: +Ziele ohne Erlaubnis und Erlaubnisse ohne Ziel. + +⚠️ **Die Ableitung ist der schwierige Teil und darf nicht im Issue entschieden +werden.** Endpunkte stehen nicht an einem Ort und nicht in einer Form; ein Teil +liegt in SOPS-Secrets, die das Rendering gar nicht zeigt. Ob die Ableitung +belastbar genug wird, um daraus einen Alarm zu bauen, oder ob sie nur einen +Bericht rechtfertigt, gehört ins Design-Gate. + +## Abnahmekriterien + +1. Ein verschobenes internes Ziel wird **vor dem Ausrollen** bemerkt, nicht + durch einen Nutzer nach dem Ausrollen. +2. Der Abgleich wird **rot vorgeführt**, nicht grün behauptet: eine Erlaubnis + testweise entfernen, Meldung erscheint, Erlaubnis zurück. +3. ⚠️ Ein Rendering, aus dem sich **nichts** ableiten ließ, meldet einen + **Fehler** — nicht „0 fehlende Erlaubnisse". Genau diese Verwechslung ist die + Fehlerklasse + [meldet-erfolg-ist-aber-blind](../wiki/stolpersteine/meldet-erfolg-ist-aber-blind.md). +4. Der Fund nennt Quelle, Ziel und Port, damit die Regel ohne weitere Suche + ergänzt werden kann. + +## Nicht Teil davon + +- **Die Egress-Richtung.** #0088 hat den ausgehenden Verkehr geschlossen; hier + geht es um die eingehende Erlaubnisliste. Ob derselbe Abgleich beide + Richtungen trägt, ist eine Frage fürs Design, keine Zusage. +- **Policies neu entwerfen.** Das Modell aus #0088 bleibt; hier kommt eine + Prüfung dazu, keine andere Regelform. +- **Namespaces ohne `default-deny`.** Wo nichts gesperrt ist, veraltet auch + keine Erlaubnis. +- Das Homelab und `game-operating`. diff --git a/docs/issues/0109-der-weg-vom-commit-ins-cluster-meldet-seinen-stillstand-nicht.md b/docs/issues/0109-der-weg-vom-commit-ins-cluster-meldet-seinen-stillstand-nicht.md new file mode 100644 index 0000000..75bf683 --- /dev/null +++ b/docs/issues/0109-der-weg-vom-commit-ins-cluster-meldet-seinen-stillstand-nicht.md @@ -0,0 +1,111 @@ +--- +type: issue +id: "0109" +status: open +created: 2026-08-21 +milestone: M5 +priority: high +area: infrastructure +host: cfgmon +related: + - "docs/aar/2026-08-21-spiegel-ausfall.md" + - "docs/issues/0088-gitops-56-networkpolicy-ausgehender-verkehr-ist-unbesch.md" + - "docs/issues/0051-cve-remediation-pass.md" +--- + +# Der Weg vom Commit ins Cluster meldet seinen Stillstand nicht + +Zwischen „gepusht" und „läuft" liegen bei uns drei Glieder: das kanonische Repo, +der Push-Spiegel, Flux. **Fällt eines aus, meldet nichts es.** Alles sieht +weiter gesund aus: der Push gelingt, die Flux-Kustomization steht auf +`Ready=True`, die Quelle auf `Ready=True` — nur eben auf einem alten Stand. + +Das ist die Fehlerklasse +[artefakt-existiert-liefert-aber-nichts](../wiki/stolpersteine/artefakt-existiert-liefert-aber-nichts.md): +Jedes Einzelteil bezeugt seine Gesundheit, und die Kette liefert trotzdem nicht. + +## Am 2026-08-21 stand die Strecke eine Stunde + +Beim gestuften cert-manager-Upgrade (#0051) kam Stufe 2 nie im Cluster an. Die +Kette, Glied für Glied gemessen, steht im +[AAR](../aar/2026-08-21-spiegel-ausfall.md); die Kurzfassung: Der Push-Spiegel +stand auf `to_retry`, weil der öffentliche Web-Zugang zum Spiegelziel während +Firewall-Arbeiten zu war. **Aufgefallen ist es nur, weil ich zufällig in diesem +Fenster ausrollen wollte.** + +Zwei Umstände machen es schlimmer, als es klingt: + +- **Der Spiegel erholt sich nicht von selbst**, wenn das Ziel zurückkommt. Die + Wartezeit-Erhöhung überlebt Aus- und Wiedereinschalten; es braucht ein echtes + Push-Ereignis. Ein unbemerkter Ausfall bleibt also auch nach dem Ende seiner + Ursache bestehen. +- ⚠️ **Der Cluster hat vom Ausfall nichts gemerkt**, weil seit #0088 ein + CoreDNS-Eintrag den Spiegel-Namen clusterintern auf die private Adresse zeigt. + Der Entwurf dazu warnte vor dem *umgekehrten* Fall; eingetreten ist das + Spiegelbild — öffentlich tot, privat gesund. Der Zeiger hat den Cluster + gerettet und **zugleich verdeckt**, dass draußen etwas kaputt war. + +## Warum das mehr ist als eine Unbequemlichkeit + +Solange die Strecke steht, sind **alle Sicherheitsbehebungen wirkungslos**, die +über sie ausgeliefert werden — und niemand erfährt es. Genau das ist der Zustand +von #0051: Ein Commit mit −14 CRITICAL im Repo und ein Cluster, der ihn nicht +kennt, sehen von außen identisch aus. Was hier fehlt, ist keine Bequemlichkeit, +sondern die Aussage „das Ausgerollte entspricht dem Beschlossenen". + +Hinzu kommt eine zweite Falle für gestufte Vorhaben: Läge der Spiegel und würden +mehrere Stufen auf Vorrat gepusht, wendete Flux nach der Erholung nur den +**letzten** Commit an — und überspränge Zwischenstufen, was cert-manager +ausdrücklich verbietet. + +## Was zu tun ist + +**Am Ende der Kette messen, nicht in ihrer Mitte.** + +Der naheliegende Griff wäre eine Regel auf den Spiegel-Zustand des kanonischen +Repos (`update_status != finished`, oder das Alter des letzten Erfolgs). Der ist +billig — aber er hängt an der Verwaltungsoberfläche genau der Komponente, die +bei uns **Entwicklungs-Infrastruktur auf Zeit** ist. Ein Dauer-Alarm auf eine +Schnittstelle, die verschwinden soll, ist ein Artefakt am falschen Ort. + +Belastbar und unabhängig davon, welches Glied bricht, ist der **Abstand zwischen +dem kanonischen Stand und dem, was Flux angewandt hat**. Diese eine Zahl deckt +alle drei Ausfälle ab — Repo, Spiegel, Flux — und überlebt es, wenn ein Glied +ausgetauscht wird. Sie ist auch die Zahl, die uns tatsächlich interessiert: +nicht „ist der Spiegel gesund", sondern „ist ausgerollt, was beschlossen wurde". + +Zusätzlich, und davon getrennt zu bewerten: **eine Prüfung des öffentlichen Wegs +zum Spiegelziel von außen.** Der interne Zeiger macht den Cluster gegen dessen +Ausfall unempfindlich und damit blind; nur eine Messung, die den privaten Pfad +nicht benutzt, sieht es. + +⚠️ **Was der Vergleich braucht, ist noch offen:** Er muss das kanonische Repo +lesen können, und er läuft in der Überwachung, nicht im Cluster. Ob das ein +Lesezugriff, ein bestehender Exporter oder etwas Drittes wird, gehört ins +Design-Gate — samt der Frage, welche Verzögerung normal ist und ab wann sie +Alarm ist. + +## Abnahmekriterien + +1. Ein Commit, der nach **einer benannten Frist** nicht im Cluster angewandt + ist, führt zu einer Meldung im Wartungsraum — unabhängig davon, welches Glied + der Kette ihn aufgehalten hat. +2. Die Prüfung wird **rot vorgeführt**: Strecke gezielt unterbrechen, Meldung + erscheint, Strecke zurück, Meldung geht weg. +3. ⚠️ Ein Vergleich, der den kanonischen Stand **nicht lesen konnte**, meldet + einen **Fehler** — nicht „kein Rückstand". Sonst sieht ein blinder Prüfer + genauso aus wie eine gesunde Strecke + ([meldet-erfolg-ist-aber-blind](../wiki/stolpersteine/meldet-erfolg-ist-aber-blind.md)). +4. Der öffentliche Weg zum Spiegelziel wird von außen geprüft und meldet sich, + **ohne** dass der interne Zeiger die Antwort liefert. + +## Nicht Teil davon + +- **Den Spiegel ersetzen oder die Topologie ändern.** Dass git.lab kanonisch ist + und rohana die Flux-Quelle, bleibt so. Hier kommt eine Messung dazu. +- **Automatisches Wiederanstoßen** eines hängenden Spiegels. Erst sehen, dann + entscheiden, ob etwas von selbst heilen soll — ein Automatismus, der einen + unbemerkten Ausfall unbemerkt behebt, nimmt nur die Meldung weg. +- **Die Regel „nicht auf Vorrat pushen"** bei gestuften Upgrades. Die steht im + AAR und ist Vorgehen, nicht Werkzeug. +- Das Homelab und `game-operating`.