Get crt of OpenShift baseURL for Keycloak (#14)
* Get crt of OpenShift baseURL for Keycloak * Don't fails when rolling out router deploymentpull/16/head
parent
560b21a838
commit
63787372bd
|
|
@ -54,8 +54,8 @@ echo "[INFO] Update OpenShift router tls secret"
|
|||
./oc project default
|
||||
./oc secrets new router-certs tls.crt=ca.crt tls.key=key.pem -o json --type='kubernetes.io/tls' --confirm | ./oc replace -f -
|
||||
echo "[INFO] Initiate a new router deployment"
|
||||
sleep 10
|
||||
./oc rollout latest dc/router -n=default
|
||||
sleep 20
|
||||
./oc rollout latest dc/router -n=default || true
|
||||
|
||||
echo "[INFO] Compile tests binary"
|
||||
docker run -t \
|
||||
|
|
|
|||
|
|
@ -215,25 +215,25 @@ func (r *ReconcileChe) Reconcile(request reconcile.Request) (reconcile.Result, e
|
|||
return reconcile.Result{}, err
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
secret := &corev1.Secret{}
|
||||
if err := r.client.Get(context.TODO(), types.NamespacedName{Name: "self-signed-certificate", Namespace: instance.Namespace}, secret);
|
||||
err != nil && errors.IsNotFound(err) {
|
||||
crt, err := r.GetRouterTlsCrt(instance)
|
||||
if err != nil {
|
||||
logrus.Errorf("Default router tls secret not found. Self signed cert isn't added")
|
||||
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()
|
||||
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 {
|
||||
if err := r.CreateTLSSecret(instance, baseURL, "openshift-api-crt"); err != nil {
|
||||
return reconcile.Result{}, err
|
||||
} else {
|
||||
secret := deploy.NewSecret(instance, "self-signed-certificate", crt)
|
||||
if err := r.CreateNewSecret(instance, secret); err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !tests {
|
||||
deployment := &appsv1.Deployment{}
|
||||
name := "che"
|
||||
|
|
|
|||
|
|
@ -318,6 +318,28 @@ func (r *ReconcileChe) CreateIdentityProviderItems(instance *orgv1.CheCluster, r
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r *ReconcileChe) CreateTLSSecret(instance *orgv1.CheCluster, url string, name string) (err error) {
|
||||
// create a secret with either router tls cert (or OpenShift API crt) when on OpenShift infra
|
||||
// and router is configured with a self signed certificate
|
||||
// this secret is used by CRW server to reach RH SSO TLS endpoint
|
||||
secret := &corev1.Secret{}
|
||||
if err := r.client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: instance.Namespace}, secret);
|
||||
err != nil && errors.IsNotFound(err) {
|
||||
crt, err := r.GetEndpointTlsCrt(instance, url)
|
||||
if err != nil {
|
||||
logrus.Errorf("Failed to extract crt. Failed to create a secret with a self signed crt: %s", err)
|
||||
return err
|
||||
} else {
|
||||
secret := deploy.NewSecret(instance, name, crt)
|
||||
if err := r.CreateNewSecret(instance, secret); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ReconcileChe) GenerateAndSaveFields(instance *orgv1.CheCluster, request reconcile.Request) (err error) {
|
||||
|
||||
chePostgresPassword := util.GetValue(instance.Spec.Database.ChePostgresPassword, util.GeneratePasswd(12))
|
||||
|
|
@ -445,7 +467,6 @@ func (r *ReconcileChe) GenerateAndSaveFields(instance *orgv1.CheCluster, request
|
|||
if len(instance.Spec.Auth.KeycloakClientId) < 1 {
|
||||
instance.Spec.Auth.KeycloakClientId = keycloakClientId
|
||||
|
||||
|
||||
if err := r.UpdateCheCRSpec(instance, "Keycloak client ID", keycloakClientId); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import (
|
|||
orgv1 "github.com/eclipse/che-operator/pkg/apis/org/v1"
|
||||
"github.com/eclipse/che-operator/pkg/deploy"
|
||||
"github.com/eclipse/che-operator/pkg/util"
|
||||
routev1 "github.com/openshift/api/route/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
"io"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
|
|
@ -251,17 +252,21 @@ func (cl *k8s) GetDeploymentPod(name string, ns string) (podName string, err err
|
|||
return podName, nil
|
||||
}
|
||||
|
||||
// GetRouterTlsCrt creates a test TLS route and gets it to extract certificate chain
|
||||
// GetEndpointTlsCrt creates a test TLS route and gets it to extract certificate chain
|
||||
// There's an easier way which is to read tls secret in default (3.11) or openshift-ingress (4.0) namespace
|
||||
// which however requires extra privileges for operator service account
|
||||
func (r *ReconcileChe) GetRouterTlsCrt(instance *orgv1.CheCluster) (certificate []byte, err error) {
|
||||
testRoute := deploy.NewTlsRoute(instance, "test", "test")
|
||||
logrus.Infof("Creating a test route %s to extract routes crt", testRoute.Name)
|
||||
if err := r.CreateNewRoute(instance, testRoute); err != nil {
|
||||
logrus.Errorf("Failed to create test route %s: %s", testRoute.Name, err)
|
||||
return nil, err
|
||||
func (r *ReconcileChe) GetEndpointTlsCrt(instance *orgv1.CheCluster, url string) (certificate []byte, err error) {
|
||||
testRoute := &routev1.Route{}
|
||||
if len(url) < 1 {
|
||||
testRoute = deploy.NewTlsRoute(instance, "test", "test")
|
||||
logrus.Infof("Creating a test route %s to extract routes crt", testRoute.Name)
|
||||
if err := r.CreateNewRoute(instance, testRoute); err != nil {
|
||||
logrus.Errorf("Failed to create test route %s: %s", testRoute.Name, err)
|
||||
return nil, err
|
||||
}
|
||||
url = "https://" + testRoute.Spec.Host
|
||||
|
||||
}
|
||||
url := "https://" + testRoute.Spec.Host
|
||||
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
|
|
@ -283,10 +288,12 @@ func (r *ReconcileChe) GetRouterTlsCrt(instance *orgv1.CheCluster) (certificate
|
|||
})
|
||||
certificate = append(certificate, crt...)
|
||||
}
|
||||
logrus.Infof("Deleting a test route %s to extract routes crt", testRoute.Name)
|
||||
if err := r.client.Delete(context.TODO(), testRoute); err != nil {
|
||||
logrus.Errorf("Failed to delete test route %s: %s", testRoute.Name, err)
|
||||
}
|
||||
|
||||
if len(url) < 1 {
|
||||
logrus.Infof("Deleting a test route %s to extract routes crt", testRoute.Name)
|
||||
if err := r.client.Delete(context.TODO(), testRoute); err != nil {
|
||||
logrus.Errorf("Failed to delete test route %s: %s", testRoute.Name, err)
|
||||
}
|
||||
}
|
||||
return certificate, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,17 +32,28 @@ func NewKeycloakDeployment(cr *orgv1.CheCluster, keycloakPostgresPassword string
|
|||
// writable dir in the upstream Keycloak image
|
||||
jbossDir = "/scripts"
|
||||
}
|
||||
// add crt to Java trust store so that Keycloak can connect to k8s API
|
||||
addCertToTrustStoreCommand := "if [ ! -z \"${CHE_SELF__SIGNED__CERT}\" ]; then echo \"${CHE_SELF__SIGNED__CERT}\" > " + jbossDir + "/openshift.crt && " +
|
||||
"keytool -importcert -alias HOSTDOMAIN0" +
|
||||
" -keystore " + jbossDir +"/openshift.jks" +
|
||||
" -file " + jbossDir + "/openshift.crt -storepass " + trustpass + " -noprompt; fi" +
|
||||
" && keytool -importcert -alias HOSTDOMAIN" +
|
||||
" -keystore " + jbossDir +"/openshift.jks" +
|
||||
" -file /var/run/secrets/kubernetes.io/serviceaccount/ca.crt -storepass " + trustpass + " -noprompt" +
|
||||
" && keytool -importkeystore -srckeystore $JAVA_HOME/jre/lib/security/cacerts" +
|
||||
|
||||
// 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 && " +
|
||||
"keytool -importcert -alias ROUTERCRT" +
|
||||
" -keystore " + jbossDir + "/openshift.jks" +
|
||||
" -file " + jbossDir + "/openshift.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"
|
||||
importJavaCacerts := "keytool -importkeystore -srckeystore $JAVA_HOME/jre/lib/security/cacerts" +
|
||||
" -destkeystore " + jbossDir + "/openshift.jks" +
|
||||
" -srcstorepass changeit -deststorepass " + trustpass
|
||||
|
||||
addCertToTrustStoreCommand := addRouterCrt + " && " + addOpenShiftAPICrt + " && " + addMountedCrt + " && " + 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" +
|
||||
|
|
@ -101,6 +112,18 @@ func NewKeycloakDeployment(cr *orgv1.CheCluster, keycloakPostgresPassword string
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OPENSHIFT_SELF__SIGNED__CERT",
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
Key: "ca.crt",
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "openshift-api-crt",
|
||||
},
|
||||
Optional: &optionalEnv,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if cheFlavor == "codeready" {
|
||||
keycloakEnv = []corev1.EnvVar{
|
||||
|
|
@ -168,6 +191,18 @@ func NewKeycloakDeployment(cr *orgv1.CheCluster, keycloakPostgresPassword string
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "OPENSHIFT_SELF__SIGNED__CERT",
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
Key: "ca.crt",
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "openshift-api-crt",
|
||||
},
|
||||
Optional: &optionalEnv,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
command := addCertToTrustStoreCommand + " && " + changeConfigCommand + " && /opt/jboss/docker-entrypoint.sh -b 0.0.0.0"
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ func GetClusterPublicHostname() (hostname string, err error) {
|
|||
client := &http.Client{}
|
||||
kubeApi := os.Getenv("KUBERNETES_PORT_443_TCP_ADDR")
|
||||
url := "https://" + kubeApi + "/.well-known/oauth-authorization-server"
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue