Skip to content

feat(rhdh): add base NetworkPolicies for RHDH deployment [RHIDP-16476] - #523

Draft
rm3l wants to merge 10 commits into
redhat-developer:mainfrom
rm3l:RHIDP-16476--implement-base-networkpolicies-for-rhdh-helm-chart
Draft

feat(rhdh): add base NetworkPolicies for RHDH deployment [RHIDP-16476]#523
rm3l wants to merge 10 commits into
redhat-developer:mainfrom
rm3l:RHIDP-16476--implement-base-networkpolicies-for-rhdh-helm-chart

Conversation

@rm3l

@rm3l rm3l commented Sep 5, 2026

Copy link
Copy Markdown
Member

Description of the change

Add default-deny + selective-allow NetworkPolicies for the RHDH backend
and built-in PostgreSQL, replicating the operator's NP behavior
(RHIDP-16475, redhat-developer/rhdh-operator#3394) in the Helm chart.

Policies are always enabled (secure by default OOTB); customers can add
additive NPs as needed.

Disables the bitnami postgresql subchart's own NPs since they default to
allow-all egress and unrestricted ingress on 5432, which is too
permissive; our replacements are tighter.

Backend NPs (always created)

Policy Description
default-deny Block all ingress + egress for backend pods
allow-dns-egress Ports 53/5353 UDP+TCP
allow-https-egress Port 443 TCP
allow-redis-egress Port 6379 TCP (broad; no pod/namespace selector since users bring their own Redis)
allow-psql-egress Port 5432 TCP to DB pods (local DB) or broad egress on configured port (external DB)
allow-metrics-ingress Port 9464 TCP from monitoring namespaces
allow-router-ingress Port 7007 TCP; OpenShift-aware namespace selector

Test-connection NPs (only when test.enabled=true)

Policy Description
allow-test-connection Egress on port 7007 TCP from test pod to backend pods
allow-test-connection-ingress Ingress on port 7007 TCP to backend pods from test pod

The test-connection pod receives a dedicated rhdh.redhat.com/test-connection: "true" label
so that NPs can target it without relying on Helm-managed labels.

DB NPs (only when postgresql.enabled=true)

Policy Description
db-default-deny Block all ingress + egress for primary DB pods
db-allow-dns-egress DNS resolution for primary
db-allow-backend-ingress Port 5432 TCP from RHDH backend pods
db-allow-replication Bidirectional port 5432 between primary and read replicas (only when postgresql.architecture=replication)
db-read-default-deny Block all ingress + egress for read replica pods (replication only)
db-read-allow-dns-egress DNS resolution for read replicas (replication only)
db-read-allow-primary-egress Port 5432 TCP from read replicas to primary (replication only)
db-read-allow-backend-ingress Port 5432 TCP from RHDH backend to read replicas (replication only)

Orchestrator NPs (when orchestrator.enabled=true)

Policy Description
allow-all-egress Allow all egress from orchestrator namespace pods

External DB handling

When postgresql.enabled=false, the db-* NPs are omitted entirely.
The allow-psql-egress policy loses its to selector (broadening to
any destination) and uses externalDatabase.port instead of hardcoded
5432.

Which issue(s) does this PR fix or relate to

How to test changes / Special notes to the reviewer

Verify with helm template across scenarios:

# Default (standalone DB, tests enabled): 12 NPs (7 backend + 2 test + 3 DB)
helm template test charts/rhdh/ | grep -c 'kind: NetworkPolicy'

# Default (tests disabled): 10 NPs (7 backend + 3 DB)
helm template test charts/rhdh/ \
  --set test.enabled=false \
  | grep -c 'kind: NetworkPolicy'

# External DB: 9 NPs (7 backend + 2 test), correct port
helm template test charts/rhdh/ \
  --set postgresql.enabled=false \
  --set externalDatabase.host=ext-db \
  --set externalDatabase.port=5433 \
  --set externalDatabase.existingSecretRef.name=s \
  | grep -c 'kind: NetworkPolicy'

# Replication: 17 NPs (7 backend + 2 test + 3 primary + 1 replication + 4 read replica)
helm template test charts/rhdh/ \
  --set postgresql.architecture=replication \
  | grep -c 'kind: NetworkPolicy'

# Non-OpenShift: allow-router-ingress uses namespaceSelector: {}
helm template test charts/rhdh/ \
  --set openshift.route.enabled=false \
  | grep -A20 allow-router-ingress

# Orchestrator: includes allow-all-egress
helm template test charts/rhdh/ \
  --set orchestrator.enabled=true \
  | grep -c 'kind: NetworkPolicy'

No bitnami postgresql NPs should appear in any scenario.

Checklist

  • For each Chart updated, version bumped in the corresponding Chart.yaml according to Semantic Versioning.
  • For each Chart updated, variables are documented in the values.yaml and added to the corresponding README.md. The pre-commit utility can be used to generate the necessary content. Run pre-commit run --all-files to run the hooks and then push any resulting changes. The pre-commit Workflow will enforce this and warn you if needed.
  • JSON Schema template updated and re-generated the raw schema via the pre-commit hook.
  • Tests pass using the Chart Testing tool and the ct lint command.
  • If you updated the orchestrator-infra chart, make sure the versions of the Knative CRDs are aligned with the versions of the CRDs installed by the OpenShift Serverless operators declared in the values.yaml file. See Installing Knative Eventing and Knative Serving CRDs for more details.

Assisted-by: Claude

@rm3l

rm3l commented Sep 5, 2026

Copy link
Copy Markdown
Member Author

/agentic_review

@rhdh-qodo-merge

rhdh-qodo-merge Bot commented Sep 5, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Orchestrator permits all egress 🐞 Bug ⛨ Security
Description
When orchestrator is enabled, the new policy selects every pod in the release namespace and permits
unrestricted egress. This overrides the selective backend and PostgreSQL egress policies for RHDH,
the database, and unrelated colocated workloads.
Code

charts/rhdh/templates/orchestrator/network-policies.yaml[R80-81]

+  egress:
+    - {}
Relevance

●●● Strong

Unrestricted namespace-wide egress directly contradicts the PR's selective egress security model.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The added policy is enabled with the orchestrator, selects all namespace pods, and allows every
egress destination. That includes backend pods selected by the new default-deny policy and
PostgreSQL pods whose new policies are intended to permit only DNS and database traffic.

charts/rhdh/templates/orchestrator/network-policies.yaml[65-81]
charts/rhdh/templates/network-policies.yaml[11-17]
charts/rhdh/templates/network-policies.yaml[242-279]
charts/rhdh/templates/deployment.yaml[28-34]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The orchestrator allow-all-egress policy uses an empty pod selector and therefore grants unrestricted egress to every pod in the release namespace, defeating the newly added backend and PostgreSQL egress restrictions.

## Issue Context
NetworkPolicy allow rules are additive. Restrict the policy to reliably labeled orchestrator/workflow pods, or isolate those workloads in a separate namespace rather than selecting all RHDH, database, and unrelated pods.

## Fix Focus Areas
- charts/rhdh/templates/orchestrator/network-policies.yaml[65-81]
- charts/rhdh/templates/network-policies.yaml[11-101]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Orchestrator bypasses ingress isolation 🐞 Bug ⛨ Security
Description
The new default-deny ingress policy remains ineffective when orchestrator is enabled because
existing orchestrator policies select every namespace pod and allow same-namespace and
OpenShift-router traffic without port restrictions. Consequently, backend and PostgreSQL pods
receive ingress beyond the selective ports and sources introduced by this PR.
Code

charts/rhdh/templates/network-policies.yaml[R15-17]

+  policyTypes:
+    - Ingress
+    - Egress
Relevance

●●● Strong

Directly defeats this PR's stated selective ingress isolation and secure-by-default intent.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The PR adds ingress isolation for backend and database pods, but the enabled orchestrator policies
use podSelector: {}. One permits router namespaces to reach all selected pods on every port, while
another permits every same-namespace pod to reach them on every port, so both backend and database
isolation are bypassed.

charts/rhdh/templates/network-policies.yaml[11-17]
charts/rhdh/templates/network-policies.yaml[242-250]
charts/rhdh/templates/orchestrator/network-policies.yaml[26-44]
charts/rhdh/templates/orchestrator/network-policies.yaml[46-62]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new backend and database ingress isolation is bypassed by orchestrator policies whose empty pod selectors cover every pod in the release namespace and whose ingress rules have no port restrictions.

## Issue Context
NetworkPolicy rules are additive, so default-deny does not supersede the existing namespace-wide allows. Apply the orchestrator policies only to reliably labeled workflow workloads, or separate those workloads into their own namespace.

## Fix Focus Areas
- charts/rhdh/templates/network-policies.yaml[11-17]
- charts/rhdh/templates/orchestrator/network-policies.yaml[12-62]
- charts/rhdh/templates/network-policies.yaml[242-250]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Redis cache egress blocked ✓ Resolved 🔗 Cross-repo conflict ≡ Correctness
Description
The new default-deny policy isolates RHDH backend egress without allowing TCP 6379, while the
redhat-developer/rhdh showcase Helm workflow configures and deploys Redis at redis:6379.
Consequently, cache operations and the cross-repo Redis verification flow will fail after adopting
this chart version.
Code

charts/rhdh/templates/network-policies.yaml[R15-17]

+  policyTypes:
+    - Ingress
+    - Egress
Relevance

●●● Strong

Configured Redis traffic is objectively omitted from the backend's newly enforced egress allowlist.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The PR applies egress isolation to backend pods and only permits DNS, HTTPS, and database traffic.
The RHDH repository's active Helm CI path deploys Redis, installs with the showcase values, mounts
an application configuration pointing to Redis on port 6379, and exposes that service on port 6379.

charts/rhdh/templates/network-policies.yaml[11-17]
charts/rhdh/templates/network-policies.yaml[35-44]
charts/rhdh/templates/network-policies.yaml[62-65]
charts/rhdh/templates/network-policies.yaml[83-101]
External repo: redhat-developer/rhdh, .ci/pipelines/cluster/eks/eks-helm-deployment.sh [22-43]
External repo: redhat-developer/rhdh, .ci/pipelines/utils.sh [384-388]
External repo: redhat-developer/rhdh, .ci/pipelines/value_files/values_showcase.yaml [92-95]
External repo: redhat-developer/rhdh, .ci/pipelines/resources/config_map/app-config-rhdh.yaml [54-56]
External repo: redhat-developer/rhdh, .ci/pipelines/resources/redis-cache/redis-deployment.yaml [53-64]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The always-on backend NetworkPolicy blocks the Redis cache used by the RHDH repository's current Helm showcase deployment because TCP 6379 is not included in the permitted egress rules.

## Issue Context
The RHDH CI workflow deploys a same-namespace Redis service labeled `app: redis`, mounts an application configuration using `redis:6379`, and then installs this Helm chart. Preserve restrictive defaults while providing an explicit Redis rule or configurable extra-egress mechanism, and coordinate the RHDH showcase values to enable it if it is not automatic.

## Fix Focus Areas
- charts/rhdh/templates/network-policies.yaml[11-17]
- charts/rhdh/templates/network-policies.yaml[46-101]
- charts/rhdh/values.yaml[421-459]
- .ci/pipelines/resources/config_map/app-config-rhdh.yaml[54-56]
- .ci/pipelines/resources/redis-cache/redis-deployment.yaml[53-64]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. User metrics scraping blocked 🐞 Bug ◔ Observability
Description
The metrics ingress policy omits openshift-user-workload-monitoring, whose pods scrape
user-namespace ServiceMonitors on OpenShift. Enabling metrics.serviceMonitor can therefore create
a valid ServiceMonitor while the new default-deny policy blocks its scraper from port 9464.
Code

charts/rhdh/templates/network-policies.yaml[R121-123]

+        - namespaceSelector:
+            matchLabels:
+              kubernetes.io/metadata.name: openshift-monitoring
Relevance

●●● Strong

Existing chart policy precedent explicitly permits this namespace, supporting the missing scraper
allow rule.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The chart creates a ServiceMonitor targeting the RHDH metrics service, but the added ingress policy
only permits four other monitoring namespaces. Existing chart policy code explicitly allows
openshift-user-workload-monitoring for OpenShift monitoring traffic, demonstrating that this
source namespace must be accommodated.

charts/rhdh/templates/network-policies.yaml[119-135]
charts/rhdh/templates/servicemonitor.yaml[20-32]
charts/rhdh/templates/orchestrator/network-policies.yaml[84-103]
charts/backstage/templates/network-policies.yaml[62-80]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The backend metrics NetworkPolicy does not allow ingress from OpenShift's `openshift-user-workload-monitoring` namespace, preventing the chart's ServiceMonitor from being scraped there.

## Issue Context
The repository's existing orchestrator monitoring policy explicitly identifies this namespace as the source of user-workload monitoring traffic. Add it to the backend metrics source selectors while retaining the TCP 9464 restriction.

## Fix Focus Areas
- charts/rhdh/templates/network-policies.yaml[119-135]
- charts/rhdh/templates/servicemonitor.yaml[20-32]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Cross-repo context — repo relationships
  Explored: repo: redhat-developer/rhdh (sha: d89b1f2b)

Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Finding overflow, which tucks the rest behind 'View more'

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

rm3l added 10 commits September 5, 2026 22:33
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
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
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
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
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
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
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
…parator

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
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
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
@rm3l
rm3l force-pushed the RHIDP-16476--implement-base-networkpolicies-for-rhdh-helm-chart branch from d2f21fb to a654f04 Compare September 5, 2026 21:19
@sonarqubecloud

sonarqubecloud Bot commented Sep 5, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant