Keycloak : Federation d’un annuaire LDAPS (Active Directory)

modifié le : 15 septembre 2022,
par Julien Louis
 

Cet article a pour but de décrire la mise en place de la fédération d’un annuaire LDAPS (Active Directory) au sein d’un royaume Keycloak.

Testé avec un domaine Active Directory On-Premises et avec Azure Active Directory.

Contexte de l’infrastructure

L’infrastructure sur laquelle je vais m’appuyer est la suivante :

  • 1 contrôleur de domaine Active Directory (AD DS) avec sa PKI (AD CS) sous Windows Serveur 2019 Standard
    • Domaine : aukfood.lan
    • FQDN du contrôleur de domaine : dc01.aukfood.lan
  • 1 serveur Keycloak en version 19.0.1

Certificat TLS

Note : Les commandes de ce chapitre sont réalisées depuis le serveur hébergeant le conteneur keycloak.

Récupération du certificat

Pour commencer, il va falloir récupérer le certificat TLS utilisé pour la liaison LDAPS.

  • LDAP = Port 389 TCP
  • LDAPS = Port 636 TCP

Avec l’utilitaire openssl, il est possible de tester que la liaison LDAPS est fonctionelle ainsi que de récupérer différentes informations (dont le certificat du serveur) :

openssl s_client -connect dc01.aukfood.lan:636

Voici le retour pour cette infra :

depth=0 CN = dc01.aukfood.lan
---
Certificate chain
 0 s:CN = dc01.aukfood.lan
   i:DC = lan, DC = aukfood, CN = aukfood-DC01-CA
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIHLzCCBRegAwIBAgITTAAAAAczDQgCtUWEjAAAAAAABzANBgkqhkiG9w0BAQsF
[...]
AniSQdTOnACZrX//9tDg73RV9w==
-----END CERTIFICATE-----
subject=CN = dc01.aukfood.lan
issuer=DC = lan, DC = aukfood, CN = aukfood-DC01-CA

Copier le Server certificate commençant par -----BEGIN CERTIFICATE----- et se terminant par -----END CERTIFICATE----- dans un fichier server-ldaps.cer :

vi server-ldaps.cer

Création du keystore

Maintenant que le certificat TLS du contrôleur de domaine a été récupéré, il va falloir l’importer dans un keystore.

Tout d’abord, installer openjdk-11-jre :

sudo apt install openjdk-11-jre

Puis importer le certificat server-ldaps.cer dans un keystore nommé keystore.jks :

keytool -import -trustcacerts -alias dc01.aukfood.lan-CA -file server-ldaps.cer -keystore keystore.jks

Saisir un mot de passe à appliquer au keystore :

Entrez le mot de passe du fichier de clés :  
Ressaisissez le nouveau mot de passe : 

Vérifier la présence du certificat dans le keystore généré :

keytool -list -keystore keystore.jks

Après avoir entrer le mot de passe du keystore, le certificat est bien présent :

Entrez le mot de passe du fichier de clés :  
Type de fichier de clés : PKCS12
Fournisseur de fichier de clés : SUN

Votre fichier de clés d'accès contient 1 entrée

dc01.aukfood.lan-ca, 22 août 2022, trustedCertEntry, 
Empreinte du certificat (SHA-256) : 61:EA:83:97:92:[...]:B5:59:EE:2C:8A:2D:EA

Déclaration du keystore

Maintenant que le keystore a été généré avec le certificat TLS du contrôleur de domaine, il va falloir le déclarer au sein de Keycloakpour qu’il puisse être exploité.

Dans la stack keycloak (voir lien en début d’article), un volume conf est monté pour la persistance des données du répertoire /opt/keycloak/conf dans le conteneur.

Envoyer le keystore précédement généré dans le conteneur :

docker cp ./keystore.jks $(docker ps -qf name=keycloak):/opt/keycloak/conf/

