100 lines
2.0 KiB
Go
100 lines
2.0 KiB
Go
package remote
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"syscall"
|
|
|
|
"github.com/pkg/sftp"
|
|
"golang.org/x/crypto/ssh"
|
|
"golang.org/x/term"
|
|
)
|
|
|
|
func ConnectWithKey(host, user string) (*sftp.Client, error) {
|
|
authMethods := loadSshKeys()
|
|
|
|
// Create SSH client configuration
|
|
config := &ssh.ClientConfig{
|
|
User: user,
|
|
Auth: authMethods,
|
|
}
|
|
|
|
return connect(host, config)
|
|
}
|
|
|
|
func ConnectWithPassword(host, user string) (*sftp.Client, error) {
|
|
fmt.Printf("%s@%s's password:", user, host)
|
|
bytePassword, err := term.ReadPassword(int(syscall.Stdin))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Create SSH client configuration
|
|
config := &ssh.ClientConfig{
|
|
User: user,
|
|
Auth: []ssh.AuthMethod{
|
|
ssh.Password(string(bytePassword)),
|
|
},
|
|
}
|
|
|
|
return connect(host, config)
|
|
}
|
|
|
|
func connect(host string, config *ssh.ClientConfig) (*sftp.Client, error) {
|
|
// Connect to the SSH server
|
|
conn, err := ssh.Dial("tcp", host, config)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot connect to ssh server: %w", err)
|
|
}
|
|
defer conn.Close()
|
|
|
|
// Open SFTP session
|
|
sftpClient, err := sftp.NewClient(conn)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot connect to ssh server: %w", err)
|
|
}
|
|
return sftpClient, nil
|
|
}
|
|
|
|
func loadSshKeys() []ssh.AuthMethod {
|
|
dirname, err := os.UserHomeDir()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
var auths []ssh.AuthMethod
|
|
entries, err := os.ReadDir(filepath.Join(dirname, ".ssh"))
|
|
if err != nil {
|
|
return auths
|
|
}
|
|
|
|
for _, entry := range entries {
|
|
if entry.IsDir() {
|
|
continue
|
|
}
|
|
name := entry.Name()
|
|
keyPath := filepath.Join(dirname, name)
|
|
keyData, err := os.ReadFile(keyPath)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
signer, err := ssh.ParsePrivateKey(keyData)
|
|
if err != nil {
|
|
fmt.Printf("%s's passphrase:", entry.Name())
|
|
bytePassword, err := term.ReadPassword(int(syscall.Stdin))
|
|
if err != nil {
|
|
continue
|
|
}
|
|
signer, err = ssh.ParsePrivateKeyWithPassphrase(keyData, bytePassword)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
}
|
|
auths = append(auths, ssh.PublicKeys(signer))
|
|
}
|
|
|
|
return auths
|
|
}
|