-
Notifications
You must be signed in to change notification settings - Fork 24
/
client.go
94 lines (81 loc) · 2.12 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package ssh
import (
stdio "io"
"github.com/Scalingo/cli/config"
"github.com/Scalingo/cli/crypto/sshkeys"
"github.com/Scalingo/go-scalingo/debug"
"golang.org/x/crypto/ssh"
"gopkg.in/errgo.v1"
)
var (
ErrNoAuthSucceed = errgo.Newf("No authentication method has succeeded")
)
type ConnectOpts struct {
Host string
Identity string
}
func Connect(opts ConnectOpts) (*ssh.Client, ssh.Signer, error) {
var (
err error
privateKeys []ssh.Signer
)
if opts.Identity == "ssh-agent" {
var agentConnection stdio.Closer
privateKeys, agentConnection, err = sshkeys.ReadPrivateKeysFromAgent()
if err != nil {
return nil, nil, errgo.Mask(err)
}
defer agentConnection.Close()
}
if len(privateKeys) == 0 {
if opts.Identity == "ssh-agent" {
opts.Identity = sshkeys.DefaultKeyPath
}
privateKey, err := sshkeys.ReadPrivateKey(opts.Identity)
if err != nil {
return nil, nil, errgo.Mask(err)
}
privateKeys = append(privateKeys, privateKey)
}
debug.Println("Identity used:", opts.Identity, "Private keys:", len(privateKeys))
client, key, err := ConnectToSSHServer(ConnectSSHOpts{
Host: opts.Host,
Keys: privateKeys,
})
if err != nil {
return nil, nil, err
}
debug.Println("SSH connection:", client.LocalAddr(), "Key:", string(key.PublicKey().Marshal()))
return client, key, nil
}
type ConnectSSHOpts struct {
Host string
Keys []ssh.Signer
}
func ConnectToSSHServer(opts ConnectSSHOpts) (*ssh.Client, ssh.Signer, error) {
var (
client *ssh.Client
privateKey ssh.Signer
err error
)
for _, privateKey = range opts.Keys {
client, err = ConnectToSSHServerWithKey(opts.Host, privateKey)
if err == nil {
break
} else {
config.C.Logger.Println("Fail to connect to the SSH server", err)
}
}
if client == nil {
return nil, nil, ErrNoAuthSucceed
}
return client, privateKey, nil
}
func ConnectToSSHServerWithKey(host string, key ssh.Signer) (*ssh.Client, error) {
sshConfig := &ssh.ClientConfig{
User: "git",
Auth: []ssh.AuthMethod{ssh.PublicKeys(key)},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
return ssh.Dial("tcp", host, sshConfig)
}