in dubboctl/pkg/hub/ssh/dialer.go [244:349]
func NewSSHClientConfig(url *nurl.URL, credentialsConfig Config) (*ssh.ClientConfig, error) {
var (
authMethods []ssh.AuthMethod
signers []ssh.Signer
err error
)
if pw, found := url.User.Password(); found {
authMethods = append(authMethods, ssh.Password(pw))
}
// add signer from explicit identity parameter
if credentialsConfig.Identity != "" {
s, err := publicKey(credentialsConfig.Identity, []byte(credentialsConfig.Identity), credentialsConfig.PassPhraseCallback)
if err != nil {
return nil, fmt.Errorf("failed to parse identity file: %w", err)
}
signers = append(signers, s)
}
// add signers from ssh-agent
if sock, found := os.LookupEnv("SSH_AUTH_SOCK"); found && sock != "" {
var agentSigners []ssh.Signer
var agentConn net.Conn
agentConn, err = dialSSHAgentConnection(sock)
if err != nil {
return nil, fmt.Errorf("failed to connect to ssh-agent's socket: %w", err)
}
agentSigners, err = agent.NewClient(agentConn).Signers()
if err != nil {
return nil, fmt.Errorf("failed to get signers from ssh-agent: %w", err)
}
signers = append(signers, agentSigners...)
}
// if there is no explicit identity file nor keys from ssh-agent then
// add keys with standard name from ~/.ssh/
if len(signers) == 0 {
var defaultKeyPaths []string
if home, err := os.UserHomeDir(); err == nil {
for _, keyName := range knownKeyNames {
p := filepath.Join(home, ".ssh", keyName)
fi, err := os.Stat(p)
if err != nil {
continue
}
if fi.Mode().IsRegular() {
defaultKeyPaths = append(defaultKeyPaths, p)
}
}
}
if len(defaultKeyPaths) == 1 {
s, err := publicKey(defaultKeyPaths[0], []byte(credentialsConfig.PassPhrase), credentialsConfig.PassPhraseCallback)
if err != nil {
return nil, err
}
signers = append(signers, s)
}
}
if len(signers) > 0 {
dedup := make(map[string]ssh.Signer)
// Dedup signers based on fingerprint, ssh-agent keys override explicit identity
for _, s := range signers {
fp := ssh.FingerprintSHA256(s.PublicKey())
// if _, found := dedup[fp]; found {
// key updated
// }
dedup[fp] = s
}
var uniq []ssh.Signer
for _, s := range dedup {
uniq = append(uniq, s)
}
authMethods = append(authMethods, ssh.PublicKeysCallback(func() ([]ssh.Signer, error) {
return uniq, nil
}))
}
if len(authMethods) == 0 && credentialsConfig.PasswordCallback != nil {
authMethods = append(authMethods, ssh.PasswordCallback(credentialsConfig.PasswordCallback))
}
const sshTimeout = 5
clientConfig := &ssh.ClientConfig{
User: url.User.Username(),
Auth: authMethods,
HostKeyCallback: createHostKeyCallback(credentialsConfig.HostKeyCallback),
HostKeyAlgorithms: []string{
ssh.KeyAlgoECDSA256,
ssh.KeyAlgoECDSA384,
ssh.KeyAlgoECDSA521,
ssh.KeyAlgoED25519,
ssh.KeyAlgoRSASHA256,
ssh.KeyAlgoRSASHA512,
ssh.KeyAlgoRSA,
ssh.KeyAlgoDSA,
},
Timeout: sshTimeout * time.Second,
}
return clientConfig, nil
}