Wednesday, August 1, 2007

Getting Active Directory Group Membership in .NET 3.5

I have previously covered pretty extensively the options for getting a user's group membership in Active Directory or ADAM (soon to be Active Directory LDS (Lightweight Directory Services)) here on the blog, in the forum, and in the book.  However, there is a new option for users of .NET 3.5 that should be of interest.

The Directory Services group at Microsoft has released in beta form a new API for dealing with a lot of the common things we need to do with users, groups, and computers in Active Directory, ADAM, and the local machine.  This API is called System.DirectoryServices.AccountManagement (or SDS.AM).  Here is a simple example of how to get a users groups (including nested, and primary):

static void Main(string[] args)
    PrincipalContext ctx = new PrincipalContext(ContextType.Domain);

    using (ctx)
        Principal p = Principal.FindByIdentity(ctx, "ryandunn");

        using (p)
            var groups = p.GetGroups();
            using (groups)
                foreach (Principal group in groups)
                    Console.WriteLine(group.SamAccountName + "-" + group.DisplayName);


That's not too bad - in fact, it looks worse than it is because I am trying to make sure everything is wrapped in a 'using' statement where necessary.  The equivalent code to do this would be many times more (using DsCrackNames or LDAP searches) and would yield far less information being returned (just the DN in most cases).

Over the next few weeks and months, I intend to dig more deeply into this namespace and put some samples up here for everyone.  This is just a taste for now, but it should show you how powerful this namespace really is.

 *Updated to fix CSS renderings in Google Reader

Thursday, April 5, 2007

Transitive Link Value Filter for SP1

If hot-LDAP-filter-action is your thing, but you were let down in my last post since it required SP2 and Longhorn, then this should get you all hot and bothered again:  Hotfix for SP1.

I know, it's a hotfix - which means you have to contact Microsoft to get it.  But if you want to take advantage of the new LDAP_MATCHING_RULE_IN_CHAIN without upgrading to SP2 or Longhorn, then this is it.

Tuesday, September 20, 2005

Expanding Group Membership in .NET 2.0

We have some new options available to us in .NET 2.0 to discover a user’s group membership.  I ran into an entry on Dominick’s blog about expanding group membership using the new IdentityReference class.  This technique assumes you can get a WindowsIdentity for the user you wish to expand.  I previously covered two other techniques here and here.

I use yet another 3rd technique similar to this in the book that actually takes the ‘tokenGroups’ attribute for any user in AD and expands the membership using the IdentityReference.  It is the most elegant of the 3 methods, IMO.

One note on Dominick’s code: a way to further optimize this is to use .Translate on the IdentityReferenceCollection so that the call is batched under the hood.

Wednesday, March 9, 2005

Enumerating Token Groups (tokenGroups) in .NET

The 'tokenGroups' attribute is a calculated attribute (we must use .RefreshCache() to get it) that exists for all users in Active Directory.  It contains a collection of SIDs for each security group that the user is a member of.  The advantage of this collection is that it only contains security groups, and it contains all security groups including nested and primary groups.  The disadvantage is that it is a little bit more complicated to do anything with this attribute.

There are two methods of enumerating the tokenGroups and returning the security groups for a user.  The first method is to use DsCrackNames on collection of SIDs and have the Win32 api return the groups in your choice of name formats.  This is a powerful and fast method, but you will need to rely on p/invoke and setting up some structures.  The other method is to build an LDAP query filter and then use the DirectorySearcher to find all the groups.  This method returns a SearchResult for each group which means you could additionally retrieve more information about the group as well as does not require any p/invoke code, so it is usually more palatable for users.

Here are the steps we would take to enumerate the groups:

1.Create a DirectoryEntry to serve as the SearchRoot for our DirectorySearcher
2.Bind to our user object with another DirectoryEntry and pull the 'tokenGroups' attribute
3.Iterate over each SID in the tokenGroup and build the LDAP filter (formatting the SID bytes correctly)
4.Search the Directory with the constructed filter
5.Iterate each returned SearchResult for your information.

Here is a sample VS.NET solution in C# that demonstrates this:  Enumerate Token Groups

The code for how to do this using DsCrackNames I will leave for another post. (UPDATESee here for DsCrackNames)

Updated 3/16/2005 - I realize that not everyone feels like digging around to find their GUID to use this sample (I initially created it for someone that only had their GUID), so I revisited this so it also accepts the user's login name as well. Download the updated example

Updated 7/13/2005 – Reader “Daniel” was kind enough to point out some errors that I had in my code.  I seem to have deleted my original code at some point and was recreating it from scratch… so I apparently forgot some very key things in the code.  My bad!  I should have tested it better.  These errors have been corrected.