Plone et LDAP : mode d'emploi
Par Jean-Sébastien Mansart - 2 commentaires
Depuis la version 2.5, Plone intègre un module d'authentification extensible grâce à des plugins : PAS (PluggableAuthService). Celà permet de s'identifier à un site Plone depuis (potentiellement) n'importe quelle source : MySQL, openID, LDAP, etc...
Je vais ici expliquer comment connecter un site Plone à une base LDAP afin de pouvoir s'identifier sur le site, modifier son mot de passe depuis l'interface Plone, ajouter des utilisateurs depuis Plone et sauvegarder des données utilisateurs dans le LDAP.
Je part du principe que vous avez des connaissances en LDAP, que vous savez ce qu'est un DN (Distinguished Name), comment créer un arbre dans le LDAP, etc...
LDAP c'est quoi ?
D'après wikipédia:
Lightweight Directory Access Protocol (LDAP) est un protocole permettant l'interrogation et la modification des services d'annuaire. Ce protocole repose sur TCP/IP. Un annuaire LDAP respecte généralement le modèle X.500 édicté par l'UIT-T : c'est une structure arborescente dont chacun des nœuds est constitué d'attributs associés à leurs valeurs.
Un LDAP est donc une base de données spécialisée pour le stockage d'information concernant des personnes et des groupes de personnes.
Ce qu'il vous faut
Pour connecter votre LDAP à votre site Plone, il vous faut :
- Un serveur LDAP (OpenLDAP, Active Directory, OpenDirectory, Lotus...)
- Un serveur Zope
- Un site Plone de version 2.5.x
- Le produit LDAPMultiPlugins
- Le produit LDAPUserFolder
- Le module python python-ldap
Le LDAPUserFolder qui se trouve sur le site de Plone.org n'est pas à jour, il date du 30 novembre 2005. Faites bien attention d'utiliser celui fournit par dataflake.org.
Copiez les deux produits LDAPMultiPlugins et LDAPUserFolder dans le dossier Products de votre instance, installez le module python-ldap, et démarrez votre serveur Zope.
Configuration du Multi Plugin
Allez dans la ZMI (Zope Management Interface), ajoutez un site Plone et allez dans l'acl_users de votre site. Dans le menu déroulant, sélectionnez LDAP Multi Plugins et cliquez sur le bouton Add. Un formulaire vous demande plusieurs information à propos de votre LDAP :
- ID : pour identifier l'objet LDAP Multi Plugin qu'on est en train d'ajouter. (généralement, je le nomme LDAP)
- Title : un titre (LDAP Serveur)
- LDAP Server : là où se trouve votre serveur LDAP (localhost par exemple)
- Login Name Attribute : l'attribut qui servira d'identifiant pour se connecter au site (laissez la valeur par défaut pour le moment)
- User ID Attribute : l'attribut qui servira d'id pour les utilisateurs (laissez la valeur par défaut pour le moment)
- RDN Attribute : l'attribut pour le Relative Distinguished Name (laissez la valeur par défaut pour le moment)
- Users Base DN : où sont stockés vos utilisateurs dans le LDAP
- Group storage : vous pouvez choisir de stocker les groupes soit sur le LDAP, soit dans Plone directement
- Groups Base DN : si vous choisissez de stocker les groupes sur le LDAP, indiquez dans quelle branche ils se trouvent
- Manager DN : indiquez où se trouve l'admin LDAP (ou=admin,dc=mon,dc=ldap,dc=com par exemple) et saisissez sont mot de passe par la même occasion
- User password encryption : le type d'encryption pour les mots de passe
- Default User Roles : le rôle par défaut des utilisateurs logué (Anonymous par défaut, on peut leur donner le rôle Member par exemple)

