From 88cb1ed7acb3d55bd1bbf4d2e63dc7df9c486a1e Mon Sep 17 00:00:00 2001 From: Michal Vala Date: Fri, 3 Dec 2021 12:20:46 +0100 Subject: [PATCH] feat: native auth kube (#1185) Signed-off-by: Michal Vala --- .../che-operator.clusterserviceversion.yaml | 8 +- .../che-operator.clusterserviceversion.yaml | 8 +- .../che-operator.clusterserviceversion.yaml | 8 +- config/manager/manager.yaml | 4 + controllers/che/checluster_controller.go | 2 +- controllers/che/checluster_controller_test.go | 4 +- controllers/che/create.go | 4 +- controllers/che/gateway_permission.go | 3 +- .../devworkspace/solver/che_routing.go | 19 +- .../devworkspace/solver/che_routing_test.go | 87 ++++---- helmcharts/next/templates/manager.yaml | 4 + pkg/deploy/defaults.go | 4 + .../dev-workspace/dev_workspace_test.go | 2 + pkg/deploy/gateway/gateway.go | 191 +++--------------- pkg/deploy/gateway/gateway_test.go | 1 + pkg/deploy/gateway/kube_rbac_proxy.go | 81 ++++++++ pkg/deploy/gateway/oauth_proxy.go | 162 +++++++++++++++ .../identity-provider/identity_provider.go | 15 +- pkg/deploy/server/server_configmap.go | 35 +++- pkg/deploy/server/server_configmap_test.go | 20 +- pkg/deploy/server/server_deployment.go | 2 +- 21 files changed, 412 insertions(+), 252 deletions(-) create mode 100644 pkg/deploy/gateway/kube_rbac_proxy.go create mode 100644 pkg/deploy/gateway/oauth_proxy.go diff --git a/bundle/next-all-namespaces/eclipse-che-preview-openshift/manifests/che-operator.clusterserviceversion.yaml b/bundle/next-all-namespaces/eclipse-che-preview-openshift/manifests/che-operator.clusterserviceversion.yaml index 061119ea6..cf82654f1 100644 --- a/bundle/next-all-namespaces/eclipse-che-preview-openshift/manifests/che-operator.clusterserviceversion.yaml +++ b/bundle/next-all-namespaces/eclipse-che-preview-openshift/manifests/che-operator.clusterserviceversion.yaml @@ -126,7 +126,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.40.0-380.next-all-namespaces + name: eclipse-che-preview-openshift.v7.40.0-381.next-all-namespaces namespace: placeholder spec: apiservicedefinitions: {} @@ -1134,6 +1134,10 @@ spec: value: quay.io/openshift/origin-oauth-proxy:4.7 - name: RELATED_IMAGE_gateway_authorization_sidecar value: quay.io/openshift/origin-kube-rbac-proxy:4.7 + - name: RELATED_IMAGE_gateway_authentication_sidecar_k8s + value: quay.io/oauth2-proxy/oauth2-proxy:v7.2.0 + - name: RELATED_IMAGE_gateway_authorization_sidecar_k8s + value: quay.io/brancz/kube-rbac-proxy:v0.11.0 - name: RELATED_IMAGE_gateway_header_sidecar value: quay.io/che-incubator/header-rewrite-proxy:latest - name: CHE_FLAVOR @@ -1439,4 +1443,4 @@ spec: maturity: stable provider: name: Eclipse Foundation - version: 7.40.0-380.next-all-namespaces + version: 7.40.0-381.next-all-namespaces diff --git a/bundle/next/eclipse-che-preview-kubernetes/manifests/che-operator.clusterserviceversion.yaml b/bundle/next/eclipse-che-preview-kubernetes/manifests/che-operator.clusterserviceversion.yaml index a0032ae5c..90421dde4 100644 --- a/bundle/next/eclipse-che-preview-kubernetes/manifests/che-operator.clusterserviceversion.yaml +++ b/bundle/next/eclipse-che-preview-kubernetes/manifests/che-operator.clusterserviceversion.yaml @@ -133,7 +133,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-kubernetes.v7.40.0-380.next + name: eclipse-che-preview-kubernetes.v7.40.0-381.next namespace: placeholder spec: apiservicedefinitions: {} @@ -1123,6 +1123,10 @@ spec: value: quay.io/openshift/origin-oauth-proxy:4.7 - name: RELATED_IMAGE_gateway_authorization_sidecar value: quay.io/openshift/origin-kube-rbac-proxy:4.7 + - name: RELATED_IMAGE_gateway_authentication_sidecar_k8s + value: quay.io/oauth2-proxy/oauth2-proxy:v7.2.0 + - name: RELATED_IMAGE_gateway_authorization_sidecar_k8s + value: quay.io/brancz/kube-rbac-proxy:v0.11.0 - name: RELATED_IMAGE_gateway_header_sidecar value: quay.io/che-incubator/header-rewrite-proxy:latest - name: CHE_FLAVOR @@ -1406,4 +1410,4 @@ spec: maturity: stable provider: name: Eclipse Foundation - version: 7.40.0-380.next + version: 7.40.0-381.next 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 178a7d2f8..f429392c7 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 @@ -126,7 +126,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.40.0-380.next + name: eclipse-che-preview-openshift.v7.40.0-381.next namespace: placeholder spec: apiservicedefinitions: {} @@ -1134,6 +1134,10 @@ spec: value: quay.io/openshift/origin-oauth-proxy:4.7 - name: RELATED_IMAGE_gateway_authorization_sidecar value: quay.io/openshift/origin-kube-rbac-proxy:4.7 + - name: RELATED_IMAGE_gateway_authentication_sidecar_k8s + value: quay.io/oauth2-proxy/oauth2-proxy:v7.2.0 + - name: RELATED_IMAGE_gateway_authorization_sidecar_k8s + value: quay.io/brancz/kube-rbac-proxy:v0.11.0 - name: RELATED_IMAGE_gateway_header_sidecar value: quay.io/che-incubator/header-rewrite-proxy:latest - name: CHE_FLAVOR @@ -1439,4 +1443,4 @@ spec: maturity: stable provider: name: Eclipse Foundation - version: 7.40.0-380.next + version: 7.40.0-381.next diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index e06e4e74a..3dff8b6e7 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -97,6 +97,10 @@ spec: value: quay.io/openshift/origin-oauth-proxy:4.7 - name: RELATED_IMAGE_gateway_authorization_sidecar value: quay.io/openshift/origin-kube-rbac-proxy:4.7 + - name: RELATED_IMAGE_gateway_authentication_sidecar_k8s + value: quay.io/oauth2-proxy/oauth2-proxy:v7.2.0 + - name: RELATED_IMAGE_gateway_authorization_sidecar_k8s + value: quay.io/brancz/kube-rbac-proxy:v0.11.0 - name: RELATED_IMAGE_gateway_header_sidecar value: quay.io/che-incubator/header-rewrite-proxy:latest - name: CHE_FLAVOR diff --git a/controllers/che/checluster_controller.go b/controllers/che/checluster_controller.go index 0dee52578..22da34569 100644 --- a/controllers/che/checluster_controller.go +++ b/controllers/che/checluster_controller.go @@ -523,7 +523,7 @@ func (r *CheClusterReconciler) reconcileFinalizers(deployContext *deploy.DeployC } } - if util.IsOpenShift && deployContext.CheCluster.IsNativeUserModeEnabled() { + if deployContext.CheCluster.IsNativeUserModeEnabled() { if _, err := r.reconcileGatewayPermissionsFinalizers(deployContext); err != nil { logrus.Error(err) } diff --git a/controllers/che/checluster_controller_test.go b/controllers/che/checluster_controller_test.go index a87acad2c..aa27fb37f 100644 --- a/controllers/che/checluster_controller_test.go +++ b/controllers/che/checluster_controller_test.go @@ -106,11 +106,11 @@ func TestNativeUserModeEnabled(t *testing.T) { expectedNativeUserValue: pointer.BoolPtr(true), }, { - name: "che-operator should not modify nativeUserMode when not on openshift", + 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: nil, + expectedNativeUserValue: pointer.BoolPtr(true), }, { name: "che-operator not modify nativeUserMode when devworkspace not enabled", diff --git a/controllers/che/create.go b/controllers/che/create.go index 84258f191..1f145d1d7 100644 --- a/controllers/che/create.go +++ b/controllers/che/create.go @@ -140,7 +140,7 @@ func (r *CheClusterReconciler) GenerateAndSaveFields(deployContext *deploy.Deplo } } - if !util.IsOpenShift || !deployContext.CheCluster.IsNativeUserModeEnabled() { + if !deployContext.CheCluster.IsNativeUserModeEnabled() { keycloakRealm := util.GetValue(deployContext.CheCluster.Spec.Auth.IdentityProviderRealm, cheFlavor) if len(deployContext.CheCluster.Spec.Auth.IdentityProviderRealm) < 1 { deployContext.CheCluster.Spec.Auth.IdentityProviderRealm = keycloakRealm @@ -249,7 +249,7 @@ func (r *CheClusterReconciler) GenerateAndSaveFields(deployContext *deploy.Deplo } } - if util.IsOpenShift && deployContext.CheCluster.Spec.DevWorkspace.Enable && deployContext.CheCluster.Spec.Auth.NativeUserMode == nil { + if deployContext.CheCluster.Spec.DevWorkspace.Enable && deployContext.CheCluster.Spec.Auth.NativeUserMode == nil { newNativeUserModeValue := util.NewBoolPointer(true) deployContext.CheCluster.Spec.Auth.NativeUserMode = newNativeUserModeValue if err := deploy.UpdateCheCRSpec(deployContext, "nativeUserMode", strconv.FormatBool(*newNativeUserModeValue)); err != nil { diff --git a/controllers/che/gateway_permission.go b/controllers/che/gateway_permission.go index 1138fa17b..fab38fba2 100644 --- a/controllers/che/gateway_permission.go +++ b/controllers/che/gateway_permission.go @@ -16,7 +16,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/deploy/gateway" - "github.com/eclipse-che/che-operator/pkg/util" rbac "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/types" ) @@ -26,7 +25,7 @@ const ( ) func (r *CheClusterReconciler) reconcileGatewayPermissions(deployContext *deploy.DeployContext) (bool, error) { - if util.IsOpenShift && deployContext.CheCluster.IsNativeUserModeEnabled() { + if deployContext.CheCluster.IsNativeUserModeEnabled() { name := gatewayPermisisonsName(deployContext.CheCluster) if _, err := deploy.SyncClusterRoleToCluster(deployContext, name, getGatewayClusterRoleRules()); err != nil { return false, err diff --git a/controllers/devworkspace/solver/che_routing.go b/controllers/devworkspace/solver/che_routing.go index a38ae7429..044df15f3 100644 --- a/controllers/devworkspace/solver/che_routing.go +++ b/controllers/devworkspace/solver/che_routing.go @@ -449,14 +449,14 @@ func provisionMainWorkspaceRoute(cheCluster *v2alpha1.CheCluster, routing *dwo.D // on OpenShift, we need to set authorization header. // This MUST come before Auth, because Auth needs Authorization header to be properly set. cfg.AddAuthHeaderRewrite(dwId) - - // authorize against kube-rbac-proxy in che-gateway. This will be needed for k8s native auth as well. - cfg.AddAuth(dwId, "http://127.0.0.1:8089?namespace="+dwNamespace) - - // make '/healthz' path of main endpoints reachable from outside - routeForHealthzEndpoint(cfg, dwId, routing.Spec.Endpoints) } + // authorize against kube-rbac-proxy in che-gateway. This will be needed for k8s native auth as well. + cfg.AddAuth(dwId, "http://127.0.0.1:8089?namespace="+dwNamespace) + + // make '/healthz' path of main endpoints reachable from outside + routeForHealthzEndpoint(cfg, dwId, routing.Spec.Endpoints) + if contents, err := yaml.Marshal(cfg); err != nil { return nil, err } else { @@ -514,13 +514,10 @@ func addEndpointToTraefikConfig(componentName string, e dw.Endpoint, cfg *gatewa 100, fmt.Sprintf("http://127.0.0.1:%d", e.TargetPort), []string{prefix}) - if util.IsOpenShift4 { - cfg.AddAuth(name, fmt.Sprintf("http://%s.%s:8089?namespace=%s", gateway.GatewayServiceName, cheCluster.Namespace, routing.Namespace)) - } + cfg.AddAuth(name, fmt.Sprintf("http://%s.%s:8089?namespace=%s", gateway.GatewayServiceName, cheCluster.Namespace, routing.Namespace)) // we need to disable auth for '/healthz' path in main endpoint, for now only on OpenShift - if util.IsOpenShift4 && - e.Attributes.GetString(string(dwo.TypeEndpointAttribute), nil) == string(dwo.MainEndpointType) { + if e.Attributes.GetString(string(dwo.TypeEndpointAttribute), nil) == string(dwo.MainEndpointType) { healthzName := name + "-healthz" healthzPath := prefix + "/healthz" cfg.AddComponent( diff --git a/controllers/devworkspace/solver/che_routing_test.go b/controllers/devworkspace/solver/che_routing_test.go index 03565e1c6..b42bfc823 100644 --- a/controllers/devworkspace/solver/che_routing_test.go +++ b/controllers/devworkspace/solver/che_routing_test.go @@ -267,9 +267,7 @@ func TestCreateRelocatedObjectsK8S(t *testing.T) { cms := &corev1.ConfigMapList{} cl.List(context.TODO(), cms) - if len(cms.Items) != 2 { - t.Errorf("there should be 2 configmaps created for the gateway config of the workspace but there were: %d", len(cms.Items)) - } + assert.Len(t, cms.Items, 2) var workspaceMainCfg *corev1.ConfigMap var workspaceCfg *corev1.ConfigMap @@ -282,59 +280,74 @@ func TestCreateRelocatedObjectsK8S(t *testing.T) { } } - if workspaceMainCfg == nil { - t.Fatalf("traefik configuration for the workspace not found") - } + assert.NotNil(t, workspaceMainCfg) traefikMainWorkspaceConfig := workspaceMainCfg.Data["wsid.yml"] - - if len(traefikMainWorkspaceConfig) == 0 { - t.Fatal("No traefik config file found in the main workspace config configmap") - } + assert.NotEmpty(t, traefikMainWorkspaceConfig) traefikWorkspaceConfig := workspaceCfg.Data["workspace.yml"] - if len(traefikWorkspaceConfig) == 0 { - t.Fatal("No traefik config file found in the workspace config configmap") - } + assert.NotEmpty(t, traefikWorkspaceConfig) workspaceConfig := gateway.TraefikConfig{} - if err := yaml.Unmarshal([]byte(traefikWorkspaceConfig), &workspaceConfig); err != nil { - t.Fatal(err) - } - - if len(workspaceConfig.HTTP.Routers) != 1 { - t.Fatalf("Expected 1 traefik router but got %d", len(workspaceConfig.HTTP.Routers)) - } + assert.NoError(t, yaml.Unmarshal([]byte(traefikWorkspaceConfig), &workspaceConfig)) + assert.Len(t, workspaceConfig.HTTP.Routers, 2) wsid := "wsid-m1-9999" - if _, ok := workspaceConfig.HTTP.Routers[wsid]; !ok { - t.Fatal("traefik config doesn't contain expected workspace configuration") - } - - if len(workspaceConfig.HTTP.Routers[wsid].Middlewares) != 1 { - t.Fatalf("Expected 1 middlewares in router but got '%d'", len(workspaceConfig.HTTP.Routers[wsid].Middlewares)) - } - - if len(workspaceConfig.HTTP.Middlewares) != 1 { - t.Fatalf("Expected 1 middlewares set but got '%d'", len(workspaceConfig.HTTP.Middlewares)) - } + assert.Contains(t, workspaceConfig.HTTP.Routers, wsid) + assert.Len(t, workspaceConfig.HTTP.Routers[wsid].Middlewares, 2) + assert.Len(t, workspaceConfig.HTTP.Middlewares, 3) mwares := []string{wsid + gateway.StripPrefixMiddlewareSuffix} for _, mware := range mwares { - if _, ok := workspaceConfig.HTTP.Middlewares[mware]; !ok { - t.Fatalf("traefik config doesn't set middleware '%s'", mware) - } + assert.Contains(t, workspaceConfig.HTTP.Middlewares, mware) found := false for _, r := range workspaceConfig.HTTP.Routers[wsid].Middlewares { if r == mware { found = true } } - if !found { - t.Fatalf("traefik config route doesn't set middleware '%s'", mware) - } + assert.True(t, found) } + workspaceMainConfig := gateway.TraefikConfig{} + assert.NoError(t, yaml.Unmarshal([]byte(traefikMainWorkspaceConfig), &workspaceMainConfig)) + assert.Len(t, workspaceMainConfig.HTTP.Middlewares, 2) + + wsid = "wsid" + mwares = []string{ + wsid + gateway.AuthMiddlewareSuffix, + wsid + gateway.StripPrefixMiddlewareSuffix} + for _, mware := range mwares { + assert.Contains(t, workspaceMainConfig.HTTP.Middlewares, mware) + + found := false + for _, r := range workspaceMainConfig.HTTP.Routers[wsid].Middlewares { + if r == mware { + found = true + } + } + assert.Truef(t, found, "traefik config route doesn't set middleware '%s'", mware) + } + + t.Run("testHealthzEndpointInMainWorkspaceRoute", func(t *testing.T) { + healthzName := "9999-healthz" + assert.Contains(t, workspaceMainConfig.HTTP.Routers, healthzName) + assert.Equal(t, workspaceMainConfig.HTTP.Routers[healthzName].Service, wsid) + assert.Equal(t, workspaceMainConfig.HTTP.Routers[healthzName].Rule, "Path(`/wsid/m1/9999/healthz`)") + assert.NotContains(t, workspaceMainConfig.HTTP.Routers[healthzName].Middlewares, "wsid"+gateway.AuthMiddlewareSuffix) + assert.Contains(t, workspaceMainConfig.HTTP.Routers[healthzName].Middlewares, "wsid"+gateway.StripPrefixMiddlewareSuffix) + assert.NotContains(t, workspaceMainConfig.HTTP.Routers[healthzName].Middlewares, "wsid"+gateway.HeaderRewriteMiddlewareSuffix) + }) + + t.Run("testHealthzEndpointInWorkspaceRoute", func(t *testing.T) { + healthzName := "wsid-m1-9999-healthz" + assert.Contains(t, workspaceConfig.HTTP.Routers, healthzName) + assert.Equal(t, workspaceConfig.HTTP.Routers[healthzName].Service, healthzName) + assert.Equal(t, workspaceConfig.HTTP.Routers[healthzName].Rule, "Path(`/m1/9999/healthz`)") + assert.NotContains(t, workspaceConfig.HTTP.Routers[healthzName].Middlewares, healthzName+gateway.AuthMiddlewareSuffix) + assert.Contains(t, workspaceConfig.HTTP.Routers[healthzName].Middlewares, healthzName+gateway.StripPrefixMiddlewareSuffix) + }) + }) } diff --git a/helmcharts/next/templates/manager.yaml b/helmcharts/next/templates/manager.yaml index e06e4e74a..3dff8b6e7 100644 --- a/helmcharts/next/templates/manager.yaml +++ b/helmcharts/next/templates/manager.yaml @@ -97,6 +97,10 @@ spec: value: quay.io/openshift/origin-oauth-proxy:4.7 - name: RELATED_IMAGE_gateway_authorization_sidecar value: quay.io/openshift/origin-kube-rbac-proxy:4.7 + - name: RELATED_IMAGE_gateway_authentication_sidecar_k8s + value: quay.io/oauth2-proxy/oauth2-proxy:v7.2.0 + - name: RELATED_IMAGE_gateway_authorization_sidecar_k8s + value: quay.io/brancz/kube-rbac-proxy:v0.11.0 - name: RELATED_IMAGE_gateway_header_sidecar value: quay.io/che-incubator/header-rewrite-proxy:latest - name: CHE_FLAVOR diff --git a/pkg/deploy/defaults.go b/pkg/deploy/defaults.go index a6c2116d8..878648b25 100644 --- a/pkg/deploy/defaults.go +++ b/pkg/deploy/defaults.go @@ -211,6 +211,8 @@ func InitDefaultsFromFile(defaultsPath string) { // Don't get some k8s specific env if !util.IsOpenShift { defaultCheTLSSecretsCreationJobImage = util.GetDeploymentEnv(operatorDeployment, util.GetArchitectureDependentEnv("RELATED_IMAGE_che_tls_secrets_creation_job")) + defaultGatewayAuthenticationSidecarImage = util.GetDeploymentEnv(operatorDeployment, util.GetArchitectureDependentEnv("RELATED_IMAGE_gateway_authentication_sidecar_k8s")) + defaultGatewayAuthorizationSidecarImage = util.GetDeploymentEnv(operatorDeployment, util.GetArchitectureDependentEnv("RELATED_IMAGE_gateway_authorization_sidecar_k8s")) } } @@ -494,6 +496,8 @@ func InitDefaultsFromEnv() { // Don't get some k8s specific env if !util.IsOpenShift { defaultCheTLSSecretsCreationJobImage = getDefaultFromEnv(util.GetArchitectureDependentEnv("RELATED_IMAGE_che_tls_secrets_creation_job")) + defaultGatewayAuthenticationSidecarImage = getDefaultFromEnv(util.GetArchitectureDependentEnv("RELATED_IMAGE_gateway_authentication_sidecar_k8s")) + defaultGatewayAuthorizationSidecarImage = getDefaultFromEnv(util.GetArchitectureDependentEnv("RELATED_IMAGE_gateway_authorization_sidecar_k8s")) } } diff --git a/pkg/deploy/dev-workspace/dev_workspace_test.go b/pkg/deploy/dev-workspace/dev_workspace_test.go index 09e389550..ffcd14997 100644 --- a/pkg/deploy/dev-workspace/dev_workspace_test.go +++ b/pkg/deploy/dev-workspace/dev_workspace_test.go @@ -86,6 +86,7 @@ func TestReconcileDevWorkspace(t *testing.T) { }, Server: orgv1.CheClusterSpecServer{ ServerExposureStrategy: "multi-host", + CustomCheProperties: map[string]string{"CHE_INFRA_KUBERNETES_ENABLE__UNSUPPORTED__K8S": "true"}, }, K8s: orgv1.CheClusterSpecK8SOnly{ IngressDomain: "che.domain", @@ -110,6 +111,7 @@ func TestReconcileDevWorkspace(t *testing.T) { }, Server: orgv1.CheClusterSpecServer{ ServerExposureStrategy: "single-host", + CustomCheProperties: map[string]string{"CHE_INFRA_KUBERNETES_ENABLE__UNSUPPORTED__K8S": "true"}, }, K8s: orgv1.CheClusterSpecK8SOnly{ IngressDomain: "che.domain", diff --git a/pkg/deploy/gateway/gateway.go b/pkg/deploy/gateway/gateway.go index 2e8db1e76..2ee81222d 100644 --- a/pkg/deploy/gateway/gateway.go +++ b/pkg/deploy/gateway/gateway.go @@ -16,7 +16,6 @@ import ( "encoding/base64" "fmt" "io/ioutil" - "strings" "sigs.k8s.io/yaml" @@ -87,7 +86,7 @@ func syncAll(deployContext *deploy.DeployContext) error { return err } - if util.IsOpenShift && deployContext.CheCluster.IsNativeUserModeEnabled() { + if deployContext.CheCluster.IsNativeUserModeEnabled() { if oauthSecret, err := getGatewaySecretSpec(deployContext); err == nil { if _, err := deploy.Sync(deployContext, oauthSecret, secretDiffOpts); err != nil { return err @@ -100,18 +99,20 @@ func syncAll(deployContext *deploy.DeployContext) error { return err } - 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) @@ -378,90 +379,6 @@ func getGatewayRoleBindingSpec(instance *orgv1.CheCluster) rbac.RoleBinding { } } -func getGatewayOauthProxyConfigSpec(instance *orgv1.CheCluster, cookieSecret string) corev1.ConfigMap { - return corev1.ConfigMap{ - TypeMeta: metav1.TypeMeta{ - APIVersion: corev1.SchemeGroupVersion.String(), - Kind: "ConfigMap", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "che-gateway-config-oauth-proxy", - Namespace: instance.Namespace, - Labels: deploy.GetLabels(instance, GatewayServiceName), - }, - Data: map[string]string{ - "oauth-proxy.cfg": fmt.Sprintf(` -http_address = ":%d" -https_address = "" -provider = "openshift" -redirect_url = "https://%s/oauth/callback" -upstreams = [ - "http://127.0.0.1:8081/" -] -client_id = "%s" -client_secret = "%s" -scope = "user:full" -openshift_service_account = "%s" -cookie_secret = "%s" -cookie_expire = "24h0m0s" -email_domains = "*" -cookie_httponly = false -pass_access_token = true -skip_provider_button = true -%s -`, GatewayServicePort, - instance.Spec.Server.CheHost, - instance.Spec.Auth.OAuthClientName, - instance.Spec.Auth.OAuthSecret, - GatewayServiceName, - cookieSecret, - skipAuthConfig(instance)), - }, - } -} - -func skipAuthConfig(instance *orgv1.CheCluster) string { - var skipAuthPaths []string - if !instance.Spec.Server.ExternalPluginRegistry { - skipAuthPaths = append(skipAuthPaths, "^/"+deploy.PluginRegistryName) - } - if !instance.Spec.Server.ExternalDevfileRegistry { - skipAuthPaths = append(skipAuthPaths, "^/"+deploy.DevfileRegistryName) - } - if util.IsOpenShift && instance.IsNativeUserModeEnabled() { - skipAuthPaths = append(skipAuthPaths, "/healthz$") - } - if len(skipAuthPaths) > 0 { - return fmt.Sprintf("skip_auth_regex = \"%s\"", strings.Join(skipAuthPaths, "|")) - } - return "" -} - -func getGatewayKubeRbacProxyConfigSpec(instance *orgv1.CheCluster) corev1.ConfigMap { - return corev1.ConfigMap{ - TypeMeta: metav1.TypeMeta{ - APIVersion: corev1.SchemeGroupVersion.String(), - Kind: "ConfigMap", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "che-gateway-config-kube-rbac-proxy", - Namespace: instance.Namespace, - Labels: deploy.GetLabels(instance, GatewayServiceName), - }, - Data: map[string]string{ - "authorization-config.yaml": ` -authorization: - rewrites: - byQueryParameter: - name: "namespace" - resourceAttributes: - apiVersion: v1 - resource: services - namespace: "{{ .Value }}"`, - }, - } -} - func generateRandomCookieSecret() []byte { return []byte(base64.StdEncoding.EncodeToString([]byte(util.GeneratePasswd(16)))) } @@ -499,7 +416,7 @@ func getGatewayHeaderRewritePluginConfigSpec(instance *orgv1.CheCluster) (*corev func getGatewayTraefikConfigSpec(instance *orgv1.CheCluster) corev1.ConfigMap { traefikPort := GatewayServicePort - if util.IsOpenShift && instance.IsNativeUserModeEnabled() { + if instance.IsNativeUserModeEnabled() { traefikPort = 8081 } data := fmt.Sprintf(` @@ -588,8 +505,6 @@ func getContainersSpec(instance *orgv1.CheCluster) []corev1.Container { configLabelsMap := util.GetMapValue(instance.Spec.Server.SingleHostGatewayConfigMapLabels, deploy.DefaultSingleHostGatewayConfigMapLabels) gatewayImage := util.GetValue(instance.Spec.Server.SingleHostGatewayImage, deploy.DefaultSingleHostGatewayImage(instance)) configSidecarImage := util.GetValue(instance.Spec.Server.SingleHostGatewayConfigSidecarImage, deploy.DefaultSingleHostGatewayConfigSidecarImage(instance)) - authnImage := util.GetValue(instance.Spec.Auth.GatewayAuthenticationSidecarImage, deploy.DefaultGatewayAuthenticationSidecarImage(instance)) - authzImage := util.GetValue(instance.Spec.Auth.GatewayAuthorizationSidecarImage, deploy.DefaultGatewayAuthorizationSidecarImage(instance)) configLabels := labels.FormatLabels(configLabelsMap) containers := []corev1.Container{ @@ -631,42 +546,10 @@ func getContainersSpec(instance *orgv1.CheCluster) []corev1.Container { }, } - if util.IsOpenShift && instance.IsNativeUserModeEnabled() { + if instance.IsNativeUserModeEnabled() { containers = append(containers, - corev1.Container{ - Name: "oauth-proxy", - Image: authnImage, - ImagePullPolicy: corev1.PullAlways, - Args: []string{ - "--config=/etc/oauth-proxy/oauth-proxy.cfg", - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "oauth-proxy-config", - MountPath: "/etc/oauth-proxy", - }, - }, - Ports: []corev1.ContainerPort{ - {ContainerPort: GatewayServicePort, Protocol: "TCP"}, - }, - }, - corev1.Container{ - Name: "kube-rbac-proxy", - Image: authzImage, - ImagePullPolicy: corev1.PullAlways, - Args: []string{ - "--insecure-listen-address=0.0.0.0:8089", - "--upstream=http://127.0.0.1:8090/ping", - "--logtostderr=true", - "--config-file=/etc/kube-rbac-proxy/authorization-config.yaml", - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "kube-rbac-proxy-config", - MountPath: "/etc/kube-rbac-proxy", - }, - }, - }) + getOauthProxyContainerSpec(instance), + getKubeRbacProxyContainerSpec(instance)) } return containers @@ -713,39 +596,23 @@ func getVolumesSpec(instance *orgv1.CheCluster) []corev1.Volume { }, } - if util.IsOpenShift && instance.IsNativeUserModeEnabled() { - volumes = append(volumes, corev1.Volume{ - Name: "oauth-proxy-config", - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: "che-gateway-config-oauth-proxy", - }, - }, - }, - }) + if instance.IsNativeUserModeEnabled() { + volumes = append(volumes, + getOauthProxyConfigVolume(), + getKubeRbacProxyConfigVolume()) - 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", + }, }, }, - }, - }) - - volumes = append(volumes, corev1.Volume{ - Name: "kube-rbac-proxy-config", - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: "che-gateway-config-kube-rbac-proxy", - }, - }, - }, - }) + }) + } } return volumes diff --git a/pkg/deploy/gateway/gateway_test.go b/pkg/deploy/gateway/gateway_test.go index 9947dacad..0b9b6d268 100644 --- a/pkg/deploy/gateway/gateway_test.go +++ b/pkg/deploy/gateway/gateway_test.go @@ -205,6 +205,7 @@ func TestOauthProxyConfigUnauthorizedPaths(t *testing.T) { }) t.Run("no devfile-registry auth", func(t *testing.T) { + util.IsOpenShift = true configmap := getGatewayOauthProxyConfigSpec(&orgv1.CheCluster{ Spec: orgv1.CheClusterSpec{ Server: orgv1.CheClusterSpecServer{ diff --git a/pkg/deploy/gateway/kube_rbac_proxy.go b/pkg/deploy/gateway/kube_rbac_proxy.go new file mode 100644 index 000000000..1e67bd70c --- /dev/null +++ b/pkg/deploy/gateway/kube_rbac_proxy.go @@ -0,0 +1,81 @@ +// +// 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 gateway + +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" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func getGatewayKubeRbacProxyConfigSpec(instance *orgv1.CheCluster) corev1.ConfigMap { + return corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + APIVersion: corev1.SchemeGroupVersion.String(), + Kind: "ConfigMap", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "che-gateway-config-kube-rbac-proxy", + Namespace: instance.Namespace, + Labels: deploy.GetLabels(instance, GatewayServiceName), + }, + Data: map[string]string{ + "authorization-config.yaml": ` +authorization: + rewrites: + byQueryParameter: + name: "namespace" + resourceAttributes: + apiVersion: v1 + apiGroup: workspace.devfile.io + resource: devworkspaces + namespace: "{{ .Value }}"`, + }, + } +} + +func getKubeRbacProxyContainerSpec(instance *orgv1.CheCluster) corev1.Container { + authzImage := util.GetValue(instance.Spec.Auth.GatewayAuthorizationSidecarImage, deploy.DefaultGatewayAuthorizationSidecarImage(instance)) + return corev1.Container{ + Name: "kube-rbac-proxy", + Image: authzImage, + ImagePullPolicy: corev1.PullAlways, + Args: []string{ + "--insecure-listen-address=0.0.0.0:8089", + "--upstream=http://127.0.0.1:8090/ping", + "--logtostderr=true", + "--config-file=/etc/kube-rbac-proxy/authorization-config.yaml", + }, + VolumeMounts: []corev1.VolumeMount{ + { + Name: "kube-rbac-proxy-config", + MountPath: "/etc/kube-rbac-proxy", + }, + }, + } +} + +func getKubeRbacProxyConfigVolume() corev1.Volume { + return corev1.Volume{ + Name: "kube-rbac-proxy-config", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "che-gateway-config-kube-rbac-proxy", + }, + }, + }, + } +} diff --git a/pkg/deploy/gateway/oauth_proxy.go b/pkg/deploy/gateway/oauth_proxy.go new file mode 100644 index 000000000..1da582031 --- /dev/null +++ b/pkg/deploy/gateway/oauth_proxy.go @@ -0,0 +1,162 @@ +// +// 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 gateway + +import ( + "fmt" + "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/util" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func getGatewayOauthProxyConfigSpec(instance *orgv1.CheCluster, cookieSecret string) corev1.ConfigMap { + var config string + if util.IsOpenShift { + config = openshiftOauthProxyConfig(instance, cookieSecret) + } else { + config = kubernetesOauthProxyconfig(instance, cookieSecret) + } + return corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + APIVersion: corev1.SchemeGroupVersion.String(), + Kind: "ConfigMap", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "che-gateway-config-oauth-proxy", + Namespace: instance.Namespace, + Labels: deploy.GetLabels(instance, GatewayServiceName), + }, + Data: map[string]string{ + "oauth-proxy.cfg": config, + }, + } +} + +func openshiftOauthProxyConfig(instance *orgv1.CheCluster, cookieSecret string) string { + return fmt.Sprintf(` +http_address = ":%d" +https_address = "" +provider = "openshift" +redirect_url = "https://%s/oauth/callback" +upstreams = [ + "http://127.0.0.1:8081/" +] +client_id = "%s" +client_secret = "%s" +scope = "user:full" +openshift_service_account = "%s" +cookie_secret = "%s" +cookie_expire = "24h0m0s" +email_domains = "*" +cookie_httponly = false +pass_access_token = true +skip_provider_button = true +%s +`, GatewayServicePort, + instance.Spec.Server.CheHost, + instance.Spec.Auth.OAuthClientName, + instance.Spec.Auth.OAuthSecret, + GatewayServiceName, + cookieSecret, + skipAuthConfig(instance)) +} + +func kubernetesOauthProxyconfig(instance *orgv1.CheCluster, cookieSecret string) string { + return fmt.Sprintf(` +proxy_prefix = "/oauth" +http_address = ":%d" +https_address = "" +provider = "oidc" +redirect_url = "https://%s/oauth/callback" +oidc_issuer_url = "%s" +insecure_oidc_skip_issuer_verification = true +ssl_insecure_skip_verify = true +upstreams = [ + "http://127.0.0.1:8081/" +] +client_id = "%s" +client_secret = "%s" +cookie_secret = "%s" +cookie_expire = "24h0m0s" +email_domains = "*" +cookie_httponly = false +pass_authorization_header = true +skip_provider_button = true +%s +`, GatewayServicePort, + instance.Spec.Server.CheHost, + instance.Spec.Auth.IdentityProviderURL, + instance.Spec.Auth.OAuthClientName, + instance.Spec.Auth.OAuthSecret, + cookieSecret, + skipAuthConfig(instance)) +} + +func skipAuthConfig(instance *orgv1.CheCluster) string { + var skipAuthPaths []string + if !instance.Spec.Server.ExternalPluginRegistry { + skipAuthPaths = append(skipAuthPaths, "^/"+deploy.PluginRegistryName) + } + if !instance.Spec.Server.ExternalDevfileRegistry { + skipAuthPaths = append(skipAuthPaths, "^/"+deploy.DevfileRegistryName) + } + if instance.IsNativeUserModeEnabled() { + skipAuthPaths = append(skipAuthPaths, "/healthz$") + } + if len(skipAuthPaths) > 0 { + propName := "skip_auth_routes" + if util.IsOpenShift { + propName = "skip_auth_regex" + } + return fmt.Sprintf("%s = \"%s\"", propName, strings.Join(skipAuthPaths, "|")) + } + return "" +} + +func getOauthProxyContainerSpec(instance *orgv1.CheCluster) corev1.Container { + authnImage := util.GetValue(instance.Spec.Auth.GatewayAuthenticationSidecarImage, deploy.DefaultGatewayAuthenticationSidecarImage(instance)) + return corev1.Container{ + Name: "oauth-proxy", + Image: authnImage, + ImagePullPolicy: corev1.PullAlways, + Args: []string{ + "--config=/etc/oauth-proxy/oauth-proxy.cfg", + }, + VolumeMounts: []corev1.VolumeMount{ + { + Name: "oauth-proxy-config", + MountPath: "/etc/oauth-proxy", + }, + }, + Ports: []corev1.ContainerPort{ + {ContainerPort: GatewayServicePort, Protocol: "TCP"}, + }, + } +} + +func getOauthProxyConfigVolume() corev1.Volume { + return corev1.Volume{ + Name: "oauth-proxy-config", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "che-gateway-config-oauth-proxy", + }, + }, + }, + } +} diff --git a/pkg/deploy/identity-provider/identity_provider.go b/pkg/deploy/identity-provider/identity_provider.go index ee2c769b9..3ff313a00 100644 --- a/pkg/deploy/identity-provider/identity_provider.go +++ b/pkg/deploy/identity-provider/identity_provider.go @@ -49,7 +49,7 @@ var ( // the provisioning is complete, false if requeue of the reconcile request is needed. func SyncIdentityProviderToCluster(deployContext *deploy.DeployContext) (bool, error) { cr := deployContext.CheCluster - if util.IsOpenShift && deployContext.CheCluster.IsNativeUserModeEnabled() { + if deployContext.CheCluster.IsNativeUserModeEnabled() { return syncNativeIdentityProviderItems(deployContext) } else if cr.Spec.Auth.ExternalIdentityProvider { return true, nil @@ -164,12 +164,13 @@ func syncNativeIdentityProviderItems(deployContext *deploy.DeployContext) (bool, return false, err } - redirectURIs := []string{"https://" + cr.Spec.Server.CheHost + "/oauth/callback"} - - oAuthClient := deploy.GetOAuthClientSpec(cr.Spec.Auth.OAuthClientName, cr.Spec.Auth.OAuthSecret, redirectURIs) - provisioned, err := deploy.Sync(deployContext, oAuthClient, oAuthClientDiffOpts) - if !provisioned { - return false, err + if util.IsOpenShift { + redirectURIs := []string{"https://" + cr.Spec.Server.CheHost + "/oauth/callback"} + oAuthClient := deploy.GetOAuthClientSpec(cr.Spec.Auth.OAuthClientName, cr.Spec.Auth.OAuthSecret, redirectURIs) + provisioned, err := deploy.Sync(deployContext, oAuthClient, oAuthClientDiffOpts) + if !provisioned { + return false, err + } } return true, nil diff --git a/pkg/deploy/server/server_configmap.go b/pkg/deploy/server/server_configmap.go index 0e4bcb590..b595a98fb 100644 --- a/pkg/deploy/server/server_configmap.go +++ b/pkg/deploy/server/server_configmap.go @@ -49,6 +49,7 @@ type CheConfigMap struct { CheMetricsEnabled string `json:"CHE_METRICS_ENABLED"` CheInfrastructureActive string `json:"CHE_INFRASTRUCTURE_ACTIVE"` CheInfraKubernetesServiceAccountName string `json:"CHE_INFRA_KUBERNETES_SERVICE__ACCOUNT__NAME"` + CheInfraKubernetesUserClusterRoles string `json:"CHE_INFRA_KUBERNETES_USER__CLUSTER__ROLES"` DefaultTargetNamespace string `json:"CHE_INFRA_KUBERNETES_NAMESPACE_DEFAULT"` PvcStrategy string `json:"CHE_INFRA_KUBERNETES_PVC_STRATEGY"` PvcClaimSize string `json:"CHE_INFRA_KUBERNETES_PVC_QUANTITY"` @@ -61,8 +62,8 @@ type CheConfigMap struct { DbUserName string `json:"CHE_JDBC_USERNAME,omitempty"` DbPassword string `json:"CHE_JDBC_PASSWORD,omitempty"` CheLogLevel string `json:"CHE_LOG_LEVEL"` - KeycloakURL string `json:"CHE_KEYCLOAK_AUTH__SERVER__URL,omitempty"` - KeycloakInternalURL string `json:"CHE_KEYCLOAK_AUTH__INTERNAL__SERVER__URL,omitempty"` + 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"` @@ -92,15 +93,17 @@ type CheConfigMap struct { // which is used in CheCluster ConfigMap to configure CheCluster master behavior func (s *Server) getCheConfigMapData() (cheEnv map[string]string, err error) { cheHost := s.deployContext.CheCluster.Spec.Server.CheHost - keycloakURL := s.deployContext.CheCluster.Spec.Auth.IdentityProviderURL + identityProviderURL := s.deployContext.CheCluster.Spec.Auth.IdentityProviderURL // Adds `/auth` for external identity providers. // If identity provide is deployed by operator then `/auth` is already added. - if s.deployContext.CheCluster.Spec.Auth.ExternalIdentityProvider && !strings.HasSuffix(keycloakURL, "/auth") { - if strings.HasSuffix(keycloakURL, "/") { - keycloakURL = keycloakURL + "auth" + if !s.deployContext.CheCluster.IsNativeUserModeEnabled() && + s.deployContext.CheCluster.Spec.Auth.ExternalIdentityProvider && + !strings.HasSuffix(identityProviderURL, "/auth") { + if strings.HasSuffix(identityProviderURL, "/") { + identityProviderURL = identityProviderURL + "auth" } else { - keycloakURL = keycloakURL + "/auth" + identityProviderURL = identityProviderURL + "/auth" } } @@ -186,7 +189,9 @@ func (s *Server) getCheConfigMapData() (cheEnv map[string]string, err error) { cheAPI := protocol + "://" + cheHost + "/api" var keycloakInternalURL, pluginRegistryInternalURL, devfileRegistryInternalURL, cheInternalAPI, webSocketInternalEndpoint string - if s.deployContext.CheCluster.IsInternalClusterSVCNamesEnabled() && !s.deployContext.CheCluster.Spec.Auth.ExternalIdentityProvider { + if !s.deployContext.CheCluster.IsNativeUserModeEnabled() && + s.deployContext.CheCluster.IsInternalClusterSVCNamesEnabled() && + !s.deployContext.CheCluster.Spec.Auth.ExternalIdentityProvider { keycloakInternalURL = fmt.Sprintf("%s://%s.%s.svc:8080/auth", "http", deploy.IdentityProviderName, s.deployContext.CheCluster.Namespace) } @@ -210,6 +215,13 @@ func (s *Server) getCheConfigMapData() (cheEnv map[string]string, err error) { } webSocketEndpoint := wsprotocol + "://" + cheHost + "/api/websocket" + cheWorkspaceServiceAccount := "che-workspace" + cheUserClusterRoleNames := "NULL" + if s.deployContext.CheCluster.IsNativeUserModeEnabled() { + cheWorkspaceServiceAccount = "NULL" + cheUserClusterRoleNames = fmt.Sprintf("%s-cheworkspaces-clusterrole, %s-cheworkspaces-devworkspace-clusterrole", s.deployContext.CheCluster.Namespace, s.deployContext.CheCluster.Namespace) + } + data := &CheConfigMap{ CheMultiUser: "true", CheHost: cheHost, @@ -220,7 +232,8 @@ func (s *Server) getCheConfigMapData() (cheEnv map[string]string, err error) { CheWebSocketInternalEndpoint: webSocketInternalEndpoint, CheDebugServer: cheDebug, CheInfrastructureActive: infra, - CheInfraKubernetesServiceAccountName: "che-workspace", + CheInfraKubernetesServiceAccountName: cheWorkspaceServiceAccount, + CheInfraKubernetesUserClusterRoles: cheUserClusterRoleNames, DefaultTargetNamespace: workspaceNamespaceDefault, PvcStrategy: pvcStrategy, PvcClaimSize: pvcClaimSize, @@ -254,8 +267,8 @@ func (s *Server) getCheConfigMapData() (cheEnv map[string]string, err error) { CheDevWorkspacesEnabled: strconv.FormatBool(s.deployContext.CheCluster.Spec.DevWorkspace.Enable), } - data.KeycloakURL = keycloakURL - data.KeycloakInternalURL = keycloakInternalURL + data.IdentityProviderUrl = identityProviderURL + data.IdentityProviderInternalURL = keycloakInternalURL data.KeycloakRealm = keycloakRealm data.KeycloakClientId = keycloakClientId data.DatabaseURL = "jdbc:postgresql://" + chePostgresHostName + ":" + chePostgresPort + "/" + chePostgresDb diff --git a/pkg/deploy/server/server_configmap_test.go b/pkg/deploy/server/server_configmap_test.go index 726af6ca3..d5b3d6198 100644 --- a/pkg/deploy/server/server_configmap_test.go +++ b/pkg/deploy/server/server_configmap_test.go @@ -806,8 +806,8 @@ func TestShouldSetUpCorrectlyInternalIdentityProviderServiceURL(t *testing.T) { }, }, expectedData: map[string]string{ - "CHE_KEYCLOAK_AUTH__INTERNAL__SERVER__URL": "", - "CHE_KEYCLOAK_AUTH__SERVER__URL": "http://external-keycloak/auth", + "CHE_OIDC_AUTH__INTERNAL__SERVER__URL": "", + "CHE_OIDC_AUTH__SERVER__URL": "http://external-keycloak/auth", }, }, { @@ -829,8 +829,8 @@ func TestShouldSetUpCorrectlyInternalIdentityProviderServiceURL(t *testing.T) { }, }, expectedData: map[string]string{ - "CHE_KEYCLOAK_AUTH__INTERNAL__SERVER__URL": "", - "CHE_KEYCLOAK_AUTH__SERVER__URL": "http://external-keycloak/auth", + "CHE_OIDC_AUTH__INTERNAL__SERVER__URL": "", + "CHE_OIDC_AUTH__SERVER__URL": "http://external-keycloak/auth", }, }, { @@ -855,8 +855,8 @@ func TestShouldSetUpCorrectlyInternalIdentityProviderServiceURL(t *testing.T) { }, }, expectedData: map[string]string{ - "CHE_KEYCLOAK_AUTH__INTERNAL__SERVER__URL": "", - "CHE_KEYCLOAK_AUTH__SERVER__URL": "http://external-keycloak/auth", + "CHE_OIDC_AUTH__INTERNAL__SERVER__URL": "", + "CHE_OIDC_AUTH__SERVER__URL": "http://external-keycloak/auth", }, }, { @@ -881,8 +881,8 @@ func TestShouldSetUpCorrectlyInternalIdentityProviderServiceURL(t *testing.T) { }, }, expectedData: map[string]string{ - "CHE_KEYCLOAK_AUTH__INTERNAL__SERVER__URL": "", - "CHE_KEYCLOAK_AUTH__SERVER__URL": "http://keycloak/auth", + "CHE_OIDC_AUTH__INTERNAL__SERVER__URL": "", + "CHE_OIDC_AUTH__SERVER__URL": "http://keycloak/auth", }, }, { @@ -904,8 +904,8 @@ func TestShouldSetUpCorrectlyInternalIdentityProviderServiceURL(t *testing.T) { }, }, expectedData: map[string]string{ - "CHE_KEYCLOAK_AUTH__INTERNAL__SERVER__URL": "http://keycloak.eclipse-che.svc:8080/auth", - "CHE_KEYCLOAK_AUTH__SERVER__URL": "http://keycloak/auth", + "CHE_OIDC_AUTH__INTERNAL__SERVER__URL": "http://keycloak.eclipse-che.svc:8080/auth", + "CHE_OIDC_AUTH__SERVER__URL": "http://keycloak/auth", }, }, } diff --git a/pkg/deploy/server/server_deployment.go b/pkg/deploy/server/server_deployment.go index 43593897b..6183f6fcc 100644 --- a/pkg/deploy/server/server_deployment.go +++ b/pkg/deploy/server/server_deployment.go @@ -162,7 +162,7 @@ func (s Server) getDeploymentSpec() (*appsv1.Deployment, error) { FieldPath: "metadata.namespace"}}, }) - if util.IsOpenShift && s.deployContext.CheCluster.IsNativeUserModeEnabled() { + if s.deployContext.CheCluster.IsNativeUserModeEnabled() { cheEnv = append(cheEnv, corev1.EnvVar{ Name: "CHE_AUTH_NATIVEUSER", Value: "true",