Adds a default-deny-ingress CiliumNetworkPolicy for the external-secrets namespace (the cluster-wide ESO controller — currently the only namespace-scoped gap this issue found that isn't already being closed by another open PR, see below).
Ingress: intra-namespace (controller/webhook/cert-controller) + host/remote-node (kube-apiserver drives the ExternalSecret/SecretStore admission webhook and the controller's watch/create calls) + the standard ICMP allow.
Egress: intra-namespace, DNS, the openbao KV API on :8200 (verified — kubernetes/infrastructure/post-crds/openbao-clustersecretstore.yaml is the onlyClusterSecretStore in this cluster, and openbao-ns.yaml already has a matching ingress grant for the external-secrets namespace), and host/remote-node for kube-apiserver (Secret writes, leader-election Lease, webhook CA-bundle updates). No world egress — nothing outside the cluster is a SecretStore target.
Registered in kubernetes/infrastructure/network-policies/kustomization.yaml.
Scope: dropped from this PR, already covered by other open PRs
The original finding (issue #194) also flagged woodpecker-ci (no CNP) and openbao (ingress-only, egress unenforced) — this branch initially fixed both, but:
PR #235 (fix/issue-193-woodpecker-ci-hardening) already adds kubernetes/infrastructure/network-policies/woodpecker-ci-ns.yaml, and deliberately leaves egress default-allow because enforcing egress in this namespace previously broke crowdsec (commit 66dbe9f) — context this branch didn't have. Rather than ship a second, conflicting, more-restrictive egress policy for the same file, that's deferred entirely to #235.
PR #231 (fix/issue-202-openbao-hardening) already adds an egress block to openbao-ns.yaml as part of a broader hardening pass (also including a world allowance for OIDC that this branch's version didn't have). Deferred to #231 to avoid a duplicate/conflicting diff on the same file.
Also NOT covered: music-assistant
Issue #194 asked to "cover music-assistant for consistency." Its only workload (kubernetes/apps/music-assistant/deployment.yaml) runs hostNetwork: true (required for L2 adjacency on the IoT VLAN — Snapcast/SlimProto/Sendspin audio-sync timing). A namespace-scoped CiliumNetworkPolicy cannot enforce anything against a hostNetwork pod: Cilium classifies its traffic under the node's reserved:host identity, not a distinct pod endpoint, so a CNP here would apply cleanly but enforce nothing — the same documented limitation already called out in rook-ceph-ns.yaml for the Ceph daemons ("outside Cilium endpoint policy entirely — rely on UDM-side firewalling"). Confirmed against the wiki (existing notes independently record this as a deliberate, already-known exception for this exact workload) and against this cluster's config (no CiliumClusterwideNetworkPolicy/host-firewall deployed anywhere). Real enforcement would need host-firewall, which also touches the Ceph daemons and CNI components sharing hostNetwork — out of this issue's scope. Noted in a comment on #194 rather than merged here.
Verification
kubectl kustomize kubernetes/infrastructure/network-policies renders cleanly (no cluster access needed); openbao-ns.yaml in this branch is now byte-identical to origin/master (the only diff left is the new external-secrets-ns.yaml file + its kustomization.yaml entry).
Fixes #194
## What
Adds a `default-deny-ingress` CiliumNetworkPolicy for the `external-secrets` namespace (the cluster-wide ESO controller — currently the only namespace-scoped gap this issue found that isn't already being closed by another open PR, see below).
- Ingress: intra-namespace (controller/webhook/cert-controller) + host/remote-node (kube-apiserver drives the ExternalSecret/SecretStore admission webhook and the controller's watch/create calls) + the standard ICMP allow.
- Egress: intra-namespace, DNS, the openbao KV API on `:8200` (verified — `kubernetes/infrastructure/post-crds/openbao-clustersecretstore.yaml` is the *only* `ClusterSecretStore` in this cluster, and `openbao-ns.yaml` already has a matching ingress grant for the `external-secrets` namespace), and host/remote-node for kube-apiserver (Secret writes, leader-election Lease, webhook CA-bundle updates). No `world` egress — nothing outside the cluster is a SecretStore target.
- Registered in `kubernetes/infrastructure/network-policies/kustomization.yaml`.
## Scope: dropped from this PR, already covered by other open PRs
The original finding (issue #194) also flagged `woodpecker-ci` (no CNP) and `openbao` (ingress-only, egress unenforced) — this branch initially fixed both, but:
- **PR #235** (`fix/issue-193-woodpecker-ci-hardening`) already adds `kubernetes/infrastructure/network-policies/woodpecker-ci-ns.yaml`, and deliberately leaves egress default-allow because enforcing egress in this namespace previously broke crowdsec (commit `66dbe9f`) — context this branch didn't have. Rather than ship a second, conflicting, more-restrictive egress policy for the same file, that's deferred entirely to #235.
- **PR #231** (`fix/issue-202-openbao-hardening`) already adds an egress block to `openbao-ns.yaml` as part of a broader hardening pass (also including a `world` allowance for OIDC that this branch's version didn't have). Deferred to #231 to avoid a duplicate/conflicting diff on the same file.
## Also NOT covered: music-assistant
Issue #194 asked to "cover music-assistant for consistency." Its only workload (`kubernetes/apps/music-assistant/deployment.yaml`) runs `hostNetwork: true` (required for L2 adjacency on the IoT VLAN — Snapcast/SlimProto/Sendspin audio-sync timing). A namespace-scoped CiliumNetworkPolicy cannot enforce anything against a hostNetwork pod: Cilium classifies its traffic under the node's `reserved:host` identity, not a distinct pod endpoint, so a CNP here would apply cleanly but enforce nothing — the same documented limitation already called out in `rook-ceph-ns.yaml` for the Ceph daemons ("outside Cilium endpoint policy entirely — rely on UDM-side firewalling"). Confirmed against the wiki (existing notes independently record this as a deliberate, already-known exception for this exact workload) and against this cluster's config (no `CiliumClusterwideNetworkPolicy`/host-firewall deployed anywhere). Real enforcement would need host-firewall, which also touches the Ceph daemons and CNI components sharing hostNetwork — out of this issue's scope. Noted in a comment on #194 rather than merged here.
## Verification
`kubectl kustomize kubernetes/infrastructure/network-policies` renders cleanly (no cluster access needed); `openbao-ns.yaml` in this branch is now byte-identical to `origin/master` (the only diff left is the new `external-secrets-ns.yaml` file + its `kustomization.yaml` entry).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Closes the gaps from #194: external-secrets and woodpecker-ci had no
CiliumNetworkPolicy at all (Cilium defaults to allow-all absent one), and
openbao-ns.yaml had an ingress-only CNP with no egress block, which leaves
egress from openbao pods completely unenforced rather than merely permissive.
- external-secrets-ns.yaml: default-deny-ingress; egress scoped to the
namespace, DNS, and the openbao KV API on :8200 (the only
ClusterSecretStore in this cluster) plus host/remote-node for
kube-apiserver (webhook admission, Secret watch/create, leader election).
- woodpecker-ci-ns.yaml: this namespace hosts only ephemeral, sometimes
privileged, pipeline-defined step pods (no static workloads) — the goal
is blocking lateral movement into unrelated namespaces while still
allowing the git clone (east-west via k8s_gateway -> traefik, since
gitea.renner.uno now has an in-cluster Ingress) and the broad internet
egress every CI system legitimately needs (image pulls, package
managers).
- openbao-ns.yaml: added an egress block (DNS, intra-namespace, host/
remote-node for the k8s auth method + kubelet) so egress enforcement is
actually turned on, not just missing.
music-assistant is deliberately NOT covered here: its only workload runs
hostNetwork: true, so a namespace-scoped CiliumNetworkPolicy would select
no enforceable pod-network endpoint and be a no-op (same documented
limitation as the rook-ceph Ceph daemons). Left for a comment on #194
rather than shipping a policy that looks protective but isn't.
Co-Authored-By: Claude Bot <claude-bot@renner.uno>
PR #235 (fix/issue-193-woodpecker-ci-hardening) already adds
kubernetes/infrastructure/network-policies/woodpecker-ci-ns.yaml, with a
deliberately different (and better-informed) egress design: default-allow,
because a past attempt at egress enforcement in this namespace broke
crowdsec (66dbe9f) — history this branch didn't have context on.
PR #231 (fix/issue-202-openbao-hardening) already adds an egress block to
openbao-ns.yaml as part of a broader OpenBao hardening pass, including a
"world" allowance (OIDC) this branch's version omitted.
Dropping both here to avoid shipping a conflicting/duplicate policy;
external-secrets-ns.yaml (this issue's third gap, not covered by any other
open PR) is the only change left on this branch.
Co-Authored-By: Claude Bot <claude-bot@renner.uno>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Fixes #194
What
Adds a
default-deny-ingressCiliumNetworkPolicy for theexternal-secretsnamespace (the cluster-wide ESO controller — currently the only namespace-scoped gap this issue found that isn't already being closed by another open PR, see below).:8200(verified —kubernetes/infrastructure/post-crds/openbao-clustersecretstore.yamlis the onlyClusterSecretStorein this cluster, andopenbao-ns.yamlalready has a matching ingress grant for theexternal-secretsnamespace), and host/remote-node for kube-apiserver (Secret writes, leader-election Lease, webhook CA-bundle updates). Noworldegress — nothing outside the cluster is a SecretStore target.kubernetes/infrastructure/network-policies/kustomization.yaml.Scope: dropped from this PR, already covered by other open PRs
The original finding (issue #194) also flagged
woodpecker-ci(no CNP) andopenbao(ingress-only, egress unenforced) — this branch initially fixed both, but:fix/issue-193-woodpecker-ci-hardening) already addskubernetes/infrastructure/network-policies/woodpecker-ci-ns.yaml, and deliberately leaves egress default-allow because enforcing egress in this namespace previously broke crowdsec (commit66dbe9f) — context this branch didn't have. Rather than ship a second, conflicting, more-restrictive egress policy for the same file, that's deferred entirely to #235.fix/issue-202-openbao-hardening) already adds an egress block toopenbao-ns.yamlas part of a broader hardening pass (also including aworldallowance for OIDC that this branch's version didn't have). Deferred to #231 to avoid a duplicate/conflicting diff on the same file.Also NOT covered: music-assistant
Issue #194 asked to "cover music-assistant for consistency." Its only workload (
kubernetes/apps/music-assistant/deployment.yaml) runshostNetwork: true(required for L2 adjacency on the IoT VLAN — Snapcast/SlimProto/Sendspin audio-sync timing). A namespace-scoped CiliumNetworkPolicy cannot enforce anything against a hostNetwork pod: Cilium classifies its traffic under the node'sreserved:hostidentity, not a distinct pod endpoint, so a CNP here would apply cleanly but enforce nothing — the same documented limitation already called out inrook-ceph-ns.yamlfor the Ceph daemons ("outside Cilium endpoint policy entirely — rely on UDM-side firewalling"). Confirmed against the wiki (existing notes independently record this as a deliberate, already-known exception for this exact workload) and against this cluster's config (noCiliumClusterwideNetworkPolicy/host-firewall deployed anywhere). Real enforcement would need host-firewall, which also touches the Ceph daemons and CNI components sharing hostNetwork — out of this issue's scope. Noted in a comment on #194 rather than merged here.Verification
kubectl kustomize kubernetes/infrastructure/network-policiesrenders cleanly (no cluster access needed);openbao-ns.yamlin this branch is now byte-identical toorigin/master(the only diff left is the newexternal-secrets-ns.yamlfile + itskustomization.yamlentry).🤖 Generated with Claude Code