通过 Powershell 从 AD 用户获取顶级 OU

通过 Powershell 从 AD 用户获取顶级 OU

我问这个问题主要是想问是否有更好的方法来完成我正在做的工作。我还想知道是否有人认为通过这种方式获取这些信息存在问题。

我正在尝试获取用户所在的顶级 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

简单说一下,最终目标是让我获取每个“站点”OU 内部的“已禁用”OU 的路径。这样我的脚本就可以在禁用帐户时将对象移动到该站点的顶级 OU 中的正确位置(OU=Disabled,OU=Site,DC=example,DC=com)。

答案1

有谁看到过这样做有什么问题吗?

是的,我发现您当前的方法可能会出现两个直接的问题。


1. 转义逗号

考虑名称中带有逗号的 OU,例如:OU=Users\, Admin,DC=corp,DC=example

您的使用string.Split()不会关心转义序列,最终会得到:

 Admin,DC=corp,DC=example

使用-split带有后视功能的正则表达式运算符来确保忽略转义的逗号:

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

2.可移植性

您的代码假设 DN 的 NC 部分(例如DC=example,DC=com)将始终只有 2 个标签宽。这意味着如果您在可能想要在其他域/环境中重复使用的脚本中使用它,您的代码将会失败。

我会从右到左抓住每个部分,直到找到一个没有RDNDC前缀:

$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 ','

答案2

我认为使用 Pathname COM 对象并直接请求 DN 的父级更简单。您可以将其放入循环中while以获取对象的层次结构。使用我的示例广告名称模块:

$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

答案3

所以您是在寻找帐户路径的 DN?您可以使用使用 (?) 非贪婪限定符的正则表达式来执行此操作。没有拆分,因此转义逗号不是问题。

"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

相关内容