LDAP — Использование подстановочного знака в элементе фильтра

#c# #active-directory #ldap #wildcard #directorysearcher

#c# #active-directory #ldap #подстановочный знак #directorysearcher

Вопрос:

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

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

 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://learn.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 = "(amp;(objectClass=user)(memberof=*))";

    // Works but only for one group
    searcher.Filter = "(amp;(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 = "(amp;(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_questionamp;sys_id=00d29fa1db101fc01dcaf3231f96197f ) Я попытался изменить подстановочный знак * на % , но это не изменило результат.

Комментарии:

1. «Все пользователи и их группы» — то есть вы хотите, чтобы поиск возвращал как пользовательские , так и групповые объекты?

2. Вместо этого используйте System.DirctoryServices.AccountManagement пространство имен, это намного проще — learn.microsoft.com/en-us/dotnet/api /…

Ответ №1:

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

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

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("(amp;(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. Если в этих группах есть участники из внешних доверенных доменов, то в конечном итоге вы обнаружите внешние объекты участника безопасности вместо их реальных пользовательских объектов. Это совсем другая вещь, с которой нужно иметь дело, если это проблема для вас.

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

Ответ №2:

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

 (
amp;(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))
)
  

Ответ №3:

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

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

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

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