Compare commits

...

11 Commits

Author SHA1 Message Date
Bo-Yi Wu b447da961e chore: remove auto load .env file
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2020-06-15 16:37:09 +08:00
Bo-Yi Wu 4d46a02d53 chore: bump easyssh to 1.3.7 2020-05-24 13:57:02 +08:00
Bo-Yi Wu 7994d5555e chore: update dependency 2020-05-24 12:43:43 +08:00
Bo-Yi Wu c7d8b0f2e9 chore: upgrade easy-ssh 2020-05-24 12:05:38 +08:00
Bo-Yi Wu 7755fdb39f chore: upgrade easy-ssh 2020-05-24 12:04:21 +08:00
Bo-Yi Wu 83417639b9 chore: clean up go module 2020-05-24 10:46:44 +08:00
Bo-Yi Wu 7344ac6529 chore: support UseInsecureCipher (#158) 2020-05-24 10:43:11 +08:00
Bo-Yi Wu 1288a4b20d docs: update fingerprint comment.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2020-05-19 14:11:26 +08:00
Bo-Yi Wu 11ec0bec7e update makefile
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2020-05-19 14:02:15 +08:00
Bo-Yi Wu a2c6be3c19 support Fingerprint (#157) 2020-05-19 14:01:28 +08:00
Bo-Yi Wu 923defc397 easyssh-proxy upgrade => v1.3.5
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2020-05-19 12:55:32 +08:00
6 changed files with 214 additions and 67 deletions
+3 -1
View File
@@ -117,16 +117,18 @@ endif
docker push $(DEPLOY_ACCOUNT)/$(DEPLOY_IMAGE):$(tag)
ssh-server:
adduser -h /home/drone-scp -s /bin/bash -D -S drone-scp
adduser -h /home/drone-scp -s /bin/sh -D -S drone-scp
echo drone-scp:1234 | chpasswd
mkdir -p /home/drone-scp/.ssh
chmod 700 /home/drone-scp/.ssh
cat tests/.ssh/id_rsa.pub >> /home/drone-scp/.ssh/authorized_keys
cat tests/.ssh/test.pub >> /home/drone-scp/.ssh/authorized_keys
chmod 600 /home/drone-scp/.ssh/authorized_keys
chown -R drone-scp /home/drone-scp/.ssh
# install ssh and start server
apk add --update openssh openrc
rm -rf /etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_dsa_key
sed -i 's/^#PubkeyAuthentication yes/PubkeyAuthentication yes/g' /etc/ssh/sshd_config
sed -i 's/AllowTcpForwarding no/AllowTcpForwarding yes/g' /etc/ssh/sshd_config
./tests/entrypoint.sh /usr/sbin/sshd -D &
+3 -2
View File
@@ -3,8 +3,9 @@ module github.com/appleboy/drone-ssh
go 1.14
require (
github.com/appleboy/easyssh-proxy v1.3.4
github.com/appleboy/easyssh-proxy v1.3.7
github.com/joho/godotenv v1.3.0
github.com/stretchr/testify v1.3.0
github.com/stretchr/testify v1.5.1
github.com/urfave/cli v1.22.4
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37
)
+9 -2
View File
@@ -1,8 +1,8 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/ScaleFT/sshkeys v0.0.0-20181112160850-82451a803681 h1:JS2rl38kZmHgWa0xINSaSYH0Whtvem64/4+Ef0+Y5pE=
github.com/ScaleFT/sshkeys v0.0.0-20181112160850-82451a803681/go.mod h1:WfDateMPQ/55dPbZRp5Zxrux5WiEaHsjk9puUhz0KgY=
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.7 h1:4XsChI8PuAd6jwTIKvTCH97vWmknvMJGxYi0PLiULG8=
github.com/appleboy/easyssh-proxy v1.3.7/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=
@@ -17,18 +17,25 @@ github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA=
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876 h1:sKJQZMuxjOAR/Uo2LBfU90onWEf1dF4C+0hPJCc9Mpc=
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 h1:cg5LA/zNPRzIXIWSCxQW10Rvpy94aQh3LT/ShoCpkHw=
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+48 -28
View File
@@ -7,7 +7,6 @@ import (
"github.com/appleboy/easyssh-proxy"
"github.com/joho/godotenv"
_ "github.com/joho/godotenv/autoload"
"github.com/urfave/cli"
)
@@ -19,7 +18,6 @@ func main() {
if filename, found := os.LookupEnv("PLUGIN_ENV_FILE"); found {
_ = godotenv.Load(filename)
}
defaultCiphers := cli.StringSlice{"aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc"}
app := cli.NewApp()
app.Name = "Drone SSH"
app.Usage = "Executing remote ssh commands"
@@ -63,7 +61,16 @@ func main() {
Name: "ciphers",
Usage: "The allowed cipher algorithms. If unspecified then a sensible",
EnvVar: "PLUGIN_CIPHERS,SSH_CIPHERS,CIPHERS,INPUT_CIPHERS",
Value: &defaultCiphers,
},
cli.BoolFlag{
Name: "useInsecureCipher",
Usage: "include more ciphers with use_insecure_cipher",
EnvVar: "PLUGIN_USE_INSECURE_CIPHER,SSH_USE_INSECURE_CIPHER,USE_INSECURE_CIPHER,INPUT_USE_INSECURE_CIPHER",
},
cli.StringFlag{
Name: "fingerprint",
Usage: "fingerprint SHA256 of the host public key, default is to skip verification",
EnvVar: "PLUGIN_FINGERPRINT,SSH_FINGERPRINT,FINGERPRINT,INPUT_FINGERPRINT",
},
cli.StringSliceFlag{
Name: "host,H",
@@ -155,7 +162,16 @@ func main() {
Name: "proxy.ciphers",
Usage: "The allowed cipher algorithms. If unspecified then a sensible",
EnvVar: "PLUGIN_PROXY_CIPHERS,SSH_PROXY_CIPHERS,PROXY_CIPHERS,INPUT_PROXY_CIPHERS",
Value: &defaultCiphers,
},
cli.BoolFlag{
Name: "proxy.useInsecureCipher",
Usage: "include more ciphers with use_insecure_cipher",
EnvVar: "PLUGIN_PROXY_USE_INSECURE_CIPHER,SSH_PROXY_USE_INSECURE_CIPHER,PROXY_USE_INSECURE_CIPHER,INPUT_PROXY_USE_INSECURE_CIPHER",
},
cli.StringFlag{
Name: "proxy.fingerprint",
Usage: "fingerprint SHA256 of the host public key, default is to skip verification",
EnvVar: "PLUGIN_PROXY_FINGERPRINT,SSH_PROXY_FINGERPRINT,PROXY_FINGERPRINT,INPUT_PROXY_FINGERPRINT",
},
cli.StringSliceFlag{
Name: "envs",
@@ -214,31 +230,35 @@ func run(c *cli.Context) error {
}
plugin := Plugin{
Config: Config{
Key: c.String("ssh-key"),
KeyPath: c.String("key-path"),
Username: c.String("user"),
Password: c.String("password"),
Passphrase: c.String("ssh-passphrase"),
Host: c.StringSlice("host"),
Port: c.Int("port"),
Timeout: c.Duration("timeout"),
CommandTimeout: c.Duration("command.timeout"),
Script: scripts,
ScriptStop: c.Bool("script.stop"),
Envs: c.StringSlice("envs"),
Debug: c.Bool("debug"),
Sync: c.Bool("sync"),
Ciphers: c.StringSlice("ciphers"),
Key: c.String("ssh-key"),
KeyPath: c.String("key-path"),
Username: c.String("user"),
Password: c.String("password"),
Passphrase: c.String("ssh-passphrase"),
Fingerprint: c.String("fingerprint"),
Host: c.StringSlice("host"),
Port: c.Int("port"),
Timeout: c.Duration("timeout"),
CommandTimeout: c.Duration("command.timeout"),
Script: scripts,
ScriptStop: c.Bool("script.stop"),
Envs: c.StringSlice("envs"),
Debug: c.Bool("debug"),
Sync: c.Bool("sync"),
Ciphers: c.StringSlice("ciphers"),
UseInsecureCipher: c.Bool("useInsecureCipher"),
Proxy: easyssh.DefaultConfig{
Key: c.String("proxy.ssh-key"),
KeyPath: c.String("proxy.key-path"),
User: c.String("proxy.username"),
Password: c.String("proxy.password"),
Passphrase: c.String("proxy.ssh-passphrase"),
Server: c.String("proxy.host"),
Port: c.String("proxy.port"),
Timeout: c.Duration("proxy.timeout"),
Ciphers: c.StringSlice("proxy.ciphers"),
Key: c.String("proxy.ssh-key"),
KeyPath: c.String("proxy.key-path"),
User: c.String("proxy.username"),
Password: c.String("proxy.password"),
Passphrase: c.String("proxy.ssh-passphrase"),
Fingerprint: c.String("proxy.fingerprint"),
Server: c.String("proxy.host"),
Port: c.String("proxy.port"),
Timeout: c.Duration("proxy.timeout"),
Ciphers: c.StringSlice("proxy.ciphers"),
UseInsecureCipher: c.Bool("proxy.useInsecureCipher"),
},
},
Writer: os.Stdout,
+40 -34
View File
@@ -23,22 +23,24 @@ var (
type (
// Config for the plugin.
Config struct {
Key string
Passphrase string
KeyPath string
Username string
Password string
Host []string
Port int
Timeout time.Duration
CommandTimeout time.Duration
Script []string
ScriptStop bool
Envs []string
Proxy easyssh.DefaultConfig
Debug bool
Sync bool
Ciphers []string
Key string
Passphrase string
KeyPath string
Username string
Password string
Host []string
Port int
Fingerprint string
Timeout time.Duration
CommandTimeout time.Duration
Script []string
ScriptStop bool
Envs []string
Proxy easyssh.DefaultConfig
Debug bool
Sync bool
Ciphers []string
UseInsecureCipher bool
}
// Plugin structure
@@ -55,25 +57,29 @@ func escapeArg(arg string) string {
func (p Plugin) exec(host string, wg *sync.WaitGroup, errChannel chan error) {
// Create MakeConfig instance with remote username, server address and path to private key.
ssh := &easyssh.MakeConfig{
Server: host,
User: p.Config.Username,
Password: p.Config.Password,
Port: strconv.Itoa(p.Config.Port),
Key: p.Config.Key,
KeyPath: p.Config.KeyPath,
Passphrase: p.Config.Passphrase,
Timeout: p.Config.Timeout,
Ciphers: p.Config.Ciphers,
Server: host,
User: p.Config.Username,
Password: p.Config.Password,
Port: strconv.Itoa(p.Config.Port),
Key: p.Config.Key,
KeyPath: p.Config.KeyPath,
Passphrase: p.Config.Passphrase,
Timeout: p.Config.Timeout,
Ciphers: p.Config.Ciphers,
Fingerprint: p.Config.Fingerprint,
UseInsecureCipher: p.Config.UseInsecureCipher,
Proxy: easyssh.DefaultConfig{
Server: p.Config.Proxy.Server,
User: p.Config.Proxy.User,
Password: p.Config.Proxy.Password,
Port: p.Config.Proxy.Port,
Key: p.Config.Proxy.Key,
KeyPath: p.Config.Proxy.KeyPath,
Passphrase: p.Config.Proxy.Passphrase,
Timeout: p.Config.Proxy.Timeout,
Ciphers: p.Config.Proxy.Ciphers,
Server: p.Config.Proxy.Server,
User: p.Config.Proxy.User,
Password: p.Config.Proxy.Password,
Port: p.Config.Proxy.Port,
Key: p.Config.Proxy.Key,
KeyPath: p.Config.Proxy.KeyPath,
Passphrase: p.Config.Proxy.Passphrase,
Timeout: p.Config.Proxy.Timeout,
Ciphers: p.Config.Proxy.Ciphers,
Fingerprint: p.Config.Proxy.Fingerprint,
UseInsecureCipher: p.Config.Proxy.UseInsecureCipher,
},
}
+111
View File
@@ -3,6 +3,7 @@ package main
import (
"bytes"
"io"
"io/ioutil"
"os"
"reflect"
"strings"
@@ -11,6 +12,7 @@ import (
"github.com/appleboy/easyssh-proxy"
"github.com/stretchr/testify/assert"
"golang.org/x/crypto/ssh"
)
func TestMissingHostOrUser(t *testing.T) {
@@ -384,6 +386,80 @@ func TestCommandOutput(t *testing.T) {
assert.Equal(t, unindent(expected), unindent(buffer.String()))
}
func TestWrongFingerprint(t *testing.T) {
var (
buffer bytes.Buffer
)
plugin := Plugin{
Config: Config{
Host: []string{"localhost"},
Username: "drone-scp",
Port: 22,
KeyPath: "./tests/.ssh/id_rsa",
Script: []string{
"whoami",
},
Fingerprint: "wrong",
},
Writer: &buffer,
}
err := plugin.Exec()
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 TestFingerprint(t *testing.T) {
var (
buffer bytes.Buffer
expected = `
======CMD======
whoami
======END======
out: drone-scp
`
)
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",
Script: []string{
"whoami",
},
Fingerprint: ssh.FingerprintSHA256(hostKey),
CommandTimeout: 10 * time.Second,
},
Writer: &buffer,
}
err = plugin.Exec()
assert.Nil(t, err)
assert.Equal(t, unindent(expected), unindent(buffer.String()))
}
func TestScriptStop(t *testing.T) {
var (
buffer bytes.Buffer
@@ -593,3 +669,38 @@ func TestPlugin_scriptCommands(t *testing.T) {
})
}
}
func TestUseInsecureCipher(t *testing.T) {
var (
buffer bytes.Buffer
expected = `
======CMD======
mkdir a/b/c
mkdir d/e/f
======END======
err: mkdir: can't create directory 'a/b/c': No such file or directory
err: mkdir: can't create directory 'd/e/f': No such file or directory
`
)
plugin := Plugin{
Config: Config{
Host: []string{"localhost"},
Username: "drone-scp",
Port: 22,
KeyPath: "./tests/.ssh/id_rsa",
Script: []string{
"mkdir a/b/c",
"mkdir d/e/f",
},
CommandTimeout: 10 * time.Second,
UseInsecureCipher: true,
},
Writer: &buffer,
}
err := plugin.Exec()
assert.NotNil(t, err)
assert.Equal(t, unindent(expected), unindent(buffer.String()))
}