Назад | Перейти на главную страницу

Почему я могу добавить ACE в ACL с помощью Active Directory - пользователи и компьютеры, но не с помощью PowerShell?

У меня есть подразделение в AD под названием SQL. Я делегировал полный контроль над OU пользователю sqladmin.

Если я вхожу на рядовой сервер как sqladmin, я могу использовать «Пользователи и компьютеры Active Directory» для создания двух разных компьютерных объектов: AG и Cluster. Я могу использовать ADUC, чтобы установить безопасность на компьютерном объекте AG, чтобы компьютерный объект «Кластер» имел полный контроль.

Однако, если я попытаюсь сделать это с помощью PowerShell, отключив текущий ACL от AG и добавив ACE, я получу ошибку «Доступ запрещен» при попытке установить ACL для объекта AG Computer.

Вот мой код

$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

Однако, если я вхожу в систему как администратор домена и запускаю код, он работает нормально. Код не работает только тогда, когда я вхожу в систему как пользователь sqladmin. Однако я могу выполнить эту задачу с помощью sqladmin, используя графический интерфейс.

Я также могу подтвердить, что если я использую графический интерфейс, созданный ACE имеет тип Generic All для CLUSTER $ и соответствует тому, что я пытаюсь сделать в PowerShell. Мне нужно обновить ACL с помощью учетной записи пользователя, которой был делегирован доступ к OU с помощью PowerShell.

Вот ошибка, которую я вижу, когда пытаюсь сделать это с помощью 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, даже если он не изменился. А поскольку у вас нет доступа, вам будет отказано в доступе.

Есть связанный вопрос Вот у которого есть обходной путь для работы с разрешениями на объекты файловой системы. Но GetAccessControl() не существует для объектов AD.

Однако у объекта 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.