概要
正直なことを話すとたぶん、人はcrypto: golang.org/x/crypto/sshさえ読めばGolangでSSHを書けるようになる。
しかし、サーバーを実際に運用していくことになれば踏み台サーバーを用意して100台のサーバーにアクセスすることもよくあることである。
100台のサーバーにアクセスしたいのに前回 のようなやり方を取っていると100台分のサーバーに設定をせねばならずたぶんなのですがviperを用いて設定ファイルを書くことになるのだと思います。2重管理による徒労感は半端ないです。実装も膨らむし...
ssh_configが使いたい
kevinburke/ssh_configというライブラリには ssh_config を読み込む機能がありますのでこれを使って ~/.ssh/config の設定情報を使ってSSH接続をしてみます(サンプルはlocalhost)。
package main
import (
"bytes"
"github.com/kevinburke/ssh_config"
"golang.org/x/crypto/ssh"
"io/ioutil"
"log"
)
func main() {
host := "localhost"
user := ssh_config.Get(host, "User")
addr := ssh_config.Get(host, "Hostname") + ":" + ssh_config.Get(host, "Port")
auth := []ssh.AuthMethod{}
buf, err := ioutil.ReadFile(ssh_config.Get(host, "IdentityFile"))
if err != nil {
panic(err)
}
key, err := ssh.ParsePrivateKey(buf)
if err != nil {
panic(err)
}
auth = append(auth, ssh.PublicKeys(key))
config := &ssh.ClientConfig{
User: user,
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
Auth: auth,
}
conn, err := ssh.Dial("tcp", addr, 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/configを使って *ssh.Client を作成する