Nouvel article dans la série sur Alfresco et le SSO, nous allons parler aujourd’hui de Kerberos. Derrière ce terme un peu barbare se cache en réalité un principe d’authentification relativement simple. En deux mots, Kerberos est un protocole d’authentification réseau développé au MIT pendant les années 80-90, son principe de fonctionnement repose sur l’utilisation de tickets signés par des clés secrètes (chiffrement symétrique).
# Principe de fonctionnement de Kerberos
Je ne vais pas détailler dans son intégralité le fonctionnement du protocole Kerberos, ce n’est pas le but de cet article. Je vais juste essayer de poser quelques bases afin de comprendre son intégration dans Alfresco.
Kerberos fait intervenir 3 entités :
- un KDC (Key Distribution Center) : entité dite « de confiance » permettant de générer les clés secrètes (par exemple : Active Directory)
- un client : un utilisateur souhaitant accéder à une application sur le réseau
- une application : dans le cas de cet article, il s’agit d’Alfresco
Le premier échange se fait entre le client et le KDC pour obtenir un TGT (Ticket Granting Ticket).
- étape 1 – le client demande un TGT au KDC : « Hello, je suis l’utilisateur Laurent et j’ai besoin d’un TGT »
- étape 2 – réponse du KDC contenant le TGT : « Voici le TGT demandé, tu peux l’utiliser si tu arrives à le déchiffrer avec ton mot de passe »
Dans le cas de l’utilisation de Kerberos dans un environnement Microsoft (postes Windows reliés à un domaine Active Directory), cet échange se fait au moment de l’ouverture de la session et est transparente pour l’utilisateur.
À ce stade, l’utilisateur a en sa possession un TGT. Ce TGT lui permet d’obtenir un ST (Service Ticket) auprès du KDC. Ce ST est utilisé ensuite pour accéder à une application.
- étape 3 – le client demande un ST au KDC : « Re, voici mon TGT, donne moi un ST pour accéder à App »
- étape 4 – réponse du KDC contenant le ST : « Voici le ST demandé, tu peux l’envoyer à App »
- étape 5 – le client envoie le ST à App : « Hello, voici mon ST, tu peux l’utiliser pour m’authentifier »
- étape 6 – réponse de App au client : « Ok, j’ai pu déchiffrer le ST et tu es bien authentifié »
Lors de l’étape 3, le client demande un Service Ticket lié à l’application à laquelle l’utilisateur souhaite accéder. Dans sa demande, le client doit préciser le « Principal » du service demandé. Ce « Principal » est un terme précis dans le vocabulaire Kerberos. Dans le cas de l’utilisation de Kerberos pour accéder à un service HTTP (comme c’est le cas pour Alfresco), le « Principal » est de la forme suivante : HTTP/<app-dns-entry.exemple.org>@<REALM>
Il faut remplacer :
<app-dns-entry.exemple.org>
par le nom de domaine associé au service HTTP<REALM>
par le nom du Realm Kerberos
Par exemple : HTTP/ged.atolcd.com@AD.ATOLCD.COM
L’étape 4 peut sembler magique. Comment fait l’application pour valider le ST et authentifier l’utilisateur ? Le ticket ST est chiffré avec la clé secrète du compte lié à l’application. Ce ST contient, entre autre, le login de l’utilisateur. Il faut donc une information au niveau de l’application pour déchiffrer le ST et obtenir ainsi le login de l’utilisateur. Et c’est maintenant qu’entre en jeu le fameux fichier keytab. Le keytab est un fichier contenant les clés permettant de déchiffrer le ticket ST. Une fois le ST déchiffré à l’aide du keytab, l’application vérifie le contenu du ST et en extrait le login de l’utilisateur. Et voilà !
Vous remarquerez que le fichier keytab joue un rôle majeur et qu’il contient des informations sensibles. Il est important de protéger ce fichier au maximum et de ne pas le rendre accessible à tout le monde.
Voilà, c’est une rapide présentation du protocole Kerberos. J’ai pris plein de raccourcis, mais cela permet de poser quelques bases et d’expliquer un peu la magie qui gravite autour de Kerberos.
# Et concrètement, ça donne quoi ?
Pour illustrer cet article, je vais prendre l’exemple de la mise en place d’un Alfresco dans un contexte Microsoft : utilisation de Active Directory avec des postes Windows connectés au domaine. Cet exemple correspond à 100% des cas que nous avons pu rencontrés lors de nos installation d’Alfresco avec authentification Kerberos (et ça devrait donc parler à la plupart des lecteurs).
Le contexte lié notre exemple :
- Active Directory
- domaine :
ad.atolcd.com
- realm Kerberos associé :
AD.ATOLCD.COM
(le même, mais en majuscule)
- domaine :
- Alfresco
- installé sur un serveur Linux
- URL d’accès :
https://ged.atolcd.com
Les étapes suivantes sont nécessaires à la mise en place de Kerberos :
- côté Active Directory :
- création du compte de service associé à Alfresco
- génération du fichier keytab associé à ce compte de service
- côté serveur Alfresco :
- configuration Kerberos au niveau système
- configuration Kerberos au niveau Java
- configuration Kerberos au niveau Alfresco
- configuration Kerberos au niveau Share
# Actions côté Active Directory
Tous les détails sont indiquées dans la documentation Alfresco. Il n’y a rien de plus à ajouter. Ah si ! Une seule chose : n’oubliez pas l’étape 1.m ! Je ne sais pas pourquoi, mais cette étape passe souvent à la trappe, et on en a besoin pour Share.
Pour reprendre notre exemple, cela donne les actions suivantes :
- création d’un compte utilisateur
- on le nommera
svc_ged
(peu importe le nom, utilisez votre convention de nommage, il faut juste bien penser à le reprendre dans les commandes suivantes) - bien reprendre les indications données dans la doc Alfresco : le mot de passe n’expire pas, cocher l’option « Do not require Kerberos preauthentication » dans l’onglet « Account Options« .
- on le nommera
- utilisation de la commande
ktpass
pour créer le fichier keytab (pour rappel, ce fichier keytab permettra de déchiffrer le ticket ST envoyé par le client) :
1 |
ktpass -princ HTTP/ged.atolcd.com@AD.ATOLCD.COM -pass <le mot de passe du compte svc_ged> -mapuser svc_ged -crypto all -ptype KRB5_NT_PRINCIPAL -kvno 0 -out ged.atolcd.com.keybab |
- si besoin, on associe d’autres « Principals » à notre compte
svc_ged
(cette étape est nécessaire uniquement si les utilisateurs accèdent à Alfresco sur un autre hostname que ged.atolcd.com, par exemplehttps://ged/
) :
1 |
setspn -a HTTP/ged svc_ged |
- et on n’oublie pas la fameuse étape 1.m de la procédure Alfresco : cocher « Trust this user for delegation to any service (Kerberos only) » dans l’onglet « Delegation«
Et voilà, on est bon côté Active Directory. Il ne reste plus qu’à copier le fichier ged.atolcd.com.keybab
sur le serveur Alfresco.
# Actions côté Alfresco
# Configuration système
Au niveau du système, un seul fichier à configurer pour Kerberos, il s’agit du fichier /etc/krb5.conf
. Il sera unique à chaque installation, mais vous pouvez utiliser l’exemple suivant comme base :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
[logging] default = FILE:/var/log/krb5libs.log kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmind.log [libdefaults] default_realm = AD.ATOLCD.COM dns_lookup_realm = false dns_lookup_kdc = false ticket_lifetime = 24h renew_lifetime = 7d forwardable = true default_tkt_enctypes = rc4-hmac default_tgs_enctypes = rc4-hmac [realms] AD.ATOLCD.COM = { kdc = ad.atolcd.com admin_server = ad.atolcd.com } [domain_realm] .ad.atolcd.com = AD.ATOLCD.COM ad.atolcd.com = AD.ATOLCD.COM |
# Configuration Java
Premièrement, il faut créer le fichier login.conf
avec un contenu ressemblant à ceci :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
Alfresco { com.sun.security.auth.module.Krb5LoginModule sufficient; }; AlfrescoHTTP { com.sun.security.auth.module.Krb5LoginModule required storeKey=true useKeyTab=true doNotPrompt=true keyTab="/chemin/vers/ged.atolcd.com.keybab" principal="HTTP/ged.atolcd.com@AD.ATOLCD.COM"; }; ShareHTTP { com.sun.security.auth.module.Krb5LoginModule required storeKey=true useKeyTab=true doNotPrompt=true keyTab="/chemin/vers/ged.atolcd.com.keybab" principal="HTTP/ged.atolcd.com@AD.ATOLCD.COM"; }; com.sun.net.ssl.client { com.sun.security.auth.module.Krb5LoginModule sufficient; }; other { com.sun.security.auth.module.Krb5LoginModule sufficient; }; |
Il faudra bien sûr adapter le chemin ver le fichier keytab.
Et ensuite, il faut passer des paramètres Java supplémentaires à Tomcat :
1 2 |
-Dsun.security.krb5.msinterop.kstring=true -Djava.security.auth.login.config=<chemin_vers>/login.conf |
# Configuration Alfresco
Côté Alfresco, tout va se passer dans le fichier alfresco-global.properties
. Il faut mettre à jour le paramètre authentication.chain
pour ajouter une authentification du type kerberos et ensuite indiquer le realm Kerberos à utiliser.
1 2 3 |
authentication.chain=kerberos1:kerberos,alfrescoNtlm1:alfrescoNtlm kerberos.authentication.realm=AD.ATOLCD.COM |
Alfresco utilisera l’entrée AlfrescoHTTP
présent dans le fichier login.conf
pour identifier le fichier keytab à utiliser.
# Configuration Share
La configuration Kerberos de Share se fait dans le fichier share-config-custom.xml
. Vers la ligne 316 de ce fichier, vous trouverez un bloc XML pour la configuration Kerberos. Il faut modifier ce bloc XML pour qu’il ressemble à ceci :
1 2 3 4 5 6 7 8 9 |
<config evaluator="string-compare" condition="Kerberos" replace="true"> <kerberos> <password>secret</password> <realm>AD.ATOLCD.COM</realm> <endpoint-spn>HTTP/ged.atolcd.com@AD.ATOLCD.COM</endpoint-spn> <config-entry>ShareHTTP</config-entry> <stripUserNameSuffix>true</stripUserNameSuffix> </kerberos> </config> |
Il n’est pas nécessaire de modifier les balises <password>
, <config-entry>
et <stripUserNameSuffix>
. Uniquement les balises <realm>
et <endpoint-spn>
doivent être modifiées.
Toujours dans ce même fichier, à la ligne 432, vous trouverez un autre bloc XML :
1 2 3 |
<config evaluator="string-compare" condition="Remote"> [...] </config> |
Il suffit simplement de dé-commenter la totalité de ce bloc XML.
# Dernière étape
Et pour finir, il ne reste plus qu’à redémarrer Tomcat pour prendre en compte la nouvelle configuration. Si tout s’est bien passé, vous devriez avoir accès à Alfresco Share depuis votre navigateur sans avoir besoin de saisir votre login ni votre mot de passe.
Ça c’est la théorie. Dans le monde réel, ça se passe souvent moins bien que prévu. Et quand ça fonctionne du premier coup, je fais une croix dans le calendrier et je paie ma tournée aux collègues pour fêter ça.
# À l’aide, ça ne fonctionne pas !
Dans un premier temps, j’ai envie de dire « Normal, c’est le genre de chose qui ne fonctionne jamais du premier coup ». Et dans un second temps, mon petit doigt me fait signe dans l’oreillette qu’il y a une deadline pour la mise en prod et qu’il faut trouver ce qui coince. Du coup, pour vous aider, je vous ai listé les problèmes les plus couramment rencontrés (le tout agrémenté de quelques pistes de réflexion).
# Les fichiers de logs
Ça devrait être un réflexe pour tout le monde au moindre problème rencontré. Est-ce qu’il y a des erreurs dans les fichiers de logs Alfresco et/ou Share. Si oui, ces erreurs vous donnerons une première piste pour résoudre le problème.
# Valider la configuration Kerberos au niveau système
La configuration Kerberos est en place au niveau système sur votre serveur Alfresco (le fichier /etc/krb5.conf
), on va tester ça tout de suite.
En ligne de commande, directement depuis le serveur Alfresco :
1 2 3 4 5 6 7 8 9 10 11 |
# liste les tickets Kerberos en cours (ne devrait rien lister) klist # obtention d'un ticket TGT (remplacer <username> par votre identifiant personnel Active Directory) kinit <username> # si c'est ok, klist devrait vous afficher votre ticket klist # et on fait du ménage kdestroy |
# Valider le fichier keytab
Le test prend moins de 30s, pourquoi s’en priver ?
En ligne de commande, directement depuis le serveur Alfresco :
1 2 3 4 5 6 7 8 9 10 11 |
# liste les tickets Kerberos en cours (ne devrait rien lister) klist # obtention d'un ticket Kerberos à l'aide du keytab (et sans mot de passe, si vous avez bien suivi) kinit HTTP/ged.atolcd.com@AD.ATOLCD.COM -k -t /chemin/vers/ged.atolcd.com.keybab # si c'est ok, klist devrait vous afficher votre ticket klist # et on fait du ménage kdestroy |
# Configuration du poste client
C’est de là que tout commence, si le poste client n’est pas correctement configuré, point de salut. Il faut vérifier que le navigateur accepte de faire du Kerberos avec le service demandé.
Pour Internet Explorer, l’URL d’accès à Alfresco doit se trouver dans la zone de sécurité « Local Intranet ». Chrome reprenant la configuration d’Internet Explorer, si celui-ci fonctionne, Chrome devrait en faire autant.
Pour Firefox, tout se passe dans « about:config », les paramètre network.negotiate-auth.delegation-uris
et network.negotiate-auth.trusted-uris
doivent être modifiés pour englober l’URL d’accès à Alfresco.
Si l’accès se fait en HTTPS (ce que je ne peux que vous conseiller), il faut également vérifier que le certificat HTTPS est reconnu comme valide par les navigateurs.
Dernier point, ces trois navigateurs refuseront de faire du Kerberos dans les fenêtres en navigation privée. N’utilisez pas cette méthode pour tester Kerberos, ça ne pourra pas fonctionner.
# Il faut être à l’heure
Quasiment toutes, si ce n’est toutes, les informations échangées par le protocole Kerberos contiennent un timestamp avec une date d’expiration. Autant pour le TGT, la durée de validité est généralement de plusieurs heures. Autant pour le ST, cette durée de validité est de l’ordre de quelques minutes (deux minutes dans la configuration Active Directory par défaut. Si une des trois entités (client, KDC ou application) a une horloge locale avec un écart de plus de 2 minutes, l’authentification Kerberos échouera.
C’est un argument supplémentaire pour la mise en place du protocole NTP sur toute votre infrastructure.
# Ce n’est pas la taille qui compte
Bah, en fait si, elle compte ! Le ticket ST envoyé par le navigateur vers Alfresco contient des informations sur l’utilisateur à l’origine de la demande. La taille de ce ticket peut donc varier d’un utilisateur à l’autre (par exemple, en fonction du nombre de groupes auxquels appartient l’utilisateur). Or, ce ticket transite via l’entête HTTP Authorization
, et, dans certains cas, la taille de ce ticket peut dépasser une certaine limite ce qui entraîne le rejet de la requête HTTP.
Cette limite dépend du serveur utilisé et n’est pas spécifiée dans la norme HTTP. Elle est généralement de 8 Ko (en tout cas pour Apache HTTPD et Tomcat). Il faut faire le tour de toute la chaîne entre le navigateur et Alfresco, et vérifier si un des éléments traversés ne serait pas à l’origine d’un blocage : proxy, reverse-proxy, waf, etc.
# Java Cryptography Extension (JCE)
C’était vrai avec les vielles versions de Oracle JDK, mais ce n’est plus le cas avec OpenJDK. Il était nécessaire d’installer manuellement le jar « Java Cryptography Extension (JCE) » car la distribution de Java fournie par Oracle ne contenait pas toutes les bibliothèques nécessaires au déchiffrement des tickets Kerberos.
- Pour Oracle JDK 7 : https://www.oracle.com/java/technologies/javase-jce7-downloads.html
- Et pour Oracle JDK 8 : https://www.oracle.com/java/technologies/javase-jce8-downloads.html
# Enregistrement DNS (A ou CNAME ?)
Là, c’est un peu plus subtile. Lors de la création de l’enregistrement DNS pour votre Alfresco, vous avez le choix entre deux types d’enregistrement :
- type A : vous associez directement un nom avec une adresse IP
- type CNAME : vous associez le nom à un alias (alias qui pourrait également être un CNAME ou de type A)
Il est important de faire la distinction entre les deux, car le « Principal » indiqué par le navigateur au KDC pour obtenir le ST (étape 3 du schéma tout en haut) dépend de ce choix.
Cas d’un enregistrement de type A, le nom ged.atolcd.com
est directement associé à l’adresse IP du serveur Alfresco (par exemple 203.0.113.42). Le « Principal » sera : HTTP/ged.atolcd.com@AD.ATOLCD.COM
.
Par contre, dans le cas d’un enregistrement de type CNAME, le nom ged.atolcd.com
est associé à un alias. Généralement, il s’agit le nom du serveur qui, lui-même, est un enregistrement de type A associé à l’adresse IP du serveur Alfresco (par exemple : ged.atolcd.com → srv-alfresco-62.priv.atolcd.com → 203.0.113.42). Dans ce cas, le « Principal » sera : HTTP/srv-alfresco-62.priv.atolcd.com@AD.ATOLCD.COM
.
Plus de détails : http://web.mit.edu/kerberos/www/krb5-latest/doc/admin/princ_dns.html
# Tester avec curl
Si ça ne fonctionne toujours pas, rien de mieux pour tester qu’un outil en ligne de commande en mode verbose. Avec curl, vous devriez récupérer une erreur exploitable et avoir une piste pour résoudre le problème.
En ligne de commande, directement depuis le serveur Alfresco :
1 2 3 4 5 |
# obtention d'un ticket TGT (remplacer <username> par votre identifiant personnel Active Directory) kinit <username> # appel curl avec authentification Kerberos curl -v --negotiate -u : --delegation always https://ged.atolcd.com/share/page/ |
# Le mot de la fin
Cet article met en oeuvre Kerberos en utilisant le sous-système d’authentification intégré directement dans Alfresco. Le contenu de cet article reste cependant valide si vous souhaitez intégrer Kerberos à une autre application. Alors n’hésitez pas à vous en servir comme base. C’est notamment le cas si vous utilisez le principe décrit dans le précédent article External authentication avec un module d’authentification Kerberos.
D’ailleurs, dans les versions 6.2 d’Alfresco, l’authentification Kerberos intégré dans Alfresco semble un peu cassé (voir MNT-21363 et MNT-21511). Une des solutions envisageables est justement passer par le module d’authentification mod_auth_gssapi le temps que l’éditeur sorte un correctif.
Prochain article, le mois prochain. Nous aborderons le module d’authentification SAML d’Alfresco. En attendant, je me sauve en congés pendant une semaine pour profiter du dé-confinement !
Laisser un commentaire