I have been struggling to find a good way to query out the members of a specified AD Group.
I have no issues in finding the group, or even querying users based on criteria.
currently I have
PrincipalContext context = new PrincipalContext(ContextType.Domain, _domain, ADServerUser, ADServerPassword);
UserPrincipal userPrinciple = new UserPrincipal(context);
userPrinciple.GivenName = "stringToSearchForFirstName";
userPrinciple.Name = "stringToSearchForUserName";
userPrinciple.Surname = "stringToSearchForLastName";
PrincipalSearcher srch = new PrincipalSearcher(new UserPrincipal(context));
srch.QueryFilter = userPrinciple;
var result = srch.FindAll();
This give me all the users that I want, however it doesn't filter the group down.
I can use the GroupPrinciple Object along with the principal search, but then I can't filter down the Users.
I kind of want a way to be able to apply both a UserPrincipal and GroupPrincipal to filter the returned results by BOTH Group and User parameters.
I've used a linq where clause to try and do a match to see if the user is in a group but when i get all users the query times out. makes sense over all.
However if i query out the group, I have no way of using the principalSearcher to apply the query.
Any ideas on how to do this?
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, _domain);
// get the AD Group you are wanting to Query
GroupPrincipal group = GroupPrincipal.FindByIdentity("cn=YourGroupname");
foreach(Principal p in group.Members)
{
//do what ever coding you need to do here
}
From my research I have concluded that using the Principal Objects to be able to filter on both group and user parameters is not possible. we needed to revert to using query string methods to AD to solve the issue.
Related
I currently have the following code which successfully gets all Security Groups from AD and adds them into a Check List box:
try
{
Logging.LogMessageToFile("Reading Security Groups from AD.");
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
GroupPrincipal qbeGroup = new GroupPrincipal(ctx);
PrincipalSearcher srch = new PrincipalSearcher(qbeGroup);
foreach (var found in srch.FindAll())
{
lstAdGroups.Items.Clear();
lstAdGroups.Items.Add(found);
}
}
catch (Exception ex)
{
Logging.LogMessageToFile("Unexpected error reading Security Groups from AD: " + ex.Message);
}
My issue is that it currently pulls every Security Group (where ideally I'd only like to only list custom created security groups (eg, exclude any from the Users or Builtin OU's). I can't see if there are any properties against groups to filter 'custom' from out the box. Is this even possible?
PrincipalSearcher can only filter based on attributes that are exposed in properties of the various Principal classes. If you're looking for groups, you're limited to filtering based on the properties of the GroupPrincipal class.
That issues aside, filtering out objects in certain OUs isn't something you can do in a query at all simply because there is no AD attribute that contains the OU that you're allowed to filter on. So there is two ways you can do this:
Do what you're already doing, but in your loop, look at the DistinguishedName property of the result. If it's in an OU you don't like, then just continue;.
You can use DirectorySearcher directly (which is what PrincipalSearcher uses in the background anyway), and filter by the isCriticalSystemObject attribute. That will filter out built-in objects like the Domain Admins and Users groups, etc.
Here is a simple example using DirectorySearcher that just outputs the name of each group:
var searcher = new DirectorySearcher("(&(objectClass=group)(!isCriticalSystemObject=TRUE))");
using (var results = searcher.FindAll()) {
foreach (SearchResult result in results) {
Console.WriteLine(result.Properties["cn"][0]);
}
}
I have the following code. It is supposed to check with the ldap server what roles does a user has and display all of them and delete any role that doesnt exist on the ldap server. Right now it doesnt display "domain users" group as it is the primary group. But i need it to display domain users role as well. I tried including the (primaryGroupID=513) in the filter but that doesnt work as 'directorySearcher.FindOne();' returns null after i add the primaryGroupID to the filter.
I am sure you have done your research as well. I dont believe there is an easy way to access the groups that are set up as primary, or part of the groups that are members of the same group as Domain Users. My account in my AD have 125 groups but only 70 shows up if i query via powershell or DirectoryEntry.
I know that the following code works and pulls all the groups regardless of what type of group it is.
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
UserPrincipal user = (UserPrincipal)Principal.FindByIdentity(ctx, userID);
PrincipalSearchResult<Principal> userGroups = user.GetAuthorizationGroups();
You can access the default group if you get the PrimaryGroupID first.
We document the LDAP Filter that can be used.
And there is also Get-ADPrincipalGroupMembership
This worked flawlessly
`if (results!=null)
{
//find primary group (by default Domain Users)
var User = results.GetDirectoryEntry();
User.RefreshCache(new string[] { "tokenGroups" });
foreach (byte[] resultBytes in User.Properties["tokenGroups"])
{
var SID = new SecurityIdentifier(resultBytes, 0);
var sidSearcher = new DirectorySearcher();
sidSearcher.SearchRoot = directoryEntry;
sidSearcher.Filter = "(objectSid=" + SID.Value + ")";
sidSearcher.PropertiesToLoad.Add("name");
var sidResult = sidSearcher.FindOne();
if (sidResult != null)
{
MemberGroups.Add((string)sidResult.Properties["name"][0]);
}
}`
I am working on authenticating an MVC4 application using Active Directory. Users are assigned to local security groups specific for this application (Local_Group_APP_myApp_Admin).
I am using a custom AuthorizeAttribute. The attribute on top of my action methods is:
[AuthorizeAD(Groups = "Local_Group_APP_myApp_Admin")]
In the custom AuthorizeAttribute class I have:
foreach (var group in groups)
if (userPrincipal.IsMemberOf(context, IdentityType.Name, group))
return true;
}
This would check whether the user is a member of Local_Group_APP_myApp_Admin, which is false (I don't know why). If I get the PARENT (global) group of Local_Group_APP_myApp_Admin, I think IsMemberOf(global_group) would return true.
How to get the parent group of a local group?
Although you have not specified where userPrincipal is set, it seems like your problem is IsMemberOf only returns true if the user is actually a member of that group. If you need to recursively check for group membership you need to do something more like:
using (PrincipalSearchResult<Principal> securityGroups = user.GetAuthorizationGroups())
{
return securityGroups.Any(g => groups.Contains(g.Name));
}
GetAuthorizationGroups returns all security groups the user has membership of.
You can query LDAP to get all the parent groups from a subgroup using the following C#/LDAP query, you can see the full context of the code in this answer, you will need to get your LDAP path correct
DirectorySearcher searcher = new DirectorySearcher(entry, "(&(objectcategory=group)(cn=Local_Group_APP_myApp_Admin))", new string[] { "memberof" });
SearchResult result = searcher.FindOne();
We got a special multivalue attribute. Let's call it ourOwnManagedBy which can contain users or groups (their DN) that manages the current group.
How can I retrieve a list of all groups that a specific user manages (with the help of managedBy and ourOwnManagedBy)?
For instance. Let's say that the user is member of the group GlobalAdministrators and that the group ApplicationAdministrators has GlobalAdministrations as a member. And finally the group MyApplication which has ApplicationAdministrators in the ourOwnManagedBy attribute.
User is member of GlobalAdministrators
GlobalAdministrators is member of ApplicationAdministrators
MyApplication got ApplicationAdministrators in ourOwnManagedBy
How do I use that information to find all groups that a specific user manages? Is it possible to do some kind of recursive check in custom attributes (that contains DNs of users and groups)?
Update
I've tried to use a directory search filter like this:
string.Format("(ourOwnManagedBy:1.2.840.113556.1.4.1941:={0})", dn);
but I might have missunderstood what 1.2.840.113556.1.4.1941 does? (MSDN page)
This is, I'm afraid, not possible to accomplish with only one LDAP query. You will have to split it into subqueries and run the each separately, which in turn will choke the domain controller if there's a lot to iterate over.
I tried to do it the way I described, and the performance was horrible, at least doing it using the available modules for .NET.
The following page says 3.1.1.3.4.4 LDAP Matching Rules (extensibleMatch) says that the LDAP_MATCHING_RULE_TRANSITIVE_EVAL that you are using does work in Windows 2008 and higher editions. If you are using 2003, it may not work.
No recursion, no idea on how it will do performance wise, may have bugs.
string user = "username";
//get domain
DirectoryEntry de = System.DirectoryServices.ActiveDirectory.Domain.GetCurrentDomain().GetDirectoryEntry();
//get users dn first
string userDN;
using (var searcher = new DirectorySearcher(de))
{
searcher.Filter = String.Format("(&(objectCategory=person)(objectClass=user)(sAMAccountName={0}))", user);
searcher.PropertiesToLoad.Add("distinguishedName");
userDN = searcher.FindOne().Properties["distinguishedName"][0].ToString();
}
//get list of all users groups
List<string> groups;
//see http://stackoverflow.com/questions/6252819/find-recursive-group-membership-active-directory-using-c-sharp
using (var searcher2 = new DirectorySearcher(de))
{
searcher2.Filter = String.Format("(member:1.2.840.113556.1.4.1941:={0})", userDN);
searcher2.SearchScope = SearchScope.Subtree;
searcher2.PropertiesToLoad.Add("distinguishedName");
SearchResultCollection src = searcher2.FindAll();
groups = (from SearchResult c in src
select c.Properties["distinguishedName"][0].ToString()).ToList();
}
//build giant search query
SearchResultCollection srcGroups;
using (var searcher = new DirectorySearcher(de))
{
string baseString = "(|{0})";
string managedbybase = "(managedBy={0})";
//I've read that you can search multivalued lists using a standard ='s.
string ourOwnManagedByBase = "(ourOwnManagedBy={0})";
StringBuilder sb = new StringBuilder();
//add user DN to list of group dn's
groups.Add(userDN);
foreach (string g in groups)
{
sb.AppendFormat(managedbybase, g);
sb.AppendFormat(ourOwnManagedByBase, g);
}
searcher.Filter = string.Format(baseString, sb.ToString());
srcGroups = searcher.FindAll();
}
I'll be honest and say that this doesn't actually work for me :) But I think it's because of the way our domain is configured. If nothing else maybe it will push you in the right direciton.
To get all groups in Active Directory i have write this code in C#. It works perfectly well as i dont need to pass any servername, OU, DC etc.
UserPrincipal current_user = UserPrincipal.Current;
PrincipalContext current_context = current_user.Context;
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
GroupPrincipal qbeUser = new GroupPrincipal(ctx);
Principal userOrGroup = qbeUser as Principal;
userOrGroup.Name = "*";
PrincipalSearcher searcher = new PrincipalSearcher(userOrGroup);
List<string> AllGroups = new List<string>();
// enumerate the results - you need to check what kind of principal you get back
foreach (Principal found in searcher.FindAll())
{
// is it a UserPrincipal - do what you need to do with that...
if (found is UserPrincipal)
{
// ......
}
else if (found is GroupPrincipal)
{
AllGroups.Add(found.Name);
//GroupPrincipal gp = found as GroupPrincipal;
//var data = gp.GetMembers();
// if it's a group - do whatever you need to do with a group....
}
}
//return AllGroups;
The problem is that it list too many groups that i dont need like
PerformanceLogUsers, SchemaAdmins, HelpServiceGroups, Telnet Clients and so on.
I only need groups like Administrator, Guests and other user created group. I have read about something like these are special group and etc etc.
Any help in this regard is highly appreciated.
AD doesn't discriminate by group relevance when performing searches. It's either a group or it isn't. However, you can specify whether or not to return security groups or distribution groups, for instance.
How your directory is currently set up, is another matter. If the groups you want and the groups you don't want are both "Security Groups", then it'll pose a problem.
One solution to that would be finding some unique attribute that your relevant groups have in common (or create one) and then filter on the existence of those.