Showing posts with label find groups for user. Show all posts
Showing posts with label find groups for user. Show all posts

Sunday, 16 September 2018

Getting groups (including nested) for AD user - AccountManagement vs DirectorySearcher vs WindowsIdentity


Testing to see what is fastest to get all groups (i.e. include nested groups, not just top level groups) => WindowsIdentity appears to easily be the fastest, followed by directorysearcher and then accountManagement.

Over 50 tests:
WindowsIdentity average of .3 seconds
DirectorySearcher average of  1.2 seconds
AccountManagement average of 2.3 seconds


Suspect there is a reason why not to use WindowsIdentity because it is so much faster, but not sure what its restrictions are yet.



    class Program
    {
        static AccountManagementService ams = new AccountManagementService();
        static DirectorySearcherService dss = new DirectorySearcherService();
        static WindowsIdentityService wis = new WindowsIdentityService();

        static void Main(string[] args)
        {
            var userId = ConfigurationManager.AppSettings["UsernameToFind"];
            var iterations = 50;
            var amsTimeTaken = new List<long>();
            var dssTimeTaken = new List<long>();
            var wisTimeTaken = new List<long>();

            for (var i = 0; i < iterations; i++)
            {
                amsTimeTaken.Add(CallAms(userId));
                dssTimeTaken.Add(CallDss(userId));
                wisTimeTaken.Add(CallWis(userId));
                Console.WriteLine($"iteration {i} done");
            }

            Console.WriteLine($"AMS average is {(amsTimeTaken.Sum() / iterations)}");
            Console.WriteLine($"DSS average is {(dssTimeTaken.Sum() / iterations)}");
            Console.WriteLine($"WIS average is {(wisTimeTaken.Sum() / iterations)}");

            Console.ReadKey();
        }

        static long CallAms(string userId)
        {
            var watch = System.Diagnostics.Stopwatch.StartNew();
            ams.Lookup(userId);
            watch.Stop();
            return watch.ElapsedMilliseconds;
        }
        static long CallDss(string userId)
        {
            var watch = System.Diagnostics.Stopwatch.StartNew();
            dss.Lookup(userId);
            watch.Stop();
            return watch.ElapsedMilliseconds;
        }
        static long CallWis(string userId)
        {
            var watch = System.Diagnostics.Stopwatch.StartNew();
            wis.Lookup(userId);
            watch.Stop();
            return watch.ElapsedMilliseconds;
        }
    }


    public class WindowsIdentityService
    {
        public List<string> Lookup(string userName)
        {
            List<string> result = new List<string>();
            WindowsIdentity wi = new WindowsIdentity(userName);

            foreach (IdentityReference group in wi.Groups)
            {
                try
                {
                    result.Add(group.Translate(typeof(NTAccount)).ToString().Replace("HIQ\\",""));
                }
                catch (Exception ex) { }
            }
            return result;
        }
    }

    public class AccountManagementService
    {
        string _domain = ConfigurationManager.AppSettings["AmsDomain"];
        public List<string> Lookup(string userId)
        {
            var output = new List<string>();

            using (var ctx = new PrincipalContext(ContextType.Domain, _domain))
            {
                using (var user = UserPrincipal.FindByIdentity(ctx, userId))
                {
                    if (user != null)
                    {
                        output = user.GetAuthorizationGroups() //this returns a collection of principal objects
                            .Select(x => x.SamAccountName)
                            .ToList();
                    }
                }
            }
            return output;
        }
    }


    public class DirectorySearcherService
    {

        public List<string> Lookup(string userId)
        {
            List<string> userNestedMembership = new List<string>();
           
            DirectoryEntry domainConnection = new DirectoryEntry();
            domainConnection.Path = ConfigurationManager.AppSettings["DssDomainPath"];

            DirectorySearcher samSearcher = new DirectorySearcher();
           
            samSearcher.SearchRoot = domainConnection;
            samSearcher.Filter = "(samAccountName=" + userId + ")";
            samSearcher.PropertiesToLoad.Add("displayName");

            SearchResult samResult = samSearcher.FindOne();

            if (samResult != null)
            {
                DirectoryEntry theUser = samResult.GetDirectoryEntry();
                theUser.RefreshCache(new string[] { "tokenGroups" });

                foreach (byte[] resultBytes in theUser.Properties["tokenGroups"])
                {
                    System.Security.Principal.SecurityIdentifier mySID = new System.Security.Principal.SecurityIdentifier(resultBytes, 0);

                    DirectorySearcher sidSearcher = new DirectorySearcher();

                    sidSearcher.SearchRoot = domainConnection;
                    sidSearcher.Filter = "(objectSid=" + mySID.Value + ")";
                    sidSearcher.PropertiesToLoad.Add("distinguishedName");
                    sidSearcher.PropertiesToLoad.Add("name");

                    SearchResult sidResult = sidSearcher.FindOne();

                    if (sidResult != null)
                    {
                        userNestedMembership.Add((string)sidResult.Properties["name"][0]);
                    }
                }
               
            }
            else
            {
                Console.WriteLine("The user doesn't exist");
            }

            return userNestedMembership;

        }

    }