diff --git a/Makefile b/Makefile index 9cb6aa797..e11489905 100644 --- a/Makefile +++ b/Makefile @@ -254,7 +254,7 @@ vet: ## Run go vet against code. go vet ./... ENVTEST_ASSETS_DIR=$(shell pwd)/testbin -test: manifests generate fmt vet prepare-templates ## Run tests. +test: prepare-templates ## Run tests. export MOCK_API=true; go test -mod=vendor ./... -coverprofile cover.out ##@ Build @@ -664,8 +664,9 @@ get-next-version-increment: echo "$${incrementPart}" update-resources: SHELL := /bin/bash -update-resources: check-requirements update-resource-images update-roles update-helmcharts +update-resources: check-requirements update-resource-images update-roles $(MAKE) bundle channel=next + $(MAKE) update-helmcharts HELM_FOLDER=next update-helmcharts: SHELL := /bin/bash update-helmcharts: add-license-download check-requirements diff --git a/README.md b/README.md index bc1c45524..e2c24c21a 100644 --- a/README.md +++ b/README.md @@ -201,28 +201,6 @@ spec: ```bash $ chectl server:update -n --che-operator-cr-patch-yaml -### OpenShift OAuth - -OpenShift clusters include a built-in OAuth server. Che operator supports this authentication method. It's enabled by default. - -To disable OpenShift OAuth use command line: - -```bash -$ kubectl patch checluster/eclipse-che -n --type=merge -p '{"spec":{"auth":{"openShiftoAuth": false}}}' -``` - -or create `cr-patch.yaml` and use it with chectl: - -```yaml -spec: - auth: - openShiftoAuth: false -``` - -```bash -$ chectl server:update -n --che-operator-cr-patch-yaml -``` - ### TLS TLS is enabled by default. diff --git a/api/conversion.go b/api/conversion.go index a06848e5e..677958188 100644 --- a/api/conversion.go +++ b/api/conversion.go @@ -17,6 +17,7 @@ import ( "github.com/eclipse-che/che-operator/api/v2alpha1" "github.com/eclipse-che/che-operator/pkg/deploy" "github.com/eclipse-che/che-operator/pkg/util" + "k8s.io/utils/pointer" "sigs.k8s.io/yaml" ) @@ -104,7 +105,6 @@ func V2alpha1ToV1(v2 *v2alpha1.CheCluster, v1Obj *v1.CheCluster) error { v2alpha1ToV1_Enabled(v1Obj, v2) v2alpha1ToV1_Host(v1Obj, v2) - v2alpha1ToV1_GatewayEnabled(v1Obj, v2) v2alpha1ToV1_GatewayImage(v1Obj, v2) v2alpha1ToV1_GatewayConfigurerImage(v1Obj, v2) v2alpha1ToV1_GatewayTlsSecretName(v1Obj, v2) @@ -145,7 +145,6 @@ func v1ToV2alpha1_WorkspaceDomainEndpointsTlsSecretName(v1 *v1.CheCluster, v2 *v } func v1ToV2alpha1_GatewayEnabled(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) { - exposureStrategy := util.GetServerExposureStrategy(v1) // On Kubernetes, we can have single-host realized using ingresses (that use the same host but different paths). // This is actually not supported on DWCO where we always use the gateway for that. So here, we actually just // ignore the Spec.K8s.SingleHostExposureType, but we need to be aware of it when converting back. @@ -153,8 +152,7 @@ func v1ToV2alpha1_GatewayEnabled(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) { // treat it as such for v2. The difference between default-host and single-host is that the default-host uses // the cluster domain itself as the base domain whereas single-host uses a configured domain. In v2 we always // need a domain configured. - val := exposureStrategy == "single-host" || exposureStrategy == "default-host" - v2.Spec.Gateway.Enabled = &val + v2.Spec.Gateway.Enabled = pointer.BoolPtr(true) } func v1ToV2alpha1_GatewayImage(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) { @@ -184,11 +182,6 @@ func v1ToV2alpha1_K8sIngressAnnotations(v1 *v1.CheCluster, v2 *v2alpha1.CheClust } v2.Spec.K8s.IngressAnnotations["kubernetes.io/ingress.class"] = v1.Spec.K8s.IngressClass } - - // This is what is applied in the deploy/ingress.go but I don't think it is applicable in our situation - // if ingressStrategy != "multi-host" && (component == DevfileRegistryName || component == PluginRegistryName) { - // annotations["nginx.ingress.kubernetes.io/rewrite-target"] = "/$1" - // } } func v2alpha1ToV1_Enabled(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) { @@ -219,70 +212,6 @@ func v2alpha1ToV1_WorkspaceDomainEndpointsTlsSecretName(v1 *v1.CheCluster, v2 *v } } -func v2alpha1ToV1_GatewayEnabled(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) { - v1Strategy := util.GetServerExposureStrategy(v1) - v1IngressStrategy := v1.Spec.K8s.IngressStrategy - - var v2Strategy string - if v2.Spec.Gateway.IsEnabled() { - v2Strategy = "single-host" - } else { - v2Strategy = "multi-host" - } - - if v1.Spec.Server.ServerExposureStrategy == "" { - // in the original, the server exposure strategy was undefined, so we need to check whether we can leave it that way - if util.IsOpenShift { - if v2Strategy != v1Strategy { - // only update if the v2Strategy doesn't correspond to the default determined from the v1 - v1.Spec.Server.ServerExposureStrategy = v2Strategy - } - } else { - // on Kubernetes, the strategy might have been defined by the deprecated Spec.K8s.IngressStrategy - if v1IngressStrategy != "" { - // check for the default host - if v1IngressStrategy == "default-host" { - if v2Strategy != "single-host" { - v1.Spec.K8s.IngressStrategy = v2Strategy - } - } else if v2Strategy != v1Strategy { - // only change the strategy if the determined strategy would differ - v1.Spec.K8s.IngressStrategy = v2Strategy - } - } else { - if v2Strategy != v1Strategy { - // only update if the v2Strategy doesn't correspond to the default determined from the v1 - v1.Spec.Server.ServerExposureStrategy = v2Strategy - } - } - } - } else { - // The below table specifies how to convert the v2Strategy back to v1 taking into the account the original state of v1 - // from which v2 was converted before (which could also be just the default v1, if v2 was created on its own) - // - // v2Strategy | orig v1Strategy | orig v1ExposureType | resulting v1Strategy | resulting v1ExposureType - // ---------------------------------------------------------------------------------------------------- - // single | single | native | single | orig - // single | single | gateway | single | orig - // single | default | NA | default | orig - // single | multi | NA | single | orig - // multi | single | native | multi | orig - // multi | single | gateway | multi | orig - // multi | default | NA | multi | orig - // multi | multi | NA | multi | orig - // - // Notice that we don't ever want to update the singlehost exposure type. This is only used on Kubernetes and dictates how - // we are going to expose the singlehost endpoints - either using ingresses (native) or using the gateway. - // Because this distinction is not made in DWCO, which always uses the gateway, we just keep whatever the value was originally. - // - // The default-host is actually not supported in v2... but it is quite similar to single host in that everything is exposed - // through the cluster hostname and when converting to v2, we convert it to single-host - if v1Strategy != "default-host" || v2Strategy != "single-host" { - v1.Spec.Server.ServerExposureStrategy = v2Strategy - } - } -} - func v2alpha1ToV1_GatewayImage(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) { v1.Spec.Server.SingleHostGatewayImage = v2.Spec.Gateway.Image } diff --git a/api/conversion_test.go b/api/conversion_test.go index 122c5d91b..8fd1308e3 100644 --- a/api/conversion_test.go +++ b/api/conversion_test.go @@ -13,7 +13,6 @@ package org import ( - "fmt" "reflect" "testing" @@ -54,10 +53,9 @@ func TestV1ToV2alpha1(t *testing.T) { }, }, K8s: v1.CheClusterSpecK8SOnly{ - IngressDomain: "ingressDomain", - IngressClass: "traefik", - TlsSecretName: "k8sSecret", - IngressStrategy: "single-host", + IngressDomain: "ingressDomain", + IngressClass: "traefik", + TlsSecretName: "k8sSecret", }, Metrics: v1.CheClusterSpecMetrics{ Enable: true, @@ -207,8 +205,8 @@ func TestV1ToV2alpha1(t *testing.T) { t.FailNow() } - if *v2.Spec.Gateway.Enabled { - t.Errorf("The default for OpenShift without devworkspace enabled (which is our testing object) is multihost, but we found v2 in singlehost.") + if !*v2.Spec.Gateway.Enabled { + t.Errorf("The default for OpenShift is single") } }) }) @@ -418,11 +416,6 @@ func TestV2alpha1ToV1(t *testing.T) { if err != nil { t.Error(err) } - - if util.GetServerExposureStrategy(v1) != "single-host" { - t.Logf("When gateway.enabled is true in v2, v1 is single-host.") - t.FailNow() - } }) }) @@ -463,180 +456,6 @@ func TestV2alpha1ToV1(t *testing.T) { }) } -func TestExposureStrategyConversions(t *testing.T) { - testWithExposure := func(v1ExposureStrategy string, v1IngressStrategy string, v1DevWorkspaceEnabled bool, v2GatewayEnabledChange *bool, test func(*testing.T, *v1.CheCluster)) { - origV1 := &v1.CheCluster{ - Spec: v1.CheClusterSpec{ - Server: v1.CheClusterSpecServer{ - ServerExposureStrategy: v1ExposureStrategy, - }, - K8s: v1.CheClusterSpecK8SOnly{ - IngressStrategy: v1IngressStrategy, - }, - DevWorkspace: v1.CheClusterSpecDevWorkspace{ - Enable: v1DevWorkspaceEnabled, - }, - }, - } - - t.Run(fmt.Sprintf("[v1ExposureStrategy=%v/v1IngressStrategy=%v/v1DevworkspaceEnabled=%v/v2GatewayEnabledChange=%v]", v1ExposureStrategy, v1IngressStrategy, v1DevWorkspaceEnabled, v2GatewayEnabledChange), func(t *testing.T) { - v2 := &v2alpha1.CheCluster{} - if err := V1ToV2alpha1(origV1, v2); err != nil { - t.Error(err) - } - - if v2GatewayEnabledChange != nil { - v2.Spec.Gateway.Enabled = v2GatewayEnabledChange - } - - // now convert back and run the test - v1Tested := &v1.CheCluster{} - if err := V2alpha1ToV1(v2, v1Tested); err != nil { - t.Error(err) - } - - test(t, v1Tested) - }) - } - - testWithExposure("single-host", "", true, nil, func(t *testing.T, old *v1.CheCluster) { - if old.Spec.Server.ServerExposureStrategy != "single-host" { - t.Errorf("The v1 should have single-host exposure after conversion") - } - }) - - testWithExposure("single-host", "", true, pointer.BoolPtr(false), func(t *testing.T, old *v1.CheCluster) { - if old.Spec.Server.ServerExposureStrategy != "multi-host" { - t.Errorf("The v1 should have multi-host exposure after conversion") - } - }) - - testWithExposure("multi-host", "", true, nil, func(t *testing.T, old *v1.CheCluster) { - if old.Spec.Server.ServerExposureStrategy != "multi-host" { - t.Errorf("The v1 should have multi-host exposure after conversion") - } - }) - - testWithExposure("multi-host", "", true, pointer.BoolPtr(true), func(t *testing.T, old *v1.CheCluster) { - if old.Spec.Server.ServerExposureStrategy != "single-host" { - t.Errorf("The v1 should have single-host exposure after conversion") - } - }) - - testWithExposure("default-host", "", true, nil, func(t *testing.T, old *v1.CheCluster) { - if old.Spec.Server.ServerExposureStrategy != "default-host" { - t.Errorf("The v1 should have default-host exposure after conversion") - } - }) - - testWithExposure("default-host", "", true, pointer.BoolPtr(true), func(t *testing.T, old *v1.CheCluster) { - if old.Spec.Server.ServerExposureStrategy != "default-host" { - t.Errorf("The v1 should have default-host exposure after conversion") - } - }) - - testWithExposure("default-host", "", true, pointer.BoolPtr(false), func(t *testing.T, old *v1.CheCluster) { - if old.Spec.Server.ServerExposureStrategy != "multi-host" { - t.Errorf("The v1 should have multi-host exposure after conversion") - } - }) - - onFakeKubernetes(func() { - testWithExposure("", "single-host", true, nil, func(t *testing.T, old *v1.CheCluster) { - if old.Spec.Server.ServerExposureStrategy != "" { - t.Errorf("The server exposure strategy should have been left empty after conversion but was: %v", old.Spec.Server.ServerExposureStrategy) - } - if old.Spec.K8s.IngressStrategy != "single-host" { - t.Errorf("The ingress strategy should have been unchanged after conversion but was: %v", old.Spec.K8s.IngressStrategy) - } - }) - - testWithExposure("", "single-host", true, pointer.BoolPtr(false), func(t *testing.T, old *v1.CheCluster) { - if old.Spec.Server.ServerExposureStrategy != "" { - t.Errorf("The server exposure strategy should have been left empty after conversion but was: %v", old.Spec.Server.ServerExposureStrategy) - } - if old.Spec.K8s.IngressStrategy != "multi-host" { - t.Errorf("The ingress strategy should have been set to multi-host after conversion but was: %v", old.Spec.K8s.IngressStrategy) - } - }) - - testWithExposure("", "single-host", true, pointer.BoolPtr(true), func(t *testing.T, old *v1.CheCluster) { - if old.Spec.Server.ServerExposureStrategy != "" { - t.Errorf("The server exposure strategy should have been left empty after conversion but was: %v", old.Spec.Server.ServerExposureStrategy) - } - if old.Spec.K8s.IngressStrategy != "single-host" { - t.Errorf("The ingress strategy should have been unchanged after conversion but was: %v", old.Spec.K8s.IngressStrategy) - } - }) - - testWithExposure("", "multi-host", true, nil, func(t *testing.T, old *v1.CheCluster) { - if old.Spec.Server.ServerExposureStrategy != "" { - t.Errorf("The server exposure strategy should have been left empty after conversion but was: %v", old.Spec.Server.ServerExposureStrategy) - } - if old.Spec.K8s.IngressStrategy != "multi-host" { - t.Errorf("The ingress strategy should have been unchanged after conversion but was: %v", old.Spec.K8s.IngressStrategy) - } - }) - - // the below two tests test that we're leaving the ingress strategy unchanged if it doesn't affect the effective exposure - // strategy - testWithExposure("", "multi-host", true, pointer.BoolPtr(false), func(t *testing.T, old *v1.CheCluster) { - if old.Spec.Server.ServerExposureStrategy != "" { - t.Errorf("The server exposure strategy should have been left empty after conversion but was: %v", old.Spec.Server.ServerExposureStrategy) - } - if old.Spec.K8s.IngressStrategy != "multi-host" { - t.Errorf("The ingress strategy should have been unchanged after conversion but was: %v", old.Spec.K8s.IngressStrategy) - } - }) - - testWithExposure("", "multi-host", true, pointer.BoolPtr(true), func(t *testing.T, old *v1.CheCluster) { - if old.Spec.Server.ServerExposureStrategy != "" { - t.Errorf("The server exposure strategy should have been left empty after conversion but was: %v", old.Spec.Server.ServerExposureStrategy) - } - if old.Spec.K8s.IngressStrategy != "single-host" { - t.Errorf("The ingress strategy should have been unchanged after conversion but was: %v", old.Spec.K8s.IngressStrategy) - } - }) - - testWithExposure("", "default-host", true, nil, func(t *testing.T, old *v1.CheCluster) { - if old.Spec.Server.ServerExposureStrategy != "" { - t.Errorf("The server exposure strategy should have been left empty after conversion but was: %v", old.Spec.Server.ServerExposureStrategy) - } - if old.Spec.K8s.IngressStrategy != "default-host" { - t.Errorf("The ingress strategy should have been unchanged after conversion but was: %v", old.Spec.K8s.IngressStrategy) - } - }) - }) - - onFakeOpenShift(func() { - testWithExposure("", "", true, nil, func(t *testing.T, old *v1.CheCluster) { - if old.Spec.Server.ServerExposureStrategy != "" { - t.Errorf("The server exposure strategy should have been left empty after conversion but was: %v", old.Spec.Server.ServerExposureStrategy) - } - }) - - testWithExposure("", "", false, nil, func(t *testing.T, old *v1.CheCluster) { - if old.Spec.Server.ServerExposureStrategy != "" { - t.Errorf("The server exposure strategy should have been left empty after conversion but was: %v", old.Spec.Server.ServerExposureStrategy) - } - }) - - testWithExposure("", "", true, pointer.BoolPtr(false), func(t *testing.T, old *v1.CheCluster) { - // default on openshift with devworkspace enabled in v1 is single-host, but we've disabled the gateway in v2. So after the conversion - // v1 should change to an explicit multi-host. - if old.Spec.Server.ServerExposureStrategy != "multi-host" { - t.Errorf("The server exposure strategy should have been set to multi-host after conversion but was: %v", old.Spec.Server.ServerExposureStrategy) - } - }) - - testWithExposure("", "", true, pointer.BoolPtr(true), func(t *testing.T, old *v1.CheCluster) { - if old.Spec.Server.ServerExposureStrategy != "" { - t.Errorf("The server exposure strategy should have been left empty after conversion but was: %v", old.Spec.Server.ServerExposureStrategy) - } - }) - }) -} - func TestFullCircleV1(t *testing.T) { v1Obj := v1.CheCluster{ ObjectMeta: metav1.ObjectMeta{ @@ -661,10 +480,9 @@ func TestFullCircleV1(t *testing.T) { }, }, K8s: v1.CheClusterSpecK8SOnly{ - IngressDomain: "ingressDomain", - IngressClass: "traefik", - TlsSecretName: "k8sSecret", - IngressStrategy: "single-host", + IngressDomain: "ingressDomain", + IngressClass: "traefik", + TlsSecretName: "k8sSecret", }, Metrics: v1.CheClusterSpecMetrics{ Enable: true, diff --git a/api/v1/checluster_types.go b/api/v1/checluster_types.go index 24306299b..aa504a306 100644 --- a/api/v1/checluster_types.go +++ b/api/v1/checluster_types.go @@ -95,6 +95,7 @@ type CheClusterSpecServer struct { // Default value is `Always` for `nightly`, `next` or `latest` images, and `IfNotPresent` in other cases. // +optional CheImagePullPolicy corev1.PullPolicy `json:"cheImagePullPolicy,omitempty"` + // Deprecated. The value of this flag is ignored. // Specifies a variation of the installation. The options are `che` for upstream Che installations, or `codeready` for link:https://developers.redhat.com/products/codeready-workspaces/overview[CodeReady Workspaces] installation. // Override the default value only on necessary occasions. // +optional @@ -158,6 +159,7 @@ type CheClusterSpecServer struct { // +optional // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors="urn:alm:descriptor:com.tectonic.ui:hidden" UseInternalClusterSVCNames bool `json:"useInternalClusterSVCNames"` + // Deprecated. The value of this flag is ignored. // Disable internal cluster SVC names usage to communicate between components to speed up the traffic and avoid proxy issues. // +optional DisableInternalClusterSVCNames *bool `json:"disableInternalClusterSVCNames,omitempty"` @@ -183,9 +185,11 @@ type CheClusterSpecServer struct { // In cores. (500m = .5 cores). Default to 100m. // +optional DashboardCpuRequest string `json:"dashboardCpuRequest,omitempty"` + // Deprecated. The value of this flag is ignored. // Dashboard ingress custom settings. // +optional DashboardIngress IngressCustomSettings `json:"dashboardIngress,omitempty"` + // Deprecated. The value of this flag is ignored. // Dashboard route custom settings. // +optional DashboardRoute RouteCustomSettings `json:"dashboardRoute,omitempty"` @@ -215,9 +219,11 @@ type CheClusterSpecServer struct { // In cores. (500m = .5 cores). Default to 100m. // +optional DevfileRegistryCpuRequest string `json:"devfileRegistryCpuRequest,omitempty"` + // Deprecated. The value of this flag is ignored. // The devfile registry ingress custom settings. // +optional DevfileRegistryIngress IngressCustomSettings `json:"devfileRegistryIngress,omitempty"` + // Deprecated. The value of this flag is ignored. // The devfile registry route custom settings. // +optional DevfileRegistryRoute RouteCustomSettings `json:"devfileRegistryRoute,omitempty"` @@ -259,9 +265,11 @@ type CheClusterSpecServer struct { // In cores. (500m = .5 cores). Default to 100m. // +optional PluginRegistryCpuRequest string `json:"pluginRegistryCpuRequest,omitempty"` + // Deprecated. The value of this flag is ignored. // Plugin registry ingress custom settings. // +optional PluginRegistryIngress IngressCustomSettings `json:"pluginRegistryIngress,omitempty"` + // Deprecated. The value of this flag is ignored. // Plugin registry route custom settings. // +optional PluginRegistryRoute RouteCustomSettings `json:"pluginRegistryRoute,omitempty"` @@ -318,6 +326,7 @@ type CheClusterSpecServer struct { // In cores. (500m = .5 cores). Default to 100m. // +optional ServerCpuRequest string `json:"serverCpuRequest,omitempty"` + // Deprecated. The value of this flag is ignored. // Sets the server and workspaces exposure type. // Possible values are `multi-host`, `single-host`, `default-host`. Defaults to `multi-host`, which creates a separate ingress, or OpenShift routes, for every required endpoint. // `single-host` makes Che exposed on a single host name with workspaces exposed on subpaths. @@ -403,6 +412,7 @@ type CheClusterSpecDB struct { // +k8s:openapi-gen=true // Configuration settings related to the Authentication used by the Che installation. type CheClusterSpecAuth struct { + // Deprecated. The value of this flag is ignored. // For operating with the OpenShift OAuth authentication, create a new user account since the kubeadmin can not be used. // If the value is true, then a new OpenShift OAuth user will be created for the HTPasswd identity provider. // If the value is false and the user has already been created, then it will be removed. @@ -410,6 +420,7 @@ type CheClusterSpecAuth struct { // The user's credentials are stored in the `openshift-oauth-user-credentials` secret in 'openshift-config' namespace by Operator. // Note that this solution is Openshift 4 platform-specific. InitialOpenShiftOAuthUser *bool `json:"initialOpenShiftOAuthUser,omitempty"` + // Deprecated. The value of this flag is ignored. // Instructs the Operator on whether or not to deploy a dedicated Identity Provider (Keycloak or RH SSO instance). // Instructs the Operator on whether to deploy a dedicated Identity Provider (Keycloak or RH-SSO instance). // By default, a dedicated Identity Provider server is deployed as part of the Che installation. When `externalIdentityProvider` is `true`, @@ -422,14 +433,17 @@ type CheClusterSpecAuth struct { // See the `externalIdentityProvider` field. By default, this will be automatically calculated and set by the Operator. // +optional IdentityProviderURL string `json:"identityProviderURL,omitempty"` + // Deprecated. The value of this flag is ignored. // Overrides the name of the Identity Provider administrator user. Defaults to `admin`. // +optional IdentityProviderAdminUserName string `json:"identityProviderAdminUserName,omitempty"` + // Deprecated. The value of this flag is ignored. // Overrides the password of Keycloak administrator user. // Override this when an external Identity Provider is in use. See the `externalIdentityProvider` field. // When omitted or left blank, it is set to an auto-generated password. // +optional IdentityProviderPassword string `json:"identityProviderPassword,omitempty"` + // Deprecated. The value of this flag is ignored. // The secret that contains `user` and `password` for Identity Provider. // When the secret is defined, the `identityProviderAdminUserName` and `identityProviderPassword` are ignored. // When the value is omitted or left blank, the one of following scenarios applies: @@ -439,21 +453,25 @@ type CheClusterSpecAuth struct { // The secret must have `app.kubernetes.io/part-of=che.eclipse.org` label. // +optional IdentityProviderSecret string `json:"identityProviderSecret,omitempty"` + // Deprecated. The value of this flag is ignored. // Name of a Identity provider, Keycloak or RH-SSO, realm that is used for Che. // Override this when an external Identity Provider is in use. See the `externalIdentityProvider` field. // When omitted or left blank, it is set to the value of the `flavour` field. // +optional IdentityProviderRealm string `json:"identityProviderRealm,omitempty"` + // Deprecated. The value of this flag is ignored. // Name of a Identity provider, Keycloak or RH-SSO, `client-id` that is used for Che. // Override this when an external Identity Provider is in use. See the `externalIdentityProvider` field. // When omitted or left blank, it is set to the value of the `flavour` field suffixed with `-public`. // +optional IdentityProviderClientId string `json:"identityProviderClientId,omitempty"` + // Deprecated. The value of this flag is ignored. // Password for a Identity Provider, Keycloak or RH-SSO, to connect to the database. // Override this when an external Identity Provider is in use. See the `externalIdentityProvider` field. // When omitted or left blank, it is set to an auto-generated password. // +optional IdentityProviderPostgresPassword string `json:"identityProviderPostgresPassword,omitempty"` + // Deprecated. The value of this flag is ignored. // The secret that contains `password` for the Identity Provider, Keycloak or RH-SSO, to connect to the database. // When the secret is defined, the `identityProviderPostgresPassword` is ignored. When the value is omitted or left blank, the one of following scenarios applies: // 1. `identityProviderPostgresPassword` is defined, then it will be used to connect to the database. @@ -461,9 +479,11 @@ type CheClusterSpecAuth struct { // The secret must have `app.kubernetes.io/part-of=che.eclipse.org` label. // +optional IdentityProviderPostgresSecret string `json:"identityProviderPostgresSecret,omitempty"` + // Deprecated. The value of this flag is ignored. // Forces the default `admin` Che user to update password on first login. Defaults to `false`. // +optional UpdateAdminPassword bool `json:"updateAdminPassword"` + // Deprecated. The value of this flag is ignored. // Enables the integration of the identity provider (Keycloak / RHSSO) with OpenShift OAuth. // Empty value on OpenShift by default. This will allow users to directly login with their OpenShift user through the OpenShift login, // and have their workspaces created under personal OpenShift namespaces. @@ -476,23 +496,29 @@ type CheClusterSpecAuth struct { // Name of the secret set in the OpenShift `OAuthClient` resource used to setup identity federation on the OpenShift side. Auto-generated when left blank. See also the `OAuthClientName` field. // +optional OAuthSecret string `json:"oAuthSecret,omitempty"` + // Deprecated. The value of this flag is ignored. // Overrides the container image used in the Identity Provider, Keycloak or RH-SSO, deployment. // This includes the image tag. Omit it or leave it empty to use the default container image provided by the Operator. // +optional IdentityProviderImage string `json:"identityProviderImage,omitempty"` + // Deprecated. The value of this flag is ignored. // Overrides the image pull policy used in the Identity Provider, Keycloak or RH-SSO, deployment. // Default value is `Always` for `nightly`, `next` or `latest` images, and `IfNotPresent` in other cases. // +optional IdentityProviderImagePullPolicy corev1.PullPolicy `json:"identityProviderImagePullPolicy,omitempty"` + // Deprecated. The value of this flag is ignored. // Ingress custom settings. // +optional IdentityProviderIngress IngressCustomSettings `json:"identityProviderIngress,omitempty"` + // Deprecated. The value of this flag is ignored. // Route custom settings. // +optional IdentityProviderRoute RouteCustomSettings `json:"identityProviderRoute,omitempty"` + // Deprecated. The value of this flag is ignored. // Identity provider container custom settings. // +optional IdentityProviderContainerResources ResourcesCustomSettings `json:"identityProviderContainerResources,omitempty"` + // Deprecated. The value of this flag is ignored. // Enables native user mode. Currently works only on OpenShift and DevWorkspace engine. // Native User mode uses OpenShift OAuth directly as identity provider, without Keycloak. // +optional @@ -509,7 +535,7 @@ type CheClusterSpecAuth struct { // +optional // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors="urn:alm:descriptor:com.tectonic.ui:hidden" GatewayHeaderRewriteSidecarImage string `json:"gatewayHeaderRewriteSidecarImage,omitempty"` - + // Deprecated. The value of this flag is ignored. // Debug internal identity provider. Debug bool `json:"debug,omitempty"` } @@ -597,6 +623,7 @@ type CheClusterSpecStorage struct { type CheClusterSpecK8SOnly struct { // Global ingress domain for a Kubernetes cluster. This MUST be explicitly specified: there are no defaults. IngressDomain string `json:"ingressDomain,omitempty"` + // Deprecated. The value of this flag is ignored. // Strategy for ingress creation. Options are: `multi-host` (host is explicitly provided in ingress), // `single-host` (host is provided, path-based rules) and `default-host` (no host is provided, path-based rules). // Defaults to `multi-host` Deprecated in favor of `serverExposureStrategy` in the `server` section, @@ -617,6 +644,7 @@ type CheClusterSpecK8SOnly struct { // ID of the user the Che Pod and workspace Pods containers run as. Default value is `1724`. // +optional SecurityContextRunAsUser string `json:"securityContextRunAsUser,omitempty"` + // Deprecated. The value of this flag is ignored. // When the serverExposureStrategy is set to `single-host`, the way the server, registries and workspaces are exposed is further configured by this property. // The possible values are `native`, which means that the server and workspaces are exposed using ingresses on K8s // or `gateway` where the server and workspaces are exposed using a custom gateway based on link:https://doc.traefik.io/traefik/[Traefik]. @@ -746,7 +774,6 @@ type CheClusterStatus struct { // +operator-sdk:csv:customresourcedefinitions:type=status,displayName="Help link" // +operator-sdk:csv:customresourcedefinitions:type=status,xDescriptors="urn:alm:descriptor:org.w3:link" HelpLink string `json:"helpLink,omitempty"` - // The status of the Devworkspace subsystem // +optional DevworkspaceStatus v2alpha1.CheClusterStatusV2Alpha1 `json:"devworkspaceStatus,omitempty"` @@ -800,24 +827,3 @@ func (c *CheCluster) IsImagePullerSpecEmpty() bool { func (c *CheCluster) IsImagePullerImagesEmpty() bool { return len(c.Spec.ImagePuller.Spec.Images) == 0 } - -func (c *CheCluster) IsInternalClusterSVCNamesEnabled() bool { - return c.Spec.Server.DisableInternalClusterSVCNames == nil || !*c.Spec.Server.DisableInternalClusterSVCNames -} - -// IsInitialOpenShiftOAuthUserEnabled returns true when initial Openshift oAuth user is enabled for CheCluster resource, otherwise false. -func (c *CheCluster) IsOpenShiftOAuthUserConfigured() bool { - return c.Spec.Auth.InitialOpenShiftOAuthUser != nil && *c.Spec.Auth.InitialOpenShiftOAuthUser -} - -func (c *CheCluster) IsOpenShiftOAuthUserMustBeDeleted() bool { - return c.Spec.Auth.InitialOpenShiftOAuthUser != nil && !*c.Spec.Auth.InitialOpenShiftOAuthUser -} - -func (c *CheCluster) IsOpenShiftOAuthEnabled() bool { - return c.Spec.Auth.OpenShiftoAuth != nil && *c.Spec.Auth.OpenShiftoAuth -} - -func (c *CheCluster) IsNativeUserModeEnabled() bool { - return c.Spec.Auth.NativeUserMode != nil && *c.Spec.Auth.NativeUserMode -} diff --git a/bundle/next/eclipse-che-preview-openshift/manifests/che-operator.clusterserviceversion.yaml b/bundle/next/eclipse-che-preview-openshift/manifests/che-operator.clusterserviceversion.yaml index 8c09600d1..cc89b9a3b 100644 --- a/bundle/next/eclipse-che-preview-openshift/manifests/che-operator.clusterserviceversion.yaml +++ b/bundle/next/eclipse-che-preview-openshift/manifests/che-operator.clusterserviceversion.yaml @@ -66,7 +66,6 @@ metadata: "proxyPort": "", "proxySecret": "", "proxyURL": "", - "tlsSupport": true, "workspaceNamespaceDefault": "-che" }, "storage": { @@ -114,7 +113,7 @@ metadata: operators.operatorframework.io/project_layout: go.kubebuilder.io/v3 repository: https://github.com/eclipse-che/che-operator support: Eclipse Foundation - name: eclipse-che-preview-openshift.v7.43.0-408.next + name: eclipse-che-preview-openshift.v7.43.0-412.next namespace: placeholder spec: apiservicedefinitions: {} @@ -1079,8 +1078,6 @@ spec: value: quay.io/eclipse/che--centos--postgresql-96-centos7:9.6-b681d78125361519180a6ac05242c296f8906c11eab7e207b5ca9a89b6344392 - name: RELATED_IMAGE_postgres_13_3 value: quay.io/eclipse/che--centos--postgresql-13-centos7:1-71b24684d64da46f960682cc4216222a7e4ed8b1a31dd5a865b3e71afdea20d2 - - name: RELATED_IMAGE_keycloak - value: quay.io/eclipse/che-keycloak:next - name: RELATED_IMAGE_che_workspace_plugin_broker_metadata value: quay.io/eclipse/che-plugin-metadata-broker:v3.4.0 - name: RELATED_IMAGE_che_workspace_plugin_broker_artifacts @@ -1406,4 +1403,4 @@ spec: maturity: stable provider: name: Eclipse Foundation - version: 7.43.0-408.next + version: 7.43.0-412.next diff --git a/bundle/next/eclipse-che-preview-openshift/manifests/org_v1_che_crd.yaml b/bundle/next/eclipse-che-preview-openshift/manifests/org_v1_che_crd.yaml index 58ae38fca..1a54f6c10 100644 --- a/bundle/next/eclipse-che-preview-openshift/manifests/org_v1_che_crd.yaml +++ b/bundle/next/eclipse-che-preview-openshift/manifests/org_v1_che_crd.yaml @@ -61,14 +61,16 @@ spec: used by the Che installation. properties: debug: - description: Debug internal identity provider. + description: Deprecated. The value of this flag is ignored. + Debug internal identity provider. type: boolean externalIdentityProvider: - description: 'Instructs the Operator on whether or not to deploy - a dedicated Identity Provider (Keycloak or RH SSO instance). - Instructs the Operator on whether to deploy a dedicated Identity - Provider (Keycloak or RH-SSO instance). By default, a dedicated - Identity Provider server is deployed as part of the Che installation. + description: 'Deprecated. The value of this flag is ignored. + Instructs the Operator on whether or not to deploy a dedicated + Identity Provider (Keycloak or RH SSO instance). Instructs + the Operator on whether to deploy a dedicated Identity Provider + (Keycloak or RH-SSO instance). By default, a dedicated Identity + Provider server is deployed as part of the Che installation. When `externalIdentityProvider` is `true`, no dedicated identity provider will be deployed by the Operator and you will need to provide details about the external identity provider you @@ -90,18 +92,21 @@ spec: Sidecar functionality is now implemented in Traefik plugin. type: string identityProviderAdminUserName: - description: Overrides the name of the Identity Provider administrator + description: Deprecated. The value of this flag is ignored. + Overrides the name of the Identity Provider administrator user. Defaults to `admin`. type: string identityProviderClientId: - description: Name of a Identity provider, Keycloak or RH-SSO, - `client-id` that is used for Che. Override this when an external - Identity Provider is in use. See the `externalIdentityProvider` - field. When omitted or left blank, it is set to the value - of the `flavour` field suffixed with `-public`. + description: Deprecated. The value of this flag is ignored. + Name of a Identity provider, Keycloak or RH-SSO, `client-id` + that is used for Che. Override this when an external Identity + Provider is in use. See the `externalIdentityProvider` field. + When omitted or left blank, it is set to the value of the + `flavour` field suffixed with `-public`. type: string identityProviderContainerResources: - description: Identity provider container custom settings. + description: Deprecated. The value of this flag is ignored. + Identity provider container custom settings. properties: limits: description: Limits describes the maximum amount of compute @@ -129,19 +134,22 @@ spec: type: object type: object identityProviderImage: - description: Overrides the container image used in the Identity - Provider, Keycloak or RH-SSO, deployment. This includes the - image tag. Omit it or leave it empty to use the default container - image provided by the Operator. + description: Deprecated. The value of this flag is ignored. + Overrides the container image used in the Identity Provider, + Keycloak or RH-SSO, deployment. This includes the image tag. + Omit it or leave it empty to use the default container image + provided by the Operator. type: string identityProviderImagePullPolicy: - description: Overrides the image pull policy used in the Identity - Provider, Keycloak or RH-SSO, deployment. Default value is - `Always` for `nightly`, `next` or `latest` images, and `IfNotPresent` + description: Deprecated. The value of this flag is ignored. + Overrides the image pull policy used in the Identity Provider, + Keycloak or RH-SSO, deployment. Default value is `Always` + for `nightly`, `next` or `latest` images, and `IfNotPresent` in other cases. type: string identityProviderIngress: - description: Ingress custom settings. + description: Deprecated. The value of this flag is ignored. + Ingress custom settings. properties: annotations: additionalProperties: @@ -157,25 +165,27 @@ spec: type: string type: object identityProviderPassword: - description: Overrides the password of Keycloak administrator - user. Override this when an external Identity Provider is - in use. See the `externalIdentityProvider` field. When omitted - or left blank, it is set to an auto-generated password. + description: Deprecated. The value of this flag is ignored. + Overrides the password of Keycloak administrator user. Override + this when an external Identity Provider is in use. See the + `externalIdentityProvider` field. When omitted or left blank, + it is set to an auto-generated password. type: string identityProviderPostgresPassword: - description: Password for a Identity Provider, Keycloak or RH-SSO, - to connect to the database. Override this when an external - Identity Provider is in use. See the `externalIdentityProvider` - field. When omitted or left blank, it is set to an auto-generated - password. + description: Deprecated. The value of this flag is ignored. + Password for a Identity Provider, Keycloak or RH-SSO, to connect + to the database. Override this when an external Identity Provider + is in use. See the `externalIdentityProvider` field. When + omitted or left blank, it is set to an auto-generated password. type: string identityProviderPostgresSecret: - description: 'The secret that contains `password` for the Identity - Provider, Keycloak or RH-SSO, to connect to the database. - When the secret is defined, the `identityProviderPostgresPassword` - is ignored. When the value is omitted or left blank, the one - of following scenarios applies: 1. `identityProviderPostgresPassword` - is defined, then it will be used to connect to the database. + description: 'Deprecated. The value of this flag is ignored. + The secret that contains `password` for the Identity Provider, + Keycloak or RH-SSO, to connect to the database. When the secret + is defined, the `identityProviderPostgresPassword` is ignored. + When the value is omitted or left blank, the one of following + scenarios applies: 1. `identityProviderPostgresPassword` is + defined, then it will be used to connect to the database. 2. `identityProviderPostgresPassword` is not defined, then a new secret with the name `che-identity-postgres-secret` will be created with an auto-generated value for `password`. @@ -183,14 +193,16 @@ spec: label.' type: string identityProviderRealm: - description: Name of a Identity provider, Keycloak or RH-SSO, - realm that is used for Che. Override this when an external - Identity Provider is in use. See the `externalIdentityProvider` - field. When omitted or left blank, it is set to the value - of the `flavour` field. + description: Deprecated. The value of this flag is ignored. + Name of a Identity provider, Keycloak or RH-SSO, realm that + is used for Che. Override this when an external Identity Provider + is in use. See the `externalIdentityProvider` field. When + omitted or left blank, it is set to the value of the `flavour` + field. type: string identityProviderRoute: - description: Route custom settings. + description: Deprecated. The value of this flag is ignored. + Route custom settings. properties: annotations: additionalProperties: @@ -212,8 +224,9 @@ spec: type: string type: object identityProviderSecret: - description: 'The secret that contains `user` and `password` - for Identity Provider. When the secret is defined, the `identityProviderAdminUserName` + description: 'Deprecated. The value of this flag is ignored. + The secret that contains `user` and `password` for Identity + Provider. When the secret is defined, the `identityProviderAdminUserName` and `identityProviderPassword` are ignored. When the value is omitted or left blank, the one of following scenarios applies: 1. `identityProviderAdminUserName` and `identityProviderPassword` @@ -232,20 +245,22 @@ spec: set by the Operator. type: string initialOpenShiftOAuthUser: - description: For operating with the OpenShift OAuth authentication, - create a new user account since the kubeadmin can not be used. - If the value is true, then a new OpenShift OAuth user will - be created for the HTPasswd identity provider. If the value - is false and the user has already been created, then it will + description: Deprecated. The value of this flag is ignored. + For operating with the OpenShift OAuth authentication, create + a new user account since the kubeadmin can not be used. If + the value is true, then a new OpenShift OAuth user will be + created for the HTPasswd identity provider. If the value is + false and the user has already been created, then it will be removed. If value is an empty, then do nothing. The user's credentials are stored in the `openshift-oauth-user-credentials` secret in 'openshift-config' namespace by Operator. Note that this solution is Openshift 4 platform-specific. type: boolean nativeUserMode: - description: Enables native user mode. Currently works only - on OpenShift and DevWorkspace engine. Native User mode uses - OpenShift OAuth directly as identity provider, without Keycloak. + description: Deprecated. The value of this flag is ignored. + Enables native user mode. Currently works only on OpenShift + and DevWorkspace engine. Native User mode uses OpenShift OAuth + directly as identity provider, without Keycloak. type: boolean oAuthClientName: description: Name of the OpenShift `OAuthClient` resource used @@ -259,17 +274,19 @@ spec: field. type: string openShiftoAuth: - description: 'Enables the integration of the identity provider - (Keycloak / RHSSO) with OpenShift OAuth. Empty value on OpenShift - by default. This will allow users to directly login with their + description: 'Deprecated. The value of this flag is ignored. + Enables the integration of the identity provider (Keycloak + / RHSSO) with OpenShift OAuth. Empty value on OpenShift by + default. This will allow users to directly login with their OpenShift user through the OpenShift login, and have their workspaces created under personal OpenShift namespaces. WARNING: the `kubeadmin` user is NOT supported, and logging through it will NOT allow accessing the Che Dashboard.' type: boolean updateAdminPassword: - description: Forces the default `admin` Che user to update password - on first login. Defaults to `false`. + description: Deprecated. The value of this flag is ignored. + Forces the default `admin` Che user to update password on + first login. Defaults to `false`. type: boolean type: object database: @@ -456,10 +473,11 @@ spec: This MUST be explicitly specified: there are no defaults.' type: string ingressStrategy: - description: 'Strategy for ingress creation. Options are: `multi-host` - (host is explicitly provided in ingress), `single-host` (host - is provided, path-based rules) and `default-host` (no host - is provided, path-based rules). Defaults to `multi-host` Deprecated + description: 'Deprecated. The value of this flag is ignored. + Strategy for ingress creation. Options are: `multi-host` (host + is explicitly provided in ingress), `single-host` (host is + provided, path-based rules) and `default-host` (no host is + provided, path-based rules). Defaults to `multi-host` Deprecated in favor of `serverExposureStrategy` in the `server` section, which defines this regardless of the cluster type. When both are defined, the `serverExposureStrategy` option takes precedence.' @@ -473,15 +491,16 @@ spec: run as. Default value is `1724`. type: string singleHostExposureType: - description: When the serverExposureStrategy is set to `single-host`, - the way the server, registries and workspaces are exposed - is further configured by this property. The possible values - are `native`, which means that the server and workspaces are - exposed using ingresses on K8s or `gateway` where the server - and workspaces are exposed using a custom gateway based on - link:https://doc.traefik.io/traefik/[Traefik]. All the endpoints - whether backed by the ingress or gateway `route` always point - to the subpaths on the same domain. Defaults to `native`. + description: Deprecated. The value of this flag is ignored. + When the serverExposureStrategy is set to `single-host`, the + way the server, registries and workspaces are exposed is further + configured by this property. The possible values are `native`, + which means that the server and workspaces are exposed using + ingresses on K8s or `gateway` where the server and workspaces + are exposed using a custom gateway based on link:https://doc.traefik.io/traefik/[Traefik]. + All the endpoints whether backed by the ingress or gateway + `route` always point to the subpaths on the same domain. Defaults + to `native`. type: string tlsSecretName: description: Name of a secret that will be used to setup ingress @@ -535,9 +554,9 @@ spec: to `false`. type: string cheFlavor: - description: Specifies a variation of the installation. The - options are `che` for upstream Che installations, or `codeready` - for link:https://developers.redhat.com/products/codeready-workspaces/overview[CodeReady + description: Deprecated. The value of this flag is ignored. + Specifies a variation of the installation. The options are + `che` for upstream Che installations, or `codeready` for link:https://developers.redhat.com/products/codeready-workspaces/overview[CodeReady Workspaces] installation. Override the default value only on necessary occasions. type: string @@ -646,7 +665,8 @@ spec: or `latest` images, and `IfNotPresent` in other cases. type: string dashboardIngress: - description: Dashboard ingress custom settings. + description: Deprecated. The value of this flag is ignored. + Dashboard ingress custom settings. properties: annotations: additionalProperties: @@ -670,7 +690,8 @@ spec: deployment. Defaults to 16Mi. type: string dashboardRoute: - description: Dashboard route custom settings. + description: Deprecated. The value of this flag is ignored. + Dashboard route custom settings. properties: annotations: additionalProperties: @@ -706,7 +727,8 @@ spec: by the Operator. type: string devfileRegistryIngress: - description: The devfile registry ingress custom settings. + description: Deprecated. The value of this flag is ignored. + The devfile registry ingress custom settings. properties: annotations: additionalProperties: @@ -735,7 +757,8 @@ spec: `next` or `latest` images, and `IfNotPresent` in other cases. type: string devfileRegistryRoute: - description: The devfile registry route custom settings. + description: Deprecated. The value of this flag is ignored. + The devfile registry route custom settings. properties: annotations: additionalProperties: @@ -761,9 +784,9 @@ spec: fields. type: string disableInternalClusterSVCNames: - description: Disable internal cluster SVC names usage to communicate - between components to speed up the traffic and avoid proxy - issues. + description: Deprecated. The value of this flag is ignored. + Disable internal cluster SVC names usage to communicate between + components to speed up the traffic and avoid proxy issues. type: boolean externalDevfileRegistries: description: External devfile registries, that serves sample, @@ -828,7 +851,8 @@ spec: by the Operator. type: string pluginRegistryIngress: - description: Plugin registry ingress custom settings. + description: Deprecated. The value of this flag is ignored. + Plugin registry ingress custom settings. properties: annotations: additionalProperties: @@ -857,7 +881,8 @@ spec: `next` or `latest` images, and `IfNotPresent` in other cases. type: string pluginRegistryRoute: - description: Plugin registry route custom settings. + description: Deprecated. The value of this flag is ignored. + Plugin registry route custom settings. properties: annotations: additionalProperties: @@ -933,8 +958,9 @@ spec: deployment In cores. (500m = .5 cores). Default to 100m. type: string serverExposureStrategy: - description: Sets the server and workspaces exposure type. Possible - values are `multi-host`, `single-host`, `default-host`. Defaults + description: Deprecated. The value of this flag is ignored. + Sets the server and workspaces exposure type. Possible values + are `multi-host`, `single-host`, `default-host`. Defaults to `multi-host`, which creates a separate ingress, or OpenShift routes, for every required endpoint. `single-host` makes Che exposed on a single host name with workspaces exposed on subpaths. diff --git a/config/crd/bases/org_v1_che_crd-v1beta1.yaml b/config/crd/bases/org_v1_che_crd-v1beta1.yaml index 9b36098aa..f9c1100c4 100644 --- a/config/crd/bases/org_v1_che_crd-v1beta1.yaml +++ b/config/crd/bases/org_v1_che_crd-v1beta1.yaml @@ -54,18 +54,20 @@ spec: by the Che installation. properties: debug: - description: Debug internal identity provider. + description: Deprecated. The value of this flag is ignored. Debug + internal identity provider. type: boolean externalIdentityProvider: - description: 'Instructs the Operator on whether or not to deploy - a dedicated Identity Provider (Keycloak or RH SSO instance). Instructs - the Operator on whether to deploy a dedicated Identity Provider - (Keycloak or RH-SSO instance). By default, a dedicated Identity - Provider server is deployed as part of the Che installation. When - `externalIdentityProvider` is `true`, no dedicated identity provider - will be deployed by the Operator and you will need to provide - details about the external identity provider you are about to - use. See also all the other fields starting with: `identityProvider`.' + description: 'Deprecated. The value of this flag is ignored. Instructs + the Operator on whether or not to deploy a dedicated Identity + Provider (Keycloak or RH SSO instance). Instructs the Operator + on whether to deploy a dedicated Identity Provider (Keycloak or + RH-SSO instance). By default, a dedicated Identity Provider server + is deployed as part of the Che installation. When `externalIdentityProvider` + is `true`, no dedicated identity provider will be deployed by + the Operator and you will need to provide details about the external + identity provider you are about to use. See also all the other + fields starting with: `identityProvider`.' type: boolean gatewayAuthenticationSidecarImage: description: Gateway sidecar responsible for authentication when @@ -82,18 +84,21 @@ spec: functionality is now implemented in Traefik plugin. type: string identityProviderAdminUserName: - description: Overrides the name of the Identity Provider administrator - user. Defaults to `admin`. + description: Deprecated. The value of this flag is ignored. Overrides + the name of the Identity Provider administrator user. Defaults + to `admin`. type: string identityProviderClientId: - description: Name of a Identity provider, Keycloak or RH-SSO, `client-id` - that is used for Che. Override this when an external Identity - Provider is in use. See the `externalIdentityProvider` field. - When omitted or left blank, it is set to the value of the `flavour` - field suffixed with `-public`. + description: Deprecated. The value of this flag is ignored. Name + of a Identity provider, Keycloak or RH-SSO, `client-id` that is + used for Che. Override this when an external Identity Provider + is in use. See the `externalIdentityProvider` field. When omitted + or left blank, it is set to the value of the `flavour` field suffixed + with `-public`. type: string identityProviderContainerResources: - description: Identity provider container custom settings. + description: Deprecated. The value of this flag is ignored. Identity + provider container custom settings. properties: limits: description: Limits describes the maximum amount of compute @@ -121,19 +126,20 @@ spec: type: object type: object identityProviderImage: - description: Overrides the container image used in the Identity - Provider, Keycloak or RH-SSO, deployment. This includes the image - tag. Omit it or leave it empty to use the default container image - provided by the Operator. + description: Deprecated. The value of this flag is ignored. Overrides + the container image used in the Identity Provider, Keycloak or + RH-SSO, deployment. This includes the image tag. Omit it or leave + it empty to use the default container image provided by the Operator. type: string identityProviderImagePullPolicy: - description: Overrides the image pull policy used in the Identity - Provider, Keycloak or RH-SSO, deployment. Default value is `Always` - for `nightly`, `next` or `latest` images, and `IfNotPresent` in - other cases. + description: Deprecated. The value of this flag is ignored. Overrides + the image pull policy used in the Identity Provider, Keycloak + or RH-SSO, deployment. Default value is `Always` for `nightly`, + `next` or `latest` images, and `IfNotPresent` in other cases. type: string identityProviderIngress: - description: Ingress custom settings. + description: Deprecated. The value of this flag is ignored. Ingress + custom settings. properties: annotations: additionalProperties: @@ -148,38 +154,41 @@ spec: type: string type: object identityProviderPassword: - description: Overrides the password of Keycloak administrator user. - Override this when an external Identity Provider is in use. See - the `externalIdentityProvider` field. When omitted or left blank, - it is set to an auto-generated password. + description: Deprecated. The value of this flag is ignored. Overrides + the password of Keycloak administrator user. Override this when + an external Identity Provider is in use. See the `externalIdentityProvider` + field. When omitted or left blank, it is set to an auto-generated + password. type: string identityProviderPostgresPassword: - description: Password for a Identity Provider, Keycloak or RH-SSO, - to connect to the database. Override this when an external Identity - Provider is in use. See the `externalIdentityProvider` field. - When omitted or left blank, it is set to an auto-generated password. + description: Deprecated. The value of this flag is ignored. Password + for a Identity Provider, Keycloak or RH-SSO, to connect to the + database. Override this when an external Identity Provider is + in use. See the `externalIdentityProvider` field. When omitted + or left blank, it is set to an auto-generated password. type: string identityProviderPostgresSecret: - description: 'The secret that contains `password` for the Identity - Provider, Keycloak or RH-SSO, to connect to the database. When - the secret is defined, the `identityProviderPostgresPassword` - is ignored. When the value is omitted or left blank, the one of - following scenarios applies: 1. `identityProviderPostgresPassword` - is defined, then it will be used to connect to the database. 2. - `identityProviderPostgresPassword` is not defined, then a new - secret with the name `che-identity-postgres-secret` will be created - with an auto-generated value for `password`. The secret must have - `app.kubernetes.io/part-of=che.eclipse.org` label.' + description: 'Deprecated. The value of this flag is ignored. The + secret that contains `password` for the Identity Provider, Keycloak + or RH-SSO, to connect to the database. When the secret is defined, + the `identityProviderPostgresPassword` is ignored. When the value + is omitted or left blank, the one of following scenarios applies: + 1. `identityProviderPostgresPassword` is defined, then it will + be used to connect to the database. 2. `identityProviderPostgresPassword` + is not defined, then a new secret with the name `che-identity-postgres-secret` + will be created with an auto-generated value for `password`. The + secret must have `app.kubernetes.io/part-of=che.eclipse.org` label.' type: string identityProviderRealm: - description: Name of a Identity provider, Keycloak or RH-SSO, realm - that is used for Che. Override this when an external Identity - Provider is in use. See the `externalIdentityProvider` field. - When omitted or left blank, it is set to the value of the `flavour` - field. + description: Deprecated. The value of this flag is ignored. Name + of a Identity provider, Keycloak or RH-SSO, realm that is used + for Che. Override this when an external Identity Provider is in + use. See the `externalIdentityProvider` field. When omitted or + left blank, it is set to the value of the `flavour` field. type: string identityProviderRoute: - description: Route custom settings. + description: Deprecated. The value of this flag is ignored. Route + custom settings. properties: annotations: additionalProperties: @@ -200,8 +209,9 @@ spec: type: string type: object identityProviderSecret: - description: 'The secret that contains `user` and `password` for - Identity Provider. When the secret is defined, the `identityProviderAdminUserName` + description: 'Deprecated. The value of this flag is ignored. The + secret that contains `user` and `password` for Identity Provider. + When the secret is defined, the `identityProviderAdminUserName` and `identityProviderPassword` are ignored. When the value is omitted or left blank, the one of following scenarios applies: 1. `identityProviderAdminUserName` and `identityProviderPassword` @@ -220,20 +230,22 @@ spec: Operator. type: string initialOpenShiftOAuthUser: - description: For operating with the OpenShift OAuth authentication, - create a new user account since the kubeadmin can not be used. - If the value is true, then a new OpenShift OAuth user will be - created for the HTPasswd identity provider. If the value is false - and the user has already been created, then it will be removed. - If value is an empty, then do nothing. The user's credentials - are stored in the `openshift-oauth-user-credentials` secret in - 'openshift-config' namespace by Operator. Note that this solution - is Openshift 4 platform-specific. + description: Deprecated. The value of this flag is ignored. For + operating with the OpenShift OAuth authentication, create a new + user account since the kubeadmin can not be used. If the value + is true, then a new OpenShift OAuth user will be created for the + HTPasswd identity provider. If the value is false and the user + has already been created, then it will be removed. If value is + an empty, then do nothing. The user's credentials are stored in + the `openshift-oauth-user-credentials` secret in 'openshift-config' + namespace by Operator. Note that this solution is Openshift 4 + platform-specific. type: boolean nativeUserMode: - description: Enables native user mode. Currently works only on OpenShift - and DevWorkspace engine. Native User mode uses OpenShift OAuth - directly as identity provider, without Keycloak. + description: Deprecated. The value of this flag is ignored. Enables + native user mode. Currently works only on OpenShift and DevWorkspace + engine. Native User mode uses OpenShift OAuth directly as identity + provider, without Keycloak. type: boolean oAuthClientName: description: Name of the OpenShift `OAuthClient` resource used to @@ -247,17 +259,18 @@ spec: field. type: string openShiftoAuth: - description: 'Enables the integration of the identity provider (Keycloak - / RHSSO) with OpenShift OAuth. Empty value on OpenShift by default. - This will allow users to directly login with their OpenShift user - through the OpenShift login, and have their workspaces created - under personal OpenShift namespaces. WARNING: the `kubeadmin` - user is NOT supported, and logging through it will NOT allow accessing - the Che Dashboard.' + description: 'Deprecated. The value of this flag is ignored. Enables + the integration of the identity provider (Keycloak / RHSSO) with + OpenShift OAuth. Empty value on OpenShift by default. This will + allow users to directly login with their OpenShift user through + the OpenShift login, and have their workspaces created under personal + OpenShift namespaces. WARNING: the `kubeadmin` user is NOT supported, + and logging through it will NOT allow accessing the Che Dashboard.' type: boolean updateAdminPassword: - description: Forces the default `admin` Che user to update password - on first login. Defaults to `false`. + description: Deprecated. The value of this flag is ignored. Forces + the default `admin` Che user to update password on first login. + Defaults to `false`. type: boolean type: object database: @@ -436,13 +449,14 @@ spec: MUST be explicitly specified: there are no defaults.' type: string ingressStrategy: - description: 'Strategy for ingress creation. Options are: `multi-host` - (host is explicitly provided in ingress), `single-host` (host - is provided, path-based rules) and `default-host` (no host is - provided, path-based rules). Defaults to `multi-host` Deprecated - in favor of `serverExposureStrategy` in the `server` section, - which defines this regardless of the cluster type. When both are - defined, the `serverExposureStrategy` option takes precedence.' + description: 'Deprecated. The value of this flag is ignored. Strategy + for ingress creation. Options are: `multi-host` (host is explicitly + provided in ingress), `single-host` (host is provided, path-based + rules) and `default-host` (no host is provided, path-based rules). + Defaults to `multi-host` Deprecated in favor of `serverExposureStrategy` + in the `server` section, which defines this regardless of the + cluster type. When both are defined, the `serverExposureStrategy` + option takes precedence.' type: string securityContextFsGroup: description: The FSGroup in which the Che Pod and workspace Pods @@ -453,12 +467,13 @@ spec: run as. Default value is `1724`. type: string singleHostExposureType: - description: When the serverExposureStrategy is set to `single-host`, - the way the server, registries and workspaces are exposed is further - configured by this property. The possible values are `native`, - which means that the server and workspaces are exposed using ingresses - on K8s or `gateway` where the server and workspaces are exposed - using a custom gateway based on link:https://doc.traefik.io/traefik/[Traefik]. + description: Deprecated. The value of this flag is ignored. When + the serverExposureStrategy is set to `single-host`, the way the + server, registries and workspaces are exposed is further configured + by this property. The possible values are `native`, which means + that the server and workspaces are exposed using ingresses on + K8s or `gateway` where the server and workspaces are exposed using + a custom gateway based on link:https://doc.traefik.io/traefik/[Traefik]. All the endpoints whether backed by the ingress or gateway `route` always point to the subpaths on the same domain. Defaults to `native`. type: string @@ -514,8 +529,9 @@ spec: `false`. type: string cheFlavor: - description: Specifies a variation of the installation. The options - are `che` for upstream Che installations, or `codeready` for link:https://developers.redhat.com/products/codeready-workspaces/overview[CodeReady + description: Deprecated. The value of this flag is ignored. Specifies + a variation of the installation. The options are `che` for upstream + Che installations, or `codeready` for link:https://developers.redhat.com/products/codeready-workspaces/overview[CodeReady Workspaces] installation. Override the default value only on necessary occasions. type: string @@ -620,7 +636,8 @@ spec: `latest` images, and `IfNotPresent` in other cases. type: string dashboardIngress: - description: Dashboard ingress custom settings. + description: Deprecated. The value of this flag is ignored. Dashboard + ingress custom settings. properties: annotations: additionalProperties: @@ -643,7 +660,8 @@ spec: deployment. Defaults to 16Mi. type: string dashboardRoute: - description: Dashboard route custom settings. + description: Deprecated. The value of this flag is ignored. Dashboard + route custom settings. properties: annotations: additionalProperties: @@ -677,7 +695,8 @@ spec: to use the default container image provided by the Operator. type: string devfileRegistryIngress: - description: The devfile registry ingress custom settings. + description: Deprecated. The value of this flag is ignored. The + devfile registry ingress custom settings. properties: annotations: additionalProperties: @@ -705,7 +724,8 @@ spec: `next` or `latest` images, and `IfNotPresent` in other cases. type: string devfileRegistryRoute: - description: The devfile registry route custom settings. + description: Deprecated. The value of this flag is ignored. The + devfile registry route custom settings. properties: annotations: additionalProperties: @@ -730,8 +750,9 @@ spec: fields. type: string disableInternalClusterSVCNames: - description: Disable internal cluster SVC names usage to communicate - between components to speed up the traffic and avoid proxy issues. + description: Deprecated. The value of this flag is ignored. Disable + internal cluster SVC names usage to communicate between components + to speed up the traffic and avoid proxy issues. type: boolean externalDevfileRegistries: description: External devfile registries, that serves sample, ready-to-use @@ -795,7 +816,8 @@ spec: to use the default container image provided by the Operator. type: string pluginRegistryIngress: - description: Plugin registry ingress custom settings. + description: Deprecated. The value of this flag is ignored. Plugin + registry ingress custom settings. properties: annotations: additionalProperties: @@ -823,7 +845,8 @@ spec: `next` or `latest` images, and `IfNotPresent` in other cases. type: string pluginRegistryRoute: - description: Plugin registry route custom settings. + description: Deprecated. The value of this flag is ignored. Plugin + registry route custom settings. properties: annotations: additionalProperties: @@ -897,16 +920,17 @@ spec: In cores. (500m = .5 cores). Default to 100m. type: string serverExposureStrategy: - description: Sets the server and workspaces exposure type. Possible - values are `multi-host`, `single-host`, `default-host`. Defaults - to `multi-host`, which creates a separate ingress, or OpenShift - routes, for every required endpoint. `single-host` makes Che exposed - on a single host name with workspaces exposed on subpaths. Read - the docs to learn about the limitations of this approach. Also - consult the `singleHostExposureType` property to further configure - how the Operator and the Che server make that happen on Kubernetes. - `default-host` exposes the Che server on the host of the cluster. - Read the docs to learn about the limitations of this approach. + description: Deprecated. The value of this flag is ignored. Sets + the server and workspaces exposure type. Possible values are `multi-host`, + `single-host`, `default-host`. Defaults to `multi-host`, which + creates a separate ingress, or OpenShift routes, for every required + endpoint. `single-host` makes Che exposed on a single host name + with workspaces exposed on subpaths. Read the docs to learn about + the limitations of this approach. Also consult the `singleHostExposureType` + property to further configure how the Operator and the Che server + make that happen on Kubernetes. `default-host` exposes the Che + server on the host of the cluster. Read the docs to learn about + the limitations of this approach. type: string serverMemoryLimit: description: Overrides the memory limit used in the Che server deployment. diff --git a/config/crd/bases/org_v1_che_crd.yaml b/config/crd/bases/org_v1_che_crd.yaml index d3dac7bf4..b5b4a03d8 100644 --- a/config/crd/bases/org_v1_che_crd.yaml +++ b/config/crd/bases/org_v1_che_crd.yaml @@ -57,14 +57,16 @@ spec: used by the Che installation. properties: debug: - description: Debug internal identity provider. + description: Deprecated. The value of this flag is ignored. + Debug internal identity provider. type: boolean externalIdentityProvider: - description: 'Instructs the Operator on whether or not to deploy - a dedicated Identity Provider (Keycloak or RH SSO instance). - Instructs the Operator on whether to deploy a dedicated Identity - Provider (Keycloak or RH-SSO instance). By default, a dedicated - Identity Provider server is deployed as part of the Che installation. + description: 'Deprecated. The value of this flag is ignored. + Instructs the Operator on whether or not to deploy a dedicated + Identity Provider (Keycloak or RH SSO instance). Instructs + the Operator on whether to deploy a dedicated Identity Provider + (Keycloak or RH-SSO instance). By default, a dedicated Identity + Provider server is deployed as part of the Che installation. When `externalIdentityProvider` is `true`, no dedicated identity provider will be deployed by the Operator and you will need to provide details about the external identity provider you @@ -86,18 +88,21 @@ spec: Sidecar functionality is now implemented in Traefik plugin. type: string identityProviderAdminUserName: - description: Overrides the name of the Identity Provider administrator + description: Deprecated. The value of this flag is ignored. + Overrides the name of the Identity Provider administrator user. Defaults to `admin`. type: string identityProviderClientId: - description: Name of a Identity provider, Keycloak or RH-SSO, - `client-id` that is used for Che. Override this when an external - Identity Provider is in use. See the `externalIdentityProvider` - field. When omitted or left blank, it is set to the value - of the `flavour` field suffixed with `-public`. + description: Deprecated. The value of this flag is ignored. + Name of a Identity provider, Keycloak or RH-SSO, `client-id` + that is used for Che. Override this when an external Identity + Provider is in use. See the `externalIdentityProvider` field. + When omitted or left blank, it is set to the value of the + `flavour` field suffixed with `-public`. type: string identityProviderContainerResources: - description: Identity provider container custom settings. + description: Deprecated. The value of this flag is ignored. + Identity provider container custom settings. properties: limits: description: Limits describes the maximum amount of compute @@ -125,19 +130,22 @@ spec: type: object type: object identityProviderImage: - description: Overrides the container image used in the Identity - Provider, Keycloak or RH-SSO, deployment. This includes the - image tag. Omit it or leave it empty to use the default container - image provided by the Operator. + description: Deprecated. The value of this flag is ignored. + Overrides the container image used in the Identity Provider, + Keycloak or RH-SSO, deployment. This includes the image tag. + Omit it or leave it empty to use the default container image + provided by the Operator. type: string identityProviderImagePullPolicy: - description: Overrides the image pull policy used in the Identity - Provider, Keycloak or RH-SSO, deployment. Default value is - `Always` for `nightly`, `next` or `latest` images, and `IfNotPresent` + description: Deprecated. The value of this flag is ignored. + Overrides the image pull policy used in the Identity Provider, + Keycloak or RH-SSO, deployment. Default value is `Always` + for `nightly`, `next` or `latest` images, and `IfNotPresent` in other cases. type: string identityProviderIngress: - description: Ingress custom settings. + description: Deprecated. The value of this flag is ignored. + Ingress custom settings. properties: annotations: additionalProperties: @@ -153,25 +161,27 @@ spec: type: string type: object identityProviderPassword: - description: Overrides the password of Keycloak administrator - user. Override this when an external Identity Provider is - in use. See the `externalIdentityProvider` field. When omitted - or left blank, it is set to an auto-generated password. + description: Deprecated. The value of this flag is ignored. + Overrides the password of Keycloak administrator user. Override + this when an external Identity Provider is in use. See the + `externalIdentityProvider` field. When omitted or left blank, + it is set to an auto-generated password. type: string identityProviderPostgresPassword: - description: Password for a Identity Provider, Keycloak or RH-SSO, - to connect to the database. Override this when an external - Identity Provider is in use. See the `externalIdentityProvider` - field. When omitted or left blank, it is set to an auto-generated - password. + description: Deprecated. The value of this flag is ignored. + Password for a Identity Provider, Keycloak or RH-SSO, to connect + to the database. Override this when an external Identity Provider + is in use. See the `externalIdentityProvider` field. When + omitted or left blank, it is set to an auto-generated password. type: string identityProviderPostgresSecret: - description: 'The secret that contains `password` for the Identity - Provider, Keycloak or RH-SSO, to connect to the database. - When the secret is defined, the `identityProviderPostgresPassword` - is ignored. When the value is omitted or left blank, the one - of following scenarios applies: 1. `identityProviderPostgresPassword` - is defined, then it will be used to connect to the database. + description: 'Deprecated. The value of this flag is ignored. + The secret that contains `password` for the Identity Provider, + Keycloak or RH-SSO, to connect to the database. When the secret + is defined, the `identityProviderPostgresPassword` is ignored. + When the value is omitted or left blank, the one of following + scenarios applies: 1. `identityProviderPostgresPassword` is + defined, then it will be used to connect to the database. 2. `identityProviderPostgresPassword` is not defined, then a new secret with the name `che-identity-postgres-secret` will be created with an auto-generated value for `password`. @@ -179,14 +189,16 @@ spec: label.' type: string identityProviderRealm: - description: Name of a Identity provider, Keycloak or RH-SSO, - realm that is used for Che. Override this when an external - Identity Provider is in use. See the `externalIdentityProvider` - field. When omitted or left blank, it is set to the value - of the `flavour` field. + description: Deprecated. The value of this flag is ignored. + Name of a Identity provider, Keycloak or RH-SSO, realm that + is used for Che. Override this when an external Identity Provider + is in use. See the `externalIdentityProvider` field. When + omitted or left blank, it is set to the value of the `flavour` + field. type: string identityProviderRoute: - description: Route custom settings. + description: Deprecated. The value of this flag is ignored. + Route custom settings. properties: annotations: additionalProperties: @@ -208,8 +220,9 @@ spec: type: string type: object identityProviderSecret: - description: 'The secret that contains `user` and `password` - for Identity Provider. When the secret is defined, the `identityProviderAdminUserName` + description: 'Deprecated. The value of this flag is ignored. + The secret that contains `user` and `password` for Identity + Provider. When the secret is defined, the `identityProviderAdminUserName` and `identityProviderPassword` are ignored. When the value is omitted or left blank, the one of following scenarios applies: 1. `identityProviderAdminUserName` and `identityProviderPassword` @@ -228,20 +241,22 @@ spec: set by the Operator. type: string initialOpenShiftOAuthUser: - description: For operating with the OpenShift OAuth authentication, - create a new user account since the kubeadmin can not be used. - If the value is true, then a new OpenShift OAuth user will - be created for the HTPasswd identity provider. If the value - is false and the user has already been created, then it will + description: Deprecated. The value of this flag is ignored. + For operating with the OpenShift OAuth authentication, create + a new user account since the kubeadmin can not be used. If + the value is true, then a new OpenShift OAuth user will be + created for the HTPasswd identity provider. If the value is + false and the user has already been created, then it will be removed. If value is an empty, then do nothing. The user's credentials are stored in the `openshift-oauth-user-credentials` secret in 'openshift-config' namespace by Operator. Note that this solution is Openshift 4 platform-specific. type: boolean nativeUserMode: - description: Enables native user mode. Currently works only - on OpenShift and DevWorkspace engine. Native User mode uses - OpenShift OAuth directly as identity provider, without Keycloak. + description: Deprecated. The value of this flag is ignored. + Enables native user mode. Currently works only on OpenShift + and DevWorkspace engine. Native User mode uses OpenShift OAuth + directly as identity provider, without Keycloak. type: boolean oAuthClientName: description: Name of the OpenShift `OAuthClient` resource used @@ -255,17 +270,19 @@ spec: field. type: string openShiftoAuth: - description: 'Enables the integration of the identity provider - (Keycloak / RHSSO) with OpenShift OAuth. Empty value on OpenShift - by default. This will allow users to directly login with their + description: 'Deprecated. The value of this flag is ignored. + Enables the integration of the identity provider (Keycloak + / RHSSO) with OpenShift OAuth. Empty value on OpenShift by + default. This will allow users to directly login with their OpenShift user through the OpenShift login, and have their workspaces created under personal OpenShift namespaces. WARNING: the `kubeadmin` user is NOT supported, and logging through it will NOT allow accessing the Che Dashboard.' type: boolean updateAdminPassword: - description: Forces the default `admin` Che user to update password - on first login. Defaults to `false`. + description: Deprecated. The value of this flag is ignored. + Forces the default `admin` Che user to update password on + first login. Defaults to `false`. type: boolean type: object database: @@ -452,10 +469,11 @@ spec: This MUST be explicitly specified: there are no defaults.' type: string ingressStrategy: - description: 'Strategy for ingress creation. Options are: `multi-host` - (host is explicitly provided in ingress), `single-host` (host - is provided, path-based rules) and `default-host` (no host - is provided, path-based rules). Defaults to `multi-host` Deprecated + description: 'Deprecated. The value of this flag is ignored. + Strategy for ingress creation. Options are: `multi-host` (host + is explicitly provided in ingress), `single-host` (host is + provided, path-based rules) and `default-host` (no host is + provided, path-based rules). Defaults to `multi-host` Deprecated in favor of `serverExposureStrategy` in the `server` section, which defines this regardless of the cluster type. When both are defined, the `serverExposureStrategy` option takes precedence.' @@ -469,15 +487,16 @@ spec: run as. Default value is `1724`. type: string singleHostExposureType: - description: When the serverExposureStrategy is set to `single-host`, - the way the server, registries and workspaces are exposed - is further configured by this property. The possible values - are `native`, which means that the server and workspaces are - exposed using ingresses on K8s or `gateway` where the server - and workspaces are exposed using a custom gateway based on - link:https://doc.traefik.io/traefik/[Traefik]. All the endpoints - whether backed by the ingress or gateway `route` always point - to the subpaths on the same domain. Defaults to `native`. + description: Deprecated. The value of this flag is ignored. + When the serverExposureStrategy is set to `single-host`, the + way the server, registries and workspaces are exposed is further + configured by this property. The possible values are `native`, + which means that the server and workspaces are exposed using + ingresses on K8s or `gateway` where the server and workspaces + are exposed using a custom gateway based on link:https://doc.traefik.io/traefik/[Traefik]. + All the endpoints whether backed by the ingress or gateway + `route` always point to the subpaths on the same domain. Defaults + to `native`. type: string tlsSecretName: description: Name of a secret that will be used to setup ingress @@ -531,9 +550,9 @@ spec: to `false`. type: string cheFlavor: - description: Specifies a variation of the installation. The - options are `che` for upstream Che installations, or `codeready` - for link:https://developers.redhat.com/products/codeready-workspaces/overview[CodeReady + description: Deprecated. The value of this flag is ignored. + Specifies a variation of the installation. The options are + `che` for upstream Che installations, or `codeready` for link:https://developers.redhat.com/products/codeready-workspaces/overview[CodeReady Workspaces] installation. Override the default value only on necessary occasions. type: string @@ -642,7 +661,8 @@ spec: or `latest` images, and `IfNotPresent` in other cases. type: string dashboardIngress: - description: Dashboard ingress custom settings. + description: Deprecated. The value of this flag is ignored. + Dashboard ingress custom settings. properties: annotations: additionalProperties: @@ -666,7 +686,8 @@ spec: deployment. Defaults to 16Mi. type: string dashboardRoute: - description: Dashboard route custom settings. + description: Deprecated. The value of this flag is ignored. + Dashboard route custom settings. properties: annotations: additionalProperties: @@ -702,7 +723,8 @@ spec: by the Operator. type: string devfileRegistryIngress: - description: The devfile registry ingress custom settings. + description: Deprecated. The value of this flag is ignored. + The devfile registry ingress custom settings. properties: annotations: additionalProperties: @@ -731,7 +753,8 @@ spec: `next` or `latest` images, and `IfNotPresent` in other cases. type: string devfileRegistryRoute: - description: The devfile registry route custom settings. + description: Deprecated. The value of this flag is ignored. + The devfile registry route custom settings. properties: annotations: additionalProperties: @@ -757,9 +780,9 @@ spec: fields. type: string disableInternalClusterSVCNames: - description: Disable internal cluster SVC names usage to communicate - between components to speed up the traffic and avoid proxy - issues. + description: Deprecated. The value of this flag is ignored. + Disable internal cluster SVC names usage to communicate between + components to speed up the traffic and avoid proxy issues. type: boolean externalDevfileRegistries: description: External devfile registries, that serves sample, @@ -824,7 +847,8 @@ spec: by the Operator. type: string pluginRegistryIngress: - description: Plugin registry ingress custom settings. + description: Deprecated. The value of this flag is ignored. + Plugin registry ingress custom settings. properties: annotations: additionalProperties: @@ -853,7 +877,8 @@ spec: `next` or `latest` images, and `IfNotPresent` in other cases. type: string pluginRegistryRoute: - description: Plugin registry route custom settings. + description: Deprecated. The value of this flag is ignored. + Plugin registry route custom settings. properties: annotations: additionalProperties: @@ -929,8 +954,9 @@ spec: deployment In cores. (500m = .5 cores). Default to 100m. type: string serverExposureStrategy: - description: Sets the server and workspaces exposure type. Possible - values are `multi-host`, `single-host`, `default-host`. Defaults + description: Deprecated. The value of this flag is ignored. + Sets the server and workspaces exposure type. Possible values + are `multi-host`, `single-host`, `default-host`. Defaults to `multi-host`, which creates a separate ingress, or OpenShift routes, for every required endpoint. `single-host` makes Che exposed on a single host name with workspaces exposed on subpaths. diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index d9a533893..a692ba721 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -77,8 +77,6 @@ spec: value: quay.io/eclipse/che--centos--postgresql-96-centos7:9.6-b681d78125361519180a6ac05242c296f8906c11eab7e207b5ca9a89b6344392 - name: RELATED_IMAGE_postgres_13_3 value: quay.io/eclipse/che--centos--postgresql-13-centos7:1-71b24684d64da46f960682cc4216222a7e4ed8b1a31dd5a865b3e71afdea20d2 - - name: RELATED_IMAGE_keycloak - value: quay.io/eclipse/che-keycloak:next - name: RELATED_IMAGE_che_workspace_plugin_broker_metadata value: quay.io/eclipse/che-plugin-metadata-broker:v3.4.0 - name: RELATED_IMAGE_che_workspace_plugin_broker_artifacts diff --git a/config/samples/org.eclipse.che_v1_checluster.yaml b/config/samples/org.eclipse.che_v1_checluster.yaml index 2cfa045bf..5ba480da0 100644 --- a/config/samples/org.eclipse.che_v1_checluster.yaml +++ b/config/samples/org.eclipse.che_v1_checluster.yaml @@ -24,8 +24,6 @@ spec: cheWorkspaceClusterRole: '' # When enabled, the certificate from `che-git-self-signed-cert` ConfigMap will be propagated to the Che components and provide particular configuration for Git. gitSelfSignedCert: false - # Deprecated. Instructs the Operator to deploy Che in TLS mode. Disabling TLS sometimes cause malfunction of some Che components. - tlsSupport: true # URL (protocol+host name) of the proxy server. This drives the appropriate changes in the `JAVA_OPTS` and `https(s)_proxy` variables # in the Che server and workspaces containers. # Only use when configuring a proxy is required. Operator respects OpenShift cluster wide proxy configuration diff --git a/controllers/che/checluster_controller.go b/controllers/che/checluster_controller.go index e59f3ba27..3adee61ce 100644 --- a/controllers/che/checluster_controller.go +++ b/controllers/che/checluster_controller.go @@ -25,7 +25,6 @@ import ( identityprovider "github.com/eclipse-che/che-operator/pkg/deploy/identity-provider" imagepuller "github.com/eclipse-che/che-operator/pkg/deploy/image-puller" "github.com/eclipse-che/che-operator/pkg/deploy/migration" - openshiftoauth "github.com/eclipse-che/che-operator/pkg/deploy/openshift-oauth" "github.com/eclipse-che/che-operator/pkg/deploy/pluginregistry" "github.com/eclipse-che/che-operator/pkg/deploy/postgres" "github.com/eclipse-che/che-operator/pkg/deploy/rbac" @@ -93,9 +92,6 @@ func NewReconciler( } reconcileManager.RegisterReconciler(imagepuller.NewImagePuller()) - openShiftOAuthUser := openshiftoauth.NewOpenShiftOAuthUser() - reconcileManager.RegisterReconciler(openShiftOAuthUser) - reconcileManager.RegisterReconciler(openshiftoauth.NewOpenShiftOAuth(openShiftOAuthUser)) reconcileManager.RegisterReconciler(tls.NewCertificatesReconciler()) reconcileManager.RegisterReconciler(tls.NewTlsSecretReconciler()) reconcileManager.RegisterReconciler(devworkspace.NewDevWorkspaceReconciler()) diff --git a/controllers/che/checluster_controller_test.go b/controllers/che/checluster_controller_test.go deleted file mode 100644 index ee8fb1889..000000000 --- a/controllers/che/checluster_controller_test.go +++ /dev/null @@ -1,297 +0,0 @@ -// -// Copyright (c) 2019-2021 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 che - -import ( - "context" - "os" - - "time" - - chev1alpha1 "github.com/che-incubator/kubernetes-image-puller-operator/api/v1alpha1" - "github.com/stretchr/testify/assert" - - "github.com/eclipse-che/che-operator/pkg/deploy" - "github.com/eclipse-che/che-operator/pkg/util" - - console "github.com/openshift/api/console/v1" - - orgv1 "github.com/eclipse-che/che-operator/api/v1" - oauthv1 "github.com/openshift/api/oauth/v1" - routev1 "github.com/openshift/api/route/v1" - userv1 "github.com/openshift/api/user/v1" - operatorsv1 "github.com/operator-framework/api/pkg/operators/v1" - operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" - packagesv1 "github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/apis/operators/v1" - - "github.com/sirupsen/logrus" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/discovery" - fakeDiscovery "k8s.io/client-go/discovery/fake" - fakeclientset "k8s.io/client-go/kubernetes/fake" - "k8s.io/client-go/kubernetes/scheme" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/fake" - - configv1 "github.com/openshift/api/config/v1" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - - "testing" -) - -var ( - namespace = "eclipse-che" -) - -func TestCheController(t *testing.T) { - var err error - - util.IsOpenShift = true - util.IsOpenShift4 = true - - cl, dc, scheme := Init() - - // Create a ReconcileChe object with the scheme and fake client - r := NewReconciler(cl, cl, dc, &scheme, "") - - // get CR - checluster := &orgv1.CheCluster{} - err = cl.Get(context.TODO(), types.NamespacedName{Name: os.Getenv("CHE_FLAVOR"), Namespace: namespace}, checluster) - assert.Nil(t, err) - - // Mock request to simulate Reconcile() being called on an event for a - // watched resource . - req := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: os.Getenv("CHE_FLAVOR"), - Namespace: namespace, - }, - } - - _, err = r.Reconcile(context.TODO(), req) - assert.Nil(t, err) - - assert.True(t, util.IsObjectExists(cl, types.NamespacedName{Name: deploy.DevfileRegistryName, Namespace: checluster.Namespace}, &corev1.ConfigMap{})) - assert.True(t, util.IsObjectExists(cl, types.NamespacedName{Name: deploy.PluginRegistryName, Namespace: checluster.Namespace}, &corev1.ConfigMap{})) - - // reade checluster - err = cl.Get(context.TODO(), types.NamespacedName{Name: os.Getenv("CHE_FLAVOR"), Namespace: namespace}, checluster) - assert.Nil(t, err) - - // update CR and make sure Che configmap has been updated - checluster.Spec.Server.TlsSupport = true - err = cl.Update(context.TODO(), checluster) - assert.Nil(t, err) - - // reconcile several times - reconcileLoops := 4 - for i := 0; i < reconcileLoops; i++ { - _, err = r.Reconcile(context.TODO(), req) - assert.Nil(t, err) - } - - // get configmap - cm := &corev1.ConfigMap{} - err = cl.Get(context.TODO(), types.NamespacedName{Name: "che", Namespace: checluster.Namespace}, cm) - assert.Nil(t, err) - assert.Equal(t, cm.Data["CHE_INFRA_OPENSHIFT_TLS__ENABLED"], "true") - - // Custom ConfigMap should be gone - assert.False(t, util.IsObjectExists(cl, types.NamespacedName{Name: "custom", Namespace: checluster.Namespace}, &corev1.ConfigMap{})) - - // Get the custom role binding that should have been created for the role we passed in - assert.True(t, util.IsObjectExists(cl, types.NamespacedName{Name: "che-workspace-custom", Namespace: checluster.Namespace}, &rbacv1.RoleBinding{})) - - route := &routev1.Route{} - err = cl.Get(context.TODO(), types.NamespacedName{Name: deploy.DefaultCheFlavor(checluster), Namespace: checluster.Namespace}, route) - assert.Nil(t, err) - assert.Equal(t, route.Spec.TLS.Termination, routev1.TLSTerminationType("edge")) - - // reread checluster - err = cl.Get(context.TODO(), types.NamespacedName{Name: os.Getenv("CHE_FLAVOR"), Namespace: namespace}, checluster) - assert.Nil(t, err) - - // update CR and make sure Che configmap has been updated - checluster.Spec.Auth.OpenShiftoAuth = util.NewBoolPointer(true) - err = cl.Update(context.TODO(), checluster) - assert.Nil(t, err) - - _, err = r.Reconcile(context.TODO(), req) - assert.Nil(t, err) - - // get configmap and check if identity provider name and workspace project name are correctly set - cm = &corev1.ConfigMap{} - err = cl.Get(context.TODO(), types.NamespacedName{Name: "che", Namespace: checluster.Namespace}, cm) - assert.Nil(t, err) - assert.Equal(t, cm.Data["CHE_INFRA_OPENSHIFT_OAUTH__IDENTITY__PROVIDER"], "openshift-v4") - - // reread checluster - err = cl.Get(context.TODO(), types.NamespacedName{Name: os.Getenv("CHE_FLAVOR"), Namespace: namespace}, checluster) - assert.Nil(t, err) - assert.True(t, util.IsObjectExists(cl, types.NamespacedName{Name: checluster.Spec.Auth.OAuthClientName}, &oauthv1.OAuthClient{})) - - // check if a new Postgres deployment is not created when spec.Database.ExternalDB is true - checluster.Spec.Database.ExternalDb = true - err = cl.Update(context.TODO(), checluster) - assert.Nil(t, err) - - postgresDeployment := &appsv1.Deployment{} - err = r.client.Get(context.TODO(), types.NamespacedName{Name: deploy.PostgresName, Namespace: checluster.Namespace}, postgresDeployment) - assert.Nil(t, err) - - err = r.client.Delete(context.TODO(), postgresDeployment) - assert.Nil(t, err) - - _, err = r.Reconcile(context.TODO(), req) - assert.Nil(t, err) - - assert.False(t, util.IsObjectExists(cl, types.NamespacedName{Name: deploy.PostgresName, Namespace: checluster.Namespace}, &appsv1.Deployment{})) - - // check of storageClassName ends up in pvc spec - fakeStorageClassName := "fake-storage-class-name" - checluster.Spec.Storage.PostgresPVCStorageClassName = fakeStorageClassName - checluster.Spec.Database.ExternalDb = false - err = r.client.Update(context.TODO(), checluster) - assert.Nil(t, err) - - pvc := &corev1.PersistentVolumeClaim{} - err = r.client.Get(context.TODO(), types.NamespacedName{Name: deploy.DefaultPostgresVolumeClaimName, Namespace: checluster.Namespace}, pvc) - assert.Nil(t, err) - - err = r.client.Delete(context.TODO(), pvc) - assert.Nil(t, err) - - _, err = r.Reconcile(context.TODO(), req) - assert.Nil(t, err) - - pvc = &corev1.PersistentVolumeClaim{} - err = r.client.Get(context.TODO(), types.NamespacedName{Name: deploy.DefaultPostgresVolumeClaimName, Namespace: checluster.Namespace}, pvc) - assert.Nil(t, err) - assert.Equal(t, fakeStorageClassName, *pvc.Spec.StorageClassName) - - // reread checluster - err = cl.Get(context.TODO(), types.NamespacedName{Name: os.Getenv("CHE_FLAVOR"), Namespace: namespace}, checluster) - assert.Nil(t, err) - assert.Equal(t, "https://eclipse.org", checluster.Status.CheURL) - - // check if oAuthClient is deleted after CR is deleted (finalizer logic) - // since fake api does not set deletion timestamp, CR is updated in tests rather than deleted - deletionTimestamp := &metav1.Time{Time: time.Now()} - checluster.DeletionTimestamp = deletionTimestamp - err = r.client.Update(context.TODO(), checluster) - assert.Nil(t, err) - - _, err = r.Reconcile(context.TODO(), req) - assert.Nil(t, err) - - assert.False(t, util.IsObjectExists(cl, types.NamespacedName{Name: checluster.Spec.Auth.OAuthClientName}, &oauthv1.OAuthClient{})) -} - -func Init() (client.Client, discovery.DiscoveryInterface, runtime.Scheme) { - objs, ds, scheme := createAPIObjects() - - oAuth := &configv1.OAuth{} - oAuthClient := &oauthv1.OAuthClient{} - users := &userv1.UserList{} - user := &userv1.User{} - - // Register operator types with the runtime scheme - scheme.AddKnownTypes(oauthv1.SchemeGroupVersion, oAuth) - scheme.AddKnownTypes(oauthv1.SchemeGroupVersion, oAuthClient) - scheme.AddKnownTypes(userv1.SchemeGroupVersion, users, user) - scheme.AddKnownTypes(configv1.SchemeGroupVersion, &configv1.Proxy{}) - - // Create a fake client to mock API calls - return fake.NewFakeClient(objs...), ds, scheme -} - -func createAPIObjects() ([]runtime.Object, discovery.DiscoveryInterface, runtime.Scheme) { - pgPod := &corev1.Pod{ - TypeMeta: metav1.TypeMeta{ - Kind: "Pod", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "fake-pg-pod", - Namespace: "eclipse-che", - Labels: map[string]string{ - "component": deploy.PostgresName, - }, - }, - } - - // A CheCluster custom resource with metadata and spec - cheCR := &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: os.Getenv("CHE_FLAVOR"), - Namespace: namespace, - }, - Spec: orgv1.CheClusterSpec{ - Server: orgv1.CheClusterSpecServer{ - CheHost: "eclipse.org", - CheWorkspaceClusterRole: "cluster-admin", - }, - }, - } - - route := &routev1.Route{ - ObjectMeta: metav1.ObjectMeta{ - Name: deploy.DefaultCheFlavor(cheCR), - Namespace: namespace, - }, - } - - packageManifest := &packagesv1.PackageManifest{ - ObjectMeta: metav1.ObjectMeta{ - Name: "kubernetes-imagepuller-operator", - Namespace: namespace, - }, - } - - oAuth := &configv1.OAuth{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", - }, - } - - // Objects to track in the fake client. - objs := []runtime.Object{ - cheCR, pgPod, route, packageManifest, oAuth, - } - - // Register operator types with the runtime scheme - scheme := scheme.Scheme - scheme.AddKnownTypes(orgv1.GroupVersion, cheCR) - scheme.AddKnownTypes(routev1.SchemeGroupVersion, route) - scheme.AddKnownTypes(console.GroupVersion, &console.ConsoleLink{}) - chev1alpha1.AddToScheme(scheme) - packagesv1.AddToScheme(scheme) - operatorsv1.AddToScheme(scheme) - operatorsv1alpha1.AddToScheme(scheme) - - cli := fakeclientset.NewSimpleClientset() - fakeDiscovery, ok := cli.Discovery().(*fakeDiscovery.FakeDiscovery) - if !ok { - logrus.Error("Error creating fake discovery client") - os.Exit(1) - } - - // Create a fake client to mock API calls - return objs, fakeDiscovery, *scheme -} diff --git a/controllers/che/checluster_validator.go b/controllers/che/checluster_validator.go index 2f7f3dc94..d25c840dc 100644 --- a/controllers/che/checluster_validator.go +++ b/controllers/che/checluster_validator.go @@ -46,7 +46,7 @@ func (v *CheClusterValidator) Reconcile(ctx *deploy.DeployContext) (reconcile.Re } } - workspaceNamespaceDefault := util.GetWorkspaceNamespaceDefault(ctx.CheCluster) + workspaceNamespaceDefault := deploy.GetWorkspaceNamespaceDefault(ctx.CheCluster) if strings.Index(workspaceNamespaceDefault, "") == -1 && strings.Index(workspaceNamespaceDefault, "") == -1 { return reconcile.Result{}, false, fmt.Errorf(NamespaceStrategyErrorMessage, workspaceNamespaceDefault) } diff --git a/controllers/che/proxy.go b/controllers/che/proxy.go index 1edae0b07..ff538913d 100644 --- a/controllers/che/proxy.go +++ b/controllers/che/proxy.go @@ -61,8 +61,6 @@ func GetProxyConfiguration(deployContext *deploy.DeployContext) (*deploy.Proxy, if err != nil { return nil, err } - if deployContext.CheCluster.IsInternalClusterSVCNamesEnabled() { - cheClusterProxyConf.NoProxy = deploy.MergeNonProxy(cheClusterProxyConf.NoProxy, ".svc") - } + cheClusterProxyConf.NoProxy = deploy.MergeNonProxy(cheClusterProxyConf.NoProxy, ".svc") return cheClusterProxyConf, nil } diff --git a/controllers/che/proxy_test.go b/controllers/che/proxy_test.go index 8f138fbbe..188c9b339 100644 --- a/controllers/che/proxy_test.go +++ b/controllers/che/proxy_test.go @@ -26,7 +26,6 @@ import ( fakeDiscovery "k8s.io/client-go/discovery/fake" fakeclientset "k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/kubernetes/scheme" - "k8s.io/utils/pointer" "sigs.k8s.io/controller-runtime/pkg/client/fake" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" @@ -250,10 +249,9 @@ func TestReadProxyConfiguration(t *testing.T) { }, Spec: orgv1.CheClusterSpec{ Server: orgv1.CheClusterSpecServer{ - DisableInternalClusterSVCNames: pointer.BoolPtr(true), - ProxyURL: "http://proxy", - ProxyPort: "3128", - NonProxyHosts: "host1", + ProxyURL: "http://proxy", + ProxyPort: "3128", + NonProxyHosts: "host1", }, }, }, @@ -269,7 +267,7 @@ func TestReadProxyConfiguration(t *testing.T) { HttpsPassword: "", HttpsHost: "proxy", HttpsPort: "3128", - NoProxy: "host1", + NoProxy: "host1,.svc", TrustedCAMapName: "", }, }, diff --git a/controllers/checlusterbackup/backup_data_collector.go b/controllers/checlusterbackup/backup_data_collector.go index 87fc24cfb..2ba79853d 100644 --- a/controllers/checlusterbackup/backup_data_collector.go +++ b/controllers/checlusterbackup/backup_data_collector.go @@ -163,9 +163,6 @@ func backupDatabases(bctx *BackupContext, destDir string) (bool, error) { databasesToBackup := []string{ bctx.cheCR.Spec.Database.ChePostgresDb, } - if !bctx.cheCR.Spec.DevWorkspace.Enable { - databasesToBackup = append(databasesToBackup, "keycloak") - } k8sClient := util.GetK8Client() postgresPodName, err := k8sClient.GetDeploymentPod(deploy.PostgresName, bctx.namespace) @@ -256,12 +253,6 @@ func backupSecrets(bctx *BackupContext, destDir string) (bool, error) { if bctx.cheCR.Spec.Database.ChePostgresSecret != "" { secretsNames = append(secretsNames, bctx.cheCR.Spec.Database.ChePostgresSecret) } - if bctx.cheCR.Spec.Auth.IdentityProviderPostgresSecret != "" { - secretsNames = append(secretsNames, bctx.cheCR.Spec.Auth.IdentityProviderPostgresSecret) - } - if bctx.cheCR.Spec.Auth.IdentityProviderSecret != "" { - secretsNames = append(secretsNames, bctx.cheCR.Spec.Auth.IdentityProviderSecret) - } // Retrieve and save each secret for _, secretName := range secretsNames { diff --git a/controllers/checlusterrestore/backup_data_restorer.go b/controllers/checlusterrestore/backup_data_restorer.go index eb0bac74d..1701eea0c 100644 --- a/controllers/checlusterrestore/backup_data_restorer.go +++ b/controllers/checlusterrestore/backup_data_restorer.go @@ -111,14 +111,6 @@ func RestoreChe(rctx *RestoreContext, dataDir string) (bool, error) { return done, err } - if !rctx.cheCR.Spec.DevWorkspace.Enable { - // After Keycloak's database restoring, it is required to restart Keycloak to invalidate its cache. - done, err = deleteKeycloakPod(rctx) - if err != nil || !done { - return done, err - } - } - rctx.state.cheDatabaseRestored = true if err := rctx.UpdateRestoreStatus(); err != nil { return false, err @@ -238,24 +230,6 @@ func waitPreviousInstallationDeleted(rctx *RestoreContext) (bool, error) { return true, nil } -func deleteKeycloakPod(rctx *RestoreContext) (bool, error) { - k8sClient := util.GetK8Client() - keycloakPodName, err := k8sClient.GetDeploymentPod(deploy.IdentityProviderName, rctx.namespace) - if err != nil { - // Keycloak pod is already deleted, just skip it - return true, nil - } - keycloakPodNsN := types.NamespacedName{Name: keycloakPodName, Namespace: rctx.namespace} - keycloakPod := &corev1.Pod{} - if err := rctx.r.nonCachingClient.Get(context.TODO(), keycloakPodNsN, keycloakPod); err != nil { - return false, err - } - if err := rctx.r.nonCachingClient.Delete(context.TODO(), keycloakPod); err != nil { - return false, err - } - return true, nil -} - func restoreCheResources(rctx *RestoreContext, dataDir string) (bool, error) { partsToRestore := []func(*RestoreContext, string) (bool, error){ restoreConfigMaps, @@ -406,10 +380,6 @@ func readAndAdaptCheCRFromBackup(rctx *RestoreContext, dataDir string) (*chev1.C cheCR.Spec.Server.CheHost = "" } } - if !cheCR.Spec.Auth.ExternalIdentityProvider { - // Let operator set the URL automatically - cheCR.Spec.Auth.IdentityProviderURL = "" - } return cheCR, true, nil } @@ -466,7 +436,6 @@ func dropDatabases(rctx *RestoreContext) { databasesToDrop := []string{ rctx.cheCR.Spec.Database.ChePostgresDb, - "keycloak", } k8sClient := util.GetK8Client() @@ -525,24 +494,6 @@ func restoreDatabase(rctx *RestoreContext, dataDir string) (bool, error) { } return false, err } - - if rctx.cheCR.Spec.Server.ServerExposureStrategy == "multi-host" { - // Some databases contain values bind to cluster and/or namespace - // These values should be adjusted according to new environmant. - pathcDatabaseScript, err := getPatchDatabaseScript(rctx, dbName, dataDir) - if err != nil { - return false, err - } - if pathcDatabaseScript != "" { - execReason := fmt.Sprintf("patching %s database", dbName) - if output, err := k8sClient.DoExecIntoPod(rctx.namespace, postgresPodName, pathcDatabaseScript, execReason); err != nil { - if output != "" { - logrus.Error(output) - } - return false, err - } - } - } } } @@ -565,8 +516,6 @@ func getDatabaseOwner(rctx *RestoreContext, dbName string) (string, error) { return "", err } return string(secret.Data["user"]), nil - case "keycloak": - return "keycloak", nil default: return "postgres", nil } @@ -616,14 +565,6 @@ func getPatchDatabaseScript(rctx *RestoreContext, dbName string, dataDir string) script += "\n" + getReplaceInColumnScript(dbName, "devfile_project", "location", oldAppsSubStr, newAppsSubStr) } return script, nil - case "keycloak": - if !shouldPatchUrls { - // No need to do anything, restoring into the same cluster and the same namespace - break - } - script := getReplaceInColumnScript(dbName, "redirect_uris", "value", oldAppsSubStr, newAppsSubStr) + "\n" + - getReplaceInColumnScript(dbName, "web_origins", "value", oldAppsSubStr, newAppsSubStr) - return script, nil } return "", nil } diff --git a/helmcharts/next/crds/org_v1_che_crd.yaml b/helmcharts/next/crds/org_v1_che_crd.yaml index d3dac7bf4..b5b4a03d8 100644 --- a/helmcharts/next/crds/org_v1_che_crd.yaml +++ b/helmcharts/next/crds/org_v1_che_crd.yaml @@ -57,14 +57,16 @@ spec: used by the Che installation. properties: debug: - description: Debug internal identity provider. + description: Deprecated. The value of this flag is ignored. + Debug internal identity provider. type: boolean externalIdentityProvider: - description: 'Instructs the Operator on whether or not to deploy - a dedicated Identity Provider (Keycloak or RH SSO instance). - Instructs the Operator on whether to deploy a dedicated Identity - Provider (Keycloak or RH-SSO instance). By default, a dedicated - Identity Provider server is deployed as part of the Che installation. + description: 'Deprecated. The value of this flag is ignored. + Instructs the Operator on whether or not to deploy a dedicated + Identity Provider (Keycloak or RH SSO instance). Instructs + the Operator on whether to deploy a dedicated Identity Provider + (Keycloak or RH-SSO instance). By default, a dedicated Identity + Provider server is deployed as part of the Che installation. When `externalIdentityProvider` is `true`, no dedicated identity provider will be deployed by the Operator and you will need to provide details about the external identity provider you @@ -86,18 +88,21 @@ spec: Sidecar functionality is now implemented in Traefik plugin. type: string identityProviderAdminUserName: - description: Overrides the name of the Identity Provider administrator + description: Deprecated. The value of this flag is ignored. + Overrides the name of the Identity Provider administrator user. Defaults to `admin`. type: string identityProviderClientId: - description: Name of a Identity provider, Keycloak or RH-SSO, - `client-id` that is used for Che. Override this when an external - Identity Provider is in use. See the `externalIdentityProvider` - field. When omitted or left blank, it is set to the value - of the `flavour` field suffixed with `-public`. + description: Deprecated. The value of this flag is ignored. + Name of a Identity provider, Keycloak or RH-SSO, `client-id` + that is used for Che. Override this when an external Identity + Provider is in use. See the `externalIdentityProvider` field. + When omitted or left blank, it is set to the value of the + `flavour` field suffixed with `-public`. type: string identityProviderContainerResources: - description: Identity provider container custom settings. + description: Deprecated. The value of this flag is ignored. + Identity provider container custom settings. properties: limits: description: Limits describes the maximum amount of compute @@ -125,19 +130,22 @@ spec: type: object type: object identityProviderImage: - description: Overrides the container image used in the Identity - Provider, Keycloak or RH-SSO, deployment. This includes the - image tag. Omit it or leave it empty to use the default container - image provided by the Operator. + description: Deprecated. The value of this flag is ignored. + Overrides the container image used in the Identity Provider, + Keycloak or RH-SSO, deployment. This includes the image tag. + Omit it or leave it empty to use the default container image + provided by the Operator. type: string identityProviderImagePullPolicy: - description: Overrides the image pull policy used in the Identity - Provider, Keycloak or RH-SSO, deployment. Default value is - `Always` for `nightly`, `next` or `latest` images, and `IfNotPresent` + description: Deprecated. The value of this flag is ignored. + Overrides the image pull policy used in the Identity Provider, + Keycloak or RH-SSO, deployment. Default value is `Always` + for `nightly`, `next` or `latest` images, and `IfNotPresent` in other cases. type: string identityProviderIngress: - description: Ingress custom settings. + description: Deprecated. The value of this flag is ignored. + Ingress custom settings. properties: annotations: additionalProperties: @@ -153,25 +161,27 @@ spec: type: string type: object identityProviderPassword: - description: Overrides the password of Keycloak administrator - user. Override this when an external Identity Provider is - in use. See the `externalIdentityProvider` field. When omitted - or left blank, it is set to an auto-generated password. + description: Deprecated. The value of this flag is ignored. + Overrides the password of Keycloak administrator user. Override + this when an external Identity Provider is in use. See the + `externalIdentityProvider` field. When omitted or left blank, + it is set to an auto-generated password. type: string identityProviderPostgresPassword: - description: Password for a Identity Provider, Keycloak or RH-SSO, - to connect to the database. Override this when an external - Identity Provider is in use. See the `externalIdentityProvider` - field. When omitted or left blank, it is set to an auto-generated - password. + description: Deprecated. The value of this flag is ignored. + Password for a Identity Provider, Keycloak or RH-SSO, to connect + to the database. Override this when an external Identity Provider + is in use. See the `externalIdentityProvider` field. When + omitted or left blank, it is set to an auto-generated password. type: string identityProviderPostgresSecret: - description: 'The secret that contains `password` for the Identity - Provider, Keycloak or RH-SSO, to connect to the database. - When the secret is defined, the `identityProviderPostgresPassword` - is ignored. When the value is omitted or left blank, the one - of following scenarios applies: 1. `identityProviderPostgresPassword` - is defined, then it will be used to connect to the database. + description: 'Deprecated. The value of this flag is ignored. + The secret that contains `password` for the Identity Provider, + Keycloak or RH-SSO, to connect to the database. When the secret + is defined, the `identityProviderPostgresPassword` is ignored. + When the value is omitted or left blank, the one of following + scenarios applies: 1. `identityProviderPostgresPassword` is + defined, then it will be used to connect to the database. 2. `identityProviderPostgresPassword` is not defined, then a new secret with the name `che-identity-postgres-secret` will be created with an auto-generated value for `password`. @@ -179,14 +189,16 @@ spec: label.' type: string identityProviderRealm: - description: Name of a Identity provider, Keycloak or RH-SSO, - realm that is used for Che. Override this when an external - Identity Provider is in use. See the `externalIdentityProvider` - field. When omitted or left blank, it is set to the value - of the `flavour` field. + description: Deprecated. The value of this flag is ignored. + Name of a Identity provider, Keycloak or RH-SSO, realm that + is used for Che. Override this when an external Identity Provider + is in use. See the `externalIdentityProvider` field. When + omitted or left blank, it is set to the value of the `flavour` + field. type: string identityProviderRoute: - description: Route custom settings. + description: Deprecated. The value of this flag is ignored. + Route custom settings. properties: annotations: additionalProperties: @@ -208,8 +220,9 @@ spec: type: string type: object identityProviderSecret: - description: 'The secret that contains `user` and `password` - for Identity Provider. When the secret is defined, the `identityProviderAdminUserName` + description: 'Deprecated. The value of this flag is ignored. + The secret that contains `user` and `password` for Identity + Provider. When the secret is defined, the `identityProviderAdminUserName` and `identityProviderPassword` are ignored. When the value is omitted or left blank, the one of following scenarios applies: 1. `identityProviderAdminUserName` and `identityProviderPassword` @@ -228,20 +241,22 @@ spec: set by the Operator. type: string initialOpenShiftOAuthUser: - description: For operating with the OpenShift OAuth authentication, - create a new user account since the kubeadmin can not be used. - If the value is true, then a new OpenShift OAuth user will - be created for the HTPasswd identity provider. If the value - is false and the user has already been created, then it will + description: Deprecated. The value of this flag is ignored. + For operating with the OpenShift OAuth authentication, create + a new user account since the kubeadmin can not be used. If + the value is true, then a new OpenShift OAuth user will be + created for the HTPasswd identity provider. If the value is + false and the user has already been created, then it will be removed. If value is an empty, then do nothing. The user's credentials are stored in the `openshift-oauth-user-credentials` secret in 'openshift-config' namespace by Operator. Note that this solution is Openshift 4 platform-specific. type: boolean nativeUserMode: - description: Enables native user mode. Currently works only - on OpenShift and DevWorkspace engine. Native User mode uses - OpenShift OAuth directly as identity provider, without Keycloak. + description: Deprecated. The value of this flag is ignored. + Enables native user mode. Currently works only on OpenShift + and DevWorkspace engine. Native User mode uses OpenShift OAuth + directly as identity provider, without Keycloak. type: boolean oAuthClientName: description: Name of the OpenShift `OAuthClient` resource used @@ -255,17 +270,19 @@ spec: field. type: string openShiftoAuth: - description: 'Enables the integration of the identity provider - (Keycloak / RHSSO) with OpenShift OAuth. Empty value on OpenShift - by default. This will allow users to directly login with their + description: 'Deprecated. The value of this flag is ignored. + Enables the integration of the identity provider (Keycloak + / RHSSO) with OpenShift OAuth. Empty value on OpenShift by + default. This will allow users to directly login with their OpenShift user through the OpenShift login, and have their workspaces created under personal OpenShift namespaces. WARNING: the `kubeadmin` user is NOT supported, and logging through it will NOT allow accessing the Che Dashboard.' type: boolean updateAdminPassword: - description: Forces the default `admin` Che user to update password - on first login. Defaults to `false`. + description: Deprecated. The value of this flag is ignored. + Forces the default `admin` Che user to update password on + first login. Defaults to `false`. type: boolean type: object database: @@ -452,10 +469,11 @@ spec: This MUST be explicitly specified: there are no defaults.' type: string ingressStrategy: - description: 'Strategy for ingress creation. Options are: `multi-host` - (host is explicitly provided in ingress), `single-host` (host - is provided, path-based rules) and `default-host` (no host - is provided, path-based rules). Defaults to `multi-host` Deprecated + description: 'Deprecated. The value of this flag is ignored. + Strategy for ingress creation. Options are: `multi-host` (host + is explicitly provided in ingress), `single-host` (host is + provided, path-based rules) and `default-host` (no host is + provided, path-based rules). Defaults to `multi-host` Deprecated in favor of `serverExposureStrategy` in the `server` section, which defines this regardless of the cluster type. When both are defined, the `serverExposureStrategy` option takes precedence.' @@ -469,15 +487,16 @@ spec: run as. Default value is `1724`. type: string singleHostExposureType: - description: When the serverExposureStrategy is set to `single-host`, - the way the server, registries and workspaces are exposed - is further configured by this property. The possible values - are `native`, which means that the server and workspaces are - exposed using ingresses on K8s or `gateway` where the server - and workspaces are exposed using a custom gateway based on - link:https://doc.traefik.io/traefik/[Traefik]. All the endpoints - whether backed by the ingress or gateway `route` always point - to the subpaths on the same domain. Defaults to `native`. + description: Deprecated. The value of this flag is ignored. + When the serverExposureStrategy is set to `single-host`, the + way the server, registries and workspaces are exposed is further + configured by this property. The possible values are `native`, + which means that the server and workspaces are exposed using + ingresses on K8s or `gateway` where the server and workspaces + are exposed using a custom gateway based on link:https://doc.traefik.io/traefik/[Traefik]. + All the endpoints whether backed by the ingress or gateway + `route` always point to the subpaths on the same domain. Defaults + to `native`. type: string tlsSecretName: description: Name of a secret that will be used to setup ingress @@ -531,9 +550,9 @@ spec: to `false`. type: string cheFlavor: - description: Specifies a variation of the installation. The - options are `che` for upstream Che installations, or `codeready` - for link:https://developers.redhat.com/products/codeready-workspaces/overview[CodeReady + description: Deprecated. The value of this flag is ignored. + Specifies a variation of the installation. The options are + `che` for upstream Che installations, or `codeready` for link:https://developers.redhat.com/products/codeready-workspaces/overview[CodeReady Workspaces] installation. Override the default value only on necessary occasions. type: string @@ -642,7 +661,8 @@ spec: or `latest` images, and `IfNotPresent` in other cases. type: string dashboardIngress: - description: Dashboard ingress custom settings. + description: Deprecated. The value of this flag is ignored. + Dashboard ingress custom settings. properties: annotations: additionalProperties: @@ -666,7 +686,8 @@ spec: deployment. Defaults to 16Mi. type: string dashboardRoute: - description: Dashboard route custom settings. + description: Deprecated. The value of this flag is ignored. + Dashboard route custom settings. properties: annotations: additionalProperties: @@ -702,7 +723,8 @@ spec: by the Operator. type: string devfileRegistryIngress: - description: The devfile registry ingress custom settings. + description: Deprecated. The value of this flag is ignored. + The devfile registry ingress custom settings. properties: annotations: additionalProperties: @@ -731,7 +753,8 @@ spec: `next` or `latest` images, and `IfNotPresent` in other cases. type: string devfileRegistryRoute: - description: The devfile registry route custom settings. + description: Deprecated. The value of this flag is ignored. + The devfile registry route custom settings. properties: annotations: additionalProperties: @@ -757,9 +780,9 @@ spec: fields. type: string disableInternalClusterSVCNames: - description: Disable internal cluster SVC names usage to communicate - between components to speed up the traffic and avoid proxy - issues. + description: Deprecated. The value of this flag is ignored. + Disable internal cluster SVC names usage to communicate between + components to speed up the traffic and avoid proxy issues. type: boolean externalDevfileRegistries: description: External devfile registries, that serves sample, @@ -824,7 +847,8 @@ spec: by the Operator. type: string pluginRegistryIngress: - description: Plugin registry ingress custom settings. + description: Deprecated. The value of this flag is ignored. + Plugin registry ingress custom settings. properties: annotations: additionalProperties: @@ -853,7 +877,8 @@ spec: `next` or `latest` images, and `IfNotPresent` in other cases. type: string pluginRegistryRoute: - description: Plugin registry route custom settings. + description: Deprecated. The value of this flag is ignored. + Plugin registry route custom settings. properties: annotations: additionalProperties: @@ -929,8 +954,9 @@ spec: deployment In cores. (500m = .5 cores). Default to 100m. type: string serverExposureStrategy: - description: Sets the server and workspaces exposure type. Possible - values are `multi-host`, `single-host`, `default-host`. Defaults + description: Deprecated. The value of this flag is ignored. + Sets the server and workspaces exposure type. Possible values + are `multi-host`, `single-host`, `default-host`. Defaults to `multi-host`, which creates a separate ingress, or OpenShift routes, for every required endpoint. `single-host` makes Che exposed on a single host name with workspaces exposed on subpaths. diff --git a/helmcharts/next/templates/manager.yaml b/helmcharts/next/templates/manager.yaml index d9a533893..a692ba721 100644 --- a/helmcharts/next/templates/manager.yaml +++ b/helmcharts/next/templates/manager.yaml @@ -77,8 +77,6 @@ spec: value: quay.io/eclipse/che--centos--postgresql-96-centos7:9.6-b681d78125361519180a6ac05242c296f8906c11eab7e207b5ca9a89b6344392 - name: RELATED_IMAGE_postgres_13_3 value: quay.io/eclipse/che--centos--postgresql-13-centos7:1-71b24684d64da46f960682cc4216222a7e4ed8b1a31dd5a865b3e71afdea20d2 - - name: RELATED_IMAGE_keycloak - value: quay.io/eclipse/che-keycloak:next - name: RELATED_IMAGE_che_workspace_plugin_broker_metadata value: quay.io/eclipse/che-plugin-metadata-broker:v3.4.0 - name: RELATED_IMAGE_che_workspace_plugin_broker_artifacts diff --git a/helmcharts/next/templates/org.eclipse.che_v1_checluster.yaml b/helmcharts/next/templates/org.eclipse.che_v1_checluster.yaml index 404ff832a..e974ea32a 100644 --- a/helmcharts/next/templates/org.eclipse.che_v1_checluster.yaml +++ b/helmcharts/next/templates/org.eclipse.che_v1_checluster.yaml @@ -20,7 +20,6 @@ spec: cheClusterRoles: '' cheWorkspaceClusterRole: '' gitSelfSignedCert: false - tlsSupport: true proxyURL: '' proxyPort: '' proxySecret: '' diff --git a/pkg/deploy/consolelink/consolelink.go b/pkg/deploy/consolelink/consolelink.go index 7d1ac3b53..397a97e6f 100644 --- a/pkg/deploy/consolelink/consolelink.go +++ b/pkg/deploy/consolelink/consolelink.go @@ -44,12 +44,6 @@ func (c *ConsoleLinkReconciler) Reconcile(ctx *deploy.DeployContext) (reconcile. return reconcile.Result{}, true, nil } - if !ctx.CheCluster.Spec.Server.TlsSupport { - // console link is supported only with https - logrus.Debug("Console link won't be created. HTTP protocol is not supported.") - return reconcile.Result{}, true, nil - } - done, err := c.createConsoleLink(ctx) if !done { return reconcile.Result{Requeue: true}, false, err diff --git a/pkg/deploy/consolelink/consolelink_test.go b/pkg/deploy/consolelink/consolelink_test.go index 70d606e40..760921255 100644 --- a/pkg/deploy/consolelink/consolelink_test.go +++ b/pkg/deploy/consolelink/consolelink_test.go @@ -31,11 +31,7 @@ func TestReconcileConsoleLink(t *testing.T) { Namespace: "eclipse-che", Name: "eclipse-che", }, - Spec: orgv1.CheClusterSpec{ - Server: orgv1.CheClusterSpecServer{ - TlsSupport: true, - }, - }, + Spec: orgv1.CheClusterSpec{}, } util.IsOpenShift4 = true diff --git a/pkg/deploy/dashboard/dashboard.go b/pkg/deploy/dashboard/dashboard.go index 1dbed75bf..557dd0fe7 100644 --- a/pkg/deploy/dashboard/dashboard.go +++ b/pkg/deploy/dashboard/dashboard.go @@ -57,8 +57,6 @@ func (d *DashboardReconciler) Reconcile(ctx *deploy.DeployContext) (reconcile.Re // Expose dashboard service with route or ingress _, done, err = expose.ExposeWithHostPath(ctx, d.getComponentName(ctx), ctx.CheCluster.Spec.Server.CheHost, exposePath, - ctx.CheCluster.Spec.Server.DashboardRoute, - ctx.CheCluster.Spec.Server.DashboardIngress, d.createGatewayConfig(ctx), ) if !done { @@ -130,7 +128,7 @@ func (d *DashboardReconciler) createGatewayConfig(ctx *deploy.DeployContext) *ga 10, "http://"+d.getComponentName(ctx)+":8080", []string{}) - if util.IsOpenShift && ctx.CheCluster.IsNativeUserModeEnabled() { + if util.IsOpenShift { cfg.AddAuthHeaderRewrite(d.getComponentName(ctx)) } return cfg diff --git a/pkg/deploy/dashboard/dashboard_deployment_test.go b/pkg/deploy/dashboard/dashboard_deployment_test.go index 8269e59d2..4b483d467 100644 --- a/pkg/deploy/dashboard/dashboard_deployment_test.go +++ b/pkg/deploy/dashboard/dashboard_deployment_test.go @@ -122,19 +122,18 @@ func TestDashboardDeploymentEnvVars(t *testing.T) { envVars []corev1.EnvVar cheCluster *orgv1.CheCluster } - trueBool := true testCases := []resourcesTestCase{ { - name: "Test provisioning Che and Keycloak URLs", + name: "Test provisioning Che URLs", initObjects: []runtime.Object{}, envVars: []corev1.EnvVar{ { Name: "CHE_HOST", - Value: "http://che.com", + Value: "https://che.com", }, { Name: "CHE_URL", - Value: "http://che.com", + Value: "https://che.com", }, { Name: "CHECLUSTER_CR_NAMESPACE", @@ -164,44 +163,6 @@ func TestDashboardDeploymentEnvVars(t *testing.T) { }, }, }, - { - name: "Test provisioning Che and Keycloak URLs when internal SVC is disabled", - initObjects: []runtime.Object{}, - envVars: []corev1.EnvVar{ - { - Name: "CHE_HOST", - Value: "http://che.com", - }, - { - Name: "CHE_URL", - Value: "http://che.com", - }, - { - Name: "CHECLUSTER_CR_NAMESPACE", - Value: "eclipse-che", - }, - { - Name: "CHECLUSTER_CR_NAME", - Value: "eclipse-che", - }, - { - Name: "OPENSHIFT_CONSOLE_URL", - }, - // the following are not provisioned: CHE_INTERNAL_URL - }, - cheCluster: &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", - Name: "eclipse-che", - }, - Spec: orgv1.CheClusterSpec{ - Server: orgv1.CheClusterSpecServer{ - DisableInternalClusterSVCNames: &trueBool, - CheHost: "che.com", - }, - }, - }, - }, { name: "Test provisioning OpenShift Console URL", initObjects: []runtime.Object{ @@ -218,11 +179,11 @@ func TestDashboardDeploymentEnvVars(t *testing.T) { envVars: []corev1.EnvVar{ { Name: "CHE_HOST", - Value: "http://che.com", + Value: "https://che.com", }, { Name: "CHE_URL", - Value: "http://che.com", + Value: "https://che.com", }, { Name: "CHECLUSTER_CR_NAMESPACE", diff --git a/pkg/deploy/dashboard/dashboard_test.go b/pkg/deploy/dashboard/dashboard_test.go index 4f0c78d58..92386de1f 100644 --- a/pkg/deploy/dashboard/dashboard_test.go +++ b/pkg/deploy/dashboard/dashboard_test.go @@ -16,11 +16,9 @@ import ( "github.com/eclipse-che/che-operator/pkg/deploy" "github.com/eclipse-che/che-operator/pkg/util" "github.com/stretchr/testify/assert" - networkingv1 "k8s.io/api/networking/v1" rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/runtime" - routev1 "github.com/openshift/api/route/v1" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" @@ -40,7 +38,6 @@ func TestDashboardOpenShift(t *testing.T) { assert.Nil(t, err) assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: dashboard.getComponentName(ctx), Namespace: "eclipse-che"}, &corev1.Service{})) - assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: dashboard.getComponentName(ctx), Namespace: "eclipse-che"}, &routev1.Route{})) assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: dashboard.getComponentName(ctx), Namespace: "eclipse-che"}, &appsv1.Deployment{})) assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: DashboardSA, Namespace: "eclipse-che"}, &corev1.ServiceAccount{})) assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: dashboard.getComponentName(ctx), Namespace: "eclipse-che"}, &appsv1.Deployment{})) @@ -60,7 +57,6 @@ func TestDashboardKubernetes(t *testing.T) { assert.Nil(t, err) assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: dashboard.getComponentName(ctx), Namespace: "eclipse-che"}, &corev1.Service{})) - assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: dashboard.getComponentName(ctx), Namespace: "eclipse-che"}, &networkingv1.Ingress{})) assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: dashboard.getComponentName(ctx), Namespace: "eclipse-che"}, &appsv1.Deployment{})) assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: DashboardSA, Namespace: "eclipse-che"}, &corev1.ServiceAccount{})) assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: dashboard.getComponentName(ctx), Namespace: "eclipse-che"}, &appsv1.Deployment{})) diff --git a/pkg/deploy/dashboard/deployment_dashboard.go b/pkg/deploy/dashboard/deployment_dashboard.go index 77012f0a0..cb5b7381d 100644 --- a/pkg/deploy/dashboard/deployment_dashboard.go +++ b/pkg/deploy/dashboard/deployment_dashboard.go @@ -64,13 +64,11 @@ func (d *DashboardReconciler) getDashboardDeploymentSpec(ctx *deploy.DeployConte Value: ctx.CheCluster.Name}, ) - if ctx.CheCluster.IsInternalClusterSVCNamesEnabled() { - envVars = append(envVars, - corev1.EnvVar{ - Name: "CHE_INTERNAL_URL", - Value: fmt.Sprintf("http://%s.%s.svc:8080/api", deploy.CheServiceName, ctx.CheCluster.Namespace)}, - ) - } + envVars = append(envVars, + corev1.EnvVar{ + Name: "CHE_INTERNAL_URL", + Value: fmt.Sprintf("http://%s.%s.svc:8080/api", deploy.CheServiceName, ctx.CheCluster.Namespace)}, + ) if util.IsOpenShift { envVars = append(envVars, diff --git a/pkg/deploy/defaults.go b/pkg/deploy/defaults.go index bbdbdc88c..24bd61d5f 100644 --- a/pkg/deploy/defaults.go +++ b/pkg/deploy/defaults.go @@ -37,7 +37,6 @@ var ( defaultPvcJobsImage string defaultPostgresImage string defaultPostgres13Image string - defaultKeycloakImage string defaultSingleHostGatewayImage string defaultSingleHostGatewayConfigSidecarImage string defaultInternalRestBackupServerImage string @@ -63,7 +62,6 @@ const ( DefaultPvcClaimSize = "10Gi" DefaultIngressClass = "nginx" - DefaultKeycloakAdminUserName = "admin" DefaultCheLogLevel = "INFO" DefaultCheDebug = "false" DefaultCheMetricsPort = int32(8087) @@ -81,21 +79,9 @@ const ( KubernetesImagePullerOperatorCSV = "kubernetes-imagepuller-operator.v0.0.9" - DefaultServerExposureStrategy = "multi-host" - NativeSingleHostExposureType = "native" + ServerExposureStrategy = "single-host" GatewaySingleHostExposureType = "gateway" - // This is only to correctly manage defaults during the transition - // from Upstream 7.0.0 GA to the next version - // That fixed bug https://github.com/eclipse/che/issues/13714 - OldDefaultKeycloakUpstreamImageToDetect = "eclipse/che-keycloak:7.0.0" - OldDefaultPvcJobsUpstreamImageToDetect = "registry.access.redhat.com/ubi8-minimal:8.0-127" - OldDefaultPostgresUpstreamImageToDetect = "centos/postgresql-96-centos7:9.6" - - OldDefaultCodeReadyServerImageRepo = "registry.redhat.io/codeready-workspaces/server-rhel8" - OldDefaultCodeReadyServerImageTag = "1.2" - OldCrwPluginRegistryUrl = "https://che-plugin-registry.openshift.io" - // kubernetes default labels KubernetesComponentLabelKey = "app.kubernetes.io/component" KubernetesPartOfLabelKey = "app.kubernetes.io/part-of" @@ -118,10 +104,9 @@ const ( CheEclipseOrgManagedAnnotationsDigest = "che.eclipse.org/managed-annotations-digest" // components - IdentityProviderName = "keycloak" - DevfileRegistryName = "devfile-registry" - PluginRegistryName = "plugin-registry" - PostgresName = "postgres" + DevfileRegistryName = "devfile-registry" + PluginRegistryName = "plugin-registry" + PostgresName = "postgres" // CheServiceAccountName - service account name for che-server. CheServiceAccountName = "che" @@ -198,7 +183,6 @@ func InitDefaultsFromFile(defaultsPath string) { defaultPvcJobsImage = util.GetDeploymentEnv(operatorDeployment, util.GetArchitectureDependentEnv("RELATED_IMAGE_pvc_jobs")) defaultPostgresImage = util.GetDeploymentEnv(operatorDeployment, util.GetArchitectureDependentEnv("RELATED_IMAGE_postgres")) defaultPostgres13Image = util.GetDeploymentEnv(operatorDeployment, util.GetArchitectureDependentEnv("RELATED_IMAGE_postgres_13_3")) - defaultKeycloakImage = util.GetDeploymentEnv(operatorDeployment, util.GetArchitectureDependentEnv("RELATED_IMAGE_keycloak")) defaultSingleHostGatewayImage = util.GetDeploymentEnv(operatorDeployment, util.GetArchitectureDependentEnv("RELATED_IMAGE_single_host_gateway")) defaultSingleHostGatewayConfigSidecarImage = util.GetDeploymentEnv(operatorDeployment, util.GetArchitectureDependentEnv("RELATED_IMAGE_single_host_gateway_config_sidecar")) defaultGatewayAuthenticationSidecarImage = util.GetDeploymentEnv(operatorDeployment, util.GetArchitectureDependentEnv("RELATED_IMAGE_gateway_authentication_sidecar")) @@ -246,15 +230,6 @@ func getDefaultFromEnv(envName string) string { return value } -func MigratingToCRW2_0(cr *orgv1.CheCluster) bool { - if cr.Spec.Server.CheFlavor == "codeready" && - strings.HasPrefix(cr.Status.CheVersion, "1.2") && - strings.HasPrefix(defaultCheVersion, "2.0") { - return true - } - return false -} - func IsComponentReadinessInitContainersConfigured(cr *orgv1.CheCluster) bool { return os.Getenv("ADD_COMPONENT_READINESS_INIT_CONTAINERS") == "true" } @@ -264,7 +239,7 @@ func DefaultServerTrustStoreConfigMapName() string { } func DefaultCheFlavor(cr *orgv1.CheCluster) string { - return util.GetValue(cr.Spec.Server.CheFlavor, getDefaultFromEnv("CHE_FLAVOR")) + return getDefaultFromEnv("CHE_FLAVOR") } func DefaultConsoleLinkName() string { @@ -331,10 +306,6 @@ func DefaultDevworkspaceControllerImage(cr *orgv1.CheCluster) string { return patchDefaultImageName(cr, defaultDevworkspaceControllerImage) } -func DefaultKeycloakImage(cr *orgv1.CheCluster) string { - return patchDefaultImageName(cr, defaultKeycloakImage) -} - func DefaultPluginRegistryImage(cr *orgv1.CheCluster) string { return patchDefaultImageName(cr, defaultPluginRegistryImage) } @@ -395,12 +366,20 @@ func DefaultPullPolicyFromDockerImage(dockerImage string) string { return "IfNotPresent" } -func GetSingleHostExposureType(cr *orgv1.CheCluster) string { - if util.IsOpenShift || cr.Spec.DevWorkspace.Enable { - return GatewaySingleHostExposureType +// GetWorkspaceNamespaceDefault - returns workspace namespace default strategy, which points on the namespaces used for workspaces execution. +func GetWorkspaceNamespaceDefault(cr *orgv1.CheCluster) string { + if cr.Spec.Server.CustomCheProperties != nil { + k8sNamespaceDefault := cr.Spec.Server.CustomCheProperties["CHE_INFRA_KUBERNETES_NAMESPACE_DEFAULT"] + if k8sNamespaceDefault != "" { + return k8sNamespaceDefault + } } - return util.GetValue(cr.Spec.K8s.SingleHostExposureType, NativeSingleHostExposureType) + workspaceNamespaceDefault := cr.Namespace + if util.IsOpenShift { + workspaceNamespaceDefault = "-" + DefaultCheFlavor(cr) + } + return util.GetValue(cr.Spec.Server.WorkspaceNamespaceDefault, workspaceNamespaceDefault) } func patchDefaultImageName(cr *orgv1.CheCluster, imageName string) string { @@ -474,7 +453,6 @@ func InitDefaultsFromEnv() { // while downstream is not migrated to PostgreSQL 13.3 yet defaultPostgres13Image = os.Getenv(util.GetArchitectureDependentEnv("RELATED_IMAGE_postgres_13_3")) - defaultKeycloakImage = os.Getenv(util.GetArchitectureDependentEnv("RELATED_IMAGE_keycloak")) defaultSingleHostGatewayImage = getDefaultFromEnv(util.GetArchitectureDependentEnv("RELATED_IMAGE_single_host_gateway")) defaultSingleHostGatewayConfigSidecarImage = getDefaultFromEnv(util.GetArchitectureDependentEnv("RELATED_IMAGE_single_host_gateway_config_sidecar")) defaultInternalRestBackupServerImage = getDefaultFromEnv(util.GetArchitectureDependentEnv("RELATED_IMAGE_internal_rest_backup_server")) diff --git a/pkg/deploy/defaults.go.update.sh b/pkg/deploy/defaults.go.update.sh index 16f6f7b49..cc9f67c8a 100755 --- a/pkg/deploy/defaults.go.update.sh +++ b/pkg/deploy/defaults.go.update.sh @@ -21,8 +21,8 @@ if [[ ! -f ${defaultsFile} ]]; then curl -ssL https://raw.githubusercontent.com/eclipse-che/che-operator/main/pkg/deploy/defaults.go -o ${defaultsFile} fi -excludes="eclipse/che-keycloak|centos/postgresql-96-centos7" -for d in $(cat /tmp/defaults.go | egrep "Keycloak|Postgres|Pvc" | egrep Image | egrep -v "func|return|Old|ToDetect|$excludes" | sed -e "s#.\+= \"\(.\+\)\"#\1#"); do +excludes="eclipse|centos/postgresql-96-centos7" +for d in $(cat /tmp/defaults.go | egrep "Postgres|Pvc" | egrep Image | egrep -v "func|return|Old|ToDetect|$excludes" | sed -e "s#.\+= \"\(.\+\)\"#\1#"); do echo "- ${d}" echo -n "+ ${d%:*}:"; e=$(skopeo inspect docker://${d%:*} | yq .RepoTags | egrep -v "\[|\]|latest" | tr -d ",\" " | sort -V | tail -1) diff --git a/pkg/deploy/defaults_test.go b/pkg/deploy/defaults_test.go index 39c3dbf02..d655e0102 100644 --- a/pkg/deploy/defaults_test.go +++ b/pkg/deploy/defaults_test.go @@ -117,7 +117,6 @@ func TestCorrectAirGapPatchedImage(t *testing.T) { expectedAirGapPostgresUpstreamImageOnlyOrgChanged = makeAirGapImagePath(getHostnameFromImage(defaultPostgresImage), airGapRegistryOrganization, getImageNameFromFullImage(defaultPostgresImage)) expectedAirGapCRWPluginRegistryOnlyOrgChanged = makeAirGapImagePath(getHostnameFromImage(defaultPluginRegistryImage), airGapRegistryOrganization, getImageNameFromFullImage(defaultPluginRegistryImage)) expectedAirGapCRWPostgresImage = makeAirGapImagePath(airGapRegistryHostname, airGapRegistryOrganization, getImageNameFromFullImage(defaultPostgresImage)) - expectedAirGapKeyCloakImageOnlyHostnameChanged = makeAirGapImagePath(airGapRegistryHostname, getOrganizationFromImage(defaultKeycloakImage), getImageNameFromFullImage(defaultKeycloakImage)) expectedAirGapCRWDevfileRegistryImageOnlyHostnameChanged = makeAirGapImagePath(airGapRegistryHostname, getOrganizationFromImage(defaultDevfileRegistryImage), getImageNameFromFullImage(defaultDevfileRegistryImage)) ) @@ -157,13 +156,6 @@ func TestCorrectAirGapPatchedImage(t *testing.T) { }, }, } - upstreamOnlyHostname := &orgv1.CheCluster{ - Spec: orgv1.CheClusterSpec{ - Server: orgv1.CheClusterSpecServer{ - AirGapContainerRegistryHostname: airGapRegistryHostname, - }, - }, - } crwOnlyOrg := &orgv1.CheCluster{ Spec: orgv1.CheClusterSpec{ Server: orgv1.CheClusterSpecServer{ @@ -188,7 +180,6 @@ func TestCorrectAirGapPatchedImage(t *testing.T) { "codeready plugin registry with only the org changed": {image: defaultPluginRegistryImage, expected: expectedAirGapCRWPluginRegistryOnlyOrgChanged, cr: crwOnlyOrg}, "CRW postgres": {image: defaultPostgresImage, expected: defaultPostgresImage, cr: crw}, "CRW airgap postgres": {image: defaultPostgresImage, expected: expectedAirGapCRWPostgresImage, cr: airGapCRW}, - "airgap with only hostname defined": {image: defaultKeycloakImage, expected: expectedAirGapKeyCloakImageOnlyHostnameChanged, cr: upstreamOnlyHostname}, "crw airgap with only hostname defined": {image: defaultDevfileRegistryImage, expected: expectedAirGapCRWDevfileRegistryImageOnlyHostnameChanged, cr: crwOnlyHostname}, } for name, tc := range testCases { diff --git a/pkg/deploy/dev-workspace/dev_workspace.go b/pkg/deploy/dev-workspace/dev_workspace.go index 5a0fbf7d1..36f6f80e2 100644 --- a/pkg/deploy/dev-workspace/dev_workspace.go +++ b/pkg/deploy/dev-workspace/dev_workspace.go @@ -63,11 +63,6 @@ func (d *DevWorkspaceReconciler) Reconcile(ctx *deploy.DeployContext) (reconcile return reconcile.Result{}, true, nil } - if !ctx.CheCluster.Spec.DevWorkspace.Enable { - // Do nothing if DevWorkspace is disabled - return reconcile.Result{}, true, nil - } - if isDevWorkspaceOperatorCSVExists(ctx) { // Do nothing if DevWorkspace has been already deployed via OLM return reconcile.Result{}, true, nil diff --git a/pkg/deploy/dev-workspace/dev_workspace_test.go b/pkg/deploy/dev-workspace/dev_workspace_test.go index 978afdcb6..3fbd2f2e1 100644 --- a/pkg/deploy/dev-workspace/dev_workspace_test.go +++ b/pkg/deploy/dev-workspace/dev_workspace_test.go @@ -59,19 +59,13 @@ func TestReconcileDevWorkspace(t *testing.T) { DevWorkspace: orgv1.CheClusterSpecDevWorkspace{ Enable: true, }, - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: util.NewBoolPointer(true), - }, - Server: orgv1.CheClusterSpecServer{ - ServerExposureStrategy: "single-host", - }, }, }, IsOpenShift: true, IsOpenShift4: true, }, { - name: "Reconcile DevWorkspace on K8S multi-host", + name: "Reconcile DevWorkspace on K8S", cheCluster: &orgv1.CheCluster{ ObjectMeta: metav1.ObjectMeta{ Namespace: "eclipse-che", @@ -80,37 +74,8 @@ func TestReconcileDevWorkspace(t *testing.T) { DevWorkspace: orgv1.CheClusterSpecDevWorkspace{ Enable: true, }, - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: util.NewBoolPointer(true), - }, Server: orgv1.CheClusterSpecServer{ - ServerExposureStrategy: "multi-host", - CustomCheProperties: map[string]string{"CHE_INFRA_KUBERNETES_ENABLE__UNSUPPORTED__K8S": "true"}, - }, - K8s: orgv1.CheClusterSpecK8SOnly{ - IngressDomain: "che.domain", - }, - }, - }, - IsOpenShift: false, - IsOpenShift4: false, - }, - { - name: "Reconcile DevWorkspace on K8S single-host", - cheCluster: &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", - }, - Spec: orgv1.CheClusterSpec{ - DevWorkspace: orgv1.CheClusterSpecDevWorkspace{ - Enable: true, - }, - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: util.NewBoolPointer(true), - }, - Server: orgv1.CheClusterSpecServer{ - ServerExposureStrategy: "single-host", - CustomCheProperties: map[string]string{"CHE_INFRA_KUBERNETES_ENABLE__UNSUPPORTED__K8S": "true"}, + CustomCheProperties: map[string]string{"CHE_INFRA_KUBERNETES_ENABLE__UNSUPPORTED__K8S": "true"}, }, K8s: orgv1.CheClusterSpecK8SOnly{ IngressDomain: "che.domain", diff --git a/pkg/deploy/devfileregistry/devfileregistry.go b/pkg/deploy/devfileregistry/devfileregistry.go index 0654044bb..97d45f591 100644 --- a/pkg/deploy/devfileregistry/devfileregistry.go +++ b/pkg/deploy/devfileregistry/devfileregistry.go @@ -86,19 +86,11 @@ func (d *DevfileRegistryReconciler) exposeEndpoint(ctx *deploy.DeployContext) (s return expose.Expose( ctx, deploy.DevfileRegistryName, - ctx.CheCluster.Spec.Server.DevfileRegistryRoute, - ctx.CheCluster.Spec.Server.DevfileRegistryIngress, d.createGatewayConfig()) } func (d *DevfileRegistryReconciler) updateStatus(endpoint string, ctx *deploy.DeployContext) (bool, error) { - var devfileRegistryURL string - if ctx.CheCluster.Spec.Server.TlsSupport { - devfileRegistryURL = "https://" + endpoint - } else { - devfileRegistryURL = "http://" + endpoint - } - + devfileRegistryURL := "https://" + endpoint if devfileRegistryURL != ctx.CheCluster.Status.DevfileRegistryURL { ctx.CheCluster.Status.DevfileRegistryURL = devfileRegistryURL if err := deploy.UpdateCheCRStatus(ctx, "status: Devfile Registry URL", devfileRegistryURL); err != nil { diff --git a/pkg/deploy/devfileregistry/devfileregistry_deployment.go b/pkg/deploy/devfileregistry/devfileregistry_deployment.go index bb8f868dc..f40141b85 100644 --- a/pkg/deploy/devfileregistry/devfileregistry_deployment.go +++ b/pkg/deploy/devfileregistry/devfileregistry_deployment.go @@ -30,7 +30,7 @@ func (d *DevfileRegistryReconciler) getDevfileRegistryDeploymentSpec(ctx *deploy devfileImagesEnv := util.GetEnvByRegExp("^.*devfile_registry_image.*$") // If there is a devfile registry deployed by operator - if ctx.CheCluster.IsInternalClusterSVCNamesEnabled() && !ctx.CheCluster.Spec.Server.ExternalDevfileRegistry { + if !ctx.CheCluster.Spec.Server.ExternalDevfileRegistry { devfileImagesEnv = append(devfileImagesEnv, corev1.EnvVar{ Name: "CHE_DEVFILE_REGISTRY_INTERNAL_URL", diff --git a/pkg/deploy/devfileregistry/devfileregistry_test.go b/pkg/deploy/devfileregistry/devfileregistry_test.go index bc6e07f35..27cf56416 100644 --- a/pkg/deploy/devfileregistry/devfileregistry_test.go +++ b/pkg/deploy/devfileregistry/devfileregistry_test.go @@ -17,7 +17,6 @@ import ( orgv1 "github.com/eclipse-che/che-operator/api/v1" "github.com/eclipse-che/che-operator/pkg/deploy" "github.com/eclipse-che/che-operator/pkg/util" - routev1 "github.com/openshift/api/route/v1" "github.com/stretchr/testify/assert" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -38,7 +37,6 @@ func TestDevfileRegistryReconcile(t *testing.T) { assert.Nil(t, err) assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: "devfile-registry", Namespace: "eclipse-che"}, &corev1.Service{})) - assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: "devfile-registry", Namespace: "eclipse-che"}, &routev1.Route{})) assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: "devfile-registry", Namespace: "eclipse-che"}, &corev1.ConfigMap{})) assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: "devfile-registry", Namespace: "eclipse-che"}, &appsv1.Deployment{})) assert.NotEmpty(t, ctx.CheCluster.Status.DevfileRegistryURL) @@ -72,7 +70,7 @@ func TestShouldSetUpCorrectlyDevfileRegistryURL(t *testing.T) { }, }, }, - expectedDevfileRegistryURL: "http://devfile-registry-eclipse-che./", + expectedDevfileRegistryURL: "https:///devfile-registry", }, { name: "Test Status.DevfileRegistryURL #2", @@ -95,7 +93,7 @@ func TestShouldSetUpCorrectlyDevfileRegistryURL(t *testing.T) { }, }, }, - expectedDevfileRegistryURL: "http://devfile-registry-eclipse-che./", + expectedDevfileRegistryURL: "https:///devfile-registry", }, { name: "Test Status.DevfileRegistryURL #2", diff --git a/pkg/deploy/expose/expose.go b/pkg/deploy/expose/expose.go index b5271659d..43ccd164c 100644 --- a/pkg/deploy/expose/expose.go +++ b/pkg/deploy/expose/expose.go @@ -16,7 +16,6 @@ import ( routev1 "github.com/openshift/api/route/v1" - orgv1 "github.com/eclipse-che/che-operator/api/v1" "github.com/eclipse-che/che-operator/pkg/deploy" "github.com/eclipse-che/che-operator/pkg/deploy/gateway" "github.com/eclipse-che/che-operator/pkg/util" @@ -32,11 +31,9 @@ const ( func Expose( deployContext *deploy.DeployContext, componentName string, - routeCustomSettings orgv1.RouteCustomSettings, - ingressCustomSettings orgv1.IngressCustomSettings, gatewayConfig *gateway.TraefikConfig) (endpointUrl string, done bool, err error) { //the host and path are empty and will be evaluated for the specified component + path - return ExposeWithHostPath(deployContext, componentName, "", "", routeCustomSettings, ingressCustomSettings, gatewayConfig) + return ExposeWithHostPath(deployContext, componentName, "", "", gatewayConfig) } //Expose exposes the specified component on the specified host and domain. @@ -47,78 +44,24 @@ func ExposeWithHostPath( component string, host string, path string, - routeCustomSettings orgv1.RouteCustomSettings, - ingressCustomSettings orgv1.IngressCustomSettings, gatewayConfig *gateway.TraefikConfig) (endpointUrl string, done bool, err error) { - exposureStrategy := util.GetServerExposureStrategy(deployContext.CheCluster) - if path != "" && !strings.HasPrefix(path, "/") { path = "/" + path } - singleHostExposureType := deploy.GetSingleHostExposureType(deployContext.CheCluster) - useGateway := exposureStrategy == "single-host" && (util.IsOpenShift || singleHostExposureType == deploy.GatewaySingleHostExposureType) if !util.IsOpenShift { - if useGateway { - return exposeWithGateway(deployContext, gatewayConfig, component, path, func() { - if _, err = deploy.DeleteNamespacedObject(deployContext, component, &networking.Ingress{}); err != nil { - logrus.Error(err) - } - }) - } else { - endpointUrl, done, err = deploy.SyncIngressToCluster(deployContext, component, host, path, component, 8080, ingressCustomSettings, component) - if !done { - logrus.Infof("Waiting on ingress '%s' to be ready", component) - if err != nil { - logrus.Error(err) - } - return "", false, err - } - if err := gateway.DeleteGatewayRouteConfig(component, deployContext); !util.IsTestMode() && err != nil { + return exposeWithGateway(deployContext, gatewayConfig, component, path, func() { + if _, err = deploy.DeleteNamespacedObject(deployContext, component, &networking.Ingress{}); err != nil { logrus.Error(err) } - - return endpointUrl, true, nil - } + }) } else { - if useGateway { - return exposeWithGateway(deployContext, gatewayConfig, component, path, func() { - if _, err := deploy.DeleteNamespacedObject(deployContext, component, &routev1.Route{}); !util.IsTestMode() && err != nil { - logrus.Error(err) - } - }) - } else { - // the empty string for a host is intentional here - we let OpenShift decide on the hostname - done, err := deploy.SyncRouteToCluster(deployContext, component, host, path, component, 8080, routeCustomSettings, component) - if !done { - logrus.Infof("Waiting on route '%s' to be ready", component) - if err != nil { - logrus.Error(err) - } - return "", false, err - } - - route := &routev1.Route{} - exists, err := deploy.GetNamespacedObject(deployContext, component, route) - if !exists { - if err != nil { - logrus.Error(err) - } - return "", false, err - } - - if err := gateway.DeleteGatewayRouteConfig(component, deployContext); !util.IsTestMode() && err != nil { + return exposeWithGateway(deployContext, gatewayConfig, component, path, func() { + if _, err := deploy.DeleteNamespacedObject(deployContext, component, &routev1.Route{}); !util.IsTestMode() && err != nil { logrus.Error(err) } - - // Keycloak needs special rule in multihost. It's exposed on / which redirects to /auth - // clients which does not support redirects needs /auth be explicitely set - if path == "" && component == deploy.IdentityProviderName { - path = "/auth" - } - return route.Spec.Host + path, true, nil - } + }) } } @@ -143,11 +86,7 @@ func exposeWithGateway(deployContext *deploy.DeployContext, cleanUpRouting() if path == "" { - if component == deploy.IdentityProviderName { - path = "/auth" - } else { - path = "/" + component - } + path = "/" + component } return deployContext.CheCluster.Spec.Server.CheHost + path, true, err } diff --git a/pkg/deploy/gateway/gateway.go b/pkg/deploy/gateway/gateway.go index 2d63d9f23..3f89edd0e 100644 --- a/pkg/deploy/gateway/gateway.go +++ b/pkg/deploy/gateway/gateway.go @@ -84,13 +84,7 @@ func (p *GatewayReconciler) Finalize(ctx *deploy.DeployContext) bool { // SyncGatewayToCluster installs or deletes the gateway based on the custom resource configuration func SyncGatewayToCluster(deployContext *deploy.DeployContext) error { - if (util.GetServerExposureStrategy(deployContext.CheCluster) == "single-host" && - deploy.GetSingleHostExposureType(deployContext.CheCluster) == deploy.GatewaySingleHostExposureType) || - deployContext.CheCluster.Spec.DevWorkspace.Enable { - return syncAll(deployContext) - } - - return deleteAll(deployContext) + return syncAll(deployContext) } func syncAll(deployContext *deploy.DeployContext) error { @@ -110,33 +104,31 @@ func syncAll(deployContext *deploy.DeployContext) error { return err } - if deployContext.CheCluster.IsNativeUserModeEnabled() { - if oauthSecret, err := getGatewaySecretSpec(deployContext); err == nil { - if _, err := deploy.Sync(deployContext, oauthSecret, secretDiffOpts); err != nil { - return err - } - oauthProxyConfig := getGatewayOauthProxyConfigSpec(instance, string(oauthSecret.Data["cookie_secret"])) - if _, err := deploy.Sync(deployContext, &oauthProxyConfig, configMapDiffOpts); err != nil { + if oauthSecret, err := getGatewaySecretSpec(deployContext); err == nil { + if _, err := deploy.Sync(deployContext, oauthSecret, secretDiffOpts); err != nil { + return err + } + oauthProxyConfig := getGatewayOauthProxyConfigSpec(instance, string(oauthSecret.Data["cookie_secret"])) + if _, err := deploy.Sync(deployContext, &oauthProxyConfig, configMapDiffOpts); err != nil { + return err + } + } else { + return err + } + + kubeRbacProxyConfig := getGatewayKubeRbacProxyConfigSpec(instance) + if _, err := deploy.Sync(deployContext, &kubeRbacProxyConfig, configMapDiffOpts); err != nil { + return err + } + + if util.IsOpenShift { + if headerRewritePluginConfig, err := getGatewayHeaderRewritePluginConfigSpec(instance); err == nil { + if _, err := deploy.Sync(deployContext, headerRewritePluginConfig, configMapDiffOpts); err != nil { return err } } else { return err } - - kubeRbacProxyConfig := getGatewayKubeRbacProxyConfigSpec(instance) - if _, err := deploy.Sync(deployContext, &kubeRbacProxyConfig, configMapDiffOpts); err != nil { - return err - } - - if util.IsOpenShift { - if headerRewritePluginConfig, err := getGatewayHeaderRewritePluginConfigSpec(instance); err == nil { - if _, err := deploy.Sync(deployContext, headerRewritePluginConfig, configMapDiffOpts); err != nil { - return err - } - } else { - return err - } - } } traefikConfig := getGatewayTraefikConfigSpec(instance) @@ -196,73 +188,6 @@ func generateOauthSecretSpec(deployContext *deploy.DeployContext) *corev1.Secret } } -func deleteAll(deployContext *deploy.DeployContext) error { - instance := deployContext.CheCluster - clusterAPI := deployContext.ClusterAPI - - deployment := appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: GatewayServiceName, - Namespace: instance.Namespace, - }, - } - if err := delete(clusterAPI, &deployment); err != nil { - return err - } - - serverConfig := corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: GatewayConfigMapNamePrefix + serverComponentName, - Namespace: instance.Namespace, - }, - } - if err := delete(clusterAPI, &serverConfig); err != nil { - return err - } - - traefikConfig := corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "che-gateway-config", - Namespace: instance.Namespace, - }, - } - if err := delete(clusterAPI, &traefikConfig); err == nil { - return err - } - - roleBinding := rbac.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: GatewayServiceName, - Namespace: instance.Namespace, - }, - } - if err := delete(clusterAPI, &roleBinding); err == nil { - return err - } - - role := rbac.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: GatewayServiceName, - Namespace: instance.Namespace, - }, - } - if err := delete(clusterAPI, &role); err == nil { - return err - } - - sa := corev1.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{ - Name: GatewayServiceName, - Namespace: instance.Namespace, - }, - } - if err := delete(clusterAPI, &sa); err == nil { - return err - } - - return nil -} - func delete(clusterAPI deploy.ClusterAPI, obj metav1.Object) error { key := client.ObjectKey{Name: obj.GetName(), Namespace: obj.GetNamespace()} ro := obj.(client.Object) @@ -298,7 +223,7 @@ func getGatewayServerConfigSpec(deployContext *deploy.DeployContext) (corev1.Con "http://"+deploy.CheServiceName+":8080", []string{}) - if util.IsOpenShift && deployContext.CheCluster.IsNativeUserModeEnabled() { + if util.IsOpenShift { cfg.AddAuthHeaderRewrite(serverComponentName) // native user mode is currently only available on OpenShift but let's be defensive here so that // this doesn't break once we enable it on Kubernetes, too. Token check will have to work @@ -439,10 +364,7 @@ func getGatewayHeaderRewritePluginConfigSpec(instance *orgv1.CheCluster) (*corev } func getGatewayTraefikConfigSpec(instance *orgv1.CheCluster) corev1.ConfigMap { - traefikPort := GatewayServicePort - if instance.IsNativeUserModeEnabled() { - traefikPort = 8081 - } + traefikPort := 8081 data := fmt.Sprintf(` entrypoints: http: @@ -463,7 +385,7 @@ providers: log: level: "INFO"`, traefikPort) - if util.IsOpenShift && instance.IsNativeUserModeEnabled() { + if util.IsOpenShift { data += ` experimental: localPlugins: @@ -590,11 +512,9 @@ func getContainersSpec(instance *orgv1.CheCluster) []corev1.Container { }, } - if instance.IsNativeUserModeEnabled() { - containers = append(containers, - getOauthProxyContainerSpec(instance), - getKubeRbacProxyContainerSpec(instance)) - } + containers = append(containers, + getOauthProxyContainerSpec(instance), + getKubeRbacProxyContainerSpec(instance)) return containers } @@ -610,7 +530,7 @@ func getTraefikContainerVolumeMounts(instance *orgv1.CheCluster) []corev1.Volume MountPath: "/dynamic-config", }, } - if util.IsOpenShift && instance.IsNativeUserModeEnabled() { + if util.IsOpenShift { mounts = append(mounts, corev1.VolumeMount{ Name: "header-rewrite-traefik-plugin", MountPath: "/plugins-local/src/github.com/che-incubator/header-rewrite-traefik-plugin", @@ -640,23 +560,21 @@ func getVolumesSpec(instance *orgv1.CheCluster) []corev1.Volume { }, } - if instance.IsNativeUserModeEnabled() { - volumes = append(volumes, - getOauthProxyConfigVolume(), - getKubeRbacProxyConfigVolume()) + volumes = append(volumes, + getOauthProxyConfigVolume(), + getKubeRbacProxyConfigVolume()) - if util.IsOpenShift { - volumes = append(volumes, corev1.Volume{ - Name: "header-rewrite-traefik-plugin", - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: "che-gateway-config-header-rewrite-traefik-plugin", - }, + if util.IsOpenShift { + volumes = append(volumes, corev1.Volume{ + Name: "header-rewrite-traefik-plugin", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "che-gateway-config-header-rewrite-traefik-plugin", }, }, - }) - } + }, + }) } return volumes diff --git a/pkg/deploy/gateway/gateway_test.go b/pkg/deploy/gateway/gateway_test.go index e07a2b1b2..3b296d19e 100644 --- a/pkg/deploy/gateway/gateway_test.go +++ b/pkg/deploy/gateway/gateway_test.go @@ -23,7 +23,6 @@ import ( "github.com/stretchr/testify/assert" appsv1 "k8s.io/api/apps/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/client-go/kubernetes/scheme" @@ -42,11 +41,6 @@ func TestSyncAllToCluster(t *testing.T) { Namespace: "eclipse-che", Name: "eclipse-che", }, - Spec: orgv1.CheClusterSpec{ - Server: orgv1.CheClusterSpecServer{ - ServerExposureStrategy: "single-host", - }, - }, }, ClusterAPI: deploy.ClusterAPI{ Client: cli, @@ -66,8 +60,8 @@ func TestSyncAllToCluster(t *testing.T) { t.Fatalf("Failed to get deployment: %v", err) } - assert.Lenf(t, deployment.Spec.Template.Spec.Containers, 2, - "With classic multi-user, there should be 2 containers in the gateway, traefik and configbump. But it has '%d' containers.", len(deployment.Spec.Template.Spec.Containers)) + assert.Lenf(t, deployment.Spec.Template.Spec.Containers, 4, + "There should be 4 containers in the gateway. But it has '%d' containers.", len(deployment.Spec.Template.Spec.Containers)) for _, c := range deployment.Spec.Template.Spec.Containers { assert.NotNil(t, c.Resources, "container '%s' has not set resources", c.Name) } @@ -84,21 +78,12 @@ func TestNativeUserGateway(t *testing.T) { orgv1.SchemeBuilder.AddToScheme(scheme.Scheme) corev1.SchemeBuilder.AddToScheme(scheme.Scheme) cli := fake.NewFakeClientWithScheme(scheme.Scheme) - nativeUserMode := true deployContext := &deploy.DeployContext{ CheCluster: &orgv1.CheCluster{ ObjectMeta: metav1.ObjectMeta{ Namespace: "eclipse-che", Name: "eclipse-che", }, - Spec: orgv1.CheClusterSpec{ - Auth: orgv1.CheClusterSpecAuth{ - NativeUserMode: &nativeUserMode, - }, - Server: orgv1.CheClusterSpecServer{ - ServerExposureStrategy: "single-host", - }, - }, }, ClusterAPI: deploy.ClusterAPI{ Client: cli, @@ -138,49 +123,6 @@ func TestNativeUserGateway(t *testing.T) { } } -func TestNoGatewayForMultiHost(t *testing.T) { - orgv1.SchemeBuilder.AddToScheme(scheme.Scheme) - corev1.SchemeBuilder.AddToScheme(scheme.Scheme) - cli := fake.NewFakeClientWithScheme(scheme.Scheme) - deployContext := &deploy.DeployContext{ - CheCluster: &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", - Name: "eclipse-che", - }, - Spec: orgv1.CheClusterSpec{ - Server: orgv1.CheClusterSpecServer{ - ServerExposureStrategy: "multi-host", - }, - }, - }, - ClusterAPI: deploy.ClusterAPI{ - Client: cli, - NonCachingClient: cli, - Scheme: scheme.Scheme, - }, - } - - err := SyncGatewayToCluster(deployContext) - if err != nil { - t.Fatalf("Failed to sync Gateway: %v", err) - } - - deployment := &appsv1.Deployment{} - err = cli.Get(context.TODO(), types.NamespacedName{Name: GatewayServiceName, Namespace: "eclipse-che"}, deployment) - if err == nil { - t.Fatalf("Failed to get deployment: %v", err) - } else { - if v, ok := err.(errors.APIStatus); ok { - if v.Status().Code != 404 { - t.Fatalf("Deployment should not be found, thus code 404, but got '%d'", v.Status().Code) - } - } else { - t.Fatalf("Wrong error returned.") - } - } -} - func TestRandomCookieSecret(t *testing.T) { secret := generateRandomCookieSecret() if len(secret) != 24 { @@ -194,6 +136,9 @@ func TestRandomCookieSecret(t *testing.T) { } func TestOauthProxyConfigUnauthorizedPaths(t *testing.T) { + util.IsOpenShift = true + util.IsOpenShift4 = true + t.Run("no skip auth", func(t *testing.T) { configmap := getGatewayOauthProxyConfigSpec(&orgv1.CheCluster{ Spec: orgv1.CheClusterSpec{ @@ -202,7 +147,7 @@ func TestOauthProxyConfigUnauthorizedPaths(t *testing.T) { ExternalPluginRegistry: true, }}}, "blabol") config := configmap.Data["oauth-proxy.cfg"] - if strings.Contains(config, "skip_auth_regex") { + if !strings.Contains(config, "skip_auth_regex = \"/healthz$\"") { t.Errorf("oauth config shold not contain any skip auth when both registries are external") } }) @@ -216,7 +161,7 @@ func TestOauthProxyConfigUnauthorizedPaths(t *testing.T) { ExternalPluginRegistry: true, }}}, "blabol") config := configmap.Data["oauth-proxy.cfg"] - if !strings.Contains(config, "skip_auth_regex = \"^/devfile-registry\"") { + if !strings.Contains(config, "skip_auth_regex = \"^/devfile-registry|/healthz$\"") { t.Error("oauth config should skip auth for devfile registry", config) } }) @@ -229,7 +174,7 @@ func TestOauthProxyConfigUnauthorizedPaths(t *testing.T) { ExternalPluginRegistry: false, }}}, "blabol") config := configmap.Data["oauth-proxy.cfg"] - if !strings.Contains(config, "skip_auth_regex = \"^/plugin-registry\"") { + if !strings.Contains(config, "skip_auth_regex = \"^/plugin-registry|/healthz$\"") { t.Error("oauth config should skip auth for plugin registry", config) } }) @@ -242,17 +187,14 @@ func TestOauthProxyConfigUnauthorizedPaths(t *testing.T) { ExternalPluginRegistry: false, }}}, "blabol") config := configmap.Data["oauth-proxy.cfg"] - if !strings.Contains(config, "skip_auth_regex = \"^/plugin-registry|^/devfile-registry\"") { + if !strings.Contains(config, "skip_auth_regex = \"^/plugin-registry|^/devfile-registry|/healthz$\"") { t.Error("oauth config should skip auth for plugin and devfile registry.", config) } }) t.Run("skip '/healthz' path", func(t *testing.T) { configmap := getGatewayOauthProxyConfigSpec(&orgv1.CheCluster{ - Spec: orgv1.CheClusterSpec{ - Auth: orgv1.CheClusterSpecAuth{ - NativeUserMode: util.NewBoolPointer(true), - }}}, "blabol") + Spec: orgv1.CheClusterSpec{}}, "blabol") config := configmap.Data["oauth-proxy.cfg"] assert.Contains(t, config, "/healthz$") }) @@ -264,13 +206,7 @@ func TestTokenValidityCheckOnOpenShiftNativeUser(t *testing.T) { corev1.SchemeBuilder.AddToScheme(scheme.Scheme) cm, err := getGatewayServerConfigSpec(&deploy.DeployContext{ - CheCluster: &orgv1.CheCluster{ - Spec: orgv1.CheClusterSpec{ - Auth: orgv1.CheClusterSpecAuth{ - NativeUserMode: util.NewBoolPointer(true), - }, - }, - }, + CheCluster: &orgv1.CheCluster{}, ClusterAPI: deploy.ClusterAPI{ Scheme: scheme.Scheme, }, diff --git a/pkg/deploy/gateway/oauth_proxy.go b/pkg/deploy/gateway/oauth_proxy.go index f80cb6d53..213aff090 100644 --- a/pkg/deploy/gateway/oauth_proxy.go +++ b/pkg/deploy/gateway/oauth_proxy.go @@ -116,9 +116,7 @@ func skipAuthConfig(instance *orgv1.CheCluster) string { if !instance.Spec.Server.ExternalDevfileRegistry { skipAuthPaths = append(skipAuthPaths, "^/"+deploy.DevfileRegistryName) } - if instance.IsNativeUserModeEnabled() { - skipAuthPaths = append(skipAuthPaths, "/healthz$") - } + skipAuthPaths = append(skipAuthPaths, "/healthz$") if len(skipAuthPaths) > 0 { propName := "skip_auth_routes" if util.IsOpenShift { diff --git a/pkg/deploy/identity-provider/deployment_keycloak.go b/pkg/deploy/identity-provider/deployment_keycloak.go deleted file mode 100644 index 87237257d..000000000 --- a/pkg/deploy/identity-provider/deployment_keycloak.go +++ /dev/null @@ -1,864 +0,0 @@ -// -// Copyright (c) 2019-2021 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 identityprovider - -import ( - "context" - "regexp" - "strconv" - "strings" - - orgv1 "github.com/eclipse-che/che-operator/api/v1" - "github.com/eclipse-che/che-operator/pkg/deploy" - "github.com/eclipse-che/che-operator/pkg/deploy/postgres" - "github.com/eclipse-che/che-operator/pkg/deploy/tls" - "github.com/eclipse-che/che-operator/pkg/util" - "github.com/google/go-cmp/cmp" - "github.com/sirupsen/logrus" - appsv1 "k8s.io/api/apps/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/apimachinery/pkg/util/intstr" -) - -const ( - selectSslRequiredCommand = "OUT=$(psql keycloak -tAc \"SELECT 1 FROM REALM WHERE id = 'master'\"); " + - "if [ $OUT -eq 1 ]; then psql keycloak -tAc \"SELECT ssl_required FROM REALM WHERE id = 'master'\"; fi" - updateSslRequiredCommand = "psql keycloak -c \"update REALM set ssl_required='NONE' where id = 'master'\"" -) - -var ( - trustpass = util.GeneratePasswd(12) - keycloakCustomDiffOpts = cmp.Options{ - deploy.DefaultDeploymentDiffOpts, - cmp.Comparer(func(x, y metav1.ObjectMeta) bool { - return x.Annotations["che.self-signed-certificate.version"] == y.Annotations["che.self-signed-certificate.version"] && - x.Annotations["che.openshift-api-crt.version"] == y.Annotations["che.openshift-api-crt.version"] && - x.Annotations["che.keycloak-ssl-required-updated"] == y.Annotations["che.keycloak-ssl-required-updated"] - }), - } -) - -func SyncKeycloakDeploymentToCluster(deployContext *deploy.DeployContext) (bool, error) { - actual := &appsv1.Deployment{} - exists, err := deploy.GetNamespacedObject(deployContext, deploy.IdentityProviderName, actual) - if err != nil { - return false, err - } - - if !exists { - actual = nil - } - - specDeployment, err := GetSpecKeycloakDeployment(deployContext, actual) - if err != nil { - return false, err - } - - return deploy.SyncDeploymentSpecToCluster(deployContext, specDeployment, deploy.DefaultDeploymentDiffOpts) -} - -func GetSpecKeycloakDeployment( - deployContext *deploy.DeployContext, - clusterDeployment *appsv1.Deployment) (*appsv1.Deployment, error) { - optionalEnv := true - labels, labelSelector := deploy.GetLabelsAndSelector(deployContext.CheCluster, deploy.IdentityProviderName) - cheFlavor := deploy.DefaultCheFlavor(deployContext.CheCluster) - keycloakImage := util.GetValue(deployContext.CheCluster.Spec.Auth.IdentityProviderImage, deploy.DefaultKeycloakImage(deployContext.CheCluster)) - pullPolicy := corev1.PullPolicy(util.GetValue(string(deployContext.CheCluster.Spec.Auth.IdentityProviderImagePullPolicy), deploy.DefaultPullPolicyFromDockerImage(keycloakImage))) - jbossDir := "/opt/eap" - if cheFlavor == "che" { - // writable dir in the upstream Keycloak image - jbossDir = "/scripts" - } - jbossCli := "/opt/jboss/keycloak/bin/jboss-cli.sh" - if cheFlavor == "codeready" { - jbossCli = "/opt/eap/bin/jboss-cli.sh" - } - - if clusterDeployment != nil { - // To be compatible with prev deployments when "TRUSTPASS" env was used - clusterContainer := &clusterDeployment.Spec.Template.Spec.Containers[0] - env := util.FindEnv(clusterContainer.Env, "TRUSTPASS") - if env != nil { - trustpass = env.Value - } else { - env := util.FindEnv(clusterContainer.Env, "SSO_TRUSTSTORE_PASSWORD") - if env != nil { - trustpass = env.Value - } - } - } - - cmResourceVersions := tls.GetAdditionalCACertsConfigMapVersion(deployContext) - terminationGracePeriodSeconds := int64(30) - cheCertSecretVersion := getSecretResourceVersion("self-signed-certificate", deployContext.CheCluster.Namespace, deployContext.ClusterAPI) - openshiftApiCertSecretVersion := getSecretResourceVersion("openshift-api-crt", deployContext.CheCluster.Namespace, deployContext.ClusterAPI) - - // holds bash functions that should be available when run init commands in shell - bashFunctions := "" - - // add various certificates to Java trust store so that Keycloak can connect to OpenShift API - // certificate that OpenShift router uses (for 4.0 only) - addRouterCrt := "if [ ! -z \"${CHE_SELF__SIGNED__CERT}\" ]; then echo \"${CHE_SELF__SIGNED__CERT}\" > " + jbossDir + "/che.crt && " + - "keytool -importcert -alias ROUTERCRT" + - " -keystore " + jbossDir + "/openshift.jks" + - " -file " + jbossDir + "/che.crt -storepass " + trustpass + " -noprompt; fi" - // certificate retrieved from http call to OpenShift API endpoint - addOpenShiftAPICrt := "if [ ! -z \"${OPENSHIFT_SELF__SIGNED__CERT}\" ]; then echo \"${OPENSHIFT_SELF__SIGNED__CERT}\" > " + jbossDir + "/openshift.crt && " + - "keytool -importcert -alias OPENSHIFTAPI" + - " -keystore " + jbossDir + "/openshift.jks" + - " -file " + jbossDir + "/openshift.crt -storepass " + trustpass + " -noprompt; fi" - // certificate mounted into container /var/run/secrets - addMountedCrt := " keytool -importcert -alias MOUNTEDCRT" + - " -keystore " + jbossDir + "/openshift.jks" + - " -file /var/run/secrets/kubernetes.io/serviceaccount/ca.crt -storepass " + trustpass + " -noprompt" - addMountedServiceCrt := "if [ -f /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt ]; then " + - "keytool -importcert -alias MOUNTEDSERVICECRT" + - " -keystore " + jbossDir + "/openshift.jks" + - " -file /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt -storepass " + trustpass + " -noprompt; fi" - importJavaCacerts := "keytool -importkeystore -srckeystore /etc/pki/ca-trust/extracted/java/cacerts" + - " -destkeystore " + jbossDir + "/openshift.jks" + - " -srcstorepass changeit -deststorepass " + trustpass - - customPublicCertsDir := "/public-certs" - customPublicCertsVolumeSource := corev1.VolumeSource{} - customPublicCertsVolumeSource = corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: tls.CheAllCACertsConfigMapName, - }, - }, - } - customPublicCertsVolume := corev1.Volume{ - Name: "che-public-certs", - VolumeSource: customPublicCertsVolumeSource, - } - customPublicCertsVolumeMount := corev1.VolumeMount{ - Name: "che-public-certs", - MountPath: customPublicCertsDir, - } - addCustomPublicCertsCommand := "if [[ -d \"" + customPublicCertsDir + "\" && -n \"$(find " + customPublicCertsDir + " -type f)\" ]]; then " + - "for certfile in " + customPublicCertsDir + "/* ; do " + - "jks_import_ca_bundle $certfile " + jbossDir + "/openshift.jks " + trustpass + " ; " + - "done; fi" - - bashFunctions += getImportCABundleScript() - addCertToTrustStoreCommand := addRouterCrt + " && " + addOpenShiftAPICrt + " && " + addMountedCrt + " && " + addMountedServiceCrt + " && " + importJavaCacerts + " && " + addCustomPublicCertsCommand - - // upstream Keycloak has a bit different mechanism of adding jks - changeConfigCommand := "echo Installing certificates into Keycloak && " + - "echo -e \"embed-server --server-config=standalone.xml --std-out=echo \n" + - "/subsystem=keycloak-server/spi=truststore/:add \n" + - "/subsystem=keycloak-server/spi=truststore/provider=file/:add(properties={file => " + - "\"" + jbossDir + "/openshift.jks\", password => \"" + trustpass + "\", disabled => \"false\" },enabled=true) \n" + - "stop-embedded-server\" > /scripts/add_openshift_certificate.cli && " + - "/opt/jboss/keycloak/bin/jboss-cli.sh --file=/scripts/add_openshift_certificate.cli" - - addProxyCliCommand := "" - applyProxyCliCommand := "" - proxyEnvVars := []corev1.EnvVar{} - - if deployContext.Proxy.HttpProxy != "" { - proxyEnvVars = []corev1.EnvVar{ - { - Name: "HTTP_PROXY", - Value: deployContext.Proxy.HttpProxy, - }, - { - Name: "HTTPS_PROXY", - Value: deployContext.Proxy.HttpsProxy, - }, - { - Name: "NO_PROXY", - Value: deployContext.Proxy.NoProxy, - }, - } - - quotedNoProxy := "" - for _, noProxyHost := range strings.Split(deployContext.Proxy.NoProxy, ",") { - if len(quotedNoProxy) != 0 { - quotedNoProxy += "," - } - - var noProxyEntry string - if strings.HasPrefix(noProxyHost, ".") { - noProxyEntry = ".*" + strings.ReplaceAll(regexp.QuoteMeta(noProxyHost), "\\", "\\\\\\") - } else if strings.HasPrefix(noProxyHost, "*.") { - noProxyEntry = strings.TrimPrefix(noProxyHost, "*") - noProxyEntry = ".*" + strings.ReplaceAll(regexp.QuoteMeta(noProxyEntry), "\\", "\\\\\\") - } else { - noProxyEntry = strings.ReplaceAll(regexp.QuoteMeta(noProxyHost), "\\", "\\\\\\") - } - quotedNoProxy += "\"" + noProxyEntry + ";NO_PROXY\"" - } - - serverConfig := "standalone.xml" - if cheFlavor == "codeready" { - serverConfig = "standalone-openshift.xml" - } - addProxyCliCommand = " && echo Configuring Proxy && " + - "echo -e 'embed-server --server-config=" + serverConfig + " --std-out=echo \n" + - "/subsystem=keycloak-server/spi=connectionsHttpClient/provider=default:write-attribute(name=properties.proxy-mappings,value=[" + quotedNoProxy + ",\".*;" + deployContext.Proxy.HttpProxy + "\"]) \n" + - "stop-embedded-server' > " + jbossDir + "/setup-http-proxy.cli" - - applyProxyCliCommand = " && " + jbossCli + " --file=" + jbossDir + "/setup-http-proxy.cli" - if cheFlavor == "codeready" { - applyProxyCliCommand = " && mkdir -p " + jbossDir + "/extensions && echo '#!/bin/bash\n" + - "" + jbossDir + "/bin/jboss-cli.sh --file=" + jbossDir + "/setup-http-proxy.cli' > " + jbossDir + "/extensions/postconfigure.sh && " + - "chmod a+x " + jbossDir + "/extensions/postconfigure.sh " - } - } - - keycloakEnv := []corev1.EnvVar{ - { - Name: "CM_REVISION", - Value: cmResourceVersions, - }, - { - Name: "PROXY_ADDRESS_FORWARDING", - Value: "true", - }, - { - Name: "DB_VENDOR", - Value: "POSTGRES", - }, - { - Name: "DB_USERNAME", - Value: "keycloak", - }, - { - Name: "DB_ADDR", - Value: util.GetValue(deployContext.CheCluster.Spec.Database.ChePostgresHostName, deploy.DefaultChePostgresHostName), - }, - { - Name: "DB_DATABASE", - Value: "keycloak", - }, - { - Name: "POSTGRES_PORT_5432_TCP_ADDR", - Value: util.GetValue(deployContext.CheCluster.Spec.Database.ChePostgresHostName, deploy.DefaultChePostgresHostName), - }, - { - Name: "POSTGRES_PORT_5432_TCP_PORT", - Value: util.GetValue(deployContext.CheCluster.Spec.Database.ChePostgresPort, deploy.DefaultChePostgresPort), - }, - { - Name: "POSTGRES_PORT", - Value: util.GetValue(deployContext.CheCluster.Spec.Database.ChePostgresPort, deploy.DefaultChePostgresPort), - }, - { - Name: "POSTGRES_USER", - Value: "keycloak", - }, - { - Name: "SSO_TRUSTSTORE", - Value: "openshift.jks", - }, - { - Name: "SSO_TRUSTSTORE_DIR", - Value: jbossDir, - }, - { - Name: "SSO_TRUSTSTORE_PASSWORD", - Value: trustpass, - }, - { - Name: "CHE_SELF__SIGNED__CERT", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: "ca.crt", - LocalObjectReference: corev1.LocalObjectReference{ - Name: deploy.CheTLSSelfSignedCertificateSecretName, - }, - Optional: &optionalEnv, - }, - }, - }, - { - Name: "OPENSHIFT_SELF__SIGNED__CERT", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: "ca.crt", - LocalObjectReference: corev1.LocalObjectReference{ - Name: "openshift-api-crt", - }, - Optional: &optionalEnv, - }, - }, - }, - } - - identityProviderPostgresSecret := deployContext.CheCluster.Spec.Auth.IdentityProviderPostgresSecret - if len(identityProviderPostgresSecret) > 0 { - keycloakEnv = append(keycloakEnv, corev1.EnvVar{ - Name: "DB_PASSWORD", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: "password", - LocalObjectReference: corev1.LocalObjectReference{ - Name: identityProviderPostgresSecret, - }, - }, - }, - }) - } else { - keycloakEnv = append(keycloakEnv, corev1.EnvVar{ - Name: "DB_PASSWORD", - Value: deployContext.CheCluster.Spec.Auth.IdentityProviderPostgresPassword, - }) - } - - identityProviderSecret := deployContext.CheCluster.Spec.Auth.IdentityProviderSecret - if len(identityProviderSecret) > 0 { - keycloakEnv = append(keycloakEnv, corev1.EnvVar{ - Name: "KEYCLOAK_PASSWORD", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: "password", - LocalObjectReference: corev1.LocalObjectReference{ - Name: identityProviderSecret, - }, - }, - }, - }, - corev1.EnvVar{ - Name: "KEYCLOAK_USER", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: "user", - LocalObjectReference: corev1.LocalObjectReference{ - Name: identityProviderSecret, - }, - }, - }, - }) - } else { - keycloakEnv = append(keycloakEnv, corev1.EnvVar{ - Name: "KEYCLOAK_PASSWORD", - Value: deployContext.CheCluster.Spec.Auth.IdentityProviderPassword, - }, - corev1.EnvVar{ - Name: "KEYCLOAK_USER", - Value: deployContext.CheCluster.Spec.Auth.IdentityProviderAdminUserName, - }) - } - - if cheFlavor == "codeready" { - keycloakEnv = []corev1.EnvVar{ - { - Name: "CM_REVISION", - Value: cmResourceVersions, - }, - { - Name: "PROXY_ADDRESS_FORWARDING", - Value: "true", - }, - { - Name: "DB_SERVICE_PREFIX_MAPPING", - Value: "keycloak-postgresql=DB", - }, - { - Name: "KEYCLOAK_POSTGRESQL_SERVICE_HOST", - Value: util.GetValue(deployContext.CheCluster.Spec.Database.ChePostgresHostName, deploy.DefaultChePostgresHostName), - }, - { - Name: "KEYCLOAK_POSTGRESQL_SERVICE_PORT", - Value: util.GetValue(deployContext.CheCluster.Spec.Database.ChePostgresPort, deploy.DefaultChePostgresPort), - }, - { - Name: "DB_DATABASE", - Value: "keycloak", - }, - { - Name: "DB_USERNAME", - Value: "keycloak", - }, - { - Name: "DB_VENDOR", - Value: "POSTGRES", - }, - { - Name: "SSO_TRUSTSTORE", - Value: "openshift.jks", - }, - { - Name: "SSO_TRUSTSTORE_DIR", - Value: jbossDir, - }, - { - Name: "SSO_TRUSTSTORE_PASSWORD", - Value: trustpass, - }, - { - Name: "CHE_SELF__SIGNED__CERT", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: "ca.crt", - LocalObjectReference: corev1.LocalObjectReference{ - Name: deploy.CheTLSSelfSignedCertificateSecretName, - }, - Optional: &optionalEnv, - }, - }, - }, - { - Name: "OPENSHIFT_SELF__SIGNED__CERT", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: "ca.crt", - LocalObjectReference: corev1.LocalObjectReference{ - Name: "openshift-api-crt", - }, - Optional: &optionalEnv, - }, - }, - }, - } - - identityProviderPostgresSecret := deployContext.CheCluster.Spec.Auth.IdentityProviderPostgresSecret - if len(identityProviderPostgresSecret) > 0 { - keycloakEnv = append(keycloakEnv, corev1.EnvVar{ - Name: "DB_PASSWORD", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: "password", - LocalObjectReference: corev1.LocalObjectReference{ - Name: identityProviderPostgresSecret, - }, - }, - }, - }) - } else { - keycloakEnv = append(keycloakEnv, corev1.EnvVar{ - Name: "DB_PASSWORD", - Value: deployContext.CheCluster.Spec.Auth.IdentityProviderPostgresPassword, - }) - } - - identityProviderSecret := deployContext.CheCluster.Spec.Auth.IdentityProviderSecret - if len(identityProviderSecret) > 0 { - keycloakEnv = append(keycloakEnv, corev1.EnvVar{ - Name: "SSO_ADMIN_PASSWORD", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: "password", - LocalObjectReference: corev1.LocalObjectReference{ - Name: identityProviderSecret, - }, - }, - }, - }, - corev1.EnvVar{ - Name: "SSO_ADMIN_USERNAME", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: "user", - LocalObjectReference: corev1.LocalObjectReference{ - Name: identityProviderSecret, - }, - }, - }, - }) - } else { - keycloakEnv = append(keycloakEnv, corev1.EnvVar{ - Name: "SSO_ADMIN_PASSWORD", - Value: deployContext.CheCluster.Spec.Auth.IdentityProviderPassword, - }, - corev1.EnvVar{ - Name: "SSO_ADMIN_USERNAME", - Value: deployContext.CheCluster.Spec.Auth.IdentityProviderAdminUserName, - }) - } - } - - // Mount GITHUB_CLIENT_ID and GITHUB_SECRET to keycloak container - secrets, err := deploy.GetSecrets(deployContext, map[string]string{ - deploy.KubernetesPartOfLabelKey: deploy.CheEclipseOrg, - deploy.KubernetesComponentLabelKey: deploy.OAuthScmConfiguration, - }, map[string]string{ - deploy.CheEclipseOrgOAuthScmServer: "github", - }) - - if err != nil { - return nil, err - } else if len(secrets) == 1 { - keycloakEnv = append(keycloakEnv, corev1.EnvVar{ - Name: "GITHUB_CLIENT_ID", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: "id", - LocalObjectReference: corev1.LocalObjectReference{ - Name: secrets[0].Name, - }, - }, - }, - }, corev1.EnvVar{ - Name: "GITHUB_SECRET", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: "secret", - LocalObjectReference: corev1.LocalObjectReference{ - Name: secrets[0].Name, - }, - }, - }, - }) - } - - for _, envvar := range proxyEnvVars { - keycloakEnv = append(keycloakEnv, envvar) - } - - // Enable internal network for keycloak - if deployContext.CheCluster.IsInternalClusterSVCNamesEnabled() && !deployContext.CheCluster.Spec.Auth.ExternalIdentityProvider { - keycloakEnv = append(keycloakEnv, corev1.EnvVar{ - Name: "KEYCLOAK_FRONTEND_URL", - Value: deployContext.CheCluster.Status.KeycloakURL, - }) - } - - evaluateKeycloakSystemProperties := "KEYCLOAK_SYS_PROPS=\"-Dkeycloak.profile.feature.token_exchange=enabled -Dkeycloak.profile.feature.admin_fine_grained_authz=enabled\"" - if cheFlavor == "codeready" { - // We need to export `KEYCLOAK_SYS_PROPS` to pass them to standalone.sh via openshift-launch.sh - evaluateKeycloakSystemProperties = "export KEYCLOAK_SYS_PROPS=\"\"" - } - - // Evaluating keycloak.connectionsHttpClient.default system properties, see details: https://github.com/eclipse/che/issues/19653 - evaluateExpectContinueEnabled := "if [[ $KEYCLOAK_CONNECTIONS_HTTP_CLIENT_DEFAULT_EXPECT_CONTINUE_ENABLED != false ]]; then KEYCLOAK_SYS_PROPS=$KEYCLOAK_SYS_PROPS\" -Dkeycloak.connectionsHttpClient.default.expect-continue-enabled=true\"; fi" - evaluateReuseConnections := "if [[ $KEYCLOAK_CONNECTIONS_HTTP_CLIENT_DEFAULT_REUSE_CONNECTIONS != true ]]; then KEYCLOAK_SYS_PROPS=$KEYCLOAK_SYS_PROPS\" -Dkeycloak.connectionsHttpClient.default.reuse-connections=false\"; fi" - - command := bashFunctions + "\n" + - addCertToTrustStoreCommand + - addProxyCliCommand + - applyProxyCliCommand + - " && " + evaluateKeycloakSystemProperties + - " && " + evaluateExpectContinueEnabled + - " && " + evaluateReuseConnections + - " && " + changeConfigCommand + - " && /opt/jboss/tools/docker-entrypoint.sh -b 0.0.0.0 -c standalone.xml $KEYCLOAK_SYS_PROPS" - - if cheFlavor == "codeready" { - addUsernameReadonlyTheme := "baseTemplate=/opt/eap/themes/base/login/login-update-profile.ftl" + - " && readOnlyTemplateDir=/opt/eap/themes/codeready-username-readonly/login" + - " && readOnlyTemplate=${readOnlyTemplateDir}/login-update-profile.ftl" + - " && if [ ! -d ${readOnlyTemplateDir} ]; then" + - " mkdir -p ${readOnlyTemplateDir}" + - " && cp ${baseTemplate} ${readOnlyTemplate}" + - " && echo \"parent=rh-sso\" > ${readOnlyTemplateDir}/theme.properties" + - " && sed -i 's|id=\"username\" name=\"username\"|id=\"username\" readonly name=\"username\"|g' ${readOnlyTemplate}; fi" - addUsernameValidationForKeycloakTheme := "sed -i 's|id=\"username\" name=\"username\"|" + - "id=\"username\" " + - "pattern=\"[a-z]([-a-z0-9]{0,61}[a-z0-9])?\" " + - "title=\"Username has to comply with the DNS naming convention. An alphanumeric (a-z, and 0-9) string, with a maximum length of 63 characters, with the '-' character allowed anywhere except the first or last character.\" " + - "name=\"username\"|g' ${baseTemplate}" - patchOpenshiftLaunch := "sed -i 's|standalone.sh -c standalone-openshift.xml|standalone.sh -c standalone-openshift.xml ${KEYCLOAK_SYS_PROPS}|' /opt/eap/bin/openshift-launch.sh" - command = bashFunctions + "\n" + - addUsernameReadonlyTheme + - " && " + addUsernameValidationForKeycloakTheme + - " && " + addCertToTrustStoreCommand + - addProxyCliCommand + - applyProxyCliCommand + - " && " + evaluateKeycloakSystemProperties + - " && " + evaluateExpectContinueEnabled + - " && " + evaluateReuseConnections + - " && " + patchOpenshiftLaunch + - " && echo \"feature.token_exchange=enabled\nfeature.admin_fine_grained_authz=enabled\" > /opt/eap/standalone/configuration/profile.properties " + - " && sed -i 's/WILDCARD/ANY/g' /opt/eap/bin/launch/keycloak-spi.sh && /opt/eap/bin/openshift-launch.sh -b 0.0.0.0" - } - - sslRequiredUpdatedForMasterRealm := isSslRequiredUpdatedForMasterRealm(deployContext) - if sslRequiredUpdatedForMasterRealm { - // update command to restart pod - command = "echo \"ssl_required WAS UPDATED for master realm.\" && " + command - } - - ports := []corev1.ContainerPort{ - { - Name: deploy.IdentityProviderName, - ContainerPort: 8080, - Protocol: "TCP", - }, - } - - if deployContext.CheCluster.Spec.Auth.Debug { - ports = append(ports, corev1.ContainerPort{ - Name: "debug", - ContainerPort: 8787, - Protocol: "TCP", - }) - - keycloakEnv = append(keycloakEnv, []corev1.EnvVar{ - { - Name: "DEBUG", - Value: "true", - }, - { - Name: "DEBUG_PORT", - Value: "*:8787", - }, - }...) - - command += " --debug" - } - - args := []string{"-c", command} - - deployment := &appsv1.Deployment{ - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: "apps/v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: deploy.IdentityProviderName, - Namespace: deployContext.CheCluster.Namespace, - Labels: labels, - Annotations: map[string]string{ - "che.self-signed-certificate.version": cheCertSecretVersion, - "che.openshift-api-crt.version": openshiftApiCertSecretVersion, - "che.keycloak-ssl-required-updated": strconv.FormatBool(sslRequiredUpdatedForMasterRealm), - }, - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: labelSelector}, - Strategy: appsv1.DeploymentStrategy{ - Type: appsv1.RollingUpdateDeploymentStrategyType, - }, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: labels, - }, - Spec: corev1.PodSpec{ - Volumes: []corev1.Volume{ - customPublicCertsVolume, - }, - Containers: []corev1.Container{ - { - Name: deploy.IdentityProviderName, - Image: keycloakImage, - ImagePullPolicy: pullPolicy, - Command: []string{ - "/bin/sh", - }, - Args: args, - Ports: ports, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceMemory: util.GetResourceQuantity( - deployContext.CheCluster.Spec.Auth.IdentityProviderContainerResources.Requests.Memory, - deploy.DefaultIdentityProviderMemoryRequest), - corev1.ResourceCPU: util.GetResourceQuantity( - deployContext.CheCluster.Spec.Auth.IdentityProviderContainerResources.Requests.Cpu, - deploy.DefaultIdentityProviderCpuRequest), - }, - Limits: corev1.ResourceList{ - corev1.ResourceMemory: util.GetResourceQuantity( - deployContext.CheCluster.Spec.Auth.IdentityProviderContainerResources.Limits.Memory, - deploy.DefaultIdentityProviderMemoryLimit), - corev1.ResourceCPU: util.GetResourceQuantity( - deployContext.CheCluster.Spec.Auth.IdentityProviderContainerResources.Limits.Cpu, - deploy.DefaultIdentityProviderCpuLimit), - }, - }, - ReadinessProbe: &corev1.Probe{ - Handler: corev1.Handler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: "auth/js/keycloak.js", - Port: intstr.IntOrString{ - Type: intstr.Int, - IntVal: int32(8080), - }, - Scheme: corev1.URISchemeHTTP, - }, - }, - InitialDelaySeconds: 30, - FailureThreshold: 10, - TimeoutSeconds: 5, - PeriodSeconds: 10, - SuccessThreshold: 1, - }, - LivenessProbe: &corev1.Probe{ - Handler: corev1.Handler{ - TCPSocket: &corev1.TCPSocketAction{ - Port: intstr.FromInt(8080), - }, - }, - InitialDelaySeconds: 300, - FailureThreshold: 10, - TimeoutSeconds: 5, - PeriodSeconds: 10, - SuccessThreshold: 1, - }, - SecurityContext: &corev1.SecurityContext{ - Capabilities: &corev1.Capabilities{ - Drop: []corev1.Capability{"ALL"}, - }, - }, - Env: keycloakEnv, - VolumeMounts: []corev1.VolumeMount{ - customPublicCertsVolumeMount, - }, - }, - }, - TerminationGracePeriodSeconds: &terminationGracePeriodSeconds, - RestartPolicy: "Always", - }, - }, - }, - } - - if deploy.IsComponentReadinessInitContainersConfigured(deployContext.CheCluster) { - if !deployContext.CheCluster.Spec.Database.ExternalDb { - waitForPostgresInitContainer, err := postgres.GetWaitForPostgresInitContainer(deployContext) - if err != nil { - return nil, err - } - deployment.Spec.Template.Spec.InitContainers = append(deployment.Spec.Template.Spec.InitContainers, *waitForPostgresInitContainer) - } - } - - return deployment, nil -} - -func getSecretResourceVersion(name string, namespace string, clusterAPI deploy.ClusterAPI) string { - secret := &corev1.Secret{} - err := clusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: namespace}, secret) - if err != nil { - if !errors.IsNotFound(err) { - logrus.Errorf("Failed to get %s secret: %s", name, err) - } - return "" - } - return secret.ResourceVersion -} - -func isSslRequiredUpdatedForMasterRealm(deployContext *deploy.DeployContext) bool { - if deployContext.CheCluster.Spec.Database.ExternalDb { - return false - } - - if util.IsTestMode() { - return false - } - - actual := &appsv1.Deployment{} - exists, err := deploy.GetNamespacedObject(deployContext, deploy.IdentityProviderName, actual) - if !exists || err != nil { - if err != nil { - logrus.Error(err) - } - return false - } - - value, err := strconv.ParseBool(actual.ObjectMeta.Annotations["che.keycloak-ssl-required-updated"]) - if err == nil && value { - return true - } - - dbValue, _ := getSslRequiredForMasterRealm(deployContext.CheCluster) - return dbValue == "NONE" -} - -func getSslRequiredForMasterRealm(cr *orgv1.CheCluster) (string, error) { - stdout, err := util.K8sclient.ExecIntoPod( - cr, - deploy.PostgresName, - func(cr *orgv1.CheCluster) (string, error) { - return selectSslRequiredCommand, nil - }, - "") - return strings.TrimSpace(stdout), err -} - -func updateSslRequiredForMasterRealm(cr *orgv1.CheCluster) error { - _, err := util.K8sclient.ExecIntoPod( - cr, - deploy.PostgresName, - func(cr *orgv1.CheCluster) (string, error) { - return updateSslRequiredCommand, nil - }, - "Update ssl_required to NONE") - return err -} - -func ProvisionKeycloakResources(deployContext *deploy.DeployContext) error { - if !deployContext.CheCluster.Spec.Database.ExternalDb { - value, err := getSslRequiredForMasterRealm(deployContext.CheCluster) - if err != nil { - return err - } - - if value != "NONE" { - err := updateSslRequiredForMasterRealm(deployContext.CheCluster) - if err != nil { - return err - } - } - } - - _, err := util.K8sclient.ExecIntoPod( - deployContext.CheCluster, - deploy.IdentityProviderName, - GetKeycloakProvisionCommand, - "create realm, client and user") - return err -} - -// getImportCABundleScript returns string which contains bash function that imports ca-bundle into jks -// The function has three arguments: -// - absolute path to ca-bundle file -// - absolute path to java keystore -// - java keystore password -func getImportCABundleScript() string { - return ` - function jks_import_ca_bundle { - CA_FILE=$1 - KEYSTORE_PATH=$2 - KEYSTORE_PASSWORD=$3 - - if [ ! -f $CA_FILE ]; then - # CA bundle file doesn't exist, skip it - echo "Failed to import CA certificates from ${CA_FILE}. File doesn't exist" - return - fi - - bundle_name=$(basename $CA_FILE) - certs_imported=0 - cert_index=0 - tmp_file=/tmp/cert.pem - is_cert=false - while IFS= read -r line; do - if [ "$line" == "-----BEGIN CERTIFICATE-----" ]; then - # Start copying a new certificate - is_cert=true - cert_index=$((cert_index+1)) - # Reset destination file and add header line - echo $line > ${tmp_file} - elif [ "$line" == "-----END CERTIFICATE-----" ]; then - # End of the certificate is reached, add it to trust store - is_cert=false - echo $line >> ${tmp_file} - keytool -importcert -alias "${bundle_name}_${cert_index}" -keystore $KEYSTORE_PATH -file $tmp_file -storepass $KEYSTORE_PASSWORD -noprompt && \ - certs_imported=$((certs_imported+1)) - elif [ "$is_cert" == true ]; then - # In the middle of a certificate, copy line to target file - echo $line >> ${tmp_file} - fi - done < "$CA_FILE" - echo "Imported ${certs_imported} certificates from ${CA_FILE}" - # Clean up - rm -f $tmp_file - } - ` -} diff --git a/pkg/deploy/identity-provider/deployment_keycloak_test.go b/pkg/deploy/identity-provider/deployment_keycloak_test.go deleted file mode 100644 index 1dad62b11..000000000 --- a/pkg/deploy/identity-provider/deployment_keycloak_test.go +++ /dev/null @@ -1,330 +0,0 @@ -// -// Copyright (c) 2019-2021 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 identityprovider - -import ( - "context" - "os" - "reflect" - - "github.com/eclipse-che/che-operator/pkg/util" - "github.com/google/go-cmp/cmp" - - "github.com/eclipse-che/che-operator/pkg/deploy" - - orgv1 "github.com/eclipse-che/che-operator/api/v1" - appsv1 "k8s.io/api/apps/v1" - 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/kubernetes/scheme" - "sigs.k8s.io/controller-runtime/pkg/client/fake" - logf "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/log/zap" - - "testing" -) - -func TestDeployment(t *testing.T) { - type testCase struct { - name string - initObjects []runtime.Object - memoryLimit string - memoryRequest string - cpuLimit string - cpuRequest string - cheCluster *orgv1.CheCluster - } - - testCases := []testCase{ - { - name: "Test default limits", - initObjects: []runtime.Object{}, - memoryLimit: deploy.DefaultIdentityProviderMemoryLimit, - memoryRequest: deploy.DefaultIdentityProviderMemoryRequest, - cpuLimit: deploy.DefaultIdentityProviderCpuLimit, - cpuRequest: deploy.DefaultIdentityProviderCpuRequest, - cheCluster: &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "che-cluster", - Namespace: "eclipse-che", - }, - }, - }, - { - name: "Test custom limits", - initObjects: []runtime.Object{}, - cpuLimit: "250m", - cpuRequest: "150m", - memoryLimit: "250Mi", - memoryRequest: "150Mi", - cheCluster: &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "che-cluster", - Namespace: "eclipse-che", - }, - Spec: orgv1.CheClusterSpec{ - Auth: orgv1.CheClusterSpecAuth{ - IdentityProviderContainerResources: orgv1.ResourcesCustomSettings{ - Limits: orgv1.Resources{ - Cpu: "250m", - Memory: "250Mi", - }, - Requests: orgv1.Resources{ - Cpu: "150m", - Memory: "150Mi", - }, - }, - }, - }, - }, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - logf.SetLogger(zap.New(zap.WriteTo(os.Stdout), zap.UseDevMode(true))) - orgv1.SchemeBuilder.AddToScheme(scheme.Scheme) - testCase.initObjects = append(testCase.initObjects) - cli := fake.NewFakeClientWithScheme(scheme.Scheme, testCase.initObjects...) - - deployContext := &deploy.DeployContext{ - CheCluster: testCase.cheCluster, - ClusterAPI: deploy.ClusterAPI{ - Client: cli, - Scheme: scheme.Scheme, - }, - Proxy: &deploy.Proxy{}, - } - - deployment, err := GetSpecKeycloakDeployment(deployContext, nil) - if err != nil { - t.Fatalf("Error creating deployment: %v", err) - } - - util.CompareResources(deployment, - util.TestExpectedResources{ - MemoryLimit: testCase.memoryLimit, - MemoryRequest: testCase.memoryRequest, - CpuRequest: testCase.cpuRequest, - CpuLimit: testCase.cpuLimit, - }, - t) - - util.ValidateSecurityContext(deployment, t) - }) - } -} - -func TestMountGitHubOAuthEnvVar(t *testing.T) { - type testCase struct { - name string - initObjects []runtime.Object - cheCluster *orgv1.CheCluster - expectedIdEnv corev1.EnvVar - expectedSecretEnv corev1.EnvVar - } - - testCases := []testCase{ - { - name: "Test", - initObjects: []runtime.Object{ - &corev1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: "Secret", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "github-oauth-config", - Namespace: "eclipse-che", - Labels: map[string]string{ - "app.kubernetes.io/part-of": "che.eclipse.org", - "app.kubernetes.io/component": "oauth-scm-configuration", - }, - Annotations: map[string]string{ - "che.eclipse.org/oauth-scm-server": "github", - }, - }, - Data: map[string][]byte{ - "id": []byte("some__id"), - "secret": []byte("some_secret"), - }, - }, - }, - cheCluster: &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "che-cluster", - Namespace: "eclipse-che", - }, - }, - expectedIdEnv: corev1.EnvVar{ - Name: "GITHUB_CLIENT_ID", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: "id", - LocalObjectReference: corev1.LocalObjectReference{ - Name: "github-oauth-config", - }, - }, - }, - }, - expectedSecretEnv: corev1.EnvVar{ - Name: "GITHUB_SECRET", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: "secret", - LocalObjectReference: corev1.LocalObjectReference{ - Name: "github-oauth-config", - }, - }, - }, - }, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - logf.SetLogger(zap.New(zap.WriteTo(os.Stdout), zap.UseDevMode(true))) - orgv1.SchemeBuilder.AddToScheme(scheme.Scheme) - testCase.initObjects = append(testCase.initObjects) - cli := fake.NewFakeClientWithScheme(scheme.Scheme, testCase.initObjects...) - - deployContext := &deploy.DeployContext{ - CheCluster: testCase.cheCluster, - ClusterAPI: deploy.ClusterAPI{ - Client: cli, - Scheme: scheme.Scheme, - }, - Proxy: &deploy.Proxy{}, - } - - deployment, err := GetSpecKeycloakDeployment(deployContext, nil) - if err != nil { - t.Fatalf("Error creating deployment: %v", err) - } - - container := &deployment.Spec.Template.Spec.Containers[0] - idEnv := util.FindEnv(container.Env, "GITHUB_CLIENT_ID") - if !reflect.DeepEqual(testCase.expectedIdEnv, *idEnv) { - t.Errorf("Expected Env and Env returned from API server differ (-want, +got): %v", cmp.Diff(testCase.expectedIdEnv, idEnv)) - } - - secretEnv := util.FindEnv(container.Env, "GITHUB_SECRET") - if !reflect.DeepEqual(testCase.expectedSecretEnv, *secretEnv) { - t.Errorf("Expected CR and CR returned from API server differ (-want, +got): %v", cmp.Diff(testCase.expectedSecretEnv, secretEnv)) - } - }) - } -} - -func TestSyncKeycloakDeploymentToCluster(t *testing.T) { - orgv1.SchemeBuilder.AddToScheme(scheme.Scheme) - cli := fake.NewFakeClientWithScheme(scheme.Scheme) - deployContext := &deploy.DeployContext{ - CheCluster: &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", - Name: "eclipse-che", - }, - }, - ClusterAPI: deploy.ClusterAPI{ - Client: cli, - NonCachingClient: cli, - Scheme: scheme.Scheme, - }, - Proxy: &deploy.Proxy{}, - } - - // initial sync - done, err := SyncKeycloakDeploymentToCluster(deployContext) - if !done || err != nil { - t.Fatalf("Failed to sync deployment: %v", err) - } - - actual := &appsv1.Deployment{} - err = cli.Get(context.TODO(), types.NamespacedName{Name: deploy.IdentityProviderName, Namespace: "eclipse-che"}, actual) - if err != nil { - t.Fatalf("Failed to sync deployment: %v", err) - } - - // create certs configmap - err = cli.Create(context.TODO(), &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "ca-certs-merged", - Namespace: "eclipse-che", - // Go client set up resource version 1 itself on object creation. - // ResourceVersion: "1", - }, - }) - if err != nil { - t.Fatalf("Failed to create configmap: %v", err) - } - - // create self-signed-certificate secret - err = cli.Create(context.TODO(), &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "self-signed-certificate", - Namespace: "eclipse-che", - // Go client set up resource version 1 itself on object creation. - // ResourceVersion: "1", - }, - }) - if err != nil { - t.Fatalf("Failed to create secret: %v", err) - } - - caSecret := &corev1.Secret{} - err = cli.Get(context.TODO(), types.NamespacedName{ - Name: "self-signed-certificate", - Namespace: "eclipse-che", - }, caSecret) - if err != nil { - t.Fatalf("Failed to get secret: %v", err) - } - // Let's really change something. Go client will increment secret resource version itself(from '1' to '2'). - caSecret.GenerateName = "test" - - err = cli.Update(context.TODO(), caSecret) - if err != nil { - t.Fatalf("Failed to update secret: %s", err.Error()) - } - - // sync a new deployment - _, err = SyncKeycloakDeploymentToCluster(deployContext) - if err != nil { - t.Fatalf("Failed to sync deployment: %v", err) - } - - // sync twice to be sure update done correctly - done, err = SyncKeycloakDeploymentToCluster(deployContext) - if !done || err != nil { - t.Fatalf("Failed to sync deployment: %v", err) - } - - actual = &appsv1.Deployment{} - err = cli.Get(context.TODO(), types.NamespacedName{Name: deploy.IdentityProviderName, Namespace: "eclipse-che"}, actual) - if err != nil { - t.Fatalf("Failed to sync deployment: %v", err) - } - - // check ca-certs-merged revision - cmRevision := util.FindEnv(actual.Spec.Template.Spec.Containers[0].Env, "CM_REVISION") - if cmRevision == nil || cmRevision.Value != "1" { - t.Fatalf("Failed to sync deployment") - } - - // check self-signed-certificate secret revision - if actual.ObjectMeta.Annotations["che.self-signed-certificate.version"] != "2" { - t.Fatalf("Failed to sync deployment") - } -} diff --git a/pkg/deploy/identity-provider/exec.go b/pkg/deploy/identity-provider/exec.go deleted file mode 100644 index 6598572eb..000000000 --- a/pkg/deploy/identity-provider/exec.go +++ /dev/null @@ -1,186 +0,0 @@ -// -// Copyright (c) 2019-2021 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 identityprovider - -import ( - "bytes" - "io/ioutil" - "text/template" - - v1 "github.com/eclipse-che/che-operator/api/v1" - "github.com/eclipse-che/che-operator/pkg/deploy" - "github.com/eclipse-che/che-operator/pkg/util" - "github.com/sirupsen/logrus" -) - -func GetKeycloakProvisionCommand(cr *v1.CheCluster) (command string, err error) { - cheFlavor := deploy.DefaultCheFlavor(cr) - requiredActions := (map[bool]string{true: "\"UPDATE_PASSWORD\"", false: ""})[cr.Spec.Auth.UpdateAdminPassword] - keycloakTheme := (map[bool]string{true: "rh-sso", false: "che"})[cheFlavor == "codeready"] - realmDisplayName := (map[bool]string{true: "CodeReady Workspaces", false: "Eclipse Che"})[cheFlavor == "codeready"] - - script, keycloakRealm, keycloakClientId, keycloakUserEnvVar, keycloakPasswordEnvVar := getDefaults(cr) - data := struct { - Script string - KeycloakAdminUserName string - KeycloakAdminPassword string - KeycloakRealm string - RealmDisplayName string - KeycloakTheme string - CheHost string - KeycloakClientId string - RequiredActions string - }{ - script, - keycloakUserEnvVar, - keycloakPasswordEnvVar, - keycloakRealm, - realmDisplayName, - keycloakTheme, - cr.Spec.Server.CheHost, - keycloakClientId, - requiredActions, - } - return getCommandFromTemplateFile(cr, "/tmp/keycloak-provision.sh", data) -} - -func GetKeycloakUpdateCommand(cr *v1.CheCluster) (command string, err error) { - cheFlavor := deploy.DefaultCheFlavor(cr) - realmDisplayName := (map[bool]string{true: "CodeReady Workspaces", false: "Eclipse Che"})[cheFlavor == "codeready"] - - script, keycloakRealm, keycloakClientId, keycloakUserEnvVar, keycloakPasswordEnvVar := getDefaults(cr) - data := struct { - Script string - KeycloakAdminUserName string - KeycloakAdminPassword string - KeycloakRealm string - RealmDisplayName string - CheHost string - KeycloakClientId string - }{ - script, - keycloakUserEnvVar, - keycloakPasswordEnvVar, - keycloakRealm, - realmDisplayName, - cr.Spec.Server.CheHost, - keycloakClientId, - } - return getCommandFromTemplateFile(cr, "/tmp/keycloak-update.sh", data) -} - -func GetOpenShiftIdentityProviderProvisionCommand(cr *v1.CheCluster, oAuthClientName string, oauthSecret string) (string, error) { - isOpenShift4 := util.IsOpenShift4 - providerId := (map[bool]string{true: "openshift-v4", false: "openshift-v3"})[isOpenShift4] - apiUrl, apiInternalUrl, err := util.GetOpenShiftAPIUrls() - if err != nil { - logrus.Errorf("Failed to auto-detect public OpenShift API URL. Configure it in Identity provider details page in Keycloak admin console: %s", err) - return "", err - } - - script, keycloakRealm, keycloakClientId, keycloakUserEnvVar, keycloakPasswordEnvVar := getDefaults(cr) - data := struct { - Script string - KeycloakAdminUserName string - KeycloakAdminPassword string - KeycloakRealm string - ProviderId string - OAuthClientName string - OauthSecret string - OpenShiftApiUrl string - KeycloakClientId string - }{ - script, - keycloakUserEnvVar, - keycloakPasswordEnvVar, - keycloakRealm, - providerId, - oAuthClientName, - oauthSecret, - map[bool]string{true: apiInternalUrl, false: apiUrl}[apiInternalUrl != ""], - keycloakClientId, - } - return getCommandFromTemplateFile(cr, "/tmp/oauth-provision.sh", data) -} - -func GetGitHubIdentityProviderCreateCommand(deployContext *deploy.DeployContext) (string, error) { - cr := deployContext.CheCluster - script, keycloakRealm, _, keycloakUserEnvVar, keycloakPasswordEnvVar := getDefaults(cr) - data := struct { - Script string - KeycloakAdminUserName string - KeycloakAdminPassword string - KeycloakRealm string - ProviderId string - }{ - script, - keycloakUserEnvVar, - keycloakPasswordEnvVar, - keycloakRealm, - "github", - } - return getCommandFromTemplateFile(cr, "/tmp/create-github-identity-provider.sh", data) -} - -func GetIdentityProviderDeleteCommand(cr *v1.CheCluster, identityProvider string) (string, error) { - script, keycloakRealm, _, keycloakUserEnvVar, keycloakPasswordEnvVar := getDefaults(cr) - data := struct { - Script string - KeycloakRealm string - KeycloakAdminUserName string - KeycloakAdminPassword string - ProviderId string - }{ - script, - keycloakRealm, - keycloakUserEnvVar, - keycloakPasswordEnvVar, - identityProvider, - } - return getCommandFromTemplateFile(cr, "/tmp/delete-identity-provider.sh", data) -} - -func getCommandFromTemplateFile(cr *v1.CheCluster, templateFile string, data interface{}) (string, error) { - cheFlavor := deploy.DefaultCheFlavor(cr) - - file, err := ioutil.ReadFile(templateFile) - if err != nil { - return "", err - } - - template, err := template.New("Template").Parse(string(file)) - if err != nil { - return "", err - } - - buffer := new(bytes.Buffer) - err = template.Execute(buffer, data) - if err != nil { - return "", err - } - - if cheFlavor == "che" { - return "cd /scripts && export JAVA_TOOL_OPTIONS=-Duser.home=. && " + buffer.String(), nil - } - return "cd /home/jboss && " + buffer.String(), nil -} - -func getDefaults(cr *v1.CheCluster) (string, string, string, string, string) { - cheFlavor := deploy.DefaultCheFlavor(cr) - keycloakRealm := util.GetValue(cr.Spec.Auth.IdentityProviderRealm, cheFlavor) - keycloakClientId := util.GetValue(cr.Spec.Auth.IdentityProviderClientId, cheFlavor+"-public") - if cheFlavor == "codeready" { - return "/opt/eap/bin/kcadm.sh", keycloakRealm, keycloakClientId, "${SSO_ADMIN_USERNAME}", "${SSO_ADMIN_PASSWORD}" - } - - return "/opt/jboss/keycloak/bin/kcadm.sh", keycloakRealm, keycloakClientId, "${KEYCLOAK_USER}", "${KEYCLOAK_PASSWORD}" -} diff --git a/pkg/deploy/identity-provider/identity_provider_reconciler.go b/pkg/deploy/identity-provider/identity_provider_reconciler.go index d4e0569fe..49bef3eae 100644 --- a/pkg/deploy/identity-provider/identity_provider_reconciler.go +++ b/pkg/deploy/identity-provider/identity_provider_reconciler.go @@ -12,22 +12,15 @@ package identityprovider import ( - "context" - "errors" "strings" - "github.com/eclipse-che/che-operator/pkg/deploy/gateway" "sigs.k8s.io/controller-runtime/pkg/reconcile" - orgv1 "github.com/eclipse-che/che-operator/api/v1" "github.com/eclipse-che/che-operator/pkg/deploy" - "github.com/eclipse-che/che-operator/pkg/deploy/expose" "github.com/eclipse-che/che-operator/pkg/util" "github.com/google/go-cmp/cmp/cmpopts" oauth "github.com/openshift/api/oauth/v1" "github.com/sirupsen/logrus" - appsv1 "k8s.io/api/apps/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" ) @@ -37,17 +30,6 @@ const ( var ( oAuthClientDiffOpts = cmpopts.IgnoreFields(oauth.OAuthClient{}, "TypeMeta", "ObjectMeta") - syncItems = []func(*deploy.DeployContext) (bool, error){ - syncService, - syncExposure, - SyncKeycloakDeploymentToCluster, - syncKeycloakResources, - syncOpenShiftIdentityProvider, - SyncGitHubOAuth, - } - - keycloakUpdated = false - keycloakCheHost = "" ) type IdentityProviderReconciler struct { @@ -59,35 +41,10 @@ func NewIdentityProviderReconciler() *IdentityProviderReconciler { } func (ip *IdentityProviderReconciler) Reconcile(ctx *deploy.DeployContext) (reconcile.Result, bool, error) { - if ctx.CheCluster.Spec.Auth.ExternalIdentityProvider { - keycloakURL := ctx.CheCluster.Spec.Auth.IdentityProviderURL - if ctx.CheCluster.Status.KeycloakURL != keycloakURL { - ctx.CheCluster.Status.KeycloakURL = keycloakURL - if err := deploy.UpdateCheCRStatus(ctx, "status: Keycloak URL", keycloakURL); err != nil { - return reconcile.Result{}, false, err - } - } - - return reconcile.Result{}, true, nil + done, err := syncNativeIdentityProviderItems(ctx) + if !done { + return reconcile.Result{Requeue: true}, false, err } - - if ctx.CheCluster.IsNativeUserModeEnabled() { - done, err := syncNativeIdentityProviderItems(ctx) - if !done { - return reconcile.Result{Requeue: true}, false, err - } - return reconcile.Result{}, true, nil - } - - for _, syncItem := range syncItems { - done, err := syncItem(ctx) - if !util.IsTestMode() { - if !done { - return reconcile.Result{}, false, err - } - } - } - return reconcile.Result{}, true, nil } @@ -108,93 +65,6 @@ func (ip *IdentityProviderReconciler) Finalize(ctx *deploy.DeployContext) bool { return true } -func syncService(deployContext *deploy.DeployContext) (bool, error) { - return deploy.SyncServiceToCluster( - deployContext, - deploy.IdentityProviderName, - []string{"http"}, - []int32{8080}, - deploy.IdentityProviderName) -} - -func syncExposure(deployContext *deploy.DeployContext) (bool, error) { - cr := deployContext.CheCluster - - protocol := (map[bool]string{ - true: "https", - false: "http"})[cr.Spec.Server.TlsSupport] - endpoint, done, err := expose.Expose( - deployContext, - deploy.IdentityProviderName, - cr.Spec.Auth.IdentityProviderRoute, - cr.Spec.Auth.IdentityProviderIngress, - createGatewayConfig(deployContext.CheCluster)) - if !done { - return false, err - } - - keycloakURL := protocol + "://" + endpoint - if cr.Spec.Auth.IdentityProviderURL != keycloakURL { - cr.Spec.Auth.IdentityProviderURL = keycloakURL - if err := deploy.UpdateCheCRSpec(deployContext, "Keycloak URL", keycloakURL); err != nil { - return false, err - } - - cr.Status.KeycloakURL = keycloakURL - if err := deploy.UpdateCheCRStatus(deployContext, "Keycloak URL", keycloakURL); err != nil { - return false, err - } - } - - return true, nil -} - -func syncKeycloakResources(deployContext *deploy.DeployContext) (bool, error) { - if !util.IsTestMode() { - cr := deployContext.CheCluster - if !cr.Status.KeycloakProvisoned { - if err := ProvisionKeycloakResources(deployContext); err != nil { - return false, err - } - - for { - cr.Status.KeycloakProvisoned = true - if err := deploy.UpdateCheCRStatus(deployContext, "status: provisioned with Keycloak", "true"); err != nil && - apierrors.IsConflict(err) { - - deploy.ReloadCheClusterCR(deployContext) - continue - } - break - } - } - - // Updates keycloak if chehost has been changed - if !keycloakUpdated || keycloakCheHost != deployContext.CheCluster.Spec.Server.CheHost { - if _, err := util.K8sclient.ExecIntoPod( - deployContext.CheCluster, - deploy.IdentityProviderName, - GetKeycloakUpdateCommand, - "Update redirect URI-s and webOrigins"); err != nil { - return false, err - } else { - keycloakUpdated = true - keycloakCheHost = deployContext.CheCluster.Spec.Server.CheHost - } - } - } - - return true, nil -} - -func syncOpenShiftIdentityProvider(deployContext *deploy.DeployContext) (bool, error) { - cr := deployContext.CheCluster - if util.IsOpenShift && cr.IsOpenShiftOAuthEnabled() { - return SyncOpenShiftIdentityProviderItems(deployContext) - } - return true, nil -} - func syncNativeIdentityProviderItems(deployContext *deploy.DeployContext) (bool, error) { cr := deployContext.CheCluster @@ -222,55 +92,6 @@ func syncNativeIdentityProviderItems(deployContext *deploy.DeployContext) (bool, return true, nil } -func SyncOpenShiftIdentityProviderItems(deployContext *deploy.DeployContext) (bool, error) { - cr := deployContext.CheCluster - - if err := resolveOpenshiftOAuthClientName(deployContext); err != nil { - return false, err - } - if err := resolveOpenshiftOAuthClientSecret(deployContext); err != nil { - return false, err - } - - keycloakURL := cr.Spec.Auth.IdentityProviderURL - cheFlavor := deploy.DefaultCheFlavor(cr) - keycloakRealm := util.GetValue(cr.Spec.Auth.IdentityProviderRealm, cheFlavor) - oAuthClient := getKeycloakOAuthClientSpec(cr.Spec.Auth.OAuthClientName, cr.Spec.Auth.OAuthSecret, keycloakURL, keycloakRealm, util.IsOpenShift4) - provisioned, err := deploy.Sync(deployContext, oAuthClient, oAuthClientDiffOpts) - if !provisioned { - return false, err - } - - if !util.IsTestMode() { - if !cr.Status.OpenShiftoAuthProvisioned { - // note that this uses the instance.Spec.Auth.IdentityProviderRealm and instance.Spec.Auth.IdentityProviderClientId. - // because we're not doing much of a change detection on those fields, we can't react on them changing here. - _, err := util.K8sclient.ExecIntoPod( - cr, - deploy.IdentityProviderName, - func(cr *orgv1.CheCluster) (string, error) { - return GetOpenShiftIdentityProviderProvisionCommand(cr, cr.Spec.Auth.OAuthClientName, cr.Spec.Auth.OAuthSecret) - }, - "Create OpenShift identity provider") - if err != nil { - return false, err - } - - for { - cr.Status.OpenShiftoAuthProvisioned = true - if err := deploy.UpdateCheCRStatus(deployContext, "status: provisioned with OpenShift identity provider", "true"); err != nil && - apierrors.IsConflict(err) { - - deploy.ReloadCheClusterCR(deployContext) - continue - } - break - } - } - } - return true, nil -} - func resolveOpenshiftOAuthClientName(deployContext *deploy.DeployContext) error { cr := deployContext.CheCluster oAuthClientName := cr.Spec.Auth.OAuthClientName @@ -296,157 +117,3 @@ func resolveOpenshiftOAuthClientSecret(deployContext *deploy.DeployContext) erro } return nil } - -// SyncGitHubOAuth provisions GitHub OAuth if secret with annotation -// `che.eclipse.org/github-oauth-credentials=true` or `che.eclipse.org/oauth-scm-configuration=github` -// is mounted into a container -func SyncGitHubOAuth(deployContext *deploy.DeployContext) (bool, error) { - // get legacy secret - legacySecrets, err := deploy.GetSecrets(deployContext, map[string]string{ - deploy.KubernetesPartOfLabelKey: deploy.CheEclipseOrg, - deploy.KubernetesComponentLabelKey: deploy.IdentityProviderName + "-secret", - }, map[string]string{ - deploy.CheEclipseOrgGithubOAuthCredentials: "true", - }) - if err != nil { - return false, err - } - - secrets, err := deploy.GetSecrets(deployContext, map[string]string{ - deploy.KubernetesPartOfLabelKey: deploy.CheEclipseOrg, - deploy.KubernetesComponentLabelKey: deploy.OAuthScmConfiguration, - }, map[string]string{ - deploy.CheEclipseOrgOAuthScmServer: "github", - }) - - if err != nil { - return false, err - } else if len(secrets)+len(legacySecrets) > 1 { - return false, errors.New("More than 1 GitHub OAuth configuration secrets found") - } - - isGitHubOAuthCredentialsExists := len(secrets) == 1 || len(legacySecrets) == 1 - cr := deployContext.CheCluster - - if isGitHubOAuthCredentialsExists { - if !cr.Status.GitHubOAuthProvisioned { - if !util.IsTestMode() { - _, err := util.K8sclient.ExecIntoPod( - cr, - deploy.IdentityProviderName, - func(cr *orgv1.CheCluster) (string, error) { - return GetGitHubIdentityProviderCreateCommand(deployContext) - }, - "Create GitHub OAuth") - if err != nil { - return false, err - } - } - - cr.Status.GitHubOAuthProvisioned = true - if err := deploy.UpdateCheCRStatus(deployContext, "status: GitHub OAuth provisioned", "true"); err != nil { - return false, err - } - } - } else { - if cr.Status.GitHubOAuthProvisioned { - if !util.IsTestMode() { - _, err := util.K8sclient.ExecIntoPod( - cr, - deploy.IdentityProviderName, - func(cr *orgv1.CheCluster) (string, error) { - return GetIdentityProviderDeleteCommand(cr, "github") - }, - "Delete GitHub OAuth") - if err != nil { - return false, err - } - } - - cr.Status.GitHubOAuthProvisioned = false - if err := deploy.UpdateCheCRStatus(deployContext, "status: GitHub OAuth provisioned", "false"); err != nil { - return false, err - } - } - } - - return true, nil -} - -func deleteIdentityProvider(ctx *deploy.DeployContext) error { - if !ctx.CheCluster.IsOpenShiftOAuthEnabled() && ctx.CheCluster.Status.OpenShiftoAuthProvisioned == true { - keycloakDeployment := &appsv1.Deployment{} - if err := ctx.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: deploy.IdentityProviderName, Namespace: ctx.CheCluster.Namespace}, keycloakDeployment); err != nil { - logrus.Errorf("Deployment %s not found: %s", keycloakDeployment.Name, err.Error()) - } - - providerName := "openshift-v3" - if util.IsOpenShift4 { - providerName = "openshift-v4" - } - - _, err := util.K8sclient.ExecIntoPod( - ctx.CheCluster, - keycloakDeployment.Name, - func(cr *orgv1.CheCluster) (string, error) { - return GetIdentityProviderDeleteCommand(ctx.CheCluster, providerName) - }, - "delete OpenShift identity provider") - if err == nil { - oAuthClient := &oauth.OAuthClient{} - oAuthClientName := ctx.CheCluster.Spec.Auth.OAuthClientName - err := deploy.DeleteObjectWithFinalizer(ctx, types.NamespacedName{Name: oAuthClientName}, &oauth.OAuthClient{}, OAuthFinalizerName) - if err != nil { - logrus.Errorf("Failed to delete %s %s: %s", oAuthClient.Kind, oAuthClient.Name, err.Error()) - } - - for { - ctx.CheCluster.Status.OpenShiftoAuthProvisioned = false - if err := deploy.UpdateCheCRStatus(ctx, "OpenShiftoAuthProvisioned", "false"); err != nil { - if apierrors.IsConflict(err) { - deploy.ReloadCheClusterCR(ctx) - continue - } - } - break - } - - for { - ctx.CheCluster.Spec.Auth.OAuthSecret = "" - ctx.CheCluster.Spec.Auth.OAuthClientName = "" - updateFields := map[string]string{ - "oAuthSecret": "", - "oAuthClientName": "", - } - - if err := deploy.UpdateCheCRSpecByFields(ctx, updateFields); err != nil { - if apierrors.IsConflict(err) { - deploy.ReloadCheClusterCR(ctx) - continue - } - } - break - } - - return nil - } - return err - } - - return nil -} - -func createGatewayConfig(cheCluster *orgv1.CheCluster) *gateway.TraefikConfig { - cfg := gateway.CreateCommonTraefikConfig( - deploy.IdentityProviderName, - "PathPrefix(`/auth`)", - 10, - "http://"+deploy.IdentityProviderName+":8080", - []string{}) - - if util.IsOpenShift && cheCluster.IsNativeUserModeEnabled() { - cfg.AddAuthHeaderRewrite(deploy.IdentityProviderName) - } - - return cfg -} diff --git a/pkg/deploy/identity-provider/identity_provider_reconciler_test.go b/pkg/deploy/identity-provider/identity_provider_reconciler_test.go deleted file mode 100644 index 1106850e8..000000000 --- a/pkg/deploy/identity-provider/identity_provider_reconciler_test.go +++ /dev/null @@ -1,211 +0,0 @@ -// -// Copyright (c) 2019-2021 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 identityprovider - -import ( - "os" - "reflect" - - "github.com/eclipse-che/che-operator/pkg/deploy" - - "github.com/google/go-cmp/cmp" - - orgv1 "github.com/eclipse-che/che-operator/api/v1" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/client-go/kubernetes/scheme" - "sigs.k8s.io/controller-runtime/pkg/client/fake" - logf "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/log/zap" - - "testing" -) - -func TestSyncGitHubOAuth(t *testing.T) { - type testCase struct { - name string - initCR *orgv1.CheCluster - expectedCR *orgv1.CheCluster - initObjects []runtime.Object - } - - testCases := []testCase{ - { - name: "Should provision GitHub OAuth with legacy secret", - initCR: &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "che-cluster", - Namespace: "eclipse-che", - ResourceVersion: "0", - }, - }, - expectedCR: &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "che-cluster", - Namespace: "eclipse-che", - ResourceVersion: "1", - }, - Status: orgv1.CheClusterStatus{ - GitHubOAuthProvisioned: true, - }, - }, - initObjects: []runtime.Object{ - &corev1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: "Secret", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "github-credentials", - Namespace: "eclipse-che", - Labels: map[string]string{ - deploy.KubernetesPartOfLabelKey: deploy.CheEclipseOrg, - deploy.KubernetesComponentLabelKey: "keycloak-secret", - }, - Annotations: map[string]string{ - deploy.CheEclipseOrgGithubOAuthCredentials: "true", - }, - }, - Data: map[string][]byte{ - "key": []byte("key-data"), - }, - }, - }, - }, - { - name: "Should provision GitHub OAuth", - initCR: &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "che-cluster", - Namespace: "eclipse-che", - ResourceVersion: "0", - }, - }, - expectedCR: &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "che-cluster", - Namespace: "eclipse-che", - ResourceVersion: "1", - }, - Status: orgv1.CheClusterStatus{ - GitHubOAuthProvisioned: true, - }, - }, - initObjects: []runtime.Object{ - &corev1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: "Secret", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "github-oauth-config", - Namespace: "eclipse-che", - Labels: map[string]string{ - "app.kubernetes.io/part-of": "che.eclipse.org", - "app.kubernetes.io/component": "oauth-scm-configuration", - }, - Annotations: map[string]string{ - "che.eclipse.org/oauth-scm-server": "github", - }, - }, - }, - }, - }, - { - name: "Should not provision GitHub OAuth", - initCR: &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "che-cluster", - Namespace: "eclipse-che", - ResourceVersion: "0", - }, - }, - expectedCR: &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "che-cluster", - Namespace: "eclipse-che", - ResourceVersion: "0", - }, - }, - initObjects: []runtime.Object{ - &corev1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: "Secret", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "github-credentials", - Namespace: "eclipse-che", - Labels: map[string]string{ - deploy.KubernetesPartOfLabelKey: deploy.CheEclipseOrg, - deploy.KubernetesComponentLabelKey: "keycloak-secret", - }, - }, - Data: map[string][]byte{ - "key": []byte("key-data"), - }, - }, - }, - }, - { - name: "Should delete GitHub OAuth", - initCR: &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "che-cluster", - Namespace: "eclipse-che", - ResourceVersion: "0", - }, - Status: orgv1.CheClusterStatus{ - GitHubOAuthProvisioned: true, - }, - }, - expectedCR: &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "che-cluster", - Namespace: "eclipse-che", - ResourceVersion: "1", - }, - Status: orgv1.CheClusterStatus{ - GitHubOAuthProvisioned: false, - }, - }, - initObjects: []runtime.Object{}, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - logf.SetLogger(zap.New(zap.WriteTo(os.Stdout), zap.UseDevMode(true))) - orgv1.SchemeBuilder.AddToScheme(scheme.Scheme) - testCase.initObjects = append(testCase.initObjects, testCase.initCR) - cli := fake.NewFakeClientWithScheme(scheme.Scheme, testCase.initObjects...) - - deployContext := &deploy.DeployContext{ - CheCluster: testCase.initCR, - ClusterAPI: deploy.ClusterAPI{ - Client: cli, - Scheme: scheme.Scheme, - }, - } - - _, err := SyncGitHubOAuth(deployContext) - if err != nil { - t.Fatalf("Error mounting secret: %v", err) - } - - if !reflect.DeepEqual(testCase.expectedCR, testCase.initCR) { - t.Errorf("Expected CR and CR returned from API server differ (-want, +got): %v", cmp.Diff(testCase.expectedCR, testCase.initCR)) - } - }) - } -} diff --git a/pkg/deploy/identity-provider/identity_provider_util.go b/pkg/deploy/identity-provider/identity_provider_util.go index a3c09cf53..3565bc0af 100644 --- a/pkg/deploy/identity-provider/identity_provider_util.go +++ b/pkg/deploy/identity-provider/identity_provider_util.go @@ -12,33 +12,10 @@ package identityprovider import ( - "strings" - oauth "github.com/openshift/api/oauth/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func getKeycloakOAuthClientSpec(name string, oauthSecret string, keycloakURL string, keycloakRealm string, isOpenShift4 bool) *oauth.OAuthClient { - providerName := "openshift-v3" - if isOpenShift4 { - providerName = "openshift-v4" - } - - redirectURLSuffix := "/realms/" + keycloakRealm + "/broker/" + providerName + "/endpoint" - redirectURIs := []string{ - keycloakURL + redirectURLSuffix, - } - - keycloakURL = strings.NewReplacer("https://", "", "http://", "").Replace(keycloakURL) - if !strings.Contains(keycloakURL, "://") { - redirectURIs = []string{ - "http://" + keycloakURL + redirectURLSuffix, - "https://" + keycloakURL + redirectURLSuffix, - } - } - return getOAuthClientSpec(name, oauthSecret, redirectURIs) -} - func getOAuthClientSpec(name string, oauthSecret string, redirectURIs []string) *oauth.OAuthClient { return &oauth.OAuthClient{ TypeMeta: metav1.TypeMeta{ diff --git a/pkg/deploy/identity-provider/keycloak_readiness.go b/pkg/deploy/identity-provider/keycloak_readiness.go deleted file mode 100644 index a34e840b8..000000000 --- a/pkg/deploy/identity-provider/keycloak_readiness.go +++ /dev/null @@ -1,56 +0,0 @@ -// -// Copyright (c) 2019-2021 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 identityprovider - -import ( - "fmt" - - "github.com/eclipse-che/che-operator/pkg/deploy" - "github.com/eclipse-che/che-operator/pkg/util" - corev1 "k8s.io/api/core/v1" -) - -func GetWaitForKeycloakInitContainer(deployContext *deploy.DeployContext) (*corev1.Container, error) { - keycloakReadinessCheckerImage := deploy.DefaultKeycloakImage(deployContext.CheCluster) - imagePullPolicy := corev1.PullPolicy(deploy.DefaultPullPolicyFromDockerImage(keycloakReadinessCheckerImage)) - - return &corev1.Container{ - Name: "wait-for-identity-provider", - Image: keycloakReadinessCheckerImage, - ImagePullPolicy: imagePullPolicy, - Command: []string{ - "/bin/sh", - "-c", - getCheckKeycloakReadinessScript(deployContext), - }, - }, nil -} - -func getCheckKeycloakReadinessScript(deployContext *deploy.DeployContext) string { - cheFlavor := deploy.DefaultCheFlavor(deployContext.CheCluster) - realmName := util.GetValue(deployContext.CheCluster.Spec.Auth.IdentityProviderRealm, cheFlavor) - url := fmt.Sprintf("%s/realms/%s/.well-known/openid-configuration", deployContext.CheCluster.Status.KeycloakURL, realmName) - // URL example: https://keycloak-eclipse-che.192.168.99.254.nip.io/auth/realms/che/.well-known/openid-configuration - - script := ` - while : ; do - response_code=$(curl --connect-timeout 5 -kI %s 2>/dev/null | awk 'NR==1 {print $2}') - if [ "$response_code" == "200" ]; then - break - fi - echo 'waiting for Identity provider' - sleep 2 - done - ` - - return fmt.Sprintf(script, url) -} diff --git a/pkg/deploy/image-puller/imagepuller_test.go b/pkg/deploy/image-puller/imagepuller_test.go index 60a593445..a2a0b3acb 100644 --- a/pkg/deploy/image-puller/imagepuller_test.go +++ b/pkg/deploy/image-puller/imagepuller_test.go @@ -123,9 +123,6 @@ func TestImagePullerConfiguration(t *testing.T) { ConfigMapName: "k8s-image-puller", }, }, - Server: orgv1.CheClusterSpecServer{ - ServerExposureStrategy: "multi-host", - }, }, }, initObjects: []runtime.Object{ @@ -557,9 +554,6 @@ func InitCheCRWithImagePullerEnabled() *orgv1.CheCluster { ImagePuller: orgv1.CheClusterSpecImagePuller{ Enable: true, }, - Server: orgv1.CheClusterSpecServer{ - ServerExposureStrategy: "multi-host", - }, }, } } @@ -582,9 +576,6 @@ func InitCheCRWithImagePullerFinalizer() *orgv1.CheCluster { ImagePuller: orgv1.CheClusterSpecImagePuller{ Enable: true, }, - Server: orgv1.CheClusterSpecServer{ - ServerExposureStrategy: "multi-host", - }, }, } } @@ -603,9 +594,6 @@ func InitCheCRWithImagePullerFinalizerAndDeletionTimestamp() *orgv1.CheCluster { ImagePuller: orgv1.CheClusterSpecImagePuller{ Enable: true, }, - Server: orgv1.CheClusterSpecServer{ - ServerExposureStrategy: "multi-host", - }, }, } } @@ -628,9 +616,6 @@ func ExpectedCheCRWithImagePullerFinalizer() *orgv1.CheCluster { ImagePuller: orgv1.CheClusterSpecImagePuller{ Enable: true, }, - Server: orgv1.CheClusterSpecServer{ - ServerExposureStrategy: "multi-host", - }, }, } } @@ -675,9 +660,6 @@ func InitCheCRWithImagePullerEnabledAndDefaultValuesSet() *orgv1.CheCluster { ConfigMapName: "k8s-image-puller", }, }, - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: util.NewBoolPointer(false), - }, }, } } @@ -704,9 +686,6 @@ func InitCheCRWithImagePullerEnabledAndImagesSet(images string) *orgv1.CheCluste Images: images, }, }, - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: util.NewBoolPointer(false), - }, }, } } @@ -728,9 +707,6 @@ func InitCheCRWithImagePullerEnabledAndNewValuesSet() *orgv1.CheCluster { ConfigMapName: "k8s-image-puller-trigger-update", }, }, - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: util.NewBoolPointer(false), - }, }, } } diff --git a/pkg/deploy/ingres_test.go b/pkg/deploy/ingres_test.go index 743d166e8..b06173d62 100644 --- a/pkg/deploy/ingres_test.go +++ b/pkg/deploy/ingres_test.go @@ -19,6 +19,7 @@ import ( orgv1 "github.com/eclipse-che/che-operator/api/v1" networking "k8s.io/api/networking/v1" + v1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" @@ -52,11 +53,6 @@ func TestIngressSpec(t *testing.T) { Namespace: "eclipse-che", Name: cheFlavor, }, - Spec: orgv1.CheClusterSpec{ - K8s: orgv1.CheClusterSpecK8SOnly{ - SingleHostExposureType: GatewaySingleHostExposureType, - }, - }, } testCases := []testCase{ @@ -90,7 +86,7 @@ func TestIngressSpec(t *testing.T) { "kubernetes.io/ingress.class": "nginx", "nginx.ingress.kubernetes.io/proxy-connect-timeout": "3600", "nginx.ingress.kubernetes.io/proxy-read-timeout": "3600", - "nginx.ingress.kubernetes.io/ssl-redirect": "false", + "nginx.ingress.kubernetes.io/ssl-redirect": "true", "nginx.ingress.kubernetes.io/proxy-buffer-size": "16k", "nginx.org/websocket-services": "che-host", "annotation-key": "annotation-value", @@ -101,6 +97,7 @@ func TestIngressSpec(t *testing.T) { APIVersion: networking.SchemeGroupVersion.String(), }, Spec: networking.IngressSpec{ + TLS: []v1.IngressTLS{{Hosts: []string{"test-host"}}}, Rules: []networking.IngressRule{ { Host: "test-host", @@ -158,7 +155,7 @@ func TestIngressSpec(t *testing.T) { "nginx.ingress.kubernetes.io/proxy-connect-timeout": "3600", "nginx.ingress.kubernetes.io/proxy-read-timeout": "3600", "nginx.ingress.kubernetes.io/proxy-buffer-size": "16k", - "nginx.ingress.kubernetes.io/ssl-redirect": "false", + "nginx.ingress.kubernetes.io/ssl-redirect": "true", "nginx.org/websocket-services": "che-host", "annotation-key": "annotation-value", }, @@ -168,6 +165,7 @@ func TestIngressSpec(t *testing.T) { APIVersion: networking.SchemeGroupVersion.String(), }, Spec: networking.IngressSpec{ + TLS: []v1.IngressTLS{{Hosts: []string{"test-host"}}}, Rules: []networking.IngressRule{ { Host: "test-host", @@ -224,7 +222,7 @@ func TestIngressSpec(t *testing.T) { "nginx.ingress.kubernetes.io/proxy-connect-timeout": "3600", "nginx.ingress.kubernetes.io/proxy-read-timeout": "3600", "nginx.ingress.kubernetes.io/proxy-buffer-size": "16k", - "nginx.ingress.kubernetes.io/ssl-redirect": "false", + "nginx.ingress.kubernetes.io/ssl-redirect": "true", "nginx.org/websocket-services": "che-host", "annotation-key": "annotation-value", }, @@ -234,6 +232,7 @@ func TestIngressSpec(t *testing.T) { APIVersion: networking.SchemeGroupVersion.String(), }, Spec: networking.IngressSpec{ + TLS: []v1.IngressTLS{{Hosts: []string{"test-host"}}}, Rules: []networking.IngressRule{ { Host: "test-host", diff --git a/pkg/deploy/ingress.go b/pkg/deploy/ingress.go index 55c0af2d2..6d196eb90 100644 --- a/pkg/deploy/ingress.go +++ b/pkg/deploy/ingress.go @@ -14,7 +14,6 @@ package deploy import ( "reflect" "sort" - "strconv" orgv1 "github.com/eclipse-che/che-operator/api/v1" "github.com/eclipse-che/che-operator/pkg/util" @@ -63,9 +62,6 @@ func GetIngressSpec( component string) (ingressUrl string, i *networking.Ingress) { cheFlavor := DefaultCheFlavor(deployContext.CheCluster) - tlsSupport := deployContext.CheCluster.Spec.Server.TlsSupport - ingressStrategy := util.GetServerExposureStrategy(deployContext.CheCluster) - exposureType := GetSingleHostExposureType(deployContext.CheCluster) ingressDomain := deployContext.CheCluster.Spec.K8s.IngressDomain tlsSecretName := deployContext.CheCluster.Spec.K8s.TlsSecretName ingressClass := util.GetValue(deployContext.CheCluster.Spec.K8s.IngressClass, DefaultIngressClass) @@ -73,24 +69,18 @@ func GetIngressSpec( MergeLabels(labels, ingressCustomSettings.Labels) pathType := networking.PathTypeImplementationSpecific - if tlsSupport { - // for server and dashboard ingresses - if (component == cheFlavor || component == cheFlavor+"-dashboard") && deployContext.CheCluster.Spec.Server.CheHostTLSSecret != "" { - tlsSecretName = deployContext.CheCluster.Spec.Server.CheHostTLSSecret - } + // for server and dashboard ingresses + if (component == cheFlavor || component == cheFlavor+"-dashboard") && deployContext.CheCluster.Spec.Server.CheHostTLSSecret != "" { + tlsSecretName = deployContext.CheCluster.Spec.Server.CheHostTLSSecret } if host == "" { - if ingressStrategy == "multi-host" { - host = component + "-" + deployContext.CheCluster.Namespace + "." + ingressDomain - } else if ingressStrategy == "single-host" { - host = ingressDomain - } + host = ingressDomain } var endpointPath, ingressPath string if path == "" { - endpointPath, ingressPath = evaluatePath(component, ingressStrategy) + endpointPath, ingressPath = evaluatePath(component) } else { ingressPath = path endpointPath = path @@ -100,15 +90,14 @@ func GetIngressSpec( "kubernetes.io/ingress.class": ingressClass, "nginx.ingress.kubernetes.io/proxy-read-timeout": "3600", "nginx.ingress.kubernetes.io/proxy-connect-timeout": "3600", - "nginx.ingress.kubernetes.io/ssl-redirect": strconv.FormatBool(tlsSupport), + "nginx.ingress.kubernetes.io/ssl-redirect": "true", } - if ingressStrategy != "multi-host" && (component == DevfileRegistryName || component == PluginRegistryName) { + if component == DevfileRegistryName || component == PluginRegistryName { annotations["nginx.ingress.kubernetes.io/rewrite-target"] = "/$1" } // Set bigger proxy buffer size to prevent 502 auth error. - if component == IdentityProviderName || exposureType == GatewaySingleHostExposureType { - annotations["nginx.ingress.kubernetes.io/proxy-buffer-size"] = "16k" - } + annotations["nginx.ingress.kubernetes.io/proxy-buffer-size"] = "16k" + for k, v := range ingressCustomSettings.Annotations { annotations[k] = v } @@ -176,13 +165,11 @@ func GetIngressSpec( ingress.ObjectMeta.Annotations["nginx.org/websocket-services"] = serviceName } - if tlsSupport { - ingress.Spec.TLS = []networking.IngressTLS{ - { - Hosts: []string{host}, - SecretName: tlsSecretName, - }, - } + ingress.Spec.TLS = []networking.IngressTLS{ + { + Hosts: []string{host}, + SecretName: tlsSecretName, + }, } return host + endpointPath, ingress @@ -190,30 +177,17 @@ func GetIngressSpec( // evaluatePath evaluates ingress path (one which is used for rule) // and endpoint path (one which client should use during endpoint accessing) -func evaluatePath(component, ingressStrategy string) (endpointPath, ingressPath string) { - if ingressStrategy == "multi-host" { +func evaluatePath(component string) (endpointPath, ingressPath string) { + switch component { + case DevfileRegistryName: + fallthrough + case PluginRegistryName: + endpointPath = "/" + component + ingressPath = endpointPath + "/(.*)" + default: ingressPath = "/" endpointPath = "/" - // Keycloak needs special rule in multihost. It's exposed on / which redirects to /auth - // clients which does not support redirects needs /auth be explicitely set - if component == IdentityProviderName { - endpointPath = "/auth" - } - } else { - switch component { - case IdentityProviderName: - endpointPath = "/auth" - ingressPath = endpointPath + "/(.*)" - case DevfileRegistryName: - fallthrough - case PluginRegistryName: - endpointPath = "/" + component - ingressPath = endpointPath + "/(.*)" - default: - ingressPath = "/" - endpointPath = "/" - } - } + return endpointPath, ingressPath } diff --git a/pkg/deploy/migration/on-reconcile-one-time-migration.go b/pkg/deploy/migration/on-reconcile-one-time-migration.go index ebcf4fd34..8269a3af6 100644 --- a/pkg/deploy/migration/on-reconcile-one-time-migration.go +++ b/pkg/deploy/migration/on-reconcile-one-time-migration.go @@ -91,8 +91,6 @@ func (m *Migrator) migrate(ctx *deploy.DeployContext) (bool, error) { // - spec.server.gitSelfSignedCert ('che-git-self-signed-cert' config map) // - spec.server.proxySecret // - spec.database.chePostgresSecret -// - spec.auth.identityProviderSecret -// - spec.auth.identityProviderPostgresSecret // - spec.k8s.tlsSecretName // Note, most of the objects above are autogenerated and do not require any migration, // but to handle the case when some were created manually or operator updated, the check is done here. @@ -134,19 +132,6 @@ func addPartOfCheLabeltoUserDefinedObjects(ctx *deploy.DeployContext) error { } } - // Keycloak related secrets - if ctx.CheCluster.Spec.Auth.IdentityProviderSecret != "" { - if err := addPartOfCheLabelToSecret(ctx, ctx.CheCluster.Spec.Auth.IdentityProviderSecret); err != nil { - return err - } - } - - if ctx.CheCluster.Spec.Auth.IdentityProviderPostgresSecret != "" { - if err := addPartOfCheLabelToSecret(ctx, ctx.CheCluster.Spec.Auth.IdentityProviderPostgresSecret); err != nil { - return err - } - } - // Legacy config map with additional CA certificates if ctx.CheCluster.Spec.Server.ServerTrustStoreConfigMapName != "" { if err := addPartOfCheLabelToConfigMap(ctx, ctx.CheCluster.Spec.Server.ServerTrustStoreConfigMapName); err != nil { diff --git a/pkg/deploy/openshift-oauth/init_test.go b/pkg/deploy/openshift-oauth/init_test.go deleted file mode 100644 index f7d1b47de..000000000 --- a/pkg/deploy/openshift-oauth/init_test.go +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright (c) 2019-2021 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 openshiftoauth - -import "github.com/eclipse-che/che-operator/pkg/deploy" - -func init() { - err := deploy.InitTestDefaultsFromDeployment("../../../config/manager/manager.yaml") - if err != nil { - panic(err) - } -} diff --git a/pkg/deploy/openshift-oauth/openshiftoauth.go b/pkg/deploy/openshift-oauth/openshiftoauth.go deleted file mode 100644 index 9294e3a70..000000000 --- a/pkg/deploy/openshift-oauth/openshiftoauth.go +++ /dev/null @@ -1,117 +0,0 @@ -// -// Copyright (c) 2012-2021 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 openshiftoauth - -import ( - "context" - "reflect" - "strconv" - - "github.com/eclipse-che/che-operator/pkg/deploy" - "github.com/eclipse-che/che-operator/pkg/util" - userv1 "github.com/openshift/api/user/v1" - "github.com/sirupsen/logrus" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/reconcile" -) - -const ( - warningNoIdentityProvidersMessage = "No Openshift identity providers." - - AddIdentityProviderMessage = "Openshift oAuth was disabled. How to add identity provider read in the Help Link:" - warningNoRealUsersMessage = "No real users. Openshift oAuth was disabled. How to add new user read in the Help Link:" - failedUnableToGetOpenshiftUsers = "Unable to get users on the OpenShift cluster." - - howToAddIdentityProviderLinkOS4 = "https://docs.openshift.com/container-platform/latest/authentication/understanding-identity-provider.html#identity-provider-overview_understanding-identity-provider" - howToConfigureOAuthLinkOS3 = "https://docs.openshift.com/container-platform/3.11/install_config/configuring_authentication.html" -) - -type OpenShiftOAuth struct { - openShiftOAuthUser *OpenShiftOAuthUser -} - -func NewOpenShiftOAuth(openShiftOAuthUser *OpenShiftOAuthUser) *OpenShiftOAuth { - return &OpenShiftOAuth{ - openShiftOAuthUser, - } -} - -func (oo *OpenShiftOAuth) Reconcile(ctx *deploy.DeployContext) (reconcile.Result, bool, error) { - if util.IsOpenShift && ctx.CheCluster.Spec.Auth.OpenShiftoAuth == nil { - return oo.enableOpenShiftOAuth(ctx) - } - - return reconcile.Result{}, true, nil -} - -func (oo *OpenShiftOAuth) Finalize(ctx *deploy.DeployContext) bool { - return true -} - -func (oo *OpenShiftOAuth) enableOpenShiftOAuth(ctx *deploy.DeployContext) (reconcile.Result, bool, error) { - oauth := false - if util.IsOpenShift4 { - openshitOAuth, err := GetOpenshiftOAuth(ctx) - if err != nil { - logrus.Error("Unable to get Openshift oAuth. Cause: " + err.Error()) - } else { - if len(openshitOAuth.Spec.IdentityProviders) > 0 { - oauth = true - } else if ctx.CheCluster.IsNativeUserModeEnabled() { - // enable OpenShift OAuth without adding initial OpenShift OAuth user - // since kubeadmin is a valid user for native user mode - oauth = true - } else if ctx.CheCluster.IsOpenShiftOAuthUserConfigured() { - provisioned, err := oo.openShiftOAuthUser.Create(ctx) - if err != nil { - logrus.Error(warningNoIdentityProvidersMessage + " Operator tried to create initial OpenShift OAuth user for HTPasswd identity provider, but failed. Cause: " + err.Error()) - logrus.Info("To enable OpenShift OAuth, please add identity provider first: " + howToAddIdentityProviderLinkOS4) - - // Don't try to create initial user any more, che-operator shouldn't hang on this step. - ctx.CheCluster.Spec.Auth.InitialOpenShiftOAuthUser = nil - if err := deploy.UpdateCheCRStatus(ctx, "initialOpenShiftOAuthUser", ""); err != nil { - return reconcile.Result{}, false, err - } - oauth = false - } else { - if !provisioned { - // let's wait some time - return reconcile.Result{}, false, err - } - oauth = true - } - } - } - } else { // Openshift 3 - users := &userv1.UserList{} - listOptions := &client.ListOptions{} - if err := ctx.ClusterAPI.NonCachingClient.List(context.TODO(), users, listOptions); err != nil { - logrus.Error(failedUnableToGetOpenshiftUsers + " Cause: " + err.Error()) - } else { - oauth = len(users.Items) >= 1 - if !oauth { - logrus.Warn(warningNoRealUsersMessage + " " + howToConfigureOAuthLinkOS3) - } - } - } - - newOAuthValue := util.NewBoolPointer(oauth) - if !reflect.DeepEqual(newOAuthValue, ctx.CheCluster.Spec.Auth.OpenShiftoAuth) { - ctx.CheCluster.Spec.Auth.OpenShiftoAuth = newOAuthValue - if err := deploy.UpdateCheCRSpec(ctx, "openShiftoAuth", strconv.FormatBool(oauth)); err != nil { - return reconcile.Result{Requeue: true}, false, err - } - } - - return reconcile.Result{}, true, nil -} diff --git a/pkg/deploy/openshift-oauth/openshiftoauth_test.go b/pkg/deploy/openshift-oauth/openshiftoauth_test.go deleted file mode 100644 index 31ebc03c1..000000000 --- a/pkg/deploy/openshift-oauth/openshiftoauth_test.go +++ /dev/null @@ -1,234 +0,0 @@ -// -// Copyright (c) 2012-2021 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 openshiftoauth - -import ( - "os" - "testing" - - orgv1 "github.com/eclipse-che/che-operator/api/v1" - "github.com/eclipse-che/che-operator/pkg/deploy" - "github.com/eclipse-che/che-operator/pkg/util" - configv1 "github.com/openshift/api/config/v1" - oauthv1 "github.com/openshift/api/oauth/v1" - userv1 "github.com/openshift/api/user/v1" - "github.com/stretchr/testify/assert" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/utils/pointer" - logf "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/log/zap" -) - -var ( - nonEmptyUserList = &userv1.UserList{ - Items: []userv1.User{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "user1", - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "user2", - }, - }, - }, - } - oAuthWithNoIdentityProviders = &configv1.OAuth{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", - }, - } - oAuthWithIdentityProvider = &configv1.OAuth{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", - }, - Spec: configv1.OAuthSpec{ - IdentityProviders: []configv1.IdentityProvider{ - { - Name: "htpasswd", - }, - }, - }, - } - proxy = &configv1.Proxy{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", - }, - } -) - -func TestCaseAutoDetectOAuth(t *testing.T) { - type testCase struct { - name string - initObjects []runtime.Object - isOpenshift4 bool - initialOAuthValue *bool - oAuthExpected *bool - initialOpenShiftOAuthUserEnabled *bool - } - - testCases := []testCase{ - { - name: "che-operator should auto enable oAuth when Che CR with oAuth nil value on the Openshift 3 with users > 0", - initObjects: []runtime.Object{ - nonEmptyUserList, - &oauthv1.OAuthClient{}, - }, - isOpenshift4: false, - initialOAuthValue: nil, - oAuthExpected: pointer.BoolPtr(true), - }, - { - name: "che-operator should auto disable oAuth when Che CR with nil oAuth on the Openshift 3 with no users", - initObjects: []runtime.Object{ - &userv1.UserList{}, - &oauthv1.OAuthClient{}, - }, - isOpenshift4: false, - initialOAuthValue: pointer.BoolPtr(false), - oAuthExpected: pointer.BoolPtr(false), - }, - { - name: "che-operator should respect oAuth = true even if there no users on the Openshift 3", - initObjects: []runtime.Object{ - &userv1.UserList{}, - &oauthv1.OAuthClient{}, - }, - isOpenshift4: false, - initialOAuthValue: pointer.BoolPtr(true), - oAuthExpected: pointer.BoolPtr(true), - }, - { - name: "che-operator should respect oAuth = true even if there are some users on the Openshift 3", - initObjects: []runtime.Object{ - nonEmptyUserList, - &oauthv1.OAuthClient{}, - }, - isOpenshift4: false, - initialOAuthValue: pointer.BoolPtr(true), - oAuthExpected: pointer.BoolPtr(true), - }, - { - name: "che-operator should respect oAuth = false even if there are some users on the Openshift 3", - initObjects: []runtime.Object{ - nonEmptyUserList, - &oauthv1.OAuthClient{}, - }, - isOpenshift4: false, - initialOAuthValue: pointer.BoolPtr(false), - oAuthExpected: pointer.BoolPtr(false), - }, - { - name: "che-operator should respect oAuth = false even if no users on the Openshift 3", - initObjects: []runtime.Object{ - &userv1.UserList{}, - &oauthv1.OAuthClient{}, - }, - isOpenshift4: false, - initialOAuthValue: pointer.BoolPtr(false), - oAuthExpected: pointer.BoolPtr(false), - }, - { - name: "che-operator should auto enable oAuth when Che CR with nil value on the Openshift 4 with identity providers", - initObjects: []runtime.Object{ - oAuthWithIdentityProvider, - proxy, - }, - isOpenshift4: true, - initialOAuthValue: nil, - oAuthExpected: pointer.BoolPtr(true), - }, - { - name: "che-operator should respect oAuth = true even if there no indentity providers on the Openshift 4", - initObjects: []runtime.Object{ - oAuthWithNoIdentityProviders, - proxy, - }, - isOpenshift4: true, - initialOAuthValue: pointer.BoolPtr(true), - oAuthExpected: pointer.BoolPtr(true), - initialOpenShiftOAuthUserEnabled: pointer.BoolPtr(true), - }, - { - name: "che-operator should respect oAuth = true even if there are some users on the Openshift 4", - initObjects: []runtime.Object{ - oAuthWithIdentityProvider, - proxy, - }, - isOpenshift4: false, - initialOAuthValue: pointer.BoolPtr(true), - oAuthExpected: pointer.BoolPtr(true), - initialOpenShiftOAuthUserEnabled: pointer.BoolPtr(true), - }, - { - name: "che-operator should respect oAuth = false even if there no indentity providers on the Openshift 4", - initObjects: []runtime.Object{ - oAuthWithNoIdentityProviders, - proxy, - }, - isOpenshift4: false, - initialOAuthValue: pointer.BoolPtr(false), - oAuthExpected: pointer.BoolPtr(false), - }, - { - name: "che-operator should respect oAuth = false even if there are some users on the Openshift 4", - initObjects: []runtime.Object{ - oAuthWithIdentityProvider, - proxy, - }, - isOpenshift4: false, - initialOAuthValue: pointer.BoolPtr(false), - oAuthExpected: pointer.BoolPtr(false), - }, - { - name: "che-operator should auto disable oAuth on error retieve identity providers", - initObjects: []runtime.Object{}, - isOpenshift4: false, - initialOAuthValue: nil, - initialOpenShiftOAuthUserEnabled: pointer.BoolPtr(true), - oAuthExpected: pointer.BoolPtr(false), - }, - } - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - logf.SetLogger(zap.New(zap.WriteTo(os.Stdout), zap.UseDevMode(true))) - - checluster := &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: os.Getenv("CHE_FLAVOR"), - Namespace: "eclipse-che", - }, - Spec: orgv1.CheClusterSpec{ - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: testCase.initialOAuthValue, - InitialOpenShiftOAuthUser: testCase.initialOpenShiftOAuthUserEnabled, - }, - }, - } - - util.IsOpenShift = true - util.IsOpenShift4 = testCase.isOpenshift4 - deployContext := deploy.GetTestDeployContext(checluster, testCase.initObjects) - - openShiftOAuth := NewOpenShiftOAuth(NewOpenShiftOAuthUser()) - _, done, err := openShiftOAuth.Reconcile(deployContext) - assert.Nil(t, err) - assert.True(t, done) - - assert.NotNil(t, deployContext.CheCluster.Spec.Auth.OpenShiftoAuth) - assert.Equal(t, *testCase.oAuthExpected, *deployContext.CheCluster.Spec.Auth.OpenShiftoAuth) - }) - } -} diff --git a/pkg/deploy/openshift-oauth/openshiftoauth_user.go b/pkg/deploy/openshift-oauth/openshiftoauth_user.go deleted file mode 100644 index 6149675fb..000000000 --- a/pkg/deploy/openshift-oauth/openshiftoauth_user.go +++ /dev/null @@ -1,321 +0,0 @@ -// -// Copyright (c) 2019-2021 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 openshiftoauth - -import ( - "context" - "fmt" - - "github.com/eclipse-che/che-operator/pkg/deploy" - "github.com/eclipse-che/che-operator/pkg/util" - configv1 "github.com/openshift/api/config/v1" - userv1 "github.com/openshift/api/user/v1" - "github.com/sirupsen/logrus" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/reconcile" -) - -const ( - HtpasswdIdentityProviderName = "htpasswd-eclipse-che" - HtpasswdSecretName = "htpasswd-eclipse-che" - OcConfigNamespace = "openshift-config" - OpenShiftOAuthUserCredentialsSecret = "openshift-oauth-user-credentials" - OpenshiftOauthUserFinalizerName = "openshift-oauth-user.finalizers.che.eclipse.org" -) - -type IOpenShiftOAuthUser interface { - Create(ctx *deploy.DeployContext) (bool, error) - Delete(ctx *deploy.DeployContext) error -} - -type OpenShiftOAuthUser struct { - userPassword string - runnable util.Runnable - - deploy.Reconcilable - IOpenShiftOAuthUser -} - -func NewOpenShiftOAuthUser() *OpenShiftOAuthUser { - return &OpenShiftOAuthUser{ - userPassword: util.GeneratePasswd(6), - runnable: util.NewRunnable(), // real process, mock for tests - } -} - -func (oou *OpenShiftOAuthUser) Reconcile(ctx *deploy.DeployContext) (reconcile.Result, bool, error) { - if !util.IsOpenShift4 { - return reconcile.Result{}, true, nil - } - - if ctx.CheCluster.IsOpenShiftOAuthUserConfigured() && - (ctx.CheCluster.Spec.Auth.OpenShiftoAuth == nil || *ctx.CheCluster.Spec.Auth.OpenShiftoAuth) { - - done, err := oou.Create(ctx) - if !done { - return reconcile.Result{Requeue: true}, false, err - } - return reconcile.Result{}, true, nil - } - - if ctx.CheCluster.IsOpenShiftOAuthUserMustBeDeleted() { - if done := oou.Delete(ctx); !done { - return reconcile.Result{}, false, fmt.Errorf("unable to delete initial OpenShift OAuth user from a cluster") - } - - return reconcile.Result{}, true, nil - } - - return reconcile.Result{}, true, nil -} - -func (oou *OpenShiftOAuthUser) Finalize(ctx *deploy.DeployContext) bool { - if util.IsOpenShift4 { - return oou.Delete(ctx) - } - - return true -} - -// Creates new htpasswd provider with initial user with Che flavor name -// if Openshift cluster hasn't got identity providers then does nothing. -// It usefull for good first user experience. -// User can't use kube:admin or system:admin user in the Openshift oAuth when DevWorkspace engine disabled. -// That's why we provide initial user for good first meeting with Eclipse Che. -func (oou *OpenShiftOAuthUser) Create(ctx *deploy.DeployContext) (bool, error) { - userName := deploy.DefaultCheFlavor(ctx.CheCluster) - - // read existed password from the secret (operator has been restarted case) - oAuthUserCredentialsSecret, err := oou.getOpenShiftOAuthUserCredentialsSecret(ctx) - if err != nil { - return false, err - } else if oAuthUserCredentialsSecret != nil { - oou.userPassword = string(oAuthUserCredentialsSecret.Data["password"]) - } - - // create a new secret with user's credentials - if oAuthUserCredentialsSecret == nil { - initialUserSecretData := map[string][]byte{"user": []byte(userName), "password": []byte(oou.userPassword)} - done, err := deploy.SyncSecretToCluster(ctx, OpenShiftOAuthUserCredentialsSecret, OcConfigNamespace, initialUserSecretData) - if !done { - return false, err - } - } - - htpasswdSecretExists, _ := deploy.Get(ctx, types.NamespacedName{Name: HtpasswdSecretName, Namespace: OcConfigNamespace}, &corev1.Secret{}) - if !htpasswdSecretExists { - htpasswdFileContent, err := oou.generateHtPasswdUserInfo(userName, oou.userPassword) - if err != nil { - return false, err - } - - htpasswdFileSecretData := map[string][]byte{"htpasswd": []byte(htpasswdFileContent)} - done, err := deploy.SyncSecretToCluster(ctx, HtpasswdSecretName, OcConfigNamespace, htpasswdFileSecretData) - if !done { - return false, err - } - } - - oAuth, err := GetOpenshiftOAuth(ctx) - if err != nil { - return false, err - } - - if err := appendIdentityProvider(oAuth, ctx.ClusterAPI.NonCachingClient); err != nil { - return false, err - } - - if ctx.CheCluster.Status.OpenShiftOAuthUserCredentialsSecret != OpenShiftOAuthUserCredentialsSecret { - ctx.CheCluster.Status.OpenShiftOAuthUserCredentialsSecret = OpenShiftOAuthUserCredentialsSecret - if err := deploy.UpdateCheCRStatus(ctx, "openShiftOAuthUserCredentialsSecret", OpenShiftOAuthUserCredentialsSecret); err != nil { - return false, err - } - } - - if err := deploy.AppendFinalizer(ctx, OpenshiftOauthUserFinalizerName); err != nil { - return false, err - } - - return true, nil -} - -// Removes initial user, htpasswd provider, htpasswd secret and Che secret with username and password. -func (oou *OpenShiftOAuthUser) Delete(ctx *deploy.DeployContext) bool { - done := true - - oAuth, err := GetOpenshiftOAuth(ctx) - if err != nil { - done = false - logrus.Errorf("Failed to get Openshift OAuth, cause: %v", err) - } - - userName := deploy.DefaultCheFlavor(ctx.CheCluster) - if _, err := deploy.Delete(ctx, types.NamespacedName{Name: userName}, &userv1.User{}); err != nil { - done = false - logrus.Errorf("Failed to delete Openshift user '%s', cause: %v", userName, err) - } - - identityName := HtpasswdIdentityProviderName + ":" + userName - if _, err := deploy.Delete(ctx, types.NamespacedName{Name: identityName}, &userv1.Identity{}); err != nil { - done = false - logrus.Errorf("Failed to delete identity '%s', cause: %v", identityName, err) - } - - if err := deleteIdentityProvider(oAuth, ctx.ClusterAPI.NonCachingClient); err != nil { - done = false - logrus.Errorf("Failed to delete identity provider', cause: %v", err) - } - - if _, err = deploy.Delete(ctx, types.NamespacedName{Name: HtpasswdSecretName, Namespace: OcConfigNamespace}, &corev1.Secret{}); err != nil { - done = false - logrus.Errorf("Failed to delete HTpasswd secret '%s', cause: %v", HtpasswdSecretName, err) - } - - // legacy secret in the current namespace - if _, err = deploy.DeleteNamespacedObject(ctx, OpenShiftOAuthUserCredentialsSecret, &corev1.Secret{}); err != nil { - done = false - logrus.Errorf("Failed to delete legacy Openshift OAuth credentials secret '%s', cause: %v", OpenShiftOAuthUserCredentialsSecret, err) - } - - if _, err = deploy.Delete(ctx, types.NamespacedName{Name: OpenShiftOAuthUserCredentialsSecret, Namespace: OcConfigNamespace}, &corev1.Secret{}); err != nil { - done = false - logrus.Errorf("Failed to delete Openshift OAuth credentials secret '%s', cause: %v", OpenShiftOAuthUserCredentialsSecret, err) - } - - if err := deploy.DeleteFinalizer(ctx, OpenshiftOauthUserFinalizerName); err != nil { - done = false - logrus.Errorf("Error deleting finalizer: %v", err) - } - - ctx.CheCluster.Status.OpenShiftOAuthUserCredentialsSecret = "" - if err := deploy.UpdateCheCRStatus(ctx, "openShiftOAuthUserCredentialsSecret", ""); err != nil { - done = false - logrus.Errorf("Filed to update openShiftOAuthUserCredentialsSecret in CR status, cause: %v", err) - } - - // set 'openShiftoAuth:nil` to reenable on the following reconcile loop (if possible) - ctx.CheCluster.Spec.Auth.InitialOpenShiftOAuthUser = nil - ctx.CheCluster.Spec.Auth.OpenShiftoAuth = nil - updateFields := map[string]string{ - "openShiftoAuth": "nil", - "initialOpenShiftOAuthUser": "nil", - } - - if err := deploy.UpdateCheCRSpecByFields(ctx, updateFields); err != nil { - done = false - logrus.Errorf("Filed to update OAuth field in CR, cause: %v", err) - } - - return done -} - -func (oou *OpenShiftOAuthUser) generateHtPasswdUserInfo(userName string, password string) (string, error) { - if util.IsTestMode() { - return "", nil - } - - err := oou.runnable.Run("htpasswd", "-nbB", userName, password) - if err != nil { - return "", err - } - - if len(oou.runnable.GetStdErr()) > 0 { - return "", fmt.Errorf("Failed to generate data for HTPasswd identity provider: %s", oou.runnable.GetStdErr()) - } - return oou.runnable.GetStdOut(), nil -} - -// Gets OpenShift user credentials secret from from the secret from: -// - openshift-config namespace -// - eclipse-che namespace -func (oou *OpenShiftOAuthUser) getOpenShiftOAuthUserCredentialsSecret(ctx *deploy.DeployContext) (*corev1.Secret, error) { - secret := &corev1.Secret{} - - exists, err := deploy.Get(ctx, types.NamespacedName{Name: OpenShiftOAuthUserCredentialsSecret, Namespace: OcConfigNamespace}, secret) - if err != nil { - return nil, err - } else if exists { - return secret, nil - } - - exists, err = deploy.GetNamespacedObject(ctx, OpenShiftOAuthUserCredentialsSecret, secret) - if err != nil { - return nil, err - } else if exists { - return secret, nil - } - - return nil, nil -} - -func identityProviderExists(providerName string, oAuth *configv1.OAuth) bool { - if len(oAuth.Spec.IdentityProviders) == 0 { - return false - } - for _, identityProvider := range oAuth.Spec.IdentityProviders { - if identityProvider.Name == providerName { - return true - } - } - return false -} - -func appendIdentityProvider(oAuth *configv1.OAuth, runtimeClient client.Client) error { - htpasswdProvider := newHtpasswdProvider() - if !identityProviderExists(htpasswdProvider.Name, oAuth) { - oauthPatch := client.MergeFrom(oAuth.DeepCopy()) - - oAuth.Spec.IdentityProviders = append(oAuth.Spec.IdentityProviders, *htpasswdProvider) - - if err := runtimeClient.Patch(context.TODO(), oAuth, oauthPatch); err != nil { - return err - } - } - - return nil -} - -func newHtpasswdProvider() *configv1.IdentityProvider { - return &configv1.IdentityProvider{ - Name: HtpasswdIdentityProviderName, - MappingMethod: configv1.MappingMethodClaim, - IdentityProviderConfig: configv1.IdentityProviderConfig{ - Type: "HTPasswd", - HTPasswd: &configv1.HTPasswdIdentityProvider{ - FileData: configv1.SecretNameReference{Name: HtpasswdSecretName}, - }, - }, - } -} - -func deleteIdentityProvider(oAuth *configv1.OAuth, runtimeClient client.Client) error { - logrus.Info("Delete initial user httpasswd provider from the oAuth") - - oauthPatch := client.MergeFrom(oAuth.DeepCopy()) - ips := oAuth.Spec.IdentityProviders - for i, ip := range ips { - if ip.Name == HtpasswdIdentityProviderName { - // remove provider from slice - oAuth.Spec.IdentityProviders = append(ips[:i], ips[i+1:]...) - break - } - } - - if err := runtimeClient.Patch(context.TODO(), oAuth, oauthPatch); err != nil { - return err - } - - return nil -} diff --git a/pkg/deploy/openshift-oauth/openshiftoauth_user_test.go b/pkg/deploy/openshift-oauth/openshiftoauth_user_test.go deleted file mode 100644 index 6df519a90..000000000 --- a/pkg/deploy/openshift-oauth/openshiftoauth_user_test.go +++ /dev/null @@ -1,168 +0,0 @@ -// -// Copyright (c) 2019-2021 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 openshiftoauth - -import ( - "context" - "os" - "testing" - - orgv1 "github.com/eclipse-che/che-operator/api/v1" - "github.com/eclipse-che/che-operator/pkg/deploy" - "github.com/eclipse-che/che-operator/pkg/util" - oauth_config "github.com/openshift/api/config/v1" - userv1 "github.com/openshift/api/user/v1" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - logf "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/log/zap" -) - -const ( - testNamespace = "test-namespace" - testUserName = "test" -) - -func TestCreateInitialUser(t *testing.T) { - checluster := &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "eclipse-che", - Namespace: testNamespace, - }, - Spec: orgv1.CheClusterSpec{ - Server: orgv1.CheClusterSpecServer{ - CheFlavor: testUserName, - }, - }, - } - oAuth := &oauth_config.OAuth{ - ObjectMeta: v1.ObjectMeta{ - Name: "cluster", - }, - Spec: oauth_config.OAuthSpec{IdentityProviders: []oauth_config.IdentityProvider{}}, - } - logf.SetLogger(zap.New(zap.WriteTo(os.Stdout), zap.UseDevMode(true))) - ctx := deploy.GetTestDeployContext(checluster, []runtime.Object{oAuth}) - - openShiftOAuthUser := NewOpenShiftOAuthUser() - done, err := openShiftOAuthUser.Create(ctx) - assert.Nil(t, err) - assert.True(t, done) - - // Check created objects - expectedCheSecret := &corev1.Secret{} - err = ctx.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: OpenShiftOAuthUserCredentialsSecret, Namespace: OcConfigNamespace}, expectedCheSecret) - assert.Nil(t, err) - - expectedHtpasswsSecret := &corev1.Secret{} - err = ctx.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: HtpasswdSecretName, Namespace: OcConfigNamespace}, expectedHtpasswsSecret) - assert.Nil(t, err) - - expectedOAuth := &oauth_config.OAuth{} - err = ctx.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: "cluster"}, expectedOAuth) - assert.Nil(t, err) - assert.Equal(t, len(expectedOAuth.Spec.IdentityProviders), 1) - assert.True(t, util.ContainsString(checluster.Finalizers, OpenshiftOauthUserFinalizerName)) - - assert.Equal(t, checluster.Status.OpenShiftOAuthUserCredentialsSecret, OpenShiftOAuthUserCredentialsSecret) -} - -func TestDeleteInitialUser(t *testing.T) { - checluster := &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "eclipse-che", - Namespace: testNamespace, - }, - Spec: orgv1.CheClusterSpec{ - Server: orgv1.CheClusterSpecServer{ - CheFlavor: testUserName, - }, - }, - Status: orgv1.CheClusterStatus{ - OpenShiftOAuthUserCredentialsSecret: "some-secret", - }, - } - oAuth := &oauth_config.OAuth{ - ObjectMeta: v1.ObjectMeta{ - Name: "cluster", - }, - Spec: oauth_config.OAuthSpec{IdentityProviders: []oauth_config.IdentityProvider{*newHtpasswdProvider()}}, - } - cheSecret := &corev1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: "Secret", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: OpenShiftOAuthUserCredentialsSecret, - Namespace: OcConfigNamespace, - }, - } - htpasswdSecret := &corev1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: "Secret", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: HtpasswdSecretName, - Namespace: OcConfigNamespace, - }, - } - userIdentity := &userv1.Identity{ - ObjectMeta: metav1.ObjectMeta{ - Name: HtpasswdIdentityProviderName + ":" + testUserName, - }, - } - user := &userv1.User{ - ObjectMeta: metav1.ObjectMeta{ - Name: testUserName, - }, - } - - logf.SetLogger(zap.New(zap.WriteTo(os.Stdout), zap.UseDevMode(true))) - ctx := deploy.GetTestDeployContext(checluster, []runtime.Object{oAuth, cheSecret, htpasswdSecret, userIdentity, user}) - - openShiftOAuthUser := &OpenShiftOAuthUser{} - done := openShiftOAuthUser.Delete(ctx) - assert.True(t, done) - - expectedCheSecret := &corev1.Secret{} - err := ctx.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: OpenShiftOAuthUserCredentialsSecret, Namespace: OcConfigNamespace}, expectedCheSecret) - assert.True(t, errors.IsNotFound(err)) - - expectedHtpasswsSecret := &corev1.Secret{} - if err := ctx.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: HtpasswdSecretName, Namespace: OcConfigNamespace}, expectedHtpasswsSecret); !errors.IsNotFound(err) { - t.Errorf("Initial user secret should be deleted") - } - assert.True(t, errors.IsNotFound(err)) - - expectedUserIdentity := &userv1.Identity{} - err = ctx.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: HtpasswdIdentityProviderName + ":" + testUserName}, expectedUserIdentity) - assert.True(t, errors.IsNotFound(err)) - - expectedUser := &userv1.User{} - err = ctx.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: testUserName}, expectedUser) - assert.True(t, errors.IsNotFound(err)) - - expectedOAuth := &oauth_config.OAuth{} - err = ctx.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: "cluster"}, expectedOAuth) - assert.Nil(t, err) - assert.Equal(t, len(expectedOAuth.Spec.IdentityProviders), 0) - assert.False(t, util.ContainsString(checluster.Finalizers, OpenshiftOauthUserFinalizerName)) - assert.Empty(t, checluster.Status.OpenShiftOAuthUserCredentialsSecret) -} diff --git a/pkg/deploy/openshift-oauth/openshiftoauth_util.go b/pkg/deploy/openshift-oauth/openshiftoauth_util.go deleted file mode 100644 index 8905aa0bf..000000000 --- a/pkg/deploy/openshift-oauth/openshiftoauth_util.go +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2019-2021 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 openshiftoauth - -import ( - "github.com/eclipse-che/che-operator/pkg/deploy" - oauthv1 "github.com/openshift/api/config/v1" -) - -// Gets OpenShift OAuth. -func GetOpenshiftOAuth(ctx *deploy.DeployContext) (*oauthv1.OAuth, error) { - oAuth := &oauthv1.OAuth{} - if done, err := deploy.GetClusterObject(ctx, "cluster", oAuth); !done { - return nil, err - } - return oAuth, nil -} diff --git a/pkg/deploy/pluginregistry/pluginregistry.go b/pkg/deploy/pluginregistry/pluginregistry.go index 040983828..19ecf5f8d 100644 --- a/pkg/deploy/pluginregistry/pluginregistry.go +++ b/pkg/deploy/pluginregistry/pluginregistry.go @@ -95,18 +95,11 @@ func (p *PluginRegistryReconciler) ExposeEndpoint(ctx *deploy.DeployContext) (st return expose.Expose( ctx, deploy.PluginRegistryName, - ctx.CheCluster.Spec.Server.PluginRegistryRoute, - ctx.CheCluster.Spec.Server.PluginRegistryIngress, p.createGatewayConfig(ctx)) } func (p *PluginRegistryReconciler) updateStatus(endpoint string, ctx *deploy.DeployContext) (bool, error) { - var pluginRegistryURL string - if ctx.CheCluster.Spec.Server.TlsSupport { - pluginRegistryURL = "https://" + endpoint - } else { - pluginRegistryURL = "http://" + endpoint - } + pluginRegistryURL := "https://" + endpoint // append the API version to plugin registry if !strings.HasSuffix(pluginRegistryURL, "/") { diff --git a/pkg/deploy/pluginregistry/pluginregistry_test.go b/pkg/deploy/pluginregistry/pluginregistry_test.go index 9e0beac9c..3f0a5cf8b 100644 --- a/pkg/deploy/pluginregistry/pluginregistry_test.go +++ b/pkg/deploy/pluginregistry/pluginregistry_test.go @@ -16,7 +16,6 @@ import ( "github.com/eclipse-che/che-operator/pkg/util" "github.com/stretchr/testify/assert" - routev1 "github.com/openshift/api/route/v1" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" @@ -35,7 +34,6 @@ func TestPluginRegistryReconcile(t *testing.T) { assert.Nil(t, err) assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: "plugin-registry", Namespace: "eclipse-che"}, &corev1.Service{})) - assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: "plugin-registry", Namespace: "eclipse-che"}, &routev1.Route{})) assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: "plugin-registry", Namespace: "eclipse-che"}, &corev1.ConfigMap{})) assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: "plugin-registry", Namespace: "eclipse-che"}, &appsv1.Deployment{})) assert.NotEmpty(t, ctx.CheCluster.Status.PluginRegistryURL) diff --git a/pkg/deploy/postgres/postgres.go b/pkg/deploy/postgres/postgres.go index 10d7ac1ed..a9a591f63 100644 --- a/pkg/deploy/postgres/postgres.go +++ b/pkg/deploy/postgres/postgres.go @@ -12,7 +12,6 @@ package postgres import ( - "fmt" "strings" orgv1 "github.com/eclipse-che/che-operator/api/v1" @@ -20,7 +19,6 @@ import ( "github.com/eclipse-che/che-operator/pkg/util" "github.com/sirupsen/logrus" appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/reconcile" ) @@ -52,15 +50,6 @@ func (p *PostgresReconciler) Reconcile(ctx *deploy.DeployContext) (reconcile.Res return reconcile.Result{}, false, err } - if !ctx.CheCluster.Status.DbProvisoned { - if !util.IsTestMode() { // ignore in tests - done, err = p.provisionDB(ctx) - if !done { - return reconcile.Result{}, false, err - } - } - } - if ctx.CheCluster.Spec.Database.PostgresVersion == "" { if !util.IsTestMode() { // ignore in tests done, err := p.setDbVersion(ctx) @@ -111,40 +100,6 @@ func (p *PostgresReconciler) syncDeployment(ctx *deploy.DeployContext) (bool, er return deploy.SyncDeploymentSpecToCluster(ctx, specDeployment, deploy.DefaultDeploymentDiffOpts) } -func (p *PostgresReconciler) provisionDB(ctx *deploy.DeployContext) (bool, error) { - identityProviderPostgresPassword := ctx.CheCluster.Spec.Auth.IdentityProviderPostgresPassword - identityProviderPostgresSecret := ctx.CheCluster.Spec.Auth.IdentityProviderPostgresSecret - if identityProviderPostgresSecret != "" { - secret := &corev1.Secret{} - exists, err := deploy.GetNamespacedObject(ctx, identityProviderPostgresSecret, secret) - if err != nil { - return false, err - } else if !exists { - return false, fmt.Errorf("Secret '%s' not found", identityProviderPostgresSecret) - } - identityProviderPostgresPassword = string(secret.Data["password"]) - } - - _, err := util.K8sclient.ExecIntoPod( - ctx.CheCluster, - deploy.PostgresName, - func(cr *orgv1.CheCluster) (string, error) { - return getPostgresProvisionCommand(identityProviderPostgresPassword), nil - }, - "create Keycloak DB, user, privileges") - if err != nil { - return false, err - } - - ctx.CheCluster.Status.DbProvisoned = true - err = deploy.UpdateCheCRStatus(ctx, "status: provisioned with DB and user", "true") - if err != nil { - return false, err - } - - return true, nil -} - func (p *PostgresReconciler) setDbVersion(ctx *deploy.DeployContext) (bool, error) { postgresVersion, err := util.K8sclient.ExecIntoPod( ctx.CheCluster, @@ -167,14 +122,3 @@ func (p *PostgresReconciler) setDbVersion(ctx *deploy.DeployContext) (bool, erro return true, nil } - -func getPostgresProvisionCommand(identityProviderPostgresPassword string) (command string) { - command = "OUT=$(psql postgres -tAc \"SELECT 1 FROM pg_roles WHERE rolname='keycloak'\"); " + - "if [ $OUT -eq 1 ]; then echo \"DB exists\"; exit 0; fi " + - "&& psql -c \"CREATE USER keycloak WITH PASSWORD '" + identityProviderPostgresPassword + "'\" " + - "&& psql -c \"CREATE DATABASE keycloak\" " + - "&& psql -c \"GRANT ALL PRIVILEGES ON DATABASE keycloak TO keycloak\" " + - "&& psql -c \"ALTER USER ${POSTGRESQL_USER} WITH SUPERUSER\"" - - return command -} diff --git a/pkg/deploy/rbac/gateway_permissions.go b/pkg/deploy/rbac/gateway_permissions.go index 5c531bf97..f6dc537f5 100644 --- a/pkg/deploy/rbac/gateway_permissions.go +++ b/pkg/deploy/rbac/gateway_permissions.go @@ -35,23 +35,17 @@ func NewGatewayPermissionsReconciler() *GatewayPermissionsReconciler { } func (gp *GatewayPermissionsReconciler) Reconcile(ctx *deploy.DeployContext) (reconcile.Result, bool, error) { - if ctx.CheCluster.IsNativeUserModeEnabled() { - name := gp.gatewayPermissionsName(ctx.CheCluster) - if done, err := deploy.SyncClusterRoleToCluster(ctx, name, gp.getGatewayClusterRoleRules()); !done { - return reconcile.Result{Requeue: true}, false, err - } + name := gp.gatewayPermissionsName(ctx.CheCluster) + if done, err := deploy.SyncClusterRoleToCluster(ctx, name, gp.getGatewayClusterRoleRules()); !done { + return reconcile.Result{Requeue: true}, false, err + } - if done, err := deploy.SyncClusterRoleBindingToCluster(ctx, name, gateway.GatewayServiceName, name); !done { - return reconcile.Result{Requeue: true}, false, err - } + if done, err := deploy.SyncClusterRoleBindingToCluster(ctx, name, gateway.GatewayServiceName, name); !done { + return reconcile.Result{Requeue: true}, false, err + } - if err := deploy.AppendFinalizer(ctx, CheGatewayClusterPermissionsFinalizerName); err != nil { - return reconcile.Result{Requeue: true}, false, err - } - } else { - if done, err := gp.deleteGatewayPermissions(ctx); !done { - return reconcile.Result{Requeue: true}, false, err - } + if err := deploy.AppendFinalizer(ctx, CheGatewayClusterPermissionsFinalizerName); err != nil { + return reconcile.Result{Requeue: true}, false, err } return reconcile.Result{}, true, nil diff --git a/pkg/deploy/rbac/workspace_permissions_test.go b/pkg/deploy/rbac/workspace_permissions_test.go index 2cf7aa274..5e270f94f 100644 --- a/pkg/deploy/rbac/workspace_permissions_test.go +++ b/pkg/deploy/rbac/workspace_permissions_test.go @@ -22,7 +22,6 @@ import ( v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" - "k8s.io/utils/pointer" ) func TestReconcileWorkspacePermissions(t *testing.T) { @@ -47,9 +46,6 @@ func TestReconcileWorkspacePermissions(t *testing.T) { Server: orgv1.CheClusterSpecServer{ WorkspaceNamespaceDefault: "some-test-namespace", }, - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: pointer.BoolPtr(false), - }, }, }, }, @@ -67,9 +63,6 @@ func TestReconcileWorkspacePermissions(t *testing.T) { "CHE_INFRA_KUBERNETES_NAMESPACE_DEFAULT": "some-test-namespace", }, }, - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: pointer.BoolPtr(false), - }, }, }, }, diff --git a/pkg/deploy/route.go b/pkg/deploy/route.go index 6aaf63e09..154ce794f 100644 --- a/pkg/deploy/route.go +++ b/pkg/deploy/route.go @@ -83,7 +83,6 @@ func GetRouteSpec( component string) (*routev1.Route, error) { cheFlavor := DefaultCheFlavor(deployContext.CheCluster) - tlsSupport := deployContext.CheCluster.Spec.Server.TlsSupport labels := GetLabels(deployContext.CheCluster, component) MergeLabels(labels, routeCustomSettings.Labels) @@ -153,26 +152,24 @@ func GetRouteSpec( route.Spec.Host = fmt.Sprintf(HostNameTemplate, route.ObjectMeta.Name, route.ObjectMeta.Namespace, routeCustomSettings.Domain) } - if tlsSupport { - route.Spec.TLS = &routev1.TLSConfig{ - InsecureEdgeTerminationPolicy: routev1.InsecureEdgeTerminationPolicyRedirect, - Termination: routev1.TLSTerminationEdge, + route.Spec.TLS = &routev1.TLSConfig{ + InsecureEdgeTerminationPolicy: routev1.InsecureEdgeTerminationPolicyRedirect, + Termination: routev1.TLSTerminationEdge, + } + + // for server and dashboard ingresses + if (component == cheFlavor || component == cheFlavor+"-dashboard") && deployContext.CheCluster.Spec.Server.CheHostTLSSecret != "" { + secret := &corev1.Secret{} + namespacedName := types.NamespacedName{ + Namespace: deployContext.CheCluster.Namespace, + Name: deployContext.CheCluster.Spec.Server.CheHostTLSSecret, + } + if err := deployContext.ClusterAPI.Client.Get(context.TODO(), namespacedName, secret); err != nil { + return nil, err } - // for server and dashboard ingresses - if (component == cheFlavor || component == cheFlavor+"-dashboard") && deployContext.CheCluster.Spec.Server.CheHostTLSSecret != "" { - secret := &corev1.Secret{} - namespacedName := types.NamespacedName{ - Namespace: deployContext.CheCluster.Namespace, - Name: deployContext.CheCluster.Spec.Server.CheHostTLSSecret, - } - if err := deployContext.ClusterAPI.Client.Get(context.TODO(), namespacedName, secret); err != nil { - return nil, err - } - - route.Spec.TLS.Key = string(secret.Data["tls.key"]) - route.Spec.TLS.Certificate = string(secret.Data["tls.crt"]) - } + route.Spec.TLS.Key = string(secret.Data["tls.key"]) + route.Spec.TLS.Certificate = string(secret.Data["tls.crt"]) } return route, nil diff --git a/pkg/deploy/route_test.go b/pkg/deploy/route_test.go index 78d161110..76fbb1b32 100644 --- a/pkg/deploy/route_test.go +++ b/pkg/deploy/route_test.go @@ -84,6 +84,7 @@ func TestRouteSpec(t *testing.T) { Name: "che", Weight: &weight, }, + TLS: &routev1.TLSConfig{Termination: routev1.TLSTerminationEdge, InsecureEdgeTerminationPolicy: routev1.InsecureEdgeTerminationPolicyRedirect}, Port: &routev1.RoutePort{ TargetPort: intstr.IntOrString{ Type: intstr.Int, @@ -127,6 +128,7 @@ func TestRouteSpec(t *testing.T) { Name: "che", Weight: &weight, }, + TLS: &routev1.TLSConfig{Termination: routev1.TLSTerminationEdge, InsecureEdgeTerminationPolicy: routev1.InsecureEdgeTerminationPolicyRedirect}, Port: &routev1.RoutePort{ TargetPort: intstr.IntOrString{ Type: intstr.Int, diff --git a/pkg/deploy/server/chehost_reconciler.go b/pkg/deploy/server/chehost_reconciler.go index 03277c877..1ee809cb9 100644 --- a/pkg/deploy/server/chehost_reconciler.go +++ b/pkg/deploy/server/chehost_reconciler.go @@ -13,6 +13,7 @@ package server import ( "github.com/eclipse-che/che-operator/pkg/deploy" + "github.com/eclipse-che/che-operator/pkg/deploy/gateway" "github.com/eclipse-che/che-operator/pkg/util" routev1 "github.com/openshift/api/route/v1" networking "k8s.io/api/networking/v1" @@ -60,7 +61,7 @@ func (s *CheHostReconciler) getDefaultCheHost(ctx *deploy.DeployContext) (bool, getComponentName(ctx), "", "/", - getServerExposingServiceName(ctx.CheCluster), + gateway.GatewayServiceName, 8080, ctx.CheCluster.Spec.Server.CheServerRoute, getComponentName(ctx)) @@ -97,7 +98,6 @@ func (s *CheHostReconciler) syncCheService(ctx *deploy.DeployContext) (bool, err func (s CheHostReconciler) exposeCheEndpoint(ctx *deploy.DeployContext) (bool, error) { cheHost := "" - exposedServiceName := getServerExposingServiceName(ctx.CheCluster) if !util.IsOpenShift { _, done, err := deploy.SyncIngressToCluster( @@ -105,7 +105,7 @@ func (s CheHostReconciler) exposeCheEndpoint(ctx *deploy.DeployContext) (bool, e getComponentName(ctx), ctx.CheCluster.Spec.Server.CheHost, "", - exposedServiceName, + gateway.GatewayServiceName, 8080, ctx.CheCluster.Spec.Server.CheServerIngress, getComponentName(ctx)) @@ -132,7 +132,7 @@ func (s CheHostReconciler) exposeCheEndpoint(ctx *deploy.DeployContext) (bool, e getComponentName(ctx), customHost, "/", - exposedServiceName, + gateway.GatewayServiceName, 8080, ctx.CheCluster.Spec.Server.CheServerRoute, getComponentName(ctx)) diff --git a/pkg/deploy/server/default_values_reconciler.go b/pkg/deploy/server/default_values_reconciler.go index 268273a69..88966d5c6 100644 --- a/pkg/deploy/server/default_values_reconciler.go +++ b/pkg/deploy/server/default_values_reconciler.go @@ -13,12 +13,8 @@ package server import ( - "strconv" - "github.com/eclipse-che/che-operator/pkg/deploy" "github.com/eclipse-che/che-operator/pkg/util" - "github.com/sirupsen/logrus" - appsv1 "k8s.io/api/apps/v1" "sigs.k8s.io/controller-runtime/pkg/reconcile" ) @@ -31,14 +27,7 @@ func NewDefaultValuesReconciler() *DefaultValuesReconciler { } func (p *DefaultValuesReconciler) Reconcile(ctx *deploy.DeployContext) (reconcile.Result, bool, error) { - cheFlavor := deploy.DefaultCheFlavor(ctx.CheCluster) cheNamespace := ctx.CheCluster.Namespace - if len(ctx.CheCluster.Spec.Server.CheFlavor) < 1 { - ctx.CheCluster.Spec.Server.CheFlavor = cheFlavor - if err := deploy.UpdateCheCRSpec(ctx, "installation flavor", cheFlavor); err != nil { - return reconcile.Result{}, false, err - } - } if len(ctx.CheCluster.Spec.Database.ChePostgresSecret) < 1 { if len(ctx.CheCluster.Spec.Database.ChePostgresUser) < 1 || len(ctx.CheCluster.Spec.Database.ChePostgresPassword) < 1 { @@ -66,66 +55,6 @@ func (p *DefaultValuesReconciler) Reconcile(ctx *deploy.DeployContext) (reconcil } } } - if len(ctx.CheCluster.Spec.Auth.IdentityProviderPostgresSecret) < 1 { - keycloakPostgresPassword := util.GeneratePasswd(12) - keycloakDeployment := &appsv1.Deployment{} - exists, err := deploy.GetNamespacedObject(ctx, deploy.IdentityProviderName, keycloakDeployment) - if err != nil { - logrus.Error(err) - } - if exists { - keycloakPostgresPassword = util.GetDeploymentEnv(keycloakDeployment, "DB_PASSWORD") - } - - if len(ctx.CheCluster.Spec.Auth.IdentityProviderPostgresPassword) < 1 { - identityPostgresSecret := deploy.DefaultCheIdentityPostgresSecret() - _, err := deploy.SyncSecretToCluster(ctx, identityPostgresSecret, cheNamespace, map[string][]byte{"password": []byte(keycloakPostgresPassword)}) - if err != nil { - return reconcile.Result{}, false, err - } - ctx.CheCluster.Spec.Auth.IdentityProviderPostgresSecret = identityPostgresSecret - if err := deploy.UpdateCheCRSpec(ctx, "Identity Provider Postgres Secret", identityPostgresSecret); err != nil { - return reconcile.Result{}, false, err - } - } - } - - if len(ctx.CheCluster.Spec.Auth.IdentityProviderSecret) < 1 { - keycloakAdminUserName := util.GetValue(ctx.CheCluster.Spec.Auth.IdentityProviderAdminUserName, "admin") - keycloakAdminPassword := util.GetValue(ctx.CheCluster.Spec.Auth.IdentityProviderPassword, util.GeneratePasswd(12)) - - keycloakDeployment := &appsv1.Deployment{} - exists, _ := deploy.GetNamespacedObject(ctx, deploy.IdentityProviderName, keycloakDeployment) - if exists { - keycloakAdminUserName = util.GetDeploymentEnv(keycloakDeployment, "SSO_ADMIN_USERNAME") - keycloakAdminPassword = util.GetDeploymentEnv(keycloakDeployment, "SSO_ADMIN_PASSWORD") - } - - if len(ctx.CheCluster.Spec.Auth.IdentityProviderAdminUserName) < 1 || len(ctx.CheCluster.Spec.Auth.IdentityProviderPassword) < 1 { - identityProviderSecret := deploy.DefaultCheIdentitySecret() - _, err := deploy.SyncSecretToCluster(ctx, identityProviderSecret, cheNamespace, map[string][]byte{"user": []byte(keycloakAdminUserName), "password": []byte(keycloakAdminPassword)}) - if err != nil { - return reconcile.Result{}, false, err - } - ctx.CheCluster.Spec.Auth.IdentityProviderSecret = identityProviderSecret - if err := deploy.UpdateCheCRSpec(ctx, "Identity Provider Secret", identityProviderSecret); err != nil { - return reconcile.Result{}, false, err - } - } else { - if len(ctx.CheCluster.Spec.Auth.IdentityProviderPassword) < 1 { - ctx.CheCluster.Spec.Auth.IdentityProviderPassword = keycloakAdminPassword - if err := deploy.UpdateCheCRSpec(ctx, "Keycloak admin password", "password hidden"); err != nil { - return reconcile.Result{}, false, err - } - } - if len(ctx.CheCluster.Spec.Auth.IdentityProviderAdminUserName) < 1 { - ctx.CheCluster.Spec.Auth.IdentityProviderAdminUserName = keycloakAdminUserName - if err := deploy.UpdateCheCRSpec(ctx, "Keycloak admin username", keycloakAdminUserName); err != nil { - return reconcile.Result{}, false, err - } - } - } - } chePostgresDb := util.GetValue(ctx.CheCluster.Spec.Database.ChePostgresDb, "dbche") if len(ctx.CheCluster.Spec.Database.ChePostgresDb) < 1 { @@ -149,24 +78,6 @@ func (p *DefaultValuesReconciler) Reconcile(ctx *deploy.DeployContext) (reconcil } } - if !ctx.CheCluster.IsNativeUserModeEnabled() { - keycloakRealm := util.GetValue(ctx.CheCluster.Spec.Auth.IdentityProviderRealm, cheFlavor) - if len(ctx.CheCluster.Spec.Auth.IdentityProviderRealm) < 1 { - ctx.CheCluster.Spec.Auth.IdentityProviderRealm = keycloakRealm - if err := deploy.UpdateCheCRSpec(ctx, "Keycloak realm", keycloakRealm); err != nil { - return reconcile.Result{}, false, err - } - } - keycloakClientId := util.GetValue(ctx.CheCluster.Spec.Auth.IdentityProviderClientId, cheFlavor+"-public") - if len(ctx.CheCluster.Spec.Auth.IdentityProviderClientId) < 1 { - ctx.CheCluster.Spec.Auth.IdentityProviderClientId = keycloakClientId - - if err := deploy.UpdateCheCRSpec(ctx, "Keycloak client ID", keycloakClientId); err != nil { - return reconcile.Result{}, false, err - } - } - } - cheLogLevel := util.GetValue(ctx.CheCluster.Spec.Server.CheLogLevel, deploy.DefaultCheLogLevel) if len(ctx.CheCluster.Spec.Server.CheLogLevel) < 1 { ctx.CheCluster.Spec.Server.CheLogLevel = cheLogLevel @@ -196,76 +107,6 @@ func (p *DefaultValuesReconciler) Reconcile(ctx *deploy.DeployContext) (reconcil } } - // This is only to correctly manage defaults during the transition - // from Upstream 7.0.0 GA to the next - // version that should fixed bug https://github.com/eclipse/che/issues/13714 - // Or for the transition from CRW 1.2 to 2.0 - - if ctx.CheCluster.Spec.Storage.PvcJobsImage == deploy.OldDefaultPvcJobsUpstreamImageToDetect || - (deploy.MigratingToCRW2_0(ctx.CheCluster) && ctx.CheCluster.Spec.Storage.PvcJobsImage != "") { - ctx.CheCluster.Spec.Storage.PvcJobsImage = "" - if err := deploy.UpdateCheCRSpec(ctx, "pvc jobs image", ctx.CheCluster.Spec.Storage.PvcJobsImage); err != nil { - return reconcile.Result{}, false, err - } - } - - if ctx.CheCluster.Spec.Database.PostgresImage == deploy.OldDefaultPostgresUpstreamImageToDetect || - (deploy.MigratingToCRW2_0(ctx.CheCluster) && ctx.CheCluster.Spec.Database.PostgresImage != "") { - ctx.CheCluster.Spec.Database.PostgresImage = "" - if err := deploy.UpdateCheCRSpec(ctx, "postgres image", ctx.CheCluster.Spec.Database.PostgresImage); err != nil { - return reconcile.Result{}, false, err - } - } - - if ctx.CheCluster.Spec.Auth.IdentityProviderImage == deploy.OldDefaultKeycloakUpstreamImageToDetect || - (deploy.MigratingToCRW2_0(ctx.CheCluster) && ctx.CheCluster.Spec.Auth.IdentityProviderImage != "") { - ctx.CheCluster.Spec.Auth.IdentityProviderImage = "" - if err := deploy.UpdateCheCRSpec(ctx, "keycloak image", ctx.CheCluster.Spec.Auth.IdentityProviderImage); err != nil { - return reconcile.Result{}, false, err - } - } - - if deploy.MigratingToCRW2_0(ctx.CheCluster) && - !ctx.CheCluster.Spec.Server.ExternalPluginRegistry && - ctx.CheCluster.Spec.Server.PluginRegistryUrl == deploy.OldCrwPluginRegistryUrl { - ctx.CheCluster.Spec.Server.PluginRegistryUrl = "" - if err := deploy.UpdateCheCRSpec(ctx, "plugin registry url", ctx.CheCluster.Spec.Server.PluginRegistryUrl); err != nil { - return reconcile.Result{}, false, err - } - } - - if deploy.MigratingToCRW2_0(ctx.CheCluster) && - ctx.CheCluster.Spec.Server.CheImage == deploy.OldDefaultCodeReadyServerImageRepo { - ctx.CheCluster.Spec.Server.CheImage = "" - if err := deploy.UpdateCheCRSpec(ctx, "che image repo", ctx.CheCluster.Spec.Server.CheImage); err != nil { - return reconcile.Result{}, false, err - } - } - - if deploy.MigratingToCRW2_0(ctx.CheCluster) && - ctx.CheCluster.Spec.Server.CheImageTag == deploy.OldDefaultCodeReadyServerImageTag { - ctx.CheCluster.Spec.Server.CheImageTag = "" - if err := deploy.UpdateCheCRSpec(ctx, "che image tag", ctx.CheCluster.Spec.Server.CheImageTag); err != nil { - return reconcile.Result{}, false, err - } - } - - if ctx.CheCluster.Spec.Server.ServerExposureStrategy == "" && ctx.CheCluster.Spec.K8s.IngressStrategy == "" { - strategy := util.GetServerExposureStrategy(ctx.CheCluster) - ctx.CheCluster.Spec.Server.ServerExposureStrategy = strategy - if err := deploy.UpdateCheCRSpec(ctx, "serverExposureStrategy", strategy); err != nil { - return reconcile.Result{}, false, err - } - } - - if ctx.CheCluster.Spec.DevWorkspace.Enable && ctx.CheCluster.Spec.Auth.NativeUserMode == nil { - newNativeUserModeValue := util.NewBoolPointer(true) - ctx.CheCluster.Spec.Auth.NativeUserMode = newNativeUserModeValue - if err := deploy.UpdateCheCRSpec(ctx, "nativeUserMode", strconv.FormatBool(*newNativeUserModeValue)); err != nil { - return reconcile.Result{}, false, err - } - } - return reconcile.Result{}, true, nil } diff --git a/pkg/deploy/server/default_values_reconciler_test.go b/pkg/deploy/server/default_values_reconciler_test.go deleted file mode 100644 index 12235e508..000000000 --- a/pkg/deploy/server/default_values_reconciler_test.go +++ /dev/null @@ -1,162 +0,0 @@ -// -// Copyright (c) 2019-2021 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 server - -import ( - "os" - - "github.com/eclipse-che/che-operator/pkg/deploy" - devworkspace "github.com/eclipse-che/che-operator/pkg/deploy/dev-workspace" - "github.com/eclipse-che/che-operator/pkg/util" - "github.com/stretchr/testify/assert" - logf "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/log/zap" - - orgv1 "github.com/eclipse-che/che-operator/api/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/utils/pointer" - - "testing" -) - -func TestEnsureServerExposureStrategy(t *testing.T) { - type testCase struct { - name string - expectedCr *orgv1.CheCluster - devWorkspaceEnabled bool - initObjects []runtime.Object - } - - testCases := []testCase{ - { - name: "Single Host should be enabled if devWorkspace is enabled", - expectedCr: &orgv1.CheCluster{ - Spec: orgv1.CheClusterSpec{ - Server: orgv1.CheClusterSpecServer{ - ServerExposureStrategy: "single-host", - }, - }, - }, - devWorkspaceEnabled: true, - }, - { - name: "Multi Host should be enabled if devWorkspace is not enabled", - expectedCr: &orgv1.CheCluster{ - Spec: orgv1.CheClusterSpec{ - Server: orgv1.CheClusterSpecServer{ - ServerExposureStrategy: "multi-host", - }, - }, - }, - devWorkspaceEnabled: false, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - checluster := &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "eclipse-che", - Namespace: "eclipse-che", - }, - } - - checluster.Spec.DevWorkspace.Enable = testCase.devWorkspaceEnabled - ctx := deploy.GetTestDeployContext(checluster, []runtime.Object{}) - - defaults := NewDefaultValuesReconciler() - _, done, err := defaults.Reconcile(ctx) - assert.True(t, done) - assert.Nil(t, err) - assert.Equal(t, testCase.expectedCr.Spec.Server.ServerExposureStrategy, ctx.CheCluster.Spec.Server.ServerExposureStrategy) - }) - } -} - -func TestNativeUserModeEnabled(t *testing.T) { - type testCase struct { - name string - initObjects []runtime.Object - isOpenshift bool - devworkspaceEnabled bool - initialNativeUserValue *bool - expectedNativeUserValue *bool - } - - testCases := []testCase{ - { - name: "che-operator should use nativeUserMode when devworkspaces on openshift and no initial value in CR for nativeUserMode", - isOpenshift: true, - devworkspaceEnabled: true, - initialNativeUserValue: nil, - expectedNativeUserValue: pointer.BoolPtr(true), - }, - { - name: "che-operator should use nativeUserMode value from initial CR", - isOpenshift: true, - devworkspaceEnabled: true, - initialNativeUserValue: pointer.BoolPtr(false), - expectedNativeUserValue: pointer.BoolPtr(false), - }, - { - name: "che-operator should use nativeUserMode value from initial CR", - isOpenshift: true, - devworkspaceEnabled: true, - initialNativeUserValue: pointer.BoolPtr(true), - expectedNativeUserValue: pointer.BoolPtr(true), - }, - { - name: "che-operator should use nativeUserMode when devworkspaces on kubernetes and no initial value in CR for nativeUserMode", - isOpenshift: false, - devworkspaceEnabled: true, - initialNativeUserValue: nil, - expectedNativeUserValue: pointer.BoolPtr(true), - }, - { - name: "che-operator not modify nativeUserMode when devworkspace not enabled", - isOpenshift: true, - devworkspaceEnabled: false, - initialNativeUserValue: nil, - expectedNativeUserValue: nil, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - logf.SetLogger(zap.New(zap.WriteTo(os.Stdout), zap.UseDevMode(true))) - - checluster := &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "eclipse-che", - Namespace: "eclipse-che", - }, - } - - // reread templates (workaround after setting IsOpenShift value) - util.IsOpenShift = testCase.isOpenshift - devworkspace.DevWorkspaceTemplates = devworkspace.DevWorkspaceTemplatesPath() - devworkspace.DevWorkspaceIssuerFile = devworkspace.DevWorkspaceTemplates + "/devworkspace-controller-selfsigned-issuer.Issuer.yaml" - devworkspace.DevWorkspaceCertificateFile = devworkspace.DevWorkspaceTemplates + "/devworkspace-controller-serving-cert.Certificate.yaml" - - checluster.Spec.DevWorkspace.Enable = testCase.devworkspaceEnabled - checluster.Spec.Auth.NativeUserMode = testCase.initialNativeUserValue - ctx := deploy.GetTestDeployContext(checluster, []runtime.Object{}) - - defaults := NewDefaultValuesReconciler() - _, done, err := defaults.Reconcile(ctx) - assert.True(t, done) - assert.Nil(t, err) - assert.Equal(t, testCase.expectedNativeUserValue, ctx.CheCluster.Spec.Auth.NativeUserMode) - }) - } -} diff --git a/pkg/deploy/server/server_configmap.go b/pkg/deploy/server/server_configmap.go index b241ce755..081ae9af5 100644 --- a/pkg/deploy/server/server_configmap.go +++ b/pkg/deploy/server/server_configmap.go @@ -64,8 +64,6 @@ type CheConfigMap struct { CheLogLevel string `json:"CHE_LOG_LEVEL"` IdentityProviderUrl string `json:"CHE_OIDC_AUTH__SERVER__URL,omitempty"` IdentityProviderInternalURL string `json:"CHE_OIDC_AUTH__INTERNAL__SERVER__URL,omitempty"` - KeycloakRealm string `json:"CHE_KEYCLOAK_REALM,omitempty"` - KeycloakClientId string `json:"CHE_KEYCLOAK_CLIENT__ID,omitempty"` OpenShiftIdentityProvider string `json:"CHE_INFRA_OPENSHIFT_OAUTH__IDENTITY__PROVIDER"` JavaOpts string `json:"JAVA_OPTS"` WorkspaceJavaOpts string `json:"CHE_WORKSPACE_JAVA__OPTIONS"` @@ -95,37 +93,18 @@ func (s *CheServerReconciler) getCheConfigMapData(ctx *deploy.DeployContext) (ch cheHost := ctx.CheCluster.Spec.Server.CheHost identityProviderURL := ctx.CheCluster.Spec.Auth.IdentityProviderURL - // Adds `/auth` for external identity providers. - // If identity provide is deployed by operator then `/auth` is already added. - if !ctx.CheCluster.IsNativeUserModeEnabled() && - ctx.CheCluster.Spec.Auth.ExternalIdentityProvider && - !strings.HasSuffix(identityProviderURL, "/auth") { - if strings.HasSuffix(identityProviderURL, "/") { - identityProviderURL = identityProviderURL + "auth" - } else { - identityProviderURL = identityProviderURL + "/auth" - } - } - - cheFlavor := deploy.DefaultCheFlavor(ctx.CheCluster) infra := "kubernetes" if util.IsOpenShift { infra = "openshift" } tls := "false" openShiftIdentityProviderId := "NULL" - if util.IsOpenShift && ctx.CheCluster.IsOpenShiftOAuthEnabled() { + if util.IsOpenShift { openShiftIdentityProviderId = "openshift-v3" if util.IsOpenShift4 { openShiftIdentityProviderId = "openshift-v4" } } - tlsSupport := ctx.CheCluster.Spec.Server.TlsSupport - protocol := "http" - if tlsSupport { - protocol = "https" - tls = "true" - } proxyJavaOpts := "" cheWorkspaceNoProxy := ctx.Proxy.NoProxy @@ -158,9 +137,6 @@ func (s *CheServerReconciler) getCheConfigMapData(ctx *deploy.DeployContext) (ch chePostgresHostName := util.GetValue(ctx.CheCluster.Spec.Database.ChePostgresHostName, deploy.DefaultChePostgresHostName) chePostgresPort := util.GetValue(ctx.CheCluster.Spec.Database.ChePostgresPort, deploy.DefaultChePostgresPort) chePostgresDb := util.GetValue(ctx.CheCluster.Spec.Database.ChePostgresDb, deploy.DefaultChePostgresDb) - keycloakRealm := util.GetValue(ctx.CheCluster.Spec.Auth.IdentityProviderRealm, cheFlavor) - keycloakClientId := util.GetValue(ctx.CheCluster.Spec.Auth.IdentityProviderClientId, cheFlavor+"-public") - ingressStrategy := util.GetServerExposureStrategy(ctx.CheCluster) ingressClass := util.GetValue(ctx.CheCluster.Spec.K8s.IngressClass, deploy.DefaultIngressClass) // grab first the devfile registry url which is deployed by operator @@ -182,45 +158,26 @@ func (s *CheServerReconciler) getCheConfigMapData(ctx *deploy.DeployContext) (ch cheDebug := util.GetValue(ctx.CheCluster.Spec.Server.CheDebug, deploy.DefaultCheDebug) cheMetrics := strconv.FormatBool(ctx.CheCluster.Spec.Metrics.Enable) cheLabels := util.MapToKeyValuePairs(deploy.GetLabels(ctx.CheCluster, deploy.DefaultCheFlavor(ctx.CheCluster))) - workspaceExposure := deploy.GetSingleHostExposureType(ctx.CheCluster) singleHostGatewayConfigMapLabels := labels.FormatLabels(util.GetMapValue(ctx.CheCluster.Spec.Server.SingleHostGatewayConfigMapLabels, deploy.DefaultSingleHostGatewayConfigMapLabels)) - workspaceNamespaceDefault := util.GetWorkspaceNamespaceDefault(ctx.CheCluster) + workspaceNamespaceDefault := deploy.GetWorkspaceNamespaceDefault(ctx.CheCluster) - cheAPI := protocol + "://" + cheHost + "/api" - var keycloakInternalURL, pluginRegistryInternalURL, devfileRegistryInternalURL, cheInternalAPI, webSocketInternalEndpoint string - - if !ctx.CheCluster.IsNativeUserModeEnabled() && - ctx.CheCluster.IsInternalClusterSVCNamesEnabled() && - !ctx.CheCluster.Spec.Auth.ExternalIdentityProvider { - keycloakInternalURL = fmt.Sprintf("%s://%s.%s.svc:8080/auth", "http", deploy.IdentityProviderName, ctx.CheCluster.Namespace) - } + cheAPI := "https://" + cheHost + "/api" + var pluginRegistryInternalURL, devfileRegistryInternalURL string // If there is a devfile registry deployed by operator - if ctx.CheCluster.IsInternalClusterSVCNamesEnabled() && !ctx.CheCluster.Spec.Server.ExternalDevfileRegistry { + if !ctx.CheCluster.Spec.Server.ExternalDevfileRegistry { devfileRegistryInternalURL = fmt.Sprintf("http://%s.%s.svc:8080", deploy.DevfileRegistryName, ctx.CheCluster.Namespace) } - if ctx.CheCluster.IsInternalClusterSVCNamesEnabled() && !ctx.CheCluster.Spec.Server.ExternalPluginRegistry { + if !ctx.CheCluster.Spec.Server.ExternalPluginRegistry { pluginRegistryInternalURL = fmt.Sprintf("http://%s.%s.svc:8080/v3", deploy.PluginRegistryName, ctx.CheCluster.Namespace) } - if ctx.CheCluster.IsInternalClusterSVCNamesEnabled() { - cheInternalAPI = fmt.Sprintf("http://%s.%s.svc:8080/api", deploy.CheServiceName, ctx.CheCluster.Namespace) - webSocketInternalEndpoint = fmt.Sprintf("ws://%s.%s.svc:8080/api/websocket", deploy.CheServiceName, ctx.CheCluster.Namespace) - } - - wsprotocol := "ws" - if tlsSupport { - wsprotocol = "wss" - } - webSocketEndpoint := wsprotocol + "://" + cheHost + "/api/websocket" - - cheWorkspaceServiceAccount := "che-workspace" - cheUserClusterRoleNames := "NULL" - if ctx.CheCluster.IsNativeUserModeEnabled() { - cheWorkspaceServiceAccount = "NULL" - cheUserClusterRoleNames = fmt.Sprintf("%s-cheworkspaces-clusterrole, %s-cheworkspaces-devworkspace-clusterrole", ctx.CheCluster.Namespace, ctx.CheCluster.Namespace) - } + cheInternalAPI := fmt.Sprintf("http://%s.%s.svc:8080/api", deploy.CheServiceName, ctx.CheCluster.Namespace) + webSocketInternalEndpoint := fmt.Sprintf("ws://%s.%s.svc:8080/api/websocket", deploy.CheServiceName, ctx.CheCluster.Namespace) + webSocketEndpoint := "wss://" + cheHost + "/api/websocket" + cheWorkspaceServiceAccount := "NULL" + cheUserClusterRoleNames := fmt.Sprintf("%s-cheworkspaces-clusterrole, %s-cheworkspaces-devworkspace-clusterrole", ctx.CheCluster.Namespace, ctx.CheCluster.Namespace) data := &CheConfigMap{ CheMultiUser: "true", @@ -240,8 +197,8 @@ func (s *CheServerReconciler) getCheConfigMapData(ctx *deploy.DeployContext) (ch WorkspacePvcStorageClassName: workspacePvcStorageClassName, PvcJobsImage: pvcJobsImage, PreCreateSubPaths: preCreateSubPaths, - TlsSupport: tls, - K8STrustCerts: tls, + TlsSupport: "true", + K8STrustCerts: "true", CheLogLevel: cheLogLevel, OpenShiftIdentityProvider: openShiftIdentityProviderId, JavaOpts: deploy.DefaultJavaOpts + " " + proxyJavaOpts, @@ -261,16 +218,13 @@ func (s *CheServerReconciler) getCheConfigMapData(ctx *deploy.DeployContext) (ch CheJGroupsKubernetesLabels: cheLabels, CheMetricsEnabled: cheMetrics, CheTrustedCABundlesConfigMap: deploytls.CheAllCACertsConfigMapName, - ServerStrategy: ingressStrategy, - WorkspaceExposure: workspaceExposure, + ServerStrategy: deploy.ServerExposureStrategy, + WorkspaceExposure: deploy.GatewaySingleHostExposureType, SingleHostGatewayConfigMapLabels: singleHostGatewayConfigMapLabels, - CheDevWorkspacesEnabled: strconv.FormatBool(ctx.CheCluster.Spec.DevWorkspace.Enable), + CheDevWorkspacesEnabled: strconv.FormatBool(true), } data.IdentityProviderUrl = identityProviderURL - data.IdentityProviderInternalURL = keycloakInternalURL - data.KeycloakRealm = keycloakRealm - data.KeycloakClientId = keycloakClientId data.DatabaseURL = "jdbc:postgresql://" + chePostgresHostName + ":" + chePostgresPort + "/" + chePostgresDb if len(ctx.CheCluster.Spec.Database.ChePostgresSecret) < 1 { data.DbUserName = ctx.CheCluster.Spec.Database.ChePostgresUser @@ -294,10 +248,7 @@ func (s *CheServerReconciler) getCheConfigMapData(ctx *deploy.DeployContext) (ch "CHE_INFRA_KUBERNETES_INGRESS_ANNOTATIONS__JSON": "{\"kubernetes.io/ingress.class\": " + ingressClass + ", \"nginx.ingress.kubernetes.io/rewrite-target\": \"/$1\",\"nginx.ingress.kubernetes.io/ssl-redirect\": " + tls + ",\"nginx.ingress.kubernetes.io/proxy-connect-timeout\": \"3600\",\"nginx.ingress.kubernetes.io/proxy-read-timeout\": \"3600\"}", "CHE_INFRA_KUBERNETES_INGRESS_PATH__TRANSFORM": "%s(.*)", } - - if ctx.CheCluster.Spec.DevWorkspace.Enable { - k8sCheEnv["CHE_INFRA_KUBERNETES_ENABLE__UNSUPPORTED__K8S"] = "true" - } + k8sCheEnv["CHE_INFRA_KUBERNETES_ENABLE__UNSUPPORTED__K8S"] = "true" // Add TLS key and server certificate to properties since user workspaces is created in another // than Che server namespace, from where the Che TLS secret is not accessable diff --git a/pkg/deploy/server/server_configmap_test.go b/pkg/deploy/server/server_configmap_test.go index 752e828f3..7bdbe5ff5 100644 --- a/pkg/deploy/server/server_configmap_test.go +++ b/pkg/deploy/server/server_configmap_test.go @@ -19,7 +19,6 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/utils/pointer" orgv1 "github.com/eclipse-che/che-operator/api/v1" "github.com/eclipse-che/che-operator/pkg/util" @@ -47,15 +46,11 @@ func TestNewCheConfigMap(t *testing.T) { }, Spec: orgv1.CheClusterSpec{ Server: orgv1.CheClusterSpecServer{ - CheHost: "myhostname.com", - TlsSupport: true, + CheHost: "myhostname.com", CustomCheProperties: map[string]string{ "CHE_WORKSPACE_NO_PROXY": "myproxy.myhostname.com", }, }, - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: util.NewBoolPointer(true), - }, }, }, expectedData: map[string]string{ @@ -159,7 +154,7 @@ func TestConfigMap(t *testing.T) { }, }, expectedData: map[string]string{ - "CHE_WEBSOCKET_ENDPOINT": "ws://che-host/api/websocket", + "CHE_WEBSOCKET_ENDPOINT": "wss://che-host/api/websocket", }, }, { @@ -188,33 +183,12 @@ func TestConfigMap(t *testing.T) { }, Spec: orgv1.CheClusterSpec{ Server: orgv1.CheClusterSpecServer{ - CheHost: "che-host", - DisableInternalClusterSVCNames: pointer.BoolPtr(true), + CheHost: "che-host", }, }, }, expectedData: map[string]string{ - "CHE_WEBSOCKET_ENDPOINT": "ws://che-host/api/websocket", - }, - }, - { - name: "Kubernetes strategy should be set correctly", - cheCluster: &orgv1.CheCluster{ - TypeMeta: metav1.TypeMeta{ - Kind: "CheCluster", - APIVersion: "org.eclipse.che/v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", - }, - Spec: orgv1.CheClusterSpec{ - K8s: orgv1.CheClusterSpecK8SOnly{ - IngressStrategy: "single-host", - }, - }, - }, - expectedData: map[string]string{ - "CHE_INFRA_KUBERNETES_SERVER__STRATEGY": "single-host", + "CHE_WEBSOCKET_ENDPOINT": "wss://che-host/api/websocket", }, }, } @@ -418,9 +392,8 @@ func TestShouldSetUpCorrectlyDevfileRegistryURL(t *testing.T) { }, Spec: orgv1.CheClusterSpec{ Server: orgv1.CheClusterSpecServer{ - DisableInternalClusterSVCNames: pointer.BoolPtr(true), - ExternalDevfileRegistry: true, - DevfileRegistryUrl: "http://devfile-registry.external.1", + ExternalDevfileRegistry: true, + DevfileRegistryUrl: "http://devfile-registry.external.1", ExternalDevfileRegistries: []orgv1.ExternalDevfileRegistries{ {Url: "http://devfile-registry.external.2"}, }, @@ -432,31 +405,6 @@ func TestShouldSetUpCorrectlyDevfileRegistryURL(t *testing.T) { "CHE_WORKSPACE_DEVFILE__REGISTRY__INTERNAL__URL": "", }, }, - { - name: "Test devfile registry urls #4", - cheCluster: &orgv1.CheCluster{ - TypeMeta: metav1.TypeMeta{ - Kind: "CheCluster", - APIVersion: "org.eclipse.che/v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", - }, - Spec: orgv1.CheClusterSpec{ - Server: orgv1.CheClusterSpecServer{ - DisableInternalClusterSVCNames: pointer.BoolPtr(true), - ExternalDevfileRegistry: false, - }, - }, - Status: orgv1.CheClusterStatus{ - DevfileRegistryURL: "http://devfile-registry.internal", - }, - }, - expectedData: map[string]string{ - "CHE_WORKSPACE_DEVFILE__REGISTRY__INTERNAL__URL": "", - "CHE_WORKSPACE_DEVFILE__REGISTRY__URL": "http://devfile-registry.internal", - }, - }, { name: "Test devfile registry urls #5", cheCluster: &orgv1.CheCluster{ @@ -481,35 +429,6 @@ func TestShouldSetUpCorrectlyDevfileRegistryURL(t *testing.T) { "CHE_WORKSPACE_DEVFILE__REGISTRY__URL": "http://devfile-registry.internal", }, }, - { - name: "Test devfile registry urls #6", - cheCluster: &orgv1.CheCluster{ - TypeMeta: metav1.TypeMeta{ - Kind: "CheCluster", - APIVersion: "org.eclipse.che/v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", - }, - Spec: orgv1.CheClusterSpec{ - Server: orgv1.CheClusterSpecServer{ - DisableInternalClusterSVCNames: pointer.BoolPtr(true), - ExternalDevfileRegistry: false, - DevfileRegistryUrl: "http://devfile-registry.external.1", - ExternalDevfileRegistries: []orgv1.ExternalDevfileRegistries{ - {Url: "http://devfile-registry.external.2"}, - }, - }, - }, - Status: orgv1.CheClusterStatus{ - DevfileRegistryURL: "http://devfile-registry.internal", - }, - }, - expectedData: map[string]string{ - "CHE_WORKSPACE_DEVFILE__REGISTRY__INTERNAL__URL": "", - "CHE_WORKSPACE_DEVFILE__REGISTRY__URL": "http://devfile-registry.internal http://devfile-registry.external.1 http://devfile-registry.external.2", - }, - }, { name: "Test devfile registry urls #7", cheCluster: &orgv1.CheCluster{ @@ -579,9 +498,6 @@ func TestShouldSetUpCorrectlyInternalPluginRegistryServiceURL(t *testing.T) { Server: orgv1.CheClusterSpecServer{ ExternalPluginRegistry: true, }, - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: util.NewBoolPointer(false), - }, }, Status: orgv1.CheClusterStatus{ PluginRegistryURL: "http://external-plugin-registry", @@ -593,60 +509,6 @@ func TestShouldSetUpCorrectlyInternalPluginRegistryServiceURL(t *testing.T) { }, { name: "Test CHE_WORKSPACE_PLUGIN__REGISTRY__INTERNAL__URL #2", - cheCluster: &orgv1.CheCluster{ - TypeMeta: metav1.TypeMeta{ - Kind: "CheCluster", - APIVersion: "org.eclipse.che/v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", - }, - Spec: orgv1.CheClusterSpec{ - Server: orgv1.CheClusterSpecServer{ - DisableInternalClusterSVCNames: pointer.BoolPtr(true), - ExternalPluginRegistry: true, - }, - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: util.NewBoolPointer(false), - }, - }, - Status: orgv1.CheClusterStatus{ - PluginRegistryURL: "http://external-plugin-registry", - }, - }, - expectedData: map[string]string{ - "CHE_WORKSPACE_PLUGIN__REGISTRY__INTERNAL__URL": "", - }, - }, - { - name: "Test CHE_WORKSPACE_PLUGIN__REGISTRY__INTERNAL__URL #3", - cheCluster: &orgv1.CheCluster{ - TypeMeta: metav1.TypeMeta{ - Kind: "CheCluster", - APIVersion: "org.eclipse.che/v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", - }, - Spec: orgv1.CheClusterSpec{ - Server: orgv1.CheClusterSpecServer{ - DisableInternalClusterSVCNames: pointer.BoolPtr(true), - ExternalPluginRegistry: false, - }, - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: util.NewBoolPointer(false), - }, - }, - Status: orgv1.CheClusterStatus{ - PluginRegistryURL: "http://plugin-registry/v3", - }, - }, - expectedData: map[string]string{ - "CHE_WORKSPACE_PLUGIN__REGISTRY__INTERNAL__URL": "", - }, - }, - { - name: "Test CHE_WORKSPACE_PLUGIN__REGISTRY__INTERNAL__URL #4", cheCluster: &orgv1.CheCluster{ TypeMeta: metav1.TypeMeta{ Kind: "CheCluster", @@ -659,9 +521,6 @@ func TestShouldSetUpCorrectlyInternalPluginRegistryServiceURL(t *testing.T) { Server: orgv1.CheClusterSpecServer{ ExternalPluginRegistry: false, }, - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: util.NewBoolPointer(false), - }, }, Status: orgv1.CheClusterStatus{ PluginRegistryURL: "http://external-plugin-registry", @@ -698,30 +557,6 @@ func TestShouldSetUpCorrectlyInternalCheServerURL(t *testing.T) { } testCases := []testCase{ - { - name: "Should be an empty when internal network is disabled", - cheCluster: &orgv1.CheCluster{ - TypeMeta: metav1.TypeMeta{ - Kind: "CheCluster", - APIVersion: "org.eclipse.che/v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", - }, - Spec: orgv1.CheClusterSpec{ - Server: orgv1.CheClusterSpecServer{ - DisableInternalClusterSVCNames: pointer.BoolPtr(true), - CheHost: "che-host", - }, - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: util.NewBoolPointer(false), - }, - }, - }, - expectedData: map[string]string{ - "CHE_API_INTERNAL": "", - }, - }, { name: "Should use internal che-server url, when internal network is enabled", cheCluster: &orgv1.CheCluster{ @@ -736,9 +571,6 @@ func TestShouldSetUpCorrectlyInternalCheServerURL(t *testing.T) { Server: orgv1.CheClusterSpecServer{ CheHost: "http://che-host", }, - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: util.NewBoolPointer(false), - }, }, }, expectedData: map[string]string{ @@ -760,154 +592,3 @@ func TestShouldSetUpCorrectlyInternalCheServerURL(t *testing.T) { }) } } - -func TestShouldSetUpCorrectlyInternalIdentityProviderServiceURL(t *testing.T) { - type testCase struct { - name string - isOpenShift bool - isOpenShift4 bool - initObjects []runtime.Object - cheCluster *orgv1.CheCluster - expectedData map[string]string - } - - testCases := []testCase{ - { - name: "Should be an empty when enabled 'external' public identity provider url and internal network is enabled #1", - cheCluster: &orgv1.CheCluster{ - TypeMeta: metav1.TypeMeta{ - Kind: "CheCluster", - APIVersion: "org.eclipse.che/v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", - }, - Spec: orgv1.CheClusterSpec{ - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: util.NewBoolPointer(false), - ExternalIdentityProvider: true, - IdentityProviderURL: "http://external-keycloak", - }, - }, - }, - expectedData: map[string]string{ - "CHE_OIDC_AUTH__INTERNAL__SERVER__URL": "", - "CHE_OIDC_AUTH__SERVER__URL": "http://external-keycloak/auth", - }, - }, - { - name: "Should be an empty when enabled 'external' public identity provider url and internal network is enabled #2", - cheCluster: &orgv1.CheCluster{ - TypeMeta: metav1.TypeMeta{ - Kind: "CheCluster", - APIVersion: "org.eclipse.che/v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", - }, - Spec: orgv1.CheClusterSpec{ - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: util.NewBoolPointer(false), - ExternalIdentityProvider: true, - IdentityProviderURL: "http://external-keycloak/auth", - }, - }, - }, - expectedData: map[string]string{ - "CHE_OIDC_AUTH__INTERNAL__SERVER__URL": "", - "CHE_OIDC_AUTH__SERVER__URL": "http://external-keycloak/auth", - }, - }, - { - name: "Should be and empty when enabled 'external' public identity provider url and internal network is disabled", - cheCluster: &orgv1.CheCluster{ - TypeMeta: metav1.TypeMeta{ - Kind: "CheCluster", - APIVersion: "org.eclipse.che/v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", - }, - Spec: orgv1.CheClusterSpec{ - Server: orgv1.CheClusterSpecServer{ - DisableInternalClusterSVCNames: pointer.BoolPtr(true), - }, - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: util.NewBoolPointer(false), - ExternalIdentityProvider: true, - IdentityProviderURL: "http://external-keycloak", - }, - }, - }, - expectedData: map[string]string{ - "CHE_OIDC_AUTH__INTERNAL__SERVER__URL": "", - "CHE_OIDC_AUTH__SERVER__URL": "http://external-keycloak/auth", - }, - }, - { - name: "Should be an empty when internal network is disabled", - cheCluster: &orgv1.CheCluster{ - TypeMeta: metav1.TypeMeta{ - Kind: "CheCluster", - APIVersion: "org.eclipse.che/v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", - }, - Spec: orgv1.CheClusterSpec{ - Server: orgv1.CheClusterSpecServer{ - DisableInternalClusterSVCNames: pointer.BoolPtr(true), - }, - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: util.NewBoolPointer(false), - ExternalIdentityProvider: false, - IdentityProviderURL: "http://keycloak/auth", - }, - }, - }, - expectedData: map[string]string{ - "CHE_OIDC_AUTH__INTERNAL__SERVER__URL": "", - "CHE_OIDC_AUTH__SERVER__URL": "http://keycloak/auth", - }, - }, - { - name: "Should use internal identity provider url, when internal network is enabled", - cheCluster: &orgv1.CheCluster{ - TypeMeta: metav1.TypeMeta{ - Kind: "CheCluster", - APIVersion: "org.eclipse.che/v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", - }, - Spec: orgv1.CheClusterSpec{ - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: util.NewBoolPointer(false), - ExternalIdentityProvider: false, - IdentityProviderURL: "http://keycloak/auth", - }, - }, - }, - expectedData: map[string]string{ - "CHE_OIDC_AUTH__INTERNAL__SERVER__URL": "http://keycloak.eclipse-che.svc:8080/auth", - "CHE_OIDC_AUTH__SERVER__URL": "http://keycloak/auth", - }, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - util.IsOpenShift = testCase.isOpenShift - util.IsOpenShift4 = testCase.isOpenShift4 - ctx := deploy.GetTestDeployContext(testCase.cheCluster, []runtime.Object{}) - - server := NewCheServerReconciler() - actualData, err := server.getCheConfigMapData(ctx) - if err != nil { - t.Fatalf("Error creating ConfigMap data: %v", err) - } - - util.ValidateContainData(actualData, testCase.expectedData, t) - }) - } -} diff --git a/pkg/deploy/server/server_deployment.go b/pkg/deploy/server/server_deployment.go index c9d6ff10e..128546fe7 100644 --- a/pkg/deploy/server/server_deployment.go +++ b/pkg/deploy/server/server_deployment.go @@ -16,7 +16,6 @@ import ( "strings" "github.com/eclipse-che/che-operator/pkg/deploy" - identityprovider "github.com/eclipse-che/che-operator/pkg/deploy/identity-provider" "github.com/eclipse-che/che-operator/pkg/deploy/postgres" "github.com/eclipse-che/che-operator/pkg/deploy/tls" @@ -112,42 +111,6 @@ func (s CheServerReconciler) getDeploymentSpec(ctx *deploy.DeployContext) (*apps cheEnv = append(cheEnv, selfSignedCertEnv) cheEnv = append(cheEnv, gitSelfSignedCertEnv) cheEnv = append(cheEnv, gitSelfSignedCertHostEnv) - - identityProviderSecret := ctx.CheCluster.Spec.Auth.IdentityProviderSecret - if len(identityProviderSecret) > 0 { - cheEnv = append(cheEnv, corev1.EnvVar{ - Name: "CHE_KEYCLOAK_ADMIN__PASSWORD", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: "password", - LocalObjectReference: corev1.LocalObjectReference{ - Name: identityProviderSecret, - }, - }, - }, - }, - corev1.EnvVar{ - Name: "CHE_KEYCLOAK_ADMIN__USERNAME", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: "user", - LocalObjectReference: corev1.LocalObjectReference{ - Name: identityProviderSecret, - }, - }, - }, - }) - } else { - cheEnv = append(cheEnv, corev1.EnvVar{ - Name: "CHE_KEYCLOAK_ADMIN__PASSWORD", - Value: ctx.CheCluster.Spec.Auth.IdentityProviderPassword, - }, - corev1.EnvVar{ - Name: "CHE_KEYCLOAK_ADMIN__USERNAME", - Value: ctx.CheCluster.Spec.Auth.IdentityProviderAdminUserName, - }) - } - cheEnv = append(cheEnv, corev1.EnvVar{ Name: "CM_REVISION", @@ -160,13 +123,10 @@ func (s CheServerReconciler) getDeploymentSpec(ctx *deploy.DeployContext) (*apps APIVersion: "v1", FieldPath: "metadata.namespace"}}, }) - - if ctx.CheCluster.IsNativeUserModeEnabled() { - cheEnv = append(cheEnv, corev1.EnvVar{ - Name: "CHE_AUTH_NATIVEUSER", - Value: "true", - }) - } + cheEnv = append(cheEnv, corev1.EnvVar{ + Name: "CHE_AUTH_NATIVEUSER", + Value: "true", + }) cheImageAndTag := GetFullCheServerImageLink(ctx.CheCluster) pullPolicy := corev1.PullPolicy(util.GetValue(string(ctx.CheCluster.Spec.Server.CheImagePullPolicy), deploy.DefaultPullPolicyFromDockerImage(cheImageAndTag))) @@ -368,14 +328,6 @@ func (s CheServerReconciler) getDeploymentSpec(ctx *deploy.DeployContext) (*apps } deployment.Spec.Template.Spec.InitContainers = append(deployment.Spec.Template.Spec.InitContainers, *waitForPostgresInitContainer) } - - if !ctx.CheCluster.Spec.Auth.ExternalIdentityProvider { - waitForKeycloakInitContainer, err := identityprovider.GetWaitForKeycloakInitContainer(ctx) - if err != nil { - return nil, err - } - deployment.Spec.Template.Spec.InitContainers = append(deployment.Spec.Template.Spec.InitContainers, *waitForKeycloakInitContainer) - } } return deployment, nil diff --git a/pkg/deploy/server/server_reconciler_test.go b/pkg/deploy/server/server_reconciler_test.go index 47fe47a02..7eff4234d 100644 --- a/pkg/deploy/server/server_reconciler_test.go +++ b/pkg/deploy/server/server_reconciler_test.go @@ -36,11 +36,6 @@ func TestReconcile(t *testing.T) { Namespace: "eclipse-che", Name: os.Getenv("CHE_FLAVOR"), }, - Spec: orgv1.CheClusterSpec{ - Server: orgv1.CheClusterSpecServer{ - TlsSupport: true, - }, - }, } util.IsOpenShift = true @@ -70,11 +65,6 @@ func TestSyncLegacyConfigMap(t *testing.T) { Namespace: "eclipse-che", Name: "eclipse-che", }, - Spec: orgv1.CheClusterSpec{ - Server: orgv1.CheClusterSpecServer{ - TlsSupport: true, - }, - }, } ctx := deploy.GetTestDeployContext(cheCluster, []runtime.Object{}) diff --git a/pkg/deploy/server/server_util.go b/pkg/deploy/server/server_util.go index f86ff565e..2fd9d7153 100644 --- a/pkg/deploy/server/server_util.go +++ b/pkg/deploy/server/server_util.go @@ -14,10 +14,7 @@ package server import ( "fmt" - orgv1 "github.com/eclipse-che/che-operator/api/v1" "github.com/eclipse-che/che-operator/pkg/deploy" - "github.com/eclipse-che/che-operator/pkg/deploy/gateway" - "github.com/eclipse-che/che-operator/pkg/util" corev1 "k8s.io/api/core/v1" ) @@ -25,13 +22,6 @@ func getComponentName(ctx *deploy.DeployContext) string { return deploy.DefaultCheFlavor(ctx.CheCluster) } -func getServerExposingServiceName(cr *orgv1.CheCluster) string { - if util.GetServerExposureStrategy(cr) == "single-host" && deploy.GetSingleHostExposureType(cr) == deploy.GatewaySingleHostExposureType { - return gateway.GatewayServiceName - } - return deploy.CheServiceName -} - func getOAuthConfig(ctx *deploy.DeployContext, oauthProvider string) (*corev1.Secret, error) { secrets, err := deploy.GetSecrets(ctx, map[string]string{ deploy.KubernetesPartOfLabelKey: deploy.CheEclipseOrg, diff --git a/pkg/deploy/tls/tls_secret.go b/pkg/deploy/tls/tls_secret.go index 593c9adca..67797b9a7 100644 --- a/pkg/deploy/tls/tls_secret.go +++ b/pkg/deploy/tls/tls_secret.go @@ -15,7 +15,6 @@ package tls import ( "github.com/eclipse-che/che-operator/pkg/deploy" "github.com/eclipse-che/che-operator/pkg/util" - "github.com/sirupsen/logrus" "sigs.k8s.io/controller-runtime/pkg/reconcile" ) @@ -30,42 +29,23 @@ func NewTlsSecretReconciler() *TlsSecretReconciler { func (t *TlsSecretReconciler) Reconcile(ctx *deploy.DeployContext) (reconcile.Result, bool, error) { if util.IsOpenShift { // create a secret with router tls cert when on OpenShift infra and router is configured with a self signed certificate - if ctx.IsSelfSignedCertificate || - // To use Openshift v4 OAuth, the OAuth endpoints are served from a namespace - // and NOT from the Openshift API Master URL (as in v3) - // So we also need the self-signed certificate to access them (same as the Che server) - (util.IsOpenShift4 && ctx.CheCluster.IsOpenShiftOAuthEnabled() && !ctx.CheCluster.Spec.Server.TlsSupport) { + if ctx.IsSelfSignedCertificate { if err := CreateTLSSecretFromEndpoint(ctx, "", deploy.CheTLSSelfSignedCertificateSecretName); err != nil { return reconcile.Result{}, false, err } } - - if util.IsOpenShift && ctx.CheCluster.IsOpenShiftOAuthEnabled() { - // create a secret with OpenShift API crt to be added to keystore that RH SSO will consume - apiUrl, apiInternalUrl, err := util.GetOpenShiftAPIUrls() - if err != nil { - logrus.Errorf("Failed to get OpenShift cluster public hostname. A secret with API crt will not be created and consumed by RH-SSO/Keycloak") - } else { - baseURL := map[bool]string{true: apiInternalUrl, false: apiUrl}[apiInternalUrl != ""] - if err := CreateTLSSecretFromEndpoint(ctx, baseURL, "openshift-api-crt"); err != nil { - return reconcile.Result{}, false, err - } - } - } } else { // Handle Che TLS certificates on Kubernetes infrastructure - if ctx.CheCluster.Spec.Server.TlsSupport { - if ctx.CheCluster.Spec.K8s.TlsSecretName != "" { - // Self-signed certificate should be created to secure Che ingresses - result, err := K8sHandleCheTLSSecrets(ctx) - if result.Requeue || result.RequeueAfter > 0 { - return result, false, err - } - } else if ctx.IsSelfSignedCertificate { - // Use default self-signed ingress certificate - if err := CreateTLSSecretFromEndpoint(ctx, "", deploy.CheTLSSelfSignedCertificateSecretName); err != nil { - return reconcile.Result{}, false, err - } + if ctx.CheCluster.Spec.K8s.TlsSecretName != "" { + // Self-signed certificate should be created to secure Che ingresses + result, err := K8sHandleCheTLSSecrets(ctx) + if result.Requeue || result.RequeueAfter > 0 { + return result, false, err + } + } else if ctx.IsSelfSignedCertificate { + // Use default self-signed ingress certificate + if err := CreateTLSSecretFromEndpoint(ctx, "", deploy.CheTLSSelfSignedCertificateSecretName); err != nil { + return reconcile.Result{}, false, err } } } diff --git a/pkg/util/util.go b/pkg/util/util.go index d68e3a114..89eec82c1 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -15,14 +15,10 @@ import ( "bytes" "context" "crypto/sha256" - "crypto/tls" "encoding/base64" - "encoding/json" - "errors" "fmt" "io/ioutil" "math/rand" - "net/http" "os" "regexp" "runtime" @@ -199,23 +195,6 @@ func MergeMaps(first map[string]string, second map[string]string) map[string]str return ret } -func GetServerExposureStrategy(cheCluster *orgv1.CheCluster) string { - if cheCluster.Spec.Server.ServerExposureStrategy != "" { - return cheCluster.Spec.Server.ServerExposureStrategy - } - - if !IsOpenShift && cheCluster.Spec.K8s.IngressStrategy != "" { - return cheCluster.Spec.K8s.IngressStrategy - } - - // Explicitly switch to `single-host` mode - if cheCluster.Spec.DevWorkspace.Enable { - return "single-host" - } - - return "multi-host" -} - func IsTestMode() (isTesting bool) { testMode := os.Getenv("MOCK_API") if len(testMode) == 0 { @@ -224,103 +203,6 @@ func IsTestMode() (isTesting bool) { return true } -func GetOpenShiftAPIUrls() (string, string, error) { - // for debug purpose - apiUrl := os.Getenv("CLUSTER_API_URL") - apiInternalUrl := os.Getenv("CLUSTER_API_INTERNAL_URL") - if apiUrl != "" || apiInternalUrl != "" { - return apiUrl, apiInternalUrl, nil - } - - if IsOpenShift4 { - return getAPIUrlsForOpenShiftV4() - } - - return getAPIUrlsForOpenShiftV3() -} - -// getAPIUrlsForOpenShiftV3 is a hacky way to get OpenShift API public DNS/IP -// to be used in OpenShift oAuth provider as baseURL -func getAPIUrlsForOpenShiftV3() (apiUrl string, apiInternalUrl string, err error) { - http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} - client := &http.Client{} - kubeApi := os.Getenv("KUBERNETES_PORT_443_TCP_ADDR") - url := "https://" + kubeApi + "/.well-known/oauth-authorization-server" - req, err := http.NewRequest(http.MethodGet, url, nil) - resp, err := client.Do(req) - if err != nil { - logrus.Errorf("An error occurred when getting API public hostname: %s", err) - return "", "", err - } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - logrus.Errorf("An error occurred when getting API public hostname: %s", err) - return "", "", err - } - var jsonData map[string]interface{} - err = json.Unmarshal(body, &jsonData) - if err != nil { - logrus.Errorf("An error occurred when unmarshalling: %s", err) - return "", "", err - } - apiUrl = jsonData["issuer"].(string) - return apiUrl, "", nil -} - -// getClusterPublicHostnameForOpenshiftV3 is a way to get OpenShift API public DNS/IP -// to be used in OpenShift oAuth provider as baseURL -func getAPIUrlsForOpenShiftV4() (apiUrl string, apiInternalUrl string, err error) { - http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} - client := &http.Client{} - kubeApi := os.Getenv("KUBERNETES_PORT_443_TCP_ADDR") - url := "https://" + kubeApi + "/apis/config.openshift.io/v1/infrastructures/cluster" - req, err := http.NewRequest(http.MethodGet, url, nil) - file, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token") - if err != nil { - logrus.Errorf("Failed to locate token file: %s", err) - return "", "", err - } - token := string(file) - - req.Header = http.Header{ - "Authorization": []string{"Bearer " + token}, - } - resp, err := client.Do(req) - if err != nil { - logrus.Errorf("An error occurred when getting API public hostname: %s", err) - return "", "", err - } - defer resp.Body.Close() - if resp.StatusCode/100 != 2 { - message := url + " - " + resp.Status - logrus.Errorf("An error occurred when getting API public hostname: %s", message) - return "", "", errors.New(message) - } - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - logrus.Errorf("An error occurred when getting API public hostname: %s", err) - return "", "", err - } - var jsonData map[string]interface{} - err = json.Unmarshal(body, &jsonData) - if err != nil { - logrus.Errorf("An error occurred when unmarshalling while getting API public hostname: %s", err) - return "", "", err - } - switch status := jsonData["status"].(type) { - case map[string]interface{}: - apiUrl = status["apiServerURL"].(string) - apiInternalUrl = status["apiServerInternalURI"].(string) - default: - logrus.Errorf("An error occurred when unmarshalling while getting API public hostname: %s", body) - return "", "", errors.New(string(body)) - } - - return apiUrl, apiInternalUrl, nil -} - func GetRouterCanonicalHostname(client client.Client, namespace string) (string, error) { testRouteYaml, err := GetTestRouteYaml(client, namespace) if err != nil { @@ -479,22 +361,6 @@ func NewBoolPointer(value bool) *bool { return &variable } -// GetWorkspaceNamespaceDefault - returns workspace namespace default strategy, which points on the namespaces used for workspaces execution. -func GetWorkspaceNamespaceDefault(cr *orgv1.CheCluster) string { - if cr.Spec.Server.CustomCheProperties != nil { - k8sNamespaceDefault := cr.Spec.Server.CustomCheProperties["CHE_INFRA_KUBERNETES_NAMESPACE_DEFAULT"] - if k8sNamespaceDefault != "" { - return k8sNamespaceDefault - } - } - - workspaceNamespaceDefault := cr.Namespace - if IsOpenShift && cr.IsOpenShiftOAuthEnabled() { - workspaceNamespaceDefault = "-" + cr.Spec.Server.CheFlavor - } - return GetValue(cr.Spec.Server.WorkspaceNamespaceDefault, workspaceNamespaceDefault) -} - func GetResourceQuantity(value string, defaultValue string) resource.Quantity { if value != "" { return resource.MustParse(value) @@ -565,11 +431,5 @@ func ClearMetadata(objectMeta *metav1.ObjectMeta) { // GetCheURL returns Che url. func GetCheURL(cheCluster *orgv1.CheCluster) string { - var cheUrl string - if cheCluster.Spec.Server.TlsSupport { - cheUrl = "https://" + cheCluster.Spec.Server.CheHost - } else { - cheUrl = "http://" + cheCluster.Spec.Server.CheHost - } - return cheUrl + return "https://" + cheCluster.Spec.Server.CheHost } diff --git a/templates/create-github-identity-provider.sh b/templates/create-github-identity-provider.sh deleted file mode 100755 index f01e0c99e..000000000 --- a/templates/create-github-identity-provider.sh +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright (c) 2019-2021 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 -# - -connectToKeycloak() { - {{ .Script }} config credentials --server http://0.0.0.0:8080/auth --realm master --user {{ .KeycloakAdminUserName }} --password {{ .KeycloakAdminPassword }} -} - -createIdentityProvider() { - {{ .Script }} get identity-provider/instances/{{ .ProviderId }} -r {{ .KeycloakRealm }} - if [ $? -eq 0 ]; then - echo "{{ .ProviderId }} identity provider exists." - else - echo "Create new {{ .ProviderId }} identity provider." - if [ -z "${GITHUB_CLIENT_ID}" ] || [ -z "${GITHUB_SECRET}" ]; then - echo "Either 'GITHUB_CLIENT_ID' or 'GITHUB_SECRET' aren't set" 1>&2 - exit 1 - fi - {{ .Script }} create identity-provider/instances \ - -r {{ .KeycloakRealm }} \ - -s alias={{ .ProviderId }} \ - -s providerId={{ .ProviderId }} \ - -s enabled=true \ - -s storeToken=true \ - -s config.useJwksUrl=true \ - -s config.clientId=${GITHUB_CLIENT_ID} \ - -s config.clientSecret=${GITHUB_SECRET} \ - -s config.defaultScope=repo,user,write:public_key - fi -} - -connectToKeycloak -createIdentityProvider diff --git a/templates/delete-identity-provider.sh b/templates/delete-identity-provider.sh deleted file mode 100755 index fe05923d3..000000000 --- a/templates/delete-identity-provider.sh +++ /dev/null @@ -1,28 +0,0 @@ -# -# Copyright (c) 2019-2021 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 -# - -connectToKeycloak() { - {{ .Script }} config credentials --server http://0.0.0.0:8080/auth --realm master --user {{ .KeycloakAdminUserName }} --password {{ .KeycloakAdminPassword }} -} - -deleteIdentityProvider() { - {{ .Script }} get identity-provider/instances/{{ .ProviderId }} -r {{ .KeycloakRealm }} - if [ ! $? -eq 0 ]; then - echo "{{ .ProviderId }} identity provider does not exists." - else - echo "Delete {{ .ProviderId }} identity provider." - {{ .Script }} delete identity-provider/instances/{{ .ProviderId }} -r {{ .KeycloakRealm }} - fi -} - -connectToKeycloak -deleteIdentityProvider diff --git a/templates/keycloak-provision.sh b/templates/keycloak-provision.sh deleted file mode 100755 index 1003af4b8..000000000 --- a/templates/keycloak-provision.sh +++ /dev/null @@ -1,89 +0,0 @@ -# -# Copyright (c) 2019-2021 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 -# - -connectToKeycloak() { - {{ .Script }} config credentials --server http://0.0.0.0:8080/auth --realm master --user {{ .KeycloakAdminUserName }} --password {{ .KeycloakAdminPassword }} -} - -provisionKeycloak() { - {{ .Script }} update realms/master -s sslRequired=none - {{ .Script }} config truststore --trustpass ${SSO_TRUSTSTORE_PASSWORD} ${SSO_TRUSTSTORE_DIR}/${SSO_TRUSTSTORE} - - {{ .Script }} get realms/{{ .KeycloakRealm }} - if [ $? -eq 0 ]; then - echo "{{ .KeycloakRealm }} realm exists." - exit 0 - fi - - echo "Provision {{ .KeycloakRealm }} realm." - {{ .Script }} create realms \ - -s realm='{{ .KeycloakRealm }}' \ - -s displayName='{{ .RealmDisplayName }}' \ - -s enabled=true \ - -s sslRequired=none \ - -s registrationAllowed=false \ - -s resetPasswordAllowed=true \ - -s loginTheme={{ .KeycloakTheme }} \ - -s accountTheme={{ .KeycloakTheme }} \ - -s adminTheme={{ .KeycloakTheme }} \ - -s emailTheme={{ .KeycloakTheme }} - - DEFAULT_WEBORIGINS='"http://{{ .CheHost }}", "https://{{ .CheHost }}"' - # ADDITIONAL_WEBORIGINS is an env var in format '"url1", "url2"' - # which if specified, is provisioned to keycloak additionally to Che's URLs ones - [ ! -z "$ADDITIONAL_WEBORIGINS" ] && ADDITIONAL_WEBORIGINS=", $ADDITIONAL_WEBORIGINS" - WEBORIGINS="[$DEFAULT_WEBORIGINS $ADDITIONAL_WEBORIGINS]" - - DEFAULT_REDIRECT_URIS='"http://{{ .CheHost }}/dashboard/*", "https://{{ .CheHost }}/dashboard/*", "http://{{ .CheHost }}/factory*", "https://{{ .CheHost }}/factory*", "http://{{ .CheHost }}/f*", "https://{{ .CheHost }}/f*", "http://{{ .CheHost }}/_app/*", "https://{{ .CheHost }}/_app/*", "http://{{ .CheHost }}/swagger/*", "https://{{ .CheHost }}/swagger/*"' - # ADDITIONAL_REDIRECT_URIS is an env var in format '"url1", "url2"' - # which if specified, is provisioned to keycloak additionally to Che's URLs ones - [ ! -z "$ADDITIONAL_REDIRECT_URIS" ] && ADDITIONAL_REDIRECT_URIS=", $ADDITIONAL_REDIRECT_URIS" - REDIRECT_URIS="[$DEFAULT_REDIRECT_URIS $ADDITIONAL_REDIRECT_URIS]" - - {{ .Script }} create clients \ - -r '{{ .KeycloakRealm }}' \ - -s clientId={{ .KeycloakClientId }} \ - -s id={{ .KeycloakClientId }} \ - -s webOrigins="$WEBORIGINS" \ - -s redirectUris="$REDIRECT_URIS" \ - -s directAccessGrantsEnabled=true \ - -s publicClient=true - - {{ .Script }} create users \ - -r '{{ .KeycloakRealm }}' \ - -s username=admin \ - -s email=\"admin@admin.com\" \ - -s enabled=true \ - -s requiredActions='[{{ .RequiredActions }}]' - - {{ .Script }} set-password \ - -r '{{ .KeycloakRealm }}' \ - --username admin \ - --new-password admin - - user_id=$( {{ .Script }} get users -r '{{ .KeycloakRealm }}' -q username=admin --fields 'id' --format csv --noquotes ) - {{ .Script }} update users/${user_id} -r '{{ .KeycloakRealm }}' -s requiredActions='[{{ .RequiredActions }}]' - - {{ .Script }} add-roles \ - -r '{{ .KeycloakRealm }}' \ - --uusername admin \ - --cclientid broker \ - --rolename read-token - - CLIENT_ID=$({{ .Script }} get clients -r '{{ .KeycloakRealm }}' -q clientId=broker | sed -n 's/.*"id" *: *"\([^"]\+\).*/\1/p') - {{ .Script }} update clients/${CLIENT_ID} \ - -r '{{ .KeycloakRealm }}' \ - -s "defaultRoles+=read-token" -} - -connectToKeycloak -provisionKeycloak diff --git a/templates/keycloak-update.sh b/templates/keycloak-update.sh deleted file mode 100755 index 5c181ae30..000000000 --- a/templates/keycloak-update.sh +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright (c) 2019-2021 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 -# - -connectToKeycloak() { - {{ .Script }} config credentials --server http://0.0.0.0:8080/auth --realm master --user {{ .KeycloakAdminUserName }} --password {{ .KeycloakAdminPassword }} -} - -updateKeycloak() { - DEFAULT_WEBORIGINS='"http://{{ .CheHost }}", "https://{{ .CheHost }}"' - # ADDITIONAL_WEBORIGINS is an env var in format '"url1", "url2"' - # which if specified, is provisioned to keycloak additionally to Che's URLs ones - [ ! -z "$ADDITIONAL_WEBORIGINS" ] && ADDITIONAL_WEBORIGINS=", $ADDITIONAL_WEBORIGINS" - WEBORIGINS="[$DEFAULT_WEBORIGINS $ADDITIONAL_WEBORIGINS]" - - DEFAULT_REDIRECT_URIS='"http://{{ .CheHost }}/dashboard/*", "https://{{ .CheHost }}/dashboard/*", "http://{{ .CheHost }}/factory*", "https://{{ .CheHost }}/factory*", "http://{{ .CheHost }}/f*", "https://{{ .CheHost }}/f*", "http://{{ .CheHost }}/_app/*", "https://{{ .CheHost }}/_app/*", "http://{{ .CheHost }}/swagger/*", "https://{{ .CheHost }}/swagger/*"' - # ADDITIONAL_REDIRECT_URIS is an env var in format '"url1", "url2"' - # which if specified, is provisioned to keycloak additionally to Che's URLs ones - [ ! -z "$ADDITIONAL_REDIRECT_URIS" ] && ADDITIONAL_REDIRECT_URIS=", $ADDITIONAL_REDIRECT_URIS" - REDIRECT_URIS="[$DEFAULT_REDIRECT_URIS $ADDITIONAL_REDIRECT_URIS]" - - {{ .Script }} update clients/{{ .KeycloakClientId }} \ - -r '{{ .KeycloakRealm }}' \ - -s webOrigins="$WEBORIGINS" \ - -s redirectUris="$REDIRECT_URIS" -} - -checkKeycloak() { - REDIRECT_URIS=$({{ .Script }} get clients/{{ .KeycloakClientId }} -r '{{ .KeycloakRealm }}' | jq '.redirectUris') - FIND="http://{{ .CheHost }}/factory*" - for URI in "${REDIRECT_URIS[@]}"; do - [[ $FIND == "$URI" ]] && return 0 - done - return 1 -} - -connectToKeycloak -checkKeycloak -if [ $? -ne 0 ] -then - updateKeycloak -fi diff --git a/templates/oauth-provision.sh b/templates/oauth-provision.sh deleted file mode 100755 index 31db616bf..000000000 --- a/templates/oauth-provision.sh +++ /dev/null @@ -1,114 +0,0 @@ -# -# Copyright (c) 2019-2021 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 -# - -connect_to_keycloak() { - {{ .Script }} config credentials --server http://0.0.0.0:8080/auth --realm master --user {{ .KeycloakAdminUserName }} --password {{ .KeycloakAdminPassword }} - {{ .Script }} config truststore --trustpass ${SSO_TRUSTSTORE_PASSWORD} ${SSO_TRUSTSTORE_DIR}/${SSO_TRUSTSTORE} -} - -create_identity_provider() { - {{ .Script }} get identity-provider/instances/{{ .ProviderId }} -r {{ .KeycloakRealm }} - if [ $? -eq 0 ] - then echo "Provider exists" - else {{ .Script }} create identity-provider/instances -r {{ .KeycloakRealm }} -s alias={{ .ProviderId }} -s providerId={{ .ProviderId }} -s enabled=true -s storeToken=true -s addReadTokenRoleOnCreate=true -s config.useJwksUrl=true -s config.clientId={{ .OAuthClientName}} -s config.clientSecret={{ .OauthSecret}} -s config.baseUrl={{ .OpenShiftApiUrl }} -s config.defaultScope=user:full - fi -} - -default_to_openshift_login() { - EXECUTION_ID=$({{ .Script }} get authentication/flows/browser/executions -r {{ .KeycloakRealm }} -c | sed -e 's/.*\({[^}]\+"identity-provider-redirector"[^}]\+}\).*/\1/' -e 's/.*"id":"\([^"]\+\)".*/\1/') - ALIAS=$({{ .Script }} get authentication/flows/browser/executions -r {{ .KeycloakRealm }} -c | sed -e 's/.*\({[^}]\+"identity-provider-redirector"[^}]\+}\).*/\1/' | grep '"alias":"' | sed -e 's/.*"alias":"\([^"]\+\)".*/\1/') - if [ "${EXECUTION_ID}" == "" ] - then - echo "Could not find the identity provider redirector" - return 1 - fi - if [ -z ${ALIAS} ]; - then - echo '{"config":{"defaultProvider":"{{ .ProviderId }}"},"alias":"{{ .ProviderId }}"}' | {{ .Script }} create -r {{ .KeycloakRealm }} authentication/executions/${EXECUTION_ID}/config -f - - fi -} - -enable_openshift_token-exchange() { - IDENTITY_PROVIDER_ID=$({{ .Script }} get -r {{ .KeycloakRealm }} identity-provider/instances/{{ .ProviderId }} | grep -e '"internalId" *: *"' | sed -e 's/.*"internalId" *: *"\([^"]\+\)".*/\1/') - if [ "${IDENTITY_PROVIDER_ID}" == "" ] - then - echo "identity provider not found" - return 1 - fi - echo '{"enabled": true}' | {{ .Script }} update -r {{ .KeycloakRealm }} identity-provider/instances/{{ .ProviderId }}/management/permissions -f - - if [ $? -ne 0 ] - then - echo "failed to enable permissions on identity provider" - return 1 - fi - TOKEN_EXCHANGE_PERMISSIONS=$({{ .Script }} get -r {{ .KeycloakRealm }} identity-provider/instances/{{ .ProviderId }}/management/permissions) - if [ "${TOKEN_EXCHANGE_PERMISSIONS}" == "" ] - then - echo "token exchange permissions not found" - return 1 - fi - TOKEN_EXCHANGE_RESOURCE=$(echo ${TOKEN_EXCHANGE_PERMISSIONS} | grep -e '"resource" *: *"' | sed -e 's/.*"resource" *: *"\([^"]\+\)".*/\1/') - TOKEN_EXCHANGE_PERMISSION_ID=$(echo ${TOKEN_EXCHANGE_PERMISSIONS} | sed -e 's/.*"scopePermissions" *: *{ *"token-exchange" *: *"\([^"]\+\)".*/\1/') - if [ "${TOKEN_EXCHANGE_RESOURCE}" == "" ] || [ "${TOKEN_EXCHANGE_PERMISSION_ID}" == "" ] - then - echo "token exchange permissions do not contain expected values" - return 1 - fi - REALM_MGMT_CLIENT_ID=$({{ .Script }} get -r {{ .KeycloakRealm }} clients -q clientId=realm-management | grep -e '"id" *: *"' | sed -e 's/.*"id" *: *"\([^"]\+\)".*/\1/') - if [ "${REALM_MGMT_CLIENT_ID}" == "" ] - then - echo "Realm management client ID not found" - return 1 - fi - EXISTING_POLICY=$({{ .Script }} get -r {{ .KeycloakRealm }} clients/${REALM_MGMT_CLIENT_ID}/authz/resource-server/policy/client -q 'name={{ .ProviderId }}' | grep -e '"id" *: *"' | sed -e 's/.*"id" *: *"\([^"]\+\)".*/\1/') - if [ "${EXISTING_POLICY}" == "" ] - then - echo '{"type":"client","logic":"POSITIVE","decisionStrategy":"UNANIMOUS","name":"{{ .ProviderId }}","clients":["{{ .KeycloakClientId }}"]}' | {{ .Script }} create -r {{ .KeycloakRealm }} clients/${REALM_MGMT_CLIENT_ID}/authz/resource-server/policy/client -f - - if [ $? -ne 0 ] - then - echo "Failed to create policy" - return 1 - fi - fi - TOKEN_EXCHANGE_POLICY=$({{ .Script }} get -r {{ .KeycloakRealm }} clients/${REALM_MGMT_CLIENT_ID}/authz/resource-server/policy/client -q 'name={{ .ProviderId }}' | grep -e '"id" *: *"' | sed -e 's/.*"id" *: *"\([^"]\+\)".*/\1/') - if [ "${TOKEN_EXCHANGE_POLICY}" == "" ] - then - echo "Token exchange policy not found" - return 1 - fi - TOKEN_EXCHANGE_PERMISSION=$({{ .Script }} get -r {{ .KeycloakRealm }} clients/${REALM_MGMT_CLIENT_ID}/authz/resource-server/permission/scope/${TOKEN_EXCHANGE_PERMISSION_ID}) - if [ "${TOKEN_EXCHANGE_PERMISSION}" == "" ] - then - echo "Token exchange permission not found" - return 1 - fi - TOKEN_EXCHANGE_SCOPES=$({{ .Script }} get -r {{ .KeycloakRealm }} clients/${REALM_MGMT_CLIENT_ID}/authz/resource-server/resource/${TOKEN_EXCHANGE_RESOURCE}/scopes) - if [ "${TOKEN_EXCHANGE_SCOPES}" == "" ] - then - echo "Token exchange scopes not found" - return 1 - fi - TOKEN_EXCHANGE_SCOPE=$(echo ${TOKEN_EXCHANGE_SCOPES} | sed -e 's/.*"id" *: *"\([^"]\+\)" *, *"name" *: *"token-exchange".*/\1/') - if [ "${TOKEN_EXCHANGE_SCOPE}" == "" ] - then - echo "Token exchange scope not found" - return 1 - fi - PERMISSION_RESOURCES=$(echo ${TOKEN_EXCHANGE_PERMISSION} | grep -e 'resources *:') - if [ "${PERMISSION_RESOURCES}" == "" ] - then - echo ${TOKEN_EXCHANGE_PERMISSION} | sed -e "s/ *{\(.*}\) */{\"resources\":[\"${TOKEN_EXCHANGE_RESOURCE}\"],\"scopes\":[\"${TOKEN_EXCHANGE_SCOPE}\"],\"policies\":[\"${TOKEN_EXCHANGE_POLICY}\"],\1/" | {{ .Script }} update -r {{ .KeycloakRealm }} clients/${REALM_MGMT_CLIENT_ID}/authz/resource-server/permission/scope/${TOKEN_EXCHANGE_PERMISSION_ID} -f - - fi -} - -set -x -connect_to_keycloak && create_identity_provider && default_to_openshift_login && enable_openshift_token-exchange