From d5b59eb5e91e50598c5bf2640ec938a33ecd4371 Mon Sep 17 00:00:00 2001 From: Thore Cimbal Date: Fri, 21 Aug 2026 12:00:00 +0000 Subject: [PATCH] =?UTF-8?q?netpol:=20wave=203=20=E2=80=94=20the=20two=20na?= =?UTF-8?q?mespaces=20the=20issue=20never=20mentioned=20(#0088)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit authentik and monitoring carried only the metadata block, so every pod there could reach anything. Both now follow the pattern from matrix: the broad policy keeps an exclusion list and stays as the catch-all, and each workload gets a rule of its own. The destinations were read, not guessed. Alloy ships to 10.0.0.3 on 3100 and 9090 - taken from its running configuration. Authentik sends mail through smtp.ionos.de:587, and that is load-bearing rather than optional: the blueprints use password recovery and invitations by mail. The database and kube-state-metrics speak to nobody outside. Mail gets a /27 rather than two /32. The name resolves to .97 and .113 today, both in the provider's own block; a third address would break mail with nobody watching a rule, and thirty-two addresses of one provider's mail infrastructure is the smaller price. That is the opposite call to ClamAV on purpose - this is not a CDN in front of half the internet. Deliberately not allowed: authentik's version check. It sits behind Cloudflare with rotating addresses and nothing depends on it, so the call fails and gets logged. The manifest says so, because whoever finds that error later should know it is intended. Congruence checked in both namespaces before pushing: excluded and narrowly ruled are the same sets. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01F2Q4Ri8NGwyTZzScvKnWFM --- apps/authentik/networkpolicy.yaml | 123 ++++++++++++++++++++++++++++- apps/monitoring/networkpolicy.yaml | 79 +++++++++++++++++- 2 files changed, 200 insertions(+), 2 deletions(-) diff --git a/apps/authentik/networkpolicy.yaml b/apps/authentik/networkpolicy.yaml index 459b646..abef47a 100644 --- a/apps/authentik/networkpolicy.yaml +++ b/apps/authentik/networkpolicy.yaml @@ -120,7 +120,18 @@ metadata: name: egress-block-metadata namespace: authentik spec: - podSelector: {} + # Waehlt alle Pods AUSSER denen mit eigener, engerer Regel (#0088). + # Bleibt als Auffangnetz: Eine kuenftige Arbeitslast ohne eigene Policy + # landet hier - Metadaten gesperrt, Rest offen - statt voellig ungeregelt. + # ⚠️ Der Ausschluss MUSS hier stehen: NetworkPolicies sind additiv. + podSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: NotIn + values: + - authentik + - postgresql + - authentik-backup policyTypes: - Egress egress: @@ -147,3 +158,113 @@ spec: cidr: 0.0.0.0/0 except: - 169.254.0.0/16 +--- +# Welle 3 (#0088): Authentik-Namespace, enge Regeln je Arbeitslast. +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: egress-nur-intern + namespace: authentik +spec: + # Die Datenbank spricht mit niemandem ausserhalb des Clusters. + podSelector: + matchLabels: + app.kubernetes.io/name: postgresql + policyTypes: + - Egress + egress: + - to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: kube-system + ports: + - protocol: UDP + port: 53 + - protocol: TCP + port: 53 + - to: + - ipBlock: + cidr: 10.42.0.0/16 + - ipBlock: + cidr: 10.43.0.0/16 +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: egress-storage-box + namespace: authentik +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: authentik-backup + policyTypes: + - Egress + egress: + - to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: kube-system + ports: + - protocol: UDP + port: 53 + - protocol: TCP + port: 53 + - to: + - ipBlock: + cidr: 10.42.0.0/16 + - ipBlock: + cidr: 10.43.0.0/16 + # Hetzner Storage Box, borg ueber SSH - wie die Backups in `matrix`. + - to: + - ipBlock: + cidr: 91.98.246.178/32 + ports: + - protocol: TCP + port: 23 +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: egress-authentik-smtp + namespace: authentik +spec: + # Server und Worker tragen beide app.kubernetes.io/name=authentik. + podSelector: + matchLabels: + app.kubernetes.io/name: authentik + policyTypes: + - Egress + egress: + - to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: kube-system + ports: + - protocol: UDP + port: 53 + - protocol: TCP + port: 53 + - to: + - ipBlock: + cidr: 10.42.0.0/16 + - ipBlock: + cidr: 10.43.0.0/16 + # E-Mail-Versand ueber smtp.ionos.de:587. TRAGEND, nicht optional: die + # Blueprints nutzen Passwort-Wiederherstellung und Einladungen per Mail. + # + # /27 statt zwei /32: Der Name loest heute auf 213.165.67.97 und .113 auf, + # beide im selben Block des Anbieters. Eine dritte Adresse wuerde bei /32 + # den Mailversand brechen, ohne dass jemand eine Regel im Blick haette - + # 32 Adressen der Mail-Infrastruktur eines Anbieters sind der kleinere + # Preis. (Anders als bei ClamAV: das ist kein CDN vor dem halben Internet.) + - to: + - ipBlock: + cidr: 213.165.67.96/27 + ports: + - protocol: TCP + port: 587 + # + # BEWUSST NICHT erlaubt: version.goauthentik.io (Versionspruefung). Liegt + # hinter Cloudflare mit wechselnden Adressen und ist nicht tragend - der + # Aufruf scheitert und Authentik protokolliert es. Wer den Fehler spaeter + # findet: das ist Absicht, kein Versehen. diff --git a/apps/monitoring/networkpolicy.yaml b/apps/monitoring/networkpolicy.yaml index 2d82cdf..3a50560 100644 --- a/apps/monitoring/networkpolicy.yaml +++ b/apps/monitoring/networkpolicy.yaml @@ -24,7 +24,17 @@ metadata: name: egress-block-metadata namespace: monitoring spec: - podSelector: {} + # Waehlt alle Pods AUSSER denen mit eigener, engerer Regel (#0088). + # Bleibt als Auffangnetz: Eine kuenftige Arbeitslast ohne eigene Policy + # landet hier - Metadaten gesperrt, Rest offen - statt voellig ungeregelt. + # ⚠️ Der Ausschluss MUSS hier stehen: NetworkPolicies sind additiv. + podSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: NotIn + values: + - alloy + - kube-state-metrics policyTypes: - Egress egress: @@ -51,3 +61,70 @@ spec: cidr: 0.0.0.0/0 except: - 169.254.0.0/16 +--- +# Welle 3 (#0088): Monitoring-Namespace, enge Regeln je Arbeitslast. +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: egress-nur-intern + namespace: monitoring +spec: + # Liefert Metriken, holt selbst nichts von aussen. + podSelector: + matchLabels: + app.kubernetes.io/name: kube-state-metrics + policyTypes: + - Egress + egress: + - to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: kube-system + ports: + - protocol: UDP + port: 53 + - protocol: TCP + port: 53 + - to: + - ipBlock: + cidr: 10.42.0.0/16 + - ipBlock: + cidr: 10.43.0.0/16 +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: egress-ops-host + namespace: monitoring +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: alloy + policyTypes: + - Egress + egress: + - to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: kube-system + ports: + - protocol: UDP + port: 53 + - protocol: TCP + port: 53 + - to: + - ipBlock: + cidr: 10.42.0.0/16 + - ipBlock: + cidr: 10.43.0.0/16 + # Der operating-Host im PRIVATEN Netz: Logs nach Loki (3100), Metriken per + # remote_write nach Prometheus (9090). Beide Ziele aus der laufenden + # Alloy-Konfiguration gelesen, nicht angenommen. + - to: + - ipBlock: + cidr: 10.0.0.3/32 + ports: + - protocol: TCP + port: 3100 + - protocol: TCP + port: 9090