diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 03d6ba26c..980e03ae7 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -40,7 +40,7 @@ func printVersion() { logrus.Infof(fmt.Sprintf("Go Version: %s", runtime.Version())) logrus.Infof(fmt.Sprintf("Go OS/Arch: %s/%s", runtime.GOOS, runtime.GOARCH)) logrus.Infof(fmt.Sprintf("operator-sdk Version: %v", sdkVersion.Version)) - isOpenShift, err := util.DetectOpenShift() + isOpenShift, isOpenShift4, err := util.DetectOpenShift() if err != nil { logrus.Fatalf("Operator is exiting. An error occurred when detecting current infra: %s", err) @@ -48,6 +48,11 @@ func printVersion() { infra := "Kubernetes" if isOpenShift { infra = "OpenShift" + if isOpenShift4 { + infra += " v4.x" + } else { + infra += " v3.x" + } } logrus.Infof(fmt.Sprintf("Operator is running on %v", infra)) diff --git a/deploy/cluster_role.yaml b/deploy/cluster_role.yaml index 3fb2de35c..9531875d2 100644 --- a/deploy/cluster_role.yaml +++ b/deploy/cluster_role.yaml @@ -16,6 +16,16 @@ rules: - apiGroups: - oauth.openshift.io resources: - - "*" + - oauthclients verbs: - - "*" \ No newline at end of file + - create + - get + - delete + - list + - watch + - apiGroups: + - config.openshift.io + resources: + - infrastructures + verbs: + - get diff --git a/pkg/controller/che/che_controller.go b/pkg/controller/che/che_controller.go index d8ab9f8ab..ccd2c2167 100644 --- a/pkg/controller/che/che_controller.go +++ b/pkg/controller/che/che_controller.go @@ -56,7 +56,7 @@ func newReconciler(mgr manager.Manager) reconcile.Reconciler { // add adds a new Controller to mgr with r as the reconcile.Reconciler func add(mgr manager.Manager, r reconcile.Reconciler) error { - isOpenShift, err := util.DetectOpenShift() + isOpenShift, _, err := util.DetectOpenShift() if err != nil { logrus.Errorf("An error occurred when detecting current infra: %s", err) @@ -202,7 +202,7 @@ func (r *ReconcileChe) Reconcile(request reconcile.Request) (reconcile.Result, e return reconcile.Result{}, err } - isOpenShift, err := util.DetectOpenShift() + isOpenShift, isOpenShift4, err := util.DetectOpenShift() if err != nil { logrus.Errorf("An error occurred when detecting current infra: %s", err) } @@ -215,16 +215,19 @@ func (r *ReconcileChe) Reconcile(request reconcile.Request) (reconcile.Result, e } } } - // create a secret with router tls cert when on OpenShift infra and router is configured with a self signed certificate - selfSignedCert := instance.Spec.Server.SelfSignedCert - if isOpenShift && selfSignedCert { - if err := r.CreateTLSSecret(instance, "", "self-signed-certificate"); err != nil { - return reconcile.Result{}, err - } - } - // create a secret with OpenShift API crt to be added to keystore that RH SSO will consume if isOpenShift { - baseURL, err := util.GetClusterPublicHostname() + // create a secret with router tls cert when on OpenShift infra and router is configured with a self signed certificate + if instance.Spec.Server.SelfSignedCert || + // 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) + (isOpenShift4 && instance.Spec.Auth.OpenShiftOauth && ! instance.Spec.Server.TlsSupport) { + if err := r.CreateTLSSecret(instance, "", "self-signed-certificate"); err != nil { + return reconcile.Result{}, err + } + } + // create a secret with OpenShift API crt to be added to keystore that RH SSO will consume + baseURL, err := util.GetClusterPublicHostname(isOpenShift4) 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 { @@ -503,7 +506,7 @@ func (r *ReconcileChe) Reconcile(request reconcile.Request) (reconcile.Result, e if doInstallOpenShiftoAuthProvider { openShiftIdentityProviderStatus := instance.Status.OpenShiftoAuthProvisioned if !openShiftIdentityProviderStatus { - if err := r.CreateIdentityProviderItems(instance, request, cheFlavor, keycloakDeployment.Name); err != nil { + if err := r.CreateIdentityProviderItems(instance, request, cheFlavor, keycloakDeployment.Name, isOpenShift4); err != nil { return reconcile.Result{Requeue: true, RequeueAfter: time.Second * 5}, err } } @@ -644,7 +647,7 @@ func (r *ReconcileChe) Reconcile(request reconcile.Request) (reconcile.Result, e } // Delete OpenShift identity provider if OpenShift oAuth is false in spec // but OpenShiftoAuthProvisioned is true in CR status, e.g. when oAuth has been turned on and then turned off - deleted, err := r.ReconcileIdentityProvider(instance) + deleted, err := r.ReconcileIdentityProvider(instance, isOpenShift4) if deleted { instance.Status.OpenShiftoAuthProvisioned = false if err := r.UpdateCheCRStatus(instance, "provisioned with OpenShift oAuth", "false"); err != nil { diff --git a/pkg/controller/che/che_controller_test.go b/pkg/controller/che/che_controller_test.go index de35e466d..5f313d482 100644 --- a/pkg/controller/che/che_controller_test.go +++ b/pkg/controller/che/che_controller_test.go @@ -167,7 +167,7 @@ func TestCheController(t *testing.T) { } err = r.client.Get(context.TODO(), types.NamespacedName{Name: cheCR.Name, Namespace: cheCR.Namespace}, cheCR) - err = r.CreateIdentityProviderItems(cheCR, req, "che", "keycloak") + err = r.CreateIdentityProviderItems(cheCR, req, "che", "keycloak", false) oAuthClientName := cheCR.Spec.Auth.OauthClientName oauthSecret := cheCR.Spec.Auth.OauthSecret if err = r.client.Get(context.TODO(), types.NamespacedName{Name: oAuthClientName, Namespace: ""}, oAuthClient); err != nil { diff --git a/pkg/controller/che/create.go b/pkg/controller/che/create.go index fca2a4683..f5cbe25aa 100644 --- a/pkg/controller/che/create.go +++ b/pkg/controller/che/create.go @@ -268,7 +268,7 @@ func (r *ReconcileChe) CreateNewRoleBinding(instance *orgv1.CheCluster, roleBind return nil } -func (r *ReconcileChe) CreateIdentityProviderItems(instance *orgv1.CheCluster, request reconcile.Request, cheFlavor string, keycloakDeploymentName string) (err error) { +func (r *ReconcileChe) CreateIdentityProviderItems(instance *orgv1.CheCluster, request reconcile.Request, cheFlavor string, keycloakDeploymentName string, isOpenShift4 bool) (err error) { tests := r.tests keycloakAdminPassword := instance.Spec.Auth.KeycloakAdminPassword oAuthClientName := instance.Spec.Auth.OauthClientName @@ -289,13 +289,13 @@ func (r *ReconcileChe) CreateIdentityProviderItems(instance *orgv1.CheCluster, r } keycloakURL := instance.Spec.Auth.KeycloakURL keycloakRealm := util.GetValue(instance.Spec.Auth.KeycloakRealm, cheFlavor) - oAuthClient := deploy.NewOAuthClient(oAuthClientName, oauthSecret, keycloakURL, keycloakRealm) + oAuthClient := deploy.NewOAuthClient(oAuthClientName, oauthSecret, keycloakURL, keycloakRealm, isOpenShift4) if err := r.CreateNewOauthClient(instance, oAuthClient); err != nil { return err } if !tests { - openShiftIdentityProviderCommand := deploy.GetOpenShiftIdentityProviderProvisionCommand(instance, oAuthClientName, oauthSecret, keycloakAdminPassword) + openShiftIdentityProviderCommand := deploy.GetOpenShiftIdentityProviderProvisionCommand(instance, oAuthClientName, oauthSecret, keycloakAdminPassword, isOpenShift4) podToExec, err := k8sclient.GetDeploymentPod(keycloakDeploymentName, instance.Namespace) if err != nil { logrus.Errorf("Failed to retrieve pod name. Further exec will fail") diff --git a/pkg/controller/che/update.go b/pkg/controller/che/update.go index d7c4f71dd..364c94d7f 100644 --- a/pkg/controller/che/update.go +++ b/pkg/controller/che/update.go @@ -180,14 +180,14 @@ func (r *ReconcileChe) ReconcileTLSObjects(instance *orgv1.CheCluster, request r return true, nil } -func (r *ReconcileChe) ReconcileIdentityProvider(instance *orgv1.CheCluster) (deleted bool, err error) { +func (r *ReconcileChe) ReconcileIdentityProvider(instance *orgv1.CheCluster, isOpenShift4 bool) (deleted bool, err error) { if instance.Spec.Auth.OpenShiftOauth == false && instance.Status.OpenShiftoAuthProvisioned == true { keycloakAdminPassword := instance.Spec.Auth.KeycloakAdminPassword keycloakDeployment := &appsv1.Deployment{} if err := r.client.Get(context.TODO(), types.NamespacedName{Name: "keycloak", Namespace: instance.Namespace}, keycloakDeployment); err != nil { logrus.Errorf("Deployment %s not found: %s", keycloakDeployment.Name, err) } - deleteOpenShiftIdentityProviderProvisionCommand := deploy.GetDeleteOpenShiftIdentityProviderProvisionCommand(instance, keycloakAdminPassword) + deleteOpenShiftIdentityProviderProvisionCommand := deploy.GetDeleteOpenShiftIdentityProviderProvisionCommand(instance, keycloakAdminPassword, isOpenShift4) podToExec, err := k8sclient.GetDeploymentPod(keycloakDeployment.Name, instance.Namespace) if err != nil { logrus.Errorf("Failed to retrieve pod name. Further exec will fail") diff --git a/pkg/deploy/che_configmap.go b/pkg/deploy/che_configmap.go index c52e24d08..222a60223 100644 --- a/pkg/deploy/che_configmap.go +++ b/pkg/deploy/che_configmap.go @@ -82,7 +82,7 @@ func GetCustomConfigMapData() (cheEnv map[string]string) { func GetConfigMapData(cr *orgv1.CheCluster) (cheEnv map[string]string) { cheHost := cr.Spec.Server.CheHost keycloakURL := cr.Spec.Auth.KeycloakURL - isOpenShift, err := util.DetectOpenShift() + isOpenShift, isOpenshift4, err := util.DetectOpenShift() if err != nil { logrus.Errorf("Failed to get current infra: %s", err) } @@ -99,6 +99,9 @@ func GetConfigMapData(cr *orgv1.CheCluster) (cheEnv map[string]string) { if openshiftOAuth && isOpenShift { workspacesNamespace = "" openShiftIdentityProviderId = "openshift-v3" + if isOpenshift4 { + openShiftIdentityProviderId = "openshift-v4" + } } tlsSupport := cr.Spec.Server.TlsSupport protocol := "http" diff --git a/pkg/deploy/deployment_che.go b/pkg/deploy/deployment_che.go index 559f832fd..e2f608abd 100644 --- a/pkg/deploy/deployment_che.go +++ b/pkg/deploy/deployment_che.go @@ -27,6 +27,25 @@ func NewCheDeployment(cr *orgv1.CheCluster, cheImage string, cheTag string, cmRe optionalEnv := true cheFlavor := util.GetValue(cr.Spec.Server.CheFlavor, DefaultCheFlavor) memRequest := util.GetValue(cr.Spec.Server.ServerMemoryRequest, DefaultServerMemoryRequest) + selfSignedCertEnv := corev1.EnvVar{ + Name: "CHE_SELF__SIGNED__CERT", + Value: "", + } + + if cr.Spec.Server.SelfSignedCert { + selfSignedCertEnv = corev1.EnvVar{ + Name: "CHE_SELF__SIGNED__CERT", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + Key: "ca.crt", + LocalObjectReference: corev1.LocalObjectReference{ + Name: "self-signed-certificate", + }, + Optional: &optionalEnv, + }, + }, + } + } memLimit := util.GetValue(cr.Spec.Server.ServerMemoryLimit, DefaultServerMemoryLimit) cheDeployment := appsv1.Deployment{ TypeMeta: metav1.TypeMeta{ @@ -133,18 +152,7 @@ func NewCheDeployment(cr *orgv1.CheCluster, cheImage string, cheTag string, cmRe FieldRef: &corev1.ObjectFieldSelector{ FieldPath: "metadata.namespace"}}, }, - { - Name: "CHE_SELF__SIGNED__CERT", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - Key: "ca.crt", - LocalObjectReference: corev1.LocalObjectReference{ - Name: "self-signed-certificate", - }, - Optional: &optionalEnv, - }, - }, - }, + selfSignedCertEnv, }}, }, }, diff --git a/pkg/deploy/deployment_keycloak.go b/pkg/deploy/deployment_keycloak.go index 39ecf1127..245695d6c 100644 --- a/pkg/deploy/deployment_keycloak.go +++ b/pkg/deploy/deployment_keycloak.go @@ -35,10 +35,10 @@ func NewKeycloakDeployment(cr *orgv1.CheCluster, keycloakPostgresPassword string // 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 + "/openshift.crt && " + + 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 + "/openshift.crt -storepass " + trustpass + " -noprompt; fi" + " -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" + @@ -48,15 +48,20 @@ func NewKeycloakDeployment(cr *orgv1.CheCluster, keycloakPostgresPassword string 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 $JAVA_HOME/jre/lib/security/cacerts" + " -destkeystore " + jbossDir + "/openshift.jks" + " -srcstorepass changeit -deststorepass " + trustpass - addCertToTrustStoreCommand := addRouterCrt + " && " + addOpenShiftAPICrt + " && " + addMountedCrt + " && " + importJavaCacerts + addCertToTrustStoreCommand := addRouterCrt + " && " + addOpenShiftAPICrt + " && " + addMountedCrt + " && " + addMountedServiceCrt + " && " + importJavaCacerts startCommand := "sed -i 's/WILDCARD/ANY/g' /opt/eap/bin/launch/keycloak-spi.sh && /opt/eap/bin/openshift-launch.sh -b 0.0.0.0" // upstream Keycloak has a bit different mechanism of adding jks - changeConfigCommand := "echo -e \"embed-server --server-config=standalone.xml --std-out=echo \n" + + 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" + @@ -88,6 +93,10 @@ func NewKeycloakDeployment(cr *orgv1.CheCluster, keycloakPostgresPassword string Name: "POSTGRES_PORT_5432_TCP_PORT", Value: "5432", }, + { + Name: "POSTGRES_PORT", + Value: "5432", + }, { Name: "POSTGRES_DATABASE", Value: "keycloak", @@ -205,7 +214,7 @@ func NewKeycloakDeployment(cr *orgv1.CheCluster, keycloakPostgresPassword string }, } } - command := addCertToTrustStoreCommand + " && " + changeConfigCommand + " && /opt/jboss/docker-entrypoint.sh -b 0.0.0.0" + command := addCertToTrustStoreCommand + " && " + changeConfigCommand + " && /opt/jboss/docker-entrypoint.sh -b 0.0.0.0 -c standalone.xml" if cheFlavor == "codeready" { command = addCertToTrustStoreCommand + " && " + startCommand } diff --git a/pkg/deploy/exec_commands.go b/pkg/deploy/exec_commands.go index da81cedf7..b7d831d3f 100644 --- a/pkg/deploy/exec_commands.go +++ b/pkg/deploy/exec_commands.go @@ -77,9 +77,9 @@ func GetKeycloakProvisionCommand(cr *orgv1.CheCluster, cheHost string) (command return command } -func GetOpenShiftIdentityProviderProvisionCommand(cr *orgv1.CheCluster, oAuthClientName string, oauthSecret string, keycloakAdminPassword string) (command string) { +func GetOpenShiftIdentityProviderProvisionCommand(cr *orgv1.CheCluster, oAuthClientName string, oauthSecret string, keycloakAdminPassword string, isOpenShift4 bool) (command string) { cheFlavor := util.GetValue(cr.Spec.Server.CheFlavor, DefaultCheFlavor) - openShiftApiUrl, err := util.GetClusterPublicHostname() + openShiftApiUrl, err := util.GetClusterPublicHostname(isOpenShift4) 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) openShiftApiUrl = "RECPLACE_ME" @@ -93,25 +93,30 @@ func GetOpenShiftIdentityProviderProvisionCommand(cr *orgv1.CheCluster, oAuthCli } + providerId := "openshift-v3" + if isOpenShift4 { + providerId = "openshift-v4" + } + createOpenShiftIdentityProviderCommand := script + " config credentials --server http://0.0.0.0:8080/auth " + "--realm master --user " + keycloakAdminUserName + " --password " + keycloakAdminPassword + " && " + script + - " get identity-provider/instances/openshift-v3 -r " + keycloakRealm + "; " + + " get identity-provider/instances/" + providerId + " -r " + keycloakRealm + "; " + "if [ $? -eq 0 ]; then echo \"Provider exists\"; exit 0; fi && " + script + " create identity-provider/instances -r " + keycloakRealm + - " -s alias=openshift-v3 -s providerId=openshift-v3 -s enabled=true -s storeToken=true" + + " -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" command = createOpenShiftIdentityProviderCommand if cheFlavor == "che" { - command = "cd /scripts && " + createOpenShiftIdentityProviderCommand + command = "cd /scripts && export JAVA_TOOL_OPTIONS=-Duser.home=. && " + createOpenShiftIdentityProviderCommand } return command } -func GetDeleteOpenShiftIdentityProviderProvisionCommand(cr *orgv1.CheCluster, keycloakAdminPassword string) (command string) { +func GetDeleteOpenShiftIdentityProviderProvisionCommand(cr *orgv1.CheCluster, keycloakAdminPassword string, isOpenShift4 bool) (command string) { cheFlavor := util.GetValue(cr.Spec.Server.CheFlavor, DefaultCheFlavor) keycloakRealm := util.GetValue(cr.Spec.Auth.KeycloakRealm, cheFlavor) keycloakAdminUserName := util.GetValue(cr.Spec.Auth.KeycloakAdminUserName, DefaultKeycloakAdminUserName) @@ -121,10 +126,14 @@ func GetDeleteOpenShiftIdentityProviderProvisionCommand(cr *orgv1.CheCluster, ke } + providerName := "openshift-v3" + if isOpenShift4 { + providerName = "openshift-v4" + } deleteOpenShiftIdentityProviderCommand := script + " config credentials --server http://0.0.0.0:8080/auth " + "--realm master --user " + keycloakAdminUserName + " --password " + keycloakAdminPassword + " && " + - script + " delete identity-provider/instances/openshift-v3 -r " + keycloakRealm + script + " delete identity-provider/instances/" + providerName + " -r " + keycloakRealm command = deleteOpenShiftIdentityProviderCommand if cheFlavor == "che" { command = "cd /scripts && " + deleteOpenShiftIdentityProviderCommand diff --git a/pkg/deploy/oauthclient.go b/pkg/deploy/oauthclient.go index f99dcb362..d214d1a97 100644 --- a/pkg/deploy/oauthclient.go +++ b/pkg/deploy/oauthclient.go @@ -17,7 +17,11 @@ import ( ) -func NewOAuthClient(name string, oauthSecret string, keycloakURL string, keycloakRealm string) *oauth.OAuthClient { +func NewOAuthClient(name string, oauthSecret string, keycloakURL string, keycloakRealm string, isOpenShift4 bool) *oauth.OAuthClient { + providerName := "openshift-v3" + if isOpenShift4 { + providerName = "openshift-v4" + } return &oauth.OAuthClient{ TypeMeta: metav1.TypeMeta{ Kind: "OAuthClient", @@ -30,7 +34,7 @@ func NewOAuthClient(name string, oauthSecret string, keycloakURL string, keycloa Secret: oauthSecret, RedirectURIs: []string{ - keycloakURL + "/auth/realms/" + keycloakRealm +"/broker/openshift-v3/endpoint", + keycloakURL + "/auth/realms/" + keycloakRealm +"/broker/" + providerName + "/endpoint", }, GrantMethod: oauth.GrantHandlerPrompt, } diff --git a/pkg/util/util.go b/pkg/util/util.go index 475b27b66..8d5a7314a 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -59,30 +59,33 @@ func GeneratePasswd(stringLength int) (passwd string) { return passwd } -func DetectOpenShift() (bool, error) { +func DetectOpenShift() (isOpenshift bool, isOpenshift4 bool, anError error) { tests := IsTestMode() if !tests { kubeconfig, err := config.GetConfig() if err != nil { - return false, err + return false, false, err } discoveryClient, err := discovery.NewDiscoveryClientForConfig(kubeconfig) if err != nil { - return false, err + return false, false, err } apiList, err := discoveryClient.ServerGroups() if err != nil { - return false, err + return false, false, err } apiGroups := apiList.Groups for i := 0; i < len(apiGroups); i++ { if apiGroups[i].Name == "route.openshift.io" { - return true, nil + isOpenshift = true + } + if apiGroups[i].Name == "config.openshift.io" { + isOpenshift4 = true } } - return false, nil + return } - return true, nil + return true, false, nil } func GetValue(key string, defaultValue string) (value string) { @@ -103,9 +106,17 @@ func IsTestMode() (isTesting bool) { return true } -// GetClusterPublicHostname is a hacky way to get OpenShift API public DNS/IP +func GetClusterPublicHostname(isOpenShift4 bool) (hostname string, err error) { + if isOpenShift4 { + return GetClusterPublicHostnameForOpenshiftV4() + } else { + return GetClusterPublicHostnameForOpenshiftV3() + } +} + +// GetClusterPublicHostnameForOpenshiftV3 is a hacky way to get OpenShift API public DNS/IP // to be used in OpenShift oAuth provider as baseURL -func GetClusterPublicHostname() (hostname string, err error) { +func GetClusterPublicHostnameForOpenshiftV3() (hostname string, err error) { http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} client := &http.Client{} kubeApi := os.Getenv("KUBERNETES_PORT_443_TCP_ADDR") @@ -132,6 +143,46 @@ func GetClusterPublicHostname() (hostname string, err error) { return hostname, nil } +// GetClusterPublicHostnameForOpenshiftV3 is a way to get OpenShift API public DNS/IP +// to be used in OpenShift oAuth provider as baseURL +func GetClusterPublicHostnameForOpenshiftV4() (hostname 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) + } + 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() + 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 + } + spec := jsonData["status"].(map[string]interface{}) + hostname = spec["apiServerURL"].(string) + + return hostname, nil +} + func GenerateProxyJavaOpts(proxyURL string, proxyPort string, nonProxyHosts string, proxyUser string, proxyPassword string) (javaOpts string) { proxyHost := strings.TrimLeft(proxyURL, "https://")