I've coded this and it works, but I would like to add some validation and make sure the code is up to drupal standards. I don't have a CVS account, but will figure out how to make a patch at that point.
It is needed for multisite installs so different AD groups can be mapped differently on different sites.
This group to role mapping data is currently stored in the file: ldapgroups.conf.php
P.S. 6.x.1/0-alpha2 worked fine for both LDAP authentication and groups for me.
Configuration: Microsoft Active Directory, port 389 with TLS. Groups are specified by LDAP attributes
Comments
Comment #1
miglius commentedSure, this will be a valuable enhancement. Create this feature as a patch (preferably to the development version of the module), the community will review it and we will commit it to the main module.
Comment #2
johnbarclay commentedThis is my first Drupal patch submission. Feedback is highly desirable.
Summary
Moved configuration for LDAP Group to Drupal role mapping from ldap_integration/ldapgroups.conf.php
to be configurable via Drupal web interface. This will allow per site configuration of LDAP group to
drupal role mappings.
Admins will now need to have LDAP group to Drupal role mappings for each site on a multisite install.
Admins will also need to have separate mappings for each LDAP instance within a site.
Screenshots: http://staff.ed.uiuc.edu/jbarclay/ldapgroups/
Not sure where the hook_update code fits into this version, but I added it and tested it.
The update will import group mappings in file ldap_integration/ldapgroups.conf.php into db configuration (if this file
is left in place and the ldapgroups_roles_filter function is not commented out.)
screenshots
http://staff.ed.uiuc.edu/jbarclay/ldapgroups/
File Change Summary
ldap_integration/ldapgroups.conf.php
- removed file. data now stored in db.
ldap_integration/LDAPInterface.php
- add 2 new properties: use_group_filter and role_mappings
ldapgroups.admin.inc
- added new fields to database reset and update operations.
- added new fields to admin form.
- added functions to validate and convert back and forth from | delimited text area to serialized array
ldapgroups.module
- remove require integration/ldapgroups.conf.php
- added new fields to init
- added function _ldapgroups_roles_filter to module. was in ldap_integration/ldapgroups.conf.php
- change logic in ldapgroups_user_login to use use_group_filter property to decide to use group filtering.
ldapgroups.install
- added ldapauth.ldapgroups_use_group_filter ldapauth.ldapgroups_role_mappings to unistall and install
- added hook_update to add db columns and import group mappings in file ldap_integration/ldapgroups.conf.php into db. User's will need to leave their
old ldap_integration/ldapgroups.conf.php file in place and comment out the _ldapgroups_roles_filter function, but not their
array in ldapgroups_role_mappings()
Tests
- install groups:
- make sure fields are created: ldapauth.ldapgroups_use_group_filter, ldapauth.ldapgroups_role_mappings
- if integration/ldapgroups.conf.php is present and has function uncommented and data, make sure data is imported
- uninstall ldap groups. make sure fields are removed.
- edit configuration. test validation.
- log in and out making sure roles are mapped correctly
Comment #3
miglius commentedThanks for the patch. I have several comments though.
First, I don't like the idea of changing the LDAPInterface.php file and adding groups related properties to it. Ldapgroups should be an addon to the ldap_authentication. Most installation do not use groups module therefore LDAPInterface.php should remain as light as possible. Groups can save it's related information to the db or the drupal variables.
Second, moving filter function to the main module file is not acceptable. I thought you have implemented filter configuration in the UI (don't know if it is feasible though). The idea is that if somebody needs to implement and code a custom filters, he does not ever touch the main module file and don't mess it up. Main module file should remain unchangeable. For this reason the filter function was implemented in the separate file. So to get rid of the configuration file we should find a way to move filer implementation to the configuration UI, but not the module file.
Comment #4
johnbarclay commentedI agree. I think both are doable and desirable. I'll resubmit when I'm done.
Comment #5
johnbarclay commentedSo all the group fields in ldapauth.ldapgroups_* should go in a separate interface and table, right?
- ldapauth.ldapgroups_* moves to ldapgroups.*
e.g.
ldapauth.ldapgroups_in_dn => ldapgroups.in_dn
There should be one record in the ldapgroups table for each ldapauth record with sid as the foreign key so that each ldap server can have its own group mappings? I think this is simplest since most people will only use one server and those who use 2, may have different mappings and group structures on each.
And move them to a separate db table (ldapgroups.*)
Comment #6
miglius commentedI think that it should be enough to add a column to the ldapauth table?
Comment #7
johnbarclay commentedI ended up shifting much of the code in ldapgroups.module into a separate class to improve efficiency and readability. All the code was being required in the hook_init and ldapgroups.module regardless of it was being used. Not sure what performance effect this has but readability is improved.
I also changed the query to only remove user_roles records that were no longer granted from ldap, rather than removing them all and adding some or all of them back.
The other changes are those that I originally set out to do:
new db and form fields added to update, install, uninstall, and admin forms for configuring the 3 newly configurable fields:
1. LDAP Group to Drupal Roles Filtering on/off switch
2. Mapping of groups to drupal roles
3. php for filtering roles (defaults to current php).
Hope the efficiency and class additions are ok.
John
Comment #8
miglius commentedThanks. Since this is more a rewrite than a small patch and I don't use ldapgroups module myself, I would appreciate if somebody who actively uses ldapgroups module could install this patch and test it in various configurations.
Comment #9
johnbarclay commentedLet me clean the code up a bit and add some comments first. I've already fixed a bug also.
Comment #10
johnbarclay commentedSince this is more of a rewrite, I added a couple of simple feature requests so the testing for all could be done at once:
- ability to use ldap groups without using ldap authentication.
* http://drupal.org/node/187990
* possibly related to webserver authentication: http://drupal.org/node/324732
- ability to limit who can create accounts based on ldap group membership
* http://drupal.org/node/322093
These required a little code in ldapauth.module file, but most of the code and all of the admin is in the ldapgroups files.
Attached is the tests I did and the patch.
Note this is a patch to the dev version:
RCS file: /cvs/drupal-contrib/contributions/modules/ldap_integration/ldapauth.module,v
retrieving revision 1.32.2.18
diff -u -p -r1.32.2.18 ldapauth.module
--- ldap_integration/ldapauth.module 5 Oct 2008 18:46:47 -0000 1.32.2.18
John Barclay
Comment #11
johnbarclay commentedHeres the same patch as above (v3) with tweaks to meet Drupal coding conventions. I was travelling and read the coding conventions section of "Pro Drupal Development" and installed the coder module.
John
Comment #12
johnbarclay commentedthis patch is for the dev version of ldap groups. Its not current with the alpha and beta versions. I will bring it up to date, but if no one will test it its pointless. If 2 people will commit to testing it, I'll bring it up to date this weekend. John
Comment #13
stevestoker commentedI could test it with my sites and see if it works well.
Comment #14
johnbarclay commentedThanks stevestoker. Attached is the patch described above in 2, 7, and 10. It for alpha2. The patch in #11 is for the Oct 5th dev version. I will make a patch for the Oct 14th dev if need be.
I can't do a diff of a new file without modify rights to the repository; because I don't know how.
So I've added the missing file in #21.
Comment #15
stevestoker commentedI did the patch and so far I can't get into the ldapgroups edit page. It links back to the administer by module page. I spent a few minutes in the source to see if I could see where the problem is, but didn't see anything wrong. The patch may have worked if I could get into the groups administration page to make some changes, but so far I haven't been able to test much. The authentication is still working well. Thanks!
Comment #16
johnbarclay commentedThese are the three urls:
/admin/settings/ldap/ldapgroups
/admin/settings/ldap/ldapgroups/edit/N , where N is the id of your ldap configuration, probably 1
/admin/settings/ldap/ldapgroups/woauth/edit (for using ldap groups without ldap authentication).
Do any of these urls function? Is it possible the menu is cached? May clear the cache at: /admin/settings/performance
What url is the bad link on? (The one that points to the adminisiter by module page)
Comment #17
stevestoker commentedI tried all the urls. The first one works well, but the edit and configure links don't work. The second one causes this error:
"PHP Fatal error: require_once() [function.require]: Failed opening required 'modules/ldap_integration/ldapgroupconf.class.php' (include_path='.:/var/lib/php/includes:/usr/share/pear') in /var/www/html/drupal-lectureprep/modules/ldap_integration/ldapgroups.admin.inc on line 144"
in my httpd/error_log.
The last url works fine.
I have my caching disabled so I don't think that is a problem.
Thanks!
Comment #18
johnbarclay commentedthanks for testing. Not sure what the problem is. Line 144 is simply:
require_once(drupal_get_path('module', 'ldapgroups') .'/ldapgroupconf.class.php');
Perhaps a debugging line at 143 to see if the path is correct.
print drupal_get_path('module', 'ldapgroups') .'/ldapgroupconf.class.php'; die;
Comment #19
Chuck1 commentedHi,
I have the same proplem the reason is that the file "ldapgroupconf.class.php" is missing after the patch #15.
The file is in the patch #7, but this file with patch #15 is not working.. :(
Can you post a new patch with the file?
Comment #20
johnbarclay commentedyep. I'll try to get to this today.
Comment #21
johnbarclay commentedI can't do a diff of a new file without modify rights to the repository; because I don't know how. So the patch in #14 and the attached file placed in the top level ldap_integration folder should do the trick.
I'm also adding a zip of everything in case this doesn't do the trick. The .zip includes the ldap help module I'm working on.
Comment #22
Chuck1 commentedThank you it works now with the patch or also the zip file.
At the beginning I have trouble to find "LDAP group" menu in the 'Site configuration', because it was only called "Groups" and not "LDAP Groups" as before.
So I change in the file "ldapgroups.module":
- 'title' => 'Groups',
+ 'title' => 'LDAP Groups',
In your Help Module the link to the readme.txt must be set to "README.txt".
But I get it not working or maybe I understand something wrong :( .
In the part "LDAP group to Drupal Roles filtering" I try somenthing like this:
cn=DrupalAdmin,ou=ORG2,ou=ORG1,DC=myDomain,DC=de|drupal_role_admin
In the AD I have the AD group "DrupalAdmin" in the OU -> ORG1 -> ORG2 -> [DrupalAdmin].
In the group DrupalAdmin I have insert my AD Username, but when I logon to drupal I get not the permission that I have define in the role "drupal_role_admin" :( .
I am a little bit confused when I see some examples, because sometimes a LDAP Group is equal a AD Organisation Unit = OU (?).
When I talking from an AD group I mean a AD Global Group filled with AD users.....
Comment #23
johnbarclay commentedthanks. I'll make those 2 changes.
The text in "Mapping of LDAP groups to Drupal Roles (one per line)" depends on which mappings you are using. This is why its confusing.
At /admin/settings/ldap/ldapgroups/edit/1 there are 3 cases, any mix of which can be used to figure out what "groups" a person belongs to. They aren't necessarily LDAP groups.
-----------------------------------------
Case 1: Group is specified in user's DN
Check this option if your users' DNs look like cn=jdoe,ou=Group1,cn=example,cn=com and Group1 turns out to be the group you want.
entry would look like:
Group1|Drupal Role
------------------------------------------
Case 2: Groups are specified by LDAP attributes
entry would look like whated the attribute value was. for example if the attribute name was "memberOf" in an Active Directory, the value would be like: cn=ED Staff,ou=education,DC=ad,DC=uiuc,DC=edu
and the entry would look like:
cn=ED Staff,ou=education,DC=ad,DC=uiuc,DC=edu|staff
-------------------------------------------
Case 3:
Groups exist as LDAP entries where a multivalued attribute contains the members' CNs
not sure about this one.
--------------------------------------------
at line 302 of ldapgroupconf.class, put the following code and login. It will show the syntax to use:
if you get something like:
You should use a syntax like:
campus accounts|drupal role x
CN=crb,OU=roles,OU=Portal,DC=ad,DC=uiuc,DC=edu|drupal role 2
I hope to add this kind of ldap groups support in the help module, but need to get this patch into ldap groups.
John
Comment #24
Chuck1 commentedOk, it works and hopefully I have it understand now :).
I write down "my" small summary:
I have the following user in the following OU and Domain:
cn=User1,ou=Department,ou=Location,DC=myDomain,DC=de
and the user is also member of the following group:
cn=DrupalAdmin,ou=Germany,ou=Intranet,DC=myDomain,DC=de
Now I have done following settings in the menu -> LDAP Groups.
1. Group by DN:
Attribute of the DN which contains the group name = ou
For finding the right drupal group we take every OU name (the mapping is done later * !).
2. Group by attribute:
Attribute names (one per line) = memberof
For finding the right drupal group we take every (Active Directory) group where the user is a "member off" -> user attribute "memberof" (the mapping is done later * !).
3. Group by entry
?
4. LDAP Group to Drupal Role Filtering (* the mapping is done here!):
Mapping of LDAP Groups to Drupal Roles (one per line)=
Location|Useradmin
Remark -> this for case 1. Group by DN:cn=DrupalAdmin,ou=Germany,ou=Intranet,DC=myDomain,DC=de|admin
Remark -> this for case 2. Group by attributeIt was not clear for me when I make step 4 that I have to define the attribute before in step 2.
And yes you are right --> 'The text in "Mapping of LDAP groups to Drupal Roles (one per line)" depends on which mappings you are using. This is why its confusing.'
Thanks,
Chuck
Comment #25
johnbarclay commentedThanks very much for testing this. And your description is very helpful. I will work your description into the documentation.
Perhaps I can add to the ldap help module some code that generated mapping examples based on group configurations and your existing roles.
Comment #26
uiadrupal commentedI am testing this coding out and when I install the latest rendition i get the following errors which causes those columns to not be in my database. So I was wondering what I can do to manually enter them in so they are the correctly added to my database.
user warning: BLOB/TEXT column 'ldapgroups_role_mappings' can't have a default value query: ALTER TABLE ldapauth ADD `ldapgroups_role_mappings` TEXT DEFAULT '' in D:\IIS\WEB\DEV\test\includes\database.mysql-common.inc on line 298.
user warning: BLOB/TEXT column 'ldapgroups_role_filtering_php' can't have a default value query: ALTER TABLE ldapauth ADD `ldapgroups_role_filtering_php` TEXT DEFAULT '' in D:\IIS\WEB\DEV\test\includes\database.mysql-common.inc on line 298.
user warning: BLOB/TEXT column 'ldapgroups_roles_granted_accts' can't have a default value query: ALTER TABLE ldapauth ADD `ldapgroups_roles_granted_accts` TEXT DEFAULT '' in D:\IIS\WEB\DEV\test\includes\database.mysql-common.inc on line 298.
Thanks for any help you can give!
Comment #27
uiadrupal commentedFYI. I got around my problem by manually adding the tables without putting any default data in the fields.
Thanks for adding this ability for LDAP Groups. Makes my life a whole lot easier!
Comment #28
johnbarclay commentedThanks. I've been using this for some time and a handful of others have tried it out. I think its ready to go.
Comment #29
johnbarclay commentedShould I patch this against head or another version?
It would be great to get this into the module. With hard coded group filters it not possible to use multisite configuration or do any of the newer drupal automation techniques such as:
- features, http://dc2009.drupalcon.org/session/paradigm-reusable-drupal-features
- implementing patterns module, http://drupal.org/project/patterns
- implementing install profiles
- ctools, http://drupal.org/project/ctools
Comment #30
johnbarclay commentedI can make it non oop no problem. If I do will it make this release? ...Its a little late to mention that oop may not be appropriate since we've already had people testing it. You mention in #8 to have some people install and test it and I've been working on getting that to happen.
If it won't can we package them separately so the complementary module's progress isn't so slow and more maintainers can participate? I use the ldap groups module in many of my sites and I need it to support multisite installs.
Comment #31
miglius commentedI'm planning to include this into the next release but not in the OOP style. I thing oop is cumbersome in this particular case.
Also I would like to move the ldapauth.conf.php and ldapdata.conf.php functions to the configuration area in similar way as you did with the groups configuration.
Comment #32
johnbarclay commentedGreat. Let me know if I can help in coverting it or testing.
Aside from making the content configurable via the web, the other feature in this code is making ldap groups usable without ldap auth. In fact in would be nice to simply turn ldap auth off without turning the module off (no hook_user, hook_init, and hook user validate) and still have access to the ldap servers and functions. Like a loose api.
Comment #33
miglius commentedDon't quite understand second paragraph - using ldapgroups without ldapauth.
Comment #34
johnbarclay commentedI should say using the ldapauth functionality of configuring one or more ldap servers; but not using the functionality of authentication when a user logs on.
This allows other functionality to be built on top of the ldapauth when its not being used to log a user on.
Comment #35
miglius commentedStill don't get it. How ldapgroups can be used without logging in ldap user?
Anyways, I have attached a patch which integrates your UI changes to the ldapgroups module. Please test it. I dared to make several minor changes:
- Checkbox "Use LDAP group to Drupal roles filtering" just enables filtering based on ldap to drupal groups mapping. The php code in UI is run if configured independently of this checkbox;
- In authentication restrictions LDAP groups should be entered instead of the drupal roles. (Several groups can be mapped to the same drupal role, therefore LDAP groups give bigger options);
- Authentication restriction creates a drupal user, but does not allow to login if user does not belong to the specified groups.
Comment #36
miglius commentedComment #37
johnbarclay commentedWe use a service account to bind to LDAP. Some people call it a machine account. Its a single LDAP account that has the lowest level permissions possible for the task at hand.
It the ldap interface: /admin/settings/ldapauth/edit/1 in the field "DN for non-anonymous search: "
Comment #38
miglius commentedCommitted. Please open separate issues in case of problems.
Comment #39
miglius commentedIn reply to http://drupal.org/node/376974#comment-1368246
The test button was introduced later, not in the latest patch. It retains the configuration settings, but not the current changes. The user is supposed first to save his new settings, then to test saved settings by clicking the button. Maybe a brief explanation next to the test button could help here.
You said that configurations "Groups are specified by LDAP attributes" or "Groups exist as LDAP entries where a multivalued attribute contains the members' CNs" failed. I have not changed the logic here. Was it working for you before the patch? Can you debug where the problems are?
Why is case sensitivity which a bad thing?
ldap_groups contains the LDAP groups from which drupal allows to automatically create accounts. You have to know your LDAP structure if you want allow account creation just for subset of all your LDAP groups?
Comment #40
miglius commentedI'm closing this issue as the functionality is implemented and no comments were given. Please open a separate tickets in case of bugs.