Migration Keycloak Quarkus et Certificats TLS LDAP

Sommaire

J'utilise Keycloak depuis quelques temps sur un cluster kubernetes, installé via Helm, avec une version "legacy" basé sur wildfly. Celle-ci étant dépréciée depuis "un moment", il a bien fallu mettre à jour.

Cependant, j'ai eu quelques soucis avec la gestion des certificats TLS lorsque keycloak doit fédérer des utilisateurs depuis un annuaire LDAP. Il y a pas mal de documentation sur le net, mais rien de bien clair.

Nous allons voir ci-après comment résoudre le problème, avec une configuration qui je pense est "propre". Bon OK, pour le troll, Java, Truststore et propre je ne suis pas sûr que ça aille ensemble ^^.

Gestion Certificat TLS mode Wildfly

Lorsque keycloak wildfly était déployé (via chart helm codecentric), la procédure était "simple" :

  1. Création d'une ConfigMap contenant tous les certificats des annuaires LDAP
 1# Fichier keycloak-outgoing-ca-configmap.yaml 
 2apiVersion: v1
 3kind: ConfigMap
 4metadata:
 5  name: keycloak-outgoing-ca
 6  namespace: keycloak
 7data:
 8
 9  # Certificat raccourci pour l'exemple
10  ldap-server-1.crt: |-
11    -----BEGIN CERTIFICATE-----
12    MIIFHDCCBASgAwIBAgISA97LrVW9BV88dCiH/SxYOguZMA0GCSqGSIb3DQEBCwUA
13    MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
14    EwJSMzAeFw0yMzA4MzEwNjE4MjdaFw0yMzExMjkwNjE4MjZaMBYxFDASBgNVBAMT
15    pKA0HK66WLqZC6dSqaEHvyM87L0BMgw0Y1sC12O6fHqcmTdtHMcbfzb98Row6ubX
16    Hgy6H75N33qgbC0ZqoYHsbZyJgs04enfix0FMd3qITJuwYeISve3zkFtKTAbZfos
17    qfAo6lbCsHF9/sv540yZ7A==
18    -----END CERTIFICATE-----    
  1. Référence de cette ConfigMap lors du déploiement du chart Helm, via l'utilisation de "custom values" :
1# Paramètres défini dans un fichier custom-values.yaml
2extraVolumes: |
3  - name: keycloak-outgoing-ca
4    configMap:
5      name: keycloak-outgoing-ca  
6
7extraVolumeMounts: |
8  - name: keycloak-outgoing-ca
9    mountPath: /tmp/certs  
  1. Déploiement du chart :
1$ helm repo add codecentric https://codecentric.github.io/helm-charts
2$ helm repo update
3$ helm upgrade --install keycloak codecentric/keycloak -f custom-values.yaml

Gestion Certificat TLS mode Quarkus

Malheureusement, cette méthode ne fonctionne pas avec les déploiements actuels de Keycloak avec Quarkus, en utilisant le chart Bitnami ! Voir ici pour plus d'information.

Je ne comprends pas grand-chose dans les truststores and co., mais on me parle de "Truststore SPI" qui n'est pas paramétrable, qu'il faut passer par la surcharge de JAVA_OPTS etc. Pourtant, dans le chart Helm de Bitnami il y a bien une référence à du SPI, on doit en tirer quelque chose !

Configuration du chart

