This repository was archived by the owner on Aug 6, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathtarget.go
More file actions
95 lines (84 loc) · 2.48 KB
/
target.go
File metadata and controls
95 lines (84 loc) · 2.48 KB
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
package main
import (
"io/ioutil"
"strings"
"golang.org/x/crypto/ssh"
"os/user"
"fmt"
)
/* {
* "username": "bob",
* "host": "myserver:22",
* "auth": {
* "method": "password" or "pki",
* "artifact": "<secret>" or "/path/to/private_key.pem"
* }
* }
*/
type targetConfig struct {
User string `json:"username"`
Host string `json:"host"`
Auth struct {
Method string `json:"method"`
Artifact string `json:"artifact"`
} `json:"auth"`
}
// Fix the configuration before handing it to clientConfig():
// - if ~ found in pki artifact, expand it to home directory
func (target *targetConfig) Preprocess() error {
// A ~ in the private key path? Try to expand it!
if target.Auth.Method == "pki" &&
strings.Contains(target.Auth.Artifact, "~") {
active, err := user.Current()
if err != nil {
return fmt.Errorf("failed getting current user while expanding home (~): %s", err.Error())
}
target.Auth.Artifact = strings.Replace(target.Auth.Artifact, "~", active.HomeDir, 1)
}
return nil
}
// Generate a password-auth'd ssh ClientConfig
func (target *targetConfig) password() (*ssh.ClientConfig, error) {
// Password might be "" so can't check len(artifact)
return &ssh.ClientConfig{
User: target.User,
Auth: []ssh.AuthMethod{
ssh.Password(target.Auth.Artifact),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}, nil
}
// Generate a PKI-auth'd ssh ClientConfig
func (target *targetConfig) pki() (*ssh.ClientConfig, error) {
pem, err := ioutil.ReadFile(target.Auth.Artifact)
if err != nil {
return nil, fmt.Errorf("failed reading key: %s", err.Error())
}
signer, err := ssh.ParsePrivateKey(pem)
if err != nil {
return nil, fmt.Errorf("failed parsing key: %s", err.Error())
}
return &ssh.ClientConfig{
User: target.User,
Auth: []ssh.AuthMethod{
ssh.PublicKeys(signer),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}, nil
}
// Figure out how to generate the ssh ClientConfig, or bail
func (target *targetConfig) ClientConfig() (*ssh.ClientConfig, error) {
if len(target.User) == 0 {
return nil, fmt.Errorf("target config requires a username")
}
// Only supports password and pki methods. Soon interactive as well?
switch target.Auth.Method {
case "password":
return target.password()
case "pki":
return target.pki()
default:
err := fmt.Errorf("unknown authentication method %s", target.Auth.Method)
return nil, err
}
}