PoshCode Logo PowerShell Code Repository

SharpSsh 3 by Joel Bennett 17 months ago (modification of post by Joel Bennett view diff)
diff | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/2099"></script>download | new post

I’ve tweaked New-SshSession again, this time it supports multiple parameter sets (including one with the password in plain text, and one which takes a PSCredential).

A few wrapper functions to make working with the SSH portion of SharpSSH easier: New-SshSession, Invoke or Send Ssh commands, Receive output, all with support for “Expect” ... which means we’ll continue reading from the ssh output until we see the expected output, and then stop.

  1. #requires -version 2.0
  2. ## A simple SSH Scripting module for PowerShell
  3. ## History:
  4. ## v1 - Initial Script
  5. ## v2 - Capture default prompt in New-SshSession
  6. ## v3 - Update to advanced functions, require 2.0, and add basic help
  7.  
  8. ## USING the binaries from:
  9. ## http://downloads.sourceforge.net/sharpssh/SharpSSH-1.1.1.13.bin.zip
  10. [void][reflection.assembly]::LoadFrom( (Resolve-Path "~\Documents\WindowsPowerShell\Libraries\Tamir.SharpSSH.dll") )
  11.  
  12. Function ConvertTo-SecureString {
  13. #.Synopsis
  14. #   Helper function which converts a string to a SecureString
  15. Param([string]$input)
  16.    $result = new-object System.Security.SecureString
  17.  
  18.    foreach($c in $input.ToCharArray()) {
  19.       $result.AppendChar($c)
  20.    }
  21.    $result.MakeReadOnly()
  22.    return $result
  23. }
  24.  
  25. Function ConvertTo-PSCredential {
  26. #.Synopsis
  27. #   Helper function which converts a NetworkCredential to a PSCredential
  28. Param([System.Net.NetworkCredential]$Credential)
  29.    $result = new-object System.Security.SecureString
  30.  
  31.    foreach($c in $input.ToCharArray()) {
  32.       $result.AppendChar($c)
  33.    }
  34.    $result.MakeReadOnly()
  35.    New-Object System.Management.Automation.PSCredential "$($Credential.UserName)@$($Credential.Domain)", (ConvertTo-SecureString $Credential.Password)
  36. }
  37.  
  38. ## NOTE: These are still bare minimum functions, and only cover ssh, not sftp or scp (see here: http://poshcode.org/1034)
  39. ##       IMPORTANT: if you "expect" something that does NOT get output, you'll be completely stuck and unable to 'break'
  40. ##
  41. ## As a suggestion, the best way to handle the output is to "expect" your prompt, and then do
  42. ## select-string matching on the output that was captured before the prompt.
  43.  
  44. function New-SshSession {
  45. <#
  46. .Synopsis
  47.    Create an SSH session to a remote server
  48. .Description
  49.    Connect to a specific SSH server with the specified credentials.  Supports RSA KeyFile connections.
  50. .Parameter HostName
  51.    The server to SSH into
  52. .Parameter UserName
  53.    The user name to use for login
  54. .Parameter Password
  55.    The Password for login (Note: you really should pass this as a System.Security.SecureString, but it will accept a string instead)
  56. .Parameter KeyFile
  57.    An RSA keyfile for ssh secret key authentication (INSTEAD of username/password authentication).
  58. .Parameter Credentials
  59.    A PSCredential object containing all the information needed to log in. The login name should be in the form user@host
  60. .Parameter Passthru
  61.    If passthru is specified, the new SshShell is returned.
  62. .Example
  63.    New-SshSession Microsoft.com BillG Micr050ft
  64.    
  65.    Description
  66.    -----------
  67.    Creates a new ssh session with the ssh server at Microsoft.com using the 'BillG' as the login name and 'Micr050ft' as the password (please don't bother trying that).
  68. .Example
  69.    New-SshSession Microsoft.com -Keyfile BillGates.ppk
  70.    
  71.    Description
  72.    -----------
  73.    Creates a new ssh session with the ssh server at Microsoft.com using the credentials supplied in the BillGates.ppk private key file.
  74. .Example
  75.    $MSCred = Get-Credential BillG@Microsoft.com  # prompts for password
  76.    New-SshSession $MSCred
  77.  
  78.    Description
  79.    -----------
  80.    Creates a new ssh session based on the supplied credentials. Uses the output of $MsCred.GetNetworkCredential() for the server to log into (domain) and the username and password.
  81. #>
  82. [CmdletBinding(DefaultParameterSetName='NamePass')]
  83. Param(
  84.    [Parameter(Position=0,Mandatory=$true,ParameterSetName="NamePass",ValueFromPipelineByPropertyName=$true)]
  85.    [Parameter(Position=0,Mandatory=$true,ParameterSetName="RSAKeyFile",ValueFromPipelineByPropertyName=$true)]
  86.    [string]$HostName
  87. ,
  88.    [Parameter(Position=1,Mandatory=$false,ParameterSetName="NamePass",ValueFromPipelineByPropertyName=$true)]
  89.    [string]$UserName
  90. ,
  91.    [Parameter(Position=2,Mandatory=$false,ParameterSetName="NamePass",ValueFromPipelineByPropertyName=$true)]
  92.    $Password
  93. ,  
  94.    [Parameter(Position=1,Mandatory=$true,ParameterSetName="RSAKeyFile",ValueFromPipelineByPropertyName=$true)]
  95.    [string]$KeyFile
  96. ,
  97.    [Parameter(Position=0,Mandatory=$true,ParameterSetName="PSCredential",ValueFromPipeline=$true)]
  98.    [System.Management.Automation.PSCredential]$Credentials
  99. ,
  100.    [switch]$Passthru
  101. )
  102.    process {
  103.       switch($PSCmdlet.ParameterSetName) {
  104.          'RSAKeyFile'   {
  105.             $global:LastSshSession = new-object Tamir.SharpSsh.SshShell $HostName, $UserName
  106.             $global:LastSshSession.AddIdentityFile( (Convert-Path (Resolve-Path $KeyFile)) )
  107.            
  108.          }
  109.          'NamePass' {
  110.             if(!$UserName -or !$Password) {
  111.                $Credentials = $Host.UI.PromptForCredential("SSH Login Credentials",
  112.                                                 "Please specify credentials in user@host format",
  113.                                                 "$UserName@$HostName","")
  114.             } else {
  115.                if($Password -isnot [System.Security.SecureString]) {
  116.                   $Password = ConvertTo-SecureString $Password
  117.                }
  118.                $Credentials = New-Object System.Management.Automation.PSCredential "$UserName@$HostName", $Password
  119.             }
  120.          }
  121.       }
  122.       if($Credentials) {
  123.          $global:LastSshSession = new-object Tamir.SharpSsh.SshShell `
  124.                                           $Credentials.GetNetworkCredential().Domain,
  125.                                           $Credentials.GetNetworkCredential().UserName,
  126.                                           $Credentials.GetNetworkCredential().Password
  127.       }
  128.  
  129.       $global:LastSshSession.Connect()
  130.       $global:LastSshSession.RemoveTerminalEmulationCharacters = $true
  131.      
  132.       if($Passthru) { return $global:LastSshSession }
  133.      
  134.       $global:LastSshSession.WriteLine("")
  135.       sleep -milli 500
  136.       $global:defaultSshPrompt = [regex]::Escape( $global:LastSshSession.Expect().Split("`n")[-1] )
  137.    }
  138. }
  139.  
  140. function Remove-SshSession {
  141. <#
  142.    .Synopsis
  143.       Exits the open SshSession
  144. #>
  145. Param([Tamir.SharpSsh.SshShell]$SshShell=$global:LastSshSession)
  146.    $SshShell.WriteLine( "exit" )
  147.    sleep -milli 500
  148.    if($SshShell.ShellOpened) { Write-Warning "Shell didn't exit cleanly, closing anyway." }
  149.    $SshShell.Close()
  150.    $SshShell = $null
  151. }
  152.  
  153. function Invoke-Ssh {
  154. <#
  155.    .Synopsis
  156.       Executes an SSH command and Receives output
  157.    .Description
  158.       Invoke-Ssh is basically the same as a Send-Ssh followed by a Receive-Ssh, except that Expect defaults to $defaultSshPrompt (which is read in New-SshSession)
  159.    .Parameter Command
  160.       The command to send
  161.    .Parameter Expect
  162.       A regular expression for expect. The ssh session will wait for a line that matches this regular expression to be output before returning, and will return all the text up to AND INCLUDING the line that matches.
  163.       Defaults
  164.    .Parameter SshShell
  165.       The shell to invoke against. Defaults to the LastSshSession
  166. #>
  167. Param(
  168.    [string]$Command
  169. ,  [regex]$Expect = $global:defaultSshPrompt ## there ought to be a non-regex parameter set...
  170. ,  [Tamir.SharpSsh.SshShell]$SshShell=$global:LastSshSession
  171. )
  172.  
  173.    if($SshShell.ShellOpened) {
  174.       $SshShell.WriteLine( $command )
  175.       if($expect) {
  176.          $SshShell.Expect( $expect ).Split("`n")
  177.       }
  178.       else {
  179.          sleep -milli 500
  180.          $SshShell.Expect().Split("`n")
  181.       }
  182.    }
  183.    else { throw "The ssh shell isn't open!" }
  184. }
  185.  
  186. function Send-Ssh {
  187. <#
  188.    .Synopsis
  189.       Executes an SSH command without receiving input
  190.    .Description
  191.       Sends a command to an ssh session
  192.    .Parameter Command
  193.       The command to send
  194.    .Parameter SshShell
  195.       The shell to send to. Defaults to the LastSshSession
  196. #>
  197. Param(
  198.    [string]$command
  199. ,  [Tamir.SharpSsh.SshShell]$SshShell=$global:LastSshSession
  200. )
  201.  
  202.    if($SshShell.ShellOpened) {
  203.       $SshShell.WriteLine( $command )
  204.    }
  205.    else { throw "The ssh shell isn't open!" }
  206. }
  207.  
  208. function Receive-Ssh {
  209. <#
  210.    .Synopsis
  211.       Receives output from an SSH session
  212.    .Description
  213.       Retrieves output from an SSH session until the text matches the Expect pattern
  214.    .Parameter Expect
  215.       A regular expression for expect. The ssh session will wait for a line that matches this regular expression to be output before returning, and will return all the text up to AND INCLUDING the line that matches.
  216.    .Parameter SshShell
  217.       The shell to wait for. Defaults to the LastSshSession
  218. #>
  219. Param(
  220.    [RegEx]$expect ## there ought to be a non-regex parameter set...
  221. ,  [Tamir.SharpSsh.SshShell]$SshShell=$global:LastSshSession
  222. )
  223.    if($SshShell.ShellOpened) {
  224.       if($expect) {
  225.          $SshShell.Expect( $expect ).Split("`n")
  226.       }
  227.       else {
  228.          sleep -milli 500
  229.          $SshShell.Expect().Split("`n")
  230.       }
  231.    }
  232.    else { throw "The ssh shell isn't open!" }
  233. }

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me