私は、ドメイン内の多くの日常業務を、Domain Admins
メンバーシップを持たない技術者のグループに委任するように任命されました。これらのタスクの1つは、新しいドメインベースのDfsルート(Server 2008 R2 Enterprise DC)の作成です。そして、これは私が立ち往生しているところです。
これは基本的に、最初の名前空間サーバーとして任意の(リストの最初の)ドメインコントローラーを使用して、ドメインベースのDfsルートを作成しようとしているだけです。
$DfsnRootName="test"
$DCList = Get-ADDomainController -Filter * | ForEach-Object { ,$_.HostName }
New-DfsnRoot -Path "\\domain.contoso.com\$DfsnRootName" -TargetPath "\\$($DCList[0])\$dfsnRootName" `
-Description "Dfs-Root für $DfsnRootName" -EnableAccessBasedEnumeration $true -Type DomainV2
$DCList | ForEach-Object {
New-DfsnRootTarget -Path "\\domain.contoso.com\$DfsnRootName" `
-TargetPath "\\$_\$dfsnRootName" -State Online
}
上記のコードは、CIMリソースへのアクセスの欠落に言及する例外をスローしています。 CategoryInfoで指定されたパスROOT\Microsoft\Windows\DFSN\MSFT_DFSNamespace
は、WMIパスのように見えます。
New-DfsnRoot : Access to a CIM resource was not available to the client.
At line:1 char:1
+ New-DfsnRoot -Path "\\domain.contoso.com\$DfsnRootName" -TargetPath "\\$($DCList ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (MSFT_DFSNamespace:ROOT\Microsoft\...FT_DFSNamespace) [New-DfsnRoot], CimException
+ FullyQualifiedErrorId : MI RESULT 2,New-DfsnRoot
PS Z:\> $Error[0].CategoryInfo
Category : PermissionDenied
Activity : New-DfsnRoot
Reason : CimException
TargetName : MSFT_DFSNamespace
TargetType : ROOT\Microsoft\Windows\DFSN\MSFT_DFSNamespace
ドメイン全体のDfsコンソールを介して「委任された管理権限」を持っています:
これは事実上、追加されたプリンシパルの「フルコントロール」ACEをCN=Dfs-Configuration,CN=System
ADコンテナーに追加するだけです。
そして、 "Add Dfs root"Wizard dfsmgmt.msc
では、sc sdset scmanager
を使用してSDDL文字列を操作し、デフォルトで存在するBUILTIN\Administrators
ACEと同様に、「KA」(キーアクセス)権限を持つそれぞれのグループを追加しました。
このように、 "Add Dfs root"ウィザードを使用してすべての手順を実行できますが、ルート自体の作成はまだ失敗しています-"名前空間サーバー\ ADSRV0\Testを追加できません。アクセスが拒否されました。」
W00t?
Just Enough Administration(JEA) エンドポイントはタスクに適しています。 JEAエンドポイントの設計には、次の3つの主要な決定が必要です。
PS 5.1のPowerShellエンドポイントは技術的にはJEAエンドポイントではありませんが、メカニズムは基本的に同じです。
Get-PSSessionConfiguration
名前:Microsoft.powershell PSVersion:5.1
StartupScript:
RunAsUser:
アクセス許可:NT AUTHORITY\INTERACTIVE AccessAllowed、BUILTIN\Administrators AccessAllowed、BUILTIN\Remote Management Users AccessAllowed
これから、権限グループは誰に電話をかけることができるかを定義します。実行できることのPowerShellエンドポイントに制限はないため、完全な言語機能があります。そして最後に、RunAsUserが空白の場合、コードは提供されたユーザーまたは資格情報になりすまして実行されます。
その根拠に基づいて、 Register-PSSessionConfiguration
、および JEAの概要 。
ボーナスポイントについては、ソリューションの一部として、特に発信者として グループマネージドサービスアカウント(GMSA) を使用することを検討してください。
あなたの場合:エンドポイントを制限付き特権ユーザーによって呼び出されるように制限できます。
次に、使用する特定のコマンドレットを定義します。これらは、組み込み、または指定したカスタムモジュールから公開できます。複雑な引数を使用した特権の昇格攻撃や、昇格されたユーザーとして実行されることを利用できる低レベルのコマンドが多すぎることを回避するために、これらをタスクに固有にしてください。
ドメイン管理者のRunAsUser
、または十分な権限を持つ別のアカウントを使用できます。
ドメイン全体のDFS名前空間を作成するには、そのアカウントに名前空間サーバーに対するローカル管理者権限が必要です。つまり、ADSRV0
あなたの場合。あなたの最後のエラーメッセージは、あなたの場合はそうではないことを私に示唆しています。
ここでMatthewWetmoreのスパークのアイデアに実装の詳細を追加するために、要件に応じてDfs名前空間を設定する関数を作成し、Powershellモジュールで公開しましたLT-DFSManagement
そして、ドメインコントローラー上の「仮想アカウント」(ローカル管理者特権を取得している)で実行されるPowershellセッション構成を作成し、この関数の呼び出しに制限され、技術者セキュリティグループのメンバーがアクセスできるようにしました。
Dfsn-コマンドレットが使用できないServer 2008 R2マシンで実行するように記述されているため、コードではdfsutil
を使用しています。コードは、デフォルトでは環境で定義されないが、コードを正しく実行するために不可欠ないくつかのグローバル変数を使用していることに注意してください。
Function Add-DfsNamespace() {
<#
.SYNOPSIS
Creates a new Dfs namespace
#>
Param(
# Name of the namespace to create
[string]$Name,
# name of the security group to delegate management permissions to
[string]$DelegationTo = "ACL-$Name-Dfs-management",
# list of the servers to set up as namespace servers
$NamespaceServerList = $global:DomainControllersList
)
$ErrorActionPreference = "Stop"
Try {
$DelegationIdentity = (Get-ADGroup $DelegationTo -Server $global:THKDomainControllerToUse).SID
} Catch {
Throw "Unable to set up delegation permissions for $DelegationTo: $_"
}
$NamespaceServerList | ForEach-Object {
Try {
$NamespaceServer = $_
Write-Debug "Create a directory for the namespace: \\$NamespaceServer\c$\DfsRoots\$Name"
New-Item -Type Directory "\\$NamespaceServer\c$\DfsRoots\$Name" | Out-Null
} Catch {
Write-Warning "Creation of \\$NamespaceServer\c$\DfsRoots\$Name failed: $_"
}
# Create a new share through WMI
$share = [wmiclass]"\\$_\root\CimV2:Win32_Share"
Write-Debug 'WMI call to create the share `"$Name`" on $_'
$result=$share.Create( "c:\DfsRoots\$Name", $Name, 0)
Switch ($result.returnValue) {
0 { Write-Debug "\\$_\$Name share created successfully" }
22 { Write-Warning "Share \\$_\$Name already present" }
default { Throw "Share creation failed, return value of Win32_Share.Create: $result.returnValue" }
}
}
Write-Verbose "Creating Domain Dfs namespace $Name on namespace servers $($NamespaceServerList -join "; ")"
dfsutil root addDom "\\$($NamespaceServerList[0])\$Name"
$NamespaceServerList | ForEach-Object {
If($_ -ne $NamespaceServerList[0]) {
dfsutil target add "\\$_\$Name"
}
}
Write-Debug "Enabling Access-Based Enumeration"
dfsutil property abde enable "\\$global:sADDomainFQDN\$Name"
Write-Debug "Granting delegation rights for Namespace $Name to $DelegatedTo"
$adsiDfsNamespace = $null
$adsiDfsNamespace = [adsi]"LDAP://$global:THKDomainControllerToUse/CN=$Name,CN=Dfs-Configuration,CN=System,$sADDomainDN"
# Query ADSI for the ACL of the namespace AD object until we get a response
$retries = 0
Do {
$namespaceACL = $adsiDfsNamespace.PSBase.ObjectSecurity
If ($namespaceACL) {
# here we've got the ACL, loop will end hereafter
} Else {
Write-Debug "Waiting another round ($retries/$ADSImaxRetries) as ADSI has not yet provided a security descriptor for $($adsiDfsNamespace)"
Start-Sleep 1
}
$retries+=1
} Until (($retries -gt $ADSImaxRetries) -or ($null -ne $namespaceACL))
Write-Debug "Creating a new ACE for $DelegationTo ($DelegationIdentity)"
# Construct a new Full Control ACE for $DelegationIdentity
$newAce =
New-Object System.DirectoryServices.ActiveDirectoryAccessRule(
$DelegationIdentity,
[System.DirectoryServices.ActiveDirectoryRights]::GenericAll,
[System.Security.AccessControl.AccessControlType]::Allow,
[System.DirectoryServices.ActiveDirectorySecurityInheritance]::All
)
Write-Verbose "Updating the ACL of the Namespace $Name"
$namespaceAcl.AddAccessRule($newAce)
$adsiDfsNamespace.PSBase.CommitChanges()
}
PSSessionConfigurationファイルは、このセッション構成を使用できるセキュリティグループを定義します。
@{
'Author' = 'the-wabbit';
'RunAsVirtualAccount' = $true;
'GUID' = 'cfe0ea5f-9d19-406d-90aa-d26df4bc840f';
'TranscriptDirectory' = 'C:\ProgramData\JEAConfiguration\Transcripts';
'SchemaVersion' = '2.0.0.0';
'RoleDefinitions' = @{
'DOMAIN\ACL-DFS-Technicians-AD-JEA-Remoting' = @{
'RoleCapabilities' = 'AD-JEA-DFS' }
};
'SessionType' = 'RestrictedRemoteServer' }
そしてその AD-JEA-DFS
ロール機能ファイルは、エンドポイントをAdd-DfsNamespace関数のみに制限します。
@{
GUID = 'b17b282d-a656-41c8-a7d4-cc6a1fbc17e4'
Author = 'the-wabbit'
CompanyName = 'Looney Tunes'
Copyright = '(c) 2017 the-wabbit. All rights reserved.'
ModulesToImport = 'LT-DFSManagement'
VisibleFunctions='Add-DfsNamespace'
}
構成の最終登録により、次のことが行われます。
Register-PSSessionConfiguration -Name "DFS" -Path "C:\ProgramData\JEAConfiguration\DFS.pssc"