-
Notifications
You must be signed in to change notification settings - Fork 0
/
sftputil.go
125 lines (112 loc) · 2.61 KB
/
sftputil.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package sftputil
import (
"io"
"log"
"os"
"regexp"
"strconv"
"strings"
"github.com/pkg/sftp"
"golang.org/x/crypto/ssh"
)
const (
DefaultPort = int64(22)
)
type SftpClient struct {
Client *sftp.Client
hostname string
port int64
username string
keyPath string
password string
authMethod string
}
func NewSftpClientWithPassword(hostname string, port int64, username string, password string) (SftpClient, error) {
oSftp := SftpClient{}
oSftp.authMethod = "password"
oSftp.SetCredentials(hostname, port, username, "", password)
err := oSftp.Connect()
return oSftp, err
}
func NewSftpClientWithKeyPath(hostname string, port int64, username string, keyPath string) (SftpClient, error) {
oSftp := SftpClient{}
oSftp.authMethod = "key"
oSftp.SetCredentials(hostname, port, username, keyPath, "")
err := oSftp.Connect()
return oSftp, err
}
func (c *SftpClient) SetCredentials(hostname string, port int64, username string, keyPath string, password string) {
c.hostname = hostname
c.port = port
c.username = username
c.keyPath = keyPath
c.password = password
}
func (c *SftpClient) GetKey(sKeyPath string) (key ssh.Signer, err error) {
buf, err := os.ReadFile(sKeyPath)
if err != nil {
return nil, err
}
return ssh.ParsePrivateKey(buf)
}
func (c *SftpClient) Connect() error {
auth := []ssh.AuthMethod{}
if c.authMethod == "key" {
key, _ := c.GetKey(c.keyPath)
auth = []ssh.AuthMethod{
ssh.PublicKeys(key),
}
} else if c.authMethod == "password" {
auth = []ssh.AuthMethod{
ssh.Password(c.password),
}
}
config := &ssh.ClientConfig{
User: c.username,
Auth: auth,
}
sHost := strings.Join([]string{c.hostname, strconv.FormatInt(c.port, 10)}, ":")
sshClient, err := ssh.Dial("tcp", sHost, config)
if err != nil {
return err
}
sftpClient, err := sftp.NewClient(sshClient)
if err == nil {
c.Client = sftpClient
}
return err
}
func (c *SftpClient) Get(sPathRem string, sPathLoc string) error {
fi, err := c.Client.Open(sPathRem)
if err != nil {
rex := regexp.MustCompile(`\(SSH_FX_FAILURE\)`) // Hack, SFTP failure at 100
res := rex.FindStringSubmatch(err.Error())
if len(res) > 0 {
err := c.Connect()
if err != nil {
return err
}
return c.Get(sPathRem, sPathLoc)
}
log.Fatal(err)
}
fo, err := os.Create(sPathLoc)
if err != nil {
return err
}
defer fo.Close()
_, err = io.Copy(fo, fi)
return err
}
func (c *SftpClient) Put(sPathLoc string, sPathRem string) error {
ab, err := os.ReadFile(sPathLoc)
if err != nil {
return err
}
fRem, err := c.Client.Create(sPathRem)
if err != nil {
return err
}
_, err = fRem.Write(ab)
return err
}