Bootstrap FreeKB - OpenShift - Getting Started with Red Hat Single Sign-On (SSO)
OpenShift - Getting Started with Red Hat Single Sign-On (SSO)

Updated:   |  OpenShift articles

There are multiple different types of Identity Providers (IdP) that OpenShift can use for authentication.

Both the Red Hat build of the Keycloak Operator and Red Hat Single Sign-On (SSO) (this article) use keycloak as the backend Identity Provider (IdP) system. Red Hat Single Sign-On (SSO) is much easier to install and configure but may limit you from being able to use or configure certain features. For example, Red Hat Single Sign-On (SSO) installs and configures a Postgres SQL database for you, whereas with Red Hat build of the Keycloak Operator you install and configure the Postgres SQL database.

 

Install the Red Hat Single Sign-On (SSO) Operator

This assumes you have already installed the Red Hat Single Sign On (SSO) Operator.

The oc get operators command can be used to confirm that the Red Hat Single Sign On (SSO) Operator has been installed in the sso namespace.

]$ oc get operators
NAME                                                    AGE
rhsso-operator.sso                                      11m

 

And there should be a rhsso-operator deployment, replica set and pod in the sso namespace.

~]$ oc get deployments --namespace sso
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
rhsso-operator        1/1     1            1           14m

~]$ oc get replicasets --namespace sso
NAME                            DESIRED   CURRENT   READY   AGE
rhsso-operator-5564c95f95       1         1         1       13m

~]$ oc get pods --namespace sso
NAME                                  READY   STATUS    RESTARTS   AGE
rhsso-operator-5564c95f95-pktgt       1/1     Running   0          12m

 

Create the keycloak resource

The following command can be used to get the OpenShift ingress "apps" URL. Check out my article FreeKB - OpenShift - Display ingress domain apps URL for more details on OpenShift ingress.

oc get ingresses.config cluster --output jsonpath={.spec.domain}

 

Let's create a YAML file named keycloak.yaml that contains the following, updating hostname with the "apps" URL returned by the prior command.

apiVersion: keycloak.org/v1alpha1
kind: Keycloak
metadata:
  name: sso
  namespace: sso
  labels:
    app: sso
spec:
  externalAccess:
    enabled: True
  hostname:
    hostname: https://sso.<apps URL returned by the prior command>
  instances: 1

 

And use the oc apply command to create the keycloak resources.

oc apply --filename keycloak.yaml

 

Since the namespace of the apiVersion of the Keycloak resource is keycloak.org this should create a keycloak.keycloak.org resource named sso in this example.

]$ oc get keycloak.keycloak.org --namespace sso
NAME   AGE
sso    10s

 

This should create two pods, keycloak-0 and a postgresql pod.

]$ oc get pods --namespace sso
NAME                                  READY   STATUS    RESTARTS   AGE
keycloak-0                            1/1     Running   0          2m42s
keycloak-postgresql-f965866f9-xv4qb   1/1     Running   0          2m43s
rhsso-operator-5564c95f95-pktgt       1/1     Running   0          12m

 

A few keycloak services.

]$ oc get services --namespace sso
NAME                     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
keycloak                 ClusterIP   10.11.12.13    <none>        8443/TCP            2m59s
keycloak-discovery       ClusterIP   None             <none>        8080/TCP            2m58s
keycloak-monitoring      ClusterIP   10.11.12.13    <none>        9990/TCP            2m58s
keycloak-postgresql      ClusterIP   172.30.117.229   <none>        5432/TCP            2m59s

 

A keycloak replica set.

]$ oc get replicasets --namespace sso
NAME                            DESIRED   CURRENT   READY   AGE
keycloak-postgresql-f965866f9   1         1         1       3m27s
rhsso-operator-5564c95f95       1         1         1       13m

 

A keycloak stateful set.

]$ oc get statefulsets --namespace sso
NAME       READY   AGE
keycloak   1/1     3m54s

 

A keycloak deployment.

]$ oc get deployments --namespace sso
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
keycloak-postgresql   1/1     1            1           4m10s
rhsso-operator        1/1     1            1           14m

 

Create a Route

Let's create a YAML file that has the following to create a route to the keycloak service, which then goes to the keycloak app in the keycloak-0 pod.

apiVersion: route.openshift.io/v1
kind: Route
metadata:
  labels:
    app: keycloak
    route-type: default
  name: sso
  namespace: sso
spec:
  host: sso.<your OpenShift ingress apps URL>
  port:
    targetPort: keycloak
  tls:
    termination: reencrypt
  to:
    kind: Service
    name: keycloak
    weight: 100
  wildcardPolicy: None

 

And use the oc apply command to create the route.

oc apply --filename keycloak.yaml

 

The route should now exist.

]$ oc get routes --namespace sso
NAME                       HOST/PORT                            PATH      SERVICES   PORT       TERMINATION   WILDCARD
keycloak                   sso.apps.openshift.example.com                 keycloak   keycloak   reencrypt     None

 

And you should get the SSO console when you go to the route. Nice!

 

Sign into the SSO console

In this example, since "name" in the keycloak.yaml file is "sso" there should be a secret named credential-sso that contains the base 64 encoded username and password to sign into the SSO console.

~]$ oc get secret credential-sso --namespace sso --output yaml
apiVersion: v1
data:
  ADMIN_PASSWORD: M2labcJnMl9hVmNXYZE9PQ==
  ADMIN_USERNAME: YWzbaZ4=
kind: Secret
metadata:
  creationTimestamp: "2024-10-30T01:20:45Z"
  labels:
    app: keycloak
    keycloak: sso
  name: credential-sso
  namespace: sso
  ownerReferences:
  - apiVersion: keycloak.org/v1alpha1
    blockOwnerDeletion: true
    controller: true
    kind: Keycloak
    name: example-sso
    uid: 643e49f3-f390-4caf-a81e-0b9john.doe9f
  resourceVersion: "355828349"
  uid: a822ad9a-7038-4f3b-ab79-5a04b34f1c2f
type: Opaque

 

The base64 command can be used to decode the username and password.

~]$ oc get secret credential-sso --namespace sso --output jsonpath="{.data.ADMIN_USERNAME}" | base64 --decode
admin
~]$ oc get secret credential-sso --namespace sso --output jsonpath="{.data.ADMIN_PASSWORD}" | base64 --decode
3ibw2g2_aVcQNA==

 

And then you should be able to sign into the SSO console with the decoded admin username and password.

 

Create an OpenID client

Let's configure OpenShift to use SSO for authentication. In the SSO console, select Manage Realms > add realm.

 

Give the realm a name, ensure it is enabled (of course), and select Create.

 

In the realm you created, select Clients > Create client.

 

Get the oAuth URL of your OpenShift cluster. Check out my article FreeKB - OpenShift - Return oAuth URLs.

~]# oc get ingresses.config cluster --output jsonpath={.status.componentRoutes[].defaultHostname}
oauth-openshift.apps.openshift.example.com

 

In General settings, ensure the client protocol is OpenID Connect, enter whatever you would like for the client ID, and enter your oAuth URL.

 

Update the client Access Type to Confidential.

 

Select the Credentials tab and copy the Secret, which will be something like MdfkjM234MDSFK234sdfkljMKADSFasdfsf. On a Linux system, using printf and base64 to get the base64 encoded value of the secret.

]$ printf MdfkjM234MDSFK234sdfkljMKADSFasdfsf | base64
TWRma2pNMjM0TURTRksyMzRzZGZrbGpNS0FEU0Zhc2Rmc2Y=

 

Create a secret in the openshift-config namespace that contains clientSecret and the base64 encoded value of the Client Secret.

apiVersion: v1
kind: Secret
metadata:
  name: sso
  namespace: openshift-config
data:
  clientSecret: TWRma2pNMjM0TURTRksyMzRzZGZrbGpNS0FEU0Zhc2Rmc2Y=
type: Opaque

 

Create a User and Group

It is noteworthy that in the SSO console, you can pull in users and groups from Active Directory. However, for the purpose of this walkthrough, let’s just create a dummy user and group, for proof of concept purposes.

At Groups, create a group.

 

Create a user account and ensure the user account is a member of the group you created.

 

Give the user a password.

 

Update OpenShift to use SSO as an Identity Provider (IdP)

Before adding the SSO OpenID as an Identity Provider (IdP) in your OpenShift cluster, let's make sure the SSO issuer URL returns a response. You can simply plug the URL into your web browser address bar and something like this should be returned.

{
  "realm": "my-realm",
  "public_key": "MIIBIj...../7xwIDAQAB",
  "token-service": "https://sso.apps.openshift.example.com/auth/realms/my-realm/protocol/openid-connect",
  "account-service": "https://sso.apps.openshift.example.com/auth/realms/my-realm/account",
  "tokens-not-before": 0
}

 

Last but not least, let's add the SSO Identity Provider (IdP) to the oauth cluster resource.

  • clientSecret name must be the name of the secret you created in the openshift-config namespace that contains the sso clientSecret
  • openID issuer must be the realm you created in sso that contains your OpenID client
  • identityProviders type must be OpenID since an OpenID client was created in sso
  • issuer URL must end with the realm you created
apiVersion: config.openshift.io/v1
kind: OAuth
metadata:
  name: cluster
spec:
  identityProviders:
  - mappingMethod: add
    name: sso
    openID:
      claims:
        email:
        - email
        groups:
        - groups
        name:
        - name
        preferredUsername:
        - preferred_username
      clientID: sso-openid
      clientSecret:
        name: sso
      extraScopes: []
      issuer: https://sso.<your OpenShift apps URL>/auth/realms/my-realm
    type: OpenID

 

This should cause the authentication Cluster Operator to terminate the pods in the openshift-authentication namespace, one at a time, and spawn new pods.

~]$ oc get clusteroperators
NAME                                       VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE    MESSAGE
authentication                             4.18.22   True        True          False      122d     OAuthServerDeploymentProgressing: deployment/oauth-openshift.openshift-authentication: 2/3 pods have been updated to the latest generation and 2/3 pods are available

 

And you should see the pods in the openshift-authentication namespace Terminating and new pods being spawned.

~]$ oc get pods --namespace openshift-authentication
NAME                               READY   STATUS        RESTARTS   AGE
oauth-openshift-79776b975b-rnf6n   1/1     Terminating   0          117s
oauth-openshift-7b895986c9-f4zcw   1/1     Running       0          46s
oauth-openshift-7b895986c9-pxmcv   0/1     Pending       0          19s
oauth-openshift-7b895986c9-z5z54   1/1     Running       0          60s

 

Now when you go to the oauth URL to sign into your OpenShift cluster, there should be an SSO option. Awesome!

 

And you should be able to sign into the OpenShift cluster using one of your user accounts in keycloak.

 


 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


Please enter d4d209 in the box below so that we can be sure you are a human.