From 9b13b8537cd9864c8ac0ee963c85011df57ac422 Mon Sep 17 00:00:00 2001 From: Flegma Date: Thu, 2 Apr 2026 15:03:48 +0200 Subject: [PATCH 1/4] fix: add network policies and scope Vault permissions per service Network policies: - Default-deny ingress for 5stack namespace - Allow ingress controller to reach web, api, hasura, minio, typesense - TimescaleDB: only reachable from hasura and api - Redis: only reachable from api and connector - Hasura: only from api, web, and ingress - API: only from ingress and connector - Connector: only from api Vault: - Replace wildcard path "*" with explicit per-service read-only paths matching the kv/data/* paths used by migrate_secrets_to_vault - External-secrets can only read specific service secrets, not create/update/delete or access arbitrary vault paths Closes #413 --- base/kustomization.yaml | 3 +- base/network-policies/allow-ingress.yaml | 32 ++++++ base/network-policies/allow-internal.yaml | 119 ++++++++++++++++++++++ base/network-policies/default-deny.yaml | 9 ++ base/network-policies/kustomization.yaml | 7 ++ overlays/vault/scripts/setup-vault.sh | 37 ++++++- 6 files changed, 204 insertions(+), 3 deletions(-) create mode 100644 base/network-policies/allow-ingress.yaml create mode 100644 base/network-policies/allow-internal.yaml create mode 100644 base/network-policies/default-deny.yaml create mode 100644 base/network-policies/kustomization.yaml diff --git a/base/kustomization.yaml b/base/kustomization.yaml index da90a6b..e829f5b 100644 --- a/base/kustomization.yaml +++ b/base/kustomization.yaml @@ -13,4 +13,5 @@ resources: - web - volumes - nginx - - backups \ No newline at end of file + - backups + - network-policies \ No newline at end of file diff --git a/base/network-policies/allow-ingress.yaml b/base/network-policies/allow-ingress.yaml new file mode 100644 index 0000000..1f986a6 --- /dev/null +++ b/base/network-policies/allow-ingress.yaml @@ -0,0 +1,32 @@ +# Allow NGINX ingress controller to reach web, api, hasura, minio, typesense +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-ingress-to-services + namespace: 5stack +spec: + podSelector: + matchExpressions: + - key: app + operator: In + values: [web, api, hasura, minio, typesense] + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: ingress-nginx + ports: + - port: 3000 + protocol: TCP + - port: 5585 + protocol: TCP + - port: 8080 + protocol: TCP + - port: 9000 + protocol: TCP + - port: 9090 + protocol: TCP + - port: 8108 + protocol: TCP + policyTypes: + - Ingress diff --git a/base/network-policies/allow-internal.yaml b/base/network-policies/allow-internal.yaml new file mode 100644 index 0000000..b0070df --- /dev/null +++ b/base/network-policies/allow-internal.yaml @@ -0,0 +1,119 @@ +# TimescaleDB: allow from hasura and api only +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-timescaledb-ingress + namespace: 5stack +spec: + podSelector: + matchLabels: + app: timescaledb + ingress: + - from: + - podSelector: + matchLabels: + app: hasura + - podSelector: + matchLabels: + app: api + ports: + - port: 5432 + protocol: TCP + policyTypes: + - Ingress +--- +# Redis: allow from api and game-server-node-connector +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-redis-ingress + namespace: 5stack +spec: + podSelector: + matchLabels: + app: redis + ingress: + - from: + - podSelector: + matchLabels: + app: api + - podSelector: + matchLabels: + app: game-server-node-connector + ports: + - port: 6379 + protocol: TCP + policyTypes: + - Ingress +--- +# Hasura: allow from web, api, and ingress +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-hasura-ingress + namespace: 5stack +spec: + podSelector: + matchLabels: + app: hasura + ingress: + - from: + - podSelector: + matchLabels: + app: api + - podSelector: + matchLabels: + app: web + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: ingress-nginx + ports: + - port: 8080 + protocol: TCP + policyTypes: + - Ingress +--- +# API: allow from ingress and game-server-node-connector +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-api-ingress + namespace: 5stack +spec: + podSelector: + matchLabels: + app: api + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: ingress-nginx + - podSelector: + matchLabels: + app: game-server-node-connector + ports: + - port: 5585 + protocol: TCP + policyTypes: + - Ingress +--- +# Game server node connector: allow from api (Redis transport) +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-connector-ingress + namespace: 5stack +spec: + podSelector: + matchLabels: + app: game-server-node-connector + ingress: + - from: + - podSelector: + matchLabels: + app: api + ports: + - port: 8585 + protocol: TCP + policyTypes: + - Ingress diff --git a/base/network-policies/default-deny.yaml b/base/network-policies/default-deny.yaml new file mode 100644 index 0000000..856ca34 --- /dev/null +++ b/base/network-policies/default-deny.yaml @@ -0,0 +1,9 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: default-deny-ingress + namespace: 5stack +spec: + podSelector: {} + policyTypes: + - Ingress diff --git a/base/network-policies/kustomization.yaml b/base/network-policies/kustomization.yaml new file mode 100644 index 0000000..1811d9e --- /dev/null +++ b/base/network-policies/kustomization.yaml @@ -0,0 +1,7 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - default-deny.yaml + - allow-ingress.yaml + - allow-internal.yaml diff --git a/overlays/vault/scripts/setup-vault.sh b/overlays/vault/scripts/setup-vault.sh index 81cdae0..6c01236 100755 --- a/overlays/vault/scripts/setup-vault.sh +++ b/overlays/vault/scripts/setup-vault.sh @@ -70,8 +70,41 @@ fi echo "Creating Vault policy for external-secrets..." cat < Date: Thu, 2 Apr 2026 16:04:35 +0200 Subject: [PATCH 2/4] fix: allow game server pods to reach API for match events Game server pods (labeled app: game-server) need WebSocket access to the API for match event communication. Without this, match events would be blocked by the default-deny policy. --- base/network-policies/allow-internal.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/base/network-policies/allow-internal.yaml b/base/network-policies/allow-internal.yaml index b0070df..03d892f 100644 --- a/base/network-policies/allow-internal.yaml +++ b/base/network-policies/allow-internal.yaml @@ -73,7 +73,7 @@ spec: policyTypes: - Ingress --- -# API: allow from ingress and game-server-node-connector +# API: allow from ingress, connector, and game server pods apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: @@ -91,6 +91,11 @@ spec: - podSelector: matchLabels: app: game-server-node-connector + - podSelector: + matchExpressions: + - key: app + operator: In + values: [game-server] ports: - port: 5585 protocol: TCP From 3521e5b5f8d67e30f1d774575c38fa1582562683 Mon Sep 17 00:00:00 2001 From: Flegma Date: Thu, 2 Apr 2026 17:01:30 +0200 Subject: [PATCH 3/4] fix: add missing network policies for hasura, minio, typesense, backups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per code review — 4 critical/important missing policies: - Hasura → API: needed for auth/event/action webhooks - Backup CronJob → TimescaleDB + MinIO: needed for pg_dump + S3 upload - API → MinIO: needed for S3 operations (demos, assets) - API → Typesense: needed for player search indexing Also adds app: postgres-backup label to backup CronJob pod template so it can be selected by network policies. --- base/backups/postgres-backup-cronjob.yaml | 3 ++ base/network-policies/allow-internal.yaml | 63 ++++++++++++++++++++++- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/base/backups/postgres-backup-cronjob.yaml b/base/backups/postgres-backup-cronjob.yaml index a2a9102..229f350 100644 --- a/base/backups/postgres-backup-cronjob.yaml +++ b/base/backups/postgres-backup-cronjob.yaml @@ -10,6 +10,9 @@ spec: jobTemplate: spec: template: + metadata: + labels: + app: postgres-backup spec: restartPolicy: Never containers: diff --git a/base/network-policies/allow-internal.yaml b/base/network-policies/allow-internal.yaml index 03d892f..1d8ab56 100644 --- a/base/network-policies/allow-internal.yaml +++ b/base/network-policies/allow-internal.yaml @@ -1,4 +1,4 @@ -# TimescaleDB: allow from hasura and api only +# TimescaleDB: allow from hasura, api, and backup jobs apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: @@ -16,6 +16,9 @@ spec: - podSelector: matchLabels: app: api + - podSelector: + matchLabels: + app: postgres-backup ports: - port: 5432 protocol: TCP @@ -73,7 +76,7 @@ spec: policyTypes: - Ingress --- -# API: allow from ingress, connector, and game server pods +# API: allow from ingress, hasura (webhooks), connector, and game server pods apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: @@ -88,6 +91,9 @@ spec: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: ingress-nginx + - podSelector: + matchLabels: + app: hasura - podSelector: matchLabels: app: game-server-node-connector @@ -102,6 +108,59 @@ spec: policyTypes: - Ingress --- +# MinIO: allow from api and backup jobs +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-minio-ingress + namespace: 5stack +spec: + podSelector: + matchLabels: + app: minio + ingress: + - from: + - podSelector: + matchLabels: + app: api + - podSelector: + matchLabels: + app: postgres-backup + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: ingress-nginx + ports: + - port: 9000 + protocol: TCP + - port: 9090 + protocol: TCP + policyTypes: + - Ingress +--- +# Typesense: allow from api and ingress +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-typesense-ingress + namespace: 5stack +spec: + podSelector: + matchLabels: + app: typesense + ingress: + - from: + - podSelector: + matchLabels: + app: api + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: ingress-nginx + ports: + - port: 8108 + protocol: TCP + policyTypes: + - Ingress +--- # Game server node connector: allow from api (Redis transport) apiVersion: networking.k8s.io/v1 kind: NetworkPolicy From aeef06601b9860694cf7c23a77c65656facb571a Mon Sep 17 00:00:00 2001 From: Flegma Date: Sun, 26 Apr 2026 19:59:25 +0200 Subject: [PATCH 4/4] fix: scope network policies to internal services only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop default-deny-ingress and allow-ingress policies. Without a default-deny in place, only pods explicitly selected by allow-internal become restricted — game-server pods (and any other unselected pod) remain wide-open, so CS2 client traffic and connector/RCON paths are not affected. Per-service ingress restrictions (TimescaleDB, Redis, Hasura, API, MinIO, Typesense, connector) still apply. --- base/network-policies/allow-ingress.yaml | 32 ------------------------ base/network-policies/default-deny.yaml | 9 ------- base/network-policies/kustomization.yaml | 2 -- 3 files changed, 43 deletions(-) delete mode 100644 base/network-policies/allow-ingress.yaml delete mode 100644 base/network-policies/default-deny.yaml diff --git a/base/network-policies/allow-ingress.yaml b/base/network-policies/allow-ingress.yaml deleted file mode 100644 index 1f986a6..0000000 --- a/base/network-policies/allow-ingress.yaml +++ /dev/null @@ -1,32 +0,0 @@ -# Allow NGINX ingress controller to reach web, api, hasura, minio, typesense -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: allow-ingress-to-services - namespace: 5stack -spec: - podSelector: - matchExpressions: - - key: app - operator: In - values: [web, api, hasura, minio, typesense] - ingress: - - from: - - namespaceSelector: - matchLabels: - kubernetes.io/metadata.name: ingress-nginx - ports: - - port: 3000 - protocol: TCP - - port: 5585 - protocol: TCP - - port: 8080 - protocol: TCP - - port: 9000 - protocol: TCP - - port: 9090 - protocol: TCP - - port: 8108 - protocol: TCP - policyTypes: - - Ingress diff --git a/base/network-policies/default-deny.yaml b/base/network-policies/default-deny.yaml deleted file mode 100644 index 856ca34..0000000 --- a/base/network-policies/default-deny.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: default-deny-ingress - namespace: 5stack -spec: - podSelector: {} - policyTypes: - - Ingress diff --git a/base/network-policies/kustomization.yaml b/base/network-policies/kustomization.yaml index 1811d9e..429e89c 100644 --- a/base/network-policies/kustomization.yaml +++ b/base/network-policies/kustomization.yaml @@ -2,6 +2,4 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - - default-deny.yaml - - allow-ingress.yaml - allow-internal.yaml