ykore::tech_memo

技術的な事を適当に書きます

PowerShell で SSH (Posh-ssh)

100台以上あるCisco製ネットワーク機器のコンフィグのバックアップを取りたかったので、TeraTerm マクロでも使うかと思っていたら、Posh-ssh という PowerShell から SSH/SFTP/SCP が使える素敵なモジュールが公開されていたのでこいつを使うことにした。

github.com

インストール

インストールは %USERPROFILE%\Documents\WindowsPowerShell\Modules\Posh-SSH というフォルダを作り、GitHub の Releases からダウンロードしたファイル(.psm1 など)を展開してから Import-Module -Name Posh-SSH すれば良かった。注意事項としてはダウンロードしたファイルはファイルのプロパティから「インターネットから拾ってきたファイル」フラグを無効化する必要があった(大量にファイルがある場合は一旦Zip化して再展開すれば一斉に外れる)。

利用できる関数やコマンドレットは以下のとおりだが、コマンドによっては鍵認証が使えたり使えなかったりする。

> Get-Command -Module posh-ssh                                                                       

CommandType     Name                                               ModuleName                                           
-----------     ----                                               ----------                                           
Function        Get-PoshSSHModVersion                              posh-ssh                                             
Function        Get-SFTPChildItem                                  posh-ssh                                             
Function        Get-SFTPContent                                    posh-ssh                                             
Function        Get-SFTPLocation                                   posh-ssh                                             
Function        Get-SFTPPathAttribute                              posh-ssh                                             
Function        Get-SFTPSession                                    posh-ssh                                             
Function        Get-SSHPortForward                                 posh-ssh                                             
Function        Get-SSHSession                                     posh-ssh                                             
Function        Get-SSHTrustedHost                                 posh-ssh                                             
Function        Invoke-SSHCommand                                  posh-ssh                                             
Function        Invoke-SSHCommandStream                            posh-ssh                                             
Function        Invoke-SSHStreamExpectAction                       posh-ssh                                             
Function        Invoke-SSHStreamExpectSecureAction                 posh-ssh                                             
Function        Invoke-SSHStreamShellCommand                       posh-ssh                                             
Function        Move-SFTPItem                                      posh-ssh                                             
Function        New-SFTPFileStream                                 posh-ssh                                             
Function        New-SFTPItem                                       posh-ssh                                             
Function        New-SFTPSymlink                                    posh-ssh                                             
Function        New-SSHDynamicPortForward                          posh-ssh                                             
Function        New-SSHLocalPortForward                            posh-ssh                                             
Function        New-SSHRemotePortForward                           posh-ssh                                             
Function        New-SSHShellStream                                 posh-ssh                                             
Function        New-SSHTrustedHost                                 posh-ssh                                             
Function        Remove-SFTPItem                                    posh-ssh                                             
Function        Remove-SFTPSession                                 posh-ssh                                             
Function        Remove-SSHSession                                  posh-ssh                                             
Function        Remove-SSHTrustedHost                              posh-ssh                                             
Function        Rename-SFTPFile                                    posh-ssh                                             
Function        Set-SFTPContent                                    posh-ssh                                             
Function        Set-SFTPLocation                                   posh-ssh                                             
Function        Set-SFTPPathAttribute                              posh-ssh                                             
Function        Start-SSHPortForward                               posh-ssh                                             
Function        Stop-SSHPortForward                                posh-ssh                                             
Function        Test-SFTPPath                                      posh-ssh                                             
Cmdlet          Get-SCPFile                                        posh-ssh                                             
Cmdlet          Get-SCPFolder                                      posh-ssh                                             
Cmdlet          Get-SCPItem                                        posh-ssh                                             
Cmdlet          Get-SFTPFile                                       posh-ssh                                             
Cmdlet          Get-SFTPItem                                       posh-ssh                                             
Cmdlet          New-SFTPSession                                    posh-ssh                                             
Cmdlet          New-SSHSession                                     posh-ssh                                             
Cmdlet          Set-SCPFile                                        posh-ssh                                             
Cmdlet          Set-SCPFolder                                      posh-ssh                                             
Cmdlet          Set-SCPItem                                        posh-ssh                                             
Cmdlet          Set-SFTPFile                                       posh-ssh                                             
Cmdlet          Set-SFTPFolder                                     posh-ssh                                             
Cmdlet          Set-SFTPItem                                       posh-ssh

ログインまで

ログインしてセッションを張るまでの手順は以下とおり。認証情報は直接指定できないので PSCredential オブジェクトを作った上で渡している。 -AcceptKey オプションを指定すると、初回ログイン時のSSHフィンガープリントの確認をスキップできる。 New-SSHSession を複数実行すると複数セッションが張れる(最初の SessionId は 0、複数実行すると使用可能な SessionId が増える)。

$USERNAME = "ユーザID"
$PASSWORD = "パスワード"
$TARGETHOST = "対象機器のIPアドレス"
$ADMINPASSWORD = "特権モードのパスワード"

$securePasswd = ConvertTo-SecureString -String $PASSWORD -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($USERNAME, $securePasswd)

$sshSession = New-SSHSession -ComputerName $TARGETHOST -Credential $cred -AcceptKey -Verbose
$session = Get-SSHSession -SessionId 0

次からは使い方によってコマンドを使い分けていく。

コマンドを単純に実行するだけ

Linux OSに対してコマンドを実行して結果を返すだけの単純な使い方であれば Invoke-SSHCommand で十分だ。セッション指定もIDだけ。

Invoke-SSHCommand -Command "uname -a" -SessionId 0

Host       : ubuntu-test
Output     : {Linux ubuntu-test 4.15.0-111-generic #112-Ubuntu SMP Thu Jul 9 20:32:34 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux}                                                                                                   
ExitStatus : 0

しかし、Ciscoネットワーク機器に対して実行すると失敗する(機器によっては成功するかも?未検証)。 また、 sudopasswd などの対話型入力が必要なコマンドでも失敗するので、そういうときは別のコマンドを使用する。

対話型コマンドを実行する

対話型コマンドに対して自動化させるときは Linux なら expect のような仕組みが必要だが、Posh-ssh では Invoke-SSHStreamExpectAction という便利なコマンドがあるのでこれを使用する。 このコマンドは expect と同じく、特定の文字列を見つけたら -Action で入力する文字を指定するコマンドである。 ここでは enable を発行し特権パスワードを入力して特権EXECモードに移行している。 また、terminal length 0 を発行するときには Invoke-SSHStreamShellCommand という Invoke-SSHCommand の代わりとなるコマンドを使用している。

Invoke-SSHStreamExpectAction -ShellStream $stream -Command "enable" -ExpectString 'Password:' -Action "$($ADMINPASSWORD)" -Timeout 3
Invoke-SSHStreamShellCommand -ShellStream $stream -Command "terminal length 0"

コンフィグを取得する

いよいよCisco IOSのコンフィグを取得するのであるが、Posh-sshのバグなのか機器によっては結果が標準出力に表示されてしまったことがあったので、諦めて $stream.Write()$stream.Read() で結果を取得している。 改行コードまで含めて入力なので注意すること。

## 諦め
## $config = Invoke-SSHStreamShellCommand -ShellStream $stream -Command "show running-config"

$stream.Write("show running-config`n")
Sleep 10
$config = $stream.Read()

後片付け

最後は exit コマンドを発行してログアウトしておく。

Invoke-SSHStreamShellCommand -ShellStream $stream -Command "exit"

これで $config 変数に show running-config の結果が格納されているので適当にファイル出力しておわり。