Une fois les champs saisis, validez le formulaire. On se retrouve dans l'acl_users, cliquez sur votre LDAP Multi Plugins que vous venez d'ajouter.
On va maintenant faire le lien entre les attributs LDAP et les attributs de vos utilisateurs dans Plone.
Autentification
Cochez au passage les options "Authentication" et "Properties" et validez, puis cliquez directement sur le lien "Authentication". Dans le cadre de droite, faite remonter LDAP tout en haut. Faites la même chose pour "Properties". Ca permet de dire ce qu'on veut faire avec le LDAP. Là on lui indique que l'on veut pouvoir s'identifier et qu'on veut récupérer les propriétés (attributs) des utilisateurs stockés dans le LDAP.


Dans l'onglet "contents", cliquez sur acl_users (LDAP Serveur). Vous vous retrouvez à la configuration que vous aviez saisi juste auparavant. Allez dans l'onglet LDAP Schema. C'est à partir de là que l'on va "mapper" les attributs LDAP avec les champs Plone.

Par exemple : l'attribut LDAP "mail" va être mappé sur le champ "email", le "cn" sera mappé sur "fullname" etc...
On peut même mapper la photo jpeg...
Par contre, pas besoin de mapper le mot de passe.
Ajoutez en priorité l'attribut qui vous servira pour le login, et notifiez le dans le champs "Friendly Name",
Revenez dans l'onglet "configure", et spécifiez maintenant:
- Login Name Attribute
- User ID Attribute
- RDN Attribute
Pour ces trois champs indiquez lui l'attribut que vous avez choisi pour le login.
Une fois fait, allez dans l'onglet "users" et essayez de trouver un utilisateur pour tester que votre configuration fonctionne.
Vous pouvez ensuite tenter de vous connecter sur votre site Plone avec un utilisateur contenu dans votre LDAP.
La première partie est finie, c'était la partie facile. Pour la suite, il va falloir mettre les mains dans le cambouis.
Pour aller plus loin
Maintenant qu'on peut se connecter sur un site Plone avec des utilisateurs stockés dans un LDAP, on va s'amuser un peu à triturer tout ça.
Vous voulez pouvoir changer votre mot de passe depuis Plone ?
Vous avez spécifié des attributs dans le LDAP et vous voudriez non seulement les voir dans votre profil, mais en plus vous voulez pouvoir modifier ces valeurs ?
Vous voulez ajouter des utilisateurs depuis Plone ?
Pas de soucis, c'est là que ça commence à devenir intéressant.
De base, le Multi Plugin ne prend pas en charge la modification du mot de passe, ni l'ajout d'utilisateur. Il faut donc patcher pour lui donner de nouvelles fonctionnalités :
# On se place dans le dossier Products :
cd mon_instance/Products
# On récupère le patch :
wget http://antiloop.plone.org/LDAPMultiPlugins-plone.org.patch
# On va dans le dossier du produit :
cd LDAPMultiPlugins
# On applique le patch :
patch -p0 < ../LDAPMultiPlugins-plone.org.patch
Et après on regarde un peu ce qui a été fait. On corrige un peu les erreurs qui se sont glissées : les déclarations de sécurité ne sont pas bonnes dans le fichier LDAPMultiPlugin.py pour les méthodes doChangeUser, doDeleteUser, etc... (je sais pas si ça joue un grand rôle, mais bon...)
On redémarre le serveur zope, et on remarque que l'on a de nouvelles possibilité dans notre LDAP Multi Plugin. Cochez "User_Management" et faites monter "LDAP" en haut de la liste comme tout à l'heure.
Changement du mot de passe :
Depuis le site Plone, allez dans vos préférences, et allez sur le formulaire pour changer votre mot de passe. Testez, et normalement, ça ne marche pas.
Normal, dans la classe MembershipTool (Products.CMFPlone.MembershipTool) la méthode _findUsersAclHome n'arrive pas à trouver l'acl_users à utiliser.
Il faut donc faire un MonkeyPatch :
from Products.CMFPlone.MembershipTool import MembershipTool
from Products.CMFCore.utils import getToolByName
def _findUsersAclHome(self, userid):
portal = getToolByName(self, 'portal_url').getPortalObject()
acl_users=portal.acl_users
parent = acl_users.LDAP.acl_users
return parent
MembershipTool._findUsersAclHome = _findUsersAclHome
La ligne parent = acl_users.LDAP.acl_users spécifie implicitement où se situe l'acl_users.
On redémarre le serveur, et hop, miracle ça marche !
Stockage d'informations utilisateur dans le LDAP :
On a vu au début qu'on pouvait mapper les attributs du LDAP sur les champs Plone. C'est bien, mais des fois, on voudrait pouvoir modifier les valeurs directement depuis Plone.
Il faut déjà modifier le template personalize_form.pt pour faire afficher les champs que l'on veut.
Ensuite il faut créer une External Method qui va mettre à jour le LDAP :
from os import curdir
from os.path import join, abspath, dirname, split
import os.path
import string
import ldap
import ldap.modlist
from Products.CMFCore.utils import getToolByName
from random import Random
global username
global password
global baseDN
username = "cn=admin,dc=exemple,dc=fr"
password = 'admin'
baseDN = "ou=personnes, dc=exemple, dc=fr"
def connexionLdap(self):
try:
l = ldap.open("127.0.0.1")
l.protocol_version = ldap.VERSION3
return l
except ldap.LDAPError, e:
print e
def setMonInfo(self, uid, value):
l = self.connexionLdap()
modlist = [(2, 'monChamp', str(value))]
searchScope = ldap.SCOPE_SUBTREE
retrieveAttributes = None
searchFilter = "uid="+uid
ldap_result_id = l.search(baseDN, searchScope, searchFilter, retrieveAttributes)
result_type, result_data = l.result(ldap_result_id, 0)
dn = result_data[0][0]
try:
l.simple_bind(username, password)
l.modify_s(dn, modlist)
except ldap.LDAPError, e:
print e
Dans le fichier personalize.cpy on rajoute la ligne suivante en dessous de la déclaration de la variable member :
uid = member.getProperty('email', None)
Et on ajoute le code suivant :
context.setMonInfo(uid, 'monChamp', monChamp)
Et voilà, avec ça, quand on modifie sa fiche, le LDAP est mis à jour aussi.
Avec un peu de patience, on peu faire beaucoup d'autres choses, je n'ai abordé que quelques exemples de base, mais on a pu voir que lorsque l'on veut aller plus loin qu'une utilisation basique du serveur LDAP avec Plone, il faut mettre les mains dans le code, et c'est pas toujours joli joli...
Le MonkeyPatch pour faire fonctionner la mise à jour du mot de passe est assez crade, je n'ai pas vraiment eu le temps de trouver une meilleur solution, ni pourquoi le code d'origine ne marche pas dans ce cas.
Le fait que l'on doive patcher pour avoir de nouvelles fonctionnalités n'est pas un bon point non plus. Certes, normalement, Plone ne devrait pas être utilisé pour modifier les données du LDAP ni créer de nouveaux utilisateurs. Pourtant dans certains cas, c'est très pratique, et si en plus c'est le client qui le demande...
J'ai l'impression que le LDAPMultiPlugin n'est pas assez mature, qu'il demande encore à être amélioré. Le plus dur au final est de trouver la documentation nécessaire, surtout lorsqu'on ne sait pas qu'il existe un patch.


Commentaires
merci pour le document mai il ya un truc qui me parait flou
Comment remplissez le "Users Base DN " je ne sais pas ou se trouve mon ldap et je travaille sur le localhoost
pour le "Groups Base DN" c'est pareil, et aussi pour le "Manager DN"
pour mon compt c "zenagui" et mon mot de passe "master" et je travail sur le local host
svp repond moi par e-mail c urgent
et merci d'avance
Cool la doc et merci beaucoup. Cependant je n'arrive pas à faire le monkeyPacth. En fait j'ai un code différent de celui que vous proposez dans la doc, donc je ne sais quoi supprimer ni modifier.
Merci de votre aide.