Initial 2024-01-26
This commit is contained in:
288
cmpSnipper/cmpSnippetSshCli.go
Normal file
288
cmpSnipper/cmpSnippetSshCli.go
Normal file
@@ -0,0 +1,288 @@
|
||||
|
||||
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
|
||||
}
|
Reference in New Issue
Block a user