From 2378706a2d4dfcbea45bd05e839416dc6085c810 Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Sat, 5 Sep 2026 11:43:09 +0200 Subject: [PATCH 01/13] feat(rhdh): add base NetworkPolicies for RHDH deployment [RHIDP-16476] Add default-deny + selective-allow NetworkPolicies for the RHDH backend and built-in PostgreSQL, replicating the operator's NP behavior (RHIDP-16475) in the Helm chart. Policies are always enabled to provide a secure-by-default deployment; customers can add additive NPs as needed. Backend NPs (always created): - default-deny (ingress + egress) - allow-dns-egress (53/5353 UDP+TCP) - allow-https-egress (443 TCP) - allow-psql-egress (5432 TCP to DB pods; broad egress for external DB) - allow-metrics-ingress (9464 TCP from monitoring namespaces) - allow-router-ingress (7007 TCP; OpenShift-aware namespace selector) DB NPs (only when postgresql.enabled=true): - db-default-deny, db-allow-dns-egress, db-allow-backend-ingress - Replication-aware: additional NPs for read replicas and primary-read communication when postgresql.architecture=replication Orchestrator NPs: - allow-all-egress (when orchestrator.enabled=true) Disables bitnami postgresql subchart's own NPs (primary + readReplicas) since they default to allow-all egress and unrestricted ingress, which is too permissive. Assisted-by: Claude --- charts/rhdh/Chart.yaml | 2 +- charts/rhdh/README.md | 6 +- charts/rhdh/templates/network-policies.yaml | 421 ++++++++++++++++++ .../orchestrator/network-policies.yaml | 19 + charts/rhdh/values.yaml | 10 + 5 files changed, 454 insertions(+), 4 deletions(-) create mode 100644 charts/rhdh/templates/network-policies.yaml diff --git a/charts/rhdh/Chart.yaml b/charts/rhdh/Chart.yaml index ef40439df..3c71b5b26 100644 --- a/charts/rhdh/Chart.yaml +++ b/charts/rhdh/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: redhat-developer-hub type: application -version: 2.1.1 +version: 2.2.0 appVersion: 2.1.0 annotations: artifacthub.io/category: integration-delivery diff --git a/charts/rhdh/README.md b/charts/rhdh/README.md index f728974ac..7dc7bcdf2 100644 --- a/charts/rhdh/README.md +++ b/charts/rhdh/README.md @@ -1,7 +1,7 @@ # RHDH Helm Chart for OpenShift and Kubernetes -![Version: 2.1.1](https://img.shields.io/badge/Version-2.1.1-informational?style=flat-square) +![Version: 2.2.0](https://img.shields.io/badge/Version-2.2.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) A Helm chart for deploying Red Hat Developer Hub, which is a Red Hat supported version of Backstage. @@ -36,7 +36,7 @@ For the **Generally Available** version of this chart, see: helm repo add bitnami https://charts.bitnami.com/bitnami helm repo add redhat-developer https://redhat-developer.github.io/rhdh-chart -helm install my-rhdh redhat-developer/redhat-developer-hub --version 2.1.1 +helm install my-rhdh redhat-developer/redhat-developer-hub --version 2.2.0 ``` ## Introduction @@ -288,7 +288,7 @@ Kubernetes: `>= 1.31.0-0` | podDisruptionBudget | Pod Disruption Budget configuration. | object | `{"create":false,"maxUnavailable":1,"minAvailable":""}` | | podLabels | Labels to add to the pod. | object | `{}` | | podSecurityContext | Pod-level security context. | object | `{}` | -| postgresql | Built-in PostgreSQL database (bitnami subchart). | object | `{"auth":{"secretKeys":{"adminPasswordKey":"postgres-password","userPasswordKey":"password"}},"enabled":true,"image":{"digest":"","registry":"quay.io","repository":"fedora/postgresql-15","tag":"latest"},"postgresqlDataDir":"/var/lib/pgsql/data/userdata","primary":{"containerSecurityContext":{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"enabled":false},"extraEnvVars":[{"name":"POSTGRESQL_ADMIN_PASSWORD","valueFrom":{"secretKeyRef":{"key":"{{- include \"rhdh.postgresql.adminPasswordKey\" . }}","name":"{{- include \"rhdh.postgresql.secretName\" . }}"}}}],"persistence":{"enabled":true,"mountPath":"/var/lib/pgsql/data","size":"1Gi"},"podSecurityContext":{"enabled":false},"resources":{"limits":{"cpu":"250m","ephemeral-storage":"20Mi","memory":"1024Mi"},"requests":{"cpu":"250m","memory":"256Mi"}}},"serviceBindings":{"enabled":true}}` | +| postgresql | Built-in PostgreSQL database (bitnami subchart). | object | `{"auth":{"secretKeys":{"adminPasswordKey":"postgres-password","userPasswordKey":"password"}},"enabled":true,"image":{"digest":"","registry":"quay.io","repository":"fedora/postgresql-15","tag":"latest"},"postgresqlDataDir":"/var/lib/pgsql/data/userdata","primary":{"containerSecurityContext":{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"enabled":false},"extraEnvVars":[{"name":"POSTGRESQL_ADMIN_PASSWORD","valueFrom":{"secretKeyRef":{"key":"{{- include \"rhdh.postgresql.adminPasswordKey\" . }}","name":"{{- include \"rhdh.postgresql.secretName\" . }}"}}}],"networkPolicy":{"enabled":false},"persistence":{"enabled":true,"mountPath":"/var/lib/pgsql/data","size":"1Gi"},"podSecurityContext":{"enabled":false},"resources":{"limits":{"cpu":"250m","ephemeral-storage":"20Mi","memory":"1024Mi"},"requests":{"cpu":"250m","memory":"256Mi"}}},"readReplicas":{"networkPolicy":{"enabled":false}},"serviceBindings":{"enabled":true}}` | | preInitContainers | Init containers to run BEFORE the system init containers (e.g. inject auth credentials before install-dynamic-plugins runs). | list | `[]` | | readinessProbe | Readiness probe configuration. | object | `{"failureThreshold":3,"httpGet":{"path":"/.backstage/health/v1/readiness","port":"backend","scheme":"HTTP"},"periodSeconds":10,"successThreshold":2,"timeoutSeconds":4}` | | replicaCount | Number of desired pods. | int | `1` | diff --git a/charts/rhdh/templates/network-policies.yaml b/charts/rhdh/templates/network-policies.yaml new file mode 100644 index 000000000..06b9ce03b --- /dev/null +++ b/charts/rhdh/templates/network-policies.yaml @@ -0,0 +1,421 @@ +{{- /* +Base NetworkPolicies for RHDH backend and built-in PostgreSQL. +These cover the network requirements of a base RHDH deployment with all enabled-by-default plugins. +See https://github.com/redhat-developer/rhdh-plugin-export-overlays/blob/main/default.packages.yaml +Disabled plugins (e.g. LDAP catalog, email notifications, scaffolder HTTP requests) may need +additional user-created additive NetworkPolicies for ports not covered here. +*/ -}} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-default-deny + labels: + {{- include "rhdh.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + {{- include "rhdh.selectorLabels" . | nindent 6 }} + policyTypes: + - Ingress + - Egress + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-allow-dns-egress + labels: + {{- include "rhdh.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + {{- include "rhdh.selectorLabels" . | nindent 6 }} + policyTypes: + - Egress + egress: + - ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + - port: 5353 + protocol: UDP + - port: 5353 + protocol: TCP + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-allow-https-egress + labels: + {{- include "rhdh.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + {{- include "rhdh.selectorLabels" . | nindent 6 }} + policyTypes: + - Egress + egress: + - ports: + - port: 443 + protocol: TCP +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-allow-psql-egress + labels: + {{- include "rhdh.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + {{- include "rhdh.selectorLabels" . | nindent 6 }} + policyTypes: + - Egress + egress: + - {{- if .Values.postgresql.enabled }} + to: + - podSelector: + matchLabels: + app.kubernetes.io/name: postgresql + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: primary + {{- if eq (default "standalone" .Values.postgresql.architecture) "replication" }} + - podSelector: + matchLabels: + app.kubernetes.io/name: postgresql + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: read + {{- end }} + {{- end }} + ports: + - port: {{ if .Values.postgresql.enabled }}5432{{ else }}{{ .Values.externalDatabase.port | default 5432 }}{{ end }} + protocol: TCP + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-allow-metrics-ingress + labels: + {{- include "rhdh.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + {{- include "rhdh.selectorLabels" . | nindent 6 }} + policyTypes: + - Ingress + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: openshift-monitoring + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: gmp-system + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: gke-gmp-system + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: monitoring + ports: + - port: 9464 + protocol: TCP + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-allow-router-ingress + labels: + {{- include "rhdh.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + {{- include "rhdh.selectorLabels" . | nindent 6 }} + policyTypes: + - Ingress + ingress: + - from: + - namespaceSelector: + {{- if .Values.openshift.route.enabled }} + matchLabels: + policy-group.network.openshift.io/ingress: "" + {{- else }} + {} + {{- end }} + ports: + - port: 7007 + protocol: TCP +{{- if .Values.postgresql.enabled }} +{{- $isReplication := eq (default "standalone" .Values.postgresql.architecture) "replication" }} +--- +{{- /* +The following db-* policies are only created when the built-in PostgreSQL is enabled. +When using an external database (postgresql.enabled=false), only the backend NPs above +are created, and allow-psql-egress has no 'to' selector (broad egress on the configured port). + +These replace the bitnami subchart's own NPs (disabled via +postgresql.primary.networkPolicy.enabled=false and +postgresql.readReplicas.networkPolicy.enabled=false in values.yaml) +so we can enforce tighter rules. +*/ -}} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-db-default-deny + labels: + {{- include "rhdh.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: postgresql + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: primary + policyTypes: + - Ingress + - Egress + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-db-allow-dns-egress + labels: + {{- include "rhdh.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: postgresql + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: primary + policyTypes: + - Egress + egress: + - ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + - port: 5353 + protocol: UDP + - port: 5353 + protocol: TCP + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-db-allow-backend-ingress + labels: + {{- include "rhdh.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: postgresql + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: primary + policyTypes: + - Ingress + ingress: + - from: + - podSelector: + matchLabels: + {{- include "rhdh.selectorLabels" . | nindent 14 }} + ports: + - port: 5432 + protocol: TCP + +{{- if $isReplication }} + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-db-allow-replication + labels: + {{- include "rhdh.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: postgresql + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: primary + policyTypes: + - Ingress + - Egress + ingress: + - from: + - podSelector: + matchLabels: + app.kubernetes.io/name: postgresql + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: read + ports: + - port: 5432 + protocol: TCP + egress: + - to: + - podSelector: + matchLabels: + app.kubernetes.io/name: postgresql + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: read + ports: + - port: 5432 + protocol: TCP + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-db-read-default-deny + labels: + {{- include "rhdh.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: postgresql + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: read + policyTypes: + - Ingress + - Egress + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-db-read-allow-dns-egress + labels: + {{- include "rhdh.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: postgresql + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: read + policyTypes: + - Egress + egress: + - ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + - port: 5353 + protocol: UDP + - port: 5353 + protocol: TCP + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-db-read-allow-primary-egress + labels: + {{- include "rhdh.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: postgresql + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: read + policyTypes: + - Egress + egress: + - to: + - podSelector: + matchLabels: + app.kubernetes.io/name: postgresql + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: primary + ports: + - port: 5432 + protocol: TCP + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-db-read-allow-backend-ingress + labels: + {{- include "rhdh.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: postgresql + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: read + policyTypes: + - Ingress + ingress: + - from: + - podSelector: + matchLabels: + {{- include "rhdh.selectorLabels" . | nindent 14 }} + ports: + - port: 5432 + protocol: TCP + +{{- end }} + +{{- end }} diff --git a/charts/rhdh/templates/orchestrator/network-policies.yaml b/charts/rhdh/templates/orchestrator/network-policies.yaml index 27afbbae8..bd2b073be 100644 --- a/charts/rhdh/templates/orchestrator/network-policies.yaml +++ b/charts/rhdh/templates/orchestrator/network-policies.yaml @@ -62,6 +62,25 @@ spec: - podSelector: {} {{- end }} --- +{{- if .Values.orchestrator.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-allow-all-egress + labels: + {{- include "rhdh.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: {} + policyTypes: + - Egress + egress: + - {} +{{- end }} +--- {{- if and .Values.orchestrator.enabled .Values.orchestrator.sonataflowPlatform.monitoring.enabled }} apiVersion: networking.k8s.io/v1 kind: NetworkPolicy diff --git a/charts/rhdh/values.yaml b/charts/rhdh/values.yaml index 1639f37f1..498bfbd84 100644 --- a/charts/rhdh/values.yaml +++ b/charts/rhdh/values.yaml @@ -421,6 +421,11 @@ postgresql: adminPasswordKey: "postgres-password" userPasswordKey: "password" primary: + # The bitnami subchart ships its own NP, but it defaults to allow-all egress + # and unrestricted ingress on 5432. We disable it and provide tighter + # replacements in templates/network-policies.yaml. + networkPolicy: + enabled: false podSecurityContext: enabled: false containerSecurityContext: @@ -447,6 +452,11 @@ postgresql: secretKeyRef: key: '{{- include "rhdh.postgresql.adminPasswordKey" . }}' name: '{{- include "rhdh.postgresql.secretName" . }}' + readReplicas: + # Same rationale as primary.networkPolicy above; our own read-replica NPs + # in templates/network-policies.yaml are tighter. + networkPolicy: + enabled: false # -- External database connection. Used when postgresql.enabled is false. # See docs/external-db.md for TLS setup and privilege requirements. From e753e87b9e819a9797dd3e9ac9e4658e29b99bbf Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Sat, 5 Sep 2026 14:58:04 +0200 Subject: [PATCH 02/13] fix(rhdh): fix helm lint YAML separator error in network-policies Move the Go template comment block before the conditional so that the */-}} whitespace trimming does not merge --- and apiVersion: onto the same line. Also remove the top-level comment that caused a similar issue with the first document. Assisted-by: Claude --- charts/rhdh/templates/network-policies.yaml | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/charts/rhdh/templates/network-policies.yaml b/charts/rhdh/templates/network-policies.yaml index 06b9ce03b..538a32b26 100644 --- a/charts/rhdh/templates/network-policies.yaml +++ b/charts/rhdh/templates/network-policies.yaml @@ -1,10 +1,3 @@ -{{- /* -Base NetworkPolicies for RHDH backend and built-in PostgreSQL. -These cover the network requirements of a base RHDH deployment with all enabled-by-default plugins. -See https://github.com/redhat-developer/rhdh-plugin-export-overlays/blob/main/default.packages.yaml -Disabled plugins (e.g. LDAP catalog, email notifications, scaffolder HTTP requests) may need -additional user-created additive NetworkPolicies for ports not covered here. -*/ -}} apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: @@ -173,9 +166,6 @@ spec: ports: - port: 7007 protocol: TCP -{{- if .Values.postgresql.enabled }} -{{- $isReplication := eq (default "standalone" .Values.postgresql.architecture) "replication" }} ---- {{- /* The following db-* policies are only created when the built-in PostgreSQL is enabled. When using an external database (postgresql.enabled=false), only the backend NPs above @@ -186,6 +176,10 @@ postgresql.primary.networkPolicy.enabled=false and postgresql.readReplicas.networkPolicy.enabled=false in values.yaml) so we can enforce tighter rules. */ -}} +{{- if .Values.postgresql.enabled }} +{{- $isReplication := eq (default "standalone" .Values.postgresql.architecture) "replication" }} + +--- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: From 90dc998ee0fef087977f8c6f23acde5ff45ed2b1 Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Sat, 5 Sep 2026 15:09:36 +0200 Subject: [PATCH 03/13] fix(rhdh): fix helm lint YAML separator error in network-policies Move the Go template comment before the conditional block so that whitespace trimming does not merge --- and apiVersion: onto the same line, which caused helm lint to reject the template. Assisted-by: Claude --- charts/rhdh/templates/network-policies.yaml | 29 +++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/charts/rhdh/templates/network-policies.yaml b/charts/rhdh/templates/network-policies.yaml index 538a32b26..ef6adff85 100644 --- a/charts/rhdh/templates/network-policies.yaml +++ b/charts/rhdh/templates/network-policies.yaml @@ -166,6 +166,35 @@ spec: ports: - port: 7007 protocol: TCP + +{{- if .Values.test.enabled }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-allow-test-connection + labels: + {{- include "rhdh.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + {{- include "rhdh.selectorLabels" . | nindent 6 }} + rhdh.redhat.com/test-connection: "true" + policyTypes: + - Egress + egress: + - to: + - podSelector: + matchLabels: + {{- include "rhdh.selectorLabels" . | nindent 14 }} + ports: + - port: 7007 + protocol: TCP +{{- end }} {{- /* The following db-* policies are only created when the built-in PostgreSQL is enabled. When using an external database (postgresql.enabled=false), only the backend NPs above From e4fd573dd1e8aa451adf940a422a65207909093c Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Sat, 5 Sep 2026 15:09:50 +0200 Subject: [PATCH 04/13] fix(rhdh): allow test-connection pod through NetworkPolicies Add rhdh.redhat.com/test-connection label to the test-connection pod and a dedicated allow-test-connection NP (gated on test.enabled) that permits the test pod to egress on port 7007 to the backend. Without this, default-deny blocks the test pod's connectivity check. Assisted-by: Claude --- charts/rhdh/templates/tests/test-connection.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/charts/rhdh/templates/tests/test-connection.yaml b/charts/rhdh/templates/tests/test-connection.yaml index 92e6156ed..3ed604bea 100644 --- a/charts/rhdh/templates/tests/test-connection.yaml +++ b/charts/rhdh/templates/tests/test-connection.yaml @@ -5,6 +5,7 @@ metadata: name: "{{ include "rhdh.fullname" . }}-test-connection" labels: {{- include "rhdh.labels" . | nindent 4 }} + rhdh.redhat.com/test-connection: "true" annotations: {{- with .Values.commonAnnotations }} {{- toYaml . | nindent 4 }} From 0ca53f07c575bf36ea5adcce8276d70d099d3239 Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Sat, 5 Sep 2026 15:13:30 +0200 Subject: [PATCH 05/13] fix(rhdh): allow backend ingress from test-connection pod The test pod's egress NP alone is not enough; the backend also needs an ingress rule accepting connections on port 7007 from pods with the rhdh.redhat.com/test-connection label. Gated on test.enabled. Assisted-by: Claude --- charts/rhdh/templates/network-policies.yaml | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/charts/rhdh/templates/network-policies.yaml b/charts/rhdh/templates/network-policies.yaml index ef6adff85..36e0aacb2 100644 --- a/charts/rhdh/templates/network-policies.yaml +++ b/charts/rhdh/templates/network-policies.yaml @@ -194,6 +194,33 @@ spec: ports: - port: 7007 protocol: TCP + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-allow-test-connection-ingress + labels: + {{- include "rhdh.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + {{- include "rhdh.selectorLabels" . | nindent 6 }} + policyTypes: + - Ingress + ingress: + - from: + - podSelector: + matchLabels: + {{- include "rhdh.selectorLabels" . | nindent 14 }} + rhdh.redhat.com/test-connection: "true" + ports: + - port: 7007 + protocol: TCP {{- end }} {{- /* The following db-* policies are only created when the built-in PostgreSQL is enabled. From 27c9ef777f3eaf0fe63bfb3e16a6fa577e4e48b7 Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Sat, 5 Sep 2026 15:27:49 +0200 Subject: [PATCH 06/13] chore(rhdh): add TODO and inline comments to orchestrator NPs Mirror the comments from the operator repo so the namespace-wide podSelector concern and per-rule rationale are visible in the chart. Assisted-by: Claude --- .../orchestrator/network-policies.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/charts/rhdh/templates/orchestrator/network-policies.yaml b/charts/rhdh/templates/orchestrator/network-policies.yaml index bd2b073be..39e5d65d4 100644 --- a/charts/rhdh/templates/orchestrator/network-policies.yaml +++ b/charts/rhdh/templates/orchestrator/network-policies.yaml @@ -1,3 +1,12 @@ +{{- /* +TODO: these Orchestrator policies use podSelector: {} (namespace-wide) and conflict with +the ADR's "default deny with selective allow" and "label-scoped policies" principles. +They weaken per-component ingress isolation for RHDH backend and DB pods in the same namespace. +Even though only one Orchestrator-flavoured RHDH instance is supported per namespace (the +SonataFlow Operator enforces one SonataFlowPlatform per namespace), a non-Orchestrator RHDH +instance could coexist in the same namespace; these namespace-wide policies would affect it too. +Review and make stricter by scoping to SonataFlow-specific labels where possible. +*/ -}} {{- if .Values.orchestrator.enabled }} apiVersion: networking.k8s.io/v1 kind: NetworkPolicy @@ -15,12 +24,15 @@ spec: - from: - namespaceSelector: matchLabels: + # Allow knative events to be delivered to workflows. kubernetes.io/metadata.name: knative-eventing - namespaceSelector: matchLabels: + # Allow auxiliary knative function for workflow (such as m2k-save-transformation) kubernetes.io/metadata.name: knative-serving - namespaceSelector: matchLabels: + # Allow openshift serverless logic operator controller pod to access all pods in sonataflow kubernetes.io/metadata.name: openshift-serverless-logic --- apiVersion: networking.k8s.io/v1 @@ -41,6 +53,7 @@ spec: - from: - namespaceSelector: matchLabels: + # Allow knative events to be delivered to workflows. policy-group.network.openshift.io/ingress: "" --- apiVersion: networking.k8s.io/v1 @@ -62,6 +75,11 @@ spec: - podSelector: {} {{- end }} --- +{{- /* +Allow all egress from all pods in the namespace. +The Orchestrator backend plugin needs HTTP egress to reach SonataFlow and Data Index services; +SonataFlow workflows may also need arbitrary outbound access. +*/ -}} {{- if .Values.orchestrator.enabled }} apiVersion: networking.k8s.io/v1 kind: NetworkPolicy @@ -100,5 +118,6 @@ spec: - from: - namespaceSelector: matchLabels: + # Allow openshift-user-workload-monitoring pods to access the workflow. kubernetes.io/metadata.name: openshift-user-workload-monitoring {{- end }} From 05ac8bc0f9d7ec43e87b34c882f48d60328a55e1 Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Sat, 5 Sep 2026 16:18:47 +0200 Subject: [PATCH 07/13] feat(rhdh): add Redis egress rule (port 6379) to backend NPs Redis is part of the recommended checklist for production deployments. RHDH does not deploy Redis OOTB; users bring their own, which could be in the same namespace, a different namespace, or an external managed service. The rule has no pod or namespace selector so it covers all cases. Ref: RHDHBUGS-3724 Assisted-by: Claude --- charts/rhdh/templates/network-policies.yaml | 29 +++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/charts/rhdh/templates/network-policies.yaml b/charts/rhdh/templates/network-policies.yaml index 36e0aacb2..48686731f 100644 --- a/charts/rhdh/templates/network-policies.yaml +++ b/charts/rhdh/templates/network-policies.yaml @@ -65,6 +65,35 @@ spec: - ports: - port: 443 protocol: TCP +{{- /* +Redis is part of the recommended checklist for production deployments +(see https://docs.redhat.com/en/documentation/red_hat_developer_hub/1.10/html/setting_up_and_configuring_your_first_red_hat_developer_hub_instance/checklist-to-run-your-first-rhdh-instance-in-production_setting-up-and-configuring-your-first-red-hat-developer-hub-instance). +RHDH does not deploy Redis OOTB; users bring their own, which could be in the same +namespace, a different namespace, or an external managed service. The rule therefore +has no pod or namespace selector. +*/ -}} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-allow-redis-egress + labels: + {{- include "rhdh.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + {{- include "rhdh.selectorLabels" . | nindent 6 }} + policyTypes: + - Egress + egress: + - ports: + - port: 6379 + protocol: TCP + --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy From 41254129ab9980cfe53ff527731224d2ff015ef2 Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Sat, 5 Sep 2026 21:41:40 +0200 Subject: [PATCH 08/13] fix(rhdh): fix whitespace trimming merging allow-https-egress with separator The Go template comment before allow-redis-egress used */ -}} which stripped the newline before the --- separator, merging the preceding NP's last line with --- and producing invalid YAML. Changed to */}} to preserve the newline. Assisted-by: Claude --- charts/rhdh/templates/network-policies.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/rhdh/templates/network-policies.yaml b/charts/rhdh/templates/network-policies.yaml index 48686731f..8658a8172 100644 --- a/charts/rhdh/templates/network-policies.yaml +++ b/charts/rhdh/templates/network-policies.yaml @@ -71,7 +71,7 @@ Redis is part of the recommended checklist for production deployments RHDH does not deploy Redis OOTB; users bring their own, which could be in the same namespace, a different namespace, or an external managed service. The rule therefore has no pod or namespace selector. -*/ -}} +*/}} --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy From c9b6125477bd03b6260d3205849224f887de1e5e Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Sat, 5 Sep 2026 21:49:34 +0200 Subject: [PATCH 09/13] refactor(rhdh): use YAML comments instead of Go template comments in NPs Go template comments with whitespace trimming (e.g. */ -}}) have caused YAML separator merging bugs twice. YAML comments avoid this entirely; they survive rendering but Kubernetes ignores them. Assisted-by: Claude --- charts/rhdh/templates/network-policies.yaml | 32 +++++++++---------- .../orchestrator/network-policies.yaml | 24 ++++++-------- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/charts/rhdh/templates/network-policies.yaml b/charts/rhdh/templates/network-policies.yaml index 8658a8172..91ca29f29 100644 --- a/charts/rhdh/templates/network-policies.yaml +++ b/charts/rhdh/templates/network-policies.yaml @@ -65,14 +65,13 @@ spec: - ports: - port: 443 protocol: TCP -{{- /* -Redis is part of the recommended checklist for production deployments -(see https://docs.redhat.com/en/documentation/red_hat_developer_hub/1.10/html/setting_up_and_configuring_your_first_red_hat_developer_hub_instance/checklist-to-run-your-first-rhdh-instance-in-production_setting-up-and-configuring-your-first-red-hat-developer-hub-instance). -RHDH does not deploy Redis OOTB; users bring their own, which could be in the same -namespace, a different namespace, or an external managed service. The rule therefore -has no pod or namespace selector. -*/}} + --- +# Redis is part of the recommended checklist for production deployments +# (see https://docs.redhat.com/en/documentation/red_hat_developer_hub/1.10/html/setting_up_and_configuring_your_first_red_hat_developer_hub_instance/checklist-to-run-your-first-rhdh-instance-in-production_setting-up-and-configuring-your-first-red-hat-developer-hub-instance). +# RHDH does not deploy Redis OOTB; users bring their own, which could be in the same +# namespace, a different namespace, or an external managed service. The rule therefore +# has no pod or namespace selector. apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: @@ -251,17 +250,18 @@ spec: - port: 7007 protocol: TCP {{- end }} -{{- /* -The following db-* policies are only created when the built-in PostgreSQL is enabled. -When using an external database (postgresql.enabled=false), only the backend NPs above -are created, and allow-psql-egress has no 'to' selector (broad egress on the configured port). -These replace the bitnami subchart's own NPs (disabled via -postgresql.primary.networkPolicy.enabled=false and -postgresql.readReplicas.networkPolicy.enabled=false in values.yaml) -so we can enforce tighter rules. -*/ -}} {{- if .Values.postgresql.enabled }} + +# The following db-* policies are only created when the built-in PostgreSQL is enabled. +# When using an external database (postgresql.enabled=false), only the backend NPs above +# are created, and allow-psql-egress has no 'to' selector (broad egress on the configured port). +# +# These replace the bitnami subchart's own NPs (disabled via +# postgresql.primary.networkPolicy.enabled=false and +# postgresql.readReplicas.networkPolicy.enabled=false in values.yaml) +# so we can enforce tighter rules. + {{- $isReplication := eq (default "standalone" .Values.postgresql.architecture) "replication" }} --- diff --git a/charts/rhdh/templates/orchestrator/network-policies.yaml b/charts/rhdh/templates/orchestrator/network-policies.yaml index 39e5d65d4..cc05a7662 100644 --- a/charts/rhdh/templates/orchestrator/network-policies.yaml +++ b/charts/rhdh/templates/orchestrator/network-policies.yaml @@ -1,12 +1,10 @@ -{{- /* -TODO: these Orchestrator policies use podSelector: {} (namespace-wide) and conflict with -the ADR's "default deny with selective allow" and "label-scoped policies" principles. -They weaken per-component ingress isolation for RHDH backend and DB pods in the same namespace. -Even though only one Orchestrator-flavoured RHDH instance is supported per namespace (the -SonataFlow Operator enforces one SonataFlowPlatform per namespace), a non-Orchestrator RHDH -instance could coexist in the same namespace; these namespace-wide policies would affect it too. -Review and make stricter by scoping to SonataFlow-specific labels where possible. -*/ -}} +# TODO: these Orchestrator policies use podSelector: {} (namespace-wide) and conflict with +# the ADR's "default deny with selective allow" and "label-scoped policies" principles. +# They weaken per-component ingress isolation for RHDH backend and DB pods in the same namespace. +# Even though only one Orchestrator-flavoured RHDH instance is supported per namespace (the +# SonataFlow Operator enforces one SonataFlowPlatform per namespace), a non-Orchestrator RHDH +# instance could coexist in the same namespace; these namespace-wide policies would affect it too. +# Review and make stricter by scoping to SonataFlow-specific labels where possible. {{- if .Values.orchestrator.enabled }} apiVersion: networking.k8s.io/v1 kind: NetworkPolicy @@ -74,12 +72,10 @@ spec: - from: - podSelector: {} {{- end }} +# Allow all egress from all pods in the namespace. +# The Orchestrator backend plugin needs HTTP egress to reach SonataFlow and Data Index services; +# SonataFlow workflows may also need arbitrary outbound access. --- -{{- /* -Allow all egress from all pods in the namespace. -The Orchestrator backend plugin needs HTTP egress to reach SonataFlow and Data Index services; -SonataFlow workflows may also need arbitrary outbound access. -*/ -}} {{- if .Values.orchestrator.enabled }} apiVersion: networking.k8s.io/v1 kind: NetworkPolicy From a654f049fa675eb6104b36702f811e4fd4381313 Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Sat, 5 Sep 2026 22:45:24 +0200 Subject: [PATCH 10/13] fix(rhdh): add missing read replica ingress NP from primary The db-allow-replication NP allows the primary to egress to read replicas, but the read replica's default-deny blocks the incoming connection. Add db-read-allow-primary-ingress to accept ingress from the primary on port 5432. Assisted-by: Claude --- charts/rhdh/templates/network-policies.yaml | 30 +++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/charts/rhdh/templates/network-policies.yaml b/charts/rhdh/templates/network-policies.yaml index 91ca29f29..76dc3f318 100644 --- a/charts/rhdh/templates/network-policies.yaml +++ b/charts/rhdh/templates/network-policies.yaml @@ -467,6 +467,36 @@ spec: - port: 5432 protocol: TCP +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-db-read-allow-primary-ingress + labels: + {{- include "rhdh.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: postgresql + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: read + policyTypes: + - Ingress + ingress: + - from: + - podSelector: + matchLabels: + app.kubernetes.io/name: postgresql + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: primary + ports: + - port: 5432 + protocol: TCP + --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy From 1cc9f34f88d4ab27fc6d1d3386f13603a4273165 Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Mon, 7 Sep 2026 10:51:53 +0200 Subject: [PATCH 11/13] fix(rhdh): allow metrics ingress from openshift-user-workload-monitoring The chart's ServiceMonitor is a user workload, scraped by the Prometheus in openshift-user-workload-monitoring, not by the platform Prometheus in openshift-monitoring. Without this namespace in the allow list, enabling metrics.serviceMonitor would deploy the resource but its scraper would be blocked by the default-deny NP. Assisted-by: Claude --- charts/rhdh/templates/network-policies.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/charts/rhdh/templates/network-policies.yaml b/charts/rhdh/templates/network-policies.yaml index 76dc3f318..a4c9c9f11 100644 --- a/charts/rhdh/templates/network-policies.yaml +++ b/charts/rhdh/templates/network-policies.yaml @@ -152,6 +152,9 @@ spec: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: openshift-monitoring + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: openshift-user-workload-monitoring - namespaceSelector: matchLabels: kubernetes.io/metadata.name: gmp-system From 223e52e4dbf1aebb3cf04e30ea774b8c73813c92 Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Mon, 14 Sep 2026 18:23:52 +0200 Subject: [PATCH 12/13] fix(network-policies): address PR review feedback - Make test NPs Helm test hooks so they only exist during helm test - Scope test pod labels to instance + test-connection label to avoid matching backend default-deny NP - Fix orchestrator allow-all-egress --- placement outside if block - Add NetworkPolicies section to README documenting default-deny behavior, allowed traffic, and additive NP semantics Co-authored-by: Fortune Ndlovu Assisted-by: Claude --- charts/rhdh/README.md | 25 +++++++++++++++++++ charts/rhdh/README.md.gotmpl | 25 +++++++++++++++++++ charts/rhdh/templates/network-policies.yaml | 18 ++++++++----- .../orchestrator/network-policies.yaml | 2 +- .../rhdh/templates/tests/test-connection.yaml | 2 +- 5 files changed, 64 insertions(+), 8 deletions(-) diff --git a/charts/rhdh/README.md b/charts/rhdh/README.md index 0c1ce51f8..4de0b71be 100644 --- a/charts/rhdh/README.md +++ b/charts/rhdh/README.md @@ -410,6 +410,31 @@ You can also configure additional catalog index images via `catalogIndex.extraIm For detailed information on configuring the catalog index, including how to override the default image, use a private registry, or add extra catalog index images, see the [Catalog Index Configuration documentation](../../docs/catalog-index-configuration.md). +### NetworkPolicies + +This chart deploys a **default-deny** NetworkPolicy for the RHDH backend pod, blocking all ingress and egress traffic that is not explicitly allowed. When the built-in PostgreSQL is enabled (`postgresql.enabled=true`), the database pods also get their own default-deny policy with selective allow rules. + +The following traffic is allowed out of the box: + +| Direction | Port | Destination / Source | Purpose | +|-----------|------|----------------------|---------| +| Egress | 53, 5353 (UDP/TCP) | Any | DNS resolution | +| Egress | 443 (TCP) | Any | HTTPS (Git forges, auth providers, external APIs) | +| Egress | 5432 (TCP) | Built-in PostgreSQL pods (scoped) or any (external DB) | Database access | +| Egress | 6379 (TCP) | Any | Redis (BYO — no pod/namespace selector) | +| Ingress | 7007 (TCP) | OpenShift router namespace or any namespace (non-OCP) | User traffic via Route / Ingress | +| Ingress | 9464 (TCP) | `openshift-monitoring`, `openshift-user-workload-monitoring`, `gmp-system`, `gke-gmp-system`, `monitoring` | Prometheus metrics scraping | + +**Redis egress is intentionally unscoped.** RHDH does not deploy Redis; users bring their own instance, which may live in the same namespace, a different namespace, or an external managed service. The rule therefore allows egress on port 6379 to any destination. + +**Bitnami subchart NetworkPolicies are disabled** (`postgresql.primary.networkPolicy.enabled=false`, `postgresql.readReplicas.networkPolicy.enabled=false`) because this chart provides its own tighter policies for the built-in database pods. + +**Helm test NetworkPolicies** (`allow-test-connection` and `allow-test-connection-ingress`) are Helm test hooks: they are created just before `helm test` runs and cleaned up automatically on success. + +**Adding your own NetworkPolicies.** Kubernetes evaluates NetworkPolicies additively — if any policy allows a connection, the connection is permitted. You **cannot** tighten an existing allow rule by adding another NetworkPolicy; you can only broaden access. To restrict traffic further, you would need to modify or remove the chart's policies via values overrides or post-render patches. + +For more information on user workload monitoring on OpenShift, see [Configuring user workload monitoring](https://docs.redhat.com/en/documentation/monitoring_stack_for_red_hat_openshift/4.22/html/configuring_user_workload_monitoring/preparing-to-configure-the-monitoring-stack-uwm). + ### Intelligent Assistant Use `intelligentAssistant.enabled` to enable or disable the built-in Intelligent Assistant feature. diff --git a/charts/rhdh/README.md.gotmpl b/charts/rhdh/README.md.gotmpl index 96a24bb22..77060edb1 100644 --- a/charts/rhdh/README.md.gotmpl +++ b/charts/rhdh/README.md.gotmpl @@ -255,6 +255,31 @@ You can also configure additional catalog index images via `catalogIndex.extraIm For detailed information on configuring the catalog index, including how to override the default image, use a private registry, or add extra catalog index images, see the [Catalog Index Configuration documentation](../../docs/catalog-index-configuration.md). +### NetworkPolicies + +This chart deploys a **default-deny** NetworkPolicy for the RHDH backend pod, blocking all ingress and egress traffic that is not explicitly allowed. When the built-in PostgreSQL is enabled (`postgresql.enabled=true`), the database pods also get their own default-deny policy with selective allow rules. + +The following traffic is allowed out of the box: + +| Direction | Port | Destination / Source | Purpose | +|-----------|------|----------------------|---------| +| Egress | 53, 5353 (UDP/TCP) | Any | DNS resolution | +| Egress | 443 (TCP) | Any | HTTPS (Git forges, auth providers, external APIs) | +| Egress | 5432 (TCP) | Built-in PostgreSQL pods (scoped) or any (external DB) | Database access | +| Egress | 6379 (TCP) | Any | Redis (BYO — no pod/namespace selector) | +| Ingress | 7007 (TCP) | OpenShift router namespace or any namespace (non-OCP) | User traffic via Route / Ingress | +| Ingress | 9464 (TCP) | `openshift-monitoring`, `openshift-user-workload-monitoring`, `gmp-system`, `gke-gmp-system`, `monitoring` | Prometheus metrics scraping | + +**Redis egress is intentionally unscoped.** RHDH does not deploy Redis; users bring their own instance, which may live in the same namespace, a different namespace, or an external managed service. The rule therefore allows egress on port 6379 to any destination. + +**Bitnami subchart NetworkPolicies are disabled** (`postgresql.primary.networkPolicy.enabled=false`, `postgresql.readReplicas.networkPolicy.enabled=false`) because this chart provides its own tighter policies for the built-in database pods. + +**Helm test NetworkPolicies** (`allow-test-connection` and `allow-test-connection-ingress`) are Helm test hooks: they are created just before `helm test` runs and cleaned up automatically on success. + +**Adding your own NetworkPolicies.** Kubernetes evaluates NetworkPolicies additively — if any policy allows a connection, the connection is permitted. You **cannot** tighten an existing allow rule by adding another NetworkPolicy; you can only broaden access. To restrict traffic further, you would need to modify or remove the chart's policies via values overrides or post-render patches. + +For more information on user workload monitoring on OpenShift, see [Configuring user workload monitoring](https://docs.redhat.com/en/documentation/monitoring_stack_for_red_hat_openshift/4.22/html/configuring_user_workload_monitoring/preparing-to-configure-the-monitoring-stack-uwm). + ### Intelligent Assistant Use `intelligentAssistant.enabled` to enable or disable the built-in Intelligent Assistant feature. diff --git a/charts/rhdh/templates/network-policies.yaml b/charts/rhdh/templates/network-policies.yaml index a4c9c9f11..e046a3eff 100644 --- a/charts/rhdh/templates/network-policies.yaml +++ b/charts/rhdh/templates/network-policies.yaml @@ -206,14 +206,17 @@ metadata: name: {{ include "rhdh.fullname" . }}-allow-test-connection labels: {{- include "rhdh.labels" . | nindent 4 }} - {{- with .Values.commonAnnotations }} annotations: + {{- with .Values.commonAnnotations }} {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} - {{- end }} + {{- end }} + helm.sh/hook: test + helm.sh/hook-weight: "-1" + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded spec: podSelector: matchLabels: - {{- include "rhdh.selectorLabels" . | nindent 6 }} + app.kubernetes.io/instance: {{ .Release.Name }} rhdh.redhat.com/test-connection: "true" policyTypes: - Egress @@ -233,10 +236,13 @@ metadata: name: {{ include "rhdh.fullname" . }}-allow-test-connection-ingress labels: {{- include "rhdh.labels" . | nindent 4 }} - {{- with .Values.commonAnnotations }} annotations: + {{- with .Values.commonAnnotations }} {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} - {{- end }} + {{- end }} + helm.sh/hook: test + helm.sh/hook-weight: "-1" + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded spec: podSelector: matchLabels: @@ -247,7 +253,7 @@ spec: - from: - podSelector: matchLabels: - {{- include "rhdh.selectorLabels" . | nindent 14 }} + app.kubernetes.io/instance: {{ .Release.Name }} rhdh.redhat.com/test-connection: "true" ports: - port: 7007 diff --git a/charts/rhdh/templates/orchestrator/network-policies.yaml b/charts/rhdh/templates/orchestrator/network-policies.yaml index cc05a7662..d20e38579 100644 --- a/charts/rhdh/templates/orchestrator/network-policies.yaml +++ b/charts/rhdh/templates/orchestrator/network-policies.yaml @@ -72,11 +72,11 @@ spec: - from: - podSelector: {} {{- end }} +{{- if .Values.orchestrator.enabled }} # Allow all egress from all pods in the namespace. # The Orchestrator backend plugin needs HTTP egress to reach SonataFlow and Data Index services; # SonataFlow workflows may also need arbitrary outbound access. --- -{{- if .Values.orchestrator.enabled }} apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: diff --git a/charts/rhdh/templates/tests/test-connection.yaml b/charts/rhdh/templates/tests/test-connection.yaml index 3ed604bea..1f3af3167 100644 --- a/charts/rhdh/templates/tests/test-connection.yaml +++ b/charts/rhdh/templates/tests/test-connection.yaml @@ -4,7 +4,7 @@ kind: Pod metadata: name: "{{ include "rhdh.fullname" . }}-test-connection" labels: - {{- include "rhdh.labels" . | nindent 4 }} + app.kubernetes.io/instance: {{ .Release.Name }} rhdh.redhat.com/test-connection: "true" annotations: {{- with .Values.commonAnnotations }} From 58df2344ebacbb2f40d6925b62d5bf28b4c401b5 Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Mon, 14 Sep 2026 18:34:27 +0200 Subject: [PATCH 13/13] fix(network-policies): add DNS egress to test connection NP The test pod no longer inherits backend NPs, so the test connection egress NP is the only policy selecting it. Without DNS ports, the pod cannot resolve the backend service name. Co-authored-by: Fortune Ndlovu Assisted-by: Claude --- charts/rhdh/templates/network-policies.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/charts/rhdh/templates/network-policies.yaml b/charts/rhdh/templates/network-policies.yaml index e046a3eff..5be32b576 100644 --- a/charts/rhdh/templates/network-policies.yaml +++ b/charts/rhdh/templates/network-policies.yaml @@ -221,6 +221,15 @@ spec: policyTypes: - Egress egress: + - ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + - port: 5353 + protocol: UDP + - port: 5353 + protocol: TCP - to: - podSelector: matchLabels: