RHSSO IDP with IDM for Kerberos authentication flow
RHSSO & OIDC Intro
I don't like duplications so I’d like to promote my friend’s (and colleague) article about RHSSO, OAuth, and OIDC as an introduction to the topic, and just jump right into the technical guide;
Essentially that guide is intended for those who’d like to install RHSSO/Keycloak (the upstream project) with Kerberos as an authentication mechanism instead of basic auth (username+password).
I found the official project’s documentation a bit lacking and I’d like to make your life easier.
Architecture Overview
I installed the IDM (FreeIPA — the upstream project) as a container on a docker engine on a VM, and the RHSSO is installed on a VM of its own.
Furthermore, I configured the IDM as a DNS server as well for my environment (GCP).
Our “application” for testing is going to be an API that RHSSO exposes (https://<rhsso-host>:8443/auth/realms/master/account) that initiates the login process of the RHSSO just like any other application.
And finally, a VM client — a VM that is going to be an IDM-client with a Kerberos ticket, which it’ll receive after a successful login using a user that we will create in the IDM itself.
Our final test is going to be:
- Logging in to the VM client machine
- Verifying Kerberos ticket granted successfully by the IDM
- An attempt to access https://<rhsso-host>:8443/auth/realms/master/account
- A successful login to the user-personal details site without entering username+password
Now with all of the opening out of the way, let’s get to work;
Install IDM/FreeIPA as a docker container
I really can’t say how much I appreciate good opensource projects, one of them made that specific part of my work much much easier.
I had some configuration issues when I first tried to deploy it. It is quite important that the container will listen on the host’s IP address, and to enable all the ports both in the docker configuration and on the firewall-cmd on the machine itself. Also, some flags/options didn’t work as expected.
Note!! I tried to use podman but it was quite buggy, especially with the “listening on the host’s IP” part, so I used docker instead.
But happily, I manage to make it work as desired, with the following command:
## Prerequisites ##
$ sudo su -
# yum install docker -y
# yum install git -y
# systemctl enable --now docker
# git clone https://github.com/freeipa/freeipa-container.git
# cd freeipa-container
# docker build -t freeipa-server .## Explanation in the "Note" below ##
# rmdir /var/lib/ipa-data ; mkdir /var/lib/ipa-data
# setsebool -P container_manage_cgroup 1# docker login docker.io
# docker run --name idm-server-container -ti -e IPA_SERVER_IP=<vm_host_ip> -p 53:53/udp -p 53:53 -p 443:443 -p 80:80 -p 88:88/udp -p 389:389 -p 123:123/udp -p 464:464/udp -p 636:636 -p 88:88 -p 464:464 -h ipa.<your>.<domain> -v /sys/fs/cgroup:/sys/fs/cgroup:ro --tmpfs /run --tmpfs /tmp -v /var/lib/ipa-data:/data:Z freeipa-server --setup-dns
!!! if you have a problem fetching the image — try to fetch it with a specific tag: https://hub.docker.com/r/freeipa/freeipa-server !!!
This deployment has two parts.
In the first one, we install the IDM server interactively (using the command I just mentioned above) — we are doing this in that way because not all the ‘docker run’ command parameters work so it’s better the be safe then sorry I guess. At the end of that part we will make another ssh connection and force-stop the docker container.
Your final output should look like that: (I added the DNS forwarders because of my environment needs, but it’s not at all a must).
Note!! I used the “rmdir” because that is the directory that the IDM will save its data on and if we would like to reinstall it on the same machine it is required to be empty beforehand.
The second part is creating a service that runs the docker container after it has been configured, and enable + start it using systemctl so even if the server will be restarted the container will restart.
# cat > /usr/sbin/run_idm_docker.sh<< EOF
#!/bin/bash
docker start idm-server
EOF# chmod +x /usr/sbin/run_idm_docker.sh# cat > /etc/systemd/system/idm_docker.service << EOF
[Unit]
Description=run_idm_on_docker
After=network.target
[Service]
Type=idle
ExecStart=/usr/sbin/run_idm_docker.sh
TimeoutStartSec=600
TimeoutStopSec=600
[Install]
WantedBy=multi-user.target
EOF# chmod a+x /etc/systemd/system/idm_docker.service# systemctl enable --now idm_docker# systemctl status idm_docker
We also need to enable the IDM’s ports in the firewall policy. The IDM container is actually nice enough to tell us just that:
# firewall-cmd --add-port=80/tcp --add-port=443/tcp --add-port=636/tcp --add-port=389/tcp --add-port=88/tcp --add-port=53/tcp --add-port=464/tcp --add-port=88/udp --add-port=464/udp --add-port=53/udp --add-port=123/udp --permanent# firewall-cmd --reload
Add the IDM as a new nameserver to your /etc/resolv.conf and verify that the DNS resolving functionality works as expected using nslookup.
Install RHSSO/Keycloak
That part is pretty straight-forward; Run the following commands from the RHSSO/Keycloak server.
In that guide, I’m using Keycloak just in order to avoid subscription-manager complications in my environment but the exact same process will work with RHSSO.
Note!! In case you want to install it on a container (Docker/Openshift) you can use the image from official Red Hat Quay registry/Community OperatorHub here: https://www.keycloak.org/downloads.html
$ sudo su - # cd /opt
# wget https://downloads.jboss.org/keycloak/11.0.0/keycloak-11.0.0.tar.gz
# cd rh-sso-7.3/bin/
# yum install java-1.8.0-openjdk.x86_64 -y
# ./standalone.sh!! Stop it when it finish with the installation !!# cat > /etc/systemd/system/rhsso.service <<EOF
[Unit]
Description=rhsso
After=network.target
[Service]
Type=idle
ExecStart=/opt/rh-sso-7.3/bin/standalone.sh
TimeoutStartSec=600
TimeoutStopSec=600
[Install]
WantedBy=multi-user.target
EOF# chmod a+x /etc/systemd/system/rhsso.service# systemctl daemon-reload
# systemctl enable --now rhsso.service
# systemctl status rhsso.service# firewall-cmd — add-port=8443/tcp — permanent
# firewall-cmd — reload
In /etc/resolv.conf: add the IDM realm (domain) to the search options list and the IDM IP itself as the first nameserver. It is required in order to add the RHSSO as ipa-client as I’m about to do.
I advise you to make the /etc/resolv.conf immutable after the changes, just in case. Then add it to the “domain” using the ipa-client toolkit;
# sudo chattr +i /etc/resolv.conf# yum install -y ipa-client
# ipa-client-install
!! Make sure that user exists in the IDM server and that it has the required permissions!!
# kinit root
# klist !! Verification
Finally, we need to create a keytab in the IDM for the SSO so it’ll be able to authenticate users using Kerberos; Then we will pull it to the RHSSO and configure it in the UI.
Service: HTTP
Host: <rhsso-hostname>.<your domain>
(The @<realm> will be added automatically)
Then in the RHSSO server:
# ipa-getkeytab -p HTTP/vmrhsso-idp01.mtr-gcp.lab@MTR-GCP.LAB -s ipa.mtr-gcp.lab -k /opt/krb5.keytab
- Notice the output file’s location, we will use it next in the UI
In order to work with the UI we need to create an admin user: (the script is in: /opt/rh-sso-7.3/bin/)
# ./add-user-rhsso.sh -u admin -p admin# systemctl restart rhsso.service
Log in to the UI and add the “User Federation” source — that will be our IDM/FreeIPA.
Configure it
Note!! Test the connection + authentication!!!
Press the “Synchronize all users”
One last thing — make sure the “authentication scheme” in the RHSSO is configured like that:
That’s it with the RHSSO. Let’s test it.
Testing & Verification
From the VMClient (a VM with VNC-Server I installed on it for a nicer experience), make the same changes to the /etc/resolv.conf as we did in the RHSSO (including the “making it immutable” part) and run the following commands:
# sudo su -
# yum install -y ipa-client
# ipa-client-install
# exit
Create a test user in the IDM, and kinit with it in the VMclient machine:
$ kinit test
$ klist
Now that’s the only tricky part in that guide — make sure to enable Kerberos authentication in your browser. I used Firefox so I did it like this:
Now let’s access the /account API that the RHSSO exposes as a test “application” to make sure that our Kerberos authentication works.
Accept the risks and continue;
We can also see that there is a live session for that connection in the RHSSO, in case it will try to login to other applications using the same mechanism with RHSSO: