package sshutil import ( "fmt" "log" "net" "os" "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/knownhosts" ) // SecureConfig returns the currently supported non-legacy SSH algorithms from // x/crypto/ssh. This keeps SHA-1-era algorithms out without hardcoding a list // that can drift behind the library. func SecureConfig() ssh.Config { algorithms := ssh.SupportedAlgorithms() return ssh.Config{ KeyExchanges: algorithms.KeyExchanges, Ciphers: algorithms.Ciphers, MACs: algorithms.MACs, } } func HostKeyAlgorithms() []string { return ssh.SupportedAlgorithms().HostKeys } func PublicKeyAuthAlgorithms() []string { return ssh.SupportedAlgorithms().PublicKeyAuths } func ExistingPath(paths ...string) string { for _, path := range paths { if path == "" { continue } if _, err := os.Stat(path); err == nil { return path } } return "" } func HostKeyCallback(knownHostsPath string, strict bool, label string) (ssh.HostKeyCallback, string, error) { if knownHostsPath != "" { cb, err := knownhosts.New(knownHostsPath) if err != nil { return nil, "", fmt.Errorf("load %s known_hosts %s: %w", label, knownHostsPath, err) } return cb, fmt.Sprintf("known_hosts:%s", knownHostsPath), nil } if strict { return nil, "", fmt.Errorf("%s strict host key checking requires a known_hosts file", label) } return func(hostname string, remote net.Addr, key ssh.PublicKey) error { log.Printf( "WARN: %s SSH host key is not verified for %s (%s); fingerprint=%s", label, hostname, remote.String(), ssh.FingerprintSHA256(key), ) return nil }, "insecure-unverified-host-key", nil }