package util
import (
"bytes"
"errors"
"fmt"
"github.com/sirupsen/logrus"
"golang.org/x/crypto/ssh"
"strings"
"time"
)
func publicKeyAuthFunc(pemBytes, keyPassword []byte) ssh.AuthMethod {
// Create the Signer for this private key.
signer, err := ssh.ParsePrivateKeyWithPassphrase(pemBytes, keyPassword)
if err != nil {
logrus.WithError(err).Error("parse ssh key from bytes failed")
return nil
}
return ssh.PublicKeys(signer)
}
func SshRemoteRunCommand(sshClient *ssh.Client, command string) (string, error) {
session, err := sshClient.NewSession()
if err != nil {
return "", err
}
defer session.Close()
var buf bytes.Buffer
session.Stdout = &buf
err = session.Run(command)
logString := buf.String()
//logrus.WithField("CMD:", command).Info(logString)
if err != nil {
return logString, fmt.Errorf("CMD: %s OUT: %s ERROR: %s", command, logString, err)
}
return logString, err
}
func NewSshClientConfig(sshUser, sshPassword, sshType, sshKey, sshKeyPassword string) (config *ssh.ClientConfig, err error) {
if sshUser == "" {
return nil, errors.New("ssh_user can not be empty")
}
config = &ssh.ClientConfig{
Timeout: time.Second * 3,
User: sshUser,
HostKeyCallback: ssh.InsecureIgnoreHostKey(), //这个可以, 但是不够安全
//HostKeyCallback: hostKeyCallBackFunc(h.Host),
}
switch sshType {
case "password":
config.Auth = []ssh.AuthMethod{ssh.Password(sshPassword)}
case "key":
config.Auth = []ssh.AuthMethod{publicKeyAuthFunc([]byte(sshKey), []byte(sshKeyPassword))}
default:
return nil, fmt.Errorf("unknow ssh auth type: %s", sshType)
}
return
}
func CreateSimpleSshClient(sshUser, sshPassword, sshAddr string) (*ssh.Client, error) {
if !strings.Contains(sshAddr, ":") {
sshAddr = fmt.Sprintf("%s:22", sshAddr)
}
targetConfig, err := NewSshClientConfig(sshUser, sshPassword, "password", "", "")
if err != nil {
return nil, fmt.Errorf("cluster jumper proxy ssh config failed:%s", err)
}
return ssh.Dial("tcp", sshAddr, targetConfig)
}