Puis ajouter les variables suivantes sur la stack de keycloak :

services:
  app:
    [...]
    environment:
      [...]
      # Indiquer le mot de passe du keystore
      KC_SPI_TRUSTSTORE_FILE_FILE: /opt/keycloak/conf/keystore.jks
      KC_SPI_TRUSTSTORE_FILE_PASSWORD: MotDePasseTresSecure
      [...]

Le MotDePasseTresSecure est celui qui a été indiqué lors de la création du keystore.

Lister les stacks dans docker swarm :

docker stack ls

Identifier l’ID du service docker exécutant

NAME               SERVICES   ORCHESTRATOR
keycloak           1          Swarm
nextcloud          2          Swarm
portainer          2          Swarm
rocketchat         2          Swarm
swarmpit           4          Swarm
traefik            1          Swarm

La stack faisant tourner le keycloack en v19 est nommé keycloak dans ce cluster docker.

Supprimer la stack keycloak :

docker stack rm keycloak

Puis relancer la stack kycloak pour prendre en compte les nouvelles variables d’environnement concernant le truststore :

docker stack deploy -c ./keycloak/stack.yml keycloak

Le fichier stack.yml est stocké dans un répertoire nommé keycloak de mon répertoire courant. A adapter suivant son emplaccement dans le FHS.

Logs

Avant de passer à la configuration de la fédération de l’annuaire Active Directory via LDAPS à Keycloak, il est important de vérifier et de de s’assurer du bon redémarrage du conteneur.

Pour cela, lister les services en cours au sein du cluster docker :

docker service ls

Identifier le service adéquat (ici : keycloak_app) :

ID             NAME                    MODE         REPLICAS   IMAGE                                                PORTS
2degmsl8r3se   dashy                   replicated   0/0        lissy93/dashy:latest                                 
7jq3dje5b0t8   keycloak_app    replicated   1/1        quay.io/keycloak/keycloak:latest                     
ubq1dvhwv0st   nextcloud_app           replicated   1/1        nextcloud:latest                                     
arz4ca4gvfgv   nextcloud_mariadb       replicated   1/1        mariadb:latest                                       
vr2c7ptq6a8k   portainer_agent         global       5/5        portainer/agent:latest                               
h6h5merxg9a2   portainer_portainer     replicated   1/1        portainer/portainer-ce:latest                        
mzsq3uof6c1r   rocketchat_mongodb      replicated   1/1        bitnami/mongodb:4.4                                  
tmu3kz5n7xq9   rocketchat_rocketchat   replicated   1/1        registry.rocket.chat/rocketchat/rocket.chat:latest   
kos1zg1wowxi   swarmpit_agent          global       5/5        swarmpit/agent:latest                                
gtjs3mikbtaf   swarmpit_app            replicated   1/1        swarmpit/swarmpit:latest                             
nx6s2mt19bzx   swarmpit_db             replicated   1/1        couchdb:2.3.0                                        
n5oq9gx05bnd   swarmpit_influxdb       replicated   1/1        influxdb:1.7                                         
u7b8rsym5lzp   traefik_traefik         replicated   1/1        traefik:latest     

Vérifier la bonne exécution du service en gardant un shell ouvert avec la lecture des logs en temps réel :

docker service logs -f keycloak_app

Configuration de la fédération LDAPS

Note : A partir de maintenant, la configuration est à effectuer à travers la console web d’administration du service Keycloak.

User federation

Sélectionner le royaume adéquat ou en créer un nouveau (1), puis se rendre sur User federation (2) :

image-20220822202717217

Ajouter un fournisseur LDAP :

image-20220822202902853

Note : Pour les explications des différents champs, leurs fonctions, leurs utilités, etc… qui vont suivre, se référer à cet article que j’ai écris en 2021 sur l’intégration d’un annuaire LDAP (OpenLDAP, huhu) : https://slash-root.fr/keycloak-integration-ldap-externe/

