Por que posso adicionar uma ACE a uma ACL usando Usuários e Computadores do Active Directory, mas não com o PowerShell?

4

Eu tenho uma unidade organizacional no AD chamada SQL. Eu deleguei o controle total da OU a um usuário chamado sqladmin.

Se eu fizer login em um servidor membro como sqladmin, posso usar os Usuários e Computadores do Active Directory para criar dois objetos de computador diferentes, AG e Cluster. Eu posso usar ADUC para definir a segurança no objeto de computador AG, de modo que o objeto de computador Cluster tenha controle total.

No entanto, se eu tentar fazer isso com o PowerShell, obtendo a ACL atual fora do AG e adicionando uma ACE, recebo um erro de Acesso Negado quando tento definir a ACL no objeto Computador AG.

Aqui está o meu código

$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

No entanto, se eu fizer login como administrador de domínio e executar o código, tudo funcionará bem. O código só falha quando eu faço login como o usuário sqladmin. No entanto, posso executar a tarefa com sqladmin usando a GUI.

Também posso confirmar que, se eu usar a GUI, a ACE criada terá o tipo Generic All para CLUSTER $ e corresponderá ao que estou tentando fazer no PowerShell. Preciso atualizar a ACL com a conta de usuário que recebeu acesso delegado à unidade organizacional com o PowerShell.

Aqui está o erro que estou vendo quando tento fazer isso com o 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)
    
por Andy Schneider 09.11.2016 / 22:28

1 resposta

3

Eu acho que isso pode ter a ver com como Get-Acl funciona sob o capô. Se bem me lembro, ele recupera tanto a DACL (que você quer) quanto a SACL (que você não quer) do objeto. Seu usuário sqladmin só tem permissões para modificar a DACL. E quando você usa Set-Acl com seu objeto modificado, ele tenta gravar todo o objeto, incluindo a SACL, mesmo que ela não tenha mudado. E como você não tem acesso, obtém o acesso negado.

Há uma questão relacionada aqui que tem uma solução alternativa para lidar com permissões em objetos do sistema de arquivos. Mas o método GetAccessControl() não existe em objetos do AD.

No entanto, o objeto AD tem seu próprio conjunto de métodos que você pode usar como uma alternativa. Um deles é ModifyAccessRule . Aqui está uma modificação do seu código para usá-lo.

# 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.
    
por 09.11.2016 / 23:49