diff --git a/kubernetes/infrastructure/network-policies/external-secrets-ns.yaml b/kubernetes/infrastructure/network-policies/external-secrets-ns.yaml new file mode 100644 index 00000000..c40d9500 --- /dev/null +++ b/kubernetes/infrastructure/network-policies/external-secrets-ns.yaml @@ -0,0 +1,142 @@ +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + name: default-deny-ingress + namespace: external-secrets +spec: + endpointSelector: {} + ingress: + # Intra-namespace — controller ↔ webhook ↔ cert-controller. + - fromEndpoints: + - matchLabels: + "k8s:io.kubernetes.pod.namespace": external-secrets + # kube-apiserver (host identity in Cilium) drives the ExternalSecret/ + # SecretStore validating webhook and the controller's watch/list/create + # calls. Without this, every ExternalSecret apply hangs the admission + # webhook call and gets rejected — same pattern as database-ns.yaml's + # CNPG webhook rule. + - fromEntities: + - host + - remote-node + # ICMP — all standard ICMPv4 + ICMPv6 from any cluster pod. See + # home-assistant-ns.yaml for the rationale. + - fromEndpoints: + - matchExpressions: + - key: io.kubernetes.pod.namespace + operator: Exists + icmps: + - fields: + - { type: 0, family: IPv4 } + - { type: 3, family: IPv4 } + - { type: 4, family: IPv4 } + - { type: 5, family: IPv4 } + - { type: 8, family: IPv4 } + - { type: 9, family: IPv4 } + - { type: 10, family: IPv4 } + - { type: 11, family: IPv4 } + - { type: 12, family: IPv4 } + - { type: 13, family: IPv4 } + - { type: 14, family: IPv4 } + - { type: 15, family: IPv4 } + - { type: 16, family: IPv4 } + - { type: 17, family: IPv4 } + - { type: 18, family: IPv4 } + - { type: 30, family: IPv4 } + - { type: 1, family: IPv6 } + - { type: 2, family: IPv6 } + - { type: 3, family: IPv6 } + - { type: 4, family: IPv6 } + - { type: 128, family: IPv6 } + - { type: 129, family: IPv6 } + - { type: 130, family: IPv6 } + - { type: 131, family: IPv6 } + - { type: 132, family: IPv6 } + - { type: 133, family: IPv6 } + - { type: 134, family: IPv6 } + - { type: 135, family: IPv6 } + - { type: 136, family: IPv6 } + - { type: 137, family: IPv6 } + - { type: 138, family: IPv6 } + - { type: 141, family: IPv6 } + - { type: 142, family: IPv6 } + - { type: 143, family: IPv6 } + - { type: 148, family: IPv6 } + - { type: 149, family: IPv6 } + - { type: 151, family: IPv6 } + - { type: 152, family: IPv6 } + - { type: 153, family: IPv6 } + egress: + - toEndpoints: + - matchLabels: + "k8s:io.kubernetes.pod.namespace": external-secrets + # DNS resolution. + - toEndpoints: + - matchLabels: + "k8s:io.kubernetes.pod.namespace": kube-system + k8s-app: kube-dns + toPorts: + - ports: + - port: "53" + protocol: UDP + # KV API of the only ClusterSecretStore in this cluster (openbao, + # kubernetes/infrastructure/post-crds/openbao-clustersecretstore.yaml). + # Matches the existing ingress grant in openbao-ns.yaml. + - toEndpoints: + - matchLabels: + "k8s:io.kubernetes.pod.namespace": openbao + toPorts: + - ports: + - port: "8200" + protocol: TCP + # host/remote-node: kube-apiserver — watch/list/create Secret objects, + # leader-election Lease, cert-controller's webhook CA-bundle updates. + # No "world": the only SecretStore target is in-cluster openbao. + - toEntities: + - host + - remote-node + # ICMP — egress mirror; see ingress block above. + - toEndpoints: + - matchExpressions: + - key: io.kubernetes.pod.namespace + operator: Exists + icmps: + - fields: + - { type: 0, family: IPv4 } + - { type: 3, family: IPv4 } + - { type: 4, family: IPv4 } + - { type: 5, family: IPv4 } + - { type: 8, family: IPv4 } + - { type: 9, family: IPv4 } + - { type: 10, family: IPv4 } + - { type: 11, family: IPv4 } + - { type: 12, family: IPv4 } + - { type: 13, family: IPv4 } + - { type: 14, family: IPv4 } + - { type: 15, family: IPv4 } + - { type: 16, family: IPv4 } + - { type: 17, family: IPv4 } + - { type: 18, family: IPv4 } + - { type: 30, family: IPv4 } + - { type: 1, family: IPv6 } + - { type: 2, family: IPv6 } + - { type: 3, family: IPv6 } + - { type: 4, family: IPv6 } + - { type: 128, family: IPv6 } + - { type: 129, family: IPv6 } + - { type: 130, family: IPv6 } + - { type: 131, family: IPv6 } + - { type: 132, family: IPv6 } + - { type: 133, family: IPv6 } + - { type: 134, family: IPv6 } + - { type: 135, family: IPv6 } + - { type: 136, family: IPv6 } + - { type: 137, family: IPv6 } + - { type: 138, family: IPv6 } + - { type: 141, family: IPv6 } + - { type: 142, family: IPv6 } + - { type: 143, family: IPv6 } + - { type: 148, family: IPv6 } + - { type: 149, family: IPv6 } + - { type: 151, family: IPv6 } + - { type: 152, family: IPv6 } + - { type: 153, family: IPv6 } diff --git a/kubernetes/infrastructure/network-policies/kustomization.yaml b/kubernetes/infrastructure/network-policies/kustomization.yaml index 3664c064..e03f25d8 100644 --- a/kubernetes/infrastructure/network-policies/kustomization.yaml +++ b/kubernetes/infrastructure/network-policies/kustomization.yaml @@ -19,4 +19,5 @@ resources: - velero-ns.yaml - evcc-ns.yaml - openbao-ns.yaml + - external-secrets-ns.yaml - allow-cilium-health.yaml