-
Notifications
You must be signed in to change notification settings - Fork 2
/
config_host.go
155 lines (131 loc) · 4.01 KB
/
config_host.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package main
import (
"errors"
"fmt"
"os"
"time"
"golang.org/x/crypto/ssh"
)
type tomlNetwork struct {
Host string
Port int
Ciphers []string
SSHConnTimeWarn Duration `toml:"ssh_connection_time_warn"`
}
type tomlAuth struct {
User string
Password string
Key string
KeyPassphrase string `toml:"key_passphrase"`
SSHAgent bool `toml:"ssh_agent"`
Pubkey string
}
type tomlHost struct {
Disabled bool
Name string
Network tomlNetwork
Auth tomlAuth
Classes []string
Default []tomlDefault
}
func tomlHostToHost(tHost *tomlHost, config *Config, filename string) (*Host, error) {
var (
connection Connection
host Host
)
host.Connection = &connection
host.Filename = filename
if tHost.Disabled == true && config.loadDisabled == false {
return nil, nil
}
host.Disabled = (tHost.Disabled == true)
if tHost.Name == "" {
return nil, errors.New("invalid or missing 'name'")
}
host.Name = tHost.Name
if tHost.Classes == nil {
return nil, errors.New("no valid 'classes' parameter found")
}
if len(tHost.Classes) == 0 {
return nil, errors.New("empty classes")
}
for _, class := range tHost.Classes {
if !IsValidTokenName(class) {
return nil, fmt.Errorf("invalid class name '%s'", class)
}
}
host.Classes = tHost.Classes
host.Defaults = make(map[string]interface{})
if err := checkTomlDefault(host.Defaults, tHost.Default); err != nil {
return nil, err
}
if tHost.Network.Host == "" {
return nil, errors.New("[network] section, invalid or missing 'host'")
}
connection.Host = tHost.Network.Host
if tHost.Network.Port == 0 {
return nil, errors.New("[network] section, invalid or missing 'port'")
}
connection.Port = tHost.Network.Port
if tHost.Network.SSHConnTimeWarn.Duration < (1 * time.Second) {
return nil, errors.New("'ssh_connection_time_warn' can't be less than a second")
}
connection.SSHConnTimeWarn = tHost.Network.SSHConnTimeWarn.Duration
if tHost.Auth.User == "" {
return nil, errors.New("[auth] section, invalid or missing 'user'")
}
connection.User = tHost.Auth.User
connection.Ciphers = tHost.Network.Ciphers
if tHost.Auth.Key != "" && tHost.Auth.Password != "" {
return nil, errors.New("[auth] section, can't use key and password at the same time (see key_passphrase parameter, perhaps?)")
}
if tHost.Auth.KeyPassphrase != "" && tHost.Auth.Password != "" {
return nil, errors.New("[auth] section, can't use key_passphrase and password at the same time")
}
if tHost.Auth.SSHAgent == true && tHost.Auth.Password != "" {
return nil, errors.New("[auth] section, can't use SSH agent and password at the same time")
}
if tHost.Auth.SSHAgent == true && tHost.Auth.KeyPassphrase != "" {
return nil, errors.New("[auth] section, can't use SSH agent and key_passphrase at the same time")
}
if tHost.Auth.SSHAgent == true && tHost.Auth.Key != "" {
return nil, errors.New("[auth] section, can't use SSH agent and key at the same time (see pubkey parameter, perhaps?)")
}
if tHost.Auth.Key != "" {
fd, err := os.Open(tHost.Auth.Key)
if err != nil {
return nil, fmt.Errorf("can't access to key '%s': %s", tHost.Auth.Key, err)
}
fd.Close()
}
// !!! there's many returns following this line, be careful
if tHost.Auth.Password != "" {
connection.Auths = []ssh.AuthMethod{
ssh.Password(tHost.Auth.Password),
}
return &host, nil
}
if tHost.Auth.SSHAgent == true {
agent, err := SSHAgent(tHost.Auth.Pubkey)
if err != nil {
return nil, err
}
connection.Auths = []ssh.AuthMethod{
agent,
}
return &host, nil
}
if tHost.Auth.Key != "" && tHost.Auth.KeyPassphrase == "" {
connection.Auths = []ssh.AuthMethod{
PublicKeyFile(tHost.Auth.Key),
}
return &host, nil
}
if tHost.Auth.Key != "" && tHost.Auth.KeyPassphrase != "" {
connection.Auths = []ssh.AuthMethod{
PublicKeyFilePassPhrase(tHost.Auth.Key, tHost.Auth.KeyPassphrase),
}
return &host, nil
}
return nil, errors.New("[auth] section, at least one auth method is needed (password, key or ssh_agent)")
}