LDAP - использование подстановочного знака в фильтре MemberOf - PullRequest
0 голосов
/ 21 марта 2019

Мне нужно получить всех пользователей и их группы из определенной категории.

Примеры пользователей:

user  | memberof
user1 | CN=group_1,OU=Groupes,OU=CR 1,DC=zcam,DC=ztech
user1 | CN=group_2,OU=Groupes,OU=CR 1,DC=zcam,DC=ztech
user2 | CN=group_2,OU=Groupes,OU=CR 1,DC=zcam,DC=ztech
user3 | CN=group_3,OU=Groupes,OU=CR 2,DC=zcam,DC=ztech

Мне нужно получить каждого пользователя, где memberof содержит OU=Groupes,OU=CR 1,DC=zcam,DC=ztech (user1 и user2 из моего примера)

Следуя этому документу (https://docs.microsoft.com/fr-fr/windows/desktop/ADSI/search-filter-syntax) Я попробовал следующий синтаксис:

DirectoryEntry ldap = new DirectoryEntry("LDAP://xxx.xxx.xxx.xxx");
using (DirectorySearcher searcher = new DirectorySearcher(ldap))
{
    // Works but return everything
    searcher.Filter = "(&(objectClass=user)(memberof=*))";

    // Works but only for one group
    searcher.Filter = "(&(objectClass=user)(memberof=CN=group_1,OU=Groupes,OU=CR 1,DC=zcam,DC=ztechh))";

    // Doesn't work because searcher.FindAll().Count returns 0
    searcher.Filter = "(&(objectClass=user)(memberof=*,OU=Groupes,OU=CR 1,DC=zcam,DC=ztechh))";

    // searcher.FindAll().Count returns 0
    foreach (SearchResult result in searcher.FindAll()) 
    {
        [...]
    }

После этого (https://community.servicenow.com/community?id=community_question&sys_id=00d29fa1db101fc01dcaf3231f96197f) я пытался изменить подстановочный знак * на %, но это не изменило результат.

Ответы [ 3 ]

1 голос
/ 21 марта 2019

Мне нужно получить каждого пользователя, в котором memberof содержит OU = группы, OU = CR 1, DC = zcam, DC = ztech (user1 и user2 из моего примера)

Если японять правильно, я думаю, что предложение подводит итог того, что вы пытаетесь сделать.Вы хотите найти всех пользователей, которые являются членами любой группы в этом подразделении.

Active Directory не позволяет использовать подстановочные знаки для любого атрибута, который принимает distinguishedName.Это включает в себя member и memberOf.Таким образом, единственный способ сделать это состоит из двух шагов:

  1. Найти distinguishedName всех групп в этом подразделении.
  2. Поиск всех пользователей, у которых memberOf включает одного иззначения, найденные в шаге 1.

Примерно так (я не проверял это на AD, поэтому вам может потребоваться настроить его):

var groupSearch = new DirectorySearcher(
    new DirectoryEntry("LDAP://OU=Groupes,OU=CR 1,DC=zcam,DC=ztech"), //notice the OU
    "(objectClass=group)");

//if you don't do this, it will return *every* attribute, which is slower
groupSearch.PropertiesToLoad.Add("distinguishedName");

//build a user query with all the groups
var userFilter = new StringBuilder("(&(objectClass=user)(|");
using (var results = groupSearch.FindAll()) {
    foreach (SearchResult result in results) {
        userFilter.Append($"(memberOf={result.Properties["distinguishedName"][0]})");
    }
}
userFilter.Append(")");

var userSearch = new DirectorySearcher(
    new DirectoryEntry("LDAP://DC=zcam,DC=ztech"),
    userFilter.ToString());

//userSearch.PropertiesToLoad.Add(""); //add only the attributes you need to make it quicker

using (var results = userSearch.FindAll()) {
    foreach (SearchResult result in results) {
        //do something
    }
}

Обратите внимание, что этонайдет только прямых членов этих групп.Он не вернет пользователей, которые находятся во вложенных группах (когда пользователь находится в группе, которая является членом одной из этих групп).Если вы хотите этого, вы можете настроить фильтр так, чтобы он включал специальный флаг, который предписывает AD выполнять рекурсивный поиск:

userFilter.Append($"(memberOf:1.2.840.113556.1.4.1941:={result.Properties["distinguishedName"][0]})");

В зависимости от вашего домена вам может потребоваться знать две вещи:

  1. Это не вернет пользователей, которые имеют одну из этих групп в качестве своей основной группы, так как это отношение не сохраняется с использованием member / memberOf.
  2. Если в этих группах есть члены из внешних доверенныхдоменов, тогда вы в конечном итоге найдете объекты Foreign Security Principal вместо их реальных пользовательских объектов.Это совсем другое дело, если это проблема для вас.

Я написал несколько статей на эту тему, если вам интересно.Начните с этого: Active Directory: что делает члена участником?

0 голосов
/ 28 марта 2019

Наконец-то я нашел другой способ сделать. Фактически, это свойство OU=CR 1 в memberof соответствует разделению в моей AD. Поэтому я просто фильтрую вот так:

DirectoryEntry ldap = new DirectoryEntry("LDAP://xxx.xxx.xxx.xxx");
using (DirectorySearcher searcher = new DirectorySearcher(ldap))
{
    searcher.Filter = "(&(objectClass=user)(division=CR 1))";

    foreach (SearchResult result in searcher.FindAll()) 
    {
        [...]
    }

Спасибо всем за помощь.

0 голосов
/ 21 марта 2019

отредактированная версия; продлить на все ваши group_X

(
&(objectClass=user)
(|(memberof=CN=group_1,OU=Groupes,OU=CR 1,DC=zcam,DC=ztechh)
(memberof=CN=group_2,OU=Groupes,OU=CR 1,DC=zcam,DC=ztechh))
)
...