Search code examples
javadockerjbosskeycloakfederated-identity

Keycloak with custom user federation docker deployment


I'm trying to deploy Keycloak with custom user federation provider on docker. I want to use external database as an additional source of user authentication. I've tested configuration on my host (whole project extracted from .tar.gz) and it's working - I can search users from external db in admin panel or log into keycloak.

The problem is, when I run my container I get following error:

12:36:36,127 ERROR [org.jboss.as.controller.management-operation] (Controller Boot Thread) WFLYCTL0013: Operation ("deploy") failed - address: ([("deployment" => "custom-user-storage-jpa.jar")]) - failure description: {
"WFLYCTL0412: Required services that are not installed:" => ["jboss.naming.context.java.jboss.datasources.ExternalPostgresDS"],
"WFLYCTL0180: Services with missing/unavailable dependencies" => [
    "jboss.persistenceunit.\"custom-user-storage-jpa.jar#custom-user-storage-jpa\" is missing [jboss.naming.context.java.jboss.datasources.ExternalPostgresDS]",
    "jboss.persistenceunit.\"custom-user-storage-jpa.jar#custom-user-storage-jpa\".__FIRST_PHASE__ is missing [jboss.naming.context.java.jboss.datasources.ExternalPostgresDS]"
]

so I assume my jar do not see datasource configured in standalone.xml with (with name ExternalPostgresDS)

There is persistance.xml in my custom-user-storage provider, later built in jar by maven clean install

    <?xml version="1.0" encoding="UTF-8" ?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="
        http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="custom-user-storage-jpa">
        <jta-data-source>java:jboss/datasources/ExternalPostgresDS</jta-data-source>
        <properties>
            <property name="hibernate.hbm2ddl.auto" value="none" />
            <property name="hibernate.show_sql" value="false" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL95Dialect" />
        </properties>
    </persistence-unit>
</persistence>

There is also section in standalone.xml defining that datasource and driver

                <xa-datasource jndi-name="java:jboss/datasources/ExternalPostgresDS" pool-name="ExternalPostgresDS" enabled="true" use-java-context="true" statistics-enabled="${wildfly.datasources.statistics-enabled:${wildfly.statistics-enabled:false}}">
                    <xa-datasource-property name="ServerName">
                        address...
                    </xa-datasource-property>
                    <xa-datasource-property name="PortNumber">
                        5432
                    </xa-datasource-property>
                    <xa-datasource-property name="DatabaseName">
                        dbname...
                    </xa-datasource-property>
                    <xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
                    <driver>postgresql</driver>
                    <security>
                        <user-name>username...</user-name>
                        <password>password...</password>
                    </security>
                    <validation>
                        <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker"/>
                        <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter"/>
                    </validation>
                </xa-datasource>
                <drivers>
                    <driver name="postgresql" module="org.postgresql">
                        <xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
                    </driver>
                    <driver name="h2" module="com.h2database.h2">
                        <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
                    </driver>
                </drivers>

And finally there is a Dockerfile which should customize official keycloak image to my needs:

FROM jboss/keycloak:11.0.2

ENV DB_VENDOR postgres
ENV DB_ADDR addr..
ENV DB_DATABASE dbname...
ENV DB_USER user...
ENV DB_PASSWORD password...
ENV PROXY_ADDRESS_FORWARDING true
ENV KEYCLOAK_USER admin
ENV KEYCLOAK_PASSWORD password

COPY ./_resources/standalone.xml /opt/jboss/keycloak/standalone/configuration/standalone.xml
COPY ./_resources/custom-user-storage-jpa.jar /opt/jboss/keycloak/standalone/deployments/custom-user-storage-jpa.jar
COPY ./_resources/postgresql/main/module.xml /opt/jboss/keycloak/modules/system/layers/keycloak/org/postgresql/main/module.xml
COPY ./_resources/postgresql/main/postgresql-42.2.18.jar /opt/jboss/keycloak/modules/system/layers/keycloak/org/postgresql/main/postgresql-42.2.18.jar

ENV JAVA_OPTS -server -Xms2048m -Xmx6144m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m

EXPOSE 8080

Of course I checked that copied files are correct and on their place inside running container, after startup everything works fine but without my custom-user-storage deployment.

What am I missing?


Solution

  • It seems like your standalone.xml file was not read and jboss tries to use a default configuration instead.

    There is a mention of updating the default filename to standalone-ha.xml here https://lists.jboss.org/pipermail/keycloak-dev/2018-October/011304.html.

    updating the image building command to

    COPY ./_resources/standalone.xml /opt/jboss/keycloak/standalone/configuration/standalone-ha.xml
    

    should help