How to find all groups in ActiveDirectory where th

2019-01-15 21:35发布

问题:

Currently i'd like to find all groups within the Active Directory where the current user has the right WriteProperty.

The problem is that i can find all groups where the user directly is inserted, but when the user is within a group and that group has write access it won't show up. I thought that setting the booleans of GetAccessRules() would help here, but it doesn't.

So here is the code i already have:

var identity = WindowsIdentity.GetCurrent().User;
var allDomains = Forest.GetCurrentForest().Domains.Cast<Domain>();

var allSearcher = allDomains.Select(domain =>
    {
        var searcher = new DirectorySearcher(new DirectoryEntry("LDAP://" + domain.Name));
        //Apply some filter to focus on only some specfic objects
        searcher.Filter = "(&(objectClass=group)(name=*part_of_group_name*))";
        return searcher;
    });

var itemsFound = allSearcher
    .SelectMany(searcher => searcher.FindAll()
        .Cast<SearchResult>()
        .Select(result => result.GetDirectoryEntry()));

var itemsWithWriteAccess = itemsFound
    .Where(entry => entry.ObjectSecurity.GetAccessRules(true, true, typeof(SecurityIdentifier))
        .Cast<ActiveDirectoryAccessRule>()
        .Where(rule => rule.IdentityReference == identity)
        .Where(rule => (rule.ActiveDirectoryRights & ActiveDirectoryRights.WriteProperty) == ActiveDirectoryRights.WriteProperty)
        .Count() > 0);

foreach (var item in itemsWithWriteAccess)
{
    Debug.Print(item.Name);
}

回答1:

After a long time and the help of Harvey through this question i finally found a good working solution.

As already explained by Harvey it can be a little difficult to really further understand what you'll get back in entry.Properties["allowedAttributesEffective"].Value. But for normal purposes all you have to check for a write permission is that this field is simply not null.

Here is the sample code:

// (replace "part_of_group_name" with some partial group name existing in your AD)
var groupNameContains = "part_of_group_name";

var identity = WindowsIdentity.GetCurrent().User;
var allDomains = Forest.GetCurrentForest().Domains.Cast<Domain>();

var allSearcher = allDomains.Select(domain =>
{
    var searcher = new DirectorySearcher(new DirectoryEntry("LDAP://" + domain.Name));

    // Apply some filter to focus on only some specfic objects
    searcher.Filter = String.Format("(&(objectClass=group)(name=*{0}*))", groupNameContains);
    return searcher;
});

var directoryEntriesFound = allSearcher
    .SelectMany(searcher => searcher.FindAll()
        .Cast<SearchResult>()
        .Select(result => result.GetDirectoryEntry()));

var allowedTo = directoryEntriesFound.Select(entry =>
    {
        using (entry)
        {
            entry.RefreshCache(new string[] { "allowedAttributesEffective" });
            var rights = entry.Properties["allowedAttributesEffective"].Value == null ? "read only" : "write";
            return new { Name = entry.Name, AllowedTo = rights };
        }
    });

foreach (var item in allowedTo)
{
    var message = String.Format("Name = {0}, AllowedTo = {1}", item.Name, item.AllowedTo);
    Debug.Print(message);
}