Powershell:设置 AD DS 对象的所有者失败

the*_*bit 5 powershell active-directory access-control-list

我想Set-ACL在 AD DS 对象1上运行 a ,并将“域管理员”设置为我构建的 ACL 对象中的所有者。代码基本上看起来像这样2

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)"
}
Run Code Online (Sandbox Code Playgroud)

但是,当代码在 Server 2008 R2 DC (Powershell v5) 上执行时,Set-ACL 调用会返回此错误:

Set-ACL : This security ID may not be assigned as the owner of this object
Run Code Online (Sandbox Code Playgroud)

或者使用相同的安全主体从 Server 2012 R2 管理站 (Powershell v4) 运行它时出现更通用的“访问被拒绝”异常:

Set-ACL : Access is denied
Run Code Online (Sandbox Code Playgroud)

在这种特殊情况下,我什至没有更改所有者,但显然 Set-ACL 只是重写了整个安全描述符。

“修改权限”“修改所有者”已在目标对象上明确设置,我完全能够使用 gpmc.msc GUI 将这个对象的所有者更改为我在 DC 和管理站上想要的任何内容,因此这不是一个明显的权限问题。另一方面,我还看到代码一旦由域管理员组成员的用户运行就可以正常工作。

我使用的帐户故意缺少“域管理员”成员身份本身(它是“BUILTIN\Server Admins”组的成员),但需要能够自由地设置对象的所有者。我看到涵盖此错误消息的 MSDN 文章建议“了解您有权指定为所有者的用户和组”,这对我的情况没有帮助。

那么我做错了什么?


1在我的例子中是一个 GPO,但对象的类型并不那么重要,例如,我也看到这种情况发生在 OU 上。

2Set-Acl -AclObject $targetAcl -Path "AD:\$($targetObject.DistinguishedName)"调用看起来像是黑客行为,而且确实如此。我不能按照预期传递-InputObject $targetObjectSet-ACL实现InputObject该方法的对象类型SetSecurityDescriptor,而 [Microsoft.ActiveDirectory.Management.ADObject] 由于某些神秘的原因而没有这样做。

the*_*bit 1

当我认为我看到的效果可能是特定于 Set-ACL 的实现时,我尝试获取 [System.DirectoryServices.ActiveDirectorySecurity] 类并使用其 .SetOwner 方法:

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

在我在 DC 上运行代码的初始测试中,如果我想将所有者设置为我自己(取得所有权),它会起作用,但再次未能将所有者设置为Domain Admins ,这一事实让我感到震惊:

Exception calling "CommitChanges" with "0" argument(s): "A constraint violation occurred.
Run Code Online (Sandbox Code Playgroud)

对我来说幸运的是,我在 SF 上偶然发现了“Set-ACL 失败”问题的答案,该问题链接为“相关”。这个答案提到令牌特定的权限限制1 作为问题的可能原因,因此我继续在管理站上测试相同的方法,其中本地交互式 DC 令牌限制不适用。它有效 - 我现在可以根据自己的喜好在 Powershell 中设置 DS 对象的所有者(只要我不尝试在 DC 上这样做)。

TechNet 论坛中的另一个主题是提供基于 .NET 类的解决方案,将此权限添加到当前进程令牌,而不需要像 PSCX 这样的第 3 方 Cmdlet,但我还没有找到一种方法使其在我的特定情况下工作。 。


1这里的相关权限可能是SeRestorePrivilege - 默认情况下,交互式登录过程令牌禁用它。

这也意味着需要更改 AD DS 对象所有权的帐户需要通过默认内置组(例如 DC 上的服务器操作员和备份操作员)中的组成员身份或通过更改默认域控制器策略分配来获取分配的权限“恢复文件和目录”用户权限。