Après quelques essais, voici une configuration qui fonctionne, et qui me semble pas trop mal :

  1. Génération d'un truststore, contenant l'ensemble des certificats TLS des serveurs LDAP que je souhaite joindre. Un mot de passe devra être créé pour sécuriser l'accès au truststore. Pour éviter tout problème, j'utilise la même image de conteneur que ce qui tournera sur mon cluster (ici 19.0.3) :
 1$ docker run -it --rm -v ./:/tmp docker.io/bitnami/keycloak:19.0.3 bash
 2keycloak@25d1c6186533:/$ cd /tmp
 3keycloak@25d1c6186533:/tmp$ openssl x509 -text -noout -in ldap-server-1.crt 
 4keycloak@25d1c6186533:/tmp$ keytool -import -alias ldap.192.168.1.1.nip.io -keystore truststore.jks -file ldap-server-1.crt
 5keycloak@25d1c6186533:/tmp$ openssl x509 -text -noout -in ldap-server-2.crt
 6keycloak@25d1c6186533:/tmp$ keytool -import -alias ldap.192.168.1.2.nip.io -keystore truststore.jks -file ldap-server-2.crt
 7keycloak@25d1c6186533:/tmp$ keytool -list -keystore truststore.jks
 8Enter keystore password:
 9Keystore type: PKCS12
10Keystore provider: SUN
11
12Your keystore contains 2 entries
13
14ldap.192.168.1.1.nip.io, Oct 4, 2023, trustedCertEntry, 
15Certificate fingerprint (SHA-256): 13:F3:F8:65:90:C6:8A:EC:F7:86:B9:E7:82:E4:4B:09:C0:E8:B0:E4:A4:AD:1C:76:7F:B6:CE:56:1B:55:51:8F
16ldap.192.168.1.2.nip.io, Oct 4, 2023, trustedCertEntry, 
17Certificate fingerprint (SHA-256): A2:B2:01:9D:7B:87:FD:04:7F:F2:98:AF:28:80:B6:CE:9B:8F:73:88:9A:5A:DE:6D:82:D3:33:18:85:BA:66:25
  1. Génération d'un secret contenant ce truststore. Le contenu du secret devra être dans keycloak-spi.truststore.jks :
1$ kubectl create secret generic keycloak-spi-store --from-file=keycloak-spi.truststore.jks=truststore.jks
  1. Il est possible également de créer ce secret directement en les définissant dans les values du chart Helm (optionnel) :
 1[...]
 2extraDeploy:
 3  ### Creates truststore used for validating certs for outgoing connexions (LDAPs)
 4  - |
 5    apiVersion: v1
 6    kind: Secret
 7    metadata:
 8      name: {{ .Values.spi.existingSecret }}
 9    data:
10      keycloak-spi.truststore.jks: <BASE_64_FILE>    
11[...]
  1. Reste à paramétrer le chart Helm pour utiliser ce truststore. On nous parle de variables d'environnement KEYCLOAK_SPI_TRUSTSTORE_FILE, KEYCLOAK_SPI_TRUSTSTORE_PASSWORD ou encore KEYCLOAK_SPI_TRUSTSTORE_FILE_HOSTNAME_VERIFICATION_POLICY, celles-ci seront définies via les paramètres du chart (le contenu des values est disponible ici) :
 1# Extract du fichier custom-values.yaml
 2[...]
 3## SPI TLS settings
 4spi:
 5  existingSecret: "keycloak-spi-store" # Nom du secret contenant le truststore
 6  truststorePassword: "changeme" # Mot de passe du truststore pour l'exemple, en production on utilisera un secret, à définir dans passwordsSecret
 7  truststoreFilename: "keycloak-spi.truststore.jks"
 8  passwordsSecret: "" # Voir commentaires pour truststorePassword
 9  hostnameVerificationPolicy: ""STRICT" # On vérifie le nom du serveur portant le certificat
10[...]
  1. On déploie le tout !
1$ helm repo add bitnami https://charts.bitnami.com/bitnami
2$ helm repo update
3$ helm upgrade --install keycloak bitnami/keycloak --namespace keycloak --values custom-values.yaml

Vérification

Maintenant, il ne reste plus qu'à vérifier sur Keycloak que la connexion est OK.

Configuration Keycloak LDAP TLS

Allons dans la partie "User federation" du royaume qui utilise le lien vers mes serveurs LDAP, testons la connexion... Bingo !

Liaison Keycloak LDAP OK