drone-ssh: panic: runtime error: invalid memory address or nil pointer dereference

For

  deploy:
    image: appleboy/drone-ssh
    host: example.dev
    user: nemonik
    port: 22
    key: ${SSH_KEY}
    script:
      - echo "Hey"
      - ls
    when:
      branch:
        include: [ master, release/* ]

After registering my SSH_KEY as a secret via drone cli

drone secret add --image=appleboy/drone-ssh Ephemeral/nodejs-helloworld SSH_KEY "$(cat ~/.ssh/privatekey)"

I get out of drone:

2017/02/09 05:15:32 example.dev commands:  echo "Hey"
panic: runtime error: invalid memory address or nil pointer dereference
 [signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x54e043]
goroutine 18 [running]:
panic(0x62b220, 0xc42000a060)
	/usr/local/go/src/runtime/panic.go:500 +0x1a1
github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh.publicKeyCallback.auth(0xc42007f560, 0xc420010d40, 0x20, 0x20, 0xc42006cb10, 0x7, 0x772a00, 0xc4200e8000, 0x770600, 0xc4200705d0, ...)
	/srv/app/src/github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh/client_auth.go:191 +0xb3
github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh.(*connection).clientAuthenticate(0xc4200dc100, 0xc4200e0000, 0x0, 0xa)
	/srv/app/src/github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh/client_auth.go:34 
github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh.(*connection).clientHandshake(0xc4200dc100, 0xc420070db0, 0x22, 0xc4200e0000, 0x0, 0x0)
	/srv/app/src/github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh/client.go:107 +0x2ed
github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh.NewClientConn(0x774b20, 0xc42002a008, 0xc420070db0, 0x22, 0xc420069a90, 0x774b20, 0xc42002a008, 0x0, 0x0, 0xc42007f560, ...)
	/srv/app/src/github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh/client.go:75 +0x105
github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh.Dial(0x666e8c, 0x3, 0xc420070db0, 0x22, 0xc420069a90, 0x22, 0x0, 0x1)
	/srv/app/src/github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh/client.go:171 +0xb3
github.com/appleboy/drone-ssh/easyssh.(*MakeConfig).connect(0xc420069e90, 0x45c000, 0x10000c42007c010, 0x0)
	/srv/app/src/github.com/appleboy/drone-ssh/easyssh/easyssh.go:77 +0x16b
github.com/appleboy/drone-ssh/easyssh.(*MakeConfig).Stream(0xc420069e90, 0xc42006cbf0, 0xd, 0xd, 0xd, 0xc420069ca8, 0x4431ce)
	/srv/app/src/github.com/appleboy/drone-ssh/easyssh/easyssh.go:95 +0x40
github.com/appleboy/drone-ssh/easyssh.(*MakeConfig).Run(0xc420069e90, 0xc42006cbf0, 0xd, 0x666c32, 0x1, 0xc42006cbf0, 0xd)
	/srv/app/src/github.com/appleboy/drone-ssh/easyssh/easyssh.go:130 +0x5d
main.Plugin.Exec.func1(0xc42006cac6, 0xa, 0x0, 0x0, 0xc42006cb10, 0x7, 0x0, 0x0, 0xc42006c940, 0x1, ...)
	/srv/app/src/github.com/appleboy/drone-ssh/plugin.go:71 +0x330
created by main.Plugin.Exec
	/srv/app/src/github.com/appleboy/drone-ssh/plugin.go:79 +0x16e

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Comments: 52 (17 by maintainers)

Commits related to this issue

Most upvoted comments

@PeterCat12 and @appleboy:

So, awoke with the solution.

If you set a SHH_KEY secret like so

drone secret add --image=appleboy/drone-ssh Ephemeral/nodejs-helloworld SSH_KEY @/home/nemonik/.ssh/ephemeral

And then set up the pipeline like so:

  ssh-deploy:
    image: appleboy/drone-ssh
    pull: true
    host: example.dev
    port: 22
    user: nemonik    
    key: ${SSH_KEY}
    script:
      - whoami

The container/plugin will have an SSH_KEY environmental variable containing the text of your private key, but a PLUGIN_KEY environmental variable containing, well, ${SSH_KEY}. The SSH_KEY environmental variable is ignored, but the PLUGIN_KEY environmental is used to set p.Config.Key and this goes in easydrone to attempt the SSH connection resulting in a fail.

One has to understand all these parameters show up in the container/plugin prepended with PLUGIN_ and then the all caps form of the parameter.

So, your drone secret rm the SSH_KEY and instead set a PLUGIN_KEY like so

drone secret add --image=appleboy/drone-ssh Ephemeral/nodejs-helloworld PLUGIN_KEY @/home/nemonik/.ssh/ephemeral

and the modify your pipeline to:

  ssh-deploy:
    image: appleboy/drone-ssh
    pull: true
    host: example.dev
    port: 22
    user: nemonik    
    script:
      - whoami

Yeah, you don’t even pass a key value as it already exists as secret. Trigger your build and things run fine like so:

2017/03/03 16:23:24 example.dev commands:  whoami
2017/03/03 16:23:24 example.dev: outputs: nemonik
2017/03/03 16:23:24 Successfully executed commands to all host.

I would suggest updating the documentation.

For drone/drone:0.5 and drone CLI version 0.5.0+dev, it is stil a great big fail whale.

Okay. Every step:

➜  nodejs-helloworld git:(master) ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/nemonik/.ssh/id_rsa): /home/nemonik/.ssh/ephemeral
/home/nemonik/.ssh/ephemeral already exists.
Overwrite (y/n)? y
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/nemonik/.ssh/ephemeral.
Your public key has been saved in /home/nemonik/.ssh/ephemeral.pub.
The key fingerprint is:
0a:df:04:70:65:1b:0c:50:f0:fd:3b:63:2e:9b:ed:b8 nemonik@example.dev
The key's randomart image is:
+--[ RSA 2048]----+
|    +++++        |
|     + o.o       |
|      o o        |
|       . .       |
|    .   S .      |
|     o +   .     |
|      o . =      |
|        .* o     |
|        E=+      |
+-----------------+
rm ~/.ssh/authorized_keys
cat ~/.ssh/ephemeral.pub > ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
rm ~/.ssh/known_hosts

Then ls -las ~/.ssh returns:

total 20
0 drwx------.  2 nemonik nemonik   77 Feb 27 14:21 .
4 drwx------. 13 nemonik nemonik 4096 Feb 27 14:22 ..
4 -rw-------.  1 nemonik nemonik  421 Feb 27 14:19 authorized_keys
4 -rw-------.  1 nemonik nemonik   97 Feb 17 02:07 config
4 -rw-------.  1 nemonik nemonik 1675 Feb 27 14:16 ephemeral
4 -rw-------.  1 nemonik nemonik  421 Feb 27 14:16 ephemeral.pub

Add the private kek:

drone secret add --event pull_request Ephemeral/nodejs-helloworld SSH_KEY @/home/nemonik/.ssh/ephemeral

View via drone secret ls Ephemeral/nodejs-helloworld returns:

SSH_KEY
Events: push, tag, deployment, pull_request
SkipVerify: false
Conceal: false

Sign my project:

➜  ~ cd ~/Development/workspace/ephemeral/nodejs-helloworld
➜  nodejs-helloworld git:(master) drone sign  Ephemeral/nodejs-helloworld
➜  nodejs-helloworld git:(master) drone sign Ephemeral/nodejs-helloworld
➜  nodejs-helloworld git:(master) ✗ git add .
➜  nodejs-helloworld git:(master) ✗ git commit -m "drone signed"
[master 84f4345] drone signed
 1 file changed, 1 insertion(+)
 create mode 100644 .drone.yml.sig
➜  nodejs-helloworld git:(master) git push
Counting objects: 4, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 1.19 KiB | 0 bytes/s, done.
Total 3 (delta 1), reused 1 (delta 0)
To ssh://git@example.dev:10022/Ephemeral/nodejs-helloworld.git
   4f4629b..84f4345  master -> master

For this .drone.yml:

  deploy:
    image: appleboy/drone-ssh
    pull: true
    host:
      - example.dev
    port: 22
    user: nemonik
    key: ${SSH_KEY}
    script:
      - whoami

I get:

2017/02/27 19:32:21 example.dev: commands:  whoami
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x5d42e3]
goroutine 18 [running]:
github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh.publicKeyCallback.auth(0xc42007f540, 0xc42007fb20, 0x20, 0x20, 0xc42000a36c, 0x7, 0x784c20, 0xc42008c840, 0x782620, 0xc42006e630, ...)
	/srv/app/src/github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh/client_auth.go:193 +0xb3
github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh.(*connection).clientAuthenticate(0xc42007a680, 0xc4200940c0, 0x0, 0xa)
	/srv/app/src/github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh/client_auth.go:36 +0x369
github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh.(*connection).clientHandshake(0xc42007a680, 0xc42006eed0, 0x22, 0xc4200940c0, 0x0, 0x0)
	/srv/app/src/github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh/client.go:105 +0x2e6
github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh.NewClientConn(0x786e20, 0xc42007c050, 0xc42006eed0, 0x22, 0xc420067ad8, 0x786e20, 0xc42007c050, 0x0, 0x0, 0xc42007f540, ...)
	/srv/app/src/github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh/client.go:75 +0xe2
github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh.Dial(0x676bf0, 0x3, 0xc42006eed0, 0x22, 0xc420067ad8, 0x22, 0x0, 0x1)
	/srv/app/src/github.com/appleboy/drone-ssh/vendor/golang.org/x/crypto/ssh/client.go:169 +0xb3
github.com/appleboy/drone-ssh/easyssh.(*MakeConfig).connect(0xc420067ed0, 0x0, 0x0, 0x0)
	/srv/app/src/github.com/appleboy/drone-ssh/easyssh/easyssh.go:77 +0x16e
github.com/appleboy/drone-ssh/easyssh.(*MakeConfig).Stream(0xc420067ed0, 0xc42000a10e, 0x6, 0x33, 0x47, 0x50, 0x7a5860)
	/srv/app/src/github.com/appleboy/drone-ssh/easyssh/easyssh.go:95 +0x40
github.com/appleboy/drone-ssh/easyssh.(*MakeConfig).Run(0xc420067ed0, 0xc42000a10e, 0x6, 0x6769b0, 0x1, 0xc42000a10e, 0x6)
	/srv/app/src/github.com/appleboy/drone-ssh/easyssh/easyssh.go:130 +0x5d
main.Plugin.Exec.func1(0xc42000a26b, 0xa, 0x0, 0x0, 0xc42000a36c, 0x7, 0x0, 0x0, 0xc42006a8a0, 0x1, ...)
	/srv/app/src/github.com/appleboy/drone-ssh/plugin.go:71 +0x31e
created by main.Plugin.Exec
	/srv/app/src/github.com/appleboy/drone-ssh/plugin.go:79 +0x176

If I run appleboy/drone-ssh on the command line like so

docker run --rm -e PLUGIN_HOST=example.dev -e PLUGIN_USER=nemonik -e PLUGIN_KEY="$(cat /home/nemonik/.ssh/ephemeral)" -e PLUGIN_SCRIPT="whoami" -v $(pwd):$(pwd) -w $(pwd) appleboy/drone-ssh:latest

I get:

2017/02/27 19:40:58 example.dev: commands:  whoami
2017/02/27 19:40:59 example.dev: outputs: nemonik

2017/02/27 19:40:59 Successfully executed commands to all host.

@PeterCat12, I cloned the appleboy/drone-ssh repo, added logging to print out p inside the Exec function in plugin.go to verify envs were being passed, then built the image.

I added SSH_KEY_PATH and SSH_KEY secrets via drone respectfully like so

drone secret add --image=ephemeral/drone-ssh Ephemeral/nodejs-helloworld SSH_KEY_PATH /home/nemonik/.ssh/ephemeral
drone secret add --image=ephemeral/drone-ssh Ephemeral/nodejs-helloworld SSH_KEY @/home/nemonik/.ssh/ephemeral

Passing SSH_KEY_PATH ephemeral/drone-ssh spits out

{
	"Config": {
		"Key": "${SSH_KEY_PATH}",
		"KeyPath": "/home/nemonik/.ssh/ephemeral",
		"UserName": "nemonik",
		"Password": "",
		"Host": [
			"example.dev"
		],
		"Port": 22,
		"Timeout": 0,
		"Script": [
			"whoami"
		]
	}
}

for .drone.yml entry

  ssh-deploy:
#    image: appleboy/drone-ssh
    image: ephemeral/drone-ssh
#    pull: true
    host: example.dev
    port: 22
    user: nemonik    
    key: ${SSH_KEY_PATH}
    script:
      - whoami

And then for the SSH_KEY

{
	"Config": {
		"Key": "${SSH_KEY}",
		"KeyPath": "/home/nemonik/.ssh/ephemeral",
		"UserName": "nemonik",
		"Password": "",
		"Host": [
			"example.dev"
		],
		"Port": 22,
		"Timeout": 0,
		"Script": [
			"whoami"
		]
	}
}

for .drone.yml entry

  ssh-deploy:
#    image: appleboy/drone-ssh
    image: ephemeral/drone-ssh
#    pull: true
    host: example.dev
    port: 22
    user: nemonik    
    key: ${SSH_KEY}
    script:
      - whoami

Am I missing something like fundamentally stupid?

So

$ docker run --rm \
→   -e PLUGIN_HOST=192.168.1.100 \
→   -e PLUGIN_USER=drone-scp \
→   -e PLUGIN_KEY="$(cat ${HOME}/.ssh/id_rsa)" \
→   -e PLUGIN_SCRIPT="whoami" \
→   -v $(pwd):$(pwd) \
→   -w $(pwd) \
→  appleboy/drone-ssh

Modified for my environment works returning:

2017/02/27 17:45:34 cocreate-centos7: commands:  whoami
2017/02/27 17:45:34 cocreate-centos7: outputs: nemonik