12
"github.com/sirupsen/logrus"
13
"golang.org/x/crypto/ssh"
16
// CommonSSH is a common function for ssh'ing to a podman machine using system-connections
18
// TODO This should probably be taught about an machineconfig to reduce input
19
func CommonSSH(username, identityPath, name string, sshPort int, inputArgs []string) error {
20
return commonBuiltinSSH(username, identityPath, name, sshPort, inputArgs, true, os.Stdin)
23
func CommonSSHShell(username, identityPath, name string, sshPort int, inputArgs []string) error {
24
return commonNativeSSH(username, identityPath, name, sshPort, inputArgs, os.Stdin)
27
func CommonSSHSilent(username, identityPath, name string, sshPort int, inputArgs []string) error {
28
return commonBuiltinSSH(username, identityPath, name, sshPort, inputArgs, false, nil)
31
func CommonSSHWithStdin(username, identityPath, name string, sshPort int, inputArgs []string, stdin io.Reader) error {
32
return commonBuiltinSSH(username, identityPath, name, sshPort, inputArgs, true, stdin)
35
func commonBuiltinSSH(username, identityPath, name string, sshPort int, inputArgs []string, passOutput bool, stdin io.Reader) error {
36
config, err := createConfig(username, identityPath)
41
client, err := ssh.Dial("tcp", fmt.Sprintf("localhost:%d", sshPort), config)
47
session, err := client.NewSession()
53
cmd := strings.Join(inputArgs, " ")
54
logrus.Debugf("Running ssh command on machine %q: %s", name, cmd)
57
session.Stdout = os.Stdout
58
session.Stderr = os.Stderr
59
} else if logrus.IsLevelEnabled(logrus.DebugLevel) {
60
return runSessionWithDebug(session, cmd)
63
return session.Run(cmd)
66
func runSessionWithDebug(session *ssh.Session, cmd string) error {
67
outPipe, err := session.StdoutPipe()
71
errPipe, err := session.StderrPipe()
75
logOuput := func(pipe io.Reader, done chan struct{}) {
76
scanner := bufio.NewScanner(pipe)
78
logrus.Debugf("ssh output: %s", scanner.Text())
82
if err := session.Start(cmd); err != nil {
85
completed := make(chan struct{}, 2)
86
go logOuput(outPipe, completed)
87
go logOuput(errPipe, completed)
94
func createConfig(user string, identityPath string) (*ssh.ClientConfig, error) {
95
key, err := os.ReadFile(identityPath)
100
signer, err := ssh.ParsePrivateKey(key)
105
return &ssh.ClientConfig{
107
Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
108
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
112
func commonNativeSSH(username, identityPath, name string, sshPort int, inputArgs []string, stdin io.Reader) error {
113
sshDestination := username + "@localhost"
114
port := strconv.Itoa(sshPort)
117
args := []string{"-i", identityPath, "-p", port, sshDestination,
118
"-o", "IdentitiesOnly=yes",
119
"-o", "StrictHostKeyChecking=no", "-o", "LogLevel=ERROR", "-o", "SetEnv=LC_ALL="}
120
if len(inputArgs) > 0 {
122
args = append(args, inputArgs...)
124
// ensure we have a tty
125
args = append(args, "-t")
126
fmt.Printf("Connecting to vm %s. To close connection, use `~.` or `exit`\n", name)
129
cmd := exec.Command("ssh", args...)
130
logrus.Debugf("Executing: ssh %v\n", args)
132
if err := setupIOPassthrough(cmd, interactive, stdin); err != nil {