55 "log"
66 "net"
77 "os"
8- "os/user"
98 "path/filepath"
109 "strings"
1110
@@ -39,19 +38,22 @@ func (u *ConnectionURI) parseAuthMethods(target string, sshcfg *ssh_config.Confi
3938 // 2. load override as specified in ssh config
4039 // 3. load default ssh keyfile path
4140 sshKeyPaths := []string {}
41+
4242 sshKeyPath := q .Get ("keyfile" )
4343 if sshKeyPath != "" {
4444 sshKeyPaths = append (sshKeyPaths , sshKeyPath )
4545 }
4646
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+ }
5254 }
5355
54- if len (keyPaths ) == 0 {
56+ if len (sshKeyPaths ) == 0 {
5557 log .Printf ("[DEBUG] found no ssh keys, using default keypath" )
5658 sshKeyPaths = []string {defaultSSHKeyPath }
5759 }
@@ -116,14 +118,17 @@ func (u *ConnectionURI) parseAuthMethods(target string, sshcfg *ssh_config.Confi
116118// construct the whole ssh connection, which can consist of multiple hops if using proxy jumps,
117119// the ssh configuration file is loaded once and passed along to each host connection.
118120func (u * ConnectionURI ) dialSSH () (net.Conn , error ) {
121+ var sshcfg * ssh_config.Config = nil
122+
119123 sshConfigFile , err := os .Open (os .ExpandEnv (defaultSSHConfigFile ))
120124 if err != nil {
121125 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+ }
123131
124- sshcfg , err := ssh_config .Decode (sshConfigFile )
125- if err != nil {
126- log .Printf ("[WARN] Failed to parse ssh config file: %v" , err )
127132 }
128133
129134 // configuration loaded, build tunnel
@@ -164,11 +169,11 @@ func (u *ConnectionURI) dialHost(target string, sshcfg *ssh_config.Config, depth
164169 log .Printf ("[DEBUG] ssh Port is overridden to: '%s'" , port )
165170 }
166171
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
172177 log .Printf ("[DEBUG] HostName is overridden to: '%s'" , hostName )
173178 }
174179 }
@@ -182,18 +187,22 @@ func (u *ConnectionURI) dialHost(target string, sshcfg *ssh_config.Config, depth
182187 if knownHostsVerify == "ignore" {
183188 skipVerify = true
184189 } 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+ }
188195 }
189196 }
190197
191198 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+ }
197206 }
198207 }
199208
@@ -226,10 +235,12 @@ func (u *ConnectionURI) dialHost(target string, sshcfg *ssh_config.Config, depth
226235 return err
227236 }
228237
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+ }
233244 }
234245
235246 }
@@ -240,46 +251,47 @@ func (u *ConnectionURI) dialHost(target string, sshcfg *ssh_config.Config, depth
240251 HostKeyAlgorithms : hostKeyAlgorithms ,
241252 Timeout : dialTimeout ,
242253 }
254+ var bastion * ssh.Client = nil
255+ var bastion_proxy string = ""
243256
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+ }
247262 }
248263
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+ }
258274 }
259275 }
260276
261- if cfg .User == "" {
277+ // cfg.User value defaults to u.User.Username()
278+ if sshcfg != nil {
262279 sshu , err := sshcfg .Get (target , "User" )
263- log .Printf ("[DEBUG] SSH User for target '%v' is '%v'" , target , sshu )
264280 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
271283 }
272- cfg .User = sshu
273284 }
274285
286+
275287 cfg .Auth = u .parseAuthMethods (target , sshcfg )
276288 if len (cfg .Auth ) < 1 {
277289 return nil , fmt .Errorf ("could not configure SSH authentication methods" )
278290 }
279291
280292 if bastion != nil {
281293 // 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 )
283295 // Dial a connection to the service host, from the bastion
284296 conn , err := bastion .Dial ("tcp" , net .JoinHostPort (hostName , port ))
285297 if err != nil {
0 commit comments