Execute Powershell Add-Computer remotely via Invoke-Command
Solution 1
I think the problem might be with the way you're generating the credential using ConvertTo-SecureString
. By default, that cmdlet uses an encryption key specific to the current host (I think) unless you provide an explicit encryption key with the -Key
parameter. On the remote side, it needs to decrypt the string using the same encryption key which it doesn't have (because the host key is different).
First, I'd try passing the plaintext username and password as another parameter to the invoke and doing the credential creation within the script block. That will at least prove whether this is actually your problem or not.
*Edit: Here's a link to the documentation for ConvertTo-SecureString
Solution 2
Taken from: http://www.gi-architects.co.uk/2017/01/powershell-add-computer-error-when-executed-remotely/
The root of the problem is (given that your password is correct) when running interactively the domain is pre-appended and as such you only need to provide the user. But in a non-interactive environment, the domain is not known. Make sure you either include the short domain names like contoso\DMAdmin
or the full FQDN [email protected]
.
You can use the following PowerShell script if you pass the username and password as variables securely via azure automation:
$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
Related videos on Youtube
Razvan Zoitanu
Available now, SQL DBA contracts, London or remote. Microsoft certified SQL DBA with real passion for all things tech. Inquisitive, reliable, trustworthy, hard-working. Managed SQL Server since 2004, with a strong IT infrastructure background. Owner and Lead consultant of dbAZ Ltd, a consultancy focused on DBA services for SQL Server on-prem and Azure.
Updated on September 18, 2022Comments
-
Razvan Zoitanu over 1 year
Scenario:
When executed locally on the Azure VM, succesfully adds the machine to the AD, and restarts.
$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
Question:
Using the same variables, but now running the script on my machine, with another Azure VM as the target, via remote 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)
This fails when executed remotely. Why ?
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
Yet something more basic, without arguments, has no problems running remotely, so my $Uri, $Credential and general syntax seem ok, the sessions starts and runs my code:
$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
Is there a problem with Invoke-Command and the way I'm storing the credentials ? Any other options to get this done (to add new VM to domain from a PS script) ?
Solution
Use test.local\sysadmin instead of the sysadmin user to connect to 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)
Another solution (less secure) is to send the plain text user and password to the remote session, and create the credential there:
$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)
-
Razvan Zoitanu about 9 yearsDid the credential creation in the new session as a test, as you mentioned, and it works ! Will update the question with the complete solution code. Thank you Ryan !