通过Invoke-Command远程执行Powershell Add-Computer

场景:

在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 

题:

使用相同的variables,但现在在我的机器上运行脚本,以另一个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和General语法看起来没问题,会话开始并运行我的代码:

 $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而不是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) 

另一种解决scheme(不太安全)是将纯文本用户和密码发送到远程会话,并在那里创build凭证:

 $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参数提供明确的encryption密钥, 否则该cmdlet将使用特定于当前主机的encryption密钥(我认为)。 在远端,它需要使用它没有的相同encryption密钥来解密string(因为主机密钥是不同的)。

首先,我尝试传递明文用户名和密码作为另一个参数来调用脚本块中的凭证创build。 这至less会certificate这是否是你的问题。

*编辑:这是一个指向ConvertTo-SecureString文档的链接

采取: http : //www.gi-architects.co.uk/2017/01/powershell-add-computer-error-when-executed-remotely/

问题的根源在于(假设您的密码是正确的)交互式运行时,域名是预先附加的,因此您只需要提供用户。 但是在非交互式环境中,域名是不知道的。 确保您要么包含contoso\DMAdmin这样的短域名,要么包含完整的FQDN [email protected]

如果您通过azure色自动化安全地将用户名和密码作为variables传递,则可以使用以下PowerShell脚本:

$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