diff --git a/client.go b/client.go index a1165b2..07e37cf 100644 --- a/client.go +++ b/client.go @@ -6,11 +6,14 @@ package goph import ( "context" "fmt" + "strconv" + "strings" "io" "net" "os" "time" + "github.com/kevinburke/ssh_config" "github.com/pkg/sftp" "golang.org/x/crypto/ssh" ) @@ -35,9 +38,51 @@ type Config struct { // DefaultTimeout is the timeout of ssh client connection. var DefaultTimeout = 20 * time.Second +func GetAuth(host string) (Auth, error) { + auth, err := Key(getSshConfig(host, "IdentityFile"), "") + if err != nil { + return nil, fmt.Errorf("get key: %w", err) + } + return auth, nil +} + +func getSshConfig(alias string, key string) string { + // to fix https://github.com/kevinburke/ssh_config/issues/61 issue + return strings.Trim(ssh_config.Get(alias, key), "\"") +} + +func NewWithConfigFileHostKeyCallback(name string, callback ssh.HostKeyCallback) (*Client, error){ + auth, err := GetAuth(name) + if err != nil { + return nil, err + } + port, err := strconv.Atoi(getSshConfig(name, "Port")) + if err != nil { + return nil, err + } + + return NewConn(&Config{ + User: getSshConfig(name, "User"), + Addr: getSshConfig(name, "HostName"), + Port: uint(port), + Auth: auth, + Timeout: DefaultTimeout, + Callback: callback, + }) + +} + +// NewWithConfigFile starts a new ssh connection with given config file, the host public key must be in known hosts. +func NewWithConfigFile(name string) (*Client, error) { + callback, err := DefaultKnownHosts() + if err != nil { + return nil, err + } + return NewWithConfigFileHostKeyCallback(name, callback) +} + // New starts a new ssh connection, the host public key must be in known hosts. func New(user string, addr string, auth Auth) (c *Client, err error) { - callback, err := DefaultKnownHosts() if err != nil { @@ -70,6 +115,10 @@ func NewUnknown(user string, addr string, auth Auth) (*Client, error) { }) } +func NewWithConfigFileUnknown(name string) (*Client, error) { + return NewWithConfigFileHostKeyCallback(name, ssh.InsecureIgnoreHostKey()) +} + // NewConn returns new client and error if any. func NewConn(config *Config) (c *Client, err error) { diff --git a/cmd.go b/cmd.go index 3a4608f..2178463 100644 --- a/cmd.go +++ b/cmd.go @@ -6,9 +6,10 @@ package goph import ( "context" "fmt" + "strings" + "github.com/pkg/errors" "golang.org/x/crypto/ssh" - "strings" ) // Cmd it's like os/exec.Cmd but for ssh session. diff --git a/go.mod b/go.mod index f7e98dc..b86a922 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/melbahja/goph go 1.13 require ( + github.com/kevinburke/ssh_config v1.1.0 // indirect github.com/pkg/errors v0.9.1 github.com/pkg/sftp v1.13.5 golang.org/x/crypto v0.6.0 diff --git a/go.sum b/go.sum index eea2896..4aecd8a 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/kevinburke/ssh_config v1.1.0 h1:pH/t1WS9NzT8go394IqZeJTMHVm6Cr6ZJ6AQ+mdNo/o= +github.com/kevinburke/ssh_config v1.1.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=