All checks were successful
continuous-integration/drone/push Build is passing
100 lines
2.3 KiB
Go
100 lines
2.3 KiB
Go
package ssh
|
|
|
|
import (
|
|
"fmt"
|
|
"os/user"
|
|
|
|
"github.com/AlecAivazis/survey/v2"
|
|
"github.com/kevinburke/ssh_config"
|
|
"github.com/sfreiberg/simplessh"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// HostConfig is a SSH host config.
|
|
type HostConfig struct {
|
|
Host string
|
|
IdentityFile string
|
|
Port string
|
|
User string
|
|
}
|
|
|
|
// GetHostConfig retrieves a ~/.ssh/config config for a host.
|
|
func GetHostConfig(hostname string, hasIdentityFile bool) (HostConfig, error) {
|
|
var hostConfig HostConfig
|
|
|
|
var host, sshUser, port, idf string
|
|
|
|
if host = ssh_config.Get(hostname, "Hostname"); host == "" {
|
|
logrus.Debugf("no hostname found in SSH config, assuming %s", hostname)
|
|
host = hostname
|
|
}
|
|
|
|
if sshUser = ssh_config.Get(hostname, "User"); sshUser == "" {
|
|
systemUser, err := user.Current()
|
|
if err != nil {
|
|
return hostConfig, err
|
|
}
|
|
username := systemUser.Username
|
|
logrus.Debugf("no username found in SSH config, assuming %s", username)
|
|
sshUser = username
|
|
}
|
|
|
|
if port = ssh_config.Get(hostname, "Port"); port == "" {
|
|
logrus.Debugf("no port found in SSH config, assuming 22")
|
|
port = "22"
|
|
}
|
|
|
|
dummyVal := "~/.ssh/identity"
|
|
if idf = ssh_config.Get(hostname, "IdentityFile"); (idf == dummyVal || idf == "") && hasIdentityFile {
|
|
return hostConfig, fmt.Errorf("SSH identity file missing for %s from SSH config", hostname)
|
|
}
|
|
|
|
hostConfig.Host = host
|
|
hostConfig.IdentityFile = idf
|
|
hostConfig.Port = port
|
|
hostConfig.User = sshUser
|
|
|
|
logrus.Debugf("constructed SSH config %s for %s", hostConfig, hostname)
|
|
|
|
return hostConfig, nil
|
|
}
|
|
|
|
// New creates a new SSH client connection.
|
|
func New(domainName, sshAuth string) (*simplessh.Client, error) {
|
|
var client *simplessh.Client
|
|
|
|
hasIdentityFile := true
|
|
if sshAuth == "password" {
|
|
hasIdentityFile = false
|
|
}
|
|
|
|
hostConfig, err := GetHostConfig(domainName, hasIdentityFile)
|
|
if err != nil {
|
|
return client, err
|
|
}
|
|
|
|
if sshAuth == "identity-file" {
|
|
var err error
|
|
client, err = simplessh.ConnectWithAgent(hostConfig.Host, hostConfig.User)
|
|
if err != nil {
|
|
return client, err
|
|
}
|
|
} else {
|
|
password := ""
|
|
prompt := &survey.Password{
|
|
Message: "SSH password?",
|
|
}
|
|
if err := survey.AskOne(prompt, &password); err != nil {
|
|
return client, err
|
|
}
|
|
|
|
var err error
|
|
client, err = simplessh.ConnectWithPassword(hostConfig.Host, hostConfig.User, password)
|
|
if err != nil {
|
|
return client, err
|
|
}
|
|
}
|
|
|
|
return client, nil
|
|
}
|