62 lines
1.6 KiB
Go
62 lines
1.6 KiB
Go
package ssh
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"net"
|
|
"os"
|
|
|
|
cryptossh "golang.org/x/crypto/ssh"
|
|
"golang.org/x/crypto/ssh/agent"
|
|
)
|
|
|
|
type agentDialer func(network, address string) (net.Conn, error)
|
|
|
|
func authMethods(keyFile string) ([]cryptossh.AuthMethod, func(), error) {
|
|
return authMethodsWithAgent(os.Getenv("SSH_AUTH_SOCK"), net.Dial, keyFile)
|
|
}
|
|
|
|
func authMethodsWithAgent(agentSocket string, dial agentDialer, keyFile string) ([]cryptossh.AuthMethod, func(), error) {
|
|
var methods []cryptossh.AuthMethod
|
|
var closers []io.Closer
|
|
if agentSocket != "" {
|
|
methods = append(methods, cryptossh.PublicKeysCallback(func() ([]cryptossh.Signer, error) {
|
|
conn, err := dial("unix", agentSocket)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
closers = append(closers, conn)
|
|
return agent.NewClient(conn).Signers()
|
|
}))
|
|
}
|
|
if keyFile != "" {
|
|
signer, err := signerFromKeyFile(keyFile)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
methods = append(methods, cryptossh.PublicKeys(signer))
|
|
}
|
|
if len(methods) == 0 {
|
|
return nil, nil, fmt.Errorf("no SSH auth methods configured; set SSH_AUTH_SOCK or ssh_key_file")
|
|
}
|
|
return methods, func() { closeAll(closers) }, nil
|
|
}
|
|
|
|
func signerFromKeyFile(path string) (cryptossh.Signer, error) {
|
|
key, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("read ssh_key_file %q: %w", path, err)
|
|
}
|
|
signer, err := cryptossh.ParsePrivateKey(key)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("parse ssh_key_file %q: %w", path, err)
|
|
}
|
|
return signer, nil
|
|
}
|
|
|
|
func closeAll(closers []io.Closer) {
|
|
for _, closer := range closers {
|
|
_ = closer.Close()
|
|
}
|
|
}
|