Skip to content

Commit

Permalink
Merge pull request #386 from it-at-m/248-zusammenspiel-von-keycloakv2…
Browse files Browse the repository at this point in the history
…4-und-keycloakmigration-broken-bei-erneutem-start-der-migration

Hebung von Keycloak auf V25 und Dokumentation der Migration
  • Loading branch information
Nic12345678 authored Aug 7, 2024
2 parents 9bf12f3 + 5e2cd7c commit 88f2b24
Show file tree
Hide file tree
Showing 12 changed files with 1,726 additions and 15 deletions.
4 changes: 4 additions & 0 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ export default withMermaid({
text: 'Shared/Separated Datenmodell',
link: `${PATH_TECHNIK}adr/adr002-controller-service-datamodels`
},
{
text: 'Vollständige Migration nach Keycloak',
link: `${PATH_TECHNIK}adr/adr-always-full-keycloak-migration`
}
]
}
],
Expand Down
Binary file added docs/src/public/keycloak/createRealmTrigger.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/src/public/keycloak/deleteRealmAction.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
56 changes: 56 additions & 0 deletions docs/src/technik/adr/adr-always-full-keycloak-migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Immer vollständiger Migration nach Keycloak

## Status

<adr-status status='accepted'></adr-status>

## Kontext

Initiator für eine genauere Betrachtung von Keycloak und Keycloakmigration war die von renovate vorgeschlagene Hebung
von Version 20 auf 24. Diese wurde zuerst auch durchgeführt (siehe [PR - 241](https://github.com/it-at-m/Wahllokalsystem/pull/241)),
musste aber aufgrund von Inkompatibilitäten mit unseren Migrationsskripten wieder durch
[PR - 231](https://github.com/it-at-m/Wahllokalsystem/pull/231) zurückgenommen werden.
Zum Zeitpunkt der Rücknahme war nicht bekannt wie man mit den Userattributen, `wahlbezirk_art`, die wir einfügen wollten,
umgehen konnte. In diesem Zusammenhang viel auch auf, dass im Unterschied zur Version 20, mit der Version keine
Deltamigration mehr möglich war.

Es entstand das [Issue - 248](https://github.com/it-at-m/Wahllokalsystem/issues/248). Es wurde keine Lösung gefunden wie
über Keycloak-Migration die Userattribute pflegbar waren. Daher wurde das Issue geschlossen.

Später viel auf, dass die Version 20 von Keycloak und Keycloakmigration es nicht ermöglichte, die
Gruppenzuordnung einer Rolle zu entfernen ([Issue - 361](https://github.com/it-at-m/Wahllokalsystem/issues/361)).

Daher wurde das [Thema](https://github.com/it-at-m/Wahllokalsystem/issues/248) erneut eröffnet.

Die Beschreibung für den [Import](https://www.keycloak.org/server/containers#_importing_a_realm_on_startup) eines Realms
beim Start haben wir später gefunden. Die Option `Unmanaged Attributes` in den Realmsettings, ermöglichte es Userattribute
zu verwenden.

## Entscheidung

Wir verwenden Keycloak in Version 25 und Migrationen nach Keycloak werden immer vollständig durchgeführt.
Es muss keine Delta-Migration geben.

Dadurch das Keycloak zeitnah durch unseren Authservice abgelößt wird, überwog der *KISS*-Aspekt. Anstelle einer
umfangreichen Featurelist konzentrieren wir uns auf wenige notwendige Arten von API-Calls durch Keycloakmigration.

Unterstützt wird die Entscheidung gegen die Option einer Delta-Migration von unserem
Nutzungsverhalten. Wir wechseln häufig zwischen verschiedenen Feature-Branches. Die jeweiligen Branches haben
Migrationsfiles die der andere Branch nicht hat. Daher führen wir meist eine vollständige Migration durch.

## Konsequenzen

### positiv

Es ist kein Zusatzwissen oder zusätzlichen Tätigkeiten beim Erstellen des JSON-Files für den Import erforderlich. Wenn
man eine Deltamigration ermöglichen will, muss man manuell zu den exportieren Daten aus Keycloak Rollen und Benutzer hinzufügen.

Wir benötigen nur einen kleinen Teil der Funktionen von keycloakmigration. Aufgrund der Erfahrungen mit nicht
funktionierenden Features ist somit das Risiko geringer, dass wir in einen Fehler laufen.

Mit der Fokussierung auf eine vollständige Migration ist es möglich die Keycloak-Files überschaubarer anzuordnen.

### negativ

Es muss immer eine vollständige Migration erfolgen. Eine Teilmigration ist nicht möglich.

47 changes: 47 additions & 0 deletions docs/src/technik/development/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,53 @@ flowchart LR
| wls_all_bwb | test | Ein Benutzer mit allen Rechten mit der WahlbezirksArt BWB (Briefwahl) |
| wls_all_uwb | test | Ein Benutzer mit allen Rechten mit der WahlbezirksArt UWB (Urnenwahl) |

### Migration

Alle Konfigurationselemente, wie zum Beispiel User, Rollen und Client, werden automatisiert erstellt. Der Realm wird
beim Start von Keycloak importiert. Alle weiteren Elemente werden durch den `init-keycloak`-Container erstellt.

Im Rahmen der Migration werden immer alle Elemente erstellt. Daher ist notwendig, dass zuvor alte Elemente gelöscht wurden.
Somit ergeben sich folgende Schritte bei der Migration:

- alten Realm löschen
- Realm anlegen
- Migrieren von Client, Rolles und Usern

#### Löschen des alten Realm

Über die Weboberfläche kann der Realm gelöscht werden. Dazu ist der Realm `wls_realm` auszuwählen. Unter dem Menüpunkt
`Realm settings` kann über die Action (Drop-Down im oberen rechter Bereich) `Delete` der Realm gelöscht werden.

![Image with delete realm action](/keycloak/deleteRealmAction.png)
*Löschen des Realms über die Actions in den Realm Settings*

#### Realm anlegen

Um den Client, die Rollen und die User im nächsten Schritt anlegen zu können muss der Realm wieder angelegt werden.
Dies erfolgt über den Import der Realmsettings. Dazu gibt es zwei Varianten

**Variante 1 - Neustarten des Containers**

Beim Starten des Containers wird der Realm importiert.

**Variante 2 - Realm über Weboberfläche anlegen**

Über die Weboberfläche kann ein neuer Realm angelegt werden. In der darauffolgenden Ansicht wird über `browse` das
Konfigurationsfile ausgewählt und abschließend nach dem Klick auf `Create` wird der Realm angelegt.

Die Datei `import-wls-realm.json` liegt im Pfad `stack/keycloak/import` des Projektes.

![Image with create realm button](/keycloak/createRealmTrigger.png)
*Button zum Anlegen eines neues Realm im Dropdown der Realms*

#### Ausführen von `wls-init-keycloak`

Die abschließende Migration des Clients, der User, Gruppen und Rollen erfolgt durch den Container `wls-init-keycloak`.
Dazu den Container starten. Nach Abschluss der Migration beendet sich der Container.

![Image log of a wls init keycloak container run](/keycloak/exampleOfKeycloakmigrationRun.png)
*Auszug aus dem Log einer erfolgreich durchgeführten Migration*

### Beispiel-Requests

Im Soap-UI-Projekt (`DockerTest-soapui-project`) und `docker.keycloak.http` sind Beispielrequests vorhanden.
Expand Down
4 changes: 3 additions & 1 deletion stack/.env
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#
# Keycloak
#
SSO_BASE_URL=http://wls-keycloak:8080/auth
SSO_REALM=wls_realm
SSO_CLIENT_ID=wls
SSO_CLIENT_SECRET=top-secret
KEYCLOAK_RELATIV_PATH=auth
KEYCLOAK_ADMIN=admin
KEYCLOAK_ADMIN_PASSWORD=change_me
KEYCLOAK_HOSTNAME_STRICT=false
Expand All @@ -13,6 +13,8 @@ KEYCLOAK_DB=keycloak
KEYCLOAK_DB_USER=keycloak-user
KEYCLOAK_DB_PASSWORD=keycloak-secret

KEYCLOAK_MIGRATION_KEYCLOAK_URL=http://wls-keycloak:8080/${KEYCLOAK_RELATIV_PATH}

WLS_BROADCAST_SERVICE_PROFILE=local,db-oracle
WLS_BROADCAST_SERVICE_DB_URL=jdbc:oracle:thin:@//wls-db-oracle:1521/XEPDB1
WLS_BROADCAST_SERVICE_KEYCLOAK_URL=http://kubernetes.docker.internal:8100/auth/realms/${SSO_REALM}/protocol/openid-connect
Expand Down
10 changes: 7 additions & 3 deletions stack/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,10 @@ services:
## Keycloak
wls-keycloak:
container_name: wls-keycloak
image: quay.io/keycloak/keycloak:20.0.5
image: quay.io/keycloak/keycloak:25.0.2
command:
- start-dev --http-relative-path /auth
- start-dev
- '--import-realm'
depends_on:
- wls-db-postgres-keycloak
environment:
Expand All @@ -113,6 +114,9 @@ services:
- KC_DB_URL=jdbc:postgresql://wls-db-postgres-keycloak:5432/${KEYCLOAK_DB}
- KC_DB_USERNAME=${KEYCLOAK_DB_USER}
- KC_DB_PASSWORD=${KEYCLOAK_DB_PASSWORD}
- KC_HTTP_RELATIVE_PATH=${KEYCLOAK_RELATIV_PATH}
volumes:
- './keycloak/import:/opt/keycloak/data/import'
ports:
- 8100:8080
networks:
Expand All @@ -128,7 +132,7 @@ services:
environment:
- ADMIN_USER=${KEYCLOAK_ADMIN}
- ADMIN_PASSWORD=${KEYCLOAK_ADMIN_PASSWORD}
- BASEURL=${SSO_BASE_URL} # uses internal docker network to access the keycloak via its back channel port
- BASEURL=${KEYCLOAK_MIGRATION_KEYCLOAK_URL} # uses internal docker network to access the keycloak via its back channel port
- WAIT_FOR_KEYCLOAK=true
- KEYCLOAK_CHANGELOG=/migration/keycloak-changelog.yml
volumes:
Expand Down
32 changes: 31 additions & 1 deletion stack/http_requests/docker.keycloak.http
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
### get token for keycloak_test
### get token for keycloak_test
POST http://localhost:8100/auth/realms/wls_realm/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded

Expand Down Expand Up @@ -28,6 +28,36 @@ username = wls_all
client.global.set("token_type", response.body.token_type);
%}

### get token for wls_all_uwb
POST http://localhost:8100/auth/realms/wls_realm/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded

password = test &
grant_type = password &
client_secret = top-secret &
client_id = wls &
username = wls_all_uwb

> {%
client.global.set("auth_token", response.body.access_token);
client.global.set("token_type", response.body.token_type);
%}

### get token for wls_all_bwb
POST http://localhost:8100/auth/realms/wls_realm/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded

password = test &
grant_type = password &
client_secret = top-secret &
client_id = wls &
username = wls_all_bwb

> {%
client.global.set("auth_token", response.body.access_token);
client.global.set("token_type", response.body.token_type);
%}

### get userinfo with auth_token
GET http://localhost:8100/auth/realms/wls_realm/protocol/openid-connect/userinfo
Authorization: {{ token_type }} {{ auth_token }}
Loading

0 comments on commit 88f2b24

Please sign in to comment.