为什么我可以使用Active Directory用户和计算机将ACE添加到ACL,但不能用PowerShell?

我在AD中有一个名为SQL的OU。 我已经委派一个名为sqladmin的用户的完全控制权。

如果我以sqladmin身份login到成员服务器,则可以使用Active Directory用户和计算机创build两个不同的计算机对象AG和群集。 我可以使用ADUC来设置AG计算机对象上的安全性,以使群集计算机对象具有完全控制权。

但是,如果我尝试通过从AG获取当前ACL并添加ACE来使用PowerShell执行此操作,则当我尝试在AG计算机对象上设置ACL时,出现Access Denied错误。

这是我的代码

$AG = Get-ADComputer AG $cluster = Get-ADComputer cluster $AGDistinguishedName = $AG.DistinguishedName # input AD computer distinguishedname $AGacl = Get-Acl "AD:\$AGDistinguishedName" $SID = [System.Security.Principal.SecurityIdentifier] $cluster.SID $identity = [System.Security.Principal.IdentityReference] $SID $adRights = [System.DirectoryServices.ActiveDirectoryRights] "GenericAll" $type = [System.Security.AccessControl.AccessControlType] "Allow" $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] "None" $ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $identity,$adRights,$type,$inheritanceType $AGacl.AddAccessRule($ace) Set-Acl -path "AD:\$AGDistinguishedName" -AclObject $AGacl 

但是,如果我作为域pipe理员login并运行代码,它工作正常。 当我以sqladmin用户身份login时,代码只会失败。 但是,我可以使用GUI执行sqladmin的任务。

我也可以确认,如果我使用GUI,创build的ACE具有CLUSTER $的通用所有types,并且它与我在PowerShell中要做的相匹配。 我需要能够使用PowerShell委托访问OU的用户帐户来更新ACL。

以下是我在使用PowerShell尝试执行此操作时看到的错误。

 System.UnauthorizedAccessException: Access is denied ---> System.ServiceModel.FaultException: The operation failed due to insufficient access rights. --- End of inner exception stack trace --- at Microsoft.ActiveDirectory.Management.AdwsConnection.ThrowExceptionForExtendedError(String extendedErrorMessage, Exception innerException) at Microsoft.ActiveDirectory.Management.AdwsConnection.ThrowExceptionForErrorCode(String message, String errorCode, String extendedErrorMessage, Exception innerException) at Microsoft.ActiveDirectory.Management.AdwsConnection.ThrowExceptionForFaultDetail(FaultDetail faultDetail, FaultException faultException) at Microsoft.ActiveDirectory.Management.AdwsConnection.ThrowException(AdwsFault adwsFault, FaultException faultException) at Microsoft.ActiveDirectory.Management.AdwsConnection.Modify(ADModifyRequest request) at Microsoft.ActiveDirectory.Management.ADWebServiceStoreAccess.Microsoft.ActiveDirectory. Management.IADSyncOperations.Modify(ADSessionHandle handle, ADModifyRequest request) at Microsoft.ActiveDirectory.Management.ADActiveObject.Update() at Microsoft.ActiveDirectory.Management.Provider.ADProvider.SetSecurityDescriptor(String path, ObjectSecurity securityDescriptor) 

我想这可能与Get-Acl如何工作有关。 如果我记得正确,它会检索对象的DACL(你想要的)和SACL(你不想要的)。 您的sqladmin用户只具有修改DACL的权限。 而且当你用你的修改对象使用Set-Acl时,它会尝试写入包括SACL在内的整个对象,即使它没有改变。 而且由于你没有访问权限,你会被拒绝访问。

这里有一个相关的问题,有一个解决方法来处理文件系统对象的权限。 但是,AD对象上不存在GetAccessControl()方法。

但是,AD对象具有自己的一组方法,您可以将其用作替代方法。 其中之一是ModifyAccessRule 。 这是对你的代码的修改,以便使用它。

 # grab the data you need from the AD objects $AG = Get-ADComputer AG $AGDN = $AG.DistinguishedName # input AD computer distinguishedname $cluster = Get-ADComputer cluster $SID = [System.Security.Principal.SecurityIdentifier] $cluster.SID # create the ACE you want to add $identity = [System.Security.Principal.IdentityReference] $SID $adRights = [System.DirectoryServices.ActiveDirectoryRights] "GenericAll" $type = [System.Security.AccessControl.AccessControlType] "Allow" $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] "None" $ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $identity,$adRights,$type,$inheritanceType # get an ADSI reference to the AD object we're going to tweak $AGADSI = [adsi]"LDAP://$AGDN" # we need an existing boolean output variable for the function $modified = $false # call the function and commit the changes $AGADSI.PSBase.ObjectSecurity.ModifyAccessRule([System.Security.AccessControl.AccessControlModification]::Add,$ace,[ref]$modified) $AGADSI.PSBase.CommitChanges() # you could/should check the value of $modified to make sure it's True before doing the # commit. But hypothetically the only thing that would screw it up is if you botched the # ACE creation.