Today working with my brother we needed to automate some administration of some Linux VMs for Students. The goal was simple enough, in a PowerShell script create the Linux VMs, Power it on and then SSH into it to configure Linux and create student account on their VM.
Its an odd project that is sort of last minute but we think we can script a solution for the college faculty. One of the assumed easy features of this plan was to SSH into the Linux VM from PowerShell. But surprisingly their didn't a appear to be any easy solutions. The two options available appeared to be:
SharpSSH - I tried to use it but could only get the following error:
Exception getting "formatValueList": "Microsoft.PowerShell.Commands.Internal.Format.FreeFormatEntry.formatValueList"
And /N Software NetCmdlets which is a paid solution i don't have access to and didn't find very good usage on. Lastly I found that it appears best to use plink.exe. Plink comes with putty and is the command line only version of putty. The result being you can pipe your command and through plink however you first have to accept to trust the host key. That a problem because despite all my attempts I couldn't find a command parameter to allow it to accept the host key. Here is the prompt.
C:\Program Files (x86)\PuTTY>plink -ssh username@host -pw password
The server's host key is not cached in the registry. You ave no guarantee that the server is the computer you think it is.
The server's rsa2 key fingerprint is:
ssh-rsa 2048 8e:39:5f:6e:6d:80:77:50:6e:39:b0:c1:13:98:ab:c1
If you trust this host, enter "y" to add the key to PuTTY's cache and carry on connecting. If you want to carry on connecting just once, without adding the key to the cache, enter "n".
If you do not trust this host, press Return to abandon the connection.
Store key in cache? (y/n)
However I worked out a solution, it isn't pretty but it works well.
Using " Echo y " and piping that to the plink it will accept the host key, but keep entering y over and over. The solution is to then pass the command exit to plink which will logout the ssh session the second it gets logged in. With that the host key is cache and trusted. How simply plink again with out the "echo y"
ehco y | plink -ssh username@host -pw password exit
plink -ssh username@host -pw password ls
Below is the PowerShell script that will allow you to pass multiple SSH commands at once. Comment if you have questions or ways to improve this.
test
Function Invoke-SSHCommands {
Param($Hostname,$Username,$Password, $CommandArray,
$PlinkAndPath,
$ConnectOnceToAcceptHostKey = $true)
$Target = $Username + '@' + $Hostname
$plinkoptions = "-ssh $Target -pw $Password"
#Build ssh Commands
$CommandArray += "exit"
$remoteCommand = ""
$CommandArray | % {
$remoteCommand += [string]::Format('{0}; ', $_)
}
#plist prompts to accept client host key. This section will
#login and accept the host key then logout.
if($ConnectOnceToAcceptHostKey)
{
$PlinkCommand = [string]::Format('echo y | & "{0}" {1} exit',
$PlinkAndPath, $plinkoptions )
#Write-Host $PlinkCommand
$msg = Invoke-Expression $PlinkCommand
}
#format plist command
$PlinkCommand = [string]::Format('& "{0}" {1} "{2}"',
$PlinkAndPath, $plinkoptions , $remoteCommand)
#ready to run the following command
#Write-Host $PlinkCommand
$msg = Invoke-Expression $PlinkCommand
$msg
}
$PlinkAndPath = "C:\Program Files (x86)\PuTTY\plink.exe"
$Username = "remoteshell"
$Password = "pa$$w0rd"
$Hostname = "Linuxhost"
$Commands = @()
$Commands += "ls"
$Commands += "whoami"
Invoke-SSHCommands -User $Username `
-Hostname $Hostname `
-Password $Password `
-PlinkAndPath $PlinkAndPath `
-CommandArray $Command