Migration Keycloak Quarkus et Certificats TLS LDAP
Comment gérer les certificats TLS LDAP avec Keycloak, Quarkus Edition

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" :
- Création d'une
ConfigMapcontenant tous les certificats des annuaires LDAP
# Fichier keycloak-outgoing-ca-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: keycloak-outgoing-ca
namespace: keycloak
data:
# Certificat raccourci pour l'exemple
ldap-server-1.crt: |-
-----BEGIN CERTIFICATE-----
MIIFHDCCBASgAwIBAgISA97LrVW9BV88dCiH/SxYOguZMA0GCSqGSIb3DQEBCwUA
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
EwJSMzAeFw0yMzA4MzEwNjE4MjdaFw0yMzExMjkwNjE4MjZaMBYxFDASBgNVBAMT
pKA0HK66WLqZC6dSqaEHvyM87L0BMgw0Y1sC12O6fHqcmTdtHMcbfzb98Row6ubX
Hgy6H75N33qgbC0ZqoYHsbZyJgs04enfix0FMd3qITJuwYeISve3zkFtKTAbZfos
qfAo6lbCsHF9/sv540yZ7A==
-----END CERTIFICATE------ Référence de cette
ConfigMaplors du déploiement du chart Helm, via l'utilisation de "custom values" :
# Paramètres défini dans un fichier custom-values.yaml
extraVolumes: |
- name: keycloak-outgoing-ca
configMap:
name: keycloak-outgoing-ca
extraVolumeMounts: |
- name: keycloak-outgoing-ca
mountPath: /tmp/certs- Déploiement du chart :
$ helm repo add codecentric https://codecentric.github.io/helm-charts
$ helm repo update
$ helm upgrade --install keycloak codecentric/keycloak -f custom-values.yamlGestion 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 :
- 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) :
$ docker run -it --rm -v ./:/tmp docker.io/bitnami/keycloak:19.0.3 bash
keycloak@25d1c6186533:/$ cd /tmp
keycloak@25d1c6186533:/tmp$ openssl x509 -text -noout -in ldap-server-1.crt
keycloak@25d1c6186533:/tmp$ keytool -import -alias ldap.192.168.1.1.nip.io -keystore truststore.jks -file ldap-server-1.crt
keycloak@25d1c6186533:/tmp$ openssl x509 -text -noout -in ldap-server-2.crt
keycloak@25d1c6186533:/tmp$ keytool -import -alias ldap.192.168.1.2.nip.io -keystore truststore.jks -file ldap-server-2.crt
keycloak@25d1c6186533:/tmp$ keytool -list -keystore truststore.jks
Enter keystore password:
Keystore type: PKCS12
Keystore provider: SUN
Your keystore contains 2 entries
ldap.192.168.1.1.nip.io, Oct 4, 2023, trustedCertEntry,
Certificate 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
ldap.192.168.1.2.nip.io, Oct 4, 2023, trustedCertEntry,
Certificate 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- Génération d'un secret contenant ce truststore. Le contenu du secret devra être dans
keycloak-spi.truststore.jks:
$ kubectl create secret generic keycloak-spi-store --from-file=keycloak-spi.truststore.jks=truststore.jks- Il est possible également de créer ce secret directement en les définissant dans les values du chart Helm (optionnel) :
[...]
extraDeploy:
### Creates truststore used for validating certs for outgoing connexions (LDAPs)
- |
apiVersion: v1
kind: Secret
metadata:
name: {{ .Values.spi.existingSecret }}
data:
keycloak-spi.truststore.jks: <BASE_64_FILE>
[...]- Reste à paramétrer le chart Helm pour utiliser ce truststore. On nous parle de variables d'environnement
KEYCLOAK_SPI_TRUSTSTORE_FILE,KEYCLOAK_SPI_TRUSTSTORE_PASSWORDou encoreKEYCLOAK_SPI_TRUSTSTORE_FILE_HOSTNAME_VERIFICATION_POLICY, celles-ci seront définies via les paramètres du chart (le contenu des values est disponible ici) :
# Extract du fichier custom-values.yaml
[...]
## SPI TLS settings
spi:
existingSecret: "keycloak-spi-store" # Nom du secret contenant le truststore
truststorePassword: "changeme" # Mot de passe du truststore pour l'exemple, en production on utilisera un secret, à définir dans passwordsSecret
truststoreFilename: "keycloak-spi.truststore.jks"
passwordsSecret: "" # Voir commentaires pour truststorePassword
hostnameVerificationPolicy: ""STRICT" # On vérifie le nom du serveur portant le certificat
[...]- On déploie le tout !
$ helm repo add bitnami https://charts.bitnami.com/bitnami
$ helm repo update
$ helm upgrade --install keycloak bitnami/keycloak --namespace keycloak --values custom-values.yamlVérification
Maintenant, il ne reste plus qu'à vérifier sur Keycloak que la connexion est OK.

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