PowerShell で SSH (Posh-ssh)
100台以上あるCisco製ネットワーク機器のコンフィグのバックアップを取りたかったので、TeraTerm マクロでも使うかと思っていたら、Posh-ssh という PowerShell から SSH/SFTP/SCP が使える素敵なモジュールが公開されていたのでこいつを使うことにした。
インストール
インストールは %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ネットワーク機器に対して実行すると失敗する(機器によっては成功するかも?未検証)。
また、 sudo
や passwd
などの対話型入力が必要なコマンドでも失敗するので、そういうときは別のコマンドを使用する。
対話型コマンドを実行する
対話型コマンドに対して自動化させるときは 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
の結果が格納されているので適当にファイル出力しておわり。