-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ssh test code - just for reference for now
- Loading branch information
Showing
4 changed files
with
228 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package main | ||
|
||
import "net/url" | ||
|
||
// remote support | ||
|
||
// "remote" is another component type, | ||
|
||
// e.g. | ||
// geneos new remote X URL | ||
// | ||
// below is out of date | ||
|
||
// examples: | ||
// | ||
// geneos add remote name URL | ||
// URL here may be ssh://user@host etc. | ||
// URL can include path to ITRS_HOME / ITRSHome, e.g. | ||
// ssh://user@server/home/geneos | ||
// else it default to same as local | ||
// | ||
// non ssh schemes to follow | ||
// ssh support for agents and private key files - no passwords | ||
// known_hosts will be checked, no changes made, missing keys will | ||
// result in error. user must add hosts before use (ssh-keyscan) | ||
// | ||
// geneos ls remote NAME | ||
// XXX - geneos init remote NAME | ||
// | ||
// remote 'localhost' is always implied | ||
// | ||
// geneos ls remote | ||
// ... list remote locations | ||
// | ||
// geneos start gateway [name]@remote | ||
// | ||
// XXX support gateway pairs for standby - how ? | ||
// | ||
// XXX remote netprobes, auto configure with gateway for SANs etc.? | ||
// | ||
// support existing geneos-utils installs on remote | ||
|
||
type Remotes struct { | ||
Common | ||
Home string `default:"{{join .Root \"remotes\" .Name}}"` | ||
Hostname string | ||
Port int `default:"22"` | ||
Username string | ||
ITRSHome string `default:"{{.Root}}"` | ||
} | ||
|
||
func init() { | ||
components[Remote] = ComponentFuncs{ | ||
Instance: remoteInstance, | ||
Command: nil, | ||
Add: remoteAdd, | ||
Clean: nil, | ||
Reload: nil, | ||
} | ||
} | ||
|
||
func remoteInstance(name string) interface{} { | ||
// Bootstrap | ||
c := &Remotes{} | ||
c.Root = RunningConfig.ITRSHome | ||
c.Type = Remote.String() | ||
c.Name = name | ||
setDefaults(&c) | ||
return c | ||
} | ||
|
||
// | ||
// 'geneos add remote NAME SSH-URL' | ||
// | ||
func remoteAdd(name string, username string, params []string) (c Instance, err error) { | ||
if len(params) == 0 { | ||
log.Fatalln("remote destination must be provided in the form of a URL") | ||
} | ||
|
||
c = remoteInstance(name) | ||
|
||
u, err := url.Parse(params[0]) | ||
if err != nil { | ||
logDebug.Println(err) | ||
return | ||
} | ||
|
||
switch { | ||
case u.Scheme == "ssh": | ||
if u.Host == "" { | ||
log.Fatalln("hostname must be provided") | ||
} | ||
setField(c, "Hostname", u.Host) | ||
if u.Port() != "" { | ||
setField(c, "Port", u.Port()) | ||
} | ||
if u.User.Username() != "" { | ||
setField(c, "Username", u.User.Username()) | ||
} | ||
if u.Path != "" { | ||
setField(c, "ITRSHome", u.Path) | ||
} | ||
return c, writeInstanceConfig(c) | ||
default: | ||
log.Fatalln("unsupport scheme (only ssh at the moment):", u.Scheme) | ||
} | ||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package main | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"net" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/pkg/sftp" | ||
"golang.org/x/crypto/ssh" | ||
"golang.org/x/crypto/ssh/agent" | ||
"golang.org/x/crypto/ssh/knownhosts" | ||
) | ||
|
||
var userSSHdir = ".ssh" | ||
|
||
var privateKeyFiles = []string{ | ||
"id_rsa", | ||
"id_ecdsa", | ||
"id_ecdsa_sk", | ||
"id_ed25519", | ||
"id_ed25519_sk", | ||
"id_dsa", | ||
} | ||
|
||
// ssh utilities for remote connections | ||
|
||
func readSSHkeys(homedir string) (signers []ssh.Signer) { | ||
for _, keyfile := range privateKeyFiles { | ||
path := filepath.Join(homedir, ".ssh", keyfile) | ||
key, err := os.ReadFile(path) | ||
if err != nil { | ||
logDebug.Println(err) | ||
continue | ||
} | ||
signer, err := ssh.ParsePrivateKey(key) | ||
if err != nil { | ||
logDebug.Println(err) | ||
continue | ||
} | ||
logDebug.Println("loaded private key from", path) | ||
signers = append(signers, signer) | ||
} | ||
return | ||
} | ||
|
||
func sshTest(username string, host string) { | ||
socket := os.Getenv("SSH_AUTH_SOCK") | ||
sshAgent, err := net.Dial("unix", socket) | ||
if err != nil { | ||
log.Fatalf("Failed to open SSH_AUTH_SOCK: %v", err) | ||
} | ||
|
||
agentClient := agent.NewClient(sshAgent) | ||
|
||
homedir, err := os.UserHomeDir() | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
knownHostsFile := filepath.Join(homedir, ".ssh", "known_hosts") | ||
logDebug.Println(knownHostsFile) | ||
khcallback, err := knownhosts.New(knownHostsFile) | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
signers := readSSHkeys(homedir) | ||
config := &ssh.ClientConfig{ | ||
User: username, | ||
Auth: []ssh.AuthMethod{ | ||
ssh.PublicKeysCallback(agentClient.Signers), | ||
ssh.PublicKeys(signers...), | ||
}, | ||
HostKeyCallback: khcallback, | ||
} | ||
conn, err := ssh.Dial("tcp", host, config) | ||
if err != nil { | ||
log.Fatal("unable to connect: ", err) | ||
} | ||
defer conn.Close() | ||
|
||
session, err := conn.NewSession() | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
defer session.Close() | ||
|
||
var b bytes.Buffer | ||
session.Stdout = &b | ||
if err := session.Run("ls -l"); err != nil { | ||
log.Fatal("Failed to run: " + err.Error()) | ||
} | ||
fmt.Println(b.String()) | ||
|
||
client, err := sftp.NewClient(conn) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
defer client.Close() | ||
|
||
// walk a directory | ||
w := client.Walk("/home/pi") | ||
for w.Step() { | ||
if w.Err() != nil { | ||
continue | ||
} | ||
log.Println(w.Path()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters