From 7b7499c6896deb18d00eac3f2e13dddc5a450e2d Mon Sep 17 00:00:00 2001 From: rock Date: Wed, 4 Nov 2026 05:33:56 +0800 Subject: [PATCH] feat(poimen): restrict the memory database to its own namespace The database was already off the internet: every memory-db service is ClusterIP, no Ingress backs one, and no public DNS name resolves to them. That is not isolation. A ClusterIP service answers every pod in the cluster, so any workload in any namespace could open 5432. Cilium enforces NetworkPolicy, so stating the allowed sources is what closes it. Two sources: - namespace poimen, which holds every client (poimen-memory, poimen-graphql, poimen-worker, poimen-workflows, the migration Job) - namespace cnpg-system, where the CloudNativePG operator connects for switchover and failover Port 5432 only. The operator metrics port stays closed because no PodMonitor for this cluster exists. --- k8s/infra/poimen/kustomization.yaml | 2 ++ k8s/infra/poimen/memory-db-netpol.yaml | 42 ++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 k8s/infra/poimen/memory-db-netpol.yaml diff --git a/k8s/infra/poimen/kustomization.yaml b/k8s/infra/poimen/kustomization.yaml index ae6ad04..30945a6 100644 --- a/k8s/infra/poimen/kustomization.yaml +++ b/k8s/infra/poimen/kustomization.yaml @@ -6,6 +6,8 @@ kind: Kustomization # deployments (wave 0) are applied. resources: - memory-db.yaml + # ClusterIP alone is not isolation: every pod in the cluster can reach it. + - memory-db-netpol.yaml - poimen-sandbox-namespace.yaml - poimen-sandbox-quota.yaml - pi-session-netpol.yaml diff --git a/k8s/infra/poimen/memory-db-netpol.yaml b/k8s/infra/poimen/memory-db-netpol.yaml new file mode 100644 index 0000000..ddf17b8 --- /dev/null +++ b/k8s/infra/poimen/memory-db-netpol.yaml @@ -0,0 +1,42 @@ +--- +# Keep the memory database reachable only from inside its own namespace. +# +# What this does NOT change: the database was already unreachable from the +# internet. `memory-db-rw`, `memory-db-ro` and `memory-db-r` are ClusterIP +# services, no Ingress backs them, and no public DNS name resolves to them. +# +# What it fixes: a ClusterIP service is reachable by EVERY pod in the cluster, +# because Kubernetes has no implicit isolation. Cilium enforces NetworkPolicy, so +# stating the allowed sources is what turns "not on the internet" into "not +# reachable from another tenant's namespace". +# +# Two sources, both required: +# - the poimen namespace, which holds every client: poimen-memory, poimen-graphql, +# poimen-worker, poimen-workflows and the migration Job. +# - cnpg-system, where the CloudNativePG operator lives. It connects to the +# instance for switchover and failover, so a narrower rule breaks recovery. +# +# No other port is opened. The operator's metrics endpoint stays closed because no +# PodMonitor for this cluster exists, so nothing scrapes it. +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: memory-db-ingress + namespace: poimen +spec: + podSelector: + matchLabels: + cnpg.io/cluster: memory-db + policyTypes: + - Ingress + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: poimen + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: cnpg-system + ports: + - protocol: TCP + port: 5432 -- 2.54.0