The Keycloak App in the App Center saves its database access credentials in the LDAP database of UCS. This data is replicated to the Primary Directory Node and all Backup Directory Nodes. This is needed so that multiple installations of Keycloak can share the same database. Until Keycloak 26.3.5-ucs1 the App needlessly replicated these credentials to Replica Directory Nodes as well, although Keycloak cannot be installed there. This can lead to a privilege escalation where the root user of such a Replica can now get access to the database when they should not.
We changed that in said version, future updates of the credentials will only be replicated to Primary and Backup Directory Nodes. But if you have a Replica Directory Node in your domain you may find the credentials still in the local LDAP database of that node. Or in one of the various, automatically created backups of that database. If you want to get rid of that attack vector, we advice to change the password of the database user and save that new password in LDAP so that Keycloak can still access the database while on the Replica Directory Node, you will not find it anymore and in the backups, the password will be outdated.
Before we show how to change the password, please note that during this process, the connection between any Keycloak and the database may break. You would see a lot of the following errors until you are done reconfiguring the Keycloak App(s).
2026-01-09 13:14:52,762 ERROR [org.jgroups.protocols.JDBC_PING] (jgroups-581,1048adfe5cc5-22932) JGRP000220: Failed to store PingData in database
2026-01-09 13:14:53,789 ERROR [org.jgroups.protocols.JDBC_PING] (jgroups-581,1048adfe5cc5-22932) JGRP000115: Could not open connection to database: org.postgresql.util.PSQLException: FATAL: Passwort-Authentifizierung für Benutzer »keycloak« fehlgeschlagen
at org.postgresql.core.v3.ConnectionFactoryImpl.doAuthentication(ConnectionFactoryImpl.java:777)
at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:234)
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:289)
...
Here is how you would do it, assuming you are root on the Primary and are using the Postgres database that comes with UCS (that is the default for our Keycloak app):
# verify that you are on the correct host, how many installation you have
# and so on, this is what we saved:
udm settings/data list --filter cn=keycloak | sed -e '/data:/!d' -e 's/ data: //g' | base64 -d | bunzip2 ; echo
# set password for postgresql - we assume we are on a UCS where that postgres runs
password=$(makepasswd --chars=32)
su postgres -c "psql -c \"ALTER USER keycloak PASSWORD '$password';\""
# attention: from now on your Keycloak installations may fail
# until you followed until the end
# set password in UDM for all keycloak installations to access it
# assuming you are on a primary
univention-install jq
new_content=$(udm settings/data list --filter cn=keycloak | sed -e '/data:/!d' -e 's/ data: //g' | base64 -d | bunzip2 | jq ".password = \"$password\"")
new_content_b64=$(echo "$new_content" | bzip2 | base64)
udm settings/data modify --dn "cn=keycloak,cn=data,cn=univention,$(ucr get ldap/base)" --set data="$new_content_b64"
# on all UCS that run Keycloak, now do:
univention-app configure keycloak
# you should verify that Keycloak works on each host, e.g., by
univention-app logs keycloak