Skip to content

Commit be732d8

Browse files
committed
fix: SSH does not try multiple authentication methods of the same type
1 parent a7af336 commit be732d8

File tree

1 file changed

+16
-16
lines changed

1 file changed

+16
-16
lines changed

ssh.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ type SSH struct {
5858
type PasswordCallback func() (secret string, err error)
5959

6060
var (
61-
authMethodCache = sync.Map{}
61+
signerCache = sync.Map{}
6262
defaultKeypaths = []string{"~/.ssh/id_rsa", "~/.ssh/identity", "~/.ssh/id_dsa", "~/.ssh/id_ecdsa", "~/.ssh/id_ed25519"}
6363
dummyhostKeyPaths []string
6464
globalOnce sync.Once
@@ -407,33 +407,33 @@ func (c *SSH) clientConfig() (*ssh.ClientConfig, error) { //nolint:cyclop
407407
log.Tracef("%s: using %d passed-in auth methods", c, len(c.AuthMethods))
408408
config.Auth = c.AuthMethods
409409
} else if len(signers) > 0 {
410-
log.Debugf("%s: using all keys (%d) from ssh agent because a keypath was not explicitly given", c, len(signers))
411-
config.Auth = append(config.Auth, ssh.PublicKeys(signers...))
410+
log.Debugf("%s: using all keys (%d) from ssh agent", c, len(signers))
412411
}
413412

414413
for _, keyPath := range c.keyPaths {
415-
if am, ok := authMethodCache.Load(keyPath); ok {
414+
if am, ok := signerCache.Load(keyPath); ok {
416415
switch authM := am.(type) {
417-
case ssh.AuthMethod:
418-
log.Tracef("%s: using cached auth method for %s", c, keyPath)
419-
config.Auth = append(config.Auth, authM)
416+
case ssh.Signer:
417+
log.Tracef("%s: using cached signer for %s", c, keyPath)
418+
signers = append(signers, authM)
420419
case error:
421420
log.Tracef("%s: already discarded key %s: %v", c, keyPath, authM)
422421
default:
423422
log.Tracef("%s: unexpected type %T for cached auth method for %s", c, am, keyPath)
424423
}
425424
continue
426425
}
427-
privateKeyAuth, err := c.pkeySigner(signers, keyPath)
426+
signer, err := c.pkeySigner(signers, keyPath)
428427
if err != nil {
429428
log.Debugf("%s: failed to obtain a signer for identity %s: %v", c, keyPath, err)
430429
// store the error so this key won't be loaded again
431-
authMethodCache.Store(keyPath, err)
430+
signerCache.Store(keyPath, err)
432431
} else {
433-
authMethodCache.Store(keyPath, privateKeyAuth)
434-
config.Auth = append(config.Auth, privateKeyAuth)
432+
signerCache.Store(keyPath, signer)
433+
signers = append(signers, signer)
435434
}
436435
}
436+
config.Auth = append(config.Auth, ssh.PublicKeys(signers...))
437437

438438
if len(config.Auth) == 0 {
439439
return nil, fmt.Errorf("%w: no usable authentication method found", ErrCantConnect)
@@ -489,22 +489,22 @@ func (c *SSH) Connect() error {
489489
return nil
490490
}
491491

492-
func (c *SSH) pubkeySigner(signers []ssh.Signer, key ssh.PublicKey) (ssh.AuthMethod, error) {
492+
func (c *SSH) pubkeySigner(signers []ssh.Signer, key ssh.PublicKey) (ssh.Signer, error) {
493493
if len(signers) == 0 {
494494
return nil, fmt.Errorf("%w: signer not found for public key", ErrCantConnect)
495495
}
496496

497497
for _, s := range signers {
498498
if bytes.Equal(key.Marshal(), s.PublicKey().Marshal()) {
499499
log.Debugf("%s: signer for public key available in ssh agent", c)
500-
return ssh.PublicKeys(s), nil
500+
return s, nil
501501
}
502502
}
503503

504504
return nil, fmt.Errorf("%w: the provided key is a public key and is not known by agent", ErrAuthFailed)
505505
}
506506

507-
func (c *SSH) pkeySigner(signers []ssh.Signer, path string) (ssh.AuthMethod, error) {
507+
func (c *SSH) pkeySigner(signers []ssh.Signer, path string) (ssh.Signer, error) {
508508
log.Tracef("%s: checking identity file %s", c, path)
509509
key, err := os.ReadFile(path)
510510
if err != nil {
@@ -520,7 +520,7 @@ func (c *SSH) pkeySigner(signers []ssh.Signer, path string) (ssh.AuthMethod, err
520520
signer, err := ssh.ParsePrivateKey(key)
521521
if err == nil {
522522
log.Debugf("%s: using an unencrypted private key from %s", c, path)
523-
return ssh.PublicKeys(signer), nil
523+
return signer, nil
524524
}
525525

526526
var ppErr *ssh.PassphraseMissingError
@@ -543,7 +543,7 @@ func (c *SSH) pkeySigner(signers []ssh.Signer, path string) (ssh.AuthMethod, err
543543
if err != nil {
544544
return nil, fmt.Errorf("%w: protected key %s decoding failed: %w", ErrCantConnect, path, err)
545545
}
546-
return ssh.PublicKeys(signer), nil
546+
return signer, nil
547547
}
548548
}
549549

0 commit comments

Comments
 (0)