Files
cmp-go-snippet/cmpSnipper/cmpSnippetSshCli.go
2024-01-26 07:11:35 +12:00

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
}