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

Получите OU верхнего уровня от пользователя AD через Powershell

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

Я пытаюсь получить OU верхнего уровня, в котором находится пользователь, и любые OU более низкого уровня. Основная проблема заключается в том, что у нас есть несколько сайтов, некоторые из которых имеют несколько уровней OU для учетных записей пользователей (ou=doctors,ou=Users,ou=Site,dc=example,dc=com), а также на некоторых сайтах с одним OU (ou=Users,ou=Site,dc=example,dc=com). Я использовал приведенный ниже сценарий, чтобы получить путь DN, разделить его и перестроить в обратном порядке с использованием последних трех частей. Может ли кто-нибудь увидеть какие-либо проблемы с этим. Что-то в этом просто не так ...

$user = Get-ADUser CKnutson
$user.DistinguishedName
# Returns: CN=Cory Knutson,OU=IT,OU=Users,OU=Site,DC=example,DC=com

$split = $user.DistinguishedName.Split(',')
$path = "$($split[-3]),$($split[-2]),$($split[-1])"

Write-Host $path
# Returns: OU=Site,DC=example,DC=com

Просто хочу сказать, что конечной целью для меня было получить путь к «Disabled» OU, который у нас есть внутри каждого из «Site» OU. Таким образом, мой сценарий мог переместить объект при отключении учетной записи в нужное место в OU верхнего уровня этого сайта (OU=Disabled,OU=Site,DC=example,DC=com).

Может ли кто-нибудь увидеть какие-либо проблемы с этим.

Да, я вижу две неотложные проблемы, которые могут возникнуть в результате вашего нынешнего подхода.


1. Экранированные запятые

Рассмотрим подразделение с запятой в имени, например: OU=Users\, Admin,DC=corp,DC=example

Ваше использование string.Split() не будет заботиться о escape-последовательности, и вы получите:

 Admin,DC=corp,DC=example

Использовать -split Оператор регулярного выражения с ретроспективным просмотром, чтобы игнорировать экранированные запятые:

$parts = $user.DistinguishedName -split '(?<!\\),'

2. Портативность

Ваш код предполагает, что часть NC DN (например, DC=example,DC=com), всегда будет шириной всего 2 метки. Это означает, что ваш код выйдет из строя, если вы используете его в сценариях, которые, возможно, захотите использовать в других доменах / средах.

Я брал каждую часть справа налево, пока не нашел без в DC Префикс RDN:

$topParts = foreach($part in $parts[-1..-$parts.Length]){
    $part
    if($part -notlike 'DC=*'){
        break
    }
}
# Remember to reverse the RDNs again
$path = $topParts[-1..-$topParts.Length] -join ','

На мой взгляд, проще использовать COM-объект Pathname и просто запросить родительский элемент DN. Вы можете поместить это в while цикл, чтобы получить иерархию объекта. Пример использования моего ADName модуль:

$dn = Get-ADUser user | Select-Object -ExpandProperty DistinguishedName
$parent = $dn | Get-ADName -Format Parent
while ( $parent -like "OU=*" ) {
  $parent
  $parent = $parent | Get-ADName -Format Parent
}

Пример вывода:

OU=Level 3,OU=Level 2,OU=Level 1,DC=fabrikam,DC=com
OU=Level 2,OU=Level 1,DC=fabrikam,DC=com
OU=Level 1,DC=fabrikam,DC=com

Так вы после DN пути к аккаунту? Вы можете сделать это с помощью регулярного выражения, использующего квалификатор (?) Ungreedy. Разделения нет, поэтому использование экранированных запятых не является проблемой.

"CN=Cory Knutson,ou=doctors,ou=Users,ou=Site,dc=example,dc=com" -match ".+?,(OU=.+)"
$matches[1]
ou=doctors,ou=Users,ou=Site,dc=example,dc=com

"CN=Knutson\, Cory,ou=doctors,ou=Users,ou=Site,dc=example,dc=com" -match ".+?,(OU=.+)"
$matches[1]
ou=doctors,ou=Users,ou=Site,dc=example,dc=com

"CN=Cory Knutson,ou=Site,dc=example,dc=com" -match ".+?,(OU=.+)"
$matches[1]
ou=Site,dc=example,dc=com

редактировать
Мне было непонятно из фразы the top level OU that a user is in, and any lower level OUs. Вы также можете сделать это:

$dn = "CN=Cory Knutson,ou=doctors,ou=Users,ou=Site,dc=example,dc=com"
$last = ($dn.toUpper()).lastIndexOf("OU=")
$dn.substring($last)
ou=Site,dc=example,dc=com