• 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.

    keycloak.logo

    My earlier FreeIPA/IDM attempts are below.

    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.

    keycloak-0-initial-admin-user

    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.

    keycloak-1-self-cert

    Next click the Administration Console link.

    keycloak-2-main-page

    Login with admin and password (or your password if You used other one).

    keycloak-3-admin-login

    … and You can now create your new realm, add users, create groups etc. You have fully working Keycloak in production mode.

    keycloak-4-admin-console

    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.

    pam-dev

    The other one was Keycloak SSH PAM project on GitHub which provided more or less ready solution for Linux systems.

    pam-kc

    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.

    EOF
    • chevron_right

      Keycloak API

      pubsub.slavino.sk / warlord0blog · Tuesday, 26 January, 2021 - 13:16 edit

    Keycloak is a great tool for authentication and I’m bundling it into a package that includes LDAP. What I want to do is automate the deployment of Keycloak so that it is provisioned to work with the LDAP that is also deployed without the using having to fettle with Keycloak manually- This is where the &ellipsisRead the full post »

    Značky: #ldap, #Linux, #keycloak