Ryan Bolger

Ryan Bolger

Adventures In Tech

Ryan Bolger

TL;DR

Until Microsoft fixes the bug with the AD PSDrive provider, use the fully qualified PSPath to the object instead of the “AD:” PSDrive path like this:

$DN = (Get-ADUser jdoe).distinguishedName
$objectPath = "Microsoft.ActiveDirectory.Management.dll\ActiveDirectory:://RootDSE/$DN"
Get-Acl -Path $objectPath

The Story

I was browsing r/PowerShell recently and came across a thread from someone who had run into a PowerShell bug after upgrading to Windows Server 2019 (1809). The user was attempting to run Get-Acl against an AD object using the object’s distinguished name like this:

$DN = (Get-ADUser jdoe).distinguishedName
$ACL = Get-Acl -Path "AD:\$DN"

The code works just fine in Server 2016 and earlier. But the same code throws an error in Server 2019 and reportedly Windows 10 (1903) as well.

Get-Acl : The object name has bad syntax
At line:1 char:8
+ $ACL = Get-Acl -Path "AD:\$DN"
+        ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (\\RootDSE\CN=Do...C=example,DC=com:String) [Get-Acl], ADException
    + FullyQualifiedErrorId : ADProvider:ItemExists::ADError,Microsoft.PowerShell.Commands.GetAclCommand

The problem is this particular user’s DN had an escaped comma in it because the CN value was set to “Doe, Jane”. Commas are allowed in object names in AD, but they tend to cause all sorts of problems with LDAP path parsing code due to the escaping. The resulting DN of the object looks something like this:

CN=Doe\, Jane,CN=Users,DC=example,DC=com

Historically, the Windows native Active Directory PowerShell cmdlets and PSDrive provider have no issues dealing with this. But apparently a bug crept into the latest releases. It should be noted that the bug exists with any cmdlet that depends on the Active Directory PSDrive provider. Get-Acl just happens to be the one this user was using. But it also affects something as simple as Get-Item.

The Workaround

One of the things I tried while poking around this bug looking for a workaround was running Get-ChildItem against the parent container and then running Get-Acl against the PSPath parameter of the results like this.

Get-ChildItem "CN=Users,DC=example,DC=com" | ForEach-Object { Get-Acl -Path $_.PSPath }

To my pleasant surprise, it worked without issue. So I took a look at the format of the PSPath for these objects and found this for my problematic test user.

Microsoft.ActiveDirectory.Management.dll\ActiveDirectory:://RootDSE/CN=Doe\, Jane,CN=Users,DC=example,DC=com

We can generalize this out to a somewhat ugly (but at least usable) path prefix for any DN and work it into the original code like this.

$DN = (Get-ADUser jdoe).distinguishedName
$objectPath = "Microsoft.ActiveDirectory.Management.dll\ActiveDirectory:://RootDSE/$DN"
$ACL = Get-Acl -Path $objectPath

Recent Posts

Categories