Powershell: setting owner for AD DS objects fails

access-control-listactive-directorypowershell

I want to run a Set-ACL on an AD DS object1 with "Domain Admins" set as the owner in my constructed ACL object. The code looks basically like this2:

Function SetDSAcl {
       Param (
        [Microsoft.ActiveDirectory.Management.ADObject]$targetObject   # target object
    )

    $targetACL = Get-Acl "AD:\$($targetObject.DistinguishedName)"
    # [some voodoo to get the values for my new ACE]
    # Create a new AccessRule using the object constructor
    # $newAce = New-Object System.DirectoryServices.ActiveDirectoryAccessRule([...])

    # Add the generated ACE to target's ACL
    $targetAcl.AddAccessRule($newAce)

    # Persist the changed ACL to the object
    Set-ACL -AclObject $targetAcl "AD:\$($targetObject.DistinguishedName)"
}

But the Set-ACL call returns this error when the code is executed on a Server 2008 R2 DC (Powershell v5):

Set-ACL : This security ID may not be assigned as the owner of this object

or a more generic "Access denied" exception when using the same security principal to run it from a Server 2012 R2 management station (Powershell v4):

Set-ACL : Access is denied

I am not even changing the owner in this particular case, but apparently Set-ACL simply is rewriting the entire security descriptor.

"Modify permissions" and "Modify owner" have explicitly been set on the destination object and I am perfectly able to change the owner of this very object using the gpmc.msc GUI to anything I want on both the DC and the management station, so it is not an obvious permission issue. On the other hand, I also see that the code is working as soon as it is run by a user who is member of the Domain Admins group.

The account I am using is deliberately lacking the "Domain Admins" membership itself (it is a member of the "BUILTIN\Server Admins" group instead), yet needs to freely be able to set the owner of the object. I see that the MSDN article covering this error message is suggesting to "learn which users and groups you have the right to assign as owner", which is not helpful in my case.

So what am I doing wrong?


1 a GPO in my case, but the type of object does not matter as much, I also have seen it happening for OUs, for instance.

2 The Set-Acl -AclObject $targetAcl -Path "AD:\$($targetObject.DistinguishedName)" call looks like a hack and it indeed is. I cannot just pass -InputObject $targetObject to Set-ACL as InputObject expects an object type implementing the SetSecurityDescriptor method, which [Microsoft.ActiveDirectory.Management.ADObject] is not doing for some mysterious reason.

Best Answer

As I figured the effect I am seeing might be implementation-specific to Set-ACL, I tried fetching the [System.DirectoryServices.ActiveDirectorySecurity] class instead and using its .SetOwner method:

$adsiTarget = [adsi]"LDAP://$($targetObject.DistinguishedName)"
$idRef = New-Object System.Security.Principal.NTAccount("CONTOSO", "Domain Admins")
$adsiTarget.PSBase.ObjectSecurity.SetOwner($idRef)
$adsiTarget.PSBase.CommitChanges()

In my initial tests running the code on a DC, I was set off by the fact that it worked if I want to set the owner to myself (take ownership) but again failed to set the owner to Domain Admins:

Exception calling "CommitChanges" with "0" argument(s): "A constraint violation occurred.

Luckily for me, I stumbled upon an answer to the "Set-ACL fails" question here on SF which is linked as "Related". This answer is mentioning token-specific privilege restrictions1 as the possible cause of the problem, so I went on to test the same approach on the management station, where local-interactive DC token restrictions would not apply. It worked - I am able to set DS objects' owners in Powershell to my liking now (as long as I am not trying to do so on a DC).

Another thread in the TechNet forums is providing a .NET class - based solution to adding this privilege to the current process token without the need of 3rd party Cmdlets like PSCX, but I have not yet found a way to make it work in my particular case.


1 the relevant privilege here likely being SeRestorePrivilege - it is disabled for interactive logon process tokens by default.

Which also means that an account needing to change ownership on an AD DS object would need to get this privilege assigned through either group membership in the default BUILTIN groups like Server Operators and Backup Operators on DCs or through a change in the Default Domain Controllers policy assignment of the "Restore files and directories" user right.

Related Topic