Complex Search Filtering with PrincipalSearcher

6.1k Views Asked by At

I am searching in Active Directory for specific SamAccountName values using the PrincipalSearcher object because I want to return UserPrincipal's. I was wondering how I can apply two filters to that search; one being the beginning of the account name starts with xx and the other being it does not end with _c.

Currently I can search for all results beginning with xx by using xx* but I cannot figure out how to add another search term or even apply a search term for does not equal. This is what I'm currently working with.

protected override void RunTests()
{
    using (PrincipalContext context = new PrincipalContext(ContextType.Domain, "NAME", "OU=OUName",OU=name,DC=name,DC=net"))
    {
        UserPrincipal searchTemplate = new UserPrincipal(context);
        searchTemplate.Enabled = true;
        searchTemplate.SamAccountName = "xx*";

        PrincipalSearcher search = new PrincipalSearcher(searchTemplate);

        var principals = search.FindAll();
        int total = principals.Count();            

        int numInvalidUsers = RunChecks(principals, new Check[]{ 
            Check1    
            , Check2
            , Check3
        });

        Score = numInvalidUsers == 0 ? 1 : 0;
    }
}

What I'm thinking is that I need to add another parameter to the searchTemplate.SamAccountName, I'm just not sure how.

Update: I was talking to someone on Reddit who was giving me some helpful suggestions but this user has gone dark. It seems like the most common suggestion is to somehow implement LDAP filters. So if anyone knows how to implement those while still returning principal objects that would be very helpful.

1

There are 1 best solutions below

0
On BEST ANSWER

So I've finally answered this question with the help of a Reddit user from this post

Because of how I have my program setup ideally I needed to return principal objects although some casting or converting was available. The solution for returning principals objects with some extra filtering was using a LINQ statement to filter the returned results even more.

To incorporate the LINQ statement all I needed to do was alter one line, the line where I search.FindAll(); which does as follows,

var principals = search.FindAll().Where(p => !p.SamAccountName.EndsWith("_c", StringComparison.OrdinalIgnoreCase)).ToList();

Because the initial filtering is done to find all xx* I only needed to remove the accounts ending in _c with this statement, however there are lots of filtering options available with LINQ.

The user on Reddit also offered me some other suggestions since LINQ can be slow if you have a large number of returned results need to be filtered but I went for the quicker and easier answer. If you would like to see those suggestions just follow the link to the Reddit post.