-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathssh.go
108 lines (95 loc) · 2.13 KB
/
ssh.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package xk6ssh
import (
"bytes"
"fmt"
"io"
"os"
"path"
"github.com/spf13/afero"
"golang.org/x/crypto/ssh"
)
// K6SSH is the main export of the k6 extension
type K6SSH struct {
Session *ssh.Session
Client *ssh.Client
Config *ssh.ClientConfig
Out *bytes.Buffer
Stdin io.WriteCloser
fs afero.Fs
}
// ConnectionOptions provides configuration for the SSH session
type ConnectionOptions struct {
RsaKey string
Host string
Port int
Username string
Password string
}
func (k6ssh *K6SSH) rsaKeyAuthMethod(options ConnectionOptions) (ssh.AuthMethod, error) {
var pk string
if options.RsaKey != "" {
pk = options.RsaKey
} else {
pk = k6ssh.defaultKeyPath()
}
key, err := afero.ReadFile(k6ssh.fs, pk)
if err != nil {
return nil, err
}
signer, err := ssh.ParsePrivateKey(key)
if err != nil {
return nil, err
}
return ssh.PublicKeys(signer), nil
}
// Connect starts and SSH session with the provided options
func (k6ssh *K6SSH) Connect(options ConnectionOptions) error {
var authMethod ssh.AuthMethod
var err error
if options.Password != "" {
authMethod = ssh.Password(options.Password)
} else {
authMethod, err = k6ssh.rsaKeyAuthMethod(options)
if err != nil {
return err
}
}
k6ssh.Config = &ssh.ClientConfig{
Config: ssh.Config{},
User: options.Username,
Auth: []ssh.AuthMethod{authMethod},
// #nosec G106
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
ClientVersion: "",
Timeout: 0,
}
addr := fmt.Sprintf("%s:%d", options.Host, options.Port)
client, err := ssh.Dial("tcp", addr, k6ssh.Config)
if err != nil {
return err
}
k6ssh.Client = client
return nil
}
func (k6ssh *K6SSH) defaultKeyPath() string {
//nolint: forbidigo
home := os.Getenv("HOME")
if len(home) > 0 {
return path.Join(home, ".ssh/id_rsa")
}
return ""
}
// Run executes a remote command over SSH
func (k6ssh *K6SSH) Run(command string) (string, error) {
session, err := k6ssh.Client.NewSession()
if err != nil {
return "", err
}
defer func() {
_ = session.Close()
}()
var stdoutBuf bytes.Buffer
session.Stdout = &stdoutBuf
err = session.Run(command)
return stdoutBuf.String(), err
}