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)
}
package model
import (
"errors"
"fmt"
"golang.org/x/crypto/ssh"
"sshfortress/util"
)
func CreateSshClientAsAdmin(m *Machine, cj *ClusterJumper, cs *ClusterSsh) (c *ssh.Client, err error) {
if m.Id < 1 {
return nil, errors.New("CreateSshClientAsAdmin m is not valid")
}
targetConfig, err := util.NewSshClientConfig(cs.SshUser, cs.SshPassword, cs.SshType, cs.SshKey, cs.SshKeyPassword)
if err != nil {
return nil, fmt.Errorf("cluster jumper proxy ssh config failed:%s", err)
}
targetAddr := fmt.Sprintf("%s:%d", m.SshIp, m.SshPort)
var proxyConfig *ssh.ClientConfig
var proxyAddr string
if cj != nil && cj.Id > 0 {
//使用私有云集群跳板登陆
proxyConfig, err = util.NewSshClientConfig(cj.SshUser, cj.SshPassword, cj.SshType, cj.SshKey, cj.SshKeyPassword)
if err != nil {
return nil, fmt.Errorf("cluster jumper proxy ssh config failed:%s", err)
}
proxyAddr = fmt.Sprintf("%s:%d", cj.SshAddr, cj.SshPort)
}
c, err = createSshProxySshClient(targetConfig, proxyConfig, targetAddr, proxyAddr)
return
}
func CreateSshClientAsUser(m *Machine, user *User, cj *ClusterJumper) (c *ssh.Client, err error) {
targetConfig, err := util.NewSshClientConfig(user.SshUserName(), user.SshPassword, "password", "", "")
if err != nil {
return nil, fmt.Errorf("cluster jumper proxy ssh config failed:%s", err)
}
targetAddr := fmt.Sprintf("%s:%d", m.SshIp, m.SshPort)
var proxyConfig *ssh.ClientConfig
var proxyAddr string
if cj != nil && cj.Id > 0 {
//使用私有云集群跳板登陆
proxyConfig, err = util.NewSshClientConfig(cj.SshUser, cj.SshPassword, cj.SshType, cj.SshKey, cj.SshKeyPassword)
if err != nil {
return nil, fmt.Errorf("cluster jumper proxy ssh config failed:%s", err)
}
proxyAddr = fmt.Sprintf("%s:%d", cj.SshAddr, cj.SshPort)
}
c, err = createSshProxySshClient(targetConfig, proxyConfig, targetAddr, proxyAddr)
return
}
func createSshProxySshClient(targetSshConfig, proxySshConfig *ssh.ClientConfig, targetAddr, proxyAddr string) (client *ssh.Client, err error) {
if proxySshConfig == nil {
return ssh.Dial("tcp", targetAddr, targetSshConfig)
}
proxyClient, err := ssh.Dial("tcp", proxyAddr, proxySshConfig)
if err != nil {
return
}
conn, err := proxyClient.Dial("tcp", targetAddr)
if err != nil {
return
}
ncc, chans, reqs, err := ssh.NewClientConn(conn, targetAddr, targetSshConfig)
if err != nil {
return
}
client = ssh.NewClient(ncc, chans, reqs)
return
}