I am querying Active Directory via LDAP (from Java and PHP) to build a list of all groups that a user is a member of. This list must contain all least all groups (organizational-units optional) that contain groups the user is directly a member of. For example:
User1 is a member of GroupA, GroupB, and GroupC.
GroupA is a member of GroupD.
I am looking for a way to construct an LDAP query that will return GroupA, GroupB, GroupC, and GroupD all at once.
My current implementation is below, but I am looking for a more efficient way to gather this information.
Current Naive Implementation (In pseudo-code)
user = ldap_search('samaccountname=johndoe', baseDN);
allGroups = array();
foreach (user.getAttribute('memberOf') as groupDN) {
allGroups.push(groupDN);
allGroups = allGroups.merge(getAncestorGroups(groupDN));
}
function getAncestorGroups(groupDN) {
allGroups = array();
group = ldap_lookup(groupDN);
parents = group.getAttribute('memberOf');
foreach (parents as groupDN) {
allGroups.push(groupDN);
allGroups = allGroups.merge(getAncestorGroups(groupDN));
}
return allGroups;
}
Active Directory has a special search filter option that allows it to filter through chained objects, like nested groups. The capability is described here .
Here is an example of how to retrieve all users in a group, including nested groups:
(&(objectClass=user)(memberof:1.2.840.113556.1.4.1941:={0}))
where {0}
is the DN of the parent group.
You need to map the directory tree, as you move through it, so you can check to see if you have previously explored a DN, some Active Directories contain looped group inclusions. So you'll need to guard against it.
This solution also doesn't require recursion.
In some pseudo code
def getGroupsOfDN(userDN)
groups = []
groupsExplored = []
groupsToExplore = []
current = userDN
groupsToExplore << userDN
while(!groupsToExplore.empty?)
ldapentry = ldap_lookup(current)
if (!ldapentry.nil?)
groups << current
current_groups = ldapentry.getAttributes("memberOf")
current_groups.each do |groupDN|
if(groupsExplored.indexOf(groupDN) != -1)
groupsToExplore << groupDN
groupsExplored << groupDN
end
end
end
groupsToExplore.remove(current)
if (!groupsToExplore.empty?)
current = groupsToExplore.get(0)
end
return groups
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.