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" :
- 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-----
- 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
- 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 :
- 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
- 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
- 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[...]
- 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 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) :
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[...]
- 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.
Allons dans la partie "User federation" du royaume qui utilise le lien vers mes serveurs LDAP, testons la connexion... Bingo !