Nヵ月ぶりに技術ブログを書くで候
概要
正直なことを話すとたぶん、人はcrypto: golang.org/x/crypto/sshさえ読めばGolangでSSHを書けるようになる。しかし、50回ぐらい読んでいるので個人的によく使うモジュールについてのメモである。 本当にcrypto: golang.org/x/crypto/sshのドキュメントが優秀なのでここを見れば解決するのとりあえず、読んでくれそれだけではこのブログの価値はクソ以下なのでもはや、サンプルコードを書くしかない
パスワード認証
パスワード認証のみでsshを行いたければ&ssh.ClientConfigの中でHostKeyCallback: ssh.InsecureIgnoreHostKey() を設定してあげなければならない。
あとは、ssh.Dial でセッションを繋いで(切るの忘れずに) conn.NewSession()でアクセスを行って session.Stdout = &bで標準出力を確認しながらsession.Run()でコマンドを実行させる。
https://godoc.org/golang.org/x/crypto/ssh#Dial より
Dialは、指定されたSSHサーバーへのクライアント接続を開始します。これは、指定されたネットワークアドレスに接続し、SSHハンドシェイクを開始してからクライアントをセットアップする便利な機能です。着信チャネルおよび要求へのアクセスには、代わりにNewClientConnでnet.Dialを使用します。 上記のような
package main
import (
"bytes"
"log"
"golang.org/x/crypto/ssh"
)
func main() {
ip := "****.**.***.***"
port := "22"
user := "root"
pass := "********************************"
config := &ssh.ClientConfig{
User: user,
HostKeyCallback: ssh.InsecureIgnoreHostKey(), // https://github.com/golang/go/issues/19767
Auth: []ssh.AuthMethod{
ssh.Password(pass),
},
}
conn, err := ssh.Dial("tcp", ip+":"+port, config)
if err != nil {
log.Println(err)
}
defer conn.Close()
session, err := conn.NewSession()
if err != nil {
log.Println(err)
}
defer session.Close()
//Check whoami
var b bytes.Buffer
session.Stdout = &b
remote_command := "/usr/bin/whoami"
if err := session.Run(remote_command); err != nil {
log.Fatal("Failed to run: " + err.Error())
}
log.Println(remote_command + ":" + b.String())
}
鍵認証
パスワード認証と鍵認証の差は&ssh.ClientConfigのAuth: ssh.AuthMethod{} を変更すればよいだけである
package main
import (
"bytes"
"log"
"golang.org/x/crypto/ssh"
)
func main() {
ip := "***.***.***.***"
port := "22"
user := "root"
pass := "*****************"
config := &ssh.ClientConfig{
User: user,
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
Auth: []ssh.AuthMethod{
ssh.Password(pass),
},
}
conn, err := ssh.Dial("tcp", ip+":"+port, config)
if err != nil {
log.Println(err)
}
defer conn.Close()
session, err := conn.NewSession()
if err != nil {
log.Println(err)
}
defer session.Close()
//Check whoami
var b bytes.Buffer
session.Stdout = &b
remote_command := "/usr/bin/whoami"
if err := session.Run(remote_command); err != nil {
log.Fatal("Failed to run: " + err.Error())
}
log.Println(remote_command + ":" + b.String())
}
利用したコードはここ workspace_2019/blog/crypto_ssh at master · nwiizo/workspace_2019 · GitHub に載せてあるので自由に使ってください。
まとめ
基本的には crypto: golang.org/x/crypto/ssh を読めばいいのです。が、もし Golang で sshをいい感じにやっていくにはまだまだ工夫していかねばなりません。設定ファイルとの呼び出しをどうするのか?N個同時にセッションを持ちたい時にはどういった工夫が必要なのか?考慮すべき事項はたくさんあります。ですが 皆さん、オペレーションはどんどん自動化していきましょう。