©camunda

23. August 2019 / von Gunnar von der Beck

Accso stellt

Camunda

Extension

bereit

Camunda Keycloak Identity Provider released

Camunda™ (https://camunda.com/) in der aktuellen Version ist perfekt für den Einsatz von BPM in Cloud-Infrastrukturen geeignet. Durch die gelungene Spring Boot Integration, Konzepte wie das External Task Pattern und andere Features hat man viel Freiheit, seine BPM-Architektur frei nach den eigenen Anforderungen und Wünschen zu gestalten. Fehlt etwas? Kaum.

Mit einer Ausnahme: Identity-Management in der Cloud unterscheidet sich oft von klassischen Ansätzen. Weder das integrierte Identity Management noch der optionale LDAP Identity Provider sind wirklich gut zum Einsatz in der Cloud geeignet. Deshalb haben wir nach einem Weg gesucht, das Identity-Management von Camunda besser in solche Umgebungen zu integrieren.

keycloak Logo
©Keycloak

Was ist Keycloak?

Keycloak™ ist eine Open Source Identity und Access Management Plattform mit erweiterten Features wie User Federation, Identity Brokering und Social Login.

Unter anderem werden unterstützt:

  • Single-Sign On
  • Standard Protokolle wie OpenID Connect, OAuth 2.0 und SAML 2.0
  • Connections zu LDAP und Active Directory Infrastrukturen
  • Social Login
  • Zentralisiertes Management für Administration, User, Gruppen, etc.

Keycloak integriert sich sehr gut in Cloud-Architekturen und wird immer häufiger zum Identity Management in solchen Umgebungen eingesetzt. Details können https://www.keycloak.org/ entnommen werden.

Warum dieser Plugin?

Camunda stellt bereits ein generisches Beispiel für Single Sign On bei der Verwendung von Spring Boot zur Verfügung. Siehe https://github.com/camunda-consulting/code/tree/master/snippets/springboot-security-sso Natürlich können diese Prinzipien auch auf Keycloak angewendet werden.

Aus meiner Sicht ist dies ein guter Ausgangspunkt, aber SSO ist eben nur die halbe Miete. Möchte man Camunda’s IdentityService APIs verwenden oder Benutzer und Gruppen tatsächlich auch im Cockpit verfügbar haben, dann kommt man einfach nicht weiter. Aber warum sollte ich den Camunda Identity Service nicht mehr nutzen, nur weil mein Projekt in die Cloud gewechselt ist? Warum sollte ich überhaupt wertvolle Zeit investieren, um darüber nachzudenken, was möglich ist und welche Einschränkungen gelten könnten? Als Architekt möchte ich mit Keycloak genauso interagieren, wie ich es früher mit LDAP getan habe und eben eine voll integrierte Lösung nutzen. Das würde das Leben deutlich einfacher machen. Genau deshalb haben wir einen Keycloak Identity Provider Plugin implementiert.

Der Keycloak Identity Provider Plugin ist eine Community-Extension und hier verfügbar: https://github.com/camunda/camunda-bpm-identity-keycloak

Features:

  • ReadOnlyIdentityProvider
  • Umfassende Unterstützung für Benutzer- und Gruppen-Queries
  • Kompatibel mit Spring Boot OAuth2 SSO

Basis Szenario: Centralized Managment Only

Fangen wir mit dem einfachst möglichen Integrations-Szenario an:

  • Verbinde Camunda’s Identity Service mit Keycloak
  • Noch kein SSO – es bleibt zunächst beim Login über die Camunda eigene Login-Page

Für dieses Szenario muss man eine Dependency hinzufügen …

<dependency>
    <groupId>org.camunda.bpm.extension</groupId>
    <artifactId>camunda-bpm-identity-keycloak</artifactId>
    <version>1.0.0</version>
</dependency>
centralized management only
Gunnar von der Beck

… den Keycloak Identity Provider Plugin aktivieren …

package <your-package>;
 
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.camunda.bpm.extension.keycloak.plugin.KeycloakIdentityProviderPlugin;
 
@Component
@ConfigurationProperties(prefix="plugin.identity.keycloak")
public class KeycloakIdentityProvider extends KeycloakIdentityProviderPlugin {
}

… und zuletzt den Plugin in der application.yaml konfigurieren:

plugin.identity.keycloak:
  keycloakIssuerUrl: https://<your-keycloak-server>/auth/realms/<realm-name>
  keycloakAdminUrl: https://<your-keycloak-server>/auth/admin/realms/<realm-name>
  clientId: camunda-identity-service
  clientSecret: 42aa42bb-1234-4242-a24a-42a2b420cde0
  useEmailAsCamundaUserId: true
  administratorGroupName: camunda-admin

Das war es auch schon. Mehr Details zur Konfiguration von Keycloak selber und den Optionen des Plugins können der Dokumentation des Projektes entnommen werden.

Erweitertes Szenario: Single Sign On

Kommen wir nun zu einem etwas komplexeren Szenario: wir fügen Single Sign On hinzu.

  • Camunda’s Identity Service verbindet sich weiter mit Keycloak
  • Wir verbannen Camunda’s eigene Login-Page und nutzen SSO inklusive der Möglichkeit für Social Login etc.

Für dieses Szenario nutzen wir einfach alles, was Spring Security und beispielsweise die OAuth2 Integration bieten. Empfehlenswerte Artikel finden sich unter anderem hier:

Gunnar von der Beck

Angenommen, wir haben als Dependencies spring-boot-starter-security und spring-security-oauth2-autoconfigure hinzugefügt, dann liegt die Hauptarbeit darin, einen KeycloakAuthenticationProvider ähnlich dem folgenden zur Verfügung zu stellen:

/**
 * OAuth2 Authentication Provider for usage with KeycloakIdentityProviderPlugin.
 */

public class KeycloakAuthenticationProvider
    extends ContainerBasedAuthenticationProvider {
 
    @Override
    public AuthenticationResult extractAuthenticatedUser(HttpServletRequest request,
                                                         ProcessEngine engine) {
 
        // Extract authentication details
        OAuth2Authentication authentication = (OAuth2Authentication)
            SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null) {
            return AuthenticationResult.unsuccessful();
        }
        Authentication userAuthentication = authentication.getUserAuthentication();
        if (userAuthentication == null || userAuthentication.getDetails() == null) {
            return AuthenticationResult.unsuccessful();
        }
 
        // Extract user ID from Keycloak authentication result
        // depending on plugin configuration
        String userId = ((HashMap<String, String>) userAuthentication.getDetails())
            .get("email");              // useEmailAsCamundaUserId = true
        //  .get("preferred_username"); // useUsernameAsCamundaUserId = true
        //  .get("sub");                // use internal ID
 
        // Authentication successful
        AuthenticationResult authenticationResult =
            new AuthenticationResult(userId, true);
        authenticationResult.setGroups(getUserGroups(userId, engine));
 
        return authenticationResult;
    }
 
    private List<String> getUserGroups(String userId, ProcessEngine engine){
        List<String> groupIds = new ArrayList<>();
        // query groups using KeycloakIdentityProvider plugin
        engine.getIdentityService().createGroupQuery().groupMember(userId).list()
            .forEach( g -> groupIds.add(g.getId()));
        return groupIds;
    }
 
}

Natürlich gibt es dafür unterschiedliche Ansätze. Das obige Beispiel ist nur eines davon. Wichtig ist, dass die Extraktion der userId mit der Konfiguration des Keycloak Identity Provider Plugins übereinstimmen muss (entweder E-Mail, Benutzername oder interne ID von Keycloak werden als Camunda User ID verwendet). Das ist alles.

Eine passende application.yaml sieht dann wie folgt aus:

security:
  oauth2:
    client:
      client-id: camunda-identity-service
      client-secret: 42aa42bb-1234-4242-a24a-42a2b420cde0
      accessTokenUri: https://<your-keycloak-server>/auth/realms/<realm-name>/protocol/openid-connect/token
      userAuthorizationUri: https://<your-keycloak-server>/auth/realms/<realm-name>/protocol/openid-connect/auth
      scope: openid profile email
    resource:
      userInfoUri: https://<your-keycloak-server>/auth/realms/<realm-name>/protocol/openid-connect/userinfo

Weitere Details zum übergreifenden SSO-Setup können dem examples-Verzeichnis des GitHub-Repository der Erweiterung entnommen werden. Es enthält einen voll integrierten SSO-Showcase – inklusive Setup für Kubernetes. Das Beispiel soll ein grundlegendes Verständnis vermittlen, um anschließend eine eigene Implementierung starten zu können. Siehe SSO-Kubernetes-Beispiel.

In den Camunda Consulting Snippets finden sich dann weitere Beispiele für SSO, auch unter Verwendung des keycloak-spring-boot-starter Package.

Wie man leicht sehen kann, steht eine breite Auswahl an Möglichkeiten zur Verfügung. Die man ganz an die eigenen Bedürfnisse anpassen kann. Womit wir bei einem wichtigen Prinzip wären: Eine BPM-Lösung sollte sich in die Infrastruktur des Kunden integrieren. Nicht umgekehrt. Der Camunda Keycloak Identity Provider Plugin trägt genau dazu bei.

 
 

Autor

Weitere Artikel

Das könnte Sie auch interessieren