Я задаю этот вопрос в основном для того, чтобы спросить, есть ли лучший способ сделать то, что у меня есть. Я также хотел бы знать, не видит ли кто-нибудь проблем с получением этой информации таким образом.
Я пытаюсь получить 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
).
Может ли кто-нибудь увидеть какие-либо проблемы с этим.
Да, я вижу две неотложные проблемы, которые могут возникнуть в результате вашего нынешнего подхода.
Рассмотрим подразделение с запятой в имени, например: OU=Users\, Admin,DC=corp,DC=example
Ваше использование string.Split()
не будет заботиться о escape-последовательности, и вы получите:
Admin,DC=corp,DC=example
Использовать -split
Оператор регулярного выражения с ретроспективным просмотром, чтобы игнорировать экранированные запятые:
$parts = $user.DistinguishedName -split '(?<!\\),'
Ваш код предполагает, что часть 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