LDAP support was not perfect with GRUF < 3. It worked perfectly in a read-only, non-groups situation, but setting groups inside LDAP was a pain (you had to put two LDAPUserFolder objects, one for users, the other one for groups) and it was not possible to nest groups nor to set specific roles on groups.
GRUF 3.0 solves part of this problem - and it's not been easy ! This document explains how GRUF 3 handles LDAPUserFolder sources. More generally, this document explains how to have Plone + GRUF + LDAPUserFolder and beeing happy.
An LDAP directory is not a very simple thing to use. You need to have a basic knowledge of how it works before going any further. Especially, you have to precisely know what is:
Warning
If you don't master any of those LDAP concepts, just forget about plugging LDAP into Plone and go to further readings about LDAP.
Now you've got to think about what you plan to do with your LDAP directory.
If you want to set a read-only access from Zope, you don't have to read this section.
If you want to allow Zope to write into your LDAP directory, things get more complicated... A lot of issues is involved, essentially because LDAPUserFolder is NOT (and is not intended to be) an LDAP directory management tool.
Those issues are out of scope of this document.
At one point, you have to decide if you want your Zope roles and groups stored in your LDAP directory or in your ZODB. You have to make a clear choice here - it's not possible to have some groups or roles in LDAP and some of them in ZODB.
If you decide to store your groups in LDAP, it won't be possible to give Zope roles to those groups.
If you decide to store your groups in LDAP, it won't be possible to have nested groups.
Groups creation by LDAPUserFolder is not covered by this document.
By default, LDAPUserFolder expects your user class to have the following structure:
(root) o=Organization, c=US
|
|-- ou=people
|
|-- cn=User1's name
| cn: User1's name
| objectClass: top, person
...
You can easily change some of these parameters in LDAPUserFolder configuration. Especially, you can configure the attributes used to fetch or name users:
Ok. Now, the rest is just a matter of tuning things in. It will enventually work, as this is the simplest case - if you cannot manage to make this part work, don't even go further in this document :^)
Warning
Once again: you _need_ basic LDAP knowledge and basic Zope knowledge to make this work. Don't do things if you don't understand them!
LDAP interaction is an easy thing until you want to manage your groups in LDAP. That's where the things get complicated because there are several options and many elements in the chain to handle this properly.
If you don't want groups to be managed by your LDAP directory, skip this part and go to the "No groups" section below.
First of all, you MUST set "groups stored on LDAP server" in LDAPUF configuration to have your groups stored in LDAP.
LDAP Groups function differently with or without GRUF. Without GRUF, LDAP groups are mapped to Zope ROLES. With GRUF, well... it depends :-) (this is explained below)
But in any case, you groups schema must conform to something like this:
(root) o=Organization, c=US
|
|-- ou=people
| |
| |-- cn=User1's name
| | cn: User1's name
| | objectClass: top, person
/ ...
|
|-- ou=groups
|
|-- cn=Group's name
| cn: Group's name
| objectClass: groupOfNames
| member: cn=User1's name, ou=people, o=Organization, c=US
...
When reading groups, they can belong to one of the following classes : "groupOfUniqueNames", "groupOfNames", "accessGroup" or "group". Depending on that class, the attribute holding group members changes. Here's the mapping, as defined is LDAPUserFolder.utils:
GROUP_MEMBER_MAP = {
'groupOfUniqueNames' : 'uniqueMember'
, 'groupOfNames' : 'member'
, 'accessGroup' : 'member'
, 'group' : 'member'
}
Important
This shema implies a very important thing: user/group mapping is stored on the group key and not on the user key. This is something you must keep in mind while managing your LDAP directory.
If you don't want your groups to be stored on the LDAP server, just set "Groups NOT stored on LDAP server" in the "Configuration" tab of LDAPUserFolder.
Once you're happy with your LDAP structure, and once you've tested your configuration with LDAPUF alone (id est in an empty folder, without GRUF), you can proceed with GRUF.
If you want your roles and groups stored in LDAP, you have to know the following facts:
You have to set "Groups stored on LDAP server" in LDAPUF's configuration.
Your groups structure in LDAP must conform to what is explained below (ie. you must use groupOfNames-like classes and cannot use posixGroups).
If you want to set a specific role (Manager, Reviewer, ...) on a specific LDAP user, you must have the following two conditions fulfilled:
Local roles work normally - setting a local role doesn't require to write something in LDAP.
GRUF Groups have the same requirements as Zope roles plus a few others : if you want to put a user in a group, you have to care about this:
The GRUF group you want to set must be mapped, in LDAPUserFolder, to a LDAP Group. You can do this either:
- manually in LDAPUserFolder (in the "Groups" tab)
- by clicking the "Update" button located at the bottom of the "Sources" tab in GRUF 3.2.
Your LDAPUF's configured manager DN must have the right to modify this group key.
You need to use LDAPGroupFolder (provided with GRUF >3) as a Groups Source in GRUF.
If you want your groups to be stored in ZODB, things are much easier:
To have Plone work with the above configuration, it's quite simple... Just do it ! ;) It's easy with Plone 2.0.5.
All your site members should have the 'Member' role in Plone. So you have to replace, in LDAPUF's configuration page, the 'Anonymous' default role by 'Member'.
Then, drop an empty file called preview.txt in your GroupUserFolder's directory, and restart Zope. This will enable some Plone bugfixes and patches to make it work better.
...However, some Plonish stuff won't work out-of-the-box. Here's a list of known issues.
Joining a user won't work if your directory is read-only. You'd better disable this - anyway it's a bad idea to allow direct LDAP manipulation through a link on the web!
For the same reason, some forms in the users management configlet may fail. You'd rather operate in ZMI instead.
Then, you'll notice that individual user preferences page NEVER saves data back in the LDAP server. It's a normal a known behaviour - to disallow, for example, people from modifying their LDAP-stored email address.
To have the ability to see people's email, you just have to do a mapping in LDAPUserFolder, with the schema configuration page.
Plone's attribute for email is... "email".
So, if your users are stored as inetOrgPerson classes, here's the mapping you can do:
| LDAP name | Mapped to name |
|---|---|
| displayName | fullname |
| jpegPhoto | portrait |
Yes, the JPEG photo will work - at least with GRUF 3.2.
As passwords are stored crypted (and often unreadable) in LDAP, you cannot allow people to retreive their password by email.
Local role work fine with the preview.txt hint: the localroles form is able to retreive LDAP users which are not in LDAPUF's cache (people who already had this problem will know what I mean!).
However, there's a bug in folder_localroles_form which prevents assigning a local role to a group in GRUF 3.2 + Plone 2.0.x. You have to fix this template like this:
405c405 < <td tal:define="global group_name group/getUserId"> --- > <td tal:define="global group_name group/getUserName">
A version is provided (but not installed) in the gruf_plone_2_0 directory of GRUF.
The encoding used to return LDAP values to Zope is Latin 1. Ie., even if your LDAP directory manages UTF8 perfectly, you are bound to Latin1 encoding in your Zope application (unless you edit LDAPUserFolder.utils.encoding).
With GRUF 2, it was not possible to create or change a user. It's now possible to change a user quite easily. This is not covered in this document.
Mutation is quite transparent, however creation is more complex. Here's a hint on this:
All user keys must have a fillable cn, uid and sn attribute. This is right for inetOrgPerson stuff. This is required because at creation time we only know user's login (not his name nor other information). So we fill those three required fields with his login. This behaviour can be changed by customizing the gruf_ldap_required_fields script (within Plone only).
GRUF 3 now supports groups natively with different strategies. You have to choose which strategy to use depending on where your groups are stored (in your LDAP database or not).
Whatever you choose, you can always create groups through GRUF. Remember that some group assigning may need you to have the proper rights to edit your LDAP database.
If you want to store your groups in LDAP, you have to understand a few things.
First of all, LDAP supports groups and not roles. Zope natively supports roles and not groups. So what LDAPUF (alone) does is basically mapping LDAP groups to Zope roles.
[BTW, you cannot assign a role to a user if that role doesn't already exist in LDAP, even if you map, in LDAPUF, a group to that particular role.]
This is okay for the common usage but with GRUF, as groups now appear within Zope, it gets more complicated. A LDAP group can be seen either as a role or a group within Zope. We decide that with the following assertion:
If a LDAP group has the same name as a Zope role, then it's seen as a role. It's seen as a group in any other case.
Within GRUF, you've got a new user source which is called LDAPGroupFolder. Just drop it in place of your existing group source, AFTER you've instanciated your LDAPUF.
To achieve such a result, we've been obligated to hotfix LDAPUF. Please be aware that we NEVER modify a method, we just add new ones.
We integrated this product : http://zope.org/Members/volkerw/LDAPUserFolderExt/LDAPUSerFolder_0_4 So... it's not compatible anymore with GRUF 3 ! :-)
Warning: LDAPUF may cause some additional roles having the same name as groups to appear in some GRUF pages. This is due to http://www.dataflake.org/tracker/issue_00376 issue.
By now, only LDAPUF >= 2.4Beta3 has been tested successfuly. I personnally recommand LDAPUserFolder 2.5.