Obter a UO de nível superior de um usuário do AD

2

Eu estou fazendo esta pergunta principalmente para perguntar se existe uma maneira melhor de fazer o que eu tenho trabalhando. Eu também gostaria de saber se alguém vê algum problema em obter essa informação dessa maneira.

Estou tentando obter a UO de nível superior em que um usuário está e as UOs de nível inferior. O principal problema é que temos vários sites, alguns dos quais têm várias camadas de UOs para contas de usuário ( ou=doctors,ou=Users,ou=Site,dc=example,dc=com ) e alguns sites que possuem apenas uma UO ( ou=Users,ou=Site,dc=example,dc=com ). Eu usei o script abaixo para obter o caminho DN, dividi-lo e reconstruí-lo para trás com as três últimas partes. Alguém pode ver qualquer problema em fazer isso dessa maneira. Algo sobre isso parece errado ...

$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

Apenas para declarar, o objetivo final era que eu conseguisse o caminho para a UO "Desativada" que temos dentro de cada UO "Site". Assim, meu script poderia mover o objeto ao desativar a conta no local adequado, na UO de nível superior desse site ( OU=Disabled,OU=Site,DC=example,DC=com ).

    
por Cory Knutson 25.10.2017 / 00:48

3 respostas

2

Can anyone see any issues with doing it this way.

Sim, vejo dois problemas imediatos que podem surgir da sua abordagem atual.

1. Vírgulas com escape

Considere uma UO com uma vírgula em seu nome, como: OU=Users\, Admin,DC=corp,DC=example

Seu uso de string.Split() não se importa com a sequência de escape e você acaba com:

 Admin,DC=corp,DC=example

Use o operador -split regex com um lookbehind para ter certeza de que você ignorou aspas:

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

2. Portabilidade

Seu código assume que a parte NC do DN (por exemplo, DC=example,DC=com ) sempre terá apenas 2 rótulos de largura. Isso significa que seu código falhará se você usá-lo em scripts que você queira reutilizar em outros domínios / ambientes.

Eu pegaria cada parte, da direita para a esquerda até encontrar um sem o prefixo 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 ','
    
por 25.10.2017 / 15:44
0

Na minha opinião, é mais simples usar o objeto COM do Pathname e simplesmente pedir o pai do DN. Você pode colocar isso em um loop while para obter a hierarquia do objeto. Exemplo usando meu módulo 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
}

Exemplo de saída:

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
    
por 27.10.2017 / 21:49
0

Então, você está após o DN do caminho para a conta? Você pode fazer isso com uma expressão regular que usa o qualificador de ungreedy (?). Não há divisão, portanto, aspas não são um problema.

"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

Editar
Eu não estava claro a partir da frase the top level OU that a user is in, and any lower level OUs. Você também pode fazer isso:

$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
    
por 27.10.2017 / 22:54