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
- Déployé dans docker swarm avec ce stack : https://slash-root.fr/docker-swarm-stack-keycloak-v19-latest/
- URL : keycloak.example.com
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
:
cat <<EOF > server-ldaps.cer
-----BEGIN CERTIFICATE-----
MIIHLzCCBRegAwIBAgITTAAAAAczDQgCtUWEjAAAAAAABzANBgkqhkiG9w0BAQsF
[...]
AniSQdTOnACZrX//9tDg73RV9w==
-----END CERTIFICATE-----
EOF
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) :
Ajouter un fournisseur LDAP :
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
ouBind 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.
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.
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.
Tests et import utilisateurs
Il est maintenant possible de tester la connexion LDAPS et l'authenfication.
Ces 2 tests doivent aboutir :
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 :
L'importation des utilisateurs aboutie :
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.
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) :
Modifier le champ LDAP Attribute pour y inscrire sAMAccountName :
Puis, enregistrer la modification en bas de page.
Ensuite, dans l'onglet Settings, modifier l'Username LDAP attribute en y inscrivant sAMAccountName :
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 :
A présent, le login des utilisateurs importés dans Keycloak est correctement paramétré.