5
5
"log"
6
6
"net"
7
7
"os"
8
- "os/user"
9
8
"path/filepath"
10
9
"strings"
11
10
@@ -39,19 +38,22 @@ func (u *ConnectionURI) parseAuthMethods(target string, sshcfg *ssh_config.Confi
39
38
// 2. load override as specified in ssh config
40
39
// 3. load default ssh keyfile path
41
40
sshKeyPaths := []string {}
41
+
42
42
sshKeyPath := q .Get ("keyfile" )
43
43
if sshKeyPath != "" {
44
44
sshKeyPaths = append (sshKeyPaths , sshKeyPath )
45
45
}
46
46
47
- keyPaths , err := sshcfg .GetAll (target , "IdentityFile" )
48
- if err != nil {
49
- log .Printf ("[WARN] unable to get IdentityFile values - ignoring" )
50
- } else {
51
- sshKeyPaths = append (sshKeyPaths , keyPaths ... )
47
+ if sshcfg != nil {
48
+ keyPaths , err := sshcfg .GetAll (target , "IdentityFile" )
49
+ if err != nil {
50
+ log .Printf ("[WARN] unable to get IdentityFile values - ignoring" )
51
+ } else {
52
+ sshKeyPaths = append (sshKeyPaths , keyPaths ... )
53
+ }
52
54
}
53
55
54
- if len (keyPaths ) == 0 {
56
+ if len (sshKeyPaths ) == 0 {
55
57
log .Printf ("[DEBUG] found no ssh keys, using default keypath" )
56
58
sshKeyPaths = []string {defaultSSHKeyPath }
57
59
}
@@ -116,14 +118,17 @@ func (u *ConnectionURI) parseAuthMethods(target string, sshcfg *ssh_config.Confi
116
118
// construct the whole ssh connection, which can consist of multiple hops if using proxy jumps,
117
119
// the ssh configuration file is loaded once and passed along to each host connection.
118
120
func (u * ConnectionURI ) dialSSH () (net.Conn , error ) {
121
+ var sshcfg * ssh_config.Config = nil
122
+
119
123
sshConfigFile , err := os .Open (os .ExpandEnv (defaultSSHConfigFile ))
120
124
if err != nil {
121
125
log .Printf ("[WARN] Failed to open ssh config file: %v" , err )
122
- }
126
+ } else {
127
+ sshcfg , err = ssh_config .Decode (sshConfigFile )
128
+ if err != nil {
129
+ log .Printf ("[WARN] Failed to parse ssh config file: '%v' - sshconfig will be ignored." , err )
130
+ }
123
131
124
- sshcfg , err := ssh_config .Decode (sshConfigFile )
125
- if err != nil {
126
- log .Printf ("[WARN] Failed to parse ssh config file: %v" , err )
127
132
}
128
133
129
134
// configuration loaded, build tunnel
@@ -164,11 +169,11 @@ func (u *ConnectionURI) dialHost(target string, sshcfg *ssh_config.Config, depth
164
169
log .Printf ("[DEBUG] ssh Port is overridden to: '%s'" , port )
165
170
}
166
171
167
- hostName , err := sshcfg . Get ( target , "HostName" )
168
- if err = = nil {
169
- if hostName == "" {
170
- hostName = target
171
- } else {
172
+ hostName := target
173
+ if sshcfg ! = nil {
174
+ host , err := sshcfg . Get ( target , "HostName" )
175
+ if err == nil && host != "" {
176
+ hostName = host
172
177
log .Printf ("[DEBUG] HostName is overridden to: '%s'" , hostName )
173
178
}
174
179
}
@@ -182,18 +187,22 @@ func (u *ConnectionURI) dialHost(target string, sshcfg *ssh_config.Config, depth
182
187
if knownHostsVerify == "ignore" {
183
188
skipVerify = true
184
189
} else {
185
- strictCheck , err := sshcfg .Get (target , "StrictHostKeyChecking" )
186
- if err != nil && strictCheck == "yes" {
187
- skipVerify = false
190
+ if sshcfg != nil {
191
+ strictCheck , err := sshcfg .Get (target , "StrictHostKeyChecking" )
192
+ if err != nil && strictCheck == "yes" {
193
+ skipVerify = false
194
+ }
188
195
}
189
196
}
190
197
191
198
if knownHostsPath == "" {
192
- knownHosts , err := sshcfg .Get (target , "UserKnownHostsFile" )
193
- if err == nil && knownHosts != "" {
194
- knownHostsPath = knownHosts
195
- } else {
196
- knownHostsPath = defaultSSHKnownHostsPath
199
+ knownHostsPath = defaultSSHKnownHostsPath
200
+
201
+ if sshcfg != nil {
202
+ knownHosts , err := sshcfg .Get (target , "UserKnownHostsFile" )
203
+ if err == nil && knownHosts != "" {
204
+ knownHostsPath = knownHosts
205
+ }
197
206
}
198
207
}
199
208
@@ -226,10 +235,12 @@ func (u *ConnectionURI) dialHost(target string, sshcfg *ssh_config.Config, depth
226
235
return err
227
236
}
228
237
229
- keyAlgs , err := sshcfg .Get (target , "HostKeyAlgorithms" )
230
- if err == nil && keyAlgs != "" {
231
- log .Printf ("Got host key algorithms '%s'" , keyAlgs )
232
- hostKeyAlgorithms = strings .Split (keyAlgs , "," )
238
+ if sshcfg != nil {
239
+ keyAlgs , err := sshcfg .Get (target , "HostKeyAlgorithms" )
240
+ if err == nil && keyAlgs != "" {
241
+ log .Printf ("[DEBUG] HostKeyAlgorithms is overridden to '%s'" , keyAlgs )
242
+ hostKeyAlgorithms = strings .Split (keyAlgs , "," )
243
+ }
233
244
}
234
245
235
246
}
@@ -240,46 +251,47 @@ func (u *ConnectionURI) dialHost(target string, sshcfg *ssh_config.Config, depth
240
251
HostKeyAlgorithms : hostKeyAlgorithms ,
241
252
Timeout : dialTimeout ,
242
253
}
254
+ var bastion * ssh.Client = nil
255
+ var bastion_proxy string = ""
243
256
244
- proxy , err := sshcfg .Get (target , "ProxyCommand" )
245
- if err == nil && proxy != "" {
246
- log .Printf ("[WARNING] unsupported ssh ProxyCommand '%v'" , proxy )
257
+ if sshcfg != nil {
258
+ command , err := sshcfg .Get (target , "ProxyCommand" )
259
+ if err == nil && command != "" {
260
+ log .Printf ("[WARNING] unsupported ssh ProxyCommand '%v' - ignoring" , command )
261
+ }
247
262
}
248
263
249
- proxy , err = sshcfg .Get (target , "ProxyJump" )
250
- var bastion * ssh.Client
251
- if err == nil && proxy != "" {
252
- log .Printf ("[DEBUG] found ProxyJump '%v'" , proxy )
253
-
254
- // this is a proxy jump: we recurse into that proxy
255
- bastion , err = u .dialHost (proxy , sshcfg , depth + 1 )
256
- if err != nil {
257
- return nil , fmt .Errorf ("failed to connect to bastion host '%v': %w" , proxy , err )
264
+ if sshcfg != nil {
265
+ proxy , err := sshcfg .Get (target , "ProxyJump" )
266
+ if err == nil && proxy != "" {
267
+ log .Printf ("[DEBUG] found ProxyJump '%v'" , proxy )
268
+ // this is a proxy jump: we recurse into that proxy
269
+ bastion , err = u .dialHost (proxy , sshcfg , depth + 1 )
270
+ bastion_proxy = proxy
271
+ if err != nil {
272
+ return nil , fmt .Errorf ("failed to connect to bastion host '%v': %w" , proxy , err )
273
+ }
258
274
}
259
275
}
260
276
261
- if cfg .User == "" {
277
+ // cfg.User value defaults to u.User.Username()
278
+ if sshcfg != nil {
262
279
sshu , err := sshcfg .Get (target , "User" )
263
- log .Printf ("[DEBUG] SSH User for target '%v' is '%v'" , target , sshu )
264
280
if err != nil {
265
- log .Printf ("[DEBUG] ssh user: using current login" )
266
- u , err := user .Current ()
267
- if err != nil {
268
- return nil , fmt .Errorf ("unable to get username: %w" , err )
269
- }
270
- sshu = u .Username
281
+ log .Printf ("[DEBUG] ssh user for target '%v' is overridden to '%v'" , target , sshu )
282
+ cfg .User = sshu
271
283
}
272
- cfg .User = sshu
273
284
}
274
285
286
+
275
287
cfg .Auth = u .parseAuthMethods (target , sshcfg )
276
288
if len (cfg .Auth ) < 1 {
277
289
return nil , fmt .Errorf ("could not configure SSH authentication methods" )
278
290
}
279
291
280
292
if bastion != nil {
281
293
// if this is a proxied connection, we want to dial through the bastion host
282
- log .Printf ("[INFO] SSH connecting to '%v' (%v) through bastion host '%v'" , target , hostName , proxy )
294
+ log .Printf ("[INFO] SSH connecting to '%v' (%v) through bastion host '%v'" , target , hostName , bastion_proxy )
283
295
// Dial a connection to the service host, from the bastion
284
296
conn , err := bastion .Dial ("tcp" , net .JoinHostPort (hostName , port ))
285
297
if err != nil {
0 commit comments