NK-WP-0056: sso ingress for the bounded executor; README and handoff follow-up
All checks were successful
Build and Publish bounded-executor / build-and-push (push) Successful in 6s
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Identity provider journey acceptance / provider (push) Successful in 37s

netpol-sso.yaml admits only executor pods to LLDAP 17170, KeyCape 8080 and
Authelia 9091 (never LDAP 3890); test_netpol.py pins it. Prepared, not
applied. README reflects T13. Live reads: OpenBao open to all namespaces;
approval-engine and audit-core need pod-scoped rules (requested: hub messages
39a3bffa, deea5bf8).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 5502@bnt-lap001
Assistant-Session: 68b3b02f-5d0f-4e71-8421-796f62e50196
This commit is contained in:
tegwick 2026-10-31 18:27:30 +01:00
parent cd0ce905a2
commit 387f8b1c8b
4 changed files with 134 additions and 2 deletions

View file

@ -0,0 +1,45 @@
"""The sso namespace admits the bounded executor exactly where its pilot steps go (NK-WP-0056). No cluster."""
import pathlib
import unittest
import yaml
NETPOL = pathlib.Path(__file__).resolve().parents[1] / "network-policies" / "netpol-sso.yaml"
EXECUTOR = {"app.kubernetes.io/name": "bounded-executor"}
EXPECTED = {("lldap", 17170), ("keycape", 8080), ("authelia", 9091)}
def policies():
return [d for d in yaml.safe_load_all(NETPOL.read_text()) if d]
def executor_ingress():
for pol in policies():
for rule in pol["spec"].get("ingress", []):
if any(peer.get("podSelector", {}).get("matchLabels") == EXECUTOR for peer in rule["from"]):
yield pol, rule
class ExecutorIngress(unittest.TestCase):
def test_exactly_the_pilot_paths(self): # in particular never LDAP :3890
found = set()
for pol, rule in executor_ingress():
target = pol["spec"]["podSelector"]["matchLabels"]["app.kubernetes.io/name"]
found |= {(target, p["port"]) for p in rule["ports"]}
self.assertEqual(found, EXPECTED)
def test_peers_are_in_namespace_executor_pods_only(self):
for pol, rule in executor_ingress():
self.assertEqual(pol["metadata"]["namespace"], "sso")
self.assertEqual(pol["spec"]["policyTypes"], ["Ingress"])
for peer in rule["from"]:
self.assertEqual(peer, {"podSelector": {"matchLabels": EXECUTOR}})
def test_default_deny_is_kept(self):
deny = [p for p in policies() if p["metadata"]["name"] == "default-deny-all"]
self.assertEqual(deny[0]["spec"], {"podSelector": {}, "policyTypes": ["Ingress", "Egress"]})
if __name__ == "__main__":
unittest.main()

View file

@ -11,6 +11,7 @@
# user-engine → authelia :9091 (read GET /api/state for an existing sign-in)
# Traefik → authelia :9091 (login portal, user-facing)
# Traefik → lldap :17170 (admin web UI; IP-restricted at Traefik layer)
# bounded-executor → lldap :17170, keycape :8080, authelia :9091 (NK-WP-0056 Job)
#
# Allowed egress paths:
# keycape → authelia :9091 (OIDC callback orchestration)
@ -374,6 +375,72 @@ spec:
protocol: TCP
---
# ── Bounded executor → LLDAP :17170, KeyCape :8080, Authelia :9091 ───────────
# NK-WP-0056: the per-admission executor Job (rapp-bounded-executor, label
# app.kubernetes.io/name=bounded-executor) self-rotates a bind through the LLDAP
# web API and runs the synthetic journey in-cluster against KeyCape and Authelia.
# The executor's own egress-only policy lives in rapp-bounded-executor. No pod
# exists unless an admitted Job is running.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-bounded-executor-to-lldap-api
namespace: sso
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: lldap
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app.kubernetes.io/name: bounded-executor
ports:
- port: 17170
protocol: TCP
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-bounded-executor-to-keycape
namespace: sso
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: keycape
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app.kubernetes.io/name: bounded-executor
ports:
- port: 8080
protocol: TCP
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-bounded-executor-to-authelia
namespace: sso
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: authelia
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app.kubernetes.io/name: bounded-executor
ports:
- port: 9091
protocol: TCP
---
# ── Allow egress DNS (all pods) ──────────────────────────────────────────────
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy