Skip to content
This repository has been archived by the owner on Nov 3, 2022. It is now read-only.

Support private key authentication for SFTP #98

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ before_install:
- sudo curl -s -o /usr/bin/mc https://dl.minio.io/client/mc/release/linux-amd64/mc
- sudo chmod u+x /usr/bin/mc
- docker run -dp 20022:22 atmoz/sftp:alpine test:test:::backup
- ssh-keygen -b 4096 -t rsa -N "" -f /tmp/ssh_host_rsa_key -q
- >-
docker run -dp 20023:22
-v /tmp/ssh_host_rsa_key.pub:/home/test/.ssh/keys/ssh_host_rsa_key.pub:ro
-v /tmp/ssh_host_rsa_key:/etc/ssh/ssh_host_rsa_key
--name test-sftp atmoz/sftp:alpine test::1001::backup

before_script:
- sleep 10
Expand All @@ -32,6 +38,8 @@ script:
- docker logs mgob 2>&1 | grep 'S3 upload finished'
- echo 'Local backup integration test'
- docker logs mgob 2>&1 | grep 'Backup finished'
- echo 'SFTP private key authorization integration test'
- docker logs mgob 2>&1 | grep "Backup finished .* sftp-authorization-test"

after_success:
- if [ -z "$DOCKER_USER" ]; then
Expand Down
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ travis:
@docker run -d --net=host --name mgob \
--restart unless-stopped \
-v "$(TRAVIS):/config" \
-v "/tmp/ssh_host_rsa_key:/etc/ssh/ssh_host_rsa_key:ro" \
-v "/tmp/ssh_host_rsa_key.pub:/etc/ssh/ssh_host_rsa_key.pub:ro" \
$(REPOSITORY)/mgob:$(APP_VERSION).$(TRAVIS_BUILD_NUMBER) \
-ConfigPath=/config \
-StoragePath=/storage \
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ sftp:
port: 2022
username: user
password: secret
# you can also specify path to a private key and a passphrase
private_key: /etc/ssh/ssh_host_rsa_key
passphrase: secretpassphrase
# dir must exist on the SFTP server
dir: backup
# Email notifications (optional)
Expand Down
30 changes: 29 additions & 1 deletion backup/sftp.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package backup
import (
"fmt"
"io"
"io/ioutil"
"net"
"os"
"path/filepath"
Expand All @@ -16,9 +17,36 @@ import (

func sftpUpload(file string, plan config.Plan) (string, error) {
t1 := time.Now()
var ams []ssh.AuthMethod
if plan.SFTP.Password != "" {
ams = append(ams, ssh.Password(plan.SFTP.Password))
}

if plan.SFTP.PrivateKey != "" {
key, err := ioutil.ReadFile(plan.SFTP.PrivateKey)
if err != nil {
return "", errors.Wrapf(err, "Reading private_key from file %s", plan.SFTP.PrivateKey)
}

var signer ssh.Signer
switch {
case plan.SFTP.PrivateKey != "" && plan.SFTP.Passphrase != "":
signer, err = ssh.ParsePrivateKeyWithPassphrase(key, []byte(plan.SFTP.Passphrase))
if err != nil {
return "", errors.Wrapf(err, "Parsing private key from file %s", plan.SFTP.PrivateKey)
}
case plan.SFTP.PrivateKey != "":
signer, err = ssh.ParsePrivateKey(key)
if err != nil {
return "", errors.Wrapf(err, "Parsing private key from file %s", plan.SFTP.PrivateKey)
}
}
ams = append(ams, ssh.PublicKeys(signer))
}

sshConf := &ssh.ClientConfig{
User: plan.SFTP.Username,
Auth: []ssh.AuthMethod{ssh.Password(plan.SFTP.Password)},
Auth: ams,
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
return nil
},
Expand Down
12 changes: 7 additions & 5 deletions config/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,13 @@ type Azure struct {
}

type SFTP struct {
Dir string `yaml:"dir"`
Host string `yaml:"host"`
Password string `yaml:"password"`
Port int `yaml:"port"`
Username string `yaml:"username"`
Dir string `yaml:"dir"`
Host string `yaml:"host"`
Password string `yaml:"password"`
PrivateKey string `yaml:"private_key"`
Passphrase string `yaml:"passphrase"`
Port int `yaml:"port"`
Username string `yaml:"username"`
}

type SMTP struct {
Expand Down
14 changes: 14 additions & 0 deletions test/travis/sftp-authorization-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
scheduler:
cron: "* * * * *"
retention: 5
timeout: 60
target:
host: "127.0.0.1"
port: 27017
database: test
sftp:
host: "127.0.0.1"
port: 20023
username: test
private_key: /etc/ssh/ssh_host_rsa_key
dir: backup