diff --git a/bundle/backstage.io/manifests/backstage-operator.clusterserviceversion.yaml b/bundle/backstage.io/manifests/backstage-operator.clusterserviceversion.yaml index 44f2d536e..434693256 100644 --- a/bundle/backstage.io/manifests/backstage-operator.clusterserviceversion.yaml +++ b/bundle/backstage.io/manifests/backstage-operator.clusterserviceversion.yaml @@ -25,7 +25,7 @@ metadata: } } ] - createdAt: "2026-09-23T14:16:34Z" + createdAt: "2026-09-24T09:33:33Z" description: Backstage Operator operators.operatorframework.io/builder: operator-sdk-v1.42.2 operators.operatorframework.io/project_layout: go.kubebuilder.io/v4 diff --git a/bundle/rhdh/manifests/backstage-operator.clusterserviceversion.yaml b/bundle/rhdh/manifests/backstage-operator.clusterserviceversion.yaml index 5e0797a8b..a1f83f2ed 100644 --- a/bundle/rhdh/manifests/backstage-operator.clusterserviceversion.yaml +++ b/bundle/rhdh/manifests/backstage-operator.clusterserviceversion.yaml @@ -42,7 +42,7 @@ metadata: categories: Developer Tools certified: "true" containerImage: registry.redhat.io/rhdh/rhdh-rhel10-operator:2.0 - createdAt: "2026-09-23T14:16:37Z" + createdAt: "2026-09-24T09:33:34Z" description: Red Hat Developer Hub is a Red Hat supported version of Backstage. It comes with pre-built plug-ins and configuration settings, supports use of an external database, and can help streamline the process of setting up a self-managed diff --git a/bundle/rhdh/manifests/rhdh-default-config_v1_configmap.yaml b/bundle/rhdh/manifests/rhdh-default-config_v1_configmap.yaml index 84c1123e7..71ca302f0 100644 --- a/bundle/rhdh/manifests/rhdh-default-config_v1_configmap.yaml +++ b/bundle/rhdh/manifests/rhdh-default-config_v1_configmap.yaml @@ -431,6 +431,27 @@ data: - port: 443 protocol: TCP + --- + # Internal HTTP egress: plugins that talk to in-cluster services behind plain + # HTTP routes or services (e.g., Keycloak without TLS termination) need port 80. + # Restricted to cluster-internal destinations via namespaceSelector. + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + name: allow-http-egress + spec: + podSelector: + matchLabels: + rhdh.redhat.com/app: backstage # replaced at runtime with 'backstage-' + policyTypes: + - Egress + egress: + - to: + - namespaceSelector: {} + ports: + - port: 80 + 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). diff --git a/config/profile/rhdh/default-config/networkpolicy.yaml b/config/profile/rhdh/default-config/networkpolicy.yaml index b58ba4016..97ede9b48 100644 --- a/config/profile/rhdh/default-config/networkpolicy.yaml +++ b/config/profile/rhdh/default-config/networkpolicy.yaml @@ -53,6 +53,27 @@ spec: - port: 443 protocol: TCP +--- +# Internal HTTP egress: plugins that talk to in-cluster services behind plain +# HTTP routes or services (e.g., Keycloak without TLS termination) need port 80. +# Restricted to cluster-internal destinations via namespaceSelector. +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-http-egress +spec: + podSelector: + matchLabels: + rhdh.redhat.com/app: backstage # replaced at runtime with 'backstage-' + policyTypes: + - Egress + egress: + - to: + - namespaceSelector: {} + ports: + - port: 80 + 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). diff --git a/dist/rhdh/install.yaml b/dist/rhdh/install.yaml index 86ec29321..26a0a3610 100644 --- a/dist/rhdh/install.yaml +++ b/dist/rhdh/install.yaml @@ -3254,6 +3254,27 @@ data: - port: 443 protocol: TCP + --- + # Internal HTTP egress: plugins that talk to in-cluster services behind plain + # HTTP routes or services (e.g., Keycloak without TLS termination) need port 80. + # Restricted to cluster-internal destinations via namespaceSelector. + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + name: allow-http-egress + spec: + podSelector: + matchLabels: + rhdh.redhat.com/app: backstage # replaced at runtime with 'backstage-' + policyTypes: + - Egress + egress: + - to: + - namespaceSelector: {} + ports: + - port: 80 + 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). diff --git a/docs/configuration.md b/docs/configuration.md index 73237e7b6..b86f1527d 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -229,6 +229,7 @@ For example, Backstage CR named **mybackstage** will create K8s Deployment resou - The placeholder value in `podSelector.matchLabels` (`backstage` vs `backstage-psql`) determines whether a policy targets the backend or the database at runtime - DB-scoped policies are filtered out when `spec.database.enableLocalDb` is `false` - When local DB is disabled, the `allow-psql-egress` policy allows egress on port 5432 to any destination (for external databases) + - The `allow-http-egress` policy allows egress on port 80 TCP to in-cluster destinations only (`namespaceSelector: {}`), for services behind plain HTTP routes or services (e.g., Keycloak without TLS termination) - The `allow-redis-egress` policy allows egress on port 6379 TCP to any destination (Redis is not deployed by the operator; users bring their own) - The `allow-metrics-ingress` policy allows ingress on port 9464 from `openshift-monitoring`, `openshift-user-workload-monitoring`, GKE GMP namespaces (`gmp-system`, `gke-gmp-system`), and `monitoring` (kube-prometheus-stack convention) - On OpenShift, the `allow-router-ingress` policy's `namespaceSelector` is set to `policy-group.network.openshift.io/ingress: ""` diff --git a/pkg/model/networkpolicy_test.go b/pkg/model/networkpolicy_test.go index 6ac383d76..279644213 100644 --- a/pkg/model/networkpolicy_test.go +++ b/pkg/model/networkpolicy_test.go @@ -33,7 +33,7 @@ func TestDefaultNetworkPolicies(t *testing.T) { assert.NotNil(t, obj) mo := obj.Object().(*multiobject.MultiObject) - assert.Equal(t, 10, len(mo.Items), "expected 7 backend + 3 DB NPs") + assert.Equal(t, 11, len(mo.Items), "expected 8 backend + 3 DB NPs") backendLabel := utils.BackstageAppLabelValue(bs.Name) dbLabel := utils.BackstageDbAppLabelValue(bs.Name) @@ -48,7 +48,7 @@ func TestDefaultNetworkPolicies(t *testing.T) { backendCount++ } } - assert.Equal(t, 7, backendCount, "expected 7 backend NPs") + assert.Equal(t, 8, backendCount, "expected 8 backend NPs") assert.Equal(t, 3, dbCount, "expected 3 DB NPs") } @@ -63,7 +63,7 @@ func TestNetworkPoliciesWithoutLocalDb(t *testing.T) { assert.NotNil(t, obj) mo := obj.Object().(*multiobject.MultiObject) - assert.Equal(t, 7, len(mo.Items), "expected only 7 backend NPs when localDb is disabled") + assert.Equal(t, 8, len(mo.Items), "expected only 8 backend NPs when localDb is disabled") backendLabel := utils.BackstageAppLabelValue(testObj.backstage.Name) for _, item := range mo.Items { @@ -218,7 +218,7 @@ func TestNetworkPolicyFlavourMergePreservesNamespaceWidePodSelector(t *testing.T assert.NotNil(t, obj) mo := obj.Object().(*multiobject.MultiObject) - assert.Equal(t, 8, len(mo.Items), "expected 7 backend + 1 flavour NP (DB NPs filtered out)") + assert.Equal(t, 9, len(mo.Items), "expected 8 backend + 1 flavour NP (DB NPs filtered out)") backendLabel := utils.BackstageAppLabelValue(testObj.backstage.Name) var foundNamespaceWide bool diff --git a/pkg/model/testdata/default-config/networkpolicy.yaml b/pkg/model/testdata/default-config/networkpolicy.yaml index 3af990a9f..ba227df8c 100644 --- a/pkg/model/testdata/default-config/networkpolicy.yaml +++ b/pkg/model/testdata/default-config/networkpolicy.yaml @@ -48,6 +48,23 @@ spec: --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy +metadata: + name: allow-http-egress +spec: + podSelector: + matchLabels: + rhdh.redhat.com/app: backstage + policyTypes: + - Egress + egress: + - to: + - namespaceSelector: {} + ports: + - port: 80 + protocol: TCP +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy metadata: name: allow-redis-egress spec: diff --git a/pkg/model/testdata/testflavours/default-config/networkpolicy.yaml b/pkg/model/testdata/testflavours/default-config/networkpolicy.yaml index 3af990a9f..ba227df8c 100644 --- a/pkg/model/testdata/testflavours/default-config/networkpolicy.yaml +++ b/pkg/model/testdata/testflavours/default-config/networkpolicy.yaml @@ -48,6 +48,23 @@ spec: --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy +metadata: + name: allow-http-egress +spec: + podSelector: + matchLabels: + rhdh.redhat.com/app: backstage + policyTypes: + - Egress + egress: + - to: + - namespaceSelector: {} + ports: + - port: 80 + protocol: TCP +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy metadata: name: allow-redis-egress spec: