From fcd6d3aaf73b3b83edb5e587e5dff44c55815211 Mon Sep 17 00:00:00 2001 From: Anatolii Bazko Date: Wed, 22 Jul 2026 12:22:49 +0200 Subject: [PATCH 1/7] chore: Add NetworkPolicy reconciler Signed-off-by: Anatolii Bazko --- .claude/rules/api-types.md | 8 +- .claude/rules/build-and-test.md | 10 + .claude/rules/code-style.md | 6 + .claude/rules/k8s-client.md | 8 + .claude/rules/kubebuilder-defaults.md | 5 + .claude/rules/reconcilers.md | 10 +- .claude/rules/redhat-compliance.md | 6 + .claude/rules/resource-naming.md | 4 + .claude/rules/testing.md | 6 + AGENTS.md | 70 +---- api/v2/checluster_types.go | 28 ++ api/v2/zz_generated.deepcopy.go | 20 ++ .../org.eclipse.che_checlusters.yaml | 22 ++ .../bases/org.eclipse.che_checlusters.yaml | 22 ++ controllers/che/checluster_controller.go | 3 + .../usernamespace/usernamespace_controller.go | 264 +++++++++++++++++- ...espace_controller_network_policies_test.go | 219 +++++++++++++++ .../usernamespace_controller_setup_test.go | 168 +++++++++++ .../usernamespace_controller_test.go | 138 --------- deploy/deployment/kubernetes/combined.yaml | 22 ++ ....eclipse.che.CustomResourceDefinition.yaml | 22 ++ deploy/deployment/openshift/combined.yaml | 22 ++ ....eclipse.che.CustomResourceDefinition.yaml | 22 ++ ....eclipse.che.CustomResourceDefinition.yaml | 22 ++ .../next/templates/org_v2_checluster.yaml | 1 + pkg/common/diffs/diffs.go | 4 + pkg/common/k8s-client/k8s_client.go | 12 + pkg/common/k8s-client/k8s_client_types.go | 3 + pkg/common/test/test-client/test_client.go | 1 + .../container_capabilities.go | 2 +- pkg/deploy/labels.go | 6 +- pkg/deploy/networkpolicies/init_test.go | 26 ++ pkg/deploy/networkpolicies/networkpolicies.go | 161 +++++++++++ .../networkpolicies/networkpolicies_test.go | 95 +++++++ pkg/deploy/openvsx/openvsx_secret.go | 2 +- 35 files changed, 1218 insertions(+), 222 deletions(-) create mode 100644 .claude/rules/build-and-test.md create mode 100644 .claude/rules/code-style.md create mode 100644 .claude/rules/k8s-client.md create mode 100644 .claude/rules/kubebuilder-defaults.md create mode 100644 .claude/rules/redhat-compliance.md create mode 100644 .claude/rules/resource-naming.md create mode 100644 .claude/rules/testing.md create mode 100644 controllers/usernamespace/usernamespace_controller_network_policies_test.go create mode 100644 controllers/usernamespace/usernamespace_controller_setup_test.go create mode 100644 pkg/deploy/networkpolicies/init_test.go create mode 100644 pkg/deploy/networkpolicies/networkpolicies.go create mode 100644 pkg/deploy/networkpolicies/networkpolicies_test.go diff --git a/.claude/rules/api-types.md b/.claude/rules/api-types.md index daa7cd23e5..aceb843adc 100644 --- a/.claude/rules/api-types.md +++ b/.claude/rules/api-types.md @@ -1,11 +1,7 @@ ---- -paths: - - "api/**" ---- - # API Types Rules -- After modifying `api/v2/checluster_types.go`, always run `build/scripts/docker-run.sh make update-dev-resources` to regenerate CRDs, DeepCopy methods, and related manifests. +- After modifying `api/v2/checluster_types.go`, always run `make update-dev-resources` +(or `build/scripts/docker-run.sh make update-dev-resources` on macOS) to regenerate CRDs, DeepCopy methods, and related manifests. - v2 is the storage version. v1 exists only for conversion compatibility and does not need to be updated. - Webhook validation and defaulting logic live in `api/v2/checluster_webhook.go`. - `zz_generated.deepcopy.go` files are generated by `controller-gen` — never edit them manually. diff --git a/.claude/rules/build-and-test.md b/.claude/rules/build-and-test.md new file mode 100644 index 0000000000..ad7b3365b6 --- /dev/null +++ b/.claude/rules/build-and-test.md @@ -0,0 +1,10 @@ +# Build & Test Commands + +- Build: `make build` +- All unit tests: `make test` +- Single package: `MOCK_API=true go test -mod=vendor ./package/...` +- Single test: `MOCK_API=true go test -mod=vendor ./package/... -run TestSpecificName -v` +- Format: `make fmt` +- Vet: `make vet` +- Lint: `make lint` +- After making changes, always build and run the relevant tests before reporting the task as complete. diff --git a/.claude/rules/code-style.md b/.claude/rules/code-style.md new file mode 100644 index 0000000000..197b2a2b47 --- /dev/null +++ b/.claude/rules/code-style.md @@ -0,0 +1,6 @@ +# Code Style Rules + +- Add an empty line after logical blocks of code (e.g., after `if` blocks, loops, variable declaration groups) to improve readability. +- Wrap errors with context using `fmt.Errorf` at every call site instead of passing them through directly — this applies both inside the function and at the caller. When the object has a namespace, include it as `namespace/name` in the message. Use `return fmt.Errorf("failed to sync deployment %s/%s: %w", obj.Namespace, obj.Name, err)` instead of `return err`. +- Lines should not exceed 120 characters. If a function call exceeds this limit, put each argument on its own line. This does not apply to `fmt.Errorf`, `fmt.Sprintf`, and similar formatting functions — keep those on one line. +- Use `deploy.GetLabels(component)` for labeling resources in `pkg/deploy/` reconcilers. diff --git a/.claude/rules/k8s-client.md b/.claude/rules/k8s-client.md new file mode 100644 index 0000000000..053ab6e772 --- /dev/null +++ b/.claude/rules/k8s-client.md @@ -0,0 +1,8 @@ +# K8s Client Rules + +- Use the `K8sClient` wrapper (`pkg/common/k8s-client/`) for all Kubernetes operations. +- Access it via `DeployContext.ClusterAPI.ClientWrapper` (cached) or `DeployContext.ClusterAPI.NonCachingClientWrapper` (non-caching). +- **Do NOT use** the legacy functions from `pkg/deploy/sync.go` (`deploy.Sync`, `deploy.Get*`, `deploy.Delete*`, `deploy.CreateIgnoreIfExists`) — that file is deprecated. +- When using `Sync` to create/update an object in the **same namespace** as the CheCluster CR, set the owner reference before syncing: `controllerutil.SetControllerReference(ctx.CheCluster, obj, ctx.ClusterAPI.Scheme)`. Do **not** set owner references on objects in other namespaces (cross-namespace owner references are not supported by Kubernetes). +- When using `Sync`, always pass `&k8sclient.SyncOptions{DiffOpts: diffs.}` to control which fields are compared. Diff options live in `pkg/common/diffs/diffs.go`. If no diff option exists for the resource type, add one there first. +- When deleting, use `DeleteByKeyIgnoreNotFound` for idempotent cleanup (e.g., toggling a feature off). diff --git a/.claude/rules/kubebuilder-defaults.md b/.claude/rules/kubebuilder-defaults.md new file mode 100644 index 0000000000..9591863b3d --- /dev/null +++ b/.claude/rules/kubebuilder-defaults.md @@ -0,0 +1,5 @@ +# Kubebuilder Default Propagation Rule + +- When adding a `+kubebuilder:default` annotation to a field, propagate the default up to every parent struct's `+kubebuilder:default` annotation as well. +- If the parent struct already has a `+kubebuilder:default`, add the new nested default to it. If it doesn't, add one. +- This is required because kubebuilder only applies a field's default when its parent object is non-nil. A pointer field (`*Foo`) with a default on its inner fields has no effect if the parent's default doesn't instantiate it. diff --git a/.claude/rules/reconcilers.md b/.claude/rules/reconcilers.md index 61a08d5ca9..f38e7bdd88 100644 --- a/.claude/rules/reconcilers.md +++ b/.claude/rules/reconcilers.md @@ -1,14 +1,8 @@ ---- -paths: - - "pkg/deploy/**" - - "controllers/che/**" ---- - # Reconciler Rules - Every component reconciler implements the `Reconcilable` interface (`pkg/common/reconciler/reconcile_manager.go`): `Reconcile()` and `Finalize()`. -- `Reconcile()` returns `(result, done, err)` — return `done=true` only when the component is fully reconciled. -The pipeline stops at the first `done=false`. Use `RequeueAfter: time.Second` in `result` for error recovery and when dealing with cluster-scoped objects. +- `Reconcile()` returns `(result, done, err)` — return `done=true` only when the component is fully reconciled. The pipeline stops at the first `done=false`. Use `RequeueAfter: time.Second` in `result` for error recovery and when dealing with cluster-scoped objects. - Registration order in `controllers/che/checluster_controller.go` matters — reconcilers run sequentially and may depend on earlier ones having completed. - All reconcilers receive `DeployContext` (`pkg/common/chetypes/types.go`) — use its `ClusterAPI` clients for k8s operations, not standalone clients. - Some reconcilers are OpenShift-only (consolelink, container-capabilities) — guard with `infrastructure.IsOpenShift()`. +- The usernamespace controller (`controllers/usernamespace/`) is a separate controller, not a `Reconcilable` — it has its own `Reconcile(ctx, req)` method and manages per-user namespace resources. diff --git a/.claude/rules/redhat-compliance.md b/.claude/rules/redhat-compliance.md new file mode 100644 index 0000000000..66672c733f --- /dev/null +++ b/.claude/rules/redhat-compliance.md @@ -0,0 +1,6 @@ +# Red Hat Compliance Rules + +- If a code suggestion matches known open-source code, include the original license text and copyright notice. Do not suggest code whose license compatibility with EPL-2.0 cannot be verified. +- When suggesting commit messages, include `Assisted-by: {AGENT_NAME}` trailer (e.g., `Assisted-by: Claude Opus 4.6`). +- Never include credentials, tokens, or secrets in code. +- All new Go files must include the EPL-2.0 copyright header (copy from any existing file in the repo). This does not apply to files in the `vendor/` directory. diff --git a/.claude/rules/resource-naming.md b/.claude/rules/resource-naming.md new file mode 100644 index 0000000000..9bbac52f58 --- /dev/null +++ b/.claude/rules/resource-naming.md @@ -0,0 +1,4 @@ +# Resource Naming Rules + +- Resource names must not hardcode `eclipse-che`, `che`, or `devspaces`. Use `defaults.GetCheFlavor()` (from `pkg/common/operator-defaults`) to make names work for both upstream (`eclipse-che`/`che`) and downstream (`devspaces`). +- This applies to Kubernetes object names, label values, and any string embedded in resource specs that identifies the product. Constants like `constants.CheEclipseOrg` are fine — they are shared across both flavors. diff --git a/.claude/rules/testing.md b/.claude/rules/testing.md new file mode 100644 index 0000000000..3f5070ba1e --- /dev/null +++ b/.claude/rules/testing.md @@ -0,0 +1,6 @@ +# Testing Rules + +- Use `test.NewCtxBuilder()` to create test `DeployContext` instances with a fake k8s client. +- Use `infrastructure.InitializeForTesting(infrastructure.OpenShiftV4)` or `infrastructure.Kubernetes` to set the platform. Use OpenShift when testing OpenShift-specific resources (e.g., network policies with `infrastructure.IsOpenShift()` guards). +- Use `defaults.InitializeForTesting("../../config/manager/manager.yaml")` in `init_test.go` (adjust relative path) to load operator defaults for `GetCheFlavor()` and other defaults. +- Tests are co-located with source files (`*_test.go`). Test helpers live in `pkg/common/test/`. diff --git a/AGENTS.md b/AGENTS.md index 18ddbac05a..5d0abef984 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,56 +1,24 @@ # AGENTS.md -This file provides guidance to AI coding agents when working with code in this repository. +This file provides architectural context for AI coding agents working in this repository. +Actionable rules (build commands, code style, K8s client usage, compliance) live in `.claude/rules/`. ## Project Overview -Eclipse Che Operator — a Kubernetes/OpenShift operator built with Operator SDK and controller-runtime that manages -the lifecycle of Eclipse Che installations. It watches `CheCluster` custom resources and reconciles all Che components +Eclipse Che Operator — a Kubernetes/OpenShift operator built with Operator SDK and controller-runtime that manages +the lifecycle of Eclipse Che installations. It watches `CheCluster` custom resources and reconciles all Che components (dashboard, gateway, devfile registry, Che server, etc.). Go module: `github.com/eclipse-che/che-operator` -## Build & Test Commands - -```bash -# Build operator binary -make build - -# Run all unit tests -make test - -# Run a single test file or package -MOCK_API=true go test -mod=vendor ./controllers/che/... -run TestSpecificName -v - -# Run tests for a specific package -MOCK_API=true go test -mod=vendor ./pkg/deploy/gateway/... - -# Format code (uses goimports if available, falls back to go fmt) -make fmt - -# Run go vet -make vet - -# Run static code analyzers -make lint - -# Regenerate CRDs, DeepCopy methods, and related manifests -build/scripts/docker-run.sh make update-dev-resources - -# Build operator Docker image -make docker-build IMG= -``` - ## Architecture ### CRD & API Versions - **v2** (`api/v2/`) — current storage version. `CheClusterSpec` has top-level sections: `DevEnvironments`, `Components`, `GitServices`, `Networking`, `ContainerRegistry`. -- **v1** (`api/v1/`) — deprecated +- **v1** (`api/v1/`) — deprecated, exists only for conversion compatibility. - Webhooks (validation, defaulting, conversion) live in `api/v2/checluster_webhook.go`. -After modifying `api/v2/checluster_types.go`, run `build/scripts/docker-run.sh make update-dev-resources`. - ### Controller Structure **Entry point:** `cmd/main.go` — registers four controllers with the manager: @@ -62,24 +30,18 @@ After modifying `api/v2/checluster_types.go`, run `build/scripts/docker-run.sh m ### Reconciliation Pipeline -`CheClusterReconciler` uses a `ReconcilerManager` (`pkg/common/reconciler/`) that runs a chain of -`Reconcilable` implementations **in order**. Each reconciler returns `(result, done, err)` — the chain stops -at the first `done=false`. Registration order in `controllers/che/checluster_controller.go` defines the execution order: +`CheClusterReconciler` uses a `ReconcilerManager` (`pkg/common/reconciler/`) that runs a chain of +`Reconcilable` implementations **in order**. Each reconciler returns `(result, done, err)` — the chain stops +at the first `done=false`. Registration order in `controllers/che/checluster_controller.go` defines the execution order. ### DeployContext `DeployContext` (`pkg/common/chetypes/types.go`) is the central context object passed to every reconciler. It carries: - `CheCluster` — the CR being reconciled -- `ClusterAPI` — cached and non-cached k8s clients, discovery client +- `ClusterAPI` — cached and non-cached k8s clients, discovery client, `ClientWrapper` / `NonCachingClientWrapper` - `Proxy`, `Authentication` — resolved configuration - `IsSelfSignedCertificate`, `CheHost`, `DwoNamespace` -### Kubernetes Client Usage - -Use the `K8sClient` wrapper (`pkg/common/k8s-client/`) for all Kubernetes operations. Access it via `DeployContext.ClusterAPI.ClientWrapper` (cached) or `DeployContext.ClusterAPI.NonCachingClientWrapper` (non-caching, for cluster-scoped or cross-namespace objects). Key methods: `Sync`, `Create`, `CreateIfNotExists`, `GetIgnoreNotFound`, `DeleteByKeyIgnoreNotFound`, `List`. - -**Do NOT use** the legacy functions from `pkg/deploy/sync.go` (`deploy.Sync`, `deploy.Get*`, `deploy.Delete*`, `deploy.CreateIgnoreIfExists`, etc.) — that file is deprecated. - ### Component Packages (`pkg/deploy/`) Each Che component has its own package under `pkg/deploy/` (e.g., `dashboard/`, `gateway/`, `postgres/`, `identity-provider/`, `server/`). Each package typically contains: @@ -89,12 +51,12 @@ Each Che component has its own package under `pkg/deploy/` (e.g., `dashboard/`, ### Platform Detection -`pkg/common/infrastructure/` detects Kubernetes vs OpenShift and feature availability (OAuth, image puller, service monitors). +`pkg/common/infrastructure/` detects Kubernetes vs OpenShift and feature availability (OAuth, image puller, service monitors). Some reconcilers are conditionally registered based on platform (e.g., `ConsoleLink` and `ContainerCapabilities` are OpenShift-only). ### Operator Defaults -`pkg/common/operator-defaults/` reads default container images and configuration from environment variables. +`pkg/common/operator-defaults/` reads default container images and configuration from environment variables. Resource limit/request defaults live in `pkg/common/constants/`. ### Testing @@ -119,13 +81,3 @@ build/scripts/olm/test-catalog-from-sources.sh # Minikube build/scripts/minikube-tests/test-operator-from-sources.sh ``` - -## Code Style - -- Add an empty line after logical blocks of code (e.g., after `if` blocks, loops, variable declaration groups) to improve readability. -- Wrap errors with context using `fmt.Errorf` instead of passing them through directly. For example, use `return fmt.Errorf("failed to sync deployment: %w", err)` instead of `return err`. -- After modifying `api/v2/checluster_types.go`, run `make update-dev-resources` to regenerate CRDs, DeepCopy methods, and related manifests. On macOS, use `build/scripts/docker-run.sh make update-dev-resources` instead. - -## Red Hat Compliance and Responsible AI Rules - -See [redhat-compliance-and-responsible-ai.md](redhat-compliance-and-responsible-ai.md) and the Cursor rules file under `.cursor/rules/`. diff --git a/api/v2/checluster_types.go b/api/v2/checluster_types.go index b7ccbc1896..cc54e0eb9a 100644 --- a/api/v2/checluster_types.go +++ b/api/v2/checluster_types.go @@ -329,6 +329,22 @@ type CheClusterSpecNetworking struct { // +optional // +kubebuilder:default:={gateway: {configLabels: {app: che, component: che-gateway-config}}} Auth Auth `json:"auth"` + // NetworkPolicies configures NetworkPolicy resources for the Che namespace + // and user workspace namespaces. + // When enabled, the following Ingress-only allow policies are created: + // In the Che namespace: + // - allow-from-same-namespace: allows traffic between pods in the same namespace. + // - allow-from-workspaces-namespaces: allows traffic from user workspace namespaces + // (namespaces labeled app.kubernetes.io/component=workspaces-namespace). + // In each user workspace namespace: + // - allow-from-: allows traffic from the Che namespace. + // - allow-from-operators: allows traffic from the operators namespace. + // - allow-from-same-namespace: allows traffic between pods in the same namespace. + // On OpenShift, these additional policies are also created in each user workspace namespace: + // - allow-from-openshift-monitoring: allows traffic from the monitoring namespace. + // - allow-from-openshift-ingress: allows traffic from the ingress namespace. + // +optional + NetworkPolicies *NetworkPolicies `json:"networkPolicies,omitempty"` } type DevEnvironmentNetworking struct { @@ -337,6 +353,14 @@ type DevEnvironmentNetworking struct { ExternalTLSConfig *ExternalTLSConfig `json:"externalTLSConfig,omitempty"` } +// NetworkPolicies configuration settings. +// +k8s:openapi-gen=true +type NetworkPolicies struct { + // Enabled controls whether the operator creates NetworkPolicy resources. + // +optional + Enabled bool `json:"enabled"` +} + type ExternalTLSConfig struct { // Enabled determines whether external TLS configuration is used. // If set to true, the operator will not set TLS config for ingress/route objects. @@ -1259,3 +1283,7 @@ func (c *CheCluster) IsDevEnvironmentExternalTLSConfigEnabled() bool { c.Spec.DevEnvironments.Networking.ExternalTLSConfig != nil && *c.Spec.DevEnvironments.Networking.ExternalTLSConfig.Enabled } + +func (c *CheCluster) IsNetworkPoliciesEnabled() bool { + return c.Spec.Networking.NetworkPolicies != nil && c.Spec.Networking.NetworkPolicies.Enabled +} diff --git a/api/v2/zz_generated.deepcopy.go b/api/v2/zz_generated.deepcopy.go index 37951e91c1..bd94371469 100644 --- a/api/v2/zz_generated.deepcopy.go +++ b/api/v2/zz_generated.deepcopy.go @@ -521,6 +521,11 @@ func (in *CheClusterSpecNetworking) DeepCopyInto(out *CheClusterSpecNetworking) } } in.Auth.DeepCopyInto(&out.Auth) + if in.NetworkPolicies != nil { + in, out := &in.NetworkPolicies, &out.NetworkPolicies + *out = new(NetworkPolicies) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CheClusterSpecNetworking. @@ -1071,6 +1076,21 @@ func (in *KubeRbacProxy) DeepCopy() *KubeRbacProxy { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkPolicies) DeepCopyInto(out *NetworkPolicies) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPolicies. +func (in *NetworkPolicies) DeepCopy() *NetworkPolicies { + if in == nil { + return nil + } + out := new(NetworkPolicies) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OAuthProxy) DeepCopyInto(out *OAuthProxy) { *out = *in diff --git a/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml b/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml index dfe7f209a4..cb62013965 100644 --- a/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml +++ b/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml @@ -27968,6 +27968,28 @@ spec: description: Defines labels which will be set for an Ingress (a route for OpenShift platform). type: object + networkPolicies: + description: |- + NetworkPolicies configures NetworkPolicy resources for the Che namespace + and user workspace namespaces. + When enabled, the following Ingress-only allow policies are created: + In the Che namespace: + - allow-from-same-namespace: allows traffic between pods in the same namespace. + - allow-from-workspaces-namespaces: allows traffic from user workspace namespaces + (namespaces labeled app.kubernetes.io/component=workspaces-namespace). + In each user workspace namespace: + - allow-from-: allows traffic from the Che namespace. + - allow-from-operators: allows traffic from the operators namespace. + - allow-from-same-namespace: allows traffic between pods in the same namespace. + On OpenShift, these additional policies are also created in each user workspace namespace: + - allow-from-openshift-monitoring: allows traffic from the monitoring namespace. + - allow-from-openshift-ingress: allows traffic from the ingress namespace. + properties: + enabled: + description: Enabled controls whether the operator creates + NetworkPolicy resources. + type: boolean + type: object tlsSecretName: description: |- The name of the secret used to set up Ingress TLS termination. diff --git a/config/crd/bases/org.eclipse.che_checlusters.yaml b/config/crd/bases/org.eclipse.che_checlusters.yaml index 8b97ae7aae..9f7f1afe45 100644 --- a/config/crd/bases/org.eclipse.che_checlusters.yaml +++ b/config/crd/bases/org.eclipse.che_checlusters.yaml @@ -27842,6 +27842,28 @@ spec: description: Defines labels which will be set for an Ingress (a route for OpenShift platform). type: object + networkPolicies: + description: |- + NetworkPolicies configures NetworkPolicy resources for the Che namespace + and user workspace namespaces. + When enabled, the following Ingress-only allow policies are created: + In the Che namespace: + - allow-from-same-namespace: allows traffic between pods in the same namespace. + - allow-from-workspaces-namespaces: allows traffic from user workspace namespaces + (namespaces labeled app.kubernetes.io/component=workspaces-namespace). + In each user workspace namespace: + - allow-from-: allows traffic from the Che namespace. + - allow-from-operators: allows traffic from the operators namespace. + - allow-from-same-namespace: allows traffic between pods in the same namespace. + On OpenShift, these additional policies are also created in each user workspace namespace: + - allow-from-openshift-monitoring: allows traffic from the monitoring namespace. + - allow-from-openshift-ingress: allows traffic from the ingress namespace. + properties: + enabled: + description: Enabled controls whether the operator creates + NetworkPolicy resources. + type: boolean + type: object tlsSecretName: description: |- The name of the secret used to set up Ingress TLS termination. diff --git a/controllers/che/checluster_controller.go b/controllers/che/checluster_controller.go index af83202c78..8dfc68ba03 100644 --- a/controllers/che/checluster_controller.go +++ b/controllers/che/checluster_controller.go @@ -43,6 +43,7 @@ import ( "github.com/eclipse-che/che-operator/pkg/deploy/gateway" identityprovider "github.com/eclipse-che/che-operator/pkg/deploy/identity-provider" "github.com/eclipse-che/che-operator/pkg/deploy/migration" + "github.com/eclipse-che/che-operator/pkg/deploy/networkpolicies" "github.com/eclipse-che/che-operator/pkg/deploy/openvsx" openvsxdatabase "github.com/eclipse-che/che-operator/pkg/deploy/openvsx/openvsx-database" openvsxserver "github.com/eclipse-che/che-operator/pkg/deploy/openvsx/openvsx-server" @@ -127,6 +128,7 @@ func NewReconciler( reconcilerManager.AddReconciler(devworkspace.NewDwoNamespaceReconciler()) reconcilerManager.AddReconciler(dashboard.NewDashboardReconciler()) reconcilerManager.AddReconciler(gateway.NewGatewayReconciler()) + reconcilerManager.AddReconciler(networkpolicies.NewNetworkPoliciesReconciler()) reconcilerManager.AddReconciler(server.NewCheServerReconciler()) reconcilerManager.AddReconciler(imagepuller.NewImagePuller()) @@ -178,6 +180,7 @@ func (r *CheClusterReconciler) SetupWithManager(mgr ctrl.Manager) error { Owns(&rbacv1.RoleBinding{}). Owns(&corev1.ServiceAccount{}). Owns(&appsv1.Deployment{}). + Owns(&networking.NetworkPolicy{}). Watches(&corev1.ConfigMap{}, handler.EnqueueRequestsFromMapFunc(toTrustedBundleConfigMapRequestMapper), ). diff --git a/controllers/usernamespace/usernamespace_controller.go b/controllers/usernamespace/usernamespace_controller.go index d142e7583c..6c00a11663 100644 --- a/controllers/usernamespace/usernamespace_controller.go +++ b/controllers/usernamespace/usernamespace_controller.go @@ -20,10 +20,14 @@ import ( "strings" "github.com/eclipse-che/che-operator/pkg/common/diffs" + "github.com/eclipse-che/che-operator/pkg/common/infrastructure" k8sclient "github.com/eclipse-che/che-operator/pkg/common/k8s-client" + defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults" containercapabilties "github.com/eclipse-che/che-operator/pkg/deploy/container-capabilities" + "k8s.io/apimachinery/pkg/labels" "k8s.io/utils/ptr" + devworkspacedefaults "github.com/eclipse-che/che-operator/controllers/devworkspace/defaults" "github.com/eclipse-che/che-operator/controllers/namespacecache" "sigs.k8s.io/controller-runtime/pkg/controller" @@ -36,12 +40,11 @@ import ( dwconstants "github.com/devfile/devworkspace-operator/pkg/constants" chev2 "github.com/eclipse-che/che-operator/api/v2" "github.com/eclipse-che/che-operator/controllers/che" - "github.com/eclipse-che/che-operator/controllers/devworkspace/defaults" - "github.com/eclipse-che/che-operator/pkg/common/infrastructure" "github.com/eclipse-che/che-operator/pkg/deploy" projectv1 "github.com/openshift/api/project/v1" "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" + networkingv1 "k8s.io/api/networking/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -100,7 +103,8 @@ func (r *CheUserNamespaceReconciler) SetupWithManager(mgr ctrl.Manager) error { For(obj). Watches(&corev1.Secret{}, r.watchRulesForSecrets(ctx)). Watches(&corev1.ConfigMap{}, r.watchRulesForConfigMaps(ctx)). - Watches(&chev2.CheCluster{}, r.triggerAllNamespaces()) + Watches(&chev2.CheCluster{}, r.triggerAllNamespaces()). + Watches(&networkingv1.NetworkPolicy{}, r.watchRulesForNetworkPolicies(ctx)) // Use controller.TypedOptions to allow to configure 2 controllers for same object being reconciled return bld.WithOptions( @@ -135,6 +139,28 @@ func (r *CheUserNamespaceReconciler) commonRules(ctx context.Context, namesInChe } } +func (r *CheUserNamespaceReconciler) watchRulesForNetworkPolicies(_ context.Context) handler.EventHandler { + return handler.EnqueueRequestsFromMapFunc( + func(ctx context.Context, obj client.Object) []reconcile.Request { + workspaceInfo, _ := r.namespaceCache.GetNamespaceInfo(ctx, obj.GetNamespace()) + + if workspaceInfo != nil && + workspaceInfo.IsWorkspaceNamespace && + obj.GetLabels()[constants.KubernetesComponentLabelKey] == defaults.GetCheFlavor() { + + return []reconcile.Request{ + { + NamespacedName: types.NamespacedName{ + Name: obj.GetNamespace(), + }, + }, + } + } + + return []reconcile.Request{} + }) +} + func (r *CheUserNamespaceReconciler) watchRulesForConfigMaps(ctx context.Context) handler.EventHandler { rules := r.commonRules(ctx, tls.CheMergedCABundleCertsCMName) return handler.EnqueueRequestsFromMapFunc( @@ -166,7 +192,7 @@ func (r *CheUserNamespaceReconciler) triggerAllNamespaces() handler.EventHandler return handler.EnqueueRequestsFromMapFunc( handler.MapFunc(func(ctx context.Context, obj client.Object) []reconcile.Request { nss := r.namespaceCache.GetAllKnownNamespaces() - ret := make([]reconcile.Request, len(nss)) + ret := make([]reconcile.Request, 0, len(nss)) for _, ns := range nss { ret = append(ret, reconcile.Request{ @@ -277,6 +303,10 @@ func (r *CheUserNamespaceReconciler) Reconcile(ctx context.Context, req ctrl.Req return ctrl.Result{}, err } + if err = r.reconcileNetworkPolicies(ctx, req.Name, checluster); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to reconcile network policies in namespace %s: %w", req.Name, err) + } + return ctrl.Result{}, nil } @@ -313,7 +343,7 @@ func (r *CheUserNamespaceReconciler) reconcileSelfSignedCert(ctx context.Context ObjectMeta: metav1.ObjectMeta{ Name: targetCertName, Namespace: targetNs, - Labels: defaults.AddStandardLabelsForComponent(checluster, userSettingsComponentLabelValue, map[string]string{ + Labels: devworkspacedefaults.AddStandardLabelsForComponent(checluster, userSettingsComponentLabelValue, map[string]string{ dwconstants.DevWorkspaceMountLabel: "true", dwconstants.DevWorkspaceWatchSecretLabel: "true", }), @@ -375,7 +405,7 @@ func (r *CheUserNamespaceReconciler) reconcileUserSettings( annotations := map[string]string{ dwconstants.DevWorkspaceMountAsAnnotation: "env", } - labels := defaults.AddStandardLabelsForComponent(checluster, + labels := devworkspacedefaults.AddStandardLabelsForComponent(checluster, userSettingsComponentLabelValue, map[string]string{ dwconstants.DevWorkspaceMountLabel: "true", @@ -473,7 +503,7 @@ func (r *CheUserNamespaceReconciler) reconcileGitTlsCertificate(ctx context.Cont ObjectMeta: metav1.ObjectMeta{ Name: targetName, Namespace: targetNs, - Labels: defaults.AddStandardLabelsForComponent(checluster, userSettingsComponentLabelValue, map[string]string{ + Labels: devworkspacedefaults.AddStandardLabelsForComponent(checluster, userSettingsComponentLabelValue, map[string]string{ dwconstants.DevWorkspaceGitTLSLabel: "true", dwconstants.DevWorkspaceMountLabel: "true", dwconstants.DevWorkspaceWatchConfigMapLabel: "true", @@ -590,6 +620,226 @@ func (r *CheUserNamespaceReconciler) reconcileSCCPrivileges( ) } +func (r *CheUserNamespaceReconciler) reconcileNetworkPolicies( + ctx context.Context, + targetNs string, + checluster *chev2.CheCluster, +) error { + policies, err := r.getNetworkPolicies(targetNs, checluster) + if err != nil { + return fmt.Errorf("could not prepare list of network policy objects: %w", err) + } + + if !checluster.IsNetworkPoliciesEnabled() { + networkPolicyList := &networkingv1.NetworkPolicyList{} + + items, err := r.clientWrapper.List(ctx, networkPolicyList, + &client.ListOptions{ + Namespace: targetNs, + LabelSelector: labels.SelectorFromSet(deploy.GetLabels(defaults.GetCheFlavor())), + }) + if err != nil { + return fmt.Errorf("could not list NetworkPolicy objects in namespace %s: %w", targetNs, err) + } + + for _, item := range items { + networkPolicy, ok := item.(*networkingv1.NetworkPolicy) + if !ok { + continue + } + + err = r.clientWrapper.DeleteIgnoreNotFound(ctx, networkPolicy) + if err != nil { + return fmt.Errorf("failed to delete NetworkPolicy %s/%s: %w", targetNs, networkPolicy.GetName(), err) + } + } + + return nil + } + + for _, policy := range policies { + if err := r.clientWrapper.Sync( + ctx, + &policy, + &k8sclient.SyncOptions{DiffOpts: diffs.NetworkPolicy}, + ); err != nil { + return fmt.Errorf("failed to sync network policy %s/%s: %w", targetNs, policy.Name, err) + } + } + + return nil +} + +func (r *CheUserNamespaceReconciler) getNetworkPolicies( + targetNs string, + checluster *chev2.CheCluster, +) ([]networkingv1.NetworkPolicy, error) { + operatorNamespace, err := infrastructure.GetOperatorNamespace() + if err != nil { + return nil, fmt.Errorf("could not get operator namespace: %w", err) + } + + var networkPolicies []networkingv1.NetworkPolicy + + allowFromEclipseCheNetworkPolicy := networkingv1.NetworkPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: "NetworkPolicy", + APIVersion: networkingv1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-from-" + defaults.GetCheFlavor(), + Namespace: targetNs, + Labels: deploy.GetLabels(defaults.GetCheFlavor()), + }, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{}, + Ingress: []networkingv1.NetworkPolicyIngressRule{ + { + From: []networkingv1.NetworkPolicyPeer{ + { + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "kubernetes.io/metadata.name": checluster.Namespace, + }, + }, + }, + }, + }, + }, + PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress}, + }, + } + + allowFromSameNamespaceNetworkPolicy := networkingv1.NetworkPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: "NetworkPolicy", + APIVersion: networkingv1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-from-same-namespace", + Namespace: targetNs, + Labels: deploy.GetLabels(defaults.GetCheFlavor()), + }, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{}, + Ingress: []networkingv1.NetworkPolicyIngressRule{ + { + From: []networkingv1.NetworkPolicyPeer{ + { + PodSelector: &metav1.LabelSelector{}, + }, + }, + }, + }, + PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress}, + }, + } + + allowFromOperatorsNetworkPolicy := networkingv1.NetworkPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: "NetworkPolicy", + APIVersion: networkingv1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-from-operators", + Namespace: targetNs, + Labels: deploy.GetLabels(defaults.GetCheFlavor()), + }, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{}, + Ingress: []networkingv1.NetworkPolicyIngressRule{ + { + From: []networkingv1.NetworkPolicyPeer{ + { + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "kubernetes.io/metadata.name": operatorNamespace, + }, + }, + }, + }, + }, + }, + PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress}, + }, + } + + networkPolicies = append( + networkPolicies, + allowFromEclipseCheNetworkPolicy, + allowFromSameNamespaceNetworkPolicy, + allowFromOperatorsNetworkPolicy, + ) + + if infrastructure.IsOpenShift() { + allowFromOpenShiftMonitoringNetworkPolicy := networkingv1.NetworkPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: "NetworkPolicy", + APIVersion: networkingv1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-from-openshift-monitoring", + Namespace: targetNs, + Labels: deploy.GetLabels(defaults.GetCheFlavor()), + }, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{}, + Ingress: []networkingv1.NetworkPolicyIngressRule{ + { + From: []networkingv1.NetworkPolicyPeer{ + { + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "network.openshift.io/policy-group": "monitoring", + }, + }, + }, + }, + }, + }, + PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress}, + }, + } + + allowFromOpenShiftIngressNetworkPolicy := networkingv1.NetworkPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: "NetworkPolicy", + APIVersion: networkingv1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-from-openshift-ingress", + Namespace: targetNs, + Labels: deploy.GetLabels(defaults.GetCheFlavor()), + }, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{}, + Ingress: []networkingv1.NetworkPolicyIngressRule{ + { + From: []networkingv1.NetworkPolicyPeer{ + { + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "network.openshift.io/policy-group": "ingress", + }, + }, + }, + }, + }, + }, + PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress}, + }, + } + + networkPolicies = append( + networkPolicies, + allowFromOpenShiftMonitoringNetworkPolicy, + allowFromOpenShiftIngressNetworkPolicy, + ) + } + + return networkPolicies, nil +} + func prefixedName(name string) string { return "che-" + name } diff --git a/controllers/usernamespace/usernamespace_controller_network_policies_test.go b/controllers/usernamespace/usernamespace_controller_network_policies_test.go new file mode 100644 index 0000000000..f651a0af8c --- /dev/null +++ b/controllers/usernamespace/usernamespace_controller_network_policies_test.go @@ -0,0 +1,219 @@ +// +// Copyright (c) 2019-2026 Red Hat, Inc. +// This program and the accompanying materials are made +// available under the terms of the Eclipse Public License 2.0 +// which is available at https://www.eclipse.org/legal/epl-2.0/ +// +// SPDX-License-Identifier: EPL-2.0 +// +// Contributors: +// Red Hat, Inc. - initial API and implementation +// + +package usernamespace + +import ( + "context" + "testing" + + defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults" + "github.com/eclipse-che/che-operator/pkg/deploy" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + + networkingv1 "k8s.io/api/networking/v1" + + chev2 "github.com/eclipse-che/che-operator/api/v2" + "github.com/eclipse-che/che-operator/pkg/common/constants" + "github.com/eclipse-che/che-operator/pkg/common/infrastructure" + projectv1 "github.com/openshift/api/project/v1" + "github.com/stretchr/testify/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/reconcile" +) + +func TestNetworkPoliciesCreatedWhenEnabledOnOpenShift(t *testing.T) { + cheCluster := &chev2.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "eclipse-che", + Namespace: "eclipse-che", + }, + Spec: chev2.CheClusterSpec{ + Networking: chev2.CheClusterSpecNetworking{ + NetworkPolicies: &chev2.NetworkPolicies{ + Enabled: true, + }, + }, + }, + } + + userNamespace := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "user-project", + Labels: map[string]string{ + constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, + constants.KubernetesComponentLabelKey: "workspaces-namespace", + constants.WorkspaceNamespaceOwnerUidLabelKey: "some-uid", + }, + }, + } + + userProject := &projectv1.Project{ + ObjectMeta: metav1.ObjectMeta{ + Name: "user-project", + Labels: map[string]string{ + constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, + constants.KubernetesComponentLabelKey: "workspaces-namespace", + constants.WorkspaceNamespaceOwnerUidLabelKey: "some-uid", + }, + }, + } + + _, cl, r := setup(infrastructure.OpenShiftV4, cheCluster, userProject, userNamespace) + + _, err := r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "user-project"}}) + assert.NoError(t, err) + + policyNames := []string{ + "allow-from-" + defaults.GetCheFlavor(), + "allow-from-same-namespace", + "allow-from-operators", + "allow-from-openshift-monitoring", + "allow-from-openshift-ingress", + } + for _, name := range policyNames { + networkPolicy := &networkingv1.NetworkPolicy{} + err := cl.Get(context.TODO(), client.ObjectKey{Name: name, Namespace: "user-project"}, networkPolicy) + assert.NoError(t, err) + } + + networkPolicyList := &networkingv1.NetworkPolicyList{} + err = cl.List(context.TODO(), networkPolicyList) + assert.NoError(t, err) + assert.Len(t, networkPolicyList.Items, 5) +} + +func TestNetworkPoliciesCreatedWhenEnabledOnKubernetes(t *testing.T) { + cheCluster := &chev2.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "eclipse-che", + Namespace: "eclipse-che", + }, + Spec: chev2.CheClusterSpec{ + Networking: chev2.CheClusterSpecNetworking{ + NetworkPolicies: &chev2.NetworkPolicies{ + Enabled: true, + }, + }, + }, + } + + userNamespace := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "user-project", + Labels: map[string]string{ + constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, + constants.KubernetesComponentLabelKey: "workspaces-namespace", + constants.WorkspaceNamespaceOwnerUidLabelKey: "some-uid", + }, + }, + } + + _, cl, r := setup(infrastructure.Kubernetes, cheCluster, userNamespace) + + _, err := r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "user-project"}}) + assert.NoError(t, err) + + policyNames := []string{ + "allow-from-" + defaults.GetCheFlavor(), + "allow-from-same-namespace", + "allow-from-operators", + } + for _, name := range policyNames { + networkPolicy := &networkingv1.NetworkPolicy{} + err := cl.Get(context.TODO(), client.ObjectKey{Name: name, Namespace: "user-project"}, networkPolicy) + + assert.NoError(t, err) + assert.Equal(t, constants.CheEclipseOrg, networkPolicy.Labels[constants.KubernetesPartOfLabelKey]) + } + + networkPolicyList := &networkingv1.NetworkPolicyList{} + err = cl.List(context.TODO(), networkPolicyList) + assert.NoError(t, err) + assert.Len(t, networkPolicyList.Items, 3) +} + +func TestNetworkPoliciesDeletedWhenDisabled(t *testing.T) { + cheCluster := &chev2.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "eclipse-che", + Namespace: "eclipse-che", + }, + Spec: chev2.CheClusterSpec{ + Networking: chev2.CheClusterSpecNetworking{ + NetworkPolicies: &chev2.NetworkPolicies{ + Enabled: false, + }, + }, + }, + } + + allowFromCheNetworkPolicy := &networkingv1.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-from-" + defaults.GetCheFlavor(), + Namespace: "user-project", + Labels: deploy.GetLabels(defaults.GetCheFlavor()), + }, + } + + anotherAllowFromCheNetworkPolicy := &networkingv1.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "another-allow-from-" + defaults.GetCheFlavor(), + Namespace: "user-project", + }, + } + + userNamespace := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "user-project", + Labels: map[string]string{ + constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, + constants.KubernetesComponentLabelKey: "workspaces-namespace", + constants.WorkspaceNamespaceOwnerUidLabelKey: "some-uid", + }, + }, + } + + userProject := &projectv1.Project{ + ObjectMeta: metav1.ObjectMeta{ + Name: "user-project", + Labels: map[string]string{ + constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, + constants.KubernetesComponentLabelKey: "workspaces-namespace", + constants.WorkspaceNamespaceOwnerUidLabelKey: "some-uid", + }, + }, + } + + _, cl, r := setup( + infrastructure.OpenShiftV4, + cheCluster, + userProject, + userNamespace, + allowFromCheNetworkPolicy, + anotherAllowFromCheNetworkPolicy, + ) + + _, err := r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "user-project"}}) + assert.NoError(t, err) + + networkPolicy := &networkingv1.NetworkPolicy{} + err = cl.Get(context.TODO(), client.ObjectKey{Name: "allow-from-" + defaults.GetCheFlavor(), Namespace: "user-project"}, networkPolicy) + assert.Error(t, err) + assert.True(t, errors.IsNotFound(err)) + + err = cl.Get(context.TODO(), client.ObjectKey{Name: "another-allow-from-" + defaults.GetCheFlavor(), Namespace: "user-project"}, networkPolicy) + assert.NoError(t, err) +} diff --git a/controllers/usernamespace/usernamespace_controller_setup_test.go b/controllers/usernamespace/usernamespace_controller_setup_test.go new file mode 100644 index 0000000000..27985c2677 --- /dev/null +++ b/controllers/usernamespace/usernamespace_controller_setup_test.go @@ -0,0 +1,168 @@ +// +// Copyright (c) 2019-2025 Red Hat, Inc. +// This program and the accompanying materials are made +// available under the terms of the Eclipse Public License 2.0 +// which is available at https://www.eclipse.org/legal/epl-2.0/ +// +// SPDX-License-Identifier: EPL-2.0 +// +// Contributors: +// Red Hat, Inc. - initial API and implementation +// + +package usernamespace + +import ( + "context" + "sync" + "testing" + + "github.com/eclipse-che/che-operator/controllers/namespacecache" + k8sclient "github.com/eclipse-che/che-operator/pkg/common/k8s-client" + "k8s.io/utils/ptr" + + "github.com/eclipse-che/che-operator/pkg/common/test" + + chev2 "github.com/eclipse-che/che-operator/api/v2" + "github.com/eclipse-che/che-operator/pkg/common/constants" + "github.com/eclipse-che/che-operator/pkg/common/infrastructure" + "github.com/eclipse-che/che-operator/pkg/deploy/tls" + projectv1 "github.com/openshift/api/project/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func setupCheCluster(t *testing.T, ctx context.Context, cl client.Client, scheme *runtime.Scheme, cheNamespaceName string, cheName string) { + var cheNamespace metav1.Object + if infrastructure.IsOpenShift() { + cheNamespace = &projectv1.Project{} + } else { + cheNamespace = &corev1.Namespace{} + } + + cheNamespace.SetName(cheNamespaceName) + if err := cl.Create(ctx, cheNamespace.(client.Object)); err != nil { + t.Fatal(err) + } + + cheCluster := chev2.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: cheName, + Namespace: cheNamespaceName, + }, + Spec: chev2.CheClusterSpec{ + DevEnvironments: chev2.CheClusterDevEnvironments{ + DisableContainerBuildCapabilities: ptr.To(true), + NodeSelector: map[string]string{"a": "b", "c": "d"}, + Tolerations: []corev1.Toleration{ + { + Key: "a", + Operator: corev1.TolerationOpEqual, + Value: "b", + }, + { + Key: "c", + Operator: corev1.TolerationOpEqual, + Value: "d", + }, + }, + TrustedCerts: &chev2.TrustedCerts{ + GitTrustedCertsConfigMapName: "che-git-self-signed-cert", + }, + SecondsOfInactivityBeforeIdling: ptr.To(int32(1800)), + SecondsOfRunBeforeIdling: ptr.To(int32(-1)), + EditorsDownloadUrls: []chev2.EditorDownloadUrl{ + { + Editor: "che-incubator/che-idea/latest", + Url: "url_latest", + }, + { + Editor: "che-incubator/che-idea/next", + Url: "url_next", + }, + }, + }, + Networking: chev2.CheClusterSpecNetworking{ + Domain: "root-domain", + }, + }, + Status: chev2.CheClusterStatus{ + CheURL: "https://che-host", + }, + } + if err := cl.Create(ctx, &cheCluster); err != nil { + t.Fatal(err) + } + + // also create the self-signed-certificate secret to pretend we have TLS set up + cert := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: constants.DefaultSelfSignedCertificateSecretName, + Namespace: cheNamespaceName, + }, + Data: map[string][]byte{ + "ca.crt": []byte("my certificate"), + "other.data": []byte("should not be copied to target ns"), + }, + Type: "Opaque", + Immutable: ptr.To(true), + } + if err := cl.Create(ctx, cert); err != nil { + t.Fatal(err) + } + + caCerts := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: tls.CheMergedCABundleCertsCMName, + Namespace: cheNamespaceName, + }, + Data: map[string]string{ + "trusted1": "trusted cert 1", + "trusted2": "trusted cert 2", + }, + } + if err := cl.Create(ctx, caCerts); err != nil { + t.Fatal(err) + } + + gitTlsCredentials := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "che-git-self-signed-cert", + Namespace: cheNamespaceName, + }, + Data: map[string]string{ + "githost": "the.host.of.git", + "ca.crt": "the public certificate of the.host.of.git", + }, + } + if err := cl.Create(ctx, gitTlsCredentials); err != nil { + t.Fatal(err) + } + +} + +func setup(infraType infrastructure.Type, objs ...client.Object) (*runtime.Scheme, client.Client, *CheUserNamespaceReconciler) { + infrastructure.InitializeForTesting(infraType) + + ctx := test.NewCtxBuilder().WithObjects(objs...).WithCheCluster(nil).Build() + + cl := ctx.ClusterAPI.Client + scheme := ctx.ClusterAPI.Scheme + + r := &CheUserNamespaceReconciler{ + client: cl, + nonCachedClient: cl, + clientWrapper: k8sclient.NewK8sClient(cl, scheme), + nonCachedClientWrapper: k8sclient.NewK8sClient(cl, scheme), + scheme: scheme, + namespaceCache: &namespacecache.NamespaceCache{ + Client: cl, + KnownNamespaces: map[string]namespacecache.NamespaceInfo{}, + Lock: sync.Mutex{}, + }, + } + + return scheme, cl, r +} diff --git a/controllers/usernamespace/usernamespace_controller_test.go b/controllers/usernamespace/usernamespace_controller_test.go index a623ace852..68a225baa6 100644 --- a/controllers/usernamespace/usernamespace_controller_test.go +++ b/controllers/usernamespace/usernamespace_controller_test.go @@ -15,16 +15,11 @@ package usernamespace import ( "context" "encoding/json" - "sync" "testing" - "github.com/eclipse-che/che-operator/controllers/namespacecache" - k8sclient "github.com/eclipse-che/che-operator/pkg/common/k8s-client" containerbuild "github.com/eclipse-che/che-operator/pkg/deploy/container-capabilities" "k8s.io/utils/ptr" - "github.com/eclipse-che/che-operator/pkg/common/test" - rbacv1 "k8s.io/api/rbac/v1" dwconstants "github.com/devfile/devworkspace-operator/pkg/constants" @@ -37,7 +32,6 @@ import ( "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/util/workqueue" "sigs.k8s.io/controller-runtime/pkg/client" @@ -45,138 +39,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" ) -func setupCheCluster(t *testing.T, ctx context.Context, cl client.Client, scheme *runtime.Scheme, cheNamespaceName string, cheName string) { - var cheNamespace metav1.Object - if infrastructure.IsOpenShift() { - cheNamespace = &projectv1.Project{} - } else { - cheNamespace = &corev1.Namespace{} - } - - cheNamespace.SetName(cheNamespaceName) - if err := cl.Create(ctx, cheNamespace.(client.Object)); err != nil { - t.Fatal(err) - } - - cheCluster := chev2.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: cheName, - Namespace: cheNamespaceName, - }, - Spec: chev2.CheClusterSpec{ - DevEnvironments: chev2.CheClusterDevEnvironments{ - DisableContainerBuildCapabilities: ptr.To(true), - NodeSelector: map[string]string{"a": "b", "c": "d"}, - Tolerations: []corev1.Toleration{ - { - Key: "a", - Operator: corev1.TolerationOpEqual, - Value: "b", - }, - { - Key: "c", - Operator: corev1.TolerationOpEqual, - Value: "d", - }, - }, - TrustedCerts: &chev2.TrustedCerts{ - GitTrustedCertsConfigMapName: "che-git-self-signed-cert", - }, - SecondsOfInactivityBeforeIdling: ptr.To(int32(1800)), - SecondsOfRunBeforeIdling: ptr.To(int32(-1)), - EditorsDownloadUrls: []chev2.EditorDownloadUrl{ - { - Editor: "che-incubator/che-idea/latest", - Url: "url_latest", - }, - { - Editor: "che-incubator/che-idea/next", - Url: "url_next", - }, - }, - }, - Networking: chev2.CheClusterSpecNetworking{ - Domain: "root-domain", - }, - }, - Status: chev2.CheClusterStatus{ - CheURL: "https://che-host", - }, - } - if err := cl.Create(ctx, &cheCluster); err != nil { - t.Fatal(err) - } - - // also create the self-signed-certificate secret to pretend we have TLS set up - cert := &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: constants.DefaultSelfSignedCertificateSecretName, - Namespace: cheNamespaceName, - }, - Data: map[string][]byte{ - "ca.crt": []byte("my certificate"), - "other.data": []byte("should not be copied to target ns"), - }, - Type: "Opaque", - Immutable: ptr.To(true), - } - if err := cl.Create(ctx, cert); err != nil { - t.Fatal(err) - } - - caCerts := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: tls.CheMergedCABundleCertsCMName, - Namespace: cheNamespaceName, - }, - Data: map[string]string{ - "trusted1": "trusted cert 1", - "trusted2": "trusted cert 2", - }, - } - if err := cl.Create(ctx, caCerts); err != nil { - t.Fatal(err) - } - - gitTlsCredentials := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "che-git-self-signed-cert", - Namespace: cheNamespaceName, - }, - Data: map[string]string{ - "githost": "the.host.of.git", - "ca.crt": "the public certificate of the.host.of.git", - }, - } - if err := cl.Create(ctx, gitTlsCredentials); err != nil { - t.Fatal(err) - } - -} - -func setup(infraType infrastructure.Type, objs ...client.Object) (*runtime.Scheme, client.Client, *CheUserNamespaceReconciler) { - infrastructure.InitializeForTesting(infraType) - - ctx := test.NewCtxBuilder().WithObjects(objs...).WithCheCluster(nil).Build() - cl := ctx.ClusterAPI.Client - scheme := ctx.ClusterAPI.Scheme - - r := &CheUserNamespaceReconciler{ - client: cl, - nonCachedClient: cl, - clientWrapper: k8sclient.NewK8sClient(cl, scheme), - nonCachedClientWrapper: k8sclient.NewK8sClient(cl, scheme), - scheme: scheme, - namespaceCache: &namespacecache.NamespaceCache{ - Client: cl, - KnownNamespaces: map[string]namespacecache.NamespaceInfo{}, - Lock: sync.Mutex{}, - }, - } - - return scheme, cl, r -} - func TestSkipsUnlabeledNamespaces(t *testing.T) { test := func(t *testing.T, infraType infrastructure.Type, namespace metav1.Object) { ctx := context.TODO() diff --git a/deploy/deployment/kubernetes/combined.yaml b/deploy/deployment/kubernetes/combined.yaml index ff71d11434..d72d648734 100644 --- a/deploy/deployment/kubernetes/combined.yaml +++ b/deploy/deployment/kubernetes/combined.yaml @@ -27863,6 +27863,28 @@ spec: description: Defines labels which will be set for an Ingress (a route for OpenShift platform). type: object + networkPolicies: + description: |- + NetworkPolicies configures NetworkPolicy resources for the Che namespace + and user workspace namespaces. + When enabled, the following Ingress-only allow policies are created: + In the Che namespace: + - allow-from-same-namespace: allows traffic between pods in the same namespace. + - allow-from-workspaces-namespaces: allows traffic from user workspace namespaces + (namespaces labeled app.kubernetes.io/component=workspaces-namespace). + In each user workspace namespace: + - allow-from-: allows traffic from the Che namespace. + - allow-from-operators: allows traffic from the operators namespace. + - allow-from-same-namespace: allows traffic between pods in the same namespace. + On OpenShift, these additional policies are also created in each user workspace namespace: + - allow-from-openshift-monitoring: allows traffic from the monitoring namespace. + - allow-from-openshift-ingress: allows traffic from the ingress namespace. + properties: + enabled: + description: Enabled controls whether the operator creates + NetworkPolicy resources. + type: boolean + type: object tlsSecretName: description: |- The name of the secret used to set up Ingress TLS termination. diff --git a/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index 866076f6a9..1411bbeddc 100644 --- a/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -27858,6 +27858,28 @@ spec: description: Defines labels which will be set for an Ingress (a route for OpenShift platform). type: object + networkPolicies: + description: |- + NetworkPolicies configures NetworkPolicy resources for the Che namespace + and user workspace namespaces. + When enabled, the following Ingress-only allow policies are created: + In the Che namespace: + - allow-from-same-namespace: allows traffic between pods in the same namespace. + - allow-from-workspaces-namespaces: allows traffic from user workspace namespaces + (namespaces labeled app.kubernetes.io/component=workspaces-namespace). + In each user workspace namespace: + - allow-from-: allows traffic from the Che namespace. + - allow-from-operators: allows traffic from the operators namespace. + - allow-from-same-namespace: allows traffic between pods in the same namespace. + On OpenShift, these additional policies are also created in each user workspace namespace: + - allow-from-openshift-monitoring: allows traffic from the monitoring namespace. + - allow-from-openshift-ingress: allows traffic from the ingress namespace. + properties: + enabled: + description: Enabled controls whether the operator creates + NetworkPolicy resources. + type: boolean + type: object tlsSecretName: description: |- The name of the secret used to set up Ingress TLS termination. diff --git a/deploy/deployment/openshift/combined.yaml b/deploy/deployment/openshift/combined.yaml index 7b726244b3..08e9de2f04 100644 --- a/deploy/deployment/openshift/combined.yaml +++ b/deploy/deployment/openshift/combined.yaml @@ -27863,6 +27863,28 @@ spec: description: Defines labels which will be set for an Ingress (a route for OpenShift platform). type: object + networkPolicies: + description: |- + NetworkPolicies configures NetworkPolicy resources for the Che namespace + and user workspace namespaces. + When enabled, the following Ingress-only allow policies are created: + In the Che namespace: + - allow-from-same-namespace: allows traffic between pods in the same namespace. + - allow-from-workspaces-namespaces: allows traffic from user workspace namespaces + (namespaces labeled app.kubernetes.io/component=workspaces-namespace). + In each user workspace namespace: + - allow-from-: allows traffic from the Che namespace. + - allow-from-operators: allows traffic from the operators namespace. + - allow-from-same-namespace: allows traffic between pods in the same namespace. + On OpenShift, these additional policies are also created in each user workspace namespace: + - allow-from-openshift-monitoring: allows traffic from the monitoring namespace. + - allow-from-openshift-ingress: allows traffic from the ingress namespace. + properties: + enabled: + description: Enabled controls whether the operator creates + NetworkPolicy resources. + type: boolean + type: object tlsSecretName: description: |- The name of the secret used to set up Ingress TLS termination. diff --git a/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index d2cfaeb69c..3f6fb151d7 100644 --- a/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -27858,6 +27858,28 @@ spec: description: Defines labels which will be set for an Ingress (a route for OpenShift platform). type: object + networkPolicies: + description: |- + NetworkPolicies configures NetworkPolicy resources for the Che namespace + and user workspace namespaces. + When enabled, the following Ingress-only allow policies are created: + In the Che namespace: + - allow-from-same-namespace: allows traffic between pods in the same namespace. + - allow-from-workspaces-namespaces: allows traffic from user workspace namespaces + (namespaces labeled app.kubernetes.io/component=workspaces-namespace). + In each user workspace namespace: + - allow-from-: allows traffic from the Che namespace. + - allow-from-operators: allows traffic from the operators namespace. + - allow-from-same-namespace: allows traffic between pods in the same namespace. + On OpenShift, these additional policies are also created in each user workspace namespace: + - allow-from-openshift-monitoring: allows traffic from the monitoring namespace. + - allow-from-openshift-ingress: allows traffic from the ingress namespace. + properties: + enabled: + description: Enabled controls whether the operator creates + NetworkPolicy resources. + type: boolean + type: object tlsSecretName: description: |- The name of the secret used to set up Ingress TLS termination. diff --git a/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index 866076f6a9..1411bbeddc 100644 --- a/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -27858,6 +27858,28 @@ spec: description: Defines labels which will be set for an Ingress (a route for OpenShift platform). type: object + networkPolicies: + description: |- + NetworkPolicies configures NetworkPolicy resources for the Che namespace + and user workspace namespaces. + When enabled, the following Ingress-only allow policies are created: + In the Che namespace: + - allow-from-same-namespace: allows traffic between pods in the same namespace. + - allow-from-workspaces-namespaces: allows traffic from user workspace namespaces + (namespaces labeled app.kubernetes.io/component=workspaces-namespace). + In each user workspace namespace: + - allow-from-: allows traffic from the Che namespace. + - allow-from-operators: allows traffic from the operators namespace. + - allow-from-same-namespace: allows traffic between pods in the same namespace. + On OpenShift, these additional policies are also created in each user workspace namespace: + - allow-from-openshift-monitoring: allows traffic from the monitoring namespace. + - allow-from-openshift-ingress: allows traffic from the ingress namespace. + properties: + enabled: + description: Enabled controls whether the operator creates + NetworkPolicy resources. + type: boolean + type: object tlsSecretName: description: |- The name of the secret used to set up Ingress TLS termination. diff --git a/helmcharts/next/templates/org_v2_checluster.yaml b/helmcharts/next/templates/org_v2_checluster.yaml index 64c039e0c2..4f8a94efef 100644 --- a/helmcharts/next/templates/org_v2_checluster.yaml +++ b/helmcharts/next/templates/org_v2_checluster.yaml @@ -9,6 +9,7 @@ # Contributors: # Red Hat, Inc. - initial API and implementation # + apiVersion: org.eclipse.che/v2 kind: CheCluster metadata: diff --git a/pkg/common/diffs/diffs.go b/pkg/common/diffs/diffs.go index 3e008b10dd..cf88bca460 100644 --- a/pkg/common/diffs/diffs.go +++ b/pkg/common/diffs/diffs.go @@ -81,6 +81,10 @@ func ConfigMap(labelKeys []string, annotationKeys []string) cmp.Options { } } +var NetworkPolicy = cmp.Options{ + cmpopts.IgnoreFields(networking.NetworkPolicy{}, "TypeMeta", "ObjectMeta"), +} + var ServiceMonitor = cmp.Options{ cmpopts.IgnoreFields(monitoringv1.ServiceMonitor{}, "TypeMeta", "ObjectMeta"), } diff --git a/pkg/common/k8s-client/k8s_client.go b/pkg/common/k8s-client/k8s_client.go index 38e43494e8..41a3ed3e5a 100644 --- a/pkg/common/k8s-client/k8s_client.go +++ b/pkg/common/k8s-client/k8s_client.go @@ -127,6 +127,18 @@ func (k K8sClientWrapper) DeleteByKeyIgnoreNotFound( return k.deleteByKeyIgnoreNotFound(ctx, key, objectMeta, opts...) } +func (k K8sClientWrapper) DeleteIgnoreNotFound( + ctx context.Context, + obj client.Object, + opts ...client.DeleteOption, +) error { + if err := k.ensureGVK(obj); err != nil { + return err + } + + return k.doDeleteIgnoreIfNotFound(ctx, obj, opts...) +} + func (k K8sClientWrapper) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) ([]runtime.Object, error) { err := k.cli.List(ctx, list, opts...) if err != nil { diff --git a/pkg/common/k8s-client/k8s_client_types.go b/pkg/common/k8s-client/k8s_client_types.go index b2252a3e55..47d0782798 100644 --- a/pkg/common/k8s-client/k8s_client_types.go +++ b/pkg/common/k8s-client/k8s_client_types.go @@ -36,6 +36,9 @@ type K8sClient interface { // Returns true if object exists otherwise returns false. // Returns nil if object is retrieved or not found otherwise returns error. GetIgnoreNotFound(ctx context.Context, key client.ObjectKey, objectMeta client.Object, opts ...client.GetOption) (bool, error) + // DeleteIgnoreNotFound deletes object. + // Returns nil if object is deleted or not found otherwise returns error. + DeleteIgnoreNotFound(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error // DeleteByKeyIgnoreNotFound deletes object by key. // Returns nil if object is deleted or not found otherwise returns error. DeleteByKeyIgnoreNotFound(ctx context.Context, key client.ObjectKey, objectMeta client.Object, opts ...client.DeleteOption) error diff --git a/pkg/common/test/test-client/test_client.go b/pkg/common/test/test-client/test_client.go index bef4f3dc28..2e99d6ed62 100644 --- a/pkg/common/test/test-client/test_client.go +++ b/pkg/common/test/test-client/test_client.go @@ -111,6 +111,7 @@ func getScheme() *runtime.Scheme { scheme.AddKnownTypes(appsv1.SchemeGroupVersion, &appsv1.Deployment{}, &appsv1.DeploymentList{}) scheme.AddKnownTypes(chev2.GroupVersion, &chev2.CheCluster{}, &chev2.CheClusterList{}) scheme.AddKnownTypes(networkingv1.SchemeGroupVersion, &networkingv1.Ingress{}, &networkingv1.IngressList{}) + scheme.AddKnownTypes(networkingv1.SchemeGroupVersion, &networkingv1.NetworkPolicy{}, &networkingv1.NetworkPolicyList{}) scheme.AddKnownTypes(batchv1.SchemeGroupVersion, &batchv1.Job{}, &batchv1.JobList{}) scheme.AddKnownTypes(projectv1.GroupVersion, &projectv1.Project{}, &projectv1.ProjectList{}) scheme.AddKnownTypes(monitoringv1.SchemeGroupVersion, &monitoringv1.ServiceMonitor{}, &monitoringv1.ServiceMonitorList{}) diff --git a/pkg/deploy/container-capabilities/container_capabilities.go b/pkg/deploy/container-capabilities/container_capabilities.go index 227534c3ba..a1678fd8a6 100644 --- a/pkg/deploy/container-capabilities/container_capabilities.go +++ b/pkg/deploy/container-capabilities/container_capabilities.go @@ -148,7 +148,7 @@ func (r *ContainerCapabilitiesReconciler) sync(ctx *chetypes.DeployContext, cc C scc := &securityv1.SecurityContextConstraints{} if exists, err := ctx.ClusterAPI.NonCachingClientWrapper.GetIgnoreNotFound(context.TODO(), sccKey, scc); exists { - if deploy.IsPartOfEclipseCheResourceAndManagedByOperator(scc.Labels) { + if deploy.IsOperatorManagedComponent(scc.Labels, defaults.GetCheFlavor()) { // SCC exists and created by operator (custom SCC won't be updated). // Remove priority, see details https://issues.redhat.com/browse/CRW-389 scc.Priority = nil diff --git a/pkg/deploy/labels.go b/pkg/deploy/labels.go index cdfdb85d34..cb8b33c938 100644 --- a/pkg/deploy/labels.go +++ b/pkg/deploy/labels.go @@ -71,6 +71,8 @@ func GetLabelsAndAnnotations(obj client.Object) ([]string, []string) { return slices.Collect(maps.Keys(obj.GetLabels())), slices.Collect(maps.Keys(obj.GetAnnotations())) } -func IsPartOfEclipseCheResourceAndManagedByOperator(labels map[string]string) bool { - return labels[constants.KubernetesPartOfLabelKey] == constants.CheEclipseOrg && labels[constants.KubernetesManagedByLabelKey] == GetManagedByLabel() +func IsOperatorManagedComponent(labels map[string]string, component string) bool { + return labels[constants.KubernetesPartOfLabelKey] == constants.CheEclipseOrg && + labels[constants.KubernetesManagedByLabelKey] == GetManagedByLabel() && + labels[constants.KubernetesComponentLabelKey] == component } diff --git a/pkg/deploy/networkpolicies/init_test.go b/pkg/deploy/networkpolicies/init_test.go new file mode 100644 index 0000000000..acb8bccdb4 --- /dev/null +++ b/pkg/deploy/networkpolicies/init_test.go @@ -0,0 +1,26 @@ +// +// Copyright (c) 2019-2026 Red Hat, Inc. +// This program and the accompanying materials are made +// available under the terms of the Eclipse Public License 2.0 +// which is available at https://www.eclipse.org/legal/epl-2.0/ +// +// SPDX-License-Identifier: EPL-2.0 +// +// Contributors: +// Red Hat, Inc. - initial API and implementation +// + +package networkpolicies + +import ( + "github.com/eclipse-che/che-operator/pkg/common/infrastructure" + defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults" + "github.com/eclipse-che/che-operator/pkg/common/test" +) + +func init() { + test.EnableTestMode() + + infrastructure.InitializeForTesting(infrastructure.Kubernetes) + defaults.InitializeForTesting("../../../config/manager/manager.yaml") +} diff --git a/pkg/deploy/networkpolicies/networkpolicies.go b/pkg/deploy/networkpolicies/networkpolicies.go new file mode 100644 index 0000000000..26482289df --- /dev/null +++ b/pkg/deploy/networkpolicies/networkpolicies.go @@ -0,0 +1,161 @@ +// +// Copyright (c) 2019-2026 Red Hat, Inc. +// This program and the accompanying materials are made +// available under the terms of the Eclipse Public License 2.0 +// which is available at https://www.eclipse.org/legal/epl-2.0/ +// +// SPDX-License-Identifier: EPL-2.0 +// +// Contributors: +// Red Hat, Inc. - initial API and implementation +// + +package networkpolicies + +import ( + "context" + "fmt" + + "github.com/eclipse-che/che-operator/pkg/common/chetypes" + "github.com/eclipse-che/che-operator/pkg/common/constants" + "github.com/eclipse-che/che-operator/pkg/common/diffs" + k8sclient "github.com/eclipse-che/che-operator/pkg/common/k8s-client" + defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults" + "github.com/eclipse-che/che-operator/pkg/common/reconciler" + "github.com/eclipse-che/che-operator/pkg/deploy" + networkingv1 "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/reconcile" +) + +type NetworkPoliciesReconciler struct { + reconciler.Reconcilable +} + +func NewNetworkPoliciesReconciler() *NetworkPoliciesReconciler { + return &NetworkPoliciesReconciler{} +} + +func (r *NetworkPoliciesReconciler) Reconcile(ctx *chetypes.DeployContext) (reconcile.Result, bool, error) { + if !ctx.CheCluster.IsNetworkPoliciesEnabled() { + networkPolicyList := &networkingv1.NetworkPolicyList{} + + items, err := ctx.ClusterAPI.ClientWrapper.List(context.TODO(), networkPolicyList, + &client.ListOptions{ + Namespace: ctx.CheCluster.Namespace, + LabelSelector: labels.SelectorFromSet(deploy.GetLabels(defaults.GetCheFlavor())), + }) + if err != nil { + return reconcile.Result{}, false, fmt.Errorf("could not list NetworkPolicy objects in namespace %s: %w", ctx.CheCluster.Namespace, err) + } + + for _, item := range items { + networkPolicy, ok := item.(*networkingv1.NetworkPolicy) + if !ok { + continue + } + + err = ctx.ClusterAPI.ClientWrapper.DeleteIgnoreNotFound(context.TODO(), networkPolicy) + if err != nil { + return reconcile.Result{}, false, fmt.Errorf("failed to delete NetworkPolicy %s/%s: %w", networkPolicy.GetNamespace(), networkPolicy.GetName(), err) + } + } + + return reconcile.Result{}, true, nil + } + + err := r.syncNetworkPolicy(ctx) + if err != nil { + return reconcile.Result{}, false, fmt.Errorf("failed to sync NetworkPolicy: %w", err) + } + + return reconcile.Result{}, true, nil +} + +func (r *NetworkPoliciesReconciler) Finalize(_ *chetypes.DeployContext) bool { + return true +} + +func (r *NetworkPoliciesReconciler) syncNetworkPolicy(ctx *chetypes.DeployContext) error { + networkPolicies := r.getNetworkPolicies(ctx) + + for _, networkPolicy := range networkPolicies { + if err := controllerutil.SetControllerReference(ctx.CheCluster, networkPolicy, ctx.ClusterAPI.Scheme); err != nil { + return fmt.Errorf("could not set controller reference: %w", err) + } + + if err := ctx.ClusterAPI.ClientWrapper.Sync( + context.TODO(), + networkPolicy, + &k8sclient.SyncOptions{DiffOpts: diffs.NetworkPolicy}, + ); err != nil { + return fmt.Errorf("failed to sync NetworkPolicy %s/%s: %w", networkPolicy.Namespace, networkPolicy.Name, err) + } + } + + return nil +} + +func (r *NetworkPoliciesReconciler) getNetworkPolicies(ctx *chetypes.DeployContext) []*networkingv1.NetworkPolicy { + allowFromSameNamespaceNetworkPolicy := &networkingv1.NetworkPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: "NetworkPolicy", + APIVersion: networkingv1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-from-same-namespace", + Namespace: ctx.CheCluster.Namespace, + Labels: deploy.GetLabels(defaults.GetCheFlavor()), + }, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{}, + Ingress: []networkingv1.NetworkPolicyIngressRule{ + { + From: []networkingv1.NetworkPolicyPeer{ + { + PodSelector: &metav1.LabelSelector{}, + }, + }, + }, + }, + PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress}, + }, + } + + allowFromWorkspacesNamespacesNetworkPolicy := &networkingv1.NetworkPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: "NetworkPolicy", + APIVersion: networkingv1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-from-workspaces-namespaces", + Namespace: ctx.CheCluster.Namespace, + Labels: deploy.GetLabels(defaults.GetCheFlavor()), + }, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{}, + Ingress: []networkingv1.NetworkPolicyIngressRule{ + { + From: []networkingv1.NetworkPolicyPeer{ + { + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + constants.KubernetesComponentLabelKey: constants.WorkspacesNamespaceComponentName, + }, + }, + }, + }, + }, + }, + PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress}, + }, + } + + return []*networkingv1.NetworkPolicy{ + allowFromSameNamespaceNetworkPolicy, + allowFromWorkspacesNamespacesNetworkPolicy, + } +} diff --git a/pkg/deploy/networkpolicies/networkpolicies_test.go b/pkg/deploy/networkpolicies/networkpolicies_test.go new file mode 100644 index 0000000000..e154d8a527 --- /dev/null +++ b/pkg/deploy/networkpolicies/networkpolicies_test.go @@ -0,0 +1,95 @@ +// +// Copyright (c) 2019-2026 Red Hat, Inc. +// This program and the accompanying materials are made +// available under the terms of the Eclipse Public License 2.0 +// which is available at https://www.eclipse.org/legal/epl-2.0/ +// +// SPDX-License-Identifier: EPL-2.0 +// +// Contributors: +// Red Hat, Inc. - initial API and implementation +// + +package networkpolicies + +import ( + "context" + "testing" + + chev2 "github.com/eclipse-che/che-operator/api/v2" + "github.com/eclipse-che/che-operator/pkg/common/test" + "github.com/stretchr/testify/assert" + networkingv1 "k8s.io/api/networking/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +func TestReconcileNetworkPolicies(t *testing.T) { + ctx := test.NewCtxBuilder().WithCheCluster(&chev2.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "eclipse-che", + Name: "eclipse-che", + }, + Spec: chev2.CheClusterSpec{ + Networking: chev2.CheClusterSpecNetworking{ + NetworkPolicies: &chev2.NetworkPolicies{Enabled: true}, + }, + }, + }).Build() + + reconciler := NewNetworkPoliciesReconciler() + _, done, err := reconciler.Reconcile(ctx) + assert.True(t, done) + assert.NoError(t, err) + + networkPolicy := &networkingv1.NetworkPolicy{} + + err = ctx.ClusterAPI.Client.Get( + context.TODO(), + types.NamespacedName{ + Name: "allow-from-workspaces-namespaces", + Namespace: "eclipse-che", + }, + networkPolicy, + ) + assert.NoError(t, err) + + err = ctx.ClusterAPI.Client.Get( + context.TODO(), + types.NamespacedName{ + Name: "allow-from-same-namespace", + Namespace: "eclipse-che", + }, + networkPolicy, + ) + assert.NoError(t, err) + + ctx.CheCluster.Spec.Networking.NetworkPolicies.Enabled = false + + _, done, err = reconciler.Reconcile(ctx) + assert.True(t, done) + assert.NoError(t, err) + + err = ctx.ClusterAPI.Client.Get( + context.TODO(), + types.NamespacedName{ + Name: "allow-from-workspaces-namespaces", + Namespace: "eclipse-che", + }, + networkPolicy, + ) + assert.Error(t, err) + assert.True(t, errors.IsNotFound(err)) + + err = ctx.ClusterAPI.Client.Get( + context.TODO(), + types.NamespacedName{ + Name: "allow-from-same-namespace", + Namespace: "eclipse-che", + }, + networkPolicy, + ) + assert.Error(t, err) + assert.True(t, errors.IsNotFound(err)) +} diff --git a/pkg/deploy/openvsx/openvsx_secret.go b/pkg/deploy/openvsx/openvsx_secret.go index d3c623caf0..45f0f488d1 100644 --- a/pkg/deploy/openvsx/openvsx_secret.go +++ b/pkg/deploy/openvsx/openvsx_secret.go @@ -108,7 +108,7 @@ func HasCustomCredentialsSecret(ctx *chetypes.DeployContext) (bool, error) { return false, fmt.Errorf("failed to get secret: %w", err) } if exists { - return !deploy.IsPartOfEclipseCheResourceAndManagedByOperator(secret.Labels), nil + return !deploy.IsOperatorManagedComponent(secret.Labels, constants.OpenVSXDatabaseComponentName), nil } return false, nil From 9824465f7df97d75a22ba88d38490125650ba68f Mon Sep 17 00:00:00 2001 From: Anatolii Bazko Date: Wed, 22 Jul 2026 13:16:40 +0200 Subject: [PATCH 2/7] chore: Add NetworkPolicy reconciler Signed-off-by: Anatolii Bazko --- api/v2/checluster_types.go | 4 ++-- api/v2/zz_generated.deepcopy.go | 7 ++++++- .../che-operator.clusterserviceversion.yaml | 4 ++-- controllers/che/checluster_controller.go | 2 +- .../usernamespace/usernamespace_controller.go | 16 ++++++++-------- ...namespace_controller_network_policies_test.go | 7 ++++--- .../networkpolicies/networkpolicies_test.go | 5 +++-- 7 files changed, 26 insertions(+), 19 deletions(-) diff --git a/api/v2/checluster_types.go b/api/v2/checluster_types.go index cc54e0eb9a..88c97bcadd 100644 --- a/api/v2/checluster_types.go +++ b/api/v2/checluster_types.go @@ -358,7 +358,7 @@ type DevEnvironmentNetworking struct { type NetworkPolicies struct { // Enabled controls whether the operator creates NetworkPolicy resources. // +optional - Enabled bool `json:"enabled"` + Enabled *bool `json:"enabled"` } type ExternalTLSConfig struct { @@ -1285,5 +1285,5 @@ func (c *CheCluster) IsDevEnvironmentExternalTLSConfigEnabled() bool { } func (c *CheCluster) IsNetworkPoliciesEnabled() bool { - return c.Spec.Networking.NetworkPolicies != nil && c.Spec.Networking.NetworkPolicies.Enabled + return c.Spec.Networking.NetworkPolicies != nil && ptr.Deref(c.Spec.Networking.NetworkPolicies.Enabled, false) } diff --git a/api/v2/zz_generated.deepcopy.go b/api/v2/zz_generated.deepcopy.go index bd94371469..1a0ed97373 100644 --- a/api/v2/zz_generated.deepcopy.go +++ b/api/v2/zz_generated.deepcopy.go @@ -524,7 +524,7 @@ func (in *CheClusterSpecNetworking) DeepCopyInto(out *CheClusterSpecNetworking) if in.NetworkPolicies != nil { in, out := &in.NetworkPolicies, &out.NetworkPolicies *out = new(NetworkPolicies) - **out = **in + (*in).DeepCopyInto(*out) } } @@ -1079,6 +1079,11 @@ func (in *KubeRbacProxy) DeepCopy() *KubeRbacProxy { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NetworkPolicies) DeepCopyInto(out *NetworkPolicies) { *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPolicies. diff --git a/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml b/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml index 5cb5302d31..c2ecab3d48 100644 --- a/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml +++ b/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml @@ -108,7 +108,7 @@ metadata: operatorframework.io/arch.amd64: supported operatorframework.io/arch.arm64: supported operatorframework.io/os.linux: supported - name: eclipse-che.v7.121.0-1044.next + name: eclipse-che.v7.121.0-1045.next namespace: placeholder spec: apiservicedefinitions: {} @@ -1173,7 +1173,7 @@ spec: name: openvsx - image: quay.io/sclorg/postgresql-16-c9s:20260319 name: openvsx-postgres - version: 7.121.0-1044.next + version: 7.121.0-1045.next webhookdefinitions: - admissionReviewVersions: - v1 diff --git a/controllers/che/checluster_controller.go b/controllers/che/checluster_controller.go index 8dfc68ba03..cc0cd7c180 100644 --- a/controllers/che/checluster_controller.go +++ b/controllers/che/checluster_controller.go @@ -128,8 +128,8 @@ func NewReconciler( reconcilerManager.AddReconciler(devworkspace.NewDwoNamespaceReconciler()) reconcilerManager.AddReconciler(dashboard.NewDashboardReconciler()) reconcilerManager.AddReconciler(gateway.NewGatewayReconciler()) - reconcilerManager.AddReconciler(networkpolicies.NewNetworkPoliciesReconciler()) reconcilerManager.AddReconciler(server.NewCheServerReconciler()) + reconcilerManager.AddReconciler(networkpolicies.NewNetworkPoliciesReconciler()) reconcilerManager.AddReconciler(imagepuller.NewImagePuller()) if infrastructure.IsOpenShift() { diff --git a/controllers/usernamespace/usernamespace_controller.go b/controllers/usernamespace/usernamespace_controller.go index 6c00a11663..7a25a7c735 100644 --- a/controllers/usernamespace/usernamespace_controller.go +++ b/controllers/usernamespace/usernamespace_controller.go @@ -660,7 +660,7 @@ func (r *CheUserNamespaceReconciler) reconcileNetworkPolicies( for _, policy := range policies { if err := r.clientWrapper.Sync( ctx, - &policy, + policy, &k8sclient.SyncOptions{DiffOpts: diffs.NetworkPolicy}, ); err != nil { return fmt.Errorf("failed to sync network policy %s/%s: %w", targetNs, policy.Name, err) @@ -673,15 +673,15 @@ func (r *CheUserNamespaceReconciler) reconcileNetworkPolicies( func (r *CheUserNamespaceReconciler) getNetworkPolicies( targetNs string, checluster *chev2.CheCluster, -) ([]networkingv1.NetworkPolicy, error) { +) ([]*networkingv1.NetworkPolicy, error) { operatorNamespace, err := infrastructure.GetOperatorNamespace() if err != nil { return nil, fmt.Errorf("could not get operator namespace: %w", err) } - var networkPolicies []networkingv1.NetworkPolicy + var networkPolicies []*networkingv1.NetworkPolicy - allowFromEclipseCheNetworkPolicy := networkingv1.NetworkPolicy{ + allowFromEclipseCheNetworkPolicy := &networkingv1.NetworkPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "NetworkPolicy", APIVersion: networkingv1.SchemeGroupVersion.String(), @@ -710,7 +710,7 @@ func (r *CheUserNamespaceReconciler) getNetworkPolicies( }, } - allowFromSameNamespaceNetworkPolicy := networkingv1.NetworkPolicy{ + allowFromSameNamespaceNetworkPolicy := &networkingv1.NetworkPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "NetworkPolicy", APIVersion: networkingv1.SchemeGroupVersion.String(), @@ -735,7 +735,7 @@ func (r *CheUserNamespaceReconciler) getNetworkPolicies( }, } - allowFromOperatorsNetworkPolicy := networkingv1.NetworkPolicy{ + allowFromOperatorsNetworkPolicy := &networkingv1.NetworkPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "NetworkPolicy", APIVersion: networkingv1.SchemeGroupVersion.String(), @@ -772,7 +772,7 @@ func (r *CheUserNamespaceReconciler) getNetworkPolicies( ) if infrastructure.IsOpenShift() { - allowFromOpenShiftMonitoringNetworkPolicy := networkingv1.NetworkPolicy{ + allowFromOpenShiftMonitoringNetworkPolicy := &networkingv1.NetworkPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "NetworkPolicy", APIVersion: networkingv1.SchemeGroupVersion.String(), @@ -801,7 +801,7 @@ func (r *CheUserNamespaceReconciler) getNetworkPolicies( }, } - allowFromOpenShiftIngressNetworkPolicy := networkingv1.NetworkPolicy{ + allowFromOpenShiftIngressNetworkPolicy := &networkingv1.NetworkPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "NetworkPolicy", APIVersion: networkingv1.SchemeGroupVersion.String(), diff --git a/controllers/usernamespace/usernamespace_controller_network_policies_test.go b/controllers/usernamespace/usernamespace_controller_network_policies_test.go index f651a0af8c..50dd47e94c 100644 --- a/controllers/usernamespace/usernamespace_controller_network_policies_test.go +++ b/controllers/usernamespace/usernamespace_controller_network_policies_test.go @@ -20,6 +20,7 @@ import ( "github.com/eclipse-che/che-operator/pkg/deploy" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/utils/ptr" networkingv1 "k8s.io/api/networking/v1" @@ -43,7 +44,7 @@ func TestNetworkPoliciesCreatedWhenEnabledOnOpenShift(t *testing.T) { Spec: chev2.CheClusterSpec{ Networking: chev2.CheClusterSpecNetworking{ NetworkPolicies: &chev2.NetworkPolicies{ - Enabled: true, + Enabled: ptr.To(true), }, }, }, @@ -104,7 +105,7 @@ func TestNetworkPoliciesCreatedWhenEnabledOnKubernetes(t *testing.T) { Spec: chev2.CheClusterSpec{ Networking: chev2.CheClusterSpecNetworking{ NetworkPolicies: &chev2.NetworkPolicies{ - Enabled: true, + Enabled: ptr.To(true), }, }, }, @@ -154,7 +155,7 @@ func TestNetworkPoliciesDeletedWhenDisabled(t *testing.T) { Spec: chev2.CheClusterSpec{ Networking: chev2.CheClusterSpecNetworking{ NetworkPolicies: &chev2.NetworkPolicies{ - Enabled: false, + Enabled: ptr.To(false), }, }, }, diff --git a/pkg/deploy/networkpolicies/networkpolicies_test.go b/pkg/deploy/networkpolicies/networkpolicies_test.go index e154d8a527..e678a92b2f 100644 --- a/pkg/deploy/networkpolicies/networkpolicies_test.go +++ b/pkg/deploy/networkpolicies/networkpolicies_test.go @@ -23,6 +23,7 @@ import ( "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" ) func TestReconcileNetworkPolicies(t *testing.T) { @@ -33,7 +34,7 @@ func TestReconcileNetworkPolicies(t *testing.T) { }, Spec: chev2.CheClusterSpec{ Networking: chev2.CheClusterSpecNetworking{ - NetworkPolicies: &chev2.NetworkPolicies{Enabled: true}, + NetworkPolicies: &chev2.NetworkPolicies{Enabled: ptr.To(true)}, }, }, }).Build() @@ -65,7 +66,7 @@ func TestReconcileNetworkPolicies(t *testing.T) { ) assert.NoError(t, err) - ctx.CheCluster.Spec.Networking.NetworkPolicies.Enabled = false + ctx.CheCluster.Spec.Networking.NetworkPolicies.Enabled = ptr.To(false) _, done, err = reconciler.Reconcile(ctx) assert.True(t, done) From 24628973df356abbacac94da979ff1ecbc678083 Mon Sep 17 00:00:00 2001 From: Anatolii Bazko Date: Mon, 27 Jul 2026 15:21:46 +0200 Subject: [PATCH 3/7] chore: Add NetworkPolicy reconciler Introduces operator-managed NetworkPolicy resources for both the Che namespace and user workspace namespaces on OpenShift. A new `spec.networking.networkPolicy.enabled` field controls the feature (disabled by default). When enabled, the operator creates fine-grained ingress and egress policies: Che namespace policies: - allow-from-same-namespace: Che-to-Che pod traffic - allow-from-workspaces-namespaces-to-openvsx-registry - allow-from-workspaces-namespaces-to-plugin-registry - allow-from-openshift-ingress - allow-from-openshift-monitoring - allow-from-operator: operator pod to Che components - allow-to-everywhere: all egress from Che pods User workspace namespace policies: - allow-from-: ingress from Che namespace - allow-from-same-namespace: intra-namespace traffic - allow-from-devworkspace-operator: DWO to workspace pods - allow-from-openshift-monitoring - allow-from-openshift-ingress - allow-to-everywhere: all egress from workspace pods Also refactors DwoNamespaceReconciler into a utility function and extends the cache selector to watch DevWorkspace operator pods. Assisted-by: Claude Opus 4.6 Co-Authored-By: Claude Opus 4.6 --- api/v2/checluster_types.go | 39 ++-- api/v2/zz_generated.deepcopy.go | 14 +- .../che-operator.clusterserviceversion.yaml | 4 +- .../org.eclipse.che_checlusters.yaml | 32 +-- cmd/main.go | 52 +++-- .../bases/org.eclipse.che_checlusters.yaml | 32 +-- controllers/che/checluster_controller.go | 20 +- .../usernamespace/usernamespace_controller.go | 193 +++++++++------- ...espace_controller_network_policies_test.go | 216 ++++++++---------- .../usernamespace_controller_setup_test.go | 25 +- deploy/deployment/kubernetes/combined.yaml | 32 +-- ....eclipse.che.CustomResourceDefinition.yaml | 32 +-- deploy/deployment/openshift/combined.yaml | 32 +-- ....eclipse.che.CustomResourceDefinition.yaml | 32 +-- ....eclipse.che.CustomResourceDefinition.yaml | 32 +-- pkg/common/constants/constants.go | 3 + pkg/common/infrastructure/cluster.go | 4 + pkg/deploy/devworkspace/dwo_namespace.go | 47 ++-- pkg/deploy/networkpolicies/networkpolicies.go | 208 ++++++++++++++++- .../networkpolicies/networkpolicies_test.go | 137 +++++++---- 20 files changed, 740 insertions(+), 446 deletions(-) diff --git a/api/v2/checluster_types.go b/api/v2/checluster_types.go index 88c97bcadd..28d2331e61 100644 --- a/api/v2/checluster_types.go +++ b/api/v2/checluster_types.go @@ -329,22 +329,28 @@ type CheClusterSpecNetworking struct { // +optional // +kubebuilder:default:={gateway: {configLabels: {app: che, component: che-gateway-config}}} Auth Auth `json:"auth"` - // NetworkPolicies configures NetworkPolicy resources for the Che namespace - // and user workspace namespaces. - // When enabled, the following Ingress-only allow policies are created: + // NetworkPolicy configures NetworkPolicy resources for the Che namespace + // and user workspace namespaces. For OpenShift clusters only. + // When enabled, the following policies are created: // In the Che namespace: - // - allow-from-same-namespace: allows traffic between pods in the same namespace. - // - allow-from-workspaces-namespaces: allows traffic from user workspace namespaces - // (namespaces labeled app.kubernetes.io/component=workspaces-namespace). + // - allow-from-same-namespace: allows ingress traffic between Che pods in the same namespace. + // - allow-from-workspaces-namespaces-to-openvsx-registry: allows ingress traffic from user workspace + // namespaces to the OpenVSX registry. + // - allow-from-workspaces-namespaces-to-plugin-registry: allows ingress traffic from user workspace + // namespaces to the plugin registry. + // - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. + // - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. + // - allow-from-operator: allows ingress traffic from the operator pod to Che components. + // - allow-to-everywhere: allows all egress traffic from Che pods. // In each user workspace namespace: - // - allow-from-: allows traffic from the Che namespace. - // - allow-from-operators: allows traffic from the operators namespace. - // - allow-from-same-namespace: allows traffic between pods in the same namespace. - // On OpenShift, these additional policies are also created in each user workspace namespace: - // - allow-from-openshift-monitoring: allows traffic from the monitoring namespace. - // - allow-from-openshift-ingress: allows traffic from the ingress namespace. + // - allow-from-: allows ingress traffic from the Che namespace. + // - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. + // - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. + // - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. + // - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. + // - allow-to-everywhere: allows all egress traffic from workspace pods. // +optional - NetworkPolicies *NetworkPolicies `json:"networkPolicies,omitempty"` + NetworkPolicy *NetworkPolicy `json:"networkPolicy,omitempty"` } type DevEnvironmentNetworking struct { @@ -353,9 +359,9 @@ type DevEnvironmentNetworking struct { ExternalTLSConfig *ExternalTLSConfig `json:"externalTLSConfig,omitempty"` } -// NetworkPolicies configuration settings. +// NetworkPolicy configuration settings. // +k8s:openapi-gen=true -type NetworkPolicies struct { +type NetworkPolicy struct { // Enabled controls whether the operator creates NetworkPolicy resources. // +optional Enabled *bool `json:"enabled"` @@ -1285,5 +1291,6 @@ func (c *CheCluster) IsDevEnvironmentExternalTLSConfigEnabled() bool { } func (c *CheCluster) IsNetworkPoliciesEnabled() bool { - return c.Spec.Networking.NetworkPolicies != nil && ptr.Deref(c.Spec.Networking.NetworkPolicies.Enabled, false) + return c.Spec.Networking.NetworkPolicy != nil && + ptr.Deref(c.Spec.Networking.NetworkPolicy.Enabled, constants.NetworkPolicyEnabled) } diff --git a/api/v2/zz_generated.deepcopy.go b/api/v2/zz_generated.deepcopy.go index 1a0ed97373..45adecde6c 100644 --- a/api/v2/zz_generated.deepcopy.go +++ b/api/v2/zz_generated.deepcopy.go @@ -521,9 +521,9 @@ func (in *CheClusterSpecNetworking) DeepCopyInto(out *CheClusterSpecNetworking) } } in.Auth.DeepCopyInto(&out.Auth) - if in.NetworkPolicies != nil { - in, out := &in.NetworkPolicies, &out.NetworkPolicies - *out = new(NetworkPolicies) + if in.NetworkPolicy != nil { + in, out := &in.NetworkPolicy, &out.NetworkPolicy + *out = new(NetworkPolicy) (*in).DeepCopyInto(*out) } } @@ -1077,7 +1077,7 @@ func (in *KubeRbacProxy) DeepCopy() *KubeRbacProxy { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NetworkPolicies) DeepCopyInto(out *NetworkPolicies) { +func (in *NetworkPolicy) DeepCopyInto(out *NetworkPolicy) { *out = *in if in.Enabled != nil { in, out := &in.Enabled, &out.Enabled @@ -1086,12 +1086,12 @@ func (in *NetworkPolicies) DeepCopyInto(out *NetworkPolicies) { } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPolicies. -func (in *NetworkPolicies) DeepCopy() *NetworkPolicies { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPolicy. +func (in *NetworkPolicy) DeepCopy() *NetworkPolicy { if in == nil { return nil } - out := new(NetworkPolicies) + out := new(NetworkPolicy) in.DeepCopyInto(out) return out } diff --git a/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml b/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml index c2ecab3d48..0a3b022dd9 100644 --- a/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml +++ b/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml @@ -108,7 +108,7 @@ metadata: operatorframework.io/arch.amd64: supported operatorframework.io/arch.arm64: supported operatorframework.io/os.linux: supported - name: eclipse-che.v7.121.0-1045.next + name: eclipse-che.v7.121.0-1048.next namespace: placeholder spec: apiservicedefinitions: {} @@ -1173,7 +1173,7 @@ spec: name: openvsx - image: quay.io/sclorg/postgresql-16-c9s:20260319 name: openvsx-postgres - version: 7.121.0-1045.next + version: 7.121.0-1048.next webhookdefinitions: - admissionReviewVersions: - v1 diff --git a/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml b/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml index cb62013965..51580ca48f 100644 --- a/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml +++ b/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml @@ -27968,22 +27968,28 @@ spec: description: Defines labels which will be set for an Ingress (a route for OpenShift platform). type: object - networkPolicies: + networkPolicy: description: |- - NetworkPolicies configures NetworkPolicy resources for the Che namespace - and user workspace namespaces. - When enabled, the following Ingress-only allow policies are created: + NetworkPolicy configures NetworkPolicy resources for the Che namespace + and user workspace namespaces. For OpenShift clusters only. + When enabled, the following policies are created: In the Che namespace: - - allow-from-same-namespace: allows traffic between pods in the same namespace. - - allow-from-workspaces-namespaces: allows traffic from user workspace namespaces - (namespaces labeled app.kubernetes.io/component=workspaces-namespace). + - allow-from-same-namespace: allows ingress traffic between Che pods in the same namespace. + - allow-from-workspaces-namespaces-to-openvsx-registry: allows ingress traffic from user workspace + namespaces to the OpenVSX registry. + - allow-from-workspaces-namespaces-to-plugin-registry: allows ingress traffic from user workspace + namespaces to the plugin registry. + - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. + - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. + - allow-from-operator: allows ingress traffic from the operator pod to Che components. + - allow-to-everywhere: allows all egress traffic from Che pods. In each user workspace namespace: - - allow-from-: allows traffic from the Che namespace. - - allow-from-operators: allows traffic from the operators namespace. - - allow-from-same-namespace: allows traffic between pods in the same namespace. - On OpenShift, these additional policies are also created in each user workspace namespace: - - allow-from-openshift-monitoring: allows traffic from the monitoring namespace. - - allow-from-openshift-ingress: allows traffic from the ingress namespace. + - allow-from-: allows ingress traffic from the Che namespace. + - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. + - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. + - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. + - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. + - allow-to-everywhere: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/cmd/main.go b/cmd/main.go index eb2a860734..5ed23011d3 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -22,6 +22,7 @@ import ( oauthv1 "github.com/openshift/api/oauth/v1" userv1 "github.com/openshift/api/user/v1" monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" + "k8s.io/apimachinery/pkg/selection" "sigs.k8s.io/controller-runtime/pkg/webhook" "github.com/eclipse-che/che-operator/controllers/namespacecache" @@ -335,73 +336,82 @@ func main() { // watch k8s objects with labels `app.kubernetes.io/part-of=che.eclipse.org` func getCacheFunc() (cache.NewCacheFunc, error) { - partOfCheObjectSelector, err := labels.Parse(fmt.Sprintf("%s=%s", constants.KubernetesPartOfLabelKey, constants.CheEclipseOrg)) + partOfEclipseChe := labels.SelectorFromSet(map[string]string{constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg}) + + // Cache the DevWorkspace Operator pod so the cached client can be used + // to quickly determine its namespace (see `pkg/deploy/devworkspace/dwo_namespace.go` usage). + partOfEclipseCheOrDevWorkspaceRequirements, err := labels.NewRequirement( + constants.KubernetesPartOfLabelKey, + selection.In, + []string{constants.CheEclipseOrg, constants.DevWorkspaceOperatorName}, + ) if err != nil { return nil, err } + partOfEclipseCheOrDevWorkspace := labels.NewSelector().Add(*partOfEclipseCheOrDevWorkspaceRequirements) selectors := map[client.Object]cache.ByObject{ &appsv1.Deployment{}: { - Label: partOfCheObjectSelector, + Label: partOfEclipseChe, }, &corev1.Pod{}: { - Label: partOfCheObjectSelector, + Label: partOfEclipseCheOrDevWorkspace, }, &batchv1.Job{}: { - Label: partOfCheObjectSelector, + Label: partOfEclipseChe, }, &corev1.Service{}: { - Label: partOfCheObjectSelector, + Label: partOfEclipseChe, }, &networkingv1.Ingress{}: { - Label: partOfCheObjectSelector, + Label: partOfEclipseChe, }, &networkingv1.NetworkPolicy{}: { - Label: partOfCheObjectSelector, + Label: partOfEclipseChe, }, &corev1.ConfigMap{}: { - Label: partOfCheObjectSelector, + Label: partOfEclipseChe, }, &corev1.Secret{}: { - Label: partOfCheObjectSelector, + Label: partOfEclipseChe, }, &corev1.ServiceAccount{}: { - Label: partOfCheObjectSelector, + Label: partOfEclipseChe, }, &rbacv1.Role{}: { - Label: partOfCheObjectSelector, + Label: partOfEclipseChe, }, &rbacv1.RoleBinding{}: { - Label: partOfCheObjectSelector, + Label: partOfEclipseChe, }, &rbacv1.ClusterRole{}: { - Label: partOfCheObjectSelector, + Label: partOfEclipseChe, }, &rbacv1.ClusterRoleBinding{}: { - Label: partOfCheObjectSelector, + Label: partOfEclipseChe, }, &corev1.PersistentVolumeClaim{}: { - Label: partOfCheObjectSelector, + Label: partOfEclipseChe, }, &corev1.LimitRange{}: { - Label: partOfCheObjectSelector, + Label: partOfEclipseChe, }, &corev1.ResourceQuota{}: { - Label: partOfCheObjectSelector, + Label: partOfEclipseChe, }, } if infrastructure.IsOpenShift() { - selectors[&routev1.Route{}] = cache.ByObject{Label: partOfCheObjectSelector} - selectors[&templatev1.Template{}] = cache.ByObject{Label: partOfCheObjectSelector} + selectors[&routev1.Route{}] = cache.ByObject{Label: partOfEclipseChe} + selectors[&templatev1.Template{}] = cache.ByObject{Label: partOfEclipseChe} } if infrastructure.IsServiceMonitorEnabled() { - selectors[&monitoringv1.ServiceMonitor{}] = cache.ByObject{Label: partOfCheObjectSelector} + selectors[&monitoringv1.ServiceMonitor{}] = cache.ByObject{Label: partOfEclipseChe} } if infrastructure.IsOpenShiftOAuthEnabled() { - selectors[&oauthv1.OAuthClient{}] = cache.ByObject{Label: partOfCheObjectSelector} + selectors[&oauthv1.OAuthClient{}] = cache.ByObject{Label: partOfEclipseChe} } return func(config *rest.Config, opts cache.Options) (cache.Cache, error) { diff --git a/config/crd/bases/org.eclipse.che_checlusters.yaml b/config/crd/bases/org.eclipse.che_checlusters.yaml index 9f7f1afe45..c5849f2a17 100644 --- a/config/crd/bases/org.eclipse.che_checlusters.yaml +++ b/config/crd/bases/org.eclipse.che_checlusters.yaml @@ -27842,22 +27842,28 @@ spec: description: Defines labels which will be set for an Ingress (a route for OpenShift platform). type: object - networkPolicies: + networkPolicy: description: |- - NetworkPolicies configures NetworkPolicy resources for the Che namespace - and user workspace namespaces. - When enabled, the following Ingress-only allow policies are created: + NetworkPolicy configures NetworkPolicy resources for the Che namespace + and user workspace namespaces. For OpenShift clusters only. + When enabled, the following policies are created: In the Che namespace: - - allow-from-same-namespace: allows traffic between pods in the same namespace. - - allow-from-workspaces-namespaces: allows traffic from user workspace namespaces - (namespaces labeled app.kubernetes.io/component=workspaces-namespace). + - allow-from-same-namespace: allows ingress traffic between Che pods in the same namespace. + - allow-from-workspaces-namespaces-to-openvsx-registry: allows ingress traffic from user workspace + namespaces to the OpenVSX registry. + - allow-from-workspaces-namespaces-to-plugin-registry: allows ingress traffic from user workspace + namespaces to the plugin registry. + - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. + - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. + - allow-from-operator: allows ingress traffic from the operator pod to Che components. + - allow-to-everywhere: allows all egress traffic from Che pods. In each user workspace namespace: - - allow-from-: allows traffic from the Che namespace. - - allow-from-operators: allows traffic from the operators namespace. - - allow-from-same-namespace: allows traffic between pods in the same namespace. - On OpenShift, these additional policies are also created in each user workspace namespace: - - allow-from-openshift-monitoring: allows traffic from the monitoring namespace. - - allow-from-openshift-ingress: allows traffic from the ingress namespace. + - allow-from-: allows ingress traffic from the Che namespace. + - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. + - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. + - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. + - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. + - allow-to-everywhere: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/controllers/che/checluster_controller.go b/controllers/che/checluster_controller.go index cc0cd7c180..0cd1a10ada 100644 --- a/controllers/che/checluster_controller.go +++ b/controllers/che/checluster_controller.go @@ -14,12 +14,14 @@ package che import ( "context" + "fmt" "time" "github.com/eclipse-che/che-operator/pkg/common/constants" k8sclient "github.com/eclipse-che/che-operator/pkg/common/k8s-client" "github.com/eclipse-che/che-operator/pkg/common/reconciler" "github.com/eclipse-che/che-operator/pkg/deploy/metrics" + "github.com/eclipse-che/che-operator/pkg/deploy/networkpolicies" monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/controller" @@ -43,7 +45,6 @@ import ( "github.com/eclipse-che/che-operator/pkg/deploy/gateway" identityprovider "github.com/eclipse-che/che-operator/pkg/deploy/identity-provider" "github.com/eclipse-che/che-operator/pkg/deploy/migration" - "github.com/eclipse-che/che-operator/pkg/deploy/networkpolicies" "github.com/eclipse-che/che-operator/pkg/deploy/openvsx" openvsxdatabase "github.com/eclipse-che/che-operator/pkg/deploy/openvsx/openvsx-database" openvsxserver "github.com/eclipse-che/che-operator/pkg/deploy/openvsx/openvsx-server" @@ -111,6 +112,10 @@ func NewReconciler( reconcilerManager.AddReconciler(devworkspace.NewDevWorkspaceConfigReconciler()) reconcilerManager.AddReconciler(rbac.NewGatewayPermissionsReconciler()) + if infrastructure.IsOpenShift() { + reconcilerManager.AddReconciler(networkpolicies.NewNetworkPoliciesReconciler()) + } + // we have to expose che endpoint independently of syncing other server // resources since che host is used for dashboard deployment and che config map reconcilerManager.AddReconciler(server.NewCheHostReconciler()) @@ -125,11 +130,9 @@ func NewReconciler( reconcilerManager.AddReconciler(openvsxdatabase.NewOpenVSXDatabaseReconciler()) reconcilerManager.AddReconciler(openvsxserver.NewOpenVSXServerReconciler()) reconcilerManager.AddReconciler(editorsdefinitions.NewEditorsDefinitionsReconciler()) - reconcilerManager.AddReconciler(devworkspace.NewDwoNamespaceReconciler()) reconcilerManager.AddReconciler(dashboard.NewDashboardReconciler()) reconcilerManager.AddReconciler(gateway.NewGatewayReconciler()) reconcilerManager.AddReconciler(server.NewCheServerReconciler()) - reconcilerManager.AddReconciler(networkpolicies.NewNetworkPoliciesReconciler()) reconcilerManager.AddReconciler(imagepuller.NewImagePuller()) if infrastructure.IsOpenShift() { @@ -246,20 +249,23 @@ func (r *CheClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) } // Resolve proxy configuration - proxy, err := GetProxyConfiguration(deployContext) + deployContext.Proxy, err = GetProxyConfiguration(deployContext) if err != nil { r.Log.Error(err, "Error on reading proxy configuration") return ctrl.Result{}, err } - deployContext.Proxy = proxy // Resolve authentication configuration - authentication, err := ResolveAuthentication(deployContext) + deployContext.Authentication, err = ResolveAuthentication(deployContext) if err != nil { r.Log.Error(err, "Error on resolving authentication") return ctrl.Result{}, err } - deployContext.Authentication = authentication + + deployContext.DwoNamespace, err = devworkspace.GetDevWorkspaceOperatorNamespace(clusterAPI.ClientWrapper) + if err != nil { + return ctrl.Result{}, fmt.Errorf("could not get DevWorkspaceOperator namespace: %w", err) + } // Detect whether self-signed certificate is used isSelfSignedCertificate, err := tls.IsSelfSignedCertificateUsed(deployContext) diff --git a/controllers/usernamespace/usernamespace_controller.go b/controllers/usernamespace/usernamespace_controller.go index 7a25a7c735..2933d61bdf 100644 --- a/controllers/usernamespace/usernamespace_controller.go +++ b/controllers/usernamespace/usernamespace_controller.go @@ -24,6 +24,7 @@ import ( k8sclient "github.com/eclipse-che/che-operator/pkg/common/k8s-client" defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults" containercapabilties "github.com/eclipse-che/che-operator/pkg/deploy/container-capabilities" + "github.com/eclipse-che/che-operator/pkg/deploy/devworkspace" "k8s.io/apimachinery/pkg/labels" "k8s.io/utils/ptr" @@ -64,12 +65,11 @@ const ( ) type CheUserNamespaceReconciler struct { - scheme *runtime.Scheme - client client.Client - nonCachedClient client.Client - clientWrapper *k8sclient.K8sClientWrapper - nonCachedClientWrapper *k8sclient.K8sClientWrapper - namespaceCache *namespacecache.NamespaceCache + scheme *runtime.Scheme + client client.Client + nonCachedClient client.Client + clientWrapper *k8sclient.K8sClientWrapper + namespaceCache *namespacecache.NamespaceCache } var _ reconcile.Reconciler = (*CheUserNamespaceReconciler)(nil) @@ -81,12 +81,11 @@ func NewCheUserNamespaceReconciler( namespaceCache *namespacecache.NamespaceCache) *CheUserNamespaceReconciler { return &CheUserNamespaceReconciler{ - scheme: scheme, - client: client, - nonCachedClient: noncachedClient, - clientWrapper: k8sclient.NewK8sClient(client, scheme), - nonCachedClientWrapper: k8sclient.NewK8sClient(noncachedClient, scheme), - namespaceCache: namespaceCache, + scheme: scheme, + client: client, + nonCachedClient: noncachedClient, + clientWrapper: k8sclient.NewK8sClient(client, scheme), + namespaceCache: namespaceCache, } } @@ -242,6 +241,7 @@ func (r *CheUserNamespaceReconciler) Reconcile(ctx context.Context, req ctrl.Req ClusterAPI: chetypes.ClusterAPI{ Client: r.client, NonCachingClient: r.nonCachedClient, + ClientWrapper: r.clientWrapper, Scheme: r.scheme, }, } @@ -303,8 +303,10 @@ func (r *CheUserNamespaceReconciler) Reconcile(ctx context.Context, req ctrl.Req return ctrl.Result{}, err } - if err = r.reconcileNetworkPolicies(ctx, req.Name, checluster); err != nil { - return ctrl.Result{}, fmt.Errorf("failed to reconcile network policies in namespace %s: %w", req.Name, err) + if infrastructure.IsOpenShift() { + if err = r.reconcileNetworkPolicies(ctx, req.Name, deployContext); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to reconcile network policies in namespace %s: %w", req.Name, err) + } } return ctrl.Result{}, nil @@ -623,14 +625,14 @@ func (r *CheUserNamespaceReconciler) reconcileSCCPrivileges( func (r *CheUserNamespaceReconciler) reconcileNetworkPolicies( ctx context.Context, targetNs string, - checluster *chev2.CheCluster, + deployContext *chetypes.DeployContext, ) error { - policies, err := r.getNetworkPolicies(targetNs, checluster) + policies, err := r.getNetworkPolicies(targetNs, deployContext) if err != nil { return fmt.Errorf("could not prepare list of network policy objects: %w", err) } - if !checluster.IsNetworkPoliciesEnabled() { + if !deployContext.CheCluster.IsNetworkPoliciesEnabled() { networkPolicyList := &networkingv1.NetworkPolicyList{} items, err := r.clientWrapper.List(ctx, networkPolicyList, @@ -672,22 +674,20 @@ func (r *CheUserNamespaceReconciler) reconcileNetworkPolicies( func (r *CheUserNamespaceReconciler) getNetworkPolicies( targetNs string, - checluster *chev2.CheCluster, + deployContext *chetypes.DeployContext, ) ([]*networkingv1.NetworkPolicy, error) { - operatorNamespace, err := infrastructure.GetOperatorNamespace() + devWorkspaceOperatorNamespace, err := devworkspace.GetDevWorkspaceOperatorNamespace(deployContext.ClusterAPI.ClientWrapper) if err != nil { - return nil, fmt.Errorf("could not get operator namespace: %w", err) + return nil, fmt.Errorf("could not get DevWorkspaceOperator namespace: %w", err) } - var networkPolicies []*networkingv1.NetworkPolicy - - allowFromEclipseCheNetworkPolicy := &networkingv1.NetworkPolicy{ + allowFromEclipseChe := &networkingv1.NetworkPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "NetworkPolicy", APIVersion: networkingv1.SchemeGroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ - Name: "allow-from-" + defaults.GetCheFlavor(), + Name: "allow-from-" + deployContext.CheCluster.Namespace, Namespace: targetNs, Labels: deploy.GetLabels(defaults.GetCheFlavor()), }, @@ -699,7 +699,12 @@ func (r *CheUserNamespaceReconciler) getNetworkPolicies( { NamespaceSelector: &metav1.LabelSelector{ MatchLabels: map[string]string{ - "kubernetes.io/metadata.name": checluster.Namespace, + "kubernetes.io/metadata.name": deployContext.CheCluster.Namespace, + }, + }, + PodSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, }, }, }, @@ -710,7 +715,7 @@ func (r *CheUserNamespaceReconciler) getNetworkPolicies( }, } - allowFromSameNamespaceNetworkPolicy := &networkingv1.NetworkPolicy{ + allowFromSameNamespace := &networkingv1.NetworkPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "NetworkPolicy", APIVersion: networkingv1.SchemeGroupVersion.String(), @@ -735,13 +740,13 @@ func (r *CheUserNamespaceReconciler) getNetworkPolicies( }, } - allowFromOperatorsNetworkPolicy := &networkingv1.NetworkPolicy{ + allowFromDevWorkspaceOperator := &networkingv1.NetworkPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "NetworkPolicy", APIVersion: networkingv1.SchemeGroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ - Name: "allow-from-operators", + Name: "allow-from-devworkspace-operator", Namespace: targetNs, Labels: deploy.GetLabels(defaults.GetCheFlavor()), }, @@ -753,7 +758,12 @@ func (r *CheUserNamespaceReconciler) getNetworkPolicies( { NamespaceSelector: &metav1.LabelSelector{ MatchLabels: map[string]string{ - "kubernetes.io/metadata.name": operatorNamespace, + "kubernetes.io/metadata.name": devWorkspaceOperatorNamespace, + }, + }, + PodSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + constants.KubernetesPartOfLabelKey: constants.DevWorkspaceOperatorName, }, }, }, @@ -764,80 +774,89 @@ func (r *CheUserNamespaceReconciler) getNetworkPolicies( }, } - networkPolicies = append( - networkPolicies, - allowFromEclipseCheNetworkPolicy, - allowFromSameNamespaceNetworkPolicy, - allowFromOperatorsNetworkPolicy, - ) - - if infrastructure.IsOpenShift() { - allowFromOpenShiftMonitoringNetworkPolicy := &networkingv1.NetworkPolicy{ - TypeMeta: metav1.TypeMeta{ - Kind: "NetworkPolicy", - APIVersion: networkingv1.SchemeGroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "allow-from-openshift-monitoring", - Namespace: targetNs, - Labels: deploy.GetLabels(defaults.GetCheFlavor()), - }, - Spec: networkingv1.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{}, - Ingress: []networkingv1.NetworkPolicyIngressRule{ - { - From: []networkingv1.NetworkPolicyPeer{ - { - NamespaceSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "network.openshift.io/policy-group": "monitoring", - }, + allowFromOpenShiftMonitoring := &networkingv1.NetworkPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: "NetworkPolicy", + APIVersion: networkingv1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-from-openshift-monitoring", + Namespace: targetNs, + Labels: deploy.GetLabels(defaults.GetCheFlavor()), + }, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{}, + Ingress: []networkingv1.NetworkPolicyIngressRule{ + { + From: []networkingv1.NetworkPolicyPeer{ + { + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "network.openshift.io/policy-group": "monitoring", }, }, }, }, }, - PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress}, }, - } + PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress}, + }, + } - allowFromOpenShiftIngressNetworkPolicy := &networkingv1.NetworkPolicy{ - TypeMeta: metav1.TypeMeta{ - Kind: "NetworkPolicy", - APIVersion: networkingv1.SchemeGroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "allow-from-openshift-ingress", - Namespace: targetNs, - Labels: deploy.GetLabels(defaults.GetCheFlavor()), - }, - Spec: networkingv1.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{}, - Ingress: []networkingv1.NetworkPolicyIngressRule{ - { - From: []networkingv1.NetworkPolicyPeer{ - { - NamespaceSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "network.openshift.io/policy-group": "ingress", - }, + allowFromOpenShiftIngress := &networkingv1.NetworkPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: "NetworkPolicy", + APIVersion: networkingv1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-from-openshift-ingress", + Namespace: targetNs, + Labels: deploy.GetLabels(defaults.GetCheFlavor()), + }, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{}, + Ingress: []networkingv1.NetworkPolicyIngressRule{ + { + From: []networkingv1.NetworkPolicyPeer{ + { + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "network.openshift.io/policy-group": "ingress", }, }, }, }, }, - PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress}, }, - } + PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress}, + }, + } - networkPolicies = append( - networkPolicies, - allowFromOpenShiftMonitoringNetworkPolicy, - allowFromOpenShiftIngressNetworkPolicy, - ) + allowToEverywhere := &networkingv1.NetworkPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: "NetworkPolicy", + APIVersion: networkingv1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-to-everywhere", + Namespace: targetNs, + Labels: deploy.GetLabels(defaults.GetCheFlavor()), + }, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{}, + Egress: []networkingv1.NetworkPolicyEgressRule{{}}, + PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeEgress}, + }, } - return networkPolicies, nil + return []*networkingv1.NetworkPolicy{ + allowFromEclipseChe, + allowFromSameNamespace, + allowFromDevWorkspaceOperator, + allowFromOpenShiftMonitoring, + allowFromOpenShiftIngress, + allowToEverywhere, + }, nil } func prefixedName(name string) string { diff --git a/controllers/usernamespace/usernamespace_controller_network_policies_test.go b/controllers/usernamespace/usernamespace_controller_network_policies_test.go index 50dd47e94c..619fc40a18 100644 --- a/controllers/usernamespace/usernamespace_controller_network_policies_test.go +++ b/controllers/usernamespace/usernamespace_controller_network_policies_test.go @@ -16,26 +16,33 @@ import ( "context" "testing" - defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults" - "github.com/eclipse-che/che-operator/pkg/deploy" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/utils/ptr" - - networkingv1 "k8s.io/api/networking/v1" - chev2 "github.com/eclipse-che/che-operator/api/v2" "github.com/eclipse-che/che-operator/pkg/common/constants" "github.com/eclipse-che/che-operator/pkg/common/infrastructure" projectv1 "github.com/openshift/api/project/v1" "github.com/stretchr/testify/assert" + networkingv1 "k8s.io/api/networking/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" ) -func TestNetworkPoliciesCreatedWhenEnabledOnOpenShift(t *testing.T) { +var allUserNsNetworkPolicyNames = []string{ + "allow-from-eclipse-che", + "allow-from-same-namespace", + "allow-from-devworkspace-operator", + "allow-from-openshift-monitoring", + "allow-from-openshift-ingress", + "allow-to-everywhere", +} + +func buildNetworkPolicyTestObjects( + networkPolicyEnabled bool, +) (*chev2.CheCluster, *corev1.Namespace, *projectv1.Project) { cheCluster := &chev2.CheCluster{ ObjectMeta: metav1.ObjectMeta{ Name: "eclipse-che", @@ -43,8 +50,8 @@ func TestNetworkPoliciesCreatedWhenEnabledOnOpenShift(t *testing.T) { }, Spec: chev2.CheClusterSpec{ Networking: chev2.CheClusterSpecNetworking{ - NetworkPolicies: &chev2.NetworkPolicies{ - Enabled: ptr.To(true), + NetworkPolicy: &chev2.NetworkPolicy{ + Enabled: ptr.To(networkPolicyEnabled), }, }, }, @@ -72,149 +79,126 @@ func TestNetworkPoliciesCreatedWhenEnabledOnOpenShift(t *testing.T) { }, } + return cheCluster, userNamespace, userProject +} + +func TestNetworkPoliciesCreatedWhenEnabledOnOpenShift(t *testing.T) { + cheCluster, userNamespace, userProject := buildNetworkPolicyTestObjects(true) + _, cl, r := setup(infrastructure.OpenShiftV4, cheCluster, userProject, userNamespace) _, err := r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "user-project"}}) assert.NoError(t, err) - policyNames := []string{ - "allow-from-" + defaults.GetCheFlavor(), - "allow-from-same-namespace", - "allow-from-operators", - "allow-from-openshift-monitoring", - "allow-from-openshift-ingress", - } - for _, name := range policyNames { - networkPolicy := &networkingv1.NetworkPolicy{} - err := cl.Get(context.TODO(), client.ObjectKey{Name: name, Namespace: "user-project"}, networkPolicy) + npList := &networkingv1.NetworkPolicyList{} + err = cl.List(context.TODO(), npList, &client.ListOptions{Namespace: "user-project"}) + assert.NoError(t, err) + assert.Equal(t, len(allUserNsNetworkPolicyNames), len(npList.Items)) + + for _, name := range allUserNsNetworkPolicyNames { + np := &networkingv1.NetworkPolicy{} + err := cl.Get( + context.TODO(), + types.NamespacedName{Name: name, Namespace: "user-project"}, + np, + ) assert.NoError(t, err) } +} - networkPolicyList := &networkingv1.NetworkPolicyList{} - err = cl.List(context.TODO(), networkPolicyList) +func TestNetworkPoliciesDeletedWhenDisabled(t *testing.T) { + cheCluster, userNamespace, userProject := buildNetworkPolicyTestObjects(true) + + _, cl, r := setup(infrastructure.OpenShiftV4, cheCluster, userProject, userNamespace) + + _, err := r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "user-project"}}) assert.NoError(t, err) - assert.Len(t, networkPolicyList.Items, 5) -} -func TestNetworkPoliciesCreatedWhenEnabledOnKubernetes(t *testing.T) { - cheCluster := &chev2.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "eclipse-che", - Namespace: "eclipse-che", - }, - Spec: chev2.CheClusterSpec{ - Networking: chev2.CheClusterSpecNetworking{ - NetworkPolicies: &chev2.NetworkPolicies{ - Enabled: ptr.To(true), - }, - }, - }, - } + cheCluster.Spec.Networking.NetworkPolicy.Enabled = ptr.To(false) + err = cl.Update(context.TODO(), cheCluster) + assert.NoError(t, err) - userNamespace := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: "user-project", - Labels: map[string]string{ - constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, - constants.KubernetesComponentLabelKey: "workspaces-namespace", - constants.WorkspaceNamespaceOwnerUidLabelKey: "some-uid", - }, - }, + _, err = r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "user-project"}}) + assert.NoError(t, err) + + for _, name := range allUserNsNetworkPolicyNames { + np := &networkingv1.NetworkPolicy{} + err := cl.Get( + context.TODO(), + types.NamespacedName{Name: name, Namespace: "user-project"}, + np, + ) + assert.Error(t, err) + assert.True(t, errors.IsNotFound(err)) } +} - _, cl, r := setup(infrastructure.Kubernetes, cheCluster, userNamespace) +func TestNetworkPoliciesIdempotent(t *testing.T) { + cheCluster, userNamespace, userProject := buildNetworkPolicyTestObjects(true) + + _, cl, r := setup(infrastructure.OpenShiftV4, cheCluster, userProject, userNamespace) _, err := r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "user-project"}}) assert.NoError(t, err) - policyNames := []string{ - "allow-from-" + defaults.GetCheFlavor(), - "allow-from-same-namespace", - "allow-from-operators", - } - for _, name := range policyNames { - networkPolicy := &networkingv1.NetworkPolicy{} - err := cl.Get(context.TODO(), client.ObjectKey{Name: name, Namespace: "user-project"}, networkPolicy) + _, err = r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "user-project"}}) + assert.NoError(t, err) + for _, name := range allUserNsNetworkPolicyNames { + np := &networkingv1.NetworkPolicy{} + err := cl.Get( + context.TODO(), + types.NamespacedName{Name: name, Namespace: "user-project"}, + np, + ) assert.NoError(t, err) - assert.Equal(t, constants.CheEclipseOrg, networkPolicy.Labels[constants.KubernetesPartOfLabelKey]) } - - networkPolicyList := &networkingv1.NetworkPolicyList{} - err = cl.List(context.TODO(), networkPolicyList) - assert.NoError(t, err) - assert.Len(t, networkPolicyList.Items, 3) } -func TestNetworkPoliciesDeletedWhenDisabled(t *testing.T) { - cheCluster := &chev2.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "eclipse-che", - Namespace: "eclipse-che", - }, - Spec: chev2.CheClusterSpec{ - Networking: chev2.CheClusterSpecNetworking{ - NetworkPolicies: &chev2.NetworkPolicies{ - Enabled: ptr.To(false), - }, - }, - }, - } - - allowFromCheNetworkPolicy := &networkingv1.NetworkPolicy{ - ObjectMeta: metav1.ObjectMeta{ - Name: "allow-from-" + defaults.GetCheFlavor(), - Namespace: "user-project", - Labels: deploy.GetLabels(defaults.GetCheFlavor()), - }, - } +func TestNetworkPoliciesDeletedOnlyOwnedPolicies(t *testing.T) { + cheCluster, userNamespace, userProject := buildNetworkPolicyTestObjects(true) - anotherAllowFromCheNetworkPolicy := &networkingv1.NetworkPolicy{ + unownedNetworkPolicy := &networkingv1.NetworkPolicy{ ObjectMeta: metav1.ObjectMeta{ - Name: "another-allow-from-" + defaults.GetCheFlavor(), + Name: "unowned-policy", Namespace: "user-project", }, } - userNamespace := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: "user-project", - Labels: map[string]string{ - constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, - constants.KubernetesComponentLabelKey: "workspaces-namespace", - constants.WorkspaceNamespaceOwnerUidLabelKey: "some-uid", - }, - }, - } - - userProject := &projectv1.Project{ - ObjectMeta: metav1.ObjectMeta{ - Name: "user-project", - Labels: map[string]string{ - constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, - constants.KubernetesComponentLabelKey: "workspaces-namespace", - constants.WorkspaceNamespaceOwnerUidLabelKey: "some-uid", - }, - }, - } - _, cl, r := setup( infrastructure.OpenShiftV4, cheCluster, userProject, userNamespace, - allowFromCheNetworkPolicy, - anotherAllowFromCheNetworkPolicy, + unownedNetworkPolicy, ) _, err := r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "user-project"}}) assert.NoError(t, err) - networkPolicy := &networkingv1.NetworkPolicy{} - err = cl.Get(context.TODO(), client.ObjectKey{Name: "allow-from-" + defaults.GetCheFlavor(), Namespace: "user-project"}, networkPolicy) - assert.Error(t, err) - assert.True(t, errors.IsNotFound(err)) + cheCluster.Spec.Networking.NetworkPolicy.Enabled = ptr.To(false) + err = cl.Update(context.TODO(), cheCluster) + assert.NoError(t, err) + + _, err = r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "user-project"}}) + assert.NoError(t, err) - err = cl.Get(context.TODO(), client.ObjectKey{Name: "another-allow-from-" + defaults.GetCheFlavor(), Namespace: "user-project"}, networkPolicy) + for _, name := range allUserNsNetworkPolicyNames { + np := &networkingv1.NetworkPolicy{} + err := cl.Get( + context.TODO(), + types.NamespacedName{Name: name, Namespace: "user-project"}, + np, + ) + assert.Error(t, err) + assert.True(t, errors.IsNotFound(err)) + } + + np := &networkingv1.NetworkPolicy{} + err = cl.Get( + context.TODO(), + types.NamespacedName{Name: "unowned-policy", Namespace: "user-project"}, + np, + ) assert.NoError(t, err) } diff --git a/controllers/usernamespace/usernamespace_controller_setup_test.go b/controllers/usernamespace/usernamespace_controller_setup_test.go index 27985c2677..ae85f31e62 100644 --- a/controllers/usernamespace/usernamespace_controller_setup_test.go +++ b/controllers/usernamespace/usernamespace_controller_setup_test.go @@ -146,17 +146,30 @@ func setupCheCluster(t *testing.T, ctx context.Context, cl client.Client, scheme func setup(infraType infrastructure.Type, objs ...client.Object) (*runtime.Scheme, client.Client, *CheUserNamespaceReconciler) { infrastructure.InitializeForTesting(infraType) - ctx := test.NewCtxBuilder().WithObjects(objs...).WithCheCluster(nil).Build() + dwPod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "devworkspace-operator-manager", + Namespace: "devworkspace-controller", + Labels: map[string]string{ + constants.KubernetesNameLabelKey: constants.DevWorkspaceControllerName, + constants.KubernetesPartOfLabelKey: constants.DevWorkspaceOperatorName, + }, + }, + Spec: corev1.PodSpec{ + ServiceAccountName: constants.DevWorkspaceServiceAccountName, + }, + } + + ctx := test.NewCtxBuilder().WithObjects(objs...).WithObjects(dwPod).WithCheCluster(nil).Build() cl := ctx.ClusterAPI.Client scheme := ctx.ClusterAPI.Scheme r := &CheUserNamespaceReconciler{ - client: cl, - nonCachedClient: cl, - clientWrapper: k8sclient.NewK8sClient(cl, scheme), - nonCachedClientWrapper: k8sclient.NewK8sClient(cl, scheme), - scheme: scheme, + client: cl, + nonCachedClient: cl, + clientWrapper: k8sclient.NewK8sClient(cl, scheme), + scheme: scheme, namespaceCache: &namespacecache.NamespaceCache{ Client: cl, KnownNamespaces: map[string]namespacecache.NamespaceInfo{}, diff --git a/deploy/deployment/kubernetes/combined.yaml b/deploy/deployment/kubernetes/combined.yaml index d72d648734..103a874a82 100644 --- a/deploy/deployment/kubernetes/combined.yaml +++ b/deploy/deployment/kubernetes/combined.yaml @@ -27863,22 +27863,28 @@ spec: description: Defines labels which will be set for an Ingress (a route for OpenShift platform). type: object - networkPolicies: + networkPolicy: description: |- - NetworkPolicies configures NetworkPolicy resources for the Che namespace - and user workspace namespaces. - When enabled, the following Ingress-only allow policies are created: + NetworkPolicy configures NetworkPolicy resources for the Che namespace + and user workspace namespaces. For OpenShift clusters only. + When enabled, the following policies are created: In the Che namespace: - - allow-from-same-namespace: allows traffic between pods in the same namespace. - - allow-from-workspaces-namespaces: allows traffic from user workspace namespaces - (namespaces labeled app.kubernetes.io/component=workspaces-namespace). + - allow-from-same-namespace: allows ingress traffic between Che pods in the same namespace. + - allow-from-workspaces-namespaces-to-openvsx-registry: allows ingress traffic from user workspace + namespaces to the OpenVSX registry. + - allow-from-workspaces-namespaces-to-plugin-registry: allows ingress traffic from user workspace + namespaces to the plugin registry. + - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. + - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. + - allow-from-operator: allows ingress traffic from the operator pod to Che components. + - allow-to-everywhere: allows all egress traffic from Che pods. In each user workspace namespace: - - allow-from-: allows traffic from the Che namespace. - - allow-from-operators: allows traffic from the operators namespace. - - allow-from-same-namespace: allows traffic between pods in the same namespace. - On OpenShift, these additional policies are also created in each user workspace namespace: - - allow-from-openshift-monitoring: allows traffic from the monitoring namespace. - - allow-from-openshift-ingress: allows traffic from the ingress namespace. + - allow-from-: allows ingress traffic from the Che namespace. + - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. + - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. + - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. + - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. + - allow-to-everywhere: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index 1411bbeddc..f519027f38 100644 --- a/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -27858,22 +27858,28 @@ spec: description: Defines labels which will be set for an Ingress (a route for OpenShift platform). type: object - networkPolicies: + networkPolicy: description: |- - NetworkPolicies configures NetworkPolicy resources for the Che namespace - and user workspace namespaces. - When enabled, the following Ingress-only allow policies are created: + NetworkPolicy configures NetworkPolicy resources for the Che namespace + and user workspace namespaces. For OpenShift clusters only. + When enabled, the following policies are created: In the Che namespace: - - allow-from-same-namespace: allows traffic between pods in the same namespace. - - allow-from-workspaces-namespaces: allows traffic from user workspace namespaces - (namespaces labeled app.kubernetes.io/component=workspaces-namespace). + - allow-from-same-namespace: allows ingress traffic between Che pods in the same namespace. + - allow-from-workspaces-namespaces-to-openvsx-registry: allows ingress traffic from user workspace + namespaces to the OpenVSX registry. + - allow-from-workspaces-namespaces-to-plugin-registry: allows ingress traffic from user workspace + namespaces to the plugin registry. + - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. + - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. + - allow-from-operator: allows ingress traffic from the operator pod to Che components. + - allow-to-everywhere: allows all egress traffic from Che pods. In each user workspace namespace: - - allow-from-: allows traffic from the Che namespace. - - allow-from-operators: allows traffic from the operators namespace. - - allow-from-same-namespace: allows traffic between pods in the same namespace. - On OpenShift, these additional policies are also created in each user workspace namespace: - - allow-from-openshift-monitoring: allows traffic from the monitoring namespace. - - allow-from-openshift-ingress: allows traffic from the ingress namespace. + - allow-from-: allows ingress traffic from the Che namespace. + - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. + - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. + - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. + - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. + - allow-to-everywhere: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/deploy/deployment/openshift/combined.yaml b/deploy/deployment/openshift/combined.yaml index 08e9de2f04..af70321c62 100644 --- a/deploy/deployment/openshift/combined.yaml +++ b/deploy/deployment/openshift/combined.yaml @@ -27863,22 +27863,28 @@ spec: description: Defines labels which will be set for an Ingress (a route for OpenShift platform). type: object - networkPolicies: + networkPolicy: description: |- - NetworkPolicies configures NetworkPolicy resources for the Che namespace - and user workspace namespaces. - When enabled, the following Ingress-only allow policies are created: + NetworkPolicy configures NetworkPolicy resources for the Che namespace + and user workspace namespaces. For OpenShift clusters only. + When enabled, the following policies are created: In the Che namespace: - - allow-from-same-namespace: allows traffic between pods in the same namespace. - - allow-from-workspaces-namespaces: allows traffic from user workspace namespaces - (namespaces labeled app.kubernetes.io/component=workspaces-namespace). + - allow-from-same-namespace: allows ingress traffic between Che pods in the same namespace. + - allow-from-workspaces-namespaces-to-openvsx-registry: allows ingress traffic from user workspace + namespaces to the OpenVSX registry. + - allow-from-workspaces-namespaces-to-plugin-registry: allows ingress traffic from user workspace + namespaces to the plugin registry. + - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. + - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. + - allow-from-operator: allows ingress traffic from the operator pod to Che components. + - allow-to-everywhere: allows all egress traffic from Che pods. In each user workspace namespace: - - allow-from-: allows traffic from the Che namespace. - - allow-from-operators: allows traffic from the operators namespace. - - allow-from-same-namespace: allows traffic between pods in the same namespace. - On OpenShift, these additional policies are also created in each user workspace namespace: - - allow-from-openshift-monitoring: allows traffic from the monitoring namespace. - - allow-from-openshift-ingress: allows traffic from the ingress namespace. + - allow-from-: allows ingress traffic from the Che namespace. + - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. + - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. + - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. + - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. + - allow-to-everywhere: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index 3f6fb151d7..c71a48d563 100644 --- a/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -27858,22 +27858,28 @@ spec: description: Defines labels which will be set for an Ingress (a route for OpenShift platform). type: object - networkPolicies: + networkPolicy: description: |- - NetworkPolicies configures NetworkPolicy resources for the Che namespace - and user workspace namespaces. - When enabled, the following Ingress-only allow policies are created: + NetworkPolicy configures NetworkPolicy resources for the Che namespace + and user workspace namespaces. For OpenShift clusters only. + When enabled, the following policies are created: In the Che namespace: - - allow-from-same-namespace: allows traffic between pods in the same namespace. - - allow-from-workspaces-namespaces: allows traffic from user workspace namespaces - (namespaces labeled app.kubernetes.io/component=workspaces-namespace). + - allow-from-same-namespace: allows ingress traffic between Che pods in the same namespace. + - allow-from-workspaces-namespaces-to-openvsx-registry: allows ingress traffic from user workspace + namespaces to the OpenVSX registry. + - allow-from-workspaces-namespaces-to-plugin-registry: allows ingress traffic from user workspace + namespaces to the plugin registry. + - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. + - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. + - allow-from-operator: allows ingress traffic from the operator pod to Che components. + - allow-to-everywhere: allows all egress traffic from Che pods. In each user workspace namespace: - - allow-from-: allows traffic from the Che namespace. - - allow-from-operators: allows traffic from the operators namespace. - - allow-from-same-namespace: allows traffic between pods in the same namespace. - On OpenShift, these additional policies are also created in each user workspace namespace: - - allow-from-openshift-monitoring: allows traffic from the monitoring namespace. - - allow-from-openshift-ingress: allows traffic from the ingress namespace. + - allow-from-: allows ingress traffic from the Che namespace. + - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. + - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. + - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. + - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. + - allow-to-everywhere: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index 1411bbeddc..f519027f38 100644 --- a/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -27858,22 +27858,28 @@ spec: description: Defines labels which will be set for an Ingress (a route for OpenShift platform). type: object - networkPolicies: + networkPolicy: description: |- - NetworkPolicies configures NetworkPolicy resources for the Che namespace - and user workspace namespaces. - When enabled, the following Ingress-only allow policies are created: + NetworkPolicy configures NetworkPolicy resources for the Che namespace + and user workspace namespaces. For OpenShift clusters only. + When enabled, the following policies are created: In the Che namespace: - - allow-from-same-namespace: allows traffic between pods in the same namespace. - - allow-from-workspaces-namespaces: allows traffic from user workspace namespaces - (namespaces labeled app.kubernetes.io/component=workspaces-namespace). + - allow-from-same-namespace: allows ingress traffic between Che pods in the same namespace. + - allow-from-workspaces-namespaces-to-openvsx-registry: allows ingress traffic from user workspace + namespaces to the OpenVSX registry. + - allow-from-workspaces-namespaces-to-plugin-registry: allows ingress traffic from user workspace + namespaces to the plugin registry. + - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. + - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. + - allow-from-operator: allows ingress traffic from the operator pod to Che components. + - allow-to-everywhere: allows all egress traffic from Che pods. In each user workspace namespace: - - allow-from-: allows traffic from the Che namespace. - - allow-from-operators: allows traffic from the operators namespace. - - allow-from-same-namespace: allows traffic between pods in the same namespace. - On OpenShift, these additional policies are also created in each user workspace namespace: - - allow-from-openshift-monitoring: allows traffic from the monitoring namespace. - - allow-from-openshift-ingress: allows traffic from the ingress namespace. + - allow-from-: allows ingress traffic from the Che namespace. + - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. + - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. + - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. + - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. + - allow-to-everywhere: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/pkg/common/constants/constants.go b/pkg/common/constants/constants.go index 3db5587395..ca28daef01 100644 --- a/pkg/common/constants/constants.go +++ b/pkg/common/constants/constants.go @@ -180,6 +180,9 @@ const ( DefaultContainerRunSccName = "container-run" DefaultDisableContainerRunCapabilities = true + // Networking + NetworkPolicyEnabled = false + // Finalizers ContainerBuildFinalizer = "container-build.finalizers.che.eclipse.org" ContainerRunFinalizer = "che.eclipse.org/container-run" diff --git a/pkg/common/infrastructure/cluster.go b/pkg/common/infrastructure/cluster.go index 04d99e7252..e30a461e6f 100644 --- a/pkg/common/infrastructure/cluster.go +++ b/pkg/common/infrastructure/cluster.go @@ -102,6 +102,10 @@ func SetOpenShiftOAuthEnabledForTesting(enabled bool) { isOpenShiftOAuthEnabled = enabled } +func SetOperatorNamespaceForTesting(desiredOperatorNamespace string) { + operatorNamespace = desiredOperatorNamespace +} + func InitializeForTesting(desiredInfrastructure Type) { infrastructure = desiredInfrastructure diff --git a/pkg/deploy/devworkspace/dwo_namespace.go b/pkg/deploy/devworkspace/dwo_namespace.go index fa1aec959c..24dbc2f3bd 100644 --- a/pkg/deploy/devworkspace/dwo_namespace.go +++ b/pkg/deploy/devworkspace/dwo_namespace.go @@ -16,40 +16,14 @@ import ( "context" "fmt" - "github.com/eclipse-che/che-operator/pkg/common/chetypes" "github.com/eclipse-che/che-operator/pkg/common/constants" - "github.com/eclipse-che/che-operator/pkg/common/reconciler" + k8sclient "github.com/eclipse-che/che-operator/pkg/common/k8s-client" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/reconcile" ) -type DwoNamespaceReconciler struct { - reconciler.Reconcilable -} - -func NewDwoNamespaceReconciler() *DwoNamespaceReconciler { - return &DwoNamespaceReconciler{} -} - -func (r *DwoNamespaceReconciler) Reconcile(ctx *chetypes.DeployContext) (reconcile.Result, bool, error) { - dwoNamespace, err := r.getDevWorkspaceNamespace(ctx) - if err != nil { - return reconcile.Result{}, false, err - } - - ctx.DwoNamespace = dwoNamespace - return reconcile.Result{}, true, nil -} - -func (r *DwoNamespaceReconciler) Finalize(ctx *chetypes.DeployContext) bool { - return true -} - -// getDevWorkspaceNamespace returns the namespace of the DevWorkspace operator. -// It searches for the DevWorkspace Operator Pods by its labels. -func (r *DwoNamespaceReconciler) getDevWorkspaceNamespace(ctx *chetypes.DeployContext) (string, error) { +func GetDevWorkspaceOperatorNamespace(clientWrapper *k8sclient.K8sClientWrapper) (string, error) { selector := labels.SelectorFromSet( labels.Set{ constants.KubernetesNameLabelKey: constants.DevWorkspaceControllerName, @@ -57,21 +31,30 @@ func (r *DwoNamespaceReconciler) getDevWorkspaceNamespace(ctx *chetypes.DeployCo }, ) - items, err := ctx.ClusterAPI.NonCachingClientWrapper.List( + items, err := clientWrapper.List( context.TODO(), &corev1.PodList{}, &client.ListOptions{LabelSelector: selector}, ) if err != nil { - return "", err + return "", fmt.Errorf("failed to list DevWorkspace operator pods: %w", err) } + devWorkspaceOperatorNamespace := "" + for _, item := range items { pod := item.(*corev1.Pod) if pod.Spec.ServiceAccountName == constants.DevWorkspaceServiceAccountName { - return pod.Namespace, nil + if devWorkspaceOperatorNamespace != "" && devWorkspaceOperatorNamespace != pod.Namespace { + return "", fmt.Errorf("multiple DevWorkspace Operator pods were found across different namespaces") + } + devWorkspaceOperatorNamespace = pod.Namespace } } - return "", fmt.Errorf("DevWorkspace namespace not found") + if devWorkspaceOperatorNamespace != "" { + return devWorkspaceOperatorNamespace, nil + } + + return "", fmt.Errorf("DevWorkspace operator namespace not found") } diff --git a/pkg/deploy/networkpolicies/networkpolicies.go b/pkg/deploy/networkpolicies/networkpolicies.go index 26482289df..82b73a95bb 100644 --- a/pkg/deploy/networkpolicies/networkpolicies.go +++ b/pkg/deploy/networkpolicies/networkpolicies.go @@ -19,6 +19,7 @@ import ( "github.com/eclipse-che/che-operator/pkg/common/chetypes" "github.com/eclipse-che/che-operator/pkg/common/constants" "github.com/eclipse-che/che-operator/pkg/common/diffs" + "github.com/eclipse-che/che-operator/pkg/common/infrastructure" k8sclient "github.com/eclipse-che/che-operator/pkg/common/k8s-client" defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults" "github.com/eclipse-che/che-operator/pkg/common/reconciler" @@ -80,7 +81,10 @@ func (r *NetworkPoliciesReconciler) Finalize(_ *chetypes.DeployContext) bool { } func (r *NetworkPoliciesReconciler) syncNetworkPolicy(ctx *chetypes.DeployContext) error { - networkPolicies := r.getNetworkPolicies(ctx) + networkPolicies, err := r.getNetworkPolicies(ctx) + if err != nil { + return fmt.Errorf("could not get network policies: %w", err) + } for _, networkPolicy := range networkPolicies { if err := controllerutil.SetControllerReference(ctx.CheCluster, networkPolicy, ctx.ClusterAPI.Scheme); err != nil { @@ -99,8 +103,13 @@ func (r *NetworkPoliciesReconciler) syncNetworkPolicy(ctx *chetypes.DeployContex return nil } -func (r *NetworkPoliciesReconciler) getNetworkPolicies(ctx *chetypes.DeployContext) []*networkingv1.NetworkPolicy { - allowFromSameNamespaceNetworkPolicy := &networkingv1.NetworkPolicy{ +func (r *NetworkPoliciesReconciler) getNetworkPolicies(ctx *chetypes.DeployContext) ([]*networkingv1.NetworkPolicy, error) { + operatorNamespace, err := infrastructure.GetOperatorNamespace() + if err != nil { + return nil, fmt.Errorf("could not get operator namespace: %w", err) + } + + allowFromSameNamespace := &networkingv1.NetworkPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "NetworkPolicy", APIVersion: networkingv1.SchemeGroupVersion.String(), @@ -111,12 +120,20 @@ func (r *NetworkPoliciesReconciler) getNetworkPolicies(ctx *chetypes.DeployConte Labels: deploy.GetLabels(defaults.GetCheFlavor()), }, Spec: networkingv1.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{}, + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, + }, + }, Ingress: []networkingv1.NetworkPolicyIngressRule{ { From: []networkingv1.NetworkPolicyPeer{ { - PodSelector: &metav1.LabelSelector{}, + PodSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, + }, + }, }, }, }, @@ -125,18 +142,23 @@ func (r *NetworkPoliciesReconciler) getNetworkPolicies(ctx *chetypes.DeployConte }, } - allowFromWorkspacesNamespacesNetworkPolicy := &networkingv1.NetworkPolicy{ + allowFromWorkspacesNamespacesToOpenVSXRegistry := &networkingv1.NetworkPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "NetworkPolicy", APIVersion: networkingv1.SchemeGroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ - Name: "allow-from-workspaces-namespaces", + Name: "allow-from-workspaces-namespaces-to-openvsx-registry", Namespace: ctx.CheCluster.Namespace, Labels: deploy.GetLabels(defaults.GetCheFlavor()), }, Spec: networkingv1.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{}, + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, + constants.KubernetesComponentLabelKey: constants.OpenVSXServerComponentName, + }, + }, Ingress: []networkingv1.NetworkPolicyIngressRule{ { From: []networkingv1.NetworkPolicyPeer{ @@ -154,8 +176,172 @@ func (r *NetworkPoliciesReconciler) getNetworkPolicies(ctx *chetypes.DeployConte }, } - return []*networkingv1.NetworkPolicy{ - allowFromSameNamespaceNetworkPolicy, - allowFromWorkspacesNamespacesNetworkPolicy, + allowFromWorkspacesNamespacesToPluginRegistry := &networkingv1.NetworkPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: "NetworkPolicy", + APIVersion: networkingv1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-from-workspaces-namespaces-to-plugin-registry", + Namespace: ctx.CheCluster.Namespace, + Labels: deploy.GetLabels(defaults.GetCheFlavor()), + }, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, + constants.KubernetesComponentLabelKey: constants.PluginRegistryName, + }, + }, + Ingress: []networkingv1.NetworkPolicyIngressRule{ + { + From: []networkingv1.NetworkPolicyPeer{ + { + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + constants.KubernetesComponentLabelKey: constants.WorkspacesNamespaceComponentName, + }, + }, + }, + }, + }, + }, + PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress}, + }, } + + allowFromOpenShiftIngress := &networkingv1.NetworkPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: "NetworkPolicy", + APIVersion: networkingv1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-from-openshift-ingress", + Namespace: ctx.CheCluster.Namespace, + Labels: deploy.GetLabels(defaults.GetCheFlavor()), + }, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, + }, + }, + Ingress: []networkingv1.NetworkPolicyIngressRule{ + { + From: []networkingv1.NetworkPolicyPeer{ + { + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "network.openshift.io/policy-group": "ingress", + }, + }, + }, + }, + }, + }, + PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress}, + }, + } + + allowFromOpenShiftMonitoring := &networkingv1.NetworkPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: "NetworkPolicy", + APIVersion: networkingv1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-from-openshift-monitoring", + Namespace: ctx.CheCluster.Namespace, + Labels: deploy.GetLabels(defaults.GetCheFlavor()), + }, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, + }, + }, + Ingress: []networkingv1.NetworkPolicyIngressRule{ + { + From: []networkingv1.NetworkPolicyPeer{ + { + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "network.openshift.io/policy-group": "monitoring", + }, + }, + }, + }, + }, + }, + PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress}, + }, + } + + allowFromOperator := &networkingv1.NetworkPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: "NetworkPolicy", + APIVersion: networkingv1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-from-operator", + Namespace: ctx.CheCluster.Namespace, + Labels: deploy.GetLabels(defaults.GetCheFlavor()), + }, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, + }, + }, + Ingress: []networkingv1.NetworkPolicyIngressRule{ + { + From: []networkingv1.NetworkPolicyPeer{ + { + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "kubernetes.io/metadata.name": operatorNamespace, + }, + }, + PodSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, + }, + }, + }, + }, + }, + }, + PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress}, + }, + } + + allowToEverywhere := &networkingv1.NetworkPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: "NetworkPolicy", + APIVersion: networkingv1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-to-everywhere", + Namespace: ctx.CheCluster.Namespace, + Labels: deploy.GetLabels(defaults.GetCheFlavor()), + }, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, + }, + }, + Egress: []networkingv1.NetworkPolicyEgressRule{{}}, + PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeEgress}, + }, + } + + return []*networkingv1.NetworkPolicy{ + allowFromSameNamespace, + allowFromWorkspacesNamespacesToOpenVSXRegistry, + allowFromWorkspacesNamespacesToPluginRegistry, + allowFromOpenShiftIngress, + allowFromOpenShiftMonitoring, + allowFromOperator, + allowToEverywhere, + }, nil } diff --git a/pkg/deploy/networkpolicies/networkpolicies_test.go b/pkg/deploy/networkpolicies/networkpolicies_test.go index e678a92b2f..873abf04e7 100644 --- a/pkg/deploy/networkpolicies/networkpolicies_test.go +++ b/pkg/deploy/networkpolicies/networkpolicies_test.go @@ -17,6 +17,7 @@ import ( "testing" chev2 "github.com/eclipse-che/che-operator/api/v2" + "github.com/eclipse-che/che-operator/pkg/common/infrastructure" "github.com/eclipse-che/che-operator/pkg/common/test" "github.com/stretchr/testify/assert" networkingv1 "k8s.io/api/networking/v1" @@ -24,73 +25,109 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" ) -func TestReconcileNetworkPolicies(t *testing.T) { - ctx := test.NewCtxBuilder().WithCheCluster(&chev2.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", - Name: "eclipse-che", - }, - Spec: chev2.CheClusterSpec{ - Networking: chev2.CheClusterSpecNetworking{ - NetworkPolicies: &chev2.NetworkPolicies{Enabled: ptr.To(true)}, +var allNetworkPolicyNames = []string{ + "allow-from-same-namespace", + "allow-from-workspaces-namespaces-to-openvsx-registry", + "allow-from-workspaces-namespaces-to-plugin-registry", + "allow-from-openshift-ingress", + "allow-from-openshift-monitoring", + "allow-from-operator", + "allow-to-everywhere", +} + +func buildCtx(networkPolicyEnabled bool) *test.DeployContextBuild { + return test.NewCtxBuilder().WithCheCluster( + &chev2.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "eclipse-che", + Name: "eclipse-che", }, - }, - }).Build() + Spec: chev2.CheClusterSpec{ + Networking: chev2.CheClusterSpecNetworking{ + NetworkPolicy: &chev2.NetworkPolicy{Enabled: ptr.To(networkPolicyEnabled)}, + }, + }, + }) +} + +func TestReconcileNetworkPoliciesCreatesAllPolicies(t *testing.T) { + ctx := buildCtx(true).Build() + infrastructure.SetOperatorNamespaceForTesting("eclipse-che") reconciler := NewNetworkPoliciesReconciler() + _, done, err := reconciler.Reconcile(ctx) assert.True(t, done) assert.NoError(t, err) - networkPolicy := &networkingv1.NetworkPolicy{} + npList := &networkingv1.NetworkPolicyList{} + err = ctx.ClusterAPI.Client.List(context.TODO(), npList, &client.ListOptions{Namespace: "eclipse-che"}) + assert.NoError(t, err) + assert.Equal(t, len(allNetworkPolicyNames), len(npList.Items)) - err = ctx.ClusterAPI.Client.Get( - context.TODO(), - types.NamespacedName{ - Name: "allow-from-workspaces-namespaces", - Namespace: "eclipse-che", - }, - networkPolicy, - ) + for _, name := range allNetworkPolicyNames { + np := &networkingv1.NetworkPolicy{} + err := ctx.ClusterAPI.Client.Get( + context.TODO(), + types.NamespacedName{Name: name, Namespace: "eclipse-che"}, + np, + ) + assert.NoError(t, err) + } +} + +func TestReconcileNetworkPoliciesDeletesWhenDisabled(t *testing.T) { + ctx := buildCtx(true).Build() + infrastructure.SetOperatorNamespaceForTesting("eclipse-che") + + reconciler := NewNetworkPoliciesReconciler() + + _, done, err := reconciler.Reconcile(ctx) + assert.True(t, done) assert.NoError(t, err) - err = ctx.ClusterAPI.Client.Get( - context.TODO(), - types.NamespacedName{ - Name: "allow-from-same-namespace", - Namespace: "eclipse-che", - }, - networkPolicy, - ) + ctx.CheCluster.Spec.Networking.NetworkPolicy.Enabled = ptr.To(false) + + _, done, err = reconciler.Reconcile(ctx) + assert.True(t, done) assert.NoError(t, err) - ctx.CheCluster.Spec.Networking.NetworkPolicies.Enabled = ptr.To(false) + for _, name := range allNetworkPolicyNames { + np := &networkingv1.NetworkPolicy{} + err := ctx.ClusterAPI.Client.Get( + context.TODO(), + types.NamespacedName{Name: name, Namespace: "eclipse-che"}, + np, + ) + assert.Error(t, err) + assert.True(t, errors.IsNotFound(err)) + } +} + +func TestReconcileNetworkPoliciesIdempotent(t *testing.T) { + ctx := buildCtx(true).Build() + infrastructure.SetOperatorNamespaceForTesting("eclipse-che") + + reconciler := NewNetworkPoliciesReconciler() + + _, done, err := reconciler.Reconcile(ctx) + assert.True(t, done) + assert.NoError(t, err) _, done, err = reconciler.Reconcile(ctx) assert.True(t, done) assert.NoError(t, err) - err = ctx.ClusterAPI.Client.Get( - context.TODO(), - types.NamespacedName{ - Name: "allow-from-workspaces-namespaces", - Namespace: "eclipse-che", - }, - networkPolicy, - ) - assert.Error(t, err) - assert.True(t, errors.IsNotFound(err)) - - err = ctx.ClusterAPI.Client.Get( - context.TODO(), - types.NamespacedName{ - Name: "allow-from-same-namespace", - Namespace: "eclipse-che", - }, - networkPolicy, - ) - assert.Error(t, err) - assert.True(t, errors.IsNotFound(err)) + for _, name := range allNetworkPolicyNames { + np := &networkingv1.NetworkPolicy{} + err := ctx.ClusterAPI.Client.Get( + context.TODO(), + types.NamespacedName{Name: name, Namespace: "eclipse-che"}, + np, + ) + assert.NoError(t, err) + } } From 4b5408d98dd6fd590f4d4c990f820cbe5fa22954 Mon Sep 17 00:00:00 2001 From: Anatolii Bazko Date: Mon, 27 Jul 2026 15:40:40 +0200 Subject: [PATCH 4/7] commit .claude/rules/pull-requests.md Signed-off-by: Anatolii Bazko --- .claude/rules/pull-requests.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .claude/rules/pull-requests.md diff --git a/.claude/rules/pull-requests.md b/.claude/rules/pull-requests.md new file mode 100644 index 0000000000..4d89374829 --- /dev/null +++ b/.claude/rules/pull-requests.md @@ -0,0 +1,7 @@ +# Pull Request Rules + +- When creating a PR, use the project's PR template from `.github/PULL_REQUEST_TEMPLATE.md`. +- Fill in all sections: "What does this PR do?", "Screenshot/screencast of this PR", "What issues does this PR fix or reference?", and "How to test this PR?". +- Include deployment and test steps appropriate for the change (OpenShift via `test-catalog-from-sources.sh`, Minikube via `test-operator-from-sources.sh`, or both). +- Check all applicable items in the "Common Test Scenarios" checklist (deploy, start workspace, terminal, stop workspace, check operator logs). +- Check all applicable items in the "PR Checklist" (ECA, code complete, builds, tests, devfile, docs, CI/CD). From fa5682f9db5c6191a0eadf34846520e1bc2d839a Mon Sep 17 00:00:00 2001 From: Anatolii Bazko Date: Mon, 27 Jul 2026 16:25:51 +0200 Subject: [PATCH 5/7] chore: fixup Signed-off-by: Anatolii Bazko --- ...espace_controller_network_policies_test.go | 103 +++++++++--------- 1 file changed, 49 insertions(+), 54 deletions(-) diff --git a/controllers/usernamespace/usernamespace_controller_network_policies_test.go b/controllers/usernamespace/usernamespace_controller_network_policies_test.go index 619fc40a18..09e8d3625b 100644 --- a/controllers/usernamespace/usernamespace_controller_network_policies_test.go +++ b/controllers/usernamespace/usernamespace_controller_network_policies_test.go @@ -21,8 +21,8 @@ import ( "github.com/eclipse-che/che-operator/pkg/common/infrastructure" projectv1 "github.com/openshift/api/project/v1" "github.com/stretchr/testify/assert" - networkingv1 "k8s.io/api/networking/v1" corev1 "k8s.io/api/core/v1" + networkingv1 "k8s.io/api/networking/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -40,52 +40,9 @@ var allUserNsNetworkPolicyNames = []string{ "allow-to-everywhere", } -func buildNetworkPolicyTestObjects( - networkPolicyEnabled bool, -) (*chev2.CheCluster, *corev1.Namespace, *projectv1.Project) { - cheCluster := &chev2.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "eclipse-che", - Namespace: "eclipse-che", - }, - Spec: chev2.CheClusterSpec{ - Networking: chev2.CheClusterSpecNetworking{ - NetworkPolicy: &chev2.NetworkPolicy{ - Enabled: ptr.To(networkPolicyEnabled), - }, - }, - }, - } - - userNamespace := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: "user-project", - Labels: map[string]string{ - constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, - constants.KubernetesComponentLabelKey: "workspaces-namespace", - constants.WorkspaceNamespaceOwnerUidLabelKey: "some-uid", - }, - }, - } - - userProject := &projectv1.Project{ - ObjectMeta: metav1.ObjectMeta{ - Name: "user-project", - Labels: map[string]string{ - constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, - constants.KubernetesComponentLabelKey: "workspaces-namespace", - constants.WorkspaceNamespaceOwnerUidLabelKey: "some-uid", - }, - }, - } - - return cheCluster, userNamespace, userProject -} - func TestNetworkPoliciesCreatedWhenEnabledOnOpenShift(t *testing.T) { - cheCluster, userNamespace, userProject := buildNetworkPolicyTestObjects(true) - - _, cl, r := setup(infrastructure.OpenShiftV4, cheCluster, userProject, userNamespace) + cheCluster, userNamespace, userProject := buildNetworkPolicyTestObjects() + _, cl, r := setup(infrastructure.OpenShiftV4, cheCluster, userNamespace, userProject) _, err := r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "user-project"}}) assert.NoError(t, err) @@ -107,9 +64,8 @@ func TestNetworkPoliciesCreatedWhenEnabledOnOpenShift(t *testing.T) { } func TestNetworkPoliciesDeletedWhenDisabled(t *testing.T) { - cheCluster, userNamespace, userProject := buildNetworkPolicyTestObjects(true) - - _, cl, r := setup(infrastructure.OpenShiftV4, cheCluster, userProject, userNamespace) + cheCluster, userNamespace, userProject := buildNetworkPolicyTestObjects() + _, cl, r := setup(infrastructure.OpenShiftV4, cheCluster, userNamespace, userProject) _, err := r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "user-project"}}) assert.NoError(t, err) @@ -134,9 +90,8 @@ func TestNetworkPoliciesDeletedWhenDisabled(t *testing.T) { } func TestNetworkPoliciesIdempotent(t *testing.T) { - cheCluster, userNamespace, userProject := buildNetworkPolicyTestObjects(true) - - _, cl, r := setup(infrastructure.OpenShiftV4, cheCluster, userProject, userNamespace) + cheCluster, userNamespace, userProject := buildNetworkPolicyTestObjects() + _, cl, r := setup(infrastructure.OpenShiftV4, cheCluster, userNamespace, userProject) _, err := r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "user-project"}}) assert.NoError(t, err) @@ -156,7 +111,7 @@ func TestNetworkPoliciesIdempotent(t *testing.T) { } func TestNetworkPoliciesDeletedOnlyOwnedPolicies(t *testing.T) { - cheCluster, userNamespace, userProject := buildNetworkPolicyTestObjects(true) + cheCluster, userNamespace, userProject := buildNetworkPolicyTestObjects() unownedNetworkPolicy := &networkingv1.NetworkPolicy{ ObjectMeta: metav1.ObjectMeta{ @@ -168,8 +123,8 @@ func TestNetworkPoliciesDeletedOnlyOwnedPolicies(t *testing.T) { _, cl, r := setup( infrastructure.OpenShiftV4, cheCluster, - userProject, userNamespace, + userProject, unownedNetworkPolicy, ) @@ -202,3 +157,43 @@ func TestNetworkPoliciesDeletedOnlyOwnedPolicies(t *testing.T) { ) assert.NoError(t, err) } + +func buildNetworkPolicyTestObjects() (*chev2.CheCluster, client.Object, client.Object) { + cheCluster := &chev2.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "eclipse-che", + Namespace: "eclipse-che", + }, + Spec: chev2.CheClusterSpec{ + Networking: chev2.CheClusterSpecNetworking{ + NetworkPolicy: &chev2.NetworkPolicy{ + Enabled: ptr.To(true), + }, + }, + }, + } + + userNamespace := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "user-project", + Labels: map[string]string{ + constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, + constants.KubernetesComponentLabelKey: "workspaces-namespace", + constants.WorkspaceNamespaceOwnerUidLabelKey: "some-uid", + }, + }, + } + + userProject := &projectv1.Project{ + ObjectMeta: metav1.ObjectMeta{ + Name: "user-project", + Labels: map[string]string{ + constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, + constants.KubernetesComponentLabelKey: "workspaces-namespace", + constants.WorkspaceNamespaceOwnerUidLabelKey: "some-uid", + }, + }, + } + + return cheCluster, userNamespace, userProject +} From 9cb67c51e2ead840b468603d52e9dfabe77272b3 Mon Sep 17 00:00:00 2001 From: Anatolii Bazko Date: Tue, 28 Jul 2026 11:24:28 +0200 Subject: [PATCH 6/7] chore: fixup Signed-off-by: Anatolii Bazko --- api/v2/checluster_types.go | 4 +- .../che-operator.clusterserviceversion.yaml | 6 +-- .../org.eclipse.che_checlusters.yaml | 4 +- .../bases/org.eclipse.che_checlusters.yaml | 4 +- .../usernamespace/usernamespace_controller.go | 2 +- ...espace_controller_network_policies_test.go | 2 +- deploy/deployment/kubernetes/combined.yaml | 4 +- ....eclipse.che.CustomResourceDefinition.yaml | 4 +- deploy/deployment/openshift/combined.yaml | 4 +- ....eclipse.che.CustomResourceDefinition.yaml | 4 +- ....eclipse.che.CustomResourceDefinition.yaml | 4 +- pkg/deploy/networkpolicies/networkpolicies.go | 50 +++---------------- .../networkpolicies/networkpolicies_test.go | 5 +- 13 files changed, 30 insertions(+), 67 deletions(-) diff --git a/api/v2/checluster_types.go b/api/v2/checluster_types.go index 28d2331e61..527ca88901 100644 --- a/api/v2/checluster_types.go +++ b/api/v2/checluster_types.go @@ -341,14 +341,14 @@ type CheClusterSpecNetworking struct { // - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. // - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. // - allow-from-operator: allows ingress traffic from the operator pod to Che components. - // - allow-to-everywhere: allows all egress traffic from Che pods. + // - allow-all-ingress: allows all egress traffic from Che pods. // In each user workspace namespace: // - allow-from-: allows ingress traffic from the Che namespace. // - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. // - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. // - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. // - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - // - allow-to-everywhere: allows all egress traffic from workspace pods. + // - allow-all-ingress: allows all egress traffic from workspace pods. // +optional NetworkPolicy *NetworkPolicy `json:"networkPolicy,omitempty"` } diff --git a/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml b/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml index 0a3b022dd9..7124f6887d 100644 --- a/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml +++ b/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml @@ -86,7 +86,7 @@ metadata: categories: Developer Tools certified: "false" containerImage: quay.io/eclipse/che-operator:next - createdAt: "2026-07-24T14:28:09Z" + createdAt: "2026-07-28T09:23:49Z" description: A Kube-native development solution that delivers portable and collaborative developer workspaces. features.operators.openshift.io/cnf: "false" @@ -108,7 +108,7 @@ metadata: operatorframework.io/arch.amd64: supported operatorframework.io/arch.arm64: supported operatorframework.io/os.linux: supported - name: eclipse-che.v7.121.0-1048.next + name: eclipse-che.v7.121.0-1049.next namespace: placeholder spec: apiservicedefinitions: {} @@ -1173,7 +1173,7 @@ spec: name: openvsx - image: quay.io/sclorg/postgresql-16-c9s:20260319 name: openvsx-postgres - version: 7.121.0-1048.next + version: 7.121.0-1049.next webhookdefinitions: - admissionReviewVersions: - v1 diff --git a/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml b/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml index 51580ca48f..8605b706ab 100644 --- a/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml +++ b/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml @@ -27982,14 +27982,14 @@ spec: - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-operator: allows ingress traffic from the operator pod to Che components. - - allow-to-everywhere: allows all egress traffic from Che pods. + - allow-all-ingress: allows all egress traffic from Che pods. In each user workspace namespace: - allow-from-: allows ingress traffic from the Che namespace. - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - - allow-to-everywhere: allows all egress traffic from workspace pods. + - allow-all-ingress: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/config/crd/bases/org.eclipse.che_checlusters.yaml b/config/crd/bases/org.eclipse.che_checlusters.yaml index c5849f2a17..4cf5070ec4 100644 --- a/config/crd/bases/org.eclipse.che_checlusters.yaml +++ b/config/crd/bases/org.eclipse.che_checlusters.yaml @@ -27856,14 +27856,14 @@ spec: - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-operator: allows ingress traffic from the operator pod to Che components. - - allow-to-everywhere: allows all egress traffic from Che pods. + - allow-all-ingress: allows all egress traffic from Che pods. In each user workspace namespace: - allow-from-: allows ingress traffic from the Che namespace. - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - - allow-to-everywhere: allows all egress traffic from workspace pods. + - allow-all-ingress: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/controllers/usernamespace/usernamespace_controller.go b/controllers/usernamespace/usernamespace_controller.go index 2933d61bdf..cc15d3f24a 100644 --- a/controllers/usernamespace/usernamespace_controller.go +++ b/controllers/usernamespace/usernamespace_controller.go @@ -838,7 +838,7 @@ func (r *CheUserNamespaceReconciler) getNetworkPolicies( APIVersion: networkingv1.SchemeGroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ - Name: "allow-to-everywhere", + Name: "allow-all-ingress", Namespace: targetNs, Labels: deploy.GetLabels(defaults.GetCheFlavor()), }, diff --git a/controllers/usernamespace/usernamespace_controller_network_policies_test.go b/controllers/usernamespace/usernamespace_controller_network_policies_test.go index 09e8d3625b..4223d1d0ad 100644 --- a/controllers/usernamespace/usernamespace_controller_network_policies_test.go +++ b/controllers/usernamespace/usernamespace_controller_network_policies_test.go @@ -37,7 +37,7 @@ var allUserNsNetworkPolicyNames = []string{ "allow-from-devworkspace-operator", "allow-from-openshift-monitoring", "allow-from-openshift-ingress", - "allow-to-everywhere", + "allow-all-ingress", } func TestNetworkPoliciesCreatedWhenEnabledOnOpenShift(t *testing.T) { diff --git a/deploy/deployment/kubernetes/combined.yaml b/deploy/deployment/kubernetes/combined.yaml index 103a874a82..859dbe7cfb 100644 --- a/deploy/deployment/kubernetes/combined.yaml +++ b/deploy/deployment/kubernetes/combined.yaml @@ -27877,14 +27877,14 @@ spec: - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-operator: allows ingress traffic from the operator pod to Che components. - - allow-to-everywhere: allows all egress traffic from Che pods. + - allow-all-ingress: allows all egress traffic from Che pods. In each user workspace namespace: - allow-from-: allows ingress traffic from the Che namespace. - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - - allow-to-everywhere: allows all egress traffic from workspace pods. + - allow-all-ingress: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index f519027f38..a960ff4690 100644 --- a/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -27872,14 +27872,14 @@ spec: - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-operator: allows ingress traffic from the operator pod to Che components. - - allow-to-everywhere: allows all egress traffic from Che pods. + - allow-all-ingress: allows all egress traffic from Che pods. In each user workspace namespace: - allow-from-: allows ingress traffic from the Che namespace. - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - - allow-to-everywhere: allows all egress traffic from workspace pods. + - allow-all-ingress: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/deploy/deployment/openshift/combined.yaml b/deploy/deployment/openshift/combined.yaml index af70321c62..a9e25f8a49 100644 --- a/deploy/deployment/openshift/combined.yaml +++ b/deploy/deployment/openshift/combined.yaml @@ -27877,14 +27877,14 @@ spec: - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-operator: allows ingress traffic from the operator pod to Che components. - - allow-to-everywhere: allows all egress traffic from Che pods. + - allow-all-ingress: allows all egress traffic from Che pods. In each user workspace namespace: - allow-from-: allows ingress traffic from the Che namespace. - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - - allow-to-everywhere: allows all egress traffic from workspace pods. + - allow-all-ingress: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index c71a48d563..605bb1d305 100644 --- a/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -27872,14 +27872,14 @@ spec: - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-operator: allows ingress traffic from the operator pod to Che components. - - allow-to-everywhere: allows all egress traffic from Che pods. + - allow-all-ingress: allows all egress traffic from Che pods. In each user workspace namespace: - allow-from-: allows ingress traffic from the Che namespace. - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - - allow-to-everywhere: allows all egress traffic from workspace pods. + - allow-all-ingress: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index f519027f38..a960ff4690 100644 --- a/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -27872,14 +27872,14 @@ spec: - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-operator: allows ingress traffic from the operator pod to Che components. - - allow-to-everywhere: allows all egress traffic from Che pods. + - allow-all-ingress: allows all egress traffic from Che pods. In each user workspace namespace: - allow-from-: allows ingress traffic from the Che namespace. - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - - allow-to-everywhere: allows all egress traffic from workspace pods. + - allow-all-ingress: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/pkg/deploy/networkpolicies/networkpolicies.go b/pkg/deploy/networkpolicies/networkpolicies.go index 82b73a95bb..00ef85efea 100644 --- a/pkg/deploy/networkpolicies/networkpolicies.go +++ b/pkg/deploy/networkpolicies/networkpolicies.go @@ -142,55 +142,20 @@ func (r *NetworkPoliciesReconciler) getNetworkPolicies(ctx *chetypes.DeployConte }, } - allowFromWorkspacesNamespacesToOpenVSXRegistry := &networkingv1.NetworkPolicy{ + allowFromWorkspaces := &networkingv1.NetworkPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "NetworkPolicy", APIVersion: networkingv1.SchemeGroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ - Name: "allow-from-workspaces-namespaces-to-openvsx-registry", + Name: "allow-from-workspaces", Namespace: ctx.CheCluster.Namespace, Labels: deploy.GetLabels(defaults.GetCheFlavor()), }, Spec: networkingv1.NetworkPolicySpec{ PodSelector: metav1.LabelSelector{ MatchLabels: map[string]string{ - constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, - constants.KubernetesComponentLabelKey: constants.OpenVSXServerComponentName, - }, - }, - Ingress: []networkingv1.NetworkPolicyIngressRule{ - { - From: []networkingv1.NetworkPolicyPeer{ - { - NamespaceSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - constants.KubernetesComponentLabelKey: constants.WorkspacesNamespaceComponentName, - }, - }, - }, - }, - }, - }, - PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress}, - }, - } - - allowFromWorkspacesNamespacesToPluginRegistry := &networkingv1.NetworkPolicy{ - TypeMeta: metav1.TypeMeta{ - Kind: "NetworkPolicy", - APIVersion: networkingv1.SchemeGroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "allow-from-workspaces-namespaces-to-plugin-registry", - Namespace: ctx.CheCluster.Namespace, - Labels: deploy.GetLabels(defaults.GetCheFlavor()), - }, - Spec: networkingv1.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{ - constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, - constants.KubernetesComponentLabelKey: constants.PluginRegistryName, + constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg, }, }, Ingress: []networkingv1.NetworkPolicyIngressRule{ @@ -314,13 +279,13 @@ func (r *NetworkPoliciesReconciler) getNetworkPolicies(ctx *chetypes.DeployConte }, } - allowToEverywhere := &networkingv1.NetworkPolicy{ + allowAllEgress := &networkingv1.NetworkPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "NetworkPolicy", APIVersion: networkingv1.SchemeGroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ - Name: "allow-to-everywhere", + Name: "allow-all-ingress", Namespace: ctx.CheCluster.Namespace, Labels: deploy.GetLabels(defaults.GetCheFlavor()), }, @@ -337,11 +302,10 @@ func (r *NetworkPoliciesReconciler) getNetworkPolicies(ctx *chetypes.DeployConte return []*networkingv1.NetworkPolicy{ allowFromSameNamespace, - allowFromWorkspacesNamespacesToOpenVSXRegistry, - allowFromWorkspacesNamespacesToPluginRegistry, + allowFromWorkspaces, allowFromOpenShiftIngress, allowFromOpenShiftMonitoring, allowFromOperator, - allowToEverywhere, + allowAllEgress, }, nil } diff --git a/pkg/deploy/networkpolicies/networkpolicies_test.go b/pkg/deploy/networkpolicies/networkpolicies_test.go index 873abf04e7..a9b703ae5b 100644 --- a/pkg/deploy/networkpolicies/networkpolicies_test.go +++ b/pkg/deploy/networkpolicies/networkpolicies_test.go @@ -30,12 +30,11 @@ import ( var allNetworkPolicyNames = []string{ "allow-from-same-namespace", - "allow-from-workspaces-namespaces-to-openvsx-registry", - "allow-from-workspaces-namespaces-to-plugin-registry", + "allow-from-workspaces", "allow-from-openshift-ingress", "allow-from-openshift-monitoring", "allow-from-operator", - "allow-to-everywhere", + "allow-all-ingress", } func buildCtx(networkPolicyEnabled bool) *test.DeployContextBuild { From 09b928a8db2196a0701178f14e49a47d491797ee Mon Sep 17 00:00:00 2001 From: Anatolii Bazko Date: Tue, 28 Jul 2026 13:33:35 +0200 Subject: [PATCH 7/7] Rename allow-all-ingress -> allow-all-egress Signed-off-by: Anatolii Bazko --- api/v2/checluster_types.go | 4 ++-- .../manifests/che-operator.clusterserviceversion.yaml | 6 +++--- .../eclipse-che/manifests/org.eclipse.che_checlusters.yaml | 4 ++-- config/crd/bases/org.eclipse.che_checlusters.yaml | 4 ++-- controllers/usernamespace/usernamespace_controller.go | 6 +++--- .../usernamespace_controller_network_policies_test.go | 2 +- deploy/deployment/kubernetes/combined.yaml | 4 ++-- ...heclusters.org.eclipse.che.CustomResourceDefinition.yaml | 4 ++-- deploy/deployment/openshift/combined.yaml | 4 ++-- ...heclusters.org.eclipse.che.CustomResourceDefinition.yaml | 4 ++-- ...heclusters.org.eclipse.che.CustomResourceDefinition.yaml | 4 ++-- pkg/deploy/networkpolicies/networkpolicies.go | 2 +- pkg/deploy/networkpolicies/networkpolicies_test.go | 2 +- 13 files changed, 25 insertions(+), 25 deletions(-) diff --git a/api/v2/checluster_types.go b/api/v2/checluster_types.go index 527ca88901..14ded4b481 100644 --- a/api/v2/checluster_types.go +++ b/api/v2/checluster_types.go @@ -341,14 +341,14 @@ type CheClusterSpecNetworking struct { // - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. // - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. // - allow-from-operator: allows ingress traffic from the operator pod to Che components. - // - allow-all-ingress: allows all egress traffic from Che pods. + // - allow-all-egress: allows all egress traffic from Che pods. // In each user workspace namespace: // - allow-from-: allows ingress traffic from the Che namespace. // - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. // - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. // - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. // - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - // - allow-all-ingress: allows all egress traffic from workspace pods. + // - allow-all-egress: allows all egress traffic from workspace pods. // +optional NetworkPolicy *NetworkPolicy `json:"networkPolicy,omitempty"` } diff --git a/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml b/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml index 7124f6887d..a9eef2d0bb 100644 --- a/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml +++ b/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml @@ -86,7 +86,7 @@ metadata: categories: Developer Tools certified: "false" containerImage: quay.io/eclipse/che-operator:next - createdAt: "2026-07-28T09:23:49Z" + createdAt: "2026-07-28T11:33:09Z" description: A Kube-native development solution that delivers portable and collaborative developer workspaces. features.operators.openshift.io/cnf: "false" @@ -108,7 +108,7 @@ metadata: operatorframework.io/arch.amd64: supported operatorframework.io/arch.arm64: supported operatorframework.io/os.linux: supported - name: eclipse-che.v7.121.0-1049.next + name: eclipse-che.v7.121.0-1050.next namespace: placeholder spec: apiservicedefinitions: {} @@ -1173,7 +1173,7 @@ spec: name: openvsx - image: quay.io/sclorg/postgresql-16-c9s:20260319 name: openvsx-postgres - version: 7.121.0-1049.next + version: 7.121.0-1050.next webhookdefinitions: - admissionReviewVersions: - v1 diff --git a/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml b/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml index 8605b706ab..fd8406c99c 100644 --- a/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml +++ b/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml @@ -27982,14 +27982,14 @@ spec: - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-operator: allows ingress traffic from the operator pod to Che components. - - allow-all-ingress: allows all egress traffic from Che pods. + - allow-all-egress: allows all egress traffic from Che pods. In each user workspace namespace: - allow-from-: allows ingress traffic from the Che namespace. - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - - allow-all-ingress: allows all egress traffic from workspace pods. + - allow-all-egress: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/config/crd/bases/org.eclipse.che_checlusters.yaml b/config/crd/bases/org.eclipse.che_checlusters.yaml index 4cf5070ec4..9b9ee173a9 100644 --- a/config/crd/bases/org.eclipse.che_checlusters.yaml +++ b/config/crd/bases/org.eclipse.che_checlusters.yaml @@ -27856,14 +27856,14 @@ spec: - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-operator: allows ingress traffic from the operator pod to Che components. - - allow-all-ingress: allows all egress traffic from Che pods. + - allow-all-egress: allows all egress traffic from Che pods. In each user workspace namespace: - allow-from-: allows ingress traffic from the Che namespace. - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - - allow-all-ingress: allows all egress traffic from workspace pods. + - allow-all-egress: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/controllers/usernamespace/usernamespace_controller.go b/controllers/usernamespace/usernamespace_controller.go index cc15d3f24a..6f7d6b1fc7 100644 --- a/controllers/usernamespace/usernamespace_controller.go +++ b/controllers/usernamespace/usernamespace_controller.go @@ -832,13 +832,13 @@ func (r *CheUserNamespaceReconciler) getNetworkPolicies( }, } - allowToEverywhere := &networkingv1.NetworkPolicy{ + allowAllEgress := &networkingv1.NetworkPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "NetworkPolicy", APIVersion: networkingv1.SchemeGroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ - Name: "allow-all-ingress", + Name: "allow-all-egress", Namespace: targetNs, Labels: deploy.GetLabels(defaults.GetCheFlavor()), }, @@ -855,7 +855,7 @@ func (r *CheUserNamespaceReconciler) getNetworkPolicies( allowFromDevWorkspaceOperator, allowFromOpenShiftMonitoring, allowFromOpenShiftIngress, - allowToEverywhere, + allowAllEgress, }, nil } diff --git a/controllers/usernamespace/usernamespace_controller_network_policies_test.go b/controllers/usernamespace/usernamespace_controller_network_policies_test.go index 4223d1d0ad..4a4f3b8e5d 100644 --- a/controllers/usernamespace/usernamespace_controller_network_policies_test.go +++ b/controllers/usernamespace/usernamespace_controller_network_policies_test.go @@ -37,7 +37,7 @@ var allUserNsNetworkPolicyNames = []string{ "allow-from-devworkspace-operator", "allow-from-openshift-monitoring", "allow-from-openshift-ingress", - "allow-all-ingress", + "allow-all-egress", } func TestNetworkPoliciesCreatedWhenEnabledOnOpenShift(t *testing.T) { diff --git a/deploy/deployment/kubernetes/combined.yaml b/deploy/deployment/kubernetes/combined.yaml index 859dbe7cfb..cd25a438ef 100644 --- a/deploy/deployment/kubernetes/combined.yaml +++ b/deploy/deployment/kubernetes/combined.yaml @@ -27877,14 +27877,14 @@ spec: - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-operator: allows ingress traffic from the operator pod to Che components. - - allow-all-ingress: allows all egress traffic from Che pods. + - allow-all-egress: allows all egress traffic from Che pods. In each user workspace namespace: - allow-from-: allows ingress traffic from the Che namespace. - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - - allow-all-ingress: allows all egress traffic from workspace pods. + - allow-all-egress: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index a960ff4690..48580b1602 100644 --- a/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -27872,14 +27872,14 @@ spec: - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-operator: allows ingress traffic from the operator pod to Che components. - - allow-all-ingress: allows all egress traffic from Che pods. + - allow-all-egress: allows all egress traffic from Che pods. In each user workspace namespace: - allow-from-: allows ingress traffic from the Che namespace. - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - - allow-all-ingress: allows all egress traffic from workspace pods. + - allow-all-egress: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/deploy/deployment/openshift/combined.yaml b/deploy/deployment/openshift/combined.yaml index a9e25f8a49..d64f8d009c 100644 --- a/deploy/deployment/openshift/combined.yaml +++ b/deploy/deployment/openshift/combined.yaml @@ -27877,14 +27877,14 @@ spec: - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-operator: allows ingress traffic from the operator pod to Che components. - - allow-all-ingress: allows all egress traffic from Che pods. + - allow-all-egress: allows all egress traffic from Che pods. In each user workspace namespace: - allow-from-: allows ingress traffic from the Che namespace. - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - - allow-all-ingress: allows all egress traffic from workspace pods. + - allow-all-egress: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index 605bb1d305..a81d597934 100644 --- a/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -27872,14 +27872,14 @@ spec: - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-operator: allows ingress traffic from the operator pod to Che components. - - allow-all-ingress: allows all egress traffic from Che pods. + - allow-all-egress: allows all egress traffic from Che pods. In each user workspace namespace: - allow-from-: allows ingress traffic from the Che namespace. - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - - allow-all-ingress: allows all egress traffic from workspace pods. + - allow-all-egress: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index a960ff4690..48580b1602 100644 --- a/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -27872,14 +27872,14 @@ spec: - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-operator: allows ingress traffic from the operator pod to Che components. - - allow-all-ingress: allows all egress traffic from Che pods. + - allow-all-egress: allows all egress traffic from Che pods. In each user workspace namespace: - allow-from-: allows ingress traffic from the Che namespace. - allow-from-same-namespace: allows ingress traffic between pods in the same namespace. - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator. - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace. - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace. - - allow-all-ingress: allows all egress traffic from workspace pods. + - allow-all-egress: allows all egress traffic from workspace pods. properties: enabled: description: Enabled controls whether the operator creates diff --git a/pkg/deploy/networkpolicies/networkpolicies.go b/pkg/deploy/networkpolicies/networkpolicies.go index 00ef85efea..a31e00ac13 100644 --- a/pkg/deploy/networkpolicies/networkpolicies.go +++ b/pkg/deploy/networkpolicies/networkpolicies.go @@ -285,7 +285,7 @@ func (r *NetworkPoliciesReconciler) getNetworkPolicies(ctx *chetypes.DeployConte APIVersion: networkingv1.SchemeGroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ - Name: "allow-all-ingress", + Name: "allow-all-egress", Namespace: ctx.CheCluster.Namespace, Labels: deploy.GetLabels(defaults.GetCheFlavor()), }, diff --git a/pkg/deploy/networkpolicies/networkpolicies_test.go b/pkg/deploy/networkpolicies/networkpolicies_test.go index a9b703ae5b..ab6ab94051 100644 --- a/pkg/deploy/networkpolicies/networkpolicies_test.go +++ b/pkg/deploy/networkpolicies/networkpolicies_test.go @@ -34,7 +34,7 @@ var allNetworkPolicyNames = []string{ "allow-from-openshift-ingress", "allow-from-openshift-monitoring", "allow-from-operator", - "allow-all-ingress", + "allow-all-egress", } func buildCtx(networkPolicyEnabled bool) *test.DeployContextBuild {