mirror of
https://github.com/appleboy/drone-ssh.git
synced 2026-06-16 14:49:25 +08:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7d0a886109 | |||
| a83bebeafe | |||
| a41d4afc40 | |||
| 91fd4f8071 | |||
| b34fffdbd3 | |||
| d217773bac | |||
| ae023d7aa6 | |||
| 222545746b | |||
| a5f89304fd | |||
| a9cfc0c134 |
@@ -34,7 +34,7 @@ jobs:
|
||||
|
||||
- name: setup sshd server
|
||||
run: |
|
||||
apk add git make curl perl bash build-base zlib-dev ucl-dev
|
||||
apk add git make curl perl bash build-base zlib-dev ucl-dev sudo
|
||||
make ssh-server
|
||||
|
||||
- name: testing
|
||||
|
||||
@@ -104,10 +104,21 @@ ssh-server:
|
||||
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
|
||||
# add public key to root user
|
||||
mkdir -p /root/.ssh
|
||||
chmod 700 /root/.ssh
|
||||
cat tests/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
|
||||
cat tests/.ssh/test.pub >> /root/.ssh/authorized_keys
|
||||
chmod 600 /root/.ssh/authorized_keys
|
||||
# Append the following entry to run ALL command without a password for a user named drone-scp:
|
||||
cat tests/sudoers >> /etc/sudoers.d/sudoers
|
||||
# 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
|
||||
sed -i 's/^#ListenAddress 0.0.0.0/ListenAddress 0.0.0.0/g' /etc/ssh/sshd_config
|
||||
sed -i 's/^#ListenAddress ::/ListenAddress ::/g' /etc/ssh/sshd_config
|
||||
./tests/entrypoint.sh /usr/sbin/sshd -D &
|
||||
|
||||
coverage:
|
||||
|
||||
@@ -3,11 +3,11 @@ module github.com/appleboy/drone-ssh
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/appleboy/easyssh-proxy v1.4.1-0.20231106031702-5666e2ea5156
|
||||
github.com/appleboy/easyssh-proxy v1.5.0
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/urfave/cli/v2 v2.26.0
|
||||
golang.org/x/crypto v0.17.0
|
||||
github.com/urfave/cli/v2 v2.27.1
|
||||
golang.org/x/crypto v0.18.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -18,6 +18,6 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/sys v0.16.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
github.com/ScaleFT/sshkeys v1.2.0 h1:5BRp6rTVIhJzXT3VcUQrKgXR8zWA3sOsNeuyW15WUA8=
|
||||
github.com/ScaleFT/sshkeys v1.2.0/go.mod h1:gxOHeajFfvGQh/fxlC8oOKBe23xnnJTif00IFFbiT+o=
|
||||
github.com/appleboy/easyssh-proxy v1.4.1-0.20231106031702-5666e2ea5156 h1:B8SdYwqER5J7h5hzO29tK9TYB5XodDOcEW6vYe+CRIU=
|
||||
github.com/appleboy/easyssh-proxy v1.4.1-0.20231106031702-5666e2ea5156/go.mod h1:t3k8AF2MoYVIKeEj5RzVqtqppR5uXUBln+YrY3M444k=
|
||||
github.com/appleboy/easyssh-proxy v1.5.0 h1:OYdSPvYQN3mhnsMH5I2OF1TgwSEcSq33kvjQfTwvZww=
|
||||
github.com/appleboy/easyssh-proxy v1.5.0/go.mod h1:zcEMrStH91/tcUn3gUGP0KpQwUYLm8tX/Ook1AH98uc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -19,21 +19,21 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/urfave/cli/v2 v2.26.0 h1:3f3AMg3HpThFNT4I++TKOejZO8yU55t3JnnSr4S4QEI=
|
||||
github.com/urfave/cli/v2 v2.26.0/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
|
||||
github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho=
|
||||
github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
|
||||
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e h1:+SOyEddqYF09QP7vr7CgJ1eti3pY9Fn3LHO1M1r/0sI=
|
||||
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
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/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
|
||||
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=
|
||||
|
||||
@@ -38,11 +38,10 @@ func main() {
|
||||
app.Version = Version
|
||||
app.Flags = []cli.Flag{
|
||||
&cli.StringSliceFlag{
|
||||
Name: "host",
|
||||
Aliases: []string{"H"},
|
||||
Usage: "connect to host",
|
||||
EnvVars: []string{"PLUGIN_HOST", "SSH_HOST", "INPUT_HOST"},
|
||||
FilePath: ".host",
|
||||
Name: "host",
|
||||
Aliases: []string{"H"},
|
||||
Usage: "connect to host",
|
||||
EnvVars: []string{"PLUGIN_HOST", "SSH_HOST", "INPUT_HOST"},
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "port",
|
||||
@@ -53,7 +52,7 @@ func main() {
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "protocol",
|
||||
Usage: "The IP protocol to use. Default to tcp (both IPv4 and IPv6).",
|
||||
Usage: "The IP protocol to use. Valid values are \"tcp\". \"tcp4\" or \"tcp6\". Default to tcp.",
|
||||
EnvVars: []string{"PLUGIN_PROTOCOL", "SSH_PROTOCOL", "INPUT_PROTOCOL"},
|
||||
Value: "tcp",
|
||||
},
|
||||
@@ -149,8 +148,8 @@ func main() {
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "proxy.protocol",
|
||||
Usage: "The IP protocol to use for the proxy. Default to tcp (both IPv4 and IPv6).",
|
||||
EnvVars: []string{"PLUGIN_PROTOCOL", "SSH_PROTOCOL", "INPUT_PROTOCOL"},
|
||||
Usage: "The IP protocol to use for the proxy. Valid values are \"tcp\". \"tcp4\" or \"tcp6\". Default to tcp.",
|
||||
EnvVars: []string{"PLUGIN_PROXY_PROTOCOL", "SSH_PROXY_PROTOCOL", "INPUT_PROXY_PROTOCOL"},
|
||||
Value: "tcp",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
@@ -220,6 +219,11 @@ func main() {
|
||||
Usage: "pass all environment variable to shell script",
|
||||
EnvVars: []string{"PLUGIN_ALLENVS", "INPUT_ALLENVS"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "request-pty",
|
||||
Usage: "request a pseudo-terminal from the server",
|
||||
EnvVars: []string{"PLUGIN_REQUEST_PTY", "INPUT_REQUEST_PTY"},
|
||||
},
|
||||
}
|
||||
|
||||
// Override a template
|
||||
@@ -288,6 +292,7 @@ func run(c *cli.Context) error {
|
||||
Ciphers: c.StringSlice("ciphers"),
|
||||
UseInsecureCipher: c.Bool("useInsecureCipher"),
|
||||
AllEnvs: c.Bool("allenvs"),
|
||||
RequireTty: c.Bool("request-pty"),
|
||||
Proxy: easyssh.DefaultConfig{
|
||||
Key: c.String("proxy.ssh-key"),
|
||||
KeyPath: c.String("proxy.key-path"),
|
||||
|
||||
@@ -44,6 +44,7 @@ type (
|
||||
UseInsecureCipher bool
|
||||
EnvsFormat string
|
||||
AllEnvs bool
|
||||
RequireTty bool
|
||||
}
|
||||
|
||||
// Plugin structure
|
||||
@@ -60,7 +61,9 @@ func escapeArg(arg string) string {
|
||||
func (p Plugin) hostPort(host string) (string, string) {
|
||||
hosts := strings.Split(host, ":")
|
||||
port := strconv.Itoa(p.Config.Port)
|
||||
if len(hosts) > 1 {
|
||||
if len(hosts) > 1 &&
|
||||
(p.Config.Protocol == easyssh.PROTOCOL_TCP ||
|
||||
p.Config.Protocol == easyssh.PROTOCOL_TCP4) {
|
||||
host = hosts[0]
|
||||
port = hosts[1]
|
||||
}
|
||||
@@ -85,6 +88,7 @@ func (p Plugin) exec(host string, wg *sync.WaitGroup, errChannel chan error) {
|
||||
Ciphers: p.Config.Ciphers,
|
||||
Fingerprint: p.Config.Fingerprint,
|
||||
UseInsecureCipher: p.Config.UseInsecureCipher,
|
||||
RequestPty: p.Config.RequireTty,
|
||||
Proxy: easyssh.DefaultConfig{
|
||||
Server: p.Config.Proxy.Server,
|
||||
User: p.Config.Proxy.User,
|
||||
|
||||
+77
-1
@@ -797,7 +797,8 @@ func TestPlugin_hostPort(t *testing.T) {
|
||||
name: "different port",
|
||||
fields: fields{
|
||||
Config: Config{
|
||||
Port: 22,
|
||||
Port: 22,
|
||||
Protocol: easyssh.PROTOCOL_TCP4,
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
@@ -806,6 +807,20 @@ func TestPlugin_hostPort(t *testing.T) {
|
||||
wantHost: "localhost",
|
||||
wantPort: "443",
|
||||
},
|
||||
{
|
||||
name: "ipv6",
|
||||
fields: fields{
|
||||
Config: Config{
|
||||
Port: 22,
|
||||
Protocol: easyssh.PROTOCOL_TCP6,
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
h: "::1",
|
||||
},
|
||||
wantHost: "::1",
|
||||
wantPort: "22",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@@ -919,3 +934,64 @@ out: [foobar]
|
||||
|
||||
assert.Equal(t, unindent(expected), unindent(buffer.String()))
|
||||
}
|
||||
|
||||
func TestSudoCommand(t *testing.T) {
|
||||
var (
|
||||
buffer bytes.Buffer
|
||||
expected = `
|
||||
======CMD======
|
||||
sudo su - -c "whoami"
|
||||
======END======
|
||||
out: root
|
||||
`
|
||||
)
|
||||
|
||||
plugin := Plugin{
|
||||
Config: Config{
|
||||
Host: []string{"localhost"},
|
||||
Username: "drone-scp",
|
||||
Port: 22,
|
||||
KeyPath: "./tests/.ssh/id_rsa",
|
||||
Script: []string{
|
||||
`sudo su - -c "whoami"`,
|
||||
},
|
||||
CommandTimeout: 10 * time.Second,
|
||||
RequireTty: true,
|
||||
},
|
||||
Writer: &buffer,
|
||||
}
|
||||
|
||||
assert.Nil(t, plugin.Exec())
|
||||
assert.Equal(t, unindent(expected), unindent(buffer.String()))
|
||||
}
|
||||
|
||||
// TODO: TestCommandWithIPv6 is not working on github actions.
|
||||
// func TestCommandWithIPv6(t *testing.T) {
|
||||
// var (
|
||||
// buffer bytes.Buffer
|
||||
// expected = `
|
||||
// ======CMD======
|
||||
// whoami
|
||||
// ======END======
|
||||
// out: drone-scp
|
||||
// `
|
||||
// )
|
||||
|
||||
// plugin := Plugin{
|
||||
// Config: Config{
|
||||
// Host: []string{"::1"},
|
||||
// Username: "drone-scp",
|
||||
// Port: 22,
|
||||
// KeyPath: "./tests/.ssh/id_rsa",
|
||||
// Script: []string{
|
||||
// "whoami",
|
||||
// },
|
||||
// Protocol: easyssh.PROTOCOL_TCP6,
|
||||
// CommandTimeout: 10 * time.Second,
|
||||
// },
|
||||
// Writer: &buffer,
|
||||
// }
|
||||
|
||||
// assert.Nil(t, plugin.Exec())
|
||||
// assert.Equal(t, unindent(expected), unindent(buffer.String()))
|
||||
// }
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
Defaults requiretty
|
||||
drone-scp ALL=(ALL) NOPASSWD:ALL
|
||||
Reference in New Issue
Block a user