-
chevron_right
Keycloak Identity and Access Management on FreeBSD
Slixfeed · Sunday, 10 March - 10:35 · 8 minutes
Many times I wrote about FreeIPA/IDM – but I have one problem with it – its not currently possible to run FreeIPA on FreeBSD … so I searched for other open source alternatives and found Keycloak. What surprised me even more is that its even available in the FreeBSD Ports as net/keycloak port. So I wanted to check how it works/runs on FreeBSD … and this is exactly how this article happened.
My earlier FreeIPA/IDM attempts are below.
- Connect FreeBSD to FreeIPA/Red Hat Identity Management
- Connect FreeBSD 13.2 to FreeIPA/IDM
- Connect FreeBSD 14.0-STABLE to FreeIPA/IDM
- FreeBSD on FreeIPA/IDM with Poudriere Repo
First – we will create new VM for our server. I will use sysutils/vm-bhyve-devel for Bhyve but feel free to use any other hypervisor (or even w/o one). To not waste time installing I will also use provided by FreeBSD project VM-IMAGE with ZFS enabled – FreeBSD-14.0-RELEASE-amd64-zfs.raw disk0.img
host # cat /vm/.templates/freebsd.conf loader="bhyveload" cpu=1 memory=256M network0_type="virtio-net" network0_switch="public" disk0_type="nvme" disk0_name="disk0.img" host # vm create -t freebsd -c 2 -m 4G -s 10G keycloak host # ls -lh /vm/keycloak total 3402399 -rw------- 1 root wheel 10G Mar 10 10:47 disk0.img -rw-r--r-- 1 root wheel 209B Mar 10 07:20 keycloak.conf -rw-r--r-- 1 root wheel 96B Mar 10 07:22 vm-bhyve.log host # cd /vm/keycloak host # rm -f disk0.img host # cp /vm/TEMPLATE/FreeBSD-14.0-RELEASE-amd64-zfs.raw disk0.img host # truncate -s 10G disk0.img host # vm start keycloak Starting keycloak * found guest in /vm/keycloak * booting... host # vm console keycloak
Type root as user and hit [ENTER] for empty password. Now the FreeBSD setup and needed packages.
root@freebsd:~ # :> ~/.hushlogin root@freebsd:~ # cat << EOF > /etc/rc.conf hostname="keycloak.lab.org" ifconfig_DEFAULT="inet 10.1.1.211/24" defaultrouter="10.1.1.1" growfs_enable="YES" zfs_enable="YES" sshd_enable="YES" postgresql_enable="YES" keycloak_enable="YES" keycloak_env="KEYCLOAK_ADMIN=admin KEYCLOAK_ADMIN_PASSWORD=password" EOF root@freebsd:~ # echo 10.1.1.211 keycloak.lab.org keycloak >> /etc/hosts root@freebsd:~ # mkdir -p /usr/local/etc/pkg/repos root@freebsd:~ # sed -e s/quarterly/latest/g /etc/pkg/FreeBSD.conf \ > /usr/local/etc/pkg/repos/FreeBSD.conf root@freebsd:~ # echo nameserver 1.1.1.1 > /etc/resolv.conf root@freebsd:~ # drill freebsd.org | grep '^[^;]' freebsd.org. 799 IN A 96.47.72.84 root@freebsd:~ # service netif restart root@freebsd:~ # service routing restart root@freebsd:~ # service hostname restart Setting hostname: keycloak.lab.org. root@keycloak:~ # passwd Changing local password for root New Password: Retype New Password: root@keycloak:~ # cat << EOF >> /etc/ssh/sshd_config PermitRootLogin yes UseDNS no EOF root@keycloak:~ # service sshd enable root@keycloak:~ # service sshd start root@keycloak:~ # exit
Now switch to ssh(1) for better experience – needed to paste larger blocks of configs/text.
host % ssh root@10.1.1.211 root@keycloak:~ # pkg install -y keycloak postgresql16-server postgresql16-client root@keycloak:~ # service postgresql enable root@keycloak:~ # service postgresql initdb root@keycloak:~ # service postgresql start root@keycloak:~ # sockstat -l4 USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS postgres postgres 2265 7 tcp4 127.0.0.1:5432 *:* root syslogd 656 7 udp4 *:514 *:* root@keycloak:~ # su - postgres -c psql psql (16.2) Type "help" for help. postgres=# ALTER USER postgres WITH PASSWORD 'password'; postgres=# CREATE DATABASE keycloak with encoding 'UTF8'; CREATE DATABASE postgres=# GRANT ALL ON DATABASE keycloak TO postgres; GRANT postgres=# \q root@keycloak:~ # cd /usr/local/share/java/keycloak/conf root@keycloak:~ # openssl req -x509 -newkey rsa:2048 -keyout server.key.pem -out server.crt.pem -days 36500 -nodes -subj "/C=PL/ST=lodzkie/L=Lodz/O=Vermaden/OU=HR/CN=keycloak.lab.org" root@keycloak:~ # chmod 600 server.crt.pem server.key.pem root@keycloak:~ # chown keycloak:keycloak server.crt.pem server.key.pem root@keycloak:~ # cat << EOF > /usr/local/share/java/keycloak/conf/keycloak.conf db=postgres db-username=postgres db-password=password db-url=jdbc:postgresql://localhost:5432/keycloak hostname-strict-https=true hostname-url=https://keycloak.lab.org:8443/ hostname-admin-url=https://keycloak.lab.org:8443/ https-certificate-file=/usr/local/share/java/keycloak/conf/server.crt.pem https-certificate-key-file=/usr/local/share/java/keycloak/conf/server.key.pem proxy=edge EOF root@keycloak:~ # echo quarkus.transaction-manager.enable-recovery=true \ > /usr/local/share/java/keycloak/conf/quarkus.properties root@keycloak:~ # chown keycloak:keycloak /usr/local/share/java/keycloak/conf/quarkus.properties root@keycloak:~ # service keycloak enable root@keycloak:~ # service keycloak build The following run time non-cli properties were found, but will be ignored during build time: kc.db-url, kc.db-username, kc.db-password, kc.hostname-url, kc.hostname-admin-url, kc.hostname-strict-https, kc.https-certificate-file, kc.https-certificate-key-file, kc.proxy Updating the configuration and installing your custom providers, if any. Please wait. 2024-03-10 09:01:17,701 INFO [io.quarkus.deployment.QuarkusAugmentor] (main) Quarkus augmentation completed in 29796ms Server configuration updated and persisted. Run the following command to review the configuration: kc.sh show-config root@keycloak:~ # /usr/local/share/java/keycloak/bin/kc.sh show-config Current Mode: production Current Configuration: kc.config.built = true (SysPropConfigSource) kc.db = postgres (PropertiesConfigSource) kc.db-password = ******* (PropertiesConfigSource) kc.db-url = jdbc:postgresql://localhost:5432/keycloak (PropertiesConfigSource) kc.db-username = postgres (PropertiesConfigSource) kc.hostname-admin-url = https://keycloak.lab.org:8443/ (PropertiesConfigSource) kc.hostname-strict-https = true (PropertiesConfigSource) kc.hostname-url = https://keycloak.lab.org:8443/ (PropertiesConfigSource) kc.https-certificate-file = /usr/local/share/java/keycloak/conf/server.crt.pem (PropertiesConfigSource) kc.https-certificate-key-file = /usr/local/share/java/keycloak/conf/server.key.pem (PropertiesConfigSource) kc.log-console-output = default (PropertiesConfigSource) kc.log-file = ${kc.home.dir:default}${file.separator}data${file.separator}log${file.separator}keycloak.log (PropertiesConfigSource) kc.optimized = true (PersistedConfigSource) kc.proxy = edge (PropertiesConfigSource) kc.spi-hostname-default-admin-url = https://keycloak.lab.org:8443/ (PropertiesConfigSource) kc.spi-hostname-default-hostname-url = https://keycloak.lab.org:8443/ (PropertiesConfigSource) kc.spi-hostname-default-strict-https = true (PropertiesConfigSource) kc.version = 23.0.6 (SysPropConfigSource)
We now have needed packages installed. Self signed certificate for HTTPS generated. PostgreSQL database and Keycloak configured. We will need small patch to enable passing env(1) variables at the Keycloak daemon start. It will allow to use keycloak_env at the /etc/rc.conf main FreeBSD config file. This is needed to configure the initial admin user as sated in the Keycloak documentation.
Now back to the patch.
root@keycloak:~ # cat /root/keycloak.patch --- /root/keycloak 2024-03-08 11:46:21.847315000 +0000 +++ /usr/local/etc/rc.d/keycloak 2024-03-08 11:47:22.027102000 +0000 @@ -28,6 +28,7 @@ : ${keycloak_enable:=NO} : ${keycloak_user:=keycloak} : ${keycloak_group:=keycloak} +: ${keycloak_env:=""} : ${keycloak_flags="start"} : ${keycloak_java_home="/usr/local/openjdk17"} @@ -54,6 +55,7 @@ echo "Starting keycloak." ${command} ${command_args} \ + env ${keycloak_env} \ /usr/local/share/java/keycloak/bin/kc.sh \ ${keycloak_flags} } root@keycloak:~ # cd /usr/local/etc/rc.d root@keycloak:/usr/local/etc/rc.d # patch < /root/keycloak.patch Hmm... Looks like a unified diff to me... The text leading up to this was: -------------------------- |--- /root/keycloak 2024-03-08 11:46:21.847315000 +0000 |+++ /usr/local/etc/rc.d/keycloak 2024-03-08 11:47:22.027102000 +0000 -------------------------- Patching file keycloak using Plan A... Hunk #1 succeeded at 28. Hunk #2 succeeded at 55 with fuzz 2. Hmm... Ignoring the trailing garbage. done
Now we will start Keycloak. Its possible to track its startup process in the /var/log/keycloak/keycloak.out file. Below You will find last 4 lines that you want to see – with Keycloak 23.0.6 on JVM (powered by Quarkus 3.2.10.Final) started in 19.251s. message
root@keycloak:~ # service keycloak start root@keycloak:~ # tail -f /var/log/keycloak/keycloak.out (...) 2024-03-10 09:12:15,550 INFO [io.quarkus] (main) Keycloak 23.0.6 on JVM (powered by Quarkus 3.2.10.Final) started in 19.251s. Listening on: http://0.0.0.0:8080 and https://0.0.0.0:8443 2024-03-10 09:12:15,551 INFO [io.quarkus] (main) Profile prod activated. 2024-03-10 09:12:15,552 INFO [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, jdbc-h2, jdbc-mariadb, jdbc-mssql, jdbc-mysql, jdbc-oracle, jdbc-postgresql, keycloak, logging-gelf, micrometer, narayana-jta, reactive-routes, resteasy-reactive, resteasy-reactive-jackson, smallrye-context-propagation, smallrye-health, vertx] 2024-03-10 09:12:16,303 INFO [org.keycloak.services] (main) KC-SERVICES0009: Added user 'admin' to realm 'master' [CTRL]-[C] root@keycloak:~ # top -ab -o res 10 last pid: 3067; load averages: 0.50, 0.47, 0.42 up 0+02:56:35 09:19:04 18 processes: 1 running, 17 sleeping CPU: 1.4% user, 0.0% nice, 0.4% system, 0.2% interrupt, 98.0% idle Mem: 299M Active, 176M Inact, 3247M Wired, 264K Buf, 202M Free ARC: 2965M Total, 902M MFU, 1982M MRU, 4096B Anon, 12M Header, 50M Other 2766M Compressed, 2934M Uncompressed, 1.06:1 Ratio Swap: 1024M Total, 1024M Free PID USERNAME THR PRI NICE SIZE RES STATE C TIME WCPU COMMAND 2981 keycloak 41 68 0 1425M 299M uwait 1 0:37 0.00% /usr/local/openjdk17/bin/java -Dkc.config.built=true -Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.err.encoding=UTF-8 -Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8 -XX:+ExitOnOutOfMemoryError -Djava.security.egd=file:/dev/urandom -XX:+UseParallelGC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:FlightRecorderOptions=stackdepth=512 --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED -Dkc.home.dir=/usr/local/share/java/keycloak/bin/.. -Djboss.server.config.dir=/usr/local/share/java/keycloak/bin/../conf -Djava.util.logging.manager=org.jboss.logmanager.LogManager -Dquarkus-log-max-startup-records=10000 -cp /usr/local/share/java/keycloak/bin/../lib/quarkus-run.jar io.quarkus.bootstrap.runner.QuarkusEntryPoint start 3063 postgres 1 24 0 181M 49M kqread 1 0:00 0.00% postgres: postgres keycloak 127.0.0.1(21936) idle (postgres) 2266 postgres 1 20 0 178M 48M kqread 1 0:00 0.00% postgres: checkpointer (postgres) 3062 postgres 1 20 0 181M 47M kqread 1 0:00 0.00% postgres: postgres keycloak 127.0.0.1(22820) idle (postgres) 2270 postgres 1 20 0 179M 31M kqread 0 0:00 0.00% postgres: autovacuum launcher (postgres) 2271 postgres 1 20 0 179M 31M kqread 0 0:00 0.00% postgres: logical replication launcher (postgres) 2269 postgres 1 20 0 178M 31M kqread 0 0:00 0.00% postgres: walwriter (postgres) 2267 postgres 1 20 0 178M 31M kqread 0 0:00 0.00% postgres: background writer (postgres) 2265 postgres 1 20 0 178M 30M kqread 0 0:00 0.00% /usr/local/bin/postgres -D /var/db/postgres/data16 2420 root 1 20 0 22M 11M select 1 0:01 0.00% sshd: root@pts/0 (sshd)
Add also on the host system the IP information to the /etc/hosts file and check https://keycloak.lab.org:8443 in your browser.
host # echo 10.1.1.211 keycloak.lab.org keycloak >> /etc/hosts host % firefox 'https://keycloak.lab.org:8443'
As we use self signed certificate You will be warned by potential security risk. Hit ‘Advanced’ and then ‘Accept the Risk and Continue’ buttons.
Next click the Administration Console link.
Login with admin and password (or your password if You used other one).
… and You can now create your new realm, add users, create groups etc. You have fully working Keycloak in production mode.
Now … like with FreeIPA/IDM – it would be nice to attach FreeBSD to it so one could login to FreeBSD system with Keycloak user … not so fast unfortunately. To make such things be possible You need a PAM module for Keycloak … and I was not able to find one that will work on FreeBSD … and the Keycloak package also comes without one.
root@keycloak:~ # pkg info -l keycloak | grep -i pam
root@keycloak:~ #
After grepping the Internet I found two solutions … but only for Linux.
One of them was a step by step Keycloak PAM Module Development Tutorial guide which showed you how to write such PAM module.
The other one was Keycloak SSH PAM project on GitHub which provided more or less ready solution for Linux systems.
So while with FreeIPA/IDM we had server on Linux that allowed to connect FreeBSD systems to it – we now hat Keycloak server hosted on FreeBSD that allows connecting Linux systems
Not much of an improvement – but maybe someone will find that guide useful.