#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
. Итак, единственный способ сделать это в два этапа:
- Найдите
distinguishedName
все группы в этом подразделении. - Выполните поиск всех пользователей, у которых
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]})");
В зависимости от вашего домена, возможно, вам захочется знать о двух вещах:
- Это не вернет пользователей, у которых одна из этих групп является основной, поскольку эта связь не сохраняется с использованием
member
/memberOf
. - Если в этих группах есть участники из внешних доверенных доменов, то в конечном итоге вы обнаружите внешние объекты участника безопасности вместо их реальных пользовательских объектов. Это совсем другая вещь, с которой нужно иметь дело, если это проблема для вас.
Я написал несколько статей на эту тему, если вам интересно. Начните с этого: 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())
{
[...]
}
Спасибо всем за вашу помощь.