This module is reworked from the version posted by Eamon O’Reily on the technet gallery.
The original version utilised temporarily created text files and folders on the system drive for capturing putty / plink output. This modified version removes the use of files which allows the module to work on hardened servers. It also introduces an ExitCode switch to allow return codes to be outputted instead of stream text.
The linked zip file (which is directly imported as a Service Management Automation module) contains plink.exe (and required license agreement). The source code is below.
TIP: When writing SMA modules, try to keep module names (i.e. the folder) to 8 characters or less. I’ve now seen on seemingly identical machines where Service Management Automation fails to extract routines from modules if the name is larger.
Download the ssh module for Service Management Automation here.
Source Code
[[powershell]] # .SYNOPSIS Executes a PuTTY / PLink.exe SSH command using either a password or a key file. .DESCRIPTION This module has a dependency on PLink.exe available in the PuttyFiles folder. You can download this file from http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html and place this in the PuttyFiles folder. You can then zip up the SSH folder and import this into System Center R2 - Orchestrator Service Management Automation. .Example Invoke-SSHCommand -HostName "oracle7.domain.com" -Password MySecret1 -SSHCommand "ls -l" -UserName fred -AcceptHostKey Returns the text stream from the executed command .Parameter Hostname A resolveable hostname (or IP address) for a linux host .Parameter SSHCommand The SSH command to be used against the host .Parameter AcceptHostKey A switch to allow unrecognised Host Keys to be accepted .Parameter ExitCode A switch that allows exitcodes to be returned instead of (the default) text stream .Parameter Username The username to connect to the target machine .Parameter Password The Password to connect to the target machine .Parameter KeyFilePath Thepath to a key file to connect to the target machine .Inputs [string] .OutPuts [string] [int] .Notes NAME: Invoke-SSHCommand AUTHOR: Laurie Rhodes LASTEDIT: 8/11/2015 KEYWORDS: #> function Invoke-SSHCommand{ [CmdletBinding(DefaultParameterSetName='UseKeyAuthentication')] param( [Parameter(Mandatory=$True)] [ValidateNotNullOrEmpty()] [string] $HostName, [Parameter(Mandatory=$True)] [ValidateNotNullOrEmpty()] [string] $SSHCommand, [Parameter(Mandatory=$True)] [ValidateNotNullOrEmpty()] [string] $UserName, [Parameter(Mandatory=$False)] [Switch] $AcceptHostKey, [Parameter(Mandatory=$False)] [Switch] $ExitCode, [Parameter(ParameterSetName='UsePasswordAuthentication',Mandatory=$True)] [ValidateNotNullOrEmpty()] [string] $Password, [Parameter(ParameterSetName='UseKeyAuthentication', Mandatory=$True)] [ValidateNotNullOrEmpty()] [string] $KeyFilePath ) $Invocation = (Get-Variable MyInvocation -Scope 1).Value $CMDLetPath = Split-Path $Invocation.MyCommand.Path $PathtoPlink = "$($CMDLetPath)\PuttyFiles\plink.exe" if (!(Test-Path $pathtoPlink)) { Throw "Plink.exe is not located with module files Please download from http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html" } # Workaround to support PowerShell via Odata IIS extensions on Server 2012R2 # PLink isn't able to query DNS so PowerShell converts any # Hostname to an IP prior to calling Plink try{ $IPAddress = [IPAddress]$HostName #"valid IP" } catch{ # "not a valid IP" #Resolve-DNSName throws an error if a DNS name is not resolved $old_ErrorActionPreference = $ErrorActionPreference $ErrorActionPreference = 'SilentlyContinue' $IPAddress = (Resolve-DnsName -Name $HostName).IPAddress $ErrorActionPreference = $old_ErrorActionPreference } #Continue to use Plink with an IP Address if ($AcceptHostKey) { $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = "cmd.exe" $params = "/c echo y | ""$($pathtoPlink)"" $IPAddress" $pinfo.Arguments = $params $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $processstart = $p.Start() $p.WaitForExit() $stdout = $p.StandardOutput.ReadToEnd() $stderr = $p.StandardError.ReadToEnd() [int]$returncode = $p.ExitCode write-verbose "Accept Host Key Exit Code: $returncode" } if ($Password) { Write-Verbose "Calling Password Authentication" $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = $pathtoPlink $params = "-ssh -batch $($IPAddress) -l $($UserName) -pw $($Password) $($SSHCommand)" $pinfo.Arguments = $params $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $processstart = $p.Start() $p.WaitForExit() $stdout = $p.StandardOutput.ReadToEnd() $stderr = $p.StandardError.ReadToEnd() [int]$returncode = $p.ExitCode write-verbose "stdout: $stdout" write-verbose "stderr: $stderr" write-verbose "exit code: $returncode" } else{ # If a key file is set then run the command using the provided key file. All Key files should be placed in the KeyFiles folder and # must not have a passphrase protecting them. Ensure that access to the runbook workers is restricted to protect these files. if (Test-Path $KeyFilePath) { Write-Verbose "Calling Key File Authentication" $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = $pathtoPlink $params = "-ssh -batch $($IPAddress) -l $($UserName) -i "+[char]34 + $KeyFilePath +[char]34 +" $($SSHCommand)" $pinfo.Arguments = $params $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $processstart = $p.Start() $p.WaitForExit() $stdout = $p.StandardOutput.ReadToEnd() $stderr = $p.StandardError.ReadToEnd() [int]$returncode = $p.ExitCode write-verbose "stdout: $stdout" write-verbose "stderr: $stderr" write-verbose "exit code: $exitcode" } else { Throw "Key File not found" } } if ($stderr.Length -ne 0){ Throw $stderr } if ($ExitCode){ $response = $returncode } else{ $response = $stdout } return $response } Export-ModuleMember Invoke-SSHCommand [[/powershell]]
11/2015 - The version of module here has been modified to support being utilised via IIS Odata / REST call. This allows an IIS server to relay SSH commands to local linux machines from its Odata interface. For more details, have a read of this post:
Calling PowerShell Modules with REST / ODATA API
- Log in to post comments
- Log in to post comments
IIS Odata update