fix(net): renderer emits world/internet egress allow per egress class + fix jackett/plex tags
Root cause the media stack surfaced: the default-deny baseline is DNS-only egress (correct for R-NET-01 east-west), but the egress CLASS (internet/vpn) had no policy ALLOWING north-south egress — so qbittorrent/sonarr/radarr couldn't reach the internet at all (VPN downloaders broken). Add an additive per-app CiliumNetworkPolicy '<app>-allow-internet-egress' with toEntities:[world] (non-cluster); the egress-class steering + kill-switch (ADR-0015) govern the PATH (internet=WAN, vpn=tun0). East-west stays denied except declared dependencies; R-NET-01 baseline unchanged. Re-rendered all apps + regenerated L1 goldens. Also fixed jackett + plex image tags (bad pins -> :latest; Renovate/update policy pins later).
This commit is contained in:
14 files changed
+221
-5
No files matched your search
+41
-1
@@ -375,6 +375,32 @@ def _route_meta(s: dict, route: dict) -> dict:
|
||||
return meta
|
||||
|
||||
|
||||
def r_internet_egress(s: dict) -> dict:
|
||||
"""North-south egress allow: let the app reach the INTERNET (Cilium reserved `world`
|
||||
entity = everything outside the cluster), which is the whole point of the `egress` class
|
||||
(docs/03: internet-class → WAN; vpn-class → steered through the node tun0 PIA tunnel with
|
||||
the nftables kill-switch, ADR-0015). The default-deny baseline (R-NET-01) allows only DNS
|
||||
so EAST-WEST stays denied; this ADDITIVE policy opens ONLY `world` (non-cluster) egress —
|
||||
cluster/east-west traffic stays denied except the declared `dependencies`. Every app
|
||||
declares an egress class (EGRESS_CLASSES), so every app gets this. The steering + kill-
|
||||
switch (a cluster-wide singleton keyed on the egress-class pod label) decide the PATH; this
|
||||
policy decides that north-south egress is ALLOWED at all.
|
||||
"""
|
||||
return {
|
||||
"apiVersion": "cilium.io/v2",
|
||||
"kind": "CiliumNetworkPolicy",
|
||||
"metadata": {
|
||||
"name": f"{s['name']}-allow-internet-egress",
|
||||
"namespace": s["name"],
|
||||
"labels": {"app.kubernetes.io/name": s["name"]},
|
||||
},
|
||||
"spec": {
|
||||
"endpointSelector": {"matchLabels": {"app.kubernetes.io/name": s["name"]}},
|
||||
"egress": [{"toEntities": ["world"]}],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def r_httproutes(s: dict) -> list:
|
||||
"""One HTTPRoute per ingressRoute, attaching host -> service port on the shared Gateway.
|
||||
|
||||
@@ -674,6 +700,15 @@ def render(sd: dict, image_automation: bool = True) -> list:
|
||||
)
|
||||
)
|
||||
|
||||
ie = r_internet_egress(s)
|
||||
docs.append(
|
||||
(
|
||||
"CiliumNetworkPolicy world egress allow (egress class governs the path; R-NET-05): "
|
||||
f"{ie['metadata']['name']}",
|
||||
ie,
|
||||
)
|
||||
)
|
||||
|
||||
for hr in r_httproutes(s):
|
||||
docs.append((f"HTTPRoute {hr['metadata']['name']} (R-TLS/R-DNS)", hr))
|
||||
|
||||
@@ -781,7 +816,12 @@ def _selftest() -> int:
|
||||
}
|
||||
)
|
||||
cnps = [d[1] for d in dep_docs if d[1]["kind"] == "CiliumNetworkPolicy"]
|
||||
check(len(cnps) == 1, "one dependency must render one CiliumNetworkPolicy allow")
|
||||
dep_cnps = [c for c in cnps if c["metadata"]["name"] == "y-allow-db-5432"]
|
||||
check(len(dep_cnps) == 1, "one dependency must render one CiliumNetworkPolicy allow")
|
||||
check(
|
||||
any(c["metadata"]["name"] == "y-allow-internet-egress" for c in cnps),
|
||||
"every app (egress class) must render a world/internet egress allow",
|
||||
)
|
||||
|
||||
# 4b) exposure (ingressRoutes) -> an ADDITIVE gateway-ingress CiliumNetworkPolicy that
|
||||
# allows ONLY the reserved `ingress` (Gateway proxy) identity to the exposed port,
|
||||
|
||||
Reference in new issue
Block a user