deploy/k8s/networkpolicy.yaml
# Default-deny for the holger namespace, plus the two ways in and the two ways
# out that holger actually needs.
#
# Why this file exists: the 2026-06-14 security review flagged that the namespace
# was created with no NetworkPolicy beside it, and the 2026-09-11 review found it
# still absent. Without one, every pod in the cluster can reach holger's gRPC and
# HTTPS doors directly — the read gate and the RBAC gate are then the ONLY thing
# between a compromised neighbour and the artifact store, and holger's default
# posture leaves reads open. A network boundary is the assumption the airgap
# design rests on; in a cluster it has to be declared, not inherited.
#
# Apply order does not matter, but note that a NetworkPolicy is namespaced and
# additive: `default-deny` below denies everything, and each following policy
# adds back exactly one flow. A cluster whose CNI does not implement
# NetworkPolicy (some Talos installs without Cilium/Calico) will accept these
# objects and enforce nothing — check with `kubectl get networkpolicy -n holger`
# and an actual connection test before believing them.
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: holger
spec:
podSelector: {}
policyTypes: [Ingress, Egress]
---
# Clients reach the two doors. Narrow `from` to the namespaces that should hold
# clients — the empty `from` below means "any pod in the cluster", which is the
# widest useful starting point and still far narrower than no policy at all.
# In an airgap deployment, replace it with the namespaceSelector for your
# build/CI namespace.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-client-ingress
namespace: holger
spec:
podSelector:
matchLabels:
app: holger
policyTypes: [Ingress]
ingress:
- ports:
- port: 50051
protocol: TCP
- port: 8443
protocol: TCP
---
# DNS only. holger resolves nothing else in the airgap posture; a `full`-tier
# deployment that proxies to an upstream registry needs an egress rule for that
# host added here, deliberately and by address — which is the point of having
# the default-deny above.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-egress
namespace: holger
spec:
podSelector:
matchLabels:
app: holger
policyTypes: [Egress]
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP