I have a search which returns a list of groups and their members from the data provided by ADMon. The members include user objects, as well as other group objects. By using a selfjoin, I can expand this sub group and link its members with the top level group. However, I have not figured out a way to traverse an arbitrary number of nested groups. Any ideas?
I have found a solution that will work with up to 4 levels of nesting (and can be expanded to work with up to X levels). I have setup up two lookup table generating scheduled searches.
The first search runs at *:20:00 and *:50:00.
index=activedirectory source="admon" objectClass="top|group" earliest="10/28/2012:0:0:0" | dedup objectSid | eval members=split(member, "|") | mvexpand members | eval member=replace(members, "CN=", "") | eval member=replace(member, ",OU=.*", "") | table sAMAccountName, member | outputlookup ADGroupMembership1.csv
The second search runs at *:25:00 and *:55:00 (5 minutes after search #1).
| inputlookup ADGroupMembership1.csv | eval topGroup=sAMAccountName | table topGroup, sAMAccountName, member | eval joinOn=lower(member) | join max=100 type=outer joinOn [| inputlookup ADGroupMembership1.csv | eval joinOn=lower(sAMAccountName)] | dedup topGroup, member | join max=100 type=outer joinOn [| inputlookup ADGroupMembership1.csv | eval joinOn=lower(sAMAccountName)] | dedup topGroup, member | join max=100 type=outer joinOn [| inputlookup ADGroupMembership1.csv | eval joinOn=lower(sAMAccountName)] | dedup topGroup, member | join max=100 type=outer joinOn [| inputlookup ADGroupMembership1.csv | eval joinOn=lower(sAMAccountName)] | dedup topGroup, member | table topGroup, member | outputlookup ADGroupMembershipExpanded.csv
After this second search runs, a lookup table is created. The table has two columns/fields: "topGroup" and "member". If you wanted to see all of the users who are members of the group "Domain Admins" (through up to 4 levels of group nesting), you simply run this search:
| inputlookup ADGroupMembershipExpanded.csv | search topGroup="Domain Admins"
If you have more than 4 levels of nesting in your environment, you can modify search #2 to include additional instances of:
join max=100 type=outer joinOn [| inputlookup ADGroupMembership1.csv | eval joinOn=lower(sAMAccountName)] | dedup topGroup, member
You can also download the SA-ldapsearch app that does this for you.
I have found a solution that will work with up to 4 levels of nesting (and can be expanded to work with up to X levels). I have setup up two lookup table generating scheduled searches.
The first search runs at *:20:00 and *:50:00.
index=activedirectory source="admon" objectClass="top|group" earliest="10/28/2012:0:0:0" | dedup objectSid | eval members=split(member, "|") | mvexpand members | eval member=replace(members, "CN=", "") | eval member=replace(member, ",OU=.*", "") | table sAMAccountName, member | outputlookup ADGroupMembership1.csv
The second search runs at *:25:00 and *:55:00 (5 minutes after search #1).
| inputlookup ADGroupMembership1.csv | eval topGroup=sAMAccountName | table topGroup, sAMAccountName, member | eval joinOn=lower(member) | join max=100 type=outer joinOn [| inputlookup ADGroupMembership1.csv | eval joinOn=lower(sAMAccountName)] | dedup topGroup, member | join max=100 type=outer joinOn [| inputlookup ADGroupMembership1.csv | eval joinOn=lower(sAMAccountName)] | dedup topGroup, member | join max=100 type=outer joinOn [| inputlookup ADGroupMembership1.csv | eval joinOn=lower(sAMAccountName)] | dedup topGroup, member | join max=100 type=outer joinOn [| inputlookup ADGroupMembership1.csv | eval joinOn=lower(sAMAccountName)] | dedup topGroup, member | table topGroup, member | outputlookup ADGroupMembershipExpanded.csv
After this second search runs, a lookup table is created. The table has two columns/fields: "topGroup" and "member". If you wanted to see all of the users who are members of the group "Domain Admins" (through up to 4 levels of group nesting), you simply run this search:
| inputlookup ADGroupMembershipExpanded.csv | search topGroup="Domain Admins"
If you have more than 4 levels of nesting in your environment, you can modify search #2 to include additional instances of:
join max=100 type=outer joinOn [| inputlookup ADGroupMembership1.csv | eval joinOn=lower(sAMAccountName)] | dedup topGroup, member
You may want to create an additional field at index time that can be used as a reference in your searches to determine the how "deep' to traverse the user groups, etc.
It was nice meeting with you at .conf2012, and I appreciate the effort you put into this. However, after reviewing it, I'm not sure how your suggestion would be accomplished.
AD memebrships are tree like in structure. So for example I might have these events:
"Group: A; Members: Group B, Group X;"
"Group: B; Members: Group C;"
"Group: C; Members: RTAdams89, Group Y;
Because of the nesting, Groups "B", "X", "C", and "Y" and user "RTAdams89" are all members of group "A".
If I were to write a script to determine the depth, I might as well just have the script expand all the members.
I have the same problem and I'm looking for appropriate solution.
Anyone have ideas here?