Skip to content

Instantly share code, notes, and snippets.

@joegasper
Last active September 28, 2023 08:17
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save joegasper/3fafa5750261d96d5e6edf112414ae18 to your computer and use it in GitHub Desktop.
Save joegasper/3fafa5750261d96d5e6edf112414ae18 to your computer and use it in GitHub Desktop.
Convert between DistinguishedName and CanonicalName
#Updated ConvertFrom-DN to support container objects
function ConvertFrom-DN {
[cmdletbinding()]
param(
[Parameter(Mandatory, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)]
[ValidateNotNullOrEmpty()]
[string[]]$DistinguishedName
)
process {
foreach ($DN in $DistinguishedName) {
Write-Verbose $DN
$CanonNameSlug = ''
$DC = ''
foreach ( $item in ($DN.replace('\,', '~').split(','))) {
if ( $item -notmatch 'DC=') {
$CanonNameSlug = $item.Substring(3) + '/' + $CanonNameSlug
}
else {
$DC += $item.Replace('DC=', ''); $DC += '.'
}
}
$CanonicalName = $DC.Trim('.') + '/' + $CanonNameSlug.Replace('~', '\,').Trim('/')
[PSCustomObject]@{
'CanonicalName' = $CanonicalName;
}
}
}
}
function ConvertFrom-CanonicalUser {
[cmdletbinding()]
param(
[Parameter(Mandatory, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)]
[ValidateNotNullOrEmpty()]
[string]$CanonicalName
)
process {
$obj = $CanonicalName.Split('/')
[string]$DN = 'CN=' + $obj[$obj.count - 1]
for ($i = $obj.count - 2; $i -ge 1; $i--) { $DN += ',OU=' + $obj[$i] }
$obj[0].split('.') | ForEach-Object { $DN += ',DC=' + $_ }
return $DN
}
}
function ConvertFrom-CanonicalOU {
[cmdletbinding()]
param(
[Parameter(Mandatory, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)]
[ValidateNotNullOrEmpty()]
[string]$CanonicalName
)
process {
$obj = $CanonicalName.Split('/')
[string]$DN = 'OU=' + $obj[$obj.count - 1]
for ($i = $obj.count - 2; $i -ge 1; $i--) { $DN += ',OU=' + $obj[$i] }
$obj[0].split('.') | ForEach-Object { $DN += ',DC=' + $_ }
return $DN
}
}
@joegasper
Copy link
Author

Thank you @shivtorov your latest update sent me down a rabbit hole wondering if there was a way to use what AD does to map names. With Pwsh making .NET calls possible, I came across DsCrackName and namespace calls like [System.DirectoryServices.ActiveDirectory.Domain]::GetComputerDomain() right in Pwsh. This led me to a COM object called NameTranslate that had code examples! I started writing new Pwsh based off the examples, then got smarter and found this gist - seems to work with whatever I toss at it, including your last example.

Convert-ADName.ps1

$myDN = Convert-ADName -Name test01@contoso.com -InputType UPN -OutputType DN
$myCN = Convert-ADName -Name $myDN -InputType DN -OutputType canonical

$myDN
CN=\   \" 1 \+ 2 \" \= \< \#3 \> \; / \\  ~  \ ,OU=ServiceAccounts,OU=IT,OU=Departments,DC=contoso,DC=com

$myCN
contoso.com/Departments/IT/ServiceAccounts/   " 1 + 2 " = < #3 > ; \/ \\  ~   

$myContainer = 'contoso.com/Managed Service Accounts/it-mgdsvc'
Convert-ADName -Name $myContainer -InputType canonical -OutputType DN
CN=it-mgdsvc,CN=Managed Service Accounts,DC=contoso,DC=com

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment