asks-consulting / keycloak

Ansible role that installs Keycloak (v17+, Quarkus) on Ubuntu Focal
GNU General Public License v3.0
0 stars 0 forks source link

Keycloak

This Ansible role installs Keycloak (v17+, Quarkus) on an Ubuntu 20.04 LXC container, with Keycloak configured to be accessed via a reverse proxy on a different host in the same network.

Motivation

It has become time to replace auth0.com backed by Google Apps with something else. Reasons auth0 is no longer viable:

Apache virtualhost on the reverse proxy

<VirtualHost *:80>
   ServerAdmin webmaster@example.com
   ServerName keycloak.example.com

   Redirect permanent / https://keycloak.example.com/

   ErrorLog ${APACHE_LOG_DIR}/keycloak.example.com_error.log
   CustomLog ${APACHE_LOG_DIR}/keycloak.example.com_access.log combined
</VirtualHost>

<VirtualHost *:443>
   ServerAdmin webmaster@example.com
   ServerName keycloak.example.com

   ProxyPreserveHost On
   ProxyRequests Off
   ProxyPass / http://10.252.116.2:8080/
   ProxyPassReverse / http://10.252.116.2:8080/
   RequestHeader set X-Forwarded-Proto "https"
   RequestHeader set X-Forwarded-For "https"

   SSLEngine on
   SSLCertificateKeyFile   /etc/letsencrypt/live/keycloak.example.com/privkey.pem
   SSLCertificateFile      /etc/letsencrypt/live/keycloak.example.com/cert.pem
   SSLCertificateChainFile /etc/letsencrypt/live/keycloak.example.com/chain.pem

   ErrorLog ${APACHE_LOG_DIR}/keycloak.example.com_error.log
   CustomLog ${APACHE_LOG_DIR}/keycloak.example.com_access.log combined
</VirtualHost>

Role dependencies

See meta/main.yml.

psql_version: 12
db_admin_username: postgres
java_use_ppa: false
java_version: '17'

Notes

The container runs a fresh Ubuntu Focal image, along with

https://www.keycloak.org/migration/migrating-to-quarkus#_setup_of_initial_users

To add the initial admin user, set the environment variables KEYCLOAK_ADMIN and KEYCLOAK_ADMIN_PASSWORD for the username and password of the user. Keycloak uses them at the first startup to create an initial user with administration rights.

Here is an example Ansible task using the deprecated add-user-keycloak.sh function. And another example (simpler).

I plan to start by simply maintaining a "list" of users/passwords in Keycloak itself. Furthermore, I want to install Keycloak on its own LXC container configured as far as possible for production, but without going so far as to run multiple Keycloak instances with a shared database backend.

Everytime that configuration gets changed, you need to execute bin/kc.sh build to rebuild the server configuration

https://confluence.atlassian.com/jirakb/postgresql-java-sql-sqlexception-no-suitable-driver-found-828780512.html

Ensure that the PostgreSQL driver is located in [...] in lib/:

root@muscat:/home/taha
# find /opt/keycloak/lib/ -type f -name "*jdbc*"
/opt/keycloak/lib/lib/main/io.quarkus.quarkus-jdbc-mysql-deployment-2.7.5.Final.jar
/opt/keycloak/lib/lib/main/com.oracle.database.jdbc.ojdbc11-21.4.0.0.jar
/opt/keycloak/lib/lib/main/io.quarkus.quarkus-jdbc-oracle-deployment-2.7.5.Final.jar
/opt/keycloak/lib/lib/main/io.quarkus.quarkus-jdbc-mssql-2.7.5.Final.jar
/opt/keycloak/lib/lib/main/io.quarkus.quarkus-jdbc-oracle-2.7.5.Final.jar
/opt/keycloak/lib/lib/main/io.quarkus.quarkus-jdbc-mariadb-deployment-2.7.5.Final.jar
/opt/keycloak/lib/lib/main/com.microsoft.sqlserver.mssql-jdbc-7.2.2.jre8.jar
/opt/keycloak/lib/lib/main/io.quarkus.quarkus-jdbc-h2-deployment-2.7.5.Final.jar
/opt/keycloak/lib/lib/main/io.quarkus.quarkus-jdbc-postgresql-2.7.5.Final.jar
/opt/keycloak/lib/lib/main/org.mariadb.jdbc.mariadb-java-client-2.7.5.jar
/opt/keycloak/lib/lib/main/io.quarkus.quarkus-jdbc-mssql-deployment-2.7.5.Final.jar
/opt/keycloak/lib/lib/main/io.quarkus.quarkus-jdbc-mysql-2.7.5.Final.jar
/opt/keycloak/lib/lib/main/io.quarkus.quarkus-jdbc-mariadb-2.7.5.Final.jar
/opt/keycloak/lib/lib/main/org.testcontainers.jdbc-1.16.3.jar
/opt/keycloak/lib/lib/main/io.quarkus.quarkus-jdbc-h2-2.7.5.Final.jar
/opt/keycloak/lib/lib/main/org.wildfly.security.wildfly-elytron-realm-jdbc-1.18.3.Final.jar
/opt/keycloak/lib/lib/main/io.quarkus.quarkus-jdbc-postgresql-deployment-2.7.5.Final.jar

Well, seems like there is two filenames with both jdbc and postgresql in lib/lib/main/, so the PostgreSQL drivers are clearly in place.

Setting up Keycloak server

The master realm should only be used by the admin to create other realms. https://www.keycloak.org/docs/latest/server_admin/

So we should look into how to create realms with Ansible (it might or might not be worth ansiblifying this step).

How to configure Apache with OIDC with Keycloak (like what I've with auth0)?

Protecting our first application (using Apache mod_auth_openidc)

I have created a new realm, and created its first user.

The mod_auth_openidc module functions as an OpenID Connect Relying Party (RP) and enables authentication against an OpenID Connect Provider [in our case Keycloak].

I think I have managed to put my first webservice behind a Keycloak client. All of the Apache vhost config was done in the luxor playbook.

Increasing session lifetime (testing)

The default settings are not bad, but I want to make it easier for my users to pick up where they left off without having to logout/login again.

default settings for my realm

I have increased SSO Session Idle sharply and SSO Session Max slightly: new settings for solarchemist realm

Restrict user authorisation on certain clients

For example, in a single realm we usually have multiple clients, and multiple users, but only certain users should be allowed access to all clients.

It does not appear that Keycloak allows this kind of configuration out of the box.

In the client settings, enable Authorization Enabled: authorisation enabled

This causes the Authorization menu item to become visible (it wasn't before). authorisation menu

Let's try setting a user-based policy.

create authorisation policy for type user

add user policy

At this point, the client can still be accessed by all users - it seems creating a user policy is not enough by itself.

create resource based permission

add resource permission

https://github.com/zmartzone/mod_auth_openidc/wiki/Keycloak#roles

No, this is not working. I have not been able to get the VSCode client to deny authorisation for any user, whether included in the list of authorised users or not (i.e., all users in the realm can still access the app). Either Keycloak 17 does not support this stuff out of the box, or (more likely) I have misconfigured Keycloak or else lack some OIDC field in the Apache vhost config.

No useful tips on the web, so I'm pausing this project here. To be resumed at some later point.

Known issues

username exists message in log

muscat kc.sh[3315]: ERROR [org.keycloak.services] (main) KC-SERVICES0010: Failed to add user 'admin' to realm 'master': user with username exists

Even though it says error, it does not seem to affect our ability to login or anything. I assume this is due to how the superadmin username/password is set and ignore this. Note that this error has been observed on both Keycloak v17 and v20.

Refs

Ansible roles

Ansible plugins