
There are multiple ways to authenticate in OpenShift.
- htpasswd OAuth Identity Provider
- kubeadmin
- SSO keycloak (this article)
Here are my notes as I prepared for the Red Hat Certified Specialist in OpenShift Automation and Integration exam (EX380).
oc login -u admin
SSO Images and Image Streams
Let's use the oc get imagestreams command to list the sso images in the openshift namespace. Notice this contains both the 7.5 and 7.6 image streams. As I write this, 7.6 is the latest SSO image.
~]$ oc get imagestreams --namespace openshift | grep sso
postgresql13-for-sso75-openshift-rhel8 image-registry.openshift-image-registry.svc:5000/openshift/postgresql13-for-sso75-openshift-rhel8 13-el8 11 months ago
postgresql13-for-sso76-openshift-rhel8 image-registry.openshift-image-registry.svc:5000/openshift/postgresql13-for-sso76-openshift-rhel8 13-el8 11 months ago
sso75-openshift-rhel8 image-registry.openshift-image-registry.svc:5000/openshift/sso75-openshift-rhel8 7.5,latest 13 months ago
sso76-openshift-rhel8 image-registry.openshift-image-registry.svc:5000/openshift/sso76-openshift-rhel8 7.6,latest 11 months ago
If you are running OpenShift version 3.x, you can use this command to ensure image streams have the 7.6 image streams.
for resource in sso76-image-stream.json \
passthrough/ocp-3.x/sso76-ocp3-https.json \
passthrough/ocp-3.x/sso76-ocp3-postgresql.json \
passthrough/ocp-3.x/sso76-ocp3-postgresql-persistent.json \
reencrypt/ocp-3.x/sso76-ocp3-x509-https.json \
reencrypt/ocp-3.x/sso76-ocp3-x509-postgresql-persistent.json
do
oc replace -n openshift --force -f \
https://raw.githubusercontent.com/jboss-container-images/redhat-sso-7-openshift-image/sso76-dev/templates/${resource}
done
Or this command if you are running OpenShift version 4.x.
for resource in sso76-image-stream.json \
passthrough/ocp-4.x/sso76-ocp4-https.json \
passthrough/ocp-4.x/sso76-ocp4-postgresql.json \
passthrough/ocp-4.x/sso76-ocp4-postgresql-persistent.json \
reencrypt/ocp-4.x/sso76-ocp4-x509-https.json \
reencrypt/ocp-4.x/sso76-ocp4-x509-postgresql-persistent.json
do
oc replace -n openshift --force -f \
https://raw.githubusercontent.com/jboss-container-images/redhat-sso-7-openshift-image/sso76-dev/templates/${resource}
done
The oc get images command can be used to see if the SSO 7.6 image exists in the openshift namespace.
~]$ oc get images --namespace openshift | grep -i sso
sha256:1a8c42f880d58f68682d4b42b208789ac4d3cedf1fa025c8bfb980a16e707528 registry.redhat.io/rh-sso-7/sso76-openshift-rhel8@sha256:1a8c42f880d58f68682d4b42b208789ac4d3cedf1fa025c8bfb980a16e707528
If the SSO 7.6 image does not exist in the openshift namespace, the oc import-image command can be used to import the SSO 7.6 image.
oc import-image rh-sso-7/sso76-openshift-rhel8:7.6 --from=registry.redhat.io/rh-sso-7/sso76-openshift-rhel8:7.6 --namespace openshift --confirm
Namespace Setup
Let's use the oc new-project command to create a project named sso.
oc new-project sso
Let's us the oc policy add-role-to-user command to add the view cluster role to the default service account in the sso namespace so that the default service account has the view permissions.
~]$ oc policy add-role-to-user view system:serviceaccount:$(oc project -q):default
clusterrole.rbac.authorization.k8s.io/view added: "system:serviceaccount:sso:default"
The oc get rolebindings command can be used to see that a role binding was created named "view".
~]$ oc get rolebindings --namespace sso
NAME ROLE AGE
view ClusterRole/view 57s
And the oc describe rolebinding command shows that the "view" role binding is mapped to the default service account.
~]$ oc describe rolebinding view --namespace sso
Name: view
Labels: <none>
Annotations: <none>
Role:
Kind: ClusterRole
Name: view
Subjects:
Kind Name Namespace
---- ---- ---------
ServiceAccount default sso
SSL Certificate and Secret
OpenSSL can be used to create a Java keystore file that will be used to secure HTTPS requests.
The following OpenSSL command will create a private key named sso.key and a public certificate named sso.crt.
openssl req -new -newkey rsa:4096 -x509 -keyout sso.key -out sso.crt -days 365 -subj "/CN=sso.ca"
OpenSSL can be used to verify that the public certificate sso.crt expires in 1 year and has Common Name (CN) sso.ca. Check out my article FreeKB - OpenSSL - Display CER CRT PEM file data for more details on this command.
~]$ openssl x509 -in sso.crt -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
20:f9:0c:59:f1:d3:37:11:af:23:c9:b1:c0:ac:9f:9c:12:a5:7e:b4
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = sso.ca
Validity
Not Before: Aug 21 01:21:30 2024 GMT
Not After : Aug 21 01:21:30 2025 GMT
Subject: CN = sso.ca
The following Java keytool command can be used to create a PKCS12 keystore file named keystore.p12. Check out my article FreeKB - Java - Create a keystore using the Java keytool command for more details on this command.
keytool -genkeypair -keyalg RSA -keysize 2048 -dname "CN=sso.openshift.example.com" -alias jboss -keystore keystore.p12 -storetype pkcs12
The Java keytool command can be used to create a certificate sign request for the HTTPS keystore. This will create the file named sso.csr.
keytool -certreq -keyalg rsa -alias jboss -keystore keystore.p12 -storetype pkcs12 -file sso.csr
Let's create a file named san.ext that contains the following.
[SAN]
subjectAltName=DNS:sso.openshift.example.com
And then use the following OpenSSL command to create sso.pem.
openssl x509 -req -CA sso.crt -CAkey sso.key -in sso.csr -out sso.pem -days 365 -CAcreateserial -extfile san.ext -extensions SAN
The following OpenSSL command can be used to see that the sso.pem file expires in 1 year, has Common Name (CN) sso.ca and has Subject Alternative Name (SAN) sso.openshift.example.com.
~]$ openssl x509 -in sso.pem -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
75:c0:c9:76:d0:32:c5:7f:ca:d3:8e:16:bc:08:29:48:34:91:11:fe
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = sso.ca
Validity
Not Before: Aug 21 01:33:55 2024 GMT
Not After : Aug 21 01:33:55 2025 GMT
Subject: CN = sso.openshift.example.com
The following Java keytool command can be used to import sso.pem into keystore.p12. When prompted "Trust this certificate" type yes and press enter.
~]$ keytool -import -file sso.crt -alias sso.ca -keystore keystore.p12 -storetype pkcs12
Enter keystore password:
Owner: CN=sso.ca
Issuer: CN=sso.ca
Serial number: 20f90c59f1d33711af23c9b1c0ac9f9c12a57eb4
Valid from: Tue Aug 20 20:21:30 CDT 2024 until: Wed Aug 20 20:21:30 CDT 2025
Certificate fingerprints:
SHA1: BB:63:06:E9:78:31:22:EC:57:B1:BE:AB:8E:FC:B9:41:3C:D7:14:96
SHA256: 2A:01:CE:7A:6A:31:54:56:91:4F:C8:25:3E:B2:1C:EA:CB:F5:06:07:C8:EC:76:2A:94:B1:5B:CA:D2:1B:11:65
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 4096-bit RSA key
Version: 3
Extensions:
#1: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 39 CA 97 D0 BF EF 52 BD 7A D5 CC 9C D3 11 D0 0A 9.....R.z.......
0010: E0 D7 CE BE ....
]
]
#2: ObjectId: 2.5.29.19 Criticality=true
BasicConstraints:[
CA:true
PathLen:2147483647
]
#3: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 39 CA 97 D0 BF EF 52 BD 7A D5 CC 9C D3 11 D0 0A 9.....R.z.......
0010: E0 D7 CE BE ....
]
]
Trust this certificate? [no]: yes
Certificate was added to keystore
The Java keytool command can be used to import sso.pem into keystore.p12.
keytool -import -file sso.pem -alias jboss -keystore keystore.p12 -storetype pkcs12
The following Java keytool command cna be used to create the jgroups.jceks file.
keytool -genseckey -alias secret-key -storetype JCEKS -keystore jgroups.jceks
The following Java keytool command can be used to create a truststore file named truststore.p12 that contains the sso.ca public certificate.
keytool -import -file sso.crt -alias sso.ca -keystore truststore.p12 -storetype pkcs12
Last but not least, the oc create secret command can be used to create a generic secret named sso-app-secret that contains the keystore.p12 and truststore.p12 and jgroups.jceks files.
oc create secret generic sso-app-secret --from-file=keystore.p12 --from-file=jgroups.jceks --from-file=truststore.p12
Deploy the SSO app
The oc get templates command can be used to list the SSO 7.6 templates in the openshift namespace.
~]$ oc get templates --namespace openshift --output name | grep -o 'sso76.\+' | sort
sso76-https
sso76-ocp3-x509-https
sso76-ocp3-x509-postgresql-persistent
sso76-ocp4-https
sso76-ocp4-postgresql
sso76-ocp4-postgresql-persistent
sso76-ocp4-x509-https
sso76-ocp4-x509-postgresql-persistent
sso76-postgresql
sso76-postgresql-persistent
Let's use the oc new-app command to deploy SSO 7.6 using the sso76-ocp4-x509-https template (in this example). Make note of the JGroups Cluster Password and RH-SSO Administrator Username and RH-SSO Administrator Password.
~]$ oc new-app --template=sso76-ocp4-x509-https
--> Deploying template "sso-demo/sso76-ocp4-x509-https" to project sso-demo
Red Hat Single Sign-On 7.6 on OpenJDK (Ephemeral) for OpenShift 4.X
---------
An example application based on RH-SSO 7.6 on OpenJDK image. For more information about using this template, see https://github.com/jboss-container-images/redhat-sso-7-openshift-image/tree/sso76-dev/docs.
A new RH-SSO service has been created in your project. The admin username/password for accessing the master realm via the RH-SSO console is IhqmDFay/q1IpjSn0go5euxB0s1cMbAMr42wuivNF. The HTTPS keystore used for serving secure content, the JGroups keystore used for securing JGroups communications, and server truststore used for securing RH-SSO requests were automatically created via OpenShift's service serving x509 certificate secrets by using a CA bundle that is automatically injected into any configMap annotated with 'service.beta.openshift.io/inject-cabundle=true' annotation. Refer to: https://github.com/openshift/openshift-docs/blob/enterprise-4.1/release_notes/ocp-4-1-release-notes.adoc#service-ca-bundle-changes for additional details about this CA bundle. To enable also dual-network clusters that support both IPv4 and IPv6 address families, all services defined by this template are configured having the 'spec.ipFamilyPolicy' field set to 'PreferDualStack' by default.
* With parameters:
* Application Name=sso
* Custom RH-SSO Server Hostname=
* JGroups Cluster Password=PrDhK7uLJoroqetoKL7SUMYI1U1wtkUW # generated
* Datasource Minimum Pool Size=
* Datasource Maximum Pool Size=
* Datasource Transaction Isolation=
* ImageStream Namespace=openshift
* RH-SSO Administrator Username=IhqmDFay # generated
* RH-SSO Administrator Password=q1IpjSn0go5euxB0s1cMbAMr42wuivNF # generated
* RH-SSO Realm=
* RH-SSO Service Username=
* RH-SSO Service Password=
* Container Memory Limit=1Gi
--> Creating resources ...
configmap "sso-service-ca" created
service "sso" created
service "sso-ping" created
route.route.openshift.io "sso" created
Warning: apps.openshift.io/v1 DeploymentConfig is deprecated in v4.14+, unavailable in v4.10000+
deploymentconfig.apps.openshift.io "sso" created
--> Success
Access your application via route 'sso-sso-demo.apps.openshift.example.com'
Run 'oc status' to view your app.
The oc get deploymentconfigs command should show there is a deployment config.
~]$ oc get deploymentconfigs
NAME REVISION DESIRED CURRENT TRIGGERED BY
sso 1 1 10 config,image(sso76-openshift-rhel8:7.6)
The oc get replicationcontrollers command should show there is a replication controller.
~]$ oc get replicationcontrollers
NAME DESIRED CURRENT READY AGE
sso-1 1 1 0 23h
And the oc get pods command should return the sso pods.
~]$ oc get pods
NAME READY STATUS RESTARTS AGE
sso-1-deploy 1/1 Running 0 91s
sso-1-pqbkp 0/1 Running 0 89s
The oc get services command should show there are two services.
~]$ oc get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
sso ClusterIP 172.30.19.88 <none> 8443/TCP 113s
sso-ping ClusterIP None <none> 8888/TCP 113s
The oc get routes command should return a single route.
~]$ oc get routes
NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD
sso sso-sso-demo.apps.openshift.example.com sso <all> reencrypt None
The logs in the pod should show that the /auth endpoint has been registered and the keycloak server WAR has been deployed. The sso pod contains a JBOSS Enterprise Application Server (EAP) and the keycloak server WAR was deployed to the JBOSS application server.
~]$ oc logs pod/sso-1-pt4kt
01:20:14,151 INFO [org.wildfly.extension.undertow] (ServerService Thread Pool -- 76) WFLYUT0021: Registered web context: '/auth' for server 'default-server'
01:20:14,207 INFO [org.jboss.as.server] (ServerService Thread Pool -- 73) WFLYSRV0010: Deployed "keycloak-server.war" (runtime-name : "keycloak-server.war")
01:20:14,227 INFO [org.jboss.as.server] (Controller Boot Thread) WFLYSRV0212: Resuming server
Did you find this article helpful?
If so, consider buying me a coffee over at