OpenID Connect with Kerberos authentication on OpenShift 4
The Old World
In the (not so) old world our organization provided internal service over VPN and the available authentication method was LDAP authentication for each service.
Time past and then need for a Single sign one grow with it. The most common and available SSO at the time with Kerberos authentication (must by using Microsoft Active Directory).
Sense around 2010 Linux and Windows became to work together more and more with in the organization providing services to each other and the need for Kerberos authentication on Linux while using Active Directory became more available and easy to configure.
Today it is a (relative) simple task connecting a RHEL/ubuntu Linux Server to the Active Directory and using it as an Identity provider.
The new World
Today we want to run more and more application on OpenShift/Kubernetes but some Organization would still prefer to use Kerberos authentication and not switch to OpenID connect or SAML2 because of the heavy cause in this type of shift.
A very Good Open Source project that we can use to provide OpenID connect or SAML2 while working with Kerberos in the backend is keycloak
This Tutorial is to provide a way of using Kerberos authentication with keycloak web services and provide OpenID connect for a web application running on OpenShift 4.
Architecture design :
How to Configure
In our case we will start for the Active Directory side by create a keytab with specific requirements. the we build a small application using apache (httpd) Kerberos Authentication module and connect everything together.
Creating Keytab
A keytab is a file where the Service principal is stored and it’s a way for the application to identify itself in the kerberos realm. (In our case the Kerberos realm is the Active Directory Domain).
The Keytab that is been used by Red Hat SSO needs to be connected to a user on the Active Directory so the step are :
- Create a user in the AD
- Modify the user to allow 256 bit encryption
- Create the keytab from the user
- Mount the keytab for the POD deployment .
Create an AD user
There are many ways to create AD users . The important note is that the user is not required to change his password upon next login , the user is enabled and that the password will never expire.
256 encryption
The Following part is an important part of the process.
the user must support kerberos encryption in the length of 245 bit so the user must be enabled to work with this type of encryption.
In order to configure it right click on the user from the AD users and computers (ADUC) manager.
Click on “account” and in the account options make sure that “This account supports Kerberos AES 256-bit encryption” is marked as shown :
creating the keytab
In order to create the keytab open a terminal window with administrator privileges and run the following command :
ktpass -princ HTTP/<Service URL>@<Kerberos realm> -pass <password of user> -kvno 0 -mapuser <Domain short name>\<username> -out rh-sso.keytab -ptype KRB5_NT_PRINCIPAL -crypto all
Replace the following :
- “<Service URL>” with your ingress (route) URL and make sure the Kerberos realm is in Capital letters.
- Replace the <password> with the user passowrd
- Replace the “<Domain short name> with the beginning of you domain (For example in the domain “example.com” the short name with be “example”).
- Replace the username with the application user name “where we set the AES256 encryption”
For example
If our domain is example.com and the user / pass are rhsso and the URL is sso.example.com we will run the following command :
ktpass -princ HTTP/sso.example.com@EXAMPLE.COM -pass rhsso -kvno 0 -mapuser example\rhsso -out rh-sso.keytab -ptype KRB5_NT_PRINCIPAL -crypto all
we will need get the user base dn in order use it for the ldap bind connection so we need to run the following command :
dsquery user -name rh-sso # in our example the user is rh-sso
Once the command is completed successfully we will have a keytab ready for our Red Hat SSO named web-sso.keytab.
The keytab is a binary file so we need to copy it to a bastion/workstation with “oc” available on it in order to attach it to our OpenShift namespace.
Mounting the keytab
We need to enable the application access to our newly created keytab In order to configure it we need to mount the file to the application deployment and make sure it is available for reading.
First let’s create our application namespace :
# oc new-project keycloak
Create the configmap for the keytab file :
# oc create configmap krb5-keycloak --from-file=./rh-sso.keytab -n keycloak
Now we need to deploy the keycloak application and enable the usage of Kerberos authentication.
Keycloak
Users authenticate with Keycloak rather than individual applications. This means that your applications don’t have to deal with login forms, authenticating users, and storing users. Once logged-in to Keycloak, users don’t have to login again to access a different application.
This also applied to logout. Keycloak provides single-sign out, which means users only have to logout once to be logged-out of all applications that use Keycloak.
Keycloak/rh-sso Deployment
To deploy keyCloak to your Kubernetes Cluster you can run the following commands :
rh-sso
if you are using rh-sso (the commercial version ) you can skip this part and deploy RH-SSO by using the official documents !!
keycloak for Kubernetes
A very good tutorial about how to deploy keycloak can be found in the official page here
keycloak for OpenShift
A very good tutorial about how to deploy keycloak on OpenShift can be found on the official page as well here
Now that the application is available let’s patch the keytab configMap which we created earlier :
# oc set volume deployment/keycloak --add --name=krb5-keycloak --mount-path /etc/rh-sso.keytab --sub-path rh-sso.keytab --source='{"configMap":{"name":"krb5-keycloak","items":[{"key":"rh-sso.keytab","path":"rh-sso.keytab"}]}}'
(You may need to change the deployment to deploymentconfig or dc)
the keycloak application is deployed and we can move on to the configuration part :
keycloak configuration
Go to the Web Page :
Kick on the Admin Console :
Login to the portal ( the default username and password are admin/admin)
Once login let’s create a new Domain :
For this example we will call it “example” :
Once we created the Realm we can setup the user-federation :
On the Bar options we will select “ldap”:
in the following window we will configure it with the following values
- vendor : Active directory
- username LDAP attribute : sAMAccountName
- RDN LDAP attribute : sAMAccountName
- connection URL : ldap://YOUR_DC_FQDN
- users DN : dc=example,dc=com
- search scope : subtree
- bind DN : cn=rhsso,ou=services,dc=example,dc=com # this is the output of the “
dsquery"
command - bind credentials : the user password (rhsso in our example)
I highly recommend running both test before you save the configuration.
Next for the Kerberos authenticaiton we will need kerberos integration , for that we have a specific sub tab at the bottum of the page.
Once you click on it we can setup “allow kerberos authentication” to “on” and add the following inforamtion :
- kerberos realm : EXAMPLE.COM (or LAB.TEST as it shown on the image bellow)
- Next we need to set the same server principal we setup at the command running on the windows server
- KeyTab : the location of the keytab in the pod. In our case we have mounted it to /etc/rh-sso.keytab
for the final action item click on “user kerberos For password authentication” and set it to “on”
mapping users groups :
In order to pass user’s groups with in the OpenID connect token we need to create a mapper on the LDAP connection so it will know how to extract groups.
For the we need to go the “mapper” tab at the top of the page :
And click on the “create” botton to add a new mapper value.
Once clicked , a new window will appear which we need to make some adjustments to it.
make sure the following values are in place :
- Name : ad-groups
- Mapper Type: gorup-ldap-mapper
- LDAP Groups DN : dc=example,dc=com
- “Preserve group inheritance” : off
- Ignore missing groups : on
- “user groups retrieve strategy” : “GET_GROUPS_FROM_USER_MEMBEROF_ATTRIBUTE”
And “save”
Once everything is set run the “Sync LDAP GROUPS to Keycloak” botton
(if everything was setup accordningly you can on see your AD group in the keycloak server).
Kerberos authentication
In order to use kerberos authentication when trying to reach an application while using the browser we need to make sure kerberos authentication is required.
In order to configure that we need to go to authentication :
Next in the “Flows” tab on the top left change the option to “Browser” and in the 3 row click on the “REQUIRED” option int the “kerberos” line as shown in the following image :
Now when authenitcation attept is being made by the browser , kerberos will be the only option.
Adding Client
Once RH-SSO is sync with the users and the active directory groups we need to create a client for each application which requires filtering my group membership.
In order to create the client we will run the following steps.
First go to “Clients” and click on “Create”:
Next we need to set up the name and the client protocol :
Once you save the configuration a new window will appear with more options.
In this page we need to update the “Access Type” to “confidential” and make sure everything is enabled except for “implicit flow Enabled”.
Next we can add a valid Redirect URLs or just add an asterisks (*) at the line.
Once we save the configuration a few more tabs will appear at the top of the page. The second one is credential where we can extract the client secret (the ID is the name we gave the client) :
For our final step we need to make sure the client sends the active directory user groups to the application. We can achieve that by switching to the “Mappers” tab.
And create a new Mapper for the ad-groups by click on the “create” button and fill in the following infromation :
Once we added the Mapper all the user’s Active directory groups will be sent in the authentication Token.
Web Application
for our web application we need to create an httpd service with OpenID Connect module enabled on it. Once the modules is installed we will create a simple OIDC connection website and create a simple index.html file to make sure we have being authenticated and everything is set.
# mkdir web-sso && cd web-sso
index.htm
We are going to start with a simple step and create our welcome index HTML file :
# cat > index.htm << EOF
<html>
<head>
<title> My web sso </title>
<body>
<p1> Welcome to Web SSO </p>
</body>
</html>
EOF
Once our file is ready we can continue to the httpd configuration :
We will begin with the Containerfile :
FROM quay.io/centos/centos:stream8
MAINTAINER Oren Oichman <Back to Root>RUN dnf install -y httpd && dnf module enable mod_auth_openidc -y && dnf install -y mod_auth_openidc && dnf clean allCOPY run-httpd.sh /usr/sbin/run-httpd.shRUN echo "PidFile /tmp/http.pid" >> /etc/httpd/conf/httpd.conf && \
sed -i "s/Listen\ 80/Listen\ 8080/g" /etc/httpd/conf/httpd.conf && \
sed -i "s/\"logs\/error_log\"/\/dev\/stderr/g" /etc/httpd/conf/httpd.conf && \
sed -i "s/CustomLog \"logs\/access_log\"/CustomLog \/dev\/stdout/g" /etc/httpd/conf/httpd.conf && \
echo 'IncludeOptional /opt/app-root/*.conf' >> /etc/httpd/conf/httpd.conf && \
mkdir /opt/app-root/ && chown apache:apache /opt/app-root/ && chmod 777 /opt/app-root/ && \
mkdir /opt/app-root/sso && chown apache:apache /opt/app-root/sso && chmod 777 /opt/app-root/ssoCOPY index.htm /opt/app-root/sso/
USER apacheEXPOSE 8080 8081
ENTRYPOINT ["/usr/sbin/run-httpd.sh"]
And for the run-httpd file :
#!/bin/bashif [ -z ${RH_SSO_FQDN} ]; then
echo "Environment variable RH_SSO_FQDN undefined"
exit 1
elif [[ -z $CLIENT_ID ]]; then
echo "Environment variable CLIENT_ID undefined"
exit 1
elif [[ -z $CLIENT_SECRET ]]; then
echo "Environment variable CLIENT_SECRET undefined"
exit 1
elif [[ -z $WEB_SSO_ROUTE ]]; then
echo "Environment variable WEB_SSO_ROUTE undefined"
exit 1
elif [[ -z $RH_SSO_REALM ]]; then
echo "Environment variable RH_SSO_REALM undefined"
exit 1
fiecho "
<VirtualHost *:8080>
RewriteEngine On
OIDCProviderMetadataURL https://${RH_SSO_FQDN}/auth/realms/${RH_SSO_REALM}/.well-known/openid-configuration
OIDCClientID $CLIENT_ID
OIDCClientSecret $CLIENT_SECRET
OIDCRedirectURI https://${WEB_SSO_ROUTE}/oauth2callback
OIDCCryptoPassphrase openshift<Directory "/opt/app-root/sso">
AllowOverride All
Options +Indexes
DirectoryIndex index.htm index.html
</Directory>
<Location />
AuthType openid-connect
Require valid-user
</Location>
</VirtualHost>
" > /tmp/reverse.conf
mv /tmp/reverse.conf /opt/app-root/reverse.conf/usr/sbin/httpd $OPTIONS -DFOREGROUND
Once everything is set we can build the image and push it to the registry.
( in my example the registry FQDN is registry.example.com)
# export REGISTRY="registry.example.com"# buildah bud -f Containerfile -t $REGISTRY/web-sso && buildah push $REGISTRY/web-sso
Now let’s create the following deployment :
#cat > web-sso-deployment.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web-sso
name: web-sso
spec:
replicas: 1
selector:
matchLabels:
app: web-sso
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: web-sso
spec:
containers:
- image: $REGISTRY/web-sso:latest
name: web-sso
ports:
- containerPort: 8080
env:
- name: RH_SSO_FQDN
value: sso.example.com
- name: CLIENT_ID
value: web-sso
- name: CLIENT_SECRET
value: cdf18ef6-c7c6-4e21-916d-f5900e6bfb25
- name: WEB_SSO_ROUTE
value: web-sso.example.com
- name: RH_SSO_REALM
value: example
EOF
and apply it
# oc apply -f web-sso-deployment.yaml
Now let’s create the service and the route :
# oc create service clusterip web-sso --tcp=8080
and for the route :
# oc create route edge web-sso --service=web-sso --hostname=web-sso.example.com --port=8080 --insecure-policy=Redirect
Now all we need to do is login to a WorkStation which in the AD domain , Open a browser and go to https://web-sso.example.com.
If it does not prompt you any password and shows you the website then everything is working as expected
If you have any question feel free to responed/ leave a comment.
You can find on linkedin at : https://www.linkedin.com/in/orenoichman
Or twitter at : https://twitter.com/ooichman