Opened 15 years ago
Last modified 5 years ago
#5996 new defect
LdapPlugin should cascade group memberships
Reported by: | Owned by: | Emmanuel Blot | |
---|---|---|---|
Priority: | high | Component: | LdapPlugin |
Severity: | normal | Keywords: | |
Cc: | Trac Release: | 0.11 |
Description
Groups can be defined either through its direct members (which can be users or other groups), or through the memberOf attribute of users or other groups. LdapPlugin should support both methods. Also, LdapPlugin should support indirect membership of a group (where a user is a member of a group that is in its turn member of another group). Where supported matching syntax 0.113556.1.4.1941 should be used.
Typically, the LDAP query could look something like:
(&(objectClass=user)(memberOf:1.2.840.113556.1.4.1941:=CN=groupName))
Attachments (0)
Change History (2)
comment:1 Changed 5 years ago by
comment:2 Changed 5 years ago by
Ok, so turns out my previous patch does not work. Based on the code provided in ticket #7339, I made recursive groups in a more efficient way:
diff --git a/0.12/ldapplugin/api.py b/0.12/ldapplugin/api.py index 4d6f6e2..3642517 100644 --- a/0.12/ldapplugin/api.py +++ b/0.12/ldapplugin/api.py @@ -145,19 +145,36 @@ class LdapPermissionGroupProvider(Component):
del self._cache[username]
# Private API
-
def _get_user_groups(self, username):
"""Returns a list of all groups a user belongs to"""
- ldap_groups = self._ldap.get_groups()
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)
- return groups
+ grouprdns = [] + srfilter = "(&(objectclass=%s)(%s=%s))" % (self._ldap.groupname, self._ldap.groupmember, self.util.user_attrdn(username)) + srresult = self._ldap.get_dn(self._ldap.basedn, srfilter) + if srresult: + groups.extend(srresult) + for group in srresult: + groups = groups + self._get_group_parents(group) + + # Return only the RDN + for group in groups: + m = DN_RE.search(group) + if m: + grouprdn = GROUP_PREFIX + m.group('rdn') + if grouprdn not in grouprdns: + grouprdns.append(grouprdn) + return grouprdns + + def _get_group_parents(self, groupdn): + parents = [] + srfilter = "(&(objectclass=%s)(%s=%s))" % (self._ldap.groupname, self._ldap.groupmember, groupdn) + srresult = self._ldap.get_dn(self._ldap.basedn, srfilter) + if srresult: + parents.extend(srresult) + for groupdn in srresult: + parents = parents + self._get_group_parents(groupdn) + return parents +
Directive 1.2.840.113556.1.4.1941 is only handled by Active Directory and Samba4. OpenLDAP does not support it as of 2019 (Even though I can find requests for this function dating 2002).
I have a quick patch that enables recursive LDAP search. It is not optimized in terms of performance, but it works: