feat: Support import private key from file path.

This commit is contained in:
Bo-Yi Wu 2017-01-24 11:25:09 +08:00
parent 79530c6026
commit 91e9d27c5a
3 changed files with 84 additions and 2 deletions

View File

@ -30,6 +30,11 @@ func main() {
Usage: "private ssh key",
EnvVar: "PLUGIN_SSH_KEY,PLUGIN_KEY,SSH_KEY",
},
cli.StringFlag{
Name: "key-path",
Usage: "ssh private key path",
EnvVar: "PLUGIN_KEY_PATH,SSH_KEY_PATH",
},
cli.StringFlag{
Name: "user",
Usage: "connect as user",
@ -117,6 +122,7 @@ func run(c *cli.Context) error {
plugin := Plugin{
Config: Config{
Key: c.String("ssh-key"),
KeyPath: c.String("key-path"),
User: c.String("user"),
Password: c.String("password"),
Host: c.StringSlice("host"),

View File

@ -2,6 +2,7 @@ package main
import (
"fmt"
"io/ioutil"
"log"
"net"
"os"
@ -17,12 +18,14 @@ const (
missingPasswordOrKey = "Error: can't connect without a private SSH key or password"
unableConnectServer = "Error: Failed to start a SSH session"
failParsePrivateKey = "Error: Failed to parse private key"
sshKeyNotFound = "ssh: no key found"
)
type (
// Config for the plugin.
Config struct {
Key string
KeyPath string
User string
Password string
Host []string
@ -38,13 +41,29 @@ type (
}
)
// returns ssh.Signer from user you running app home path + cutted key path.
// (ex. pubkey,err := getKeyFile("/.ssh/id_rsa") )
func getKeyFile(keypath string) (ssh.Signer, error) {
buf, err := ioutil.ReadFile(keypath)
if err != nil {
return nil, err
}
pubkey, err := ssh.ParsePrivateKey(buf)
if err != nil {
return nil, err
}
return pubkey, nil
}
// Exec executes the plugin.
func (p Plugin) Exec() error {
if len(p.Config.Host) == 0 && p.Config.User == "" {
return fmt.Errorf(missingHostOrUser)
}
if p.Config.Key == "" && p.Config.Password == "" {
if p.Config.Key == "" && p.Config.Password == "" && p.Config.KeyPath == "" {
return fmt.Errorf(missingPasswordOrKey)
}
@ -57,6 +76,16 @@ func (p Plugin) Exec() error {
// auths holds the detected ssh auth methods
auths := []ssh.AuthMethod{}
if p.Config.KeyPath != "" {
pubkey, err := getKeyFile(p.Config.KeyPath)
if err != nil {
return err
}
auths = append(auths, ssh.PublicKeys(pubkey))
}
if p.Config.Key != "" {
signer, err := ssh.ParsePrivateKey([]byte(p.Config.Key))

View File

@ -61,7 +61,7 @@ func TestFailParsePrivateKey(t *testing.T) {
assert.Equal(t, failParsePrivateKey, err.Error())
}
func TestSSHScript(t *testing.T) {
func TestSSHScriptFromRawKey(t *testing.T) {
plugin := Plugin{
Config: Config{
Host: []string{"localhost"},
@ -102,3 +102,50 @@ ib4KbP5ovZlrjL++akMQ7V2fHzuQIFWnCkDA5c2ZAqzlM+ZN+HRG7gWur7Bt4XH1
err := plugin.Exec()
assert.Nil(t, err)
}
func TestWrongKeyPath(t *testing.T) {
plugin := Plugin{
Config: Config{
Host: []string{"localhost"},
User: "drone-scp",
Port: 22,
KeyPath: "/appleboy",
Script: []string{"whoami"},
},
}
err := plugin.Exec()
assert.NotNil(t, err)
assert.Equal(t, "open /appleboy: no such file or directory", err.Error())
}
func TestWrongKeyFormat(t *testing.T) {
plugin := Plugin{
Config: Config{
Host: []string{"localhost"},
User: "drone-scp",
Port: 22,
KeyPath: "./tests/.ssh/id_rsa.pub",
Script: []string{"whoami"},
},
}
err := plugin.Exec()
assert.NotNil(t, err)
assert.Equal(t, sshKeyNotFound, err.Error())
}
func TestSSHScriptFromKeyFile(t *testing.T) {
plugin := Plugin{
Config: Config{
Host: []string{"localhost"},
User: "drone-scp",
Port: 22,
KeyPath: "./tests/.ssh/id_rsa",
Script: []string{"whoami"},
},
}
err := plugin.Exec()
assert.Nil(t, err)
}