You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The runlore workload has no CiliumNetworkPolicy at all:
$ kubectl get cnp -n runloreNo resources found in runlore namespace.
Every other pod-running workload on the platform ships one. The constitution mandates default-deny + explicit allow for anything that runs a pod, so this is a straight compliance gap: runlore's egress is currently unrestricted.
How it surfaced
While chasing a suspected AWS authorization problem with runlore — there wasn't one. The EPI is Ready, the PodIdentityAssociation is Ready, the IAM policy is attached and correctly scoped read-only (ec2:Describe*, eks:Describe*, autoscaling:Describe*, cloudtrail:LookupEvents), and there are no AccessDenied errors in its logs.
The irony is worth writing down: runlore's AWS access works because nothing is restricting its egress. The moment a policy is added it will break unless the rules below are right — so this needs writing carefully, not copy-pasting.
What the policy has to allow
Egress, at minimum:
kube-dns — and the L7 DNS rule (toPorts.rules.dns.matchPattern: "*") is mandatory. Without it Cilium proxies the query but never sees the response IPs, so any toFQDNs allowlist has no IPs to match: DNS keeps working while every follow-up TCP connection is silently dropped (trap refacto: split network and eks tofu states #1 in .claude/rules/cilium-network-policies.md).
EKS Pod Identity agent at 169.254.170.23:80 — the one that will bite. The agent runs on the node's host network, so Cilium classifies the destination as the host entity: toCIDR: 169.254.170.23/32 alone silently fails, and toEntities: world does not cover link-local. It needs toEntities: ["host"] scoped to TCP 80 (trap chore(terraform): use the subnet router module v1.0.3 #3). Symptom if wrong: Connect timeout on endpoint URL: 'http://169.254.170.23/v1/credentials' — i.e. precisely the "runlore isn't authorized in AWS" failure this issue was mistaken for.
world:443 — LLM provider, Slack, GitHub (the KB repo). toFQDNs is a maintenance chase here because matchPattern: "*" does not span dots (trap feat(tofu): use the tailscale provider #2), so scope this deliberately rather than by reflex.
Ingress: the Cilium Gateway data-plane pods terminating the Tailscale-fronted HTTPRoute are the ingress entity, not a pod selector.
Acceptance
CiliumNetworkPolicy in observability/base/runlore/, default-deny + explicit allow
After it applies, runlore still reaches AWS (pod identity), Hubble, the API server, the LLM and Slack — verified with hubble observe --pod runlore/runlore-0 --verdict DROPPED, not by "the Kustomization reconciled"
An investigation runs end to end with the policy in place
Found during a platform validation session on feat/flux-schema-validation.
What
The
runloreworkload has no CiliumNetworkPolicy at all:Every other pod-running workload on the platform ships one. The constitution mandates default-deny + explicit allow for anything that runs a pod, so this is a straight compliance gap: runlore's egress is currently unrestricted.
How it surfaced
While chasing a suspected AWS authorization problem with runlore — there wasn't one. The EPI is
Ready, thePodIdentityAssociationisReady, the IAM policy is attached and correctly scoped read-only (ec2:Describe*,eks:Describe*,autoscaling:Describe*,cloudtrail:LookupEvents), and there are noAccessDeniederrors in its logs.The irony is worth writing down: runlore's AWS access works because nothing is restricting its egress. The moment a policy is added it will break unless the rules below are right — so this needs writing carefully, not copy-pasting.
What the policy has to allow
Egress, at minimum:
toPorts.rules.dns.matchPattern: "*") is mandatory. Without it Cilium proxies the query but never sees the response IPs, so anytoFQDNsallowlist has no IPs to match: DNS keeps working while every follow-up TCP connection is silently dropped (trap refacto: split network and eks tofu states #1 in.claude/rules/cilium-network-policies.md).169.254.170.23:80— the one that will bite. The agent runs on the node's host network, so Cilium classifies the destination as thehostentity:toCIDR: 169.254.170.23/32alone silently fails, andtoEntities: worlddoes not cover link-local. It needstoEntities: ["host"]scoped to TCP 80 (trap chore(terraform): use the subnet router module v1.0.3 #3). Symptom if wrong:Connect timeout on endpoint URL: 'http://169.254.170.23/v1/credentials'— i.e. precisely the "runlore isn't authorized in AWS" failure this issue was mistaken for.kube-system) — runlore dials it for network flows (chore(deps): update helm release prometheus-operator-crds to v13.0.1 #321 pinned its TLS floor to 1.2).world:443— LLM provider, Slack, GitHub (the KB repo).toFQDNsis a maintenance chase here becausematchPattern: "*"does not span dots (trap feat(tofu): use the tailscale provider #2), so scope this deliberately rather than by reflex.Ingress: the Cilium Gateway data-plane pods terminating the Tailscale-fronted HTTPRoute are the
ingressentity, not a pod selector.Acceptance
CiliumNetworkPolicyinobservability/base/runlore/, default-deny + explicit allowhubble observe --pod runlore/runlore-0 --verdict DROPPED, not by "the Kustomization reconciled"Found during a platform validation session on
feat/flux-schema-validation.