1. Einleitung

Im vergangenen Artikel zu dem Thema (Docker: WildFly Server mit Keycloak) habe ich gezeigt, wie ihr ein Docker Image des WildFly Servers inklusive Keycloak Adapter erzeugen könnt. Wenn allerdings keine Keycloak Instanz parallel läuft, bringt dieser WildFly Container keinen Mehrwert. Ich zeige euch deshalb in diesem Artikel folgendes:

  • Wie ihr einen WildFly und Keycloak Container zusammen hochfahrt.
  • Wie ihr dabei ein zuvor exportiertes Realm in Keycloak importiert.
  • Und abschließend wie ihr die Funktionalität anhand einer Beispielanwendung überprüfen könnt.

2. Docker Compose

Wir nutzen Docker Compose, um beide Container (WildFly mit Keycloak Adapater sowie Keycloak) gemeinsam zu starten und alle relevanten Parameter strukturiert angeben zu können. Dies lässt sich auch per docker run bewerkstelligen, ich persönlich finde es aber schöner hier mit einem Klick in der IDE (IntelliJ) gleich beide benötigten Container zu erzeugen und hochzufahren. In beiden Fällen bekommen wir beim Testen auf localhost allerdings Schwierigkeiten bei der Kommunikation vom WildFly hin zu Keycloak. Darauf gehe ich später ein.

Es bietet sich an die Sourcen aus GitHub zu clonen, um die folgenden Erläuterungen besser nachvollziehen zu können. Die Sourcen findest du hier auf GitHub: https://github.com/MatthiasPischka/dockering/tree/main/compositions/wildfly-mit-keycloak

Zentrale Anlaufstelle ist die Datei docker-compose.yml:

version: '3.8'

services:
  keycloak:
    image: jboss/keycloak:14.0.0
    ports:
      - "8180:8080"
    environment:
      KEYCLOAK_USER: admin
      KEYCLOAK_PASSWORD: admin1234
      KEYCLOAK_IMPORT: /tmp/Testrealm.json
    volumes:
      - ./tmp:/tmp

  wildfly:
    image: matthiaspischka/wildfly-keycloak:24.0.0-14.0.0
    ports:
      - "8080:8080"
      - "9990:9990"
    volumes:
      - ./deployments:/opt/jboss/wildfly/standalone/deployments

2.1 Keycloak Service

Das ist unser Keycloak Server, mit dem der WildFly Server später kommunizieren wird.

  • image: Unangepasstes Image von JBoss.
  • ports: Wir können den Standard-Port 8080 nicht verwenden, da dieser mit dem des WildFlys kollidiert. Deshalb nutzen wir 8180 nach außen hin.
  • environment:
    • KEYCLOAK_USER & KEYCLOAK_PASSWORD: Hierdurch legen wir einen Benutzer zur Administration von Keycloak an.
    • KEYCLOAK_IMPORT: Wir lesen ein zuvor exportiertes Realm (dazu später mehr) ein. Dadurch können wir uns auf das lokale Testen der jeweiligen Anwendung konzentrieren.
  • volumes: Das tmp Verzeichnis wird außerhalb abgelegt, um das exportiere Realm von außen in den Container setzen zu können

2.2 WildFly Service

  • image: WildFly Server inklusive Keycloak Adapter (siehe: Docker: WildFly Server mit Keycloak)
  • ports: Standard für Anwendungen (8080) und Administration (9990)
  • volumes: Hier wird das Deployment-Verzeichnis für Hot Deployments außerhalb des Containers abgelegt, sodass der WildFly auf einfachem Weg mit der Beispielanwendung versorgt werden kann

2.3 Erzeugen und Starten

Entweder klassisch par Konsole:

docker-compose -f docker-compose.yml up -d

Oder zum Beispiel als simple Run Configuration in IntelliJ IDEA:

IntelliJ Run Configuration Docker Compose
IntelliJ: Run Configuration für Docker Compose

In beiden Fällen sollten folgende Services aufrufbar sein:

3. Testrealm (Keycloak)

Das Realm wurde über die Keycloak Administrationsoberfläche angelegt und anschließend exportiert, damit es nicht jedes Mal zum Testen in einem frischen Keycloak Container konfiguriert werden muss.

Im Wesentlichen umfasst das Realm folgendes:

  • clients
    • testclient mit der Client-Rolle intern und http://localhost:8080/* als valid redirect Uri.
  • users
    • testuser mit Passwort test12
    • testintern mit Passwort test12 und zugewiesener Rolle intern

3.1 keycloak.json

Über die Keycloak Verwaltung kann im Bereich Installation (auf Client-Ebene) die Keyloak OIDC JSON exportiert werden. Diese benötigen wir für alle Anwendungen, die über Keycloak abgesichert werden sollen und die auf dem WildFly mit dem Keycloak Adapter installiert werden sollen.

Bei den zuvor gezeigten Einstellungen sieht der Export wie folgt aus:

{
  "realm": "Testrealm",
  "auth-server-url": "http://localhost:8180/auth/",
  "ssl-required": "external",
  "resource": "testclient",
  "public-client": true,
  "verify-token-audience": true,
  "use-resource-role-mappings": true,
  "confidential-port": 0
}

Entscheidend ist hier der Parameter auth-server-url, den wir für lokale Tests mit den gezeigten Docker Containern anpassen müssen. Darauf gehe ich gleich gesondert ein.

4. Beispielanwendung

Der Quellcode der im Docker Container installierten Anwendung (jsf2.3-keycloak) ist hier auf GitHub zu finden: https://github.com/MatthiasPischka/java-ee-8-beispiele/tree/master/jsf2.3-keycloak

Es handelt sich dabei um eine simple JSF 2.3 Anwendung mit zwei Seiten. Eine Seite befindet sich im öffentlichen Bereich, die zweite Seite ist per Navigation erreichbar und ist per Keycloak abgesichert. Die Anwendung kann über http://localhost:8080/jsf2.3-keycloak/ geöffnet werden, sofern die gezeigte Docker Composition korrekt hochgefahren ist. Wenn wir jetzt auf den dargestellten Link (zum internen Bereich) klicken, leitet uns der Browser zur Loginmaske von Keycloak um:

Keycloak Loginmaske Testrealm
Keycloak: Loginmakse zur Anmeldung am Testrealm

Die Beispielanwendung ist so konfiguriert, dass sich ein Benutzer aus dem Testrealm anmelden muss, dem auch die Rolle intern zugewiesen ist (das klappt hier mit dem Benutzer testintern). Erst nach erfolgreicher Anmeldung gelangt der Benutzer zum internen Bereich der Beispielanwendung.

Wie die Anwendung genau zu konfigurieren ist, wird in einem separaten Beitrag beschrieben.

4.1 auth-server-url

Wie bereits erwähnt, können wir beim Testen auf dem localhost mit Docker Container nicht die von Keycloak vorgegebene URL (http://localhost:8180/auth/) verwenden. Warum ist das so?

  1. Für die Umleitung zur Loginmaske von Keycloak innerhalb des Browsers wird die genannte URL aus der Konfiguration entnommen und entsprechend ergänzt. Dieser Schritt funktioniert auch noch, wenn der Keycloak Server wie gezeigt im Docker Container läuft. Wir haben von unserem localhost Zugriff auf alle freigegebenen Ports der Docker Container.
  2. Problematisch wird es allerdings für den WildFly Server, auf dem die Beispielanwendung installiert ist. Dieser läuft ebenfalls innerhalb eines Docker Containers. Der WildFly Server versucht intern auch über den Keycloak Adapter mit dem Keycloak Server zu kommunizieren. Dazu verwendet der Adapter die selbe Konfiguration und somit den selben Wert für die auth-server-url (http://localhost:8180/auth/). Localhost verweist innerhalb des Containers aber auf das lokale Netzwerk. Der Aufruf kommt also nicht aus dem Container heraus, um über das Host-System auf den Keycloak Container zuzugreifen. Unter Windows kann man einen Trick verwenden. Ändert man die auth-server-url auf den Wert http://gateway.docker.internal:8180/auth/ so wird das Docker Host System, auf dem die Container laufen, angesprochen. Das funktioniert in beiden Fällen:
    1. Der Browser kann gateway.docker.internal auflösen, indem die Anfragen an den localhost gerichtet werden
    2. Der WildFly kommt mit seinen Adapter Anfragen aus dem Container heraus uns setzt sie indirekt an das Host System über Port 8180 (Keycloak Container) ab.

Nähere Informationen zum genannten Problem auf dem localhost lassen sich hier finden: https://docs.docker.com/desktop/windows/networking/


0 Kommentare

Schreibe einen Kommentar

Avatar-Platzhalter

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert