Hi Again
I decided to have a go at fixing my issue by patching the plugin source.
Apologies to real python programmers - this is my first attempt at
python programming and probably contains many discordant stylistic
errors. Nevertheless it works for my setup, and may work for someone
else's - your mileage may vary, etc. Here are the issues this patch
solves:
* _get_user_groups: on my system, self._ldap.get_groups returns
empty groups, i.e. list members of value 'None'. This causes the code to
stack trace. This patch adds an 'if group!=None:' statement to step over
empty groups.
* _get_user_groups: I added some debug output from this function
to help debug my setup. It is commented out in the patch.
* get_groups: modified this function to use the group_rdn config
setting, so that only the effective groupdn is searched for groups,
rather than the whole hierarchy; on my setup this made 10 seconds or so
of difference as we have around 100 groups in our directory, only 4 of
which we are interested in. NB this may not be the right thing to do!
* user_attrdn: modified to handle multiple user_rdn values, to
accommodate Users in different LDAP containers. The function was
modified to return an array of DNs in all cases, multiple cases being
the result of splitting the user_rdn config setting using the delimiter
'|'. Even if (after splitting) there is only one item generated, a
singleton list is still returned; this is to simplify the calling code
(_get_user_groups) which has been modified to handle list return values
instead of strings. This allows user_rdn to be set like:
user_rdn = <rdn0>[|<rdnx>]*
for example:
user_rdn = ou=technical|ou=management|ou=sales
The patch is an svn diff of ldapplugin/api.py taken from my working copy
against version 2262 on your subversion server. I have attached it as a
text file.
Hope this helps someone.
Cheers
Jim
________________________________
From: Jim Page
Sent: 07 June 2007 00:05
To: '[email protected]'
Subject: RE: [Trac] Re: LdapPlugin: user_rdn support for users in
several OUs?
Hi Bruce
Thanks for the reply Bruce, but if I understand your reply correctly, it
solves a different problem to mine.
Are you describing a way of getting LDAP authentication working in
apache? Strangely enough, I am having no problem with that side of it,
all my users can log in fine to both subversion and trac using
'AuthBasicProvider ldap' etc, and I have groups set up for Trac users
and Subversion users, and use 'require ldap-group <blah>'. It doesn't
seem to matter what OU the users are under for the apache http
authentication to work as long as they are members of the right group.
The problem I am trying to solve is trying to get the Trac LdapPlugin to
assign Trac permissions to users based on their LDAP group memberships.
I have permissions assigned (via trac-admin) to various groups
(TracAdmin, TracUser, TracGuest etc); everything works as long as the
Users are in the OU I specify in user_rdn (in trac.ini). The trouble is
I want to admit users in different OUs. When a User logs in to Trac who
is in the right group but not in the right OU, trac loads (ie apache
http authentication works) but with no permissions set (empty menu bar,
front page message '403 Forbidden (WIKI_VIEW privileges are required to
perform this operation)', ie LdapPlugin group permissions is broken.
My working theory for why Apache LDAP group authentication works and
Trac LdapPlugin doesn't is that apache LDAP looks for the User in the
group's 'member' attributes. LdapPlugin looks at the User's 'memberOf'
attributes to look up the groups the user belongs to, ie back to front
compared to apache. Apache only needs to know the CN of the group (which
is supplied in 'require ldap-group') whereas the LdapPlugin needs to
know where the groups are AND where the Users are, but will only look in
<user_rdn>,<base_dn> for Users; if a given User is not in this branch
then the lookup will fail. A similar problem would exist if the Groups
themselves were in different OUs.
So it looks like I have 2 options:
1) some guru tells me how to set it up properly using the existing
version
2) I patch the plugin to allow more than one user_rdn setting,
perhaps using an array
Ideas, anyone?
Thanks again
Jim
________________________________
From: [email protected] [mailto:[EMAIL PROTECTED]
On Behalf Of Wilson, Bruce E.
Sent: 06 June 2007 19:58
To: [email protected]
Subject: [Trac] Re: LdapPlugin: user_rdn support for users in several
OUs?
We're using LDAP as well. It's a bit of a hack, but what I've done is
use an Include file that has a set of require user and require group
directives. I've built a database table, and the list is generated from
that table with a cron job. Doing it this way -- with the include file
-- lets me use the same file in both the SubVersion section of the conf
files and the Trac section. I'm actually managing three different
SubVersion repositories and two related Trac instances.
============================================================
Bruce E. Wilson ([EMAIL PROTECTED])
Environmental Sciences Division
Oak Ridge National Laboratory
________________________________
From: [email protected] [mailto:[EMAIL PROTECTED]
On Behalf Of Jim Page
Sent: Wednesday, June 06, 2007 3:41 AM
To: [email protected]
Subject: [Trac] LdapPlugin: user_rdn support for users in several OUs?
Morning All
My problem: I am using LdapPlugin to manage my Trac permissions, and
it's great. However our AD structure has users assigned to various
different OUs, Technical, Sales, Management and so on. The Groups I am
using to assign permissions are in the Technical OU (which I set up in
group_rdn), and all works fine, as long as the users themselves are in
the OU I set up in the 'user_rdn=' config entry. But there are several
users in other OUs I would like to allow in, including (rather urgently)
the Technical Manager (who is in OU=Management). Is this currently
supported in any way? Grasping at straws, I tried 'OU=*' in user_rdn
:-) but it didn't work of course.
All help gratefully received.
In the event that this is not currently supported, I am considering the
idea of patching LdapPlugin to allow an array of RDNs in user_rdn -
anyone care to comment on that idea, is it a desirable feature for
anyone except me? Is there a better way to do this?
All the best
Jim
Jim Page
Chief Technical Architect
Email Systems Ltd
Telephone: +44 (0) 870 141 7070
Facsimile: +44 (0) 870 141 8080
www.emailsystems.com <http://www.emailsystems.com> - robust messaging
technology
<BR
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Trac
Users" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/trac-users?hl=en
-~----------~----~----~----~------~----~------~--~---
Index: ldapplugin/api.py
===================================================================
--- ldapplugin/api.py (revision 2262)
+++ ldapplugin/api.py (working copy)
@@ -146,15 +146,24 @@
def _get_user_groups(self, username):
"""Returns a list of all groups a user belongs to"""
- ldap_groups = self._ldap.get_groups()
+ ldap_groups = self._ldap.get_groups(self.util.get_group_rdn())
+ ## dump some useful debug
+ ## outp = open("/tmp/trac2.log","a")
groups = []
for group in ldap_groups:
- if self._ldap.is_in_group(self.util.user_attrdn(username), group):
- m = DN_RE.search(group)
- if m:
- groupname = GROUP_PREFIX + m.group('rdn')
- if groupname not in groups:
- groups.append(groupname)
+ rdntuple = self.util.user_attrdn(username)
+ for rdnitem in rdntuple:
+ ## print >> outp, ("user: %s - trying group %s (userdn=%s)" %
(username,group,rdnitem))
+ if group!=None:
+ if self._ldap.is_in_group(rdnitem, group):
+ m = DN_RE.search(group)
+ if m:
+ groupname = GROUP_PREFIX + m.group('rdn')
+ if groupname not in groups:
+ groups.append(groupname)
+ ##print >> outp, (" group %s: found %s" %
(group,groupname))
+ ##print >> outp, ("---")
+ ##outp.close()
return groups
class LdapPermissionStore(Component):
@@ -453,6 +462,9 @@
def is_group(self, username):
return username.startswith(GROUP_PREFIX)
+
+ def get_group_rdn(self):
+ return self.group_rdn
def create_dn(self, username):
"""Create a user or group LDAP DN from his/its name"""
@@ -471,11 +483,13 @@
def user_attrdn(self, user):
"""Build the dn for a user"""
+ # in all cases we return a list, even if the list
+ # consists of one item
if self.user_rdn:
- return "%s=%s,%s,%s" % \
- (self.uidattr, user, self.user_rdn, self.basedn)
+ rdntuple = self.user_rdn.split('|')
+ return [ "%s=%s,%s,%s" % (self.uidattr, user, rdnitem,
self.basedn) for rdnitem in rdntuple ]
else:
- return "%s=%s,%s" % (self.uidattr, user, self.basedn)
+ return ["%s=%s,%s" % (self.uidattr, user, self.basedn)]
def extract_user_from_dn(self, dn):
m = DN_RE.search(dn)
@@ -536,9 +550,12 @@
self._ds.unbind_s()
self._ds = None
- def get_groups(self):
+ def get_groups(self, group_rdn):
"""Return a list of available group dns"""
- groups = self.get_dn(self.basedn, 'objectclass=' + self.groupname)
+ if group_rdn:
+ groups = self.get_dn("%s,%s" % (group_rdn,self.basedn),
'objectclass=' + self.groupname)
+ else:
+ groups = self.get_dn(self.basedn, 'objectclass=' + self.groupname)
return groups
def is_in_group(self, userdn, groupdn):