From 73d951b3f33675681162826f4cb44151c86169c0 Mon Sep 17 00:00:00 2001 From: Oleksandr Andriienko Date: Thu, 26 Nov 2020 17:26:56 +0200 Subject: [PATCH] Add ability to use internal network for Keycloak (#507) Signed-off-by: Oleksandr Andriienko --- pkg/controller/che/che_controller_test.go | 12 ++++++ pkg/deploy/data_types.go | 1 + .../identity-provider/deployment_keycloak.go | 40 +++++++++++++++++-- .../identity-provider/identity_provider.go | 2 + pkg/deploy/server/che_configmap.go | 6 ++- 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/pkg/controller/che/che_controller_test.go b/pkg/controller/che/che_controller_test.go index c435c7ca7..f35d357d2 100644 --- a/pkg/controller/che/che_controller_test.go +++ b/pkg/controller/che/che_controller_test.go @@ -439,6 +439,12 @@ func TestConfiguringInternalNetworkTest(t *testing.T) { t.Fatalf("Devfile registry internal url must be %s", pluginRegistryInternalExpected) } + keycloakInternal := cheCm.Data["CHE_KEYCLOAK_AUTH__INTERNAL__SERVER__URL"] + keycloakInternalExpected := "http://keycloak.eclipse-che.svc:8080/auth" + if keycloakInternal != keycloakInternalExpected { + t.Fatalf("Keycloak registry internal url must be %s", keycloakInternalExpected) + } + // update CR and make sure Che configmap has been updated cheCR.Spec.Server.UseInternalClusterSVCNames = false if err := cl.Update(context.TODO(), cheCR); err != nil { @@ -472,6 +478,12 @@ func TestConfiguringInternalNetworkTest(t *testing.T) { if devRegistryInternal != devRegistryInternalExpected { t.Fatalf("Plugin registry internal url must be %s", pluginRegistryInternalExpected) } + + keycloakInternal = cheCmWithDisabledInternalClusterSVCNames.Data["CHE_KEYCLOAK_AUTH__INTERNAL__SERVER__URL"] + keycloakInternalExpected = "http://keycloak/auth" + if keycloakInternal != keycloakInternalExpected { + t.Fatalf("Keycloak internal url must be %s", keycloakInternalExpected) + } } func Init() (client.Client, runtime.Scheme) { diff --git a/pkg/deploy/data_types.go b/pkg/deploy/data_types.go index acfbe1d35..313125634 100644 --- a/pkg/deploy/data_types.go +++ b/pkg/deploy/data_types.go @@ -33,6 +33,7 @@ type DeployContext struct { } type InternalService struct { + KeycloakHost string DevfileRegistryHost string PluginRegistryHost string CheHost string diff --git a/pkg/deploy/identity-provider/deployment_keycloak.go b/pkg/deploy/identity-provider/deployment_keycloak.go index 53d298cab..3195ea9a6 100644 --- a/pkg/deploy/identity-provider/deployment_keycloak.go +++ b/pkg/deploy/identity-provider/deployment_keycloak.go @@ -13,6 +13,7 @@ package identity_provider import ( "context" + "net/url" "regexp" "strconv" "strings" @@ -92,6 +93,10 @@ func getSpecKeycloakDeployment( // 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 { env := clusterDeployment.Spec.Template.Spec.Containers[0].Env @@ -205,10 +210,8 @@ func getSpecKeycloakDeployment( quotedNoProxy += "\"" + noProxyEntry + ";NO_PROXY\"" } - jbossCli := "/opt/jboss/keycloak/bin/jboss-cli.sh" serverConfig := "standalone.xml" if cheFlavor == "codeready" { - jbossCli = "/opt/eap/bin/jboss-cli.sh" serverConfig = "standalone-openshift.xml" } addProxyCliCommand = " && echo Configuring Proxy && " + @@ -486,8 +489,37 @@ func getSpecKeycloakDeployment( keycloakEnv = append(keycloakEnv, envvar) } - command := addCertToTrustStoreCommand + addProxyCliCommand + applyProxyCliCommand + " && " + changeConfigCommand + - " && /opt/jboss/docker-entrypoint.sh -b 0.0.0.0 -c standalone.xml" + var enableFixedHostNameProvider string + if deployContext.CheCluster.Spec.Server.UseInternalClusterSVCNames { + if cheFlavor == "che" { + keycloakURL, err := url.Parse(deployContext.CheCluster.Status.KeycloakURL) + if err != nil { + return nil, err + } + hostname := keycloakURL.Hostname() + enableFixedHostNameProvider = " && echo 'Use fixed hostname provider to make working internal network requests' && " + + "echo -e \"embed-server --server-config=standalone.xml --std-out=echo \n" + + "/subsystem=keycloak-server/spi=hostname:write-attribute(name=default-provider, value=\"fixed\") \n" + + "/subsystem=keycloak-server/spi=hostname/provider=fixed:write-attribute(name=properties.hostname,value=\"" + hostname + "\") \n" + if deployContext.CheCluster.Spec.Server.TlsSupport { + enableFixedHostNameProvider += "/subsystem=keycloak-server/spi=hostname/provider=fixed:write-attribute(name=properties.httpsPort,value=\"443\") \n" + + "/subsystem=keycloak-server/spi=hostname/provider=fixed:write-attribute(name=properties.alwaysHttps,value=\"true\") \n" + } else { + enableFixedHostNameProvider += "/subsystem=keycloak-server/spi=hostname/provider=fixed:write-attribute(name=properties.httpPort,value=\"80\") \n" + } + enableFixedHostNameProvider += "stop-embedded-server\" > " + jbossDir + "/use_fixed_hostname_provider.cli && " + + jbossCli + " --file=" + jbossDir + "/use_fixed_hostname_provider.cli " + } + if cheFlavor == "codeready" { + keycloakEnv = append(keycloakEnv, corev1.EnvVar{ + Name: "KEYCLOAK_FRONTEND_URL", + Value: deployContext.CheCluster.Status.KeycloakURL + "/auth", + }); + } + } + + command := addCertToTrustStoreCommand + addProxyCliCommand + applyProxyCliCommand + " && " + changeConfigCommand + enableFixedHostNameProvider + + " && /opt/jboss/docker-entrypoint.sh --debug -b 0.0.0.0 -c standalone.xml" command += " -Dkeycloak.profile.feature.token_exchange=enabled -Dkeycloak.profile.feature.admin_fine_grained_authz=enabled" if cheFlavor == "codeready" { addUsernameReadonlyTheme := "baseTemplate=/opt/eap/themes/base/login/login-update-profile.ftl" + diff --git a/pkg/deploy/identity-provider/identity_provider.go b/pkg/deploy/identity-provider/identity_provider.go index e8b41639c..5ad181b82 100644 --- a/pkg/deploy/identity-provider/identity_provider.go +++ b/pkg/deploy/identity-provider/identity_provider.go @@ -13,6 +13,7 @@ package identity_provider import ( "context" + "fmt" "strings" "github.com/eclipse/che-operator/pkg/deploy" @@ -80,6 +81,7 @@ func SyncIdentityProviderToCluster(deployContext *deploy.DeployContext) (bool, e return false, err } keycloakURL := protocol + "://" + endpoint + deployContext.InternalService.KeycloakHost = fmt.Sprintf("%s://%s.%s.svc:%d", "http", "keycloak", deployContext.CheCluster.Namespace, 8080) if instance.Spec.Auth.IdentityProviderURL != keycloakURL { instance.Spec.Auth.IdentityProviderURL = keycloakURL diff --git a/pkg/deploy/server/che_configmap.go b/pkg/deploy/server/che_configmap.go index a0ae4749a..de04c7b61 100644 --- a/pkg/deploy/server/che_configmap.go +++ b/pkg/deploy/server/che_configmap.go @@ -60,6 +60,7 @@ type CheConfigMap struct { 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"` KeycloakRealm string `json:"CHE_KEYCLOAK_REALM,omitempty"` KeycloakClientId string `json:"CHE_KEYCLOAK_CLIENT__ID,omitempty"` OpenShiftIdentityProvider string `json:"CHE_INFRA_OPENSHIFT_OAUTH__IDENTITY__PROVIDER"` @@ -183,15 +184,17 @@ func GetCheConfigMapData(deployContext *deploy.DeployContext) (cheEnv map[string cheAPI := protocol + "://" + cheHost + "/api" - var pluginRegistryInternalURL, devfileRegistryInternalURL, cheInternalAPI string + var keycloakInternalURL, pluginRegistryInternalURL, devfileRegistryInternalURL, cheInternalAPI string if deployContext.CheCluster.Spec.Server.UseInternalClusterSVCNames { devfileRegistryInternalURL = deployContext.InternalService.DevfileRegistryHost pluginRegistryInternalURL = deployContext.InternalService.PluginRegistryHost + keycloakInternalURL = deployContext.InternalService.KeycloakHost cheInternalAPI = deployContext.InternalService.CheHost + "/api" } else { devfileRegistryInternalURL = devfileRegistryURL pluginRegistryInternalURL = pluginRegistryURL + keycloakInternalURL = keycloakURL cheInternalAPI = cheAPI } @@ -241,6 +244,7 @@ func GetCheConfigMapData(deployContext *deploy.DeployContext) (cheEnv map[string if cheMultiUser == "true" { data.KeycloakURL = keycloakURL + "/auth" + data.KeycloakInternalURL = keycloakInternalURL + "/auth" data.KeycloakRealm = keycloakRealm data.KeycloakClientId = keycloakClientId data.DatabaseURL = "jdbc:postgresql://" + chePostgresHostName + ":" + chePostgresPort + "/" + chePostgresDb