docs: slice 4 — reasons at the rule, ADR-0025, and MAS resolved

The five remaining open workloads now carry their reason at the selector
rather than in an issue. An unexplained open egress reads as neglect, and
whoever reads the rule should not have to guess whether it is intent or
leftover.

ADR-0025 decides the direction the whole undertaking kept running into: pin
what holds, prefer a private path over a public one, allow a small provider
block where a /32 would break silently, and leave a CDN target open with
the reason at the rule. It also records what the decision does not achieve
- traffic to the node's own address escapes the policy entirely.

MAS is resolved and turns out to be restrictable. Its configuration is not
in the repo and its container is distroless, so it was read from the
running process through /proc in an ephemeral container: the homeserver by
internal service name, Authentik by public name - and public names resolve
to the node address, which no policy covers. The reason for keeping it
broad is therefore gone.

It is still not restricted. The sign-off is a real login, which this
session cannot perform, and a mistake there hits authentication. The
manifest now says exactly that: what is open is the acceptance, not the
analysis.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F2Q4Ri8NGwyTZzScvKnWFM
This commit is contained in:
Thore Cimbal
2026-08-21 12:00:00 +00:00
co-authored by Claude Opus 5
parent c7f7e73c6b
commit 4f6b8d79c3
3 changed files with 135 additions and 1 deletions
+2 -1
View File
@@ -91,7 +91,7 @@ Bedeutung der Meilensteine: siehe [roadmap.md](roadmap.md).
|---|---|---|
| [2026-08-21-egress-vollstaendig](docs/design/2026-08-21-egress-vollstaendig.md) | gate-4 | Design: Den ausgehenden Verkehr zu Ende schließen (#0088) |
## ADRs (24)
## ADRs (25)
| ADR | Status | Title |
|---|---|---|
@@ -119,6 +119,7 @@ Bedeutung der Meilensteine: siehe [roadmap.md](roadmap.md).
| [0022](docs/adr/0022-upstream-anschluss-durch-einmaligen-merge.md) | accepted | ADR-0022: Anschluss an Upstream durch einen einmaligen Merge, nicht durch einen geteilten Graft |
| [0023](docs/adr/0023-fremdhistorie-von-der-git-hygiene-ausnehmen.md) | accepted | ADR-0023: Fremde Historie von der Git-Hygiene ausnehmen — erklärt, nicht global |
| [0024](docs/adr/0024-drei-framework-dateien-erklaert-erweitert.md) | accepted | ADR-0024: Drei Framework-Dateien sind erklärt erweitert — Diff-Referenz statt Byte-Vergleich |
| [0025](docs/adr/0025-egress-ausnahmen-als-cidr-ausser-hinter-cdn.md) | proposed | ADR-0025: Egress-Ausnahmen werden als CIDR gepinnt — außer hinter einem CDN |
## Open AARs (6)
@@ -0,0 +1,92 @@
---
type: adr
id: "0025"
status: proposed
date: 2026-08-21
supersedes: null
superseded_by: null
related:
- "docs/issues/0088-gitops-56-networkpolicy-ausgehender-verkehr-ist-unbesch.md"
- "docs/design/2026-08-21-egress-vollstaendig.md"
---
# ADR-0025: Egress-Ausnahmen werden als CIDR gepinnt — außer hinter einem CDN
## Kontext
Der Cluster war eingehend dicht und ausgehend offen. Beim Schließen (#0088)
stellte sich dieselbe Frage bei jeder Arbeitslast: Wohin darf sie, und wie
schreibt man das auf?
Zwei Randbedingungen sind nicht verhandelbar. **NetworkPolicies kennen nur
CIDRs** — k3s setzt Standard-Policies durch, es gibt keine DNS- oder
FQDN-Regeln. Und **ein Ziel hinter einem CDN hat keine feste Adresse**:
`database.clamav.net` löst auf Cloudflare auf, mit wechselnden Adressen.
Daraus entsteht ein Konflikt, der sich nicht wegentscheiden lässt: Die
einzige ausdrückbare Regel ist eine Adressliste, und für manche Ziele gibt
es keine haltbare.
## Optionen
**A: Alles pinnen, auch CDN-Ziele.** Konsequent und einheitlich. Der Preis
ist die Ausfallart: Rotiert der Anbieter, bricht der Zugriff — und zwar
**still**. Bei ClamAV hieße das: Signaturen veralten, der Dienst läuft
weiter, kein Alarm. Genau die Fehlerklasse, gegen die dieses Projekt seine
Prüflandschaft gebaut hat.
**B: Für CDN-Ziele den Anbieterbereich erlauben.** Keine stille Ausfallart.
Cloudflare steht aber vor einem erheblichen Teil des Internets — die Regel
sähe nach Einschränkung aus und wäre praktisch keine. Eine Regel, die
Sicherheit vortäuscht, ist schlechter als eine erklärte Ausnahme.
**C: CDN-Ziele intern spiegeln.** Technisch das Beste: der Dienst bekommt
ein festes, internes Ziel. Kostet eigene Infrastruktur mit eigenem Betrieb
und eigener Ausfallart, und die will erst gebaut sein.
**D: Pinnen, wo es hält — sonst Ausgang offen lassen und begründen.**
Ehrlich und ohne stille Ausfallart. Der Preis ist Ungleichbehandlung: Einige
Arbeitslasten bleiben offen, und das muss aushaltbar begründet sein.
## Entscheidung
**Option D.**
- **Ein Ziel mit haltbarer Adresse wird gepinnt**, so eng wie möglich —
Host und Port. Beispiele aus #0088: Storage Box als `/32:23`, der
operating-Host als `/32` auf zwei Ports.
- **Ein privater Weg schlägt einen öffentlichen.** Ist ein Ziel intern
erreichbar und dort TLS-sauber, zeigt der Name intern dorthin und die
Regel erlaubt die private Adresse. So geschehen bei rohana.
- **Ein kleiner Anbieterbereich ist zulässig**, wo eine Handvoll Adressen
desselben Betreibers rotiert und ein `/32` sonst still bräche —
`smtp.ionos.de` als `/27`. Die Grenze ist Größenordnung **und** Zweck: die
Mail-Infrastruktur eines Anbieters ja, ein CDN vor dem halben Internet
nein.
- **Hinter einem CDN bleibt der Ausgang offen, mit Begründung im Manifest.**
Nicht in einem Issue, nicht in einer ADR allein: **an der Regel selbst**,
wo der nächste Leser sie sucht.
- **Nicht tragende Ziele werden nicht erlaubt**, und dass sie scheitern,
steht dabei. Beispiel: Authentiks Versionsprüfung.
## Konsequenzen
*Einfacher.* Jede Ausnahme trägt ihren Grund dort, wo sie steht. Wer eine
Regel liest, muss nicht raten, ob sie Absicht oder Rest ist. Und keine
Ausnahme hat eine stille Ausfallart — was bricht, bricht sichtbar.
*Schwerer.* Die Regeln sind nicht einheitlich, und Einheitlichkeit ist das,
was man beim Überfliegen sucht. Wer nur die Manifeste zählt, sieht offene
Ausgänge und hält sie für Nachlässigkeit; die Begründung muss er lesen.
*Was offen bleibt.* Ein interner Spiegel für Signaturen (Option C) bleibt
der bessere Weg für ClamAV und ist ausdrücklich **nicht** verworfen, nur
vertagt. Wer ihn baut, löst die einzige verbliebene breite Ausnahme, die
kein Dienstmerkmal ist.
⚠️ *Was diese Entscheidung nicht leistet.* Verkehr zur eigenen
Knoten-Adresse unterliegt der Policy nicht — am 2026-08-21 aus zwei
eingeschränkten Arbeitslasten gemessen. Jede „nur intern" laufende
Arbeitslast erreicht weiterhin, was über den Ingress veröffentlicht ist.
Das ist eine Eigenschaft der Durchsetzung, mit einer NetworkPolicy nicht zu
schließen, und gehört zu jeder Aussage über diese Regeln dazu.
@@ -521,4 +521,45 @@ das sind genau die fünf der Klasse C.
**Status:** `DONE`
> **STOP — Slice-Review.** Freigegeben durch sorb, 2026-08-21.
### Slice 4 — Klasse C begründen, und MAS geklärt
- [x] **Gründe an die Regel schreiben** — files:
`apps/production/networkpolicy.yaml` — action: für jede der fünf offenen
Arbeitslasten steht am Selektor, warum — done.
- [x] **Die Richtung entscheiden** — files:
`docs/adr/0025-egress-ausnahmen-als-cidr-ausser-hinter-cdn.md` — done,
`status: proposed`.
- [x] **MAS klären** — action: Konfiguration aus dem laufenden Prozess lesen
— done, Ergebnis unten.
**Warum die Gründe ins Manifest gehören und nicht ins Issue:** Ein offener
Ausgang, den niemand erklärt, liest sich als Nachlässigkeit. Wer die Regel
liest, soll nicht raten müssen, ob sie Absicht oder Rest ist.
**MAS ist geklärt — und einschränkbar.** Der Container ist distroless, die
Konfiguration steht nicht im Repo; gelesen wurde sie über einen ephemeren
Container durch `/proc/<pid>/root` des laufenden Prozesses:
```
http://matrix-stack-synapse-main.matrix.svc.cluster.local.:8008
https://auth.axion1337.chat/application/o/matrix/
```
Der Homeserver über den **internen** Service-Namen, Authentik über den
**öffentlichen** — und der löst auf die Knoten-Adresse auf, die der Policy
ohnehin nicht unterliegt (Gate-3-Fund). Damit fällt der Grund weg, aus dem
MAS in Klasse C stand.
⚠️ **Trotzdem nicht eingebaut.** Gate 3 hat MAS „aus Vorsicht" dort
belassen, weil ein Irrtum die Anmeldung trifft. Die Vorsicht ist durch die
Messung kleiner geworden, aber nicht gegenstandslos: Die Abnahme dafür ist
ein echter Login, und den kann diese Sitzung nicht durchführen. Das Manifest
sagt jetzt genau das — offen ist die **Abnahme**, nicht die Analyse.
**Status:** `DONE_WITH_CONCERNS` — der geplante Umfang ist fertig; eine
Arbeitslast ist nachweislich einschränkbar und bleibt es aus einem Grund,
den nur sorb ausräumen kann.
> **STOP — Slice-Review.**