mirror of
https://github.com/appleboy/drone-scp.git
synced 2026-06-04 18:23:59 +08:00
chore: support Fingerprint (#114)
This commit is contained in:
@@ -4,9 +4,10 @@ go 1.14
|
||||
|
||||
require (
|
||||
github.com/appleboy/com v0.0.6
|
||||
github.com/appleboy/easyssh-proxy v1.3.4
|
||||
github.com/appleboy/easyssh-proxy v1.3.5
|
||||
github.com/fatih/color v1.9.0
|
||||
github.com/joho/godotenv v1.3.0
|
||||
github.com/stretchr/testify v1.5.1
|
||||
github.com/urfave/cli/v2 v2.2.0
|
||||
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876
|
||||
)
|
||||
|
||||
@@ -3,8 +3,8 @@ github.com/ScaleFT/sshkeys v0.0.0-20181112160850-82451a803681 h1:JS2rl38kZmHgWa0
|
||||
github.com/ScaleFT/sshkeys v0.0.0-20181112160850-82451a803681/go.mod h1:WfDateMPQ/55dPbZRp5Zxrux5WiEaHsjk9puUhz0KgY=
|
||||
github.com/appleboy/com v0.0.6 h1:l8cZ0aQJU/SWyL79ciYAJeqV835PRdlZ6efiPhus5Ic=
|
||||
github.com/appleboy/com v0.0.6/go.mod h1:jnufjIC3opMlReyPPPye+8JqNvUzLm25o7h6SOy8nv0=
|
||||
github.com/appleboy/easyssh-proxy v1.3.4 h1:yNgzsJ9qaDNGzQILDXEK4boioJMmUUaTUsxYtCTSGqo=
|
||||
github.com/appleboy/easyssh-proxy v1.3.4/go.mod h1:Kk57I3w7OCafOjp5kgZFvxk2fO8Tca5CriBTOsbSbjY=
|
||||
github.com/appleboy/easyssh-proxy v1.3.5 h1:EGTCbqAVRcGKHQMFSxz30lQmb+0nXL+jUiCrg/FjHQM=
|
||||
github.com/appleboy/easyssh-proxy v1.3.5/go.mod h1:Kk57I3w7OCafOjp5kgZFvxk2fO8Tca5CriBTOsbSbjY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
|
||||
@@ -66,6 +66,11 @@ func main() {
|
||||
EnvVars: []string{"PLUGIN_CIPHERS", "SSH_CIPHERS", "CIPHERS", "INPUT_CIPHERS"},
|
||||
Value: cli.NewStringSlice(defaultCiphers...),
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "fingerprint",
|
||||
Usage: "fingerprint SHA256 of the host public key, default is to skip verification",
|
||||
EnvVars: []string{"PLUGIN_FINGERPRINT", "SSH_FINGERPRINT", "FINGERPRINT", "INPUT_FINGERPRINT"},
|
||||
},
|
||||
&cli.DurationFlag{
|
||||
Name: "timeout",
|
||||
Usage: "connection timeout",
|
||||
@@ -198,6 +203,11 @@ func main() {
|
||||
EnvVars: []string{"PLUGIN_PROXY_CIPHERS", "PROXY_SSH_CIPHERS", "PROXY_CIPHERS", "INPUT_PROXY_CIPHERS"},
|
||||
Value: cli.NewStringSlice(defaultCiphers...),
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "proxy.fingerprint",
|
||||
Usage: "fingerprint SHA256 of the host public key, default is to skip verification",
|
||||
EnvVars: []string{"PLUGIN_PROXY_FINGERPRINT", "SSH_PROXY_FINGERPRINT", "PROXY_FINGERPRINT", "INPUT_PROXY_FINGERPRINT"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "proxy.port",
|
||||
Usage: "connect to port of proxy",
|
||||
@@ -297,6 +307,7 @@ func run(c *cli.Context) error {
|
||||
Username: c.String("username"),
|
||||
Password: c.String("password"),
|
||||
Passphrase: c.String("ssh-passphrase"),
|
||||
Fingerprint: c.String("fingerprint"),
|
||||
Timeout: c.Duration("timeout"),
|
||||
CommandTimeout: c.Duration("command.timeout"),
|
||||
Key: c.String("ssh-key"),
|
||||
@@ -313,6 +324,7 @@ func run(c *cli.Context) error {
|
||||
Proxy: easyssh.DefaultConfig{
|
||||
Key: c.String("proxy.ssh-key"),
|
||||
Passphrase: c.String("proxy.ssh-passphrase"),
|
||||
Fingerprint: c.String("proxy.fingerprint"),
|
||||
KeyPath: c.String("proxy.key-path"),
|
||||
User: c.String("proxy.username"),
|
||||
Password: c.String("proxy.password"),
|
||||
|
||||
@@ -51,6 +51,7 @@ type (
|
||||
Password string
|
||||
Key string
|
||||
Passphrase string
|
||||
Fingerprint string
|
||||
KeyPath string
|
||||
Timeout time.Duration
|
||||
CommandTimeout time.Duration
|
||||
@@ -174,6 +175,7 @@ func (p *Plugin) removeAllDestFile() error {
|
||||
KeyPath: p.Config.KeyPath,
|
||||
Passphrase: p.Config.Passphrase,
|
||||
Timeout: p.Config.Timeout,
|
||||
Fingerprint: p.Config.Fingerprint,
|
||||
Proxy: easyssh.DefaultConfig{
|
||||
Server: p.Config.Proxy.Server,
|
||||
User: p.Config.Proxy.User,
|
||||
@@ -183,6 +185,7 @@ func (p *Plugin) removeAllDestFile() error {
|
||||
KeyPath: p.Config.Proxy.KeyPath,
|
||||
Passphrase: p.Config.Proxy.Passphrase,
|
||||
Timeout: p.Config.Proxy.Timeout,
|
||||
Fingerprint: p.Config.Proxy.Fingerprint,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -285,6 +288,7 @@ func (p *Plugin) Exec() error {
|
||||
Passphrase: p.Config.Passphrase,
|
||||
Timeout: p.Config.Timeout,
|
||||
Ciphers: p.Config.Ciphers,
|
||||
Fingerprint: p.Config.Fingerprint,
|
||||
Proxy: easyssh.DefaultConfig{
|
||||
Server: p.Config.Proxy.Server,
|
||||
User: p.Config.Proxy.User,
|
||||
@@ -295,6 +299,7 @@ func (p *Plugin) Exec() error {
|
||||
Passphrase: p.Config.Proxy.Passphrase,
|
||||
Timeout: p.Config.Proxy.Timeout,
|
||||
Ciphers: p.Config.Proxy.Ciphers,
|
||||
Fingerprint: p.Config.Proxy.Fingerprint,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
@@ -11,6 +13,7 @@ import (
|
||||
|
||||
"github.com/appleboy/easyssh-proxy"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
func TestMissingAllConfig(t *testing.T) {
|
||||
@@ -169,6 +172,90 @@ func TestSCPFileFromPublicKeyWithPassphrase(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrongFingerprint(t *testing.T) {
|
||||
u, err := user.Lookup("drone-scp")
|
||||
if err != nil {
|
||||
t.Fatalf("Lookup: %v", err)
|
||||
}
|
||||
|
||||
plugin := Plugin{
|
||||
Config: Config{
|
||||
Host: []string{"localhost"},
|
||||
Username: "drone-scp",
|
||||
Port: "22",
|
||||
KeyPath: "./tests/.ssh/id_rsa",
|
||||
Source: []string{"tests/a.txt", "tests/b.txt"},
|
||||
Target: []string{filepath.Join(u.HomeDir, "/test2")},
|
||||
CommandTimeout: 60 * time.Second,
|
||||
TarExec: "tar",
|
||||
Fingerprint: "wrong",
|
||||
},
|
||||
}
|
||||
|
||||
err = plugin.Exec()
|
||||
log.Println(err)
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func getHostPublicKeyFile(keypath string) (ssh.PublicKey, error) {
|
||||
var pubkey ssh.PublicKey
|
||||
var err error
|
||||
buf, err := ioutil.ReadFile(keypath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pubkey, _, _, _, err = ssh.ParseAuthorizedKey(buf)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pubkey, nil
|
||||
}
|
||||
|
||||
func TestSCPFileFromPublicKeyWithFingerprint(t *testing.T) {
|
||||
if os.Getenv("SSH_AUTH_SOCK") != "" {
|
||||
if err := exec.Command("eval", "`ssh-agent -k`").Run(); err != nil {
|
||||
t.Fatalf("exec: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
u, err := user.Lookup("drone-scp")
|
||||
if err != nil {
|
||||
t.Fatalf("Lookup: %v", err)
|
||||
}
|
||||
|
||||
hostKey, err := getHostPublicKeyFile("/etc/ssh/ssh_host_rsa_key.pub")
|
||||
assert.NoError(t, err)
|
||||
|
||||
plugin := Plugin{
|
||||
Config: Config{
|
||||
Host: []string{"localhost"},
|
||||
Username: "drone-scp",
|
||||
Port: "22",
|
||||
KeyPath: "./tests/.ssh/id_rsa",
|
||||
Fingerprint: ssh.FingerprintSHA256(hostKey),
|
||||
Source: []string{"tests/a.txt", "tests/b.txt"},
|
||||
Target: []string{filepath.Join(u.HomeDir, "/test2")},
|
||||
CommandTimeout: 60 * time.Second,
|
||||
TarExec: "tar",
|
||||
},
|
||||
}
|
||||
|
||||
err = plugin.Exec()
|
||||
assert.Nil(t, err)
|
||||
|
||||
// check file exist
|
||||
if _, err := os.Stat(filepath.Join(u.HomeDir, "/test2/tests/a.txt")); os.IsNotExist(err) {
|
||||
t.Fatalf("SCP-error: %v", err)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(filepath.Join(u.HomeDir, "/test2/tests/b.txt")); os.IsNotExist(err) {
|
||||
t.Fatalf("SCP-error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSCPWildcardFileList(t *testing.T) {
|
||||
if os.Getenv("SSH_AUTH_SOCK") != "" {
|
||||
if err := exec.Command("eval", "`ssh-agent -k`").Run(); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user