Tous les paramètres de synchronisation y sont traités :

  • Gestion du stockage des utilisateurs
  • L’influence du mode Import Users sur les requêtes LDAP (LDAPS, même combat)
  • L’Edit Mode et ses différents paramètres
  • Les types de Vendor
  • Les différents champs Users DN ou Bind DN
  • Les configurations possibles pour la synchronisation ainsi que leurs périodicités

General options

  • (1) Console display name : Entrer un nom afin d’identifier cette fédération d’utilisateurs au sein de Keycloak.
  • (2) Vendor : Indiquer le type d’annuaire.

image-20220823052653616

Connection and authentication settings

(1) Connection URL : Renseigner l’URL de connexion à l’annuaire LDAPS sous la forme ldaps://FQDN_DC:636. Cette URL doit correspondre au "Common Name" du certificat. Celui-ci peut être identifié lors de l’utilisation de la commande openssl au début de cet article.

(2) Use Truststore SPI : Indiquer l’utilisation du truststore javax.net.ssl.trustStore (pour le keystore.jks) uniquement pour ldaps.

(3) Bind DN : Indiquer le DistinguishedName de l’utilisateur de l’annuaire qui sera utilisé par Keycloak. Pour le récupérer facilement :

Get-ADUser UTILISATEUR_AD | FT DistinguishedName

(4) Bind credentials : Mettre le mot de passe de l’utilisateur indiqué au point précédent.

image-20220823062809118

A noter que pour le moment, il manque des informations dans le paramétrage de la liaison LDAPS. De ce fait, le "Test connection" et le "Test authentication" ne sont pas encore réalisables (Une des différences avec les versions de Keycloak sous Wildfly en version 16 et inférieure).

LDAP searching and updating

(1) Edit mode : Définir le mode d’édition de l’annuaire.

(2) Users DN : Indiquer le DistinguishedName de l’OU contenant les utilisateurs à fédérer.

image-20220823112241929

Tests et import utilisateurs

Il est maintenant possible de tester la connexion LDAPS et l’authenfication.

Ces 2 tests doivent aboutir :

image-20220823113054627

Ensuite, en haut à droite de la page, bien s’assurer que cette fédération soit enabled. Puis dans action (1), déclencher la synchronisation (2) de tous les utilisateurs :

image-20220823113544319

L’importation des utilisateurs aboutie :

image-20220823113707564

Dans les utilisateurs du royaume Keycloak, je retrouve bien les utilisateurs contenus dans l’OU définit dans la fédération.

Mappers

Dans ce contexte, l’utilisateur "Julien LOUIS", se retrouve avec un username contenant des espaces. Cela est dû au faites que l’attribut cn de l’annuaire a été mappé vers l’attribut username de Keycloak.

image-20220823120151055

Pour voir tous les utilisateurs du royaume keycloak (fédération incluse), rechercher ***** comme utilisateur.

De plus, pour l’utilisateur final, cela ne correspondra pas au login auquel il est habitué d’utiliser.

Pour modifier ce comportement, il faut mapper l’attribut sAMAccountName de l’anuaire Active Directory vers l’attribut username de Keycloak.

Se rendre sur les paramétrages de la fédération précédement réalisée, puis dans l’onglet Mappers (1), éditer le mapper username (2) :

image-20220823114704603

Modifier le champ LDAP Attribute pour y inscrire sAMAccountName :

image-20220823115150552

Puis, enregistrer la modification en bas de page.

Ensuite, dans l’onglet Settings, modifier l’Username LDAP attribute en y inscrivant sAMAccountName :

image-20220823115607818

Puis, enregistrer la modification en bas de page.

En relançant la synchronisation de tous les utilisateurs de l\’annuaire vers Keycloak, les utilisateurs sont mis à jour :

image-20220823115739535

A présent, le login des utilisateurs importés dans Keycloak est correctement paramétré.