Назад | Перейти на главную страницу

Получение сведений о пользователе из Active Directory с помощью SID

Как мне найти пользователя в моем AD, если у меня есть его SID. Я не хочу полагаться на другие атрибуты, так как я пытаюсь обнаружить изменения в них. Пример: я получаю сообщение об изменении записи пользователя, содержащее:

Message: User Account Changed:

    Target Account Name:    test12

    Target Domain:  DOMAIN

    Target Account ID:  %{S-1-5-21-3968247570-3627839482-368725868-1110}

    Caller User Name:   Administrator

    Caller Domain:  DOMAIN

    Caller Logon ID:    (0x0,0x62AB1)

    Privileges: -

Я хочу уведомить пользователя об изменении. Так что мне нужна их учетная запись из AD.

Запустите Windows PowerShell и запустите:

$strSID="S-1-5-21-500000003-1000000000-1000000003-1001"
$uSid = [ADSI]"LDAP://<SID=$strSID>"
echo $uSid

Результат должен выглядеть примерно так:

distinguishedName : {CN=John Doe,OU=Domain Admins,OU=People,OU=xxx,DC=xxx}
Path              : LDAP://<SID=S-1-5-21-500000003-1000000000-1000000003-1001>

«Способ LDAP» для этого - получить базовый объект с GUID (или SID), который будет извлекать только базовый объект и не будет иметь дополнительных данных класса. Однако из этого базового объекта вы можете получить фактическое «отличительное имя» для пользовательского объекта. Получение объекта пользователя с использованием атрибута «visibleName» вернет объект DirectoryEntry (.Net / C # / PowerShell) или объект iadsUser (VBScript) с полными данными класса и позволит вам получить любые другие данные атрибутов, которые вам нужны.

Проблема заключается в получении исходного объекта с идентификатором GUID (или SID). Некоторые источники сообщают, что вы должны преобразовать GUID строкового формата (например, {28c67c50-9778-47a4-a77a-bf56f238a0c4}) в строковое представление байтового массива (например, «\ 50 \ 7c \ c6 \ 28 \ 78 \ 97 \ a4 \ 47 \ 7a \ a7 \ bf \ 56 \ f2 \ 38 \ a0 \ c4 ") для перехода в LDAP. В соответствии с Документация Microsoft это не вариант. Достаточно простого строкового представления GUID / SID.

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

Также обратите внимание, что, хотя в документации Microsoft говорится, что допустимы несколько форматов строк GUID, единственный, который я смог успешно использовать, - это удалить символы {} -. ТАКЖЕобратите внимание, что это НЕ правильная строка "байтового массива", но просто строка GUID без специальных символов.

$strGUID = "{28c67c50-9778-47a4-a77a-bf56f238a0c4}" -replace '-|{|}',''
$guid = [ADSI]"LDAP://<GUID=$strGUID>"
$user = [ADSI]$guid.distinguishedName

Тот же процесс можно использовать для привязки SID. На странице MSDN, описывающей это, говорится, что доступно несколько форматов fstring, но наиболее распространенным будет формат s-1-5 -...-...-...-....

#Powershell
$strSID="S-1-5-21-500000003-1000000000-1000000003-1001"
$uSid = [ADSI]"LDAP://<SID=$uSid>"
$user = [ADSI]$user.distinguishedName

* ЗАПРОС *

Если вы собираетесь выполнить запрос LDAP для поиска объекта (например, сравнивая objectGUID с байтовым массивом или objectSID с байтовым массивом), то именно тогда вам нужно будет выполнить «правильный» байтовый преобразование массива. Важно отметить, что байтовый массив имеет другой порядок, чем строковое представление, поскольку он хранится как DWORD-WORD-WORD-WORD-BYTES для GUID и ДЕЙСТВИТЕЛЬНО учитывает порядок байтов. Преобразование байтового массива для SID имеет аналогичные условия.

Есть несколько различных способов выполнить преобразование, Technet имеет простой алгоритм vbScript. Вы также можете сделать что-нибудь более интересное с C # / VB.Net с помощью System.Guid или с помощью простого скрипта в PowerShell (нужно любить PowerShell!):

#Powershell
#   Creates a new System.GUID object from the supplied string.
#   Only need for this example.
$guid = [system.guid]"{28c67c50-9778-47a4-a77a-bf56f238a0c4}" 
$out=""
#Formats the array of integers as a backslash-delimited string of Hex values
$guid.ToByteArray() | %{ $out += $("\{0:x2}" -f $_) }

После этого вы сможете запросить объект, используя стандартный фильтр LDAP:

(&(objectClass=User)(objectGUID=\50\7c\c6\28\78\97\a4\47\a7\7a\bf\56\f2\38\a0\c4))

... или что-то еще, что вы можете запросить. Это должно работать и для SID.

ХОРОШО. Я нашел способ сделать это через Active Directory. Вот код для полноты:

REM Converts the SID into a format, that can be processed by ADSI or WMI
Function NormalizeSid(strSidToNormalize)
  Dim regEx,strReplace
  strReplace=""
  ' Create regular expression.
  Set regEx = New RegExp
  regEx.Global  = True
  regEx.Pattern = "(%|{|})"
  regEx.IgnoreCase = True

  ' Make replacement.
  NormalizeSid = regEx.Replace(strSidToNormalize, strReplace)
End Function

REM Searches for a SID the in the Message that was passed as argument
REM SID returned will be of the  form %{S-1-5-21-3968247570-3627839482-368725868-1110}
REM NOTE: Neither WMI nor ADSI will accept this. Use NormalizeSid like in FindUser
Function FindSidInMessage(Message)
    Dim strAccountRegex
    Dim objRegex
    Dim objMatch
    Dim strSID

    strAccountRegex = "(\%\{S\-[,0-9,\-]*\})"
    Set objRegex    = new RegExp
    objRegex.Pattern= strAccountRegex

    for each objMatch in objRegex.Execute(Message)
            REM Wscript.StdOut.writeLine "Found an Account ID: " & objMatch.value
            strSID=objMatch.value
    next

    FindSidInMessage=strSID
End Function 

REM Searches Directory for the User matching the SID passed as parameter
Function FindUser(userSID)
    Dim normalizedSID
    Dim objUser

    normalizedSID=NormalizeSid(userSID)
    Wscript.Echo "SID after escaping: " & normalizedSID

    Wscript.StdOut.writeLine "Querying AD to retrieve user-data" 
    Set objUser = GetObject("LDAP://<SID="& normalizedSID & ">")
    FindUser=objUser.EmailAddress
End Function

Надеюсь, это будет полезно другим.

Используйте PS:

$SID = "S-X-X-XX-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-XXXX"
Get-ADObject -IncludeDeletedObjects -Filter * -Properties * | where{$_.objectSid -eq $SID}