shell/ssh.go

158 lines
4.1 KiB
Go

package shell
import (
"fmt"
"io/ioutil"
"time"
"github.com/tmc/scp"
"go.wit.com/log"
"golang.org/x/crypto/ssh"
)
var sshHostname string
var sshPort int
var sshUsername string
var sshPassword string
var sshKeyfile string
func SSHclientSet(hostname string, port int, username string, pass string, keyfile string) {
sshHostname = hostname
sshPort = port
sshUsername = username
sshPassword = pass
sshKeyfile = keyfile
}
func SSHclientSCP(localfile string, remotefile string) {
log.Log(SSH, "shell.SSHclientSCP() START")
log.Log(SSH, "shell.SSHclientSCP() \tlocalfile =", localfile)
log.Log(SSH, "shell.SSHclientSCP() \tremotefile =", remotefile)
sess := mySsh(sshHostname, sshPort, sshUsername, sshPassword, sshKeyfile)
err := scp.CopyPath(localfile, remotefile, sess)
sess.Close()
log.Log(SSH, "shell.SSHclientSCP() \tscp.CopyPath() err =", err)
log.Log(SSH, "shell.SSHclientSCP() END")
}
func SSHclientRun(cmd string) {
log.Log(SSH, "shell.SSHclientRun() START cmd =", cmd)
sess := mySsh(sshHostname, sshPort, sshUsername, sshPassword, sshKeyfile)
err := sess.Run(cmd)
sess.Close()
log.Log(SSH, "shell.SSHclientRun() END err =", err)
}
func mySsh(hostname string, port int, username string, pass string, keyfile string) *ssh.Session {
// get host public key
// hostKey := getHostKey(host)
// log.Log(SSH, "hostkey =", hostKey)
publicKey, err := PublicKeyFile(keyfile)
if err != nil {
log.Log(SSH, "PublicKeyFile() error =", err)
}
// ssh client config
config := ssh.ClientConfig{
User: username,
Auth: []ssh.AuthMethod{
ssh.Password(pass),
publicKey,
},
// allow any host key to be used (non-prod)
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
// verify host public key
// HostKeyCallback: ssh.FixedHostKey(hostKey),
// optional host key algo list
HostKeyAlgorithms: []string{
ssh.KeyAlgoRSA,
ssh.KeyAlgoDSA,
ssh.KeyAlgoECDSA256,
ssh.KeyAlgoECDSA384,
ssh.KeyAlgoECDSA521,
ssh.KeyAlgoED25519,
},
// optional tcp connect timeout
Timeout: 5 * time.Second,
}
sport := fmt.Sprintf("%d", port)
// connect
client, err := ssh.Dial("tcp", hostname+":"+sport, &config)
if err != nil {
log.Error(err)
}
// defer client.Close()
// start session
sess, err := client.NewSession()
if err != nil {
log.Error(err)
}
// defer sess.Close()
return sess
}
func Scp(sess *ssh.Session, localfile string, remotefile string) {
err := scp.CopyPath(localfile, remotefile, sess)
log.Log(SSH, "scp.CopyPath() err =", err)
}
func PublicKeyFile(file string) (ssh.AuthMethod, error) {
buffer, err := ioutil.ReadFile(file)
log.Log(SSH, "buffer =", string(buffer))
if err != nil {
return nil, err
}
key, err := ssh.ParsePrivateKey(buffer)
if err != nil {
return nil, err
}
return ssh.PublicKeys(key), nil
}
// THIS doesn't work
/*
func getHostKey(host string) ssh.PublicKey {
// parse OpenSSH known_hosts file
// ssh or use ssh-keyscan to get initial key
file, err := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts"))
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
var hostKey ssh.PublicKey
for scanner.Scan() {
fields := strings.Split(scanner.Text(), " ")
if len(fields) != 3 {
continue
}
if strings.Contains(fields[0], host) {
var err error
hostKey, _, _, _, err = ssh.ParseAuthorizedKey(scanner.Bytes())
if err != nil {
log.Fatalf("error parsing %q: %v", fields[2], err)
}
break
}
}
// 9enFJdMhb8eHN/6qfHSU/jww2Mo=|pcsWQCvAyve9QXBhjL+w/LhkcHU= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMQx8BJXxD+vk3wyjy7Irzw4FA6xxJvqUP7Hb+Z+ygpOuidYj9G8x6gHEXFUnABn5YirePrWh5tNsk4Rqs48VwU=
hostKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte("9enFJdMhb8eHN/6qfHSU/jww2Mo=|pcsWQCvAyve9QXBhjL+w/LhkcHU= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMQx8BJXxD+vk3wyjy7Irzw4FA6xxJvqUP7Hb+Z+ygpOuidYj9G8x6gHEXFUnABn5YirePrWh5tNsk4Rqs48VwU="))
log.Log(SSH, "hostkey err =", err)
log.Log(SSH, "hostkey =", hostKey)
if hostKey == nil {
log.Log(SSH, "no hostkey found err =", err)
log.Fatalf("no hostkey found for %s", host)
}
return hostKey
}
*/