Мне было поручено делегировать ряд повседневных задач в нашей области группе технических специалистов, у которых нет Domain Admins
членство. Одна из этих задач - создание новых доменных корней DFS (контроллеры домена Server 2008 R2 Enterprise). И здесь я застрял.
По сути, это просто попытка создать доменный корень 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. Тропинка ROOT\Microsoft\Windows\DFSN\MSFT_DFSNamespace
приведены в CategoryInfo выглядит как путь 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.
И поскольку я получал ошибку, указывающую на отсутствие разрешений в диспетчере управления службами, используя "Добавить корень Dfs" Мастер в dfsmgmt.msc
, Я использовал sc sdset scmanager
для управления строкой SDDL, добавляя соответствующую группу с разрешениями «KA» (доступ к ключу), аналогично BUILTIN\Administrators
ACE, который существует по умолчанию.
Таким образом, я могу использовать "Добавить корень Dfs" мастер, чтобы пройти все шаги, но создание самого корня по-прежнему не удается: «Сервер пространства имен \ ADSRV0 \ Test не может быть добавлен. Доступ запрещен»
W00t?
Достаточно администрирования (JEA) конечные точки хорошо подходят для вашей задачи. Для проектирования конечной точки JEA необходимо принять три основных решения:
Конечная точка PowerShell в PS 5.1 технически не является конечной точкой JEA, но механизм по сути тот же.
Get-PSSessionConfiguration
Имя: microsoft.powershell PS Версия: 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
в твоем случае. Ваше последнее сообщение об ошибке говорит мне, что это не так в вашем случае ..
Чтобы добавить некоторые детали реализации к блестящей идее Мэтью Ветмора, мы создали функцию, настраивающую пространство имен Dfs в соответствии с нашими требованиями, представив ее в модуле Powershell. LT-DFSManagement
и создал конфигурацию сеанса Powershell, работающую под «виртуальной учетной записью» (которая получает права локального администратора) на контроллере домена, ограниченная вызовом этой самой функции и доступная для членов группы безопасности технических специалистов.
Мы используем dfsutil
в коде, который был написан для работы на машине Server 2008 R2, где Dfsn-командлеты недоступны. Имейте в виду, что в коде используются некоторые глобальные переменные, которые не будут определены в вашей среде по умолчанию, но жизненно важны для правильного выполнения кода.
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
Файл возможностей role ограничивает конечную точку только функцией 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"