I have an OU in AD called SQL. I have delegated full control of the OU to a user called sqladmin.
If I log in to a member server as sqladmin, I can use Active Directory Users and Computers to create two different computer objects, AG and Cluster. I can use ADUC to to set the security on AG computer object such that the Cluster computer object has full control.
However, if I try to do this with PowerShell by getting the current ACL off of AG and adding an ACE, I get an Access Denied error when I try to set the ACL on the AG Computer object.
Here is my code
$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
However, If I log in as a domain admin and run the code, it works fine. The code only fails when I log in as the sqladmin user. However, I can perform the task with sqladmin using the GUI.
I can also confirm that if I use the GUI, the ACE that is created has the Generic All type for CLUSTER$ and it matches what I am trying to do in PowerShell. I need to be able to update the ACL with the user account that has been delegated access to the OU with PowerShell.
Here is the error I am seeing when I try to do this with 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)
Best Answer
I think this might have to do with how
Get-Acl
works under the hood. If I recall correctly, it retrieves both the DACL (which you want) and the SACL (which you don't want) of the object. Your sqladmin user only has permissions to modify the DACL. And when you useSet-Acl
with your modified object, it tries to write the whole object including the SACL even though it hasn't changed. And since you don't have access, you get the access denied.There's a related question here that has a workaround for dealing with permissions on filesystem objects. But the
GetAccessControl()
method doesn't exist on AD objects.However, the AD object has its own set of methods that you can use as an alternative. One of them is ModifyAccessRule. Here's a modification of your code tweaked to use it.