web-dev-qa-db-ja.com

PowerShellを使用せずにActive Directoryユーザーとコンピューターを使用してACEをACLに追加できるのはなぜですか?

ADにSQLと呼ばれるOUがあります。 OUのフルコントロールをsqladminというユーザーに委任しました。

Sqladminとしてメンバーサーバーにログインすると、Active Directoryユーザーとコンピューターを使用して、AGとクラスターの2つの異なるコンピューターオブジェクトを作成できます。 ADUCを使用してAGコンピューターオブジェクトにセキュリティを設定し、クラスターコンピューターオブジェクトが完全に制御できるようにすることができます。

ただし、PowerShellでAGから現在のACLを取得してACEを追加することでこれを実行しようとすると、AGコンピューターオブジェクトにACLを設定しようとすると、アクセス拒否エラーが発生します。

これが私のコードです

$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ユーザーとしてログインしたときにのみ失敗します。ただし、GUIを使用してsqladminでタスクを実行できます。

GUIを使用すると、作成されたACEのCLUSTER $のGenericAllタイプが、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)
4
Andy Schneider

これは、_Get-Acl_が内部でどのように機能するかに関係しているのではないかと思います。私が正しく思い出すと、オブジェクトのDACL(必要なもの)とSACL(不要なもの)の両方が取得されます。 sqladminユーザーには、DACLを変更する権限しかありません。また、変更されたオブジェクトで_Set-Acl_を使用すると、変更されていなくても、SACLを含むオブジェクト全体を書き込もうとします。また、アクセス権がないため、アクセスが拒否されます。

関連する質問があります ここ ファイルシステムオブジェクトのアクセス許可を処理するための回避策があります。ただし、GetAccessControl()メソッドはADオブジェクトには存在しません。

ただし、ADオブジェクトには、代替として使用できる独自のメソッドセットがあります。それらの1つは 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.
_
3
Ryan Bolger