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

Удаленное выполнение надстройки Powershell с помощью команды Invoke-Command

Сценарий:

При выполнении локально на виртуальной машине Azure успешно добавляет компьютер в AD и перезагружается.

$DomainName = "test.local"
$AdminUserName = "sysadmin"
$Password = <mypass>
$SecurePassword = ConvertTo-SecureString $Password -asplaintext -force
$Credential = New-Object -Typename System.Management.Automation.PSCredential -Argumentlist $AdminUserName, $SecurePassword
$Credential

Add-Computer -DomainName $DomainName -Credential $Credential -Restart -Passthru -Verbose

Вопрос:

Используя те же переменные, но теперь выполняя сценарий на моем компьютере с другой виртуальной машиной Azure в качестве цели, через удаленную оболочку Powershell:

$ScriptBlockContent = { 
Param ($Arg1,$Arg2)
Add-Computer -DomainName $Arg1 -Credential $Arg2 -Restart -Passthru -Verbose}

$Session = New-PSSession -ConnectionUri $Uri -Credential $Credential
Invoke-Command -Session $Session -ScriptBlock $ScriptBlockContent -ArgumentList ($DomainName,$Credential)

Это не работает при удаленном выполнении. Зачем ?

PS C:\> Invoke-Command -Session $Session -ScriptBlock $ScriptBlockContent -ArgumentList $DomainName, $Credential
VERBOSE: Performing the operation "Join in domain 'test.local'" on target "testvm2".
Computer 'rzlab1sql1' failed to join domain 'test.local' from its current workgroup 'WORKGROUP' with following error
message: Unable to update the password. The value provided as the current password is incorrect.
    + CategoryInfo          : OperationStopped: (testvm2:String) [Add-Computer], InvalidOperationException
    + FullyQualifiedErrorId : FailToJoinDomainFromWorkgroup,Microsoft.PowerShell.Commands.AddComputerCommand
    + PSComputerName        : mylab.cloudapp.net

Тем не менее, что-то более простое, без аргументов, не имеет проблем с удаленной работой, поэтому мои $ Uri, $ Credential и общий синтаксис кажутся нормальными, сеансы запускаются и запускают мой код:

$Path = "C:\"
$Attribute = "d"

$ScriptBlockContent = { 
Param ($Arg1,$Arg2)
Get-ChildItem -Path $Arg1 -Attributes $Arg2}

$Session = New-PSSession -ConnectionUri $Uri -Credential $Credential
Invoke-Command -Session $Session -ScriptBlock $ScriptBlockContent -ArgumentList $Path, $Attribute

Есть ли проблема с Invoke-Command и способом хранения учетных данных? Есть ли другие варианты, чтобы это сделать (добавить новую виртуальную машину в домен из сценария PS)?

Решение

Использовать test.local \ sysadmin вместо сисадмин пользователя для подключения к AD.

$DomainName = "test.local"
$AdminUserName = "sysadmin"
$DomainUserName = $DomainName+"\"+$AdminUserName
$Password = <mypass>
$SecurePassword = ConvertTo-SecureString $Password -asplaintext -force
$Credential = New-Object -Typename System.Management.Automation.PSCredential -Argumentlist ($AdminUserName, $SecurePassword)
$DomainCredential = New-Object -Typename System.Management.Automation.PSCredential -Argumentlist ($DomainUserName, $SecurePassword)

$ScriptBlockContent = { 
Param ($Arg1,$Arg2)
Add-Computer -DomainName $Arg1 -Credential $Arg2 -Restart -Passthru -Verbose}

$Session = New-PSSession -ConnectionUri $Uri -Credential $Credential
Invoke-Command -Session $Session -ScriptBlock $ScriptBlockContent -ArgumentList ($DomainName, $DomainCredential)

Другое решение (менее безопасное) - отправить текстового пользователя и пароль в удаленный сеанс и создать там учетные данные:

$ScriptBlockContent = { 
Param ($Arg1,$Arg2,$Arg3,$Arg4)
Add-Computer -ComputerName $Arg4 -DomainName $Arg1 -Credential (New-Object -Typename System.Management.Automation.PSCredential -Argumentlist ($Arg1+"\"+$Arg2), (ConvertTo-SecureString $Arg3 -asplaintext -force)) -Restart -Passthru -Verbose}

$Session = New-PSSession -ConnectionUri $Uri -Credential $Credential
Invoke-Command -Session $Session -ScriptBlock $ScriptBlockContent -ArgumentList ($DomainName,$AdminUserName,$Password,$VMName)

Я думаю, проблема может быть в том, как вы генерируете учетные данные с помощью ConvertTo-SecureString. По умолчанию этот командлет использует ключ шифрования, специфичный для текущего хоста (я думаю) если только вы предоставляете явный ключ шифрования с -Key параметр. На удаленной стороне ему необходимо расшифровать строку, используя тот же ключ шифрования, которого у него нет (потому что ключ хоста другой).

Во-первых, я бы попробовал передать имя пользователя и пароль в виде открытого текста в качестве другого параметра для вызова и выполнить создание учетных данных в блоке сценария. Это хотя бы докажет, действительно ли это ваша проблема.

* Изменить: вот ссылка на документацию для ConvertTo-SecureString

Взято из: http://www.gi-architects.co.uk/2017/01/powershell-add-computer-error-when-executed-remotely/

Корень проблемы в том (при условии, что ваш пароль правильный) при интерактивном запуске домен добавляется заранее, и поэтому вам нужно только указать пользователя. Но в неинтерактивной среде домен не известен. Убедитесь, что вы включили короткие доменные имена, например contoso\DMAdmin или полное доменное имя DMAdmin@contoso.com.

Вы можете использовать следующий сценарий PowerShell, если вы безопасно передаете имя пользователя и пароль в качестве переменных с помощью автоматизации Azure:

$PasswordSec = ConvertTo-SecureString $Password -AsPlainText -Force $djuser = new-object -typename System.Management.Automation.PSCredential -argumentlist $Username, $PasswordSec Add-Computer -DomainName "contoso.com" -Credential $djuser -Restart