289 lines
4.8 KiB
Go
289 lines
4.8 KiB
Go
|
|
package cmpSnipper
|
|
|
|
import (
|
|
"io"
|
|
"bufio"
|
|
"strings"
|
|
"net"
|
|
"golang.org/x/crypto/ssh"
|
|
)
|
|
|
|
type cmpSshCliStruct struct {
|
|
Host string
|
|
Connect *ssh.Client
|
|
Session *ssh.Session
|
|
Output *bufio.Reader
|
|
}
|
|
|
|
|
|
func (app *App) SshAddHostKey(host string, remote net.Addr, pubKey ssh.PublicKey) error {
|
|
app.Log(pubKey)
|
|
return nil
|
|
}
|
|
|
|
func (app *App) SshConnReal(cmpSshCli *cmpSshCliStruct, host string, keyfile string) error {
|
|
var err error
|
|
|
|
cmpSshCli.Host = host
|
|
|
|
key, err := app.FileReadLimit(keyfile, 1048576)
|
|
|
|
if err != nil {
|
|
app.Log(err)
|
|
return err
|
|
}
|
|
|
|
signer, err := ssh.ParsePrivateKey(key)
|
|
|
|
if err != nil {
|
|
app.Log(err)
|
|
return err
|
|
}
|
|
|
|
config := &ssh.ClientConfig{
|
|
User: "root",
|
|
Auth: []ssh.AuthMethod{
|
|
// HostKeyCallback: InsecureIgnoreHostKey(),
|
|
// ssh.Password("yourpassword"),
|
|
ssh.PublicKeys(signer),
|
|
},
|
|
// HostKeyCallback: ssh.FixedHostKey(hostKey),
|
|
HostKeyCallback: ssh.HostKeyCallback(func(host string, remote net.Addr, key ssh.PublicKey) error {
|
|
app.SshAddHostKey(host, remote, key)
|
|
|
|
return nil
|
|
}),
|
|
}
|
|
|
|
cmpSshCli.Connect, err = ssh.Dial("tcp", cmpSshCli.Host, config)
|
|
|
|
if err != nil {
|
|
app.Log(err)
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (app *App) SshSession(cmpSshCli *cmpSshCliStruct) error {
|
|
var err error
|
|
|
|
cmpSshCli.Session, err = cmpSshCli.Connect.NewSession()
|
|
|
|
if err != nil {
|
|
app.Log(err)
|
|
return err
|
|
}
|
|
|
|
// defer cmpSshCli.Session.Close()
|
|
|
|
modes := ssh.TerminalModes{
|
|
ssh.ECHO: 0,
|
|
}
|
|
|
|
err = cmpSshCli.Session.RequestPty("xterm", 50, 80, modes)
|
|
|
|
if err != nil {
|
|
app.Log(err)
|
|
return err
|
|
}
|
|
|
|
// sshIn, err := session.StdinPipe()
|
|
// if err != nil {
|
|
// app.Log(err)
|
|
// return err
|
|
// }
|
|
|
|
sshOut, err := cmpSshCli.Session.StdoutPipe()
|
|
|
|
if err != nil {
|
|
app.Log(err)
|
|
return err
|
|
}
|
|
|
|
sshErr, err := cmpSshCli.Session.StderrPipe()
|
|
|
|
if err != nil {
|
|
app.Log(err)
|
|
return err
|
|
}
|
|
|
|
output := io.MultiReader(sshOut, sshErr)
|
|
|
|
cmpSshCli.Output = bufio.NewReader(output)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (app *App) SshConn(host string, keyfile string) (int, error) {
|
|
var err error
|
|
|
|
// app.Log(url)
|
|
|
|
var cmpSshCli cmpSshCliStruct
|
|
|
|
err = app.SshConnReal(&cmpSshCli, host, keyfile)
|
|
|
|
if err != nil {
|
|
return -1, err
|
|
}
|
|
|
|
err = app.SshSession(&cmpSshCli)
|
|
|
|
if err != nil {
|
|
return -1, err
|
|
}
|
|
|
|
app.SshList = append(app.SshList, cmpSshCli)
|
|
|
|
app.Log("Append new")
|
|
|
|
return len(app.SshList)-1, nil
|
|
}
|
|
|
|
func (app *App) SshExec(cmpWbsCli cmpWbsCliStruct, idx int, cma []string) (error) {
|
|
var err error
|
|
|
|
cmd := strings.Join(cma, " ")
|
|
|
|
cmpSshCli := app.SshList[idx]
|
|
|
|
// app.Log("idx: '%s', '%s'", idx, cmpSshCli.Host)
|
|
|
|
err = cmpSshCli.Session.Start(cmd)
|
|
|
|
if err != nil {
|
|
app.Log(err)
|
|
return err
|
|
}
|
|
|
|
res := map[string]interface{}{
|
|
"string": nil,
|
|
}
|
|
|
|
var bli []byte
|
|
var sli string
|
|
|
|
for {
|
|
bli, _, err = cmpSshCli.Output.ReadLine()
|
|
|
|
if err != nil {
|
|
app.Log("Complete")
|
|
break
|
|
}
|
|
|
|
sli = string(bli)
|
|
|
|
app.Log(sli)
|
|
|
|
res["string"] = sli
|
|
|
|
app.HttpWebSockSendTo(cmpWbsCli, "cmpSshTest", res)
|
|
}
|
|
|
|
cmpSshCli.Session.Wait()
|
|
|
|
app.Log("Free resource SshList[" + string(idx) + "]")
|
|
|
|
cmpSshCli.Session.Close()
|
|
|
|
cmpSshCli.Connect.Close()
|
|
|
|
|
|
app.Log("Remove SshList[" + string(idx) + "]")
|
|
|
|
var list []cmpSshCliStruct
|
|
|
|
for i, li := range app.SshList {
|
|
if i == idx {
|
|
continue
|
|
}
|
|
|
|
list = append(list, li)
|
|
}
|
|
|
|
app.SshList = list
|
|
|
|
app.Log("End")
|
|
|
|
// done <- true
|
|
|
|
return nil
|
|
}
|
|
|
|
func (app *App) CmpSshTestSnip(parm any) (any, error) {
|
|
var err error
|
|
|
|
// var ifcIM map[string]interface{} = parm
|
|
|
|
cli, err := app.SnipGetCli(parm)
|
|
|
|
// app.Log(cli)
|
|
|
|
if err != nil {
|
|
return map[string]interface{}{
|
|
"string": "Not client found",
|
|
}, err
|
|
}
|
|
|
|
|
|
host, err := app.ConfGetStr("sshTestHost", "HostPort")
|
|
|
|
if err != nil {
|
|
return map[string]interface{}{
|
|
"string": "Not set sshTestHost.HostPort",
|
|
}, err
|
|
}
|
|
|
|
keyfile, err := app.ConfGetStr("sshTestHost", "PrivateKeyFile")
|
|
|
|
if err != nil {
|
|
return map[string]interface{}{
|
|
"string": "Not set sshTestHost.PrivateKeyFile",
|
|
}, err
|
|
}
|
|
|
|
cmi, err := app.ConfGetIfc("sshTestHost", "Command")
|
|
|
|
if err != nil {
|
|
return map[string]interface{}{
|
|
"string": "Not set sshTestHost.Command",
|
|
}, err
|
|
}
|
|
|
|
cml := cmi.([]interface{})
|
|
|
|
cma := make([]string, len(cml))
|
|
|
|
for i, v := range cml {
|
|
cma[i] = v.(string)
|
|
}
|
|
|
|
/*
|
|
if cma[0] == "none" {
|
|
return map[string]interface{}{
|
|
"string": "Can't get command",
|
|
}, err
|
|
}
|
|
*/
|
|
|
|
idx, err := app.SshConn(host, keyfile)
|
|
|
|
if err != nil {
|
|
return map[string]interface{}{
|
|
"string": "Connection to '" + host + "' failed",
|
|
}, err
|
|
}
|
|
|
|
go func() {
|
|
app.SshExec(cli, idx, cma)
|
|
}()
|
|
|
|
app.Log("Wait")
|
|
|
|
return map[string]interface{}{
|
|
"string": "Launch: " + strings.Join(cma, " "),
|
|
}, nil
|
|
}
|