Why does Principal.IsMemberOf () return false for some groups?

Why is Principal.IsMemberOf(GroupPrincipal)

( MSDN ) returning negative for the group Domain Computers

in the following test?

[TestMethod]
public void DomainComputerTest()
{
    var distinguishedName = "CN=MyMachine,DC=SomeDomain,DC=local";
    using( var pc = new PrincipalContext( ContextType.Domain, "SomeDomain.local", "UserName", "Password" ) )
    using( var computer = ComputerPrincipal.FindByIdentity( pc, IdentityType.DistinguishedName, distinguishedName ) )
    {
        Assert.IsNotNull( computer );
        // Get the groups for the computer.
        var groups = computer.GetGroups().Cast<GroupPrincipal>();
        foreach( var group in groups )
        {
            // Immediately turn around and test that the computer is a member of the groups it returned.
            Assert.IsTrue( computer.IsMemberOf( group ), "Computer is not member of group {0}", group.Name );
        }
    }
}

      

Result message: Assert.IsTrue failed. The computer is not a member of the Domain Computers group.

The computer is indeed a member of the Domain Computers group, which correctly returns the GetGroups () method. In fact, if you try to add a computer to the group, a PrincipalExistsException is thrown.

I can reproduce the same behavior with users and the Domain Users group. Is it because groups are the main groups? Is it because these are the default groups?

Edit to add: we're using .NET 4.5.1.

+3


source to share


3 answers


This seems to be a problem that has always existed.

Every question I have found with your same problem has gone unanswered. I couldn't find anything that said it was logged as a bug, but it seems to exist since .NET 3.5.

I tried to get your example back true

(changed the information for my work domain of course). Regardless, he returned false

. Decompiling the class Principal

in dotPeek only gave a guess. Going through and configuring Visual Studio to step into the .NET framework was a bust because it wouldn't go into the required methods. I can step into other .NET framework code, but nothing on Principal

. Not sure if these methods are tag related SecurityCriticalAttribute

or not. It would be nice to confirm this.

My suggestion for you is to log this as an error and, at the same time, take a different route to determine if the computer is a member. My test group.Members

actually contained a computer.

I got the same problem with .NET 3.5, 4.0, 4.5, 4.5.1



Here are some links:

Work - GroupPrincipal.IsMemberOf always returns false

A 2010 MSDN blog post with a comment that had the same problem as you.

NOTE. I usually didn't answer that way, but since every question I found with this problem had 0 answers or a workaround, I thought it would be helpful for future readers to see some kind of "answer" to this problem.

+4


source


For other developers who find this, here's what I did. This is a simplified version of the code I unwrapped, but from the looks of it I'm guessing the problem is with the primary group relationship. This may not be true , but so far it works for us.

You can get a copy DirectoryEntry

for ComputerPrincipal

like this.

var entry = (DirectoryEntry)computerPrincipal.GetUnderlyingObject();

      

And I am using this extension method to check the relationship to the main group.



public static bool IsPrimaryGroupFor( this GroupPrincipal group, DirectoryEntry target )
{
    // .Value will return an int like "123", which is the last part of the group SID
    var id = target.Properties[ "primaryGroupID" ].Value.ToString();
    // strip the account domain SID from the group SID.
    var groupId = group.Sid.Value.Remove( 0, group.Sid.AccountDomainSid.Value.Length + 1 );

    // If the 
    return id.Equals( groupId, StringComparison.OrdinalIgnoreCase );
}

      

We are syncing AD group memberships, so we found this issue in code like the following:

public void AddComputerToGroups( ComputerPrincipal computer, ICollection<GroupPrincipal> groups )
{
    var directoryEntry = (DirectoryEntry)computer.GetUnderlyingObject();

    foreach( var principal in groups.Where(g=> !computer.IsMemberOf(g) )
    {
        principal.Members.Add( computer );
        principal.Save(); // Exception thrown because computer already existed in the primary group.
    }
}

      

+1


source


So, I believe you may run into the same problem as me, but for a computer account, not a user account.

Principal.IsInRole ("AD Group Name") always returns false, no exceptions

Make sure that the account running the code has read permissions on both containers Computers

and Users

on the domain where the computer causing the error / experiencing the problem is registered.

0


source







All Articles