diff --git a/DOCS.md b/DOCS.md index 5c76400..395a952 100644 --- a/DOCS.md +++ b/DOCS.md @@ -178,6 +178,23 @@ Example configuration for passphrase which protecting a private key: - echo "you can't see the steps." ``` +Example configuration for forcing protocol to IPv4 only: + +```diff + - name: ssh commands + image: ghcr.io/appleboy/drone-ssh + settings: + host: foo.com + username: root + password: 1234 + port: 22 ++ protocol: tcp4 + script: + - echo hello + - echo world +``` + + ## Secret Reference | Key | Description | @@ -197,6 +214,7 @@ Example configuration for passphrase which protecting a private key: |-----|-------------| | `host` | target hostname or IP | | `port` | ssh port of target host | +| `protocol` | IP protocol to use: either tcp, tcp4 or tcp6 | | `username` | account for target host user | | `password` | password for target host user | | `key` | plain text of user private key | @@ -208,6 +226,7 @@ Example configuration for passphrase which protecting a private key: | `command_timeout` | Command timeout is the maximum amount of time for the execute commands, default is 10 minutes. | | `proxy_host` | proxy hostname or IP | | `proxy_port` | ssh port of proxy host | +| `proxy_protocol` | IP protocol to use for the proxy: either tcp, tcp4 or tcp6 | | `proxy_username` | account for proxy host user | | `proxy_password` | password for proxy host user | | `proxy_key` | plain text of proxy private key | diff --git a/go.mod b/go.mod index 043f43b..6c0e8a1 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/appleboy/drone-ssh go 1.18 require ( - github.com/appleboy/easyssh-proxy v1.3.10 + github.com/appleboy/easyssh-proxy v1.3.11-0.20230609114136-a50c12e64039 github.com/joho/godotenv v1.5.1 github.com/stretchr/testify v1.8.4 github.com/urfave/cli/v2 v2.25.7 diff --git a/go.sum b/go.sum index 8a60be6..982384e 100644 --- a/go.sum +++ b/go.sum @@ -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.3.10 h1:iriF68tlrYoxgWhS7t7Wyr0FA+hJlOem5tMfm+RDlx4= -github.com/appleboy/easyssh-proxy v1.3.10/go.mod h1:T81pu/Cxx/zf/7YXhFCFiucBa4xeQ81ci5b0PFnMRJc= +github.com/appleboy/easyssh-proxy v1.3.11-0.20230609114136-a50c12e64039 h1:u1o1Ft7PltG4+iOAmEubuyXx5fiDHWIvP+JiCClL+ak= +github.com/appleboy/easyssh-proxy v1.3.11-0.20230609114136-a50c12e64039/go.mod h1:6nn1KPv9GP9BrK8tgl+d/w68jX4rpLeooO3FAcC/lds= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/main.go b/main.go index f97eff1..0ccef0f 100644 --- a/main.go +++ b/main.go @@ -51,6 +51,12 @@ func main() { EnvVars: []string{"PLUGIN_PORT", "SSH_PORT", "INPUT_PORT"}, Value: 22, }, + &cli.StringFlag{ + Name: "protocol", + Usage: "The IP protocol to use. Default to tcp (both IPv4 and IPv6).", + EnvVars: []string{"PLUGIN_PROTOCOL", "SSH_PROTOCOL", "INPUT_PROTOCOL"}, + Value: "tcp", + }, &cli.StringFlag{ Name: "username", Aliases: []string{"user", "u"}, @@ -141,6 +147,12 @@ func main() { EnvVars: []string{"PLUGIN_PROXY_PORT", "PROXY_SSH_PORT", "INPUT_PROXY_PORT"}, Value: "22", }, + &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"}, + Value: "tcp", + }, &cli.StringFlag{ Name: "proxy.username", Usage: "connect as user of proxy", @@ -259,6 +271,7 @@ func run(c *cli.Context) error { Fingerprint: c.String("fingerprint"), Host: c.StringSlice("host"), Port: c.Int("port"), + Protocol: easyssh.Protocol(c.String("protocol")), Timeout: c.Duration("timeout"), CommandTimeout: c.Duration("command.timeout"), Script: scripts, @@ -278,6 +291,7 @@ func run(c *cli.Context) error { Fingerprint: c.String("proxy.fingerprint"), Server: c.String("proxy.host"), Port: c.String("proxy.port"), + Protocol: easyssh.Protocol(c.String("proxy.protocol")), Timeout: c.Duration("proxy.timeout"), Ciphers: c.StringSlice("proxy.ciphers"), UseInsecureCipher: c.Bool("proxy.useInsecureCipher"), diff --git a/plugin.go b/plugin.go index 14d619f..582e2bb 100644 --- a/plugin.go +++ b/plugin.go @@ -30,6 +30,7 @@ type ( Password string Host []string Port int + Protocol easyssh.Protocol Fingerprint string Timeout time.Duration CommandTimeout time.Duration @@ -75,6 +76,7 @@ func (p Plugin) exec(host string, wg *sync.WaitGroup, errChannel chan error) { User: p.Config.Username, Password: p.Config.Password, Port: port, + Protocol: p.Config.Protocol, Key: p.Config.Key, KeyPath: p.Config.KeyPath, Passphrase: p.Config.Passphrase, @@ -87,6 +89,7 @@ func (p Plugin) exec(host string, wg *sync.WaitGroup, errChannel chan error) { User: p.Config.Proxy.User, Password: p.Config.Proxy.Password, Port: p.Config.Proxy.Port, + Protocol: p.Config.Proxy.Protocol, Key: p.Config.Proxy.Key, KeyPath: p.Config.Proxy.KeyPath, Passphrase: p.Config.Proxy.Passphrase, diff --git a/plugin_test.go b/plugin_test.go index 91e252e..ac8038e 100644 --- a/plugin_test.go +++ b/plugin_test.go @@ -113,6 +113,40 @@ func TestSSHScriptFromKeyFile(t *testing.T) { assert.Nil(t, err) } +func TestSSHIPv4Only(t *testing.T) { + plugin := Plugin{ + Config: Config{ + Host: []string{"localhost", "127.0.0.1"}, + Username: "drone-scp", + Port: 22, + Protocol: easyssh.PROTOCOL_TCP4, + KeyPath: "./tests/.ssh/id_rsa", + Script: []string{"whoami", "ls -al"}, + CommandTimeout: 60 * time.Second, + }, + } + + err := plugin.Exec() + assert.Nil(t, err) +} + +func TestSSHIPv6OnlyError(t *testing.T) { + plugin := Plugin{ + Config: Config{ + Host: []string{"127.0.0.1"}, + Username: "drone-scp", + Port: 22, + Protocol: easyssh.PROTOCOL_TCP6, + KeyPath: "./tests/.ssh/id_rsa", + Script: []string{"whoami", "ls -al"}, + CommandTimeout: 60 * time.Second, + }, + } + + err := plugin.Exec() + assert.NotNil(t, err) +} + func TestStreamFromSSHCommand(t *testing.T) { plugin := Plugin{ Config: Config{