mirror of
https://github.com/appleboy/drone-ssh.git
synced 2025-05-09 18:23:21 +08:00
support Fingerprint (#157)
This commit is contained in:
parent
923defc397
commit
a2c6be3c19
30
main.go
30
main.go
@ -65,6 +65,11 @@ func main() {
|
|||||||
EnvVar: "PLUGIN_CIPHERS,SSH_CIPHERS,CIPHERS,INPUT_CIPHERS",
|
EnvVar: "PLUGIN_CIPHERS,SSH_CIPHERS,CIPHERS,INPUT_CIPHERS",
|
||||||
Value: &defaultCiphers,
|
Value: &defaultCiphers,
|
||||||
},
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "fingerprint",
|
||||||
|
Usage: "fingerprint as unpadded base64 encoded sha256 hash.",
|
||||||
|
EnvVar: "PLUGIN_FINGERPRINT,SSH_FINGERPRINT,FINGERPRINT,INPUT_FINGERPRINT",
|
||||||
|
},
|
||||||
cli.StringSliceFlag{
|
cli.StringSliceFlag{
|
||||||
Name: "host,H",
|
Name: "host,H",
|
||||||
Usage: "connect to host",
|
Usage: "connect to host",
|
||||||
@ -157,6 +162,11 @@ func main() {
|
|||||||
EnvVar: "PLUGIN_PROXY_CIPHERS,SSH_PROXY_CIPHERS,PROXY_CIPHERS,INPUT_PROXY_CIPHERS",
|
EnvVar: "PLUGIN_PROXY_CIPHERS,SSH_PROXY_CIPHERS,PROXY_CIPHERS,INPUT_PROXY_CIPHERS",
|
||||||
Value: &defaultCiphers,
|
Value: &defaultCiphers,
|
||||||
},
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "proxy.fingerprint",
|
||||||
|
Usage: "fingerprint as unpadded base64 encoded sha256 hash.",
|
||||||
|
EnvVar: "PLUGIN_PROXY_FINGERPRINT,SSH_PROXY_FINGERPRINT,PROXY_FINGERPRINT,INPUT_PROXY_FINGERPRINT",
|
||||||
|
},
|
||||||
cli.StringSliceFlag{
|
cli.StringSliceFlag{
|
||||||
Name: "envs",
|
Name: "envs",
|
||||||
Usage: "pass environment variable to shell script",
|
Usage: "pass environment variable to shell script",
|
||||||
@ -219,6 +229,7 @@ func run(c *cli.Context) error {
|
|||||||
Username: c.String("user"),
|
Username: c.String("user"),
|
||||||
Password: c.String("password"),
|
Password: c.String("password"),
|
||||||
Passphrase: c.String("ssh-passphrase"),
|
Passphrase: c.String("ssh-passphrase"),
|
||||||
|
Fingerprint: c.String("fingerprint"),
|
||||||
Host: c.StringSlice("host"),
|
Host: c.StringSlice("host"),
|
||||||
Port: c.Int("port"),
|
Port: c.Int("port"),
|
||||||
Timeout: c.Duration("timeout"),
|
Timeout: c.Duration("timeout"),
|
||||||
@ -230,15 +241,16 @@ func run(c *cli.Context) error {
|
|||||||
Sync: c.Bool("sync"),
|
Sync: c.Bool("sync"),
|
||||||
Ciphers: c.StringSlice("ciphers"),
|
Ciphers: c.StringSlice("ciphers"),
|
||||||
Proxy: easyssh.DefaultConfig{
|
Proxy: easyssh.DefaultConfig{
|
||||||
Key: c.String("proxy.ssh-key"),
|
Key: c.String("proxy.ssh-key"),
|
||||||
KeyPath: c.String("proxy.key-path"),
|
KeyPath: c.String("proxy.key-path"),
|
||||||
User: c.String("proxy.username"),
|
User: c.String("proxy.username"),
|
||||||
Password: c.String("proxy.password"),
|
Password: c.String("proxy.password"),
|
||||||
Passphrase: c.String("proxy.ssh-passphrase"),
|
Passphrase: c.String("proxy.ssh-passphrase"),
|
||||||
Server: c.String("proxy.host"),
|
Fingerprint: c.String("proxy.fingerprint"),
|
||||||
Port: c.String("proxy.port"),
|
Server: c.String("proxy.host"),
|
||||||
Timeout: c.Duration("proxy.timeout"),
|
Port: c.String("proxy.port"),
|
||||||
Ciphers: c.StringSlice("proxy.ciphers"),
|
Timeout: c.Duration("proxy.timeout"),
|
||||||
|
Ciphers: c.StringSlice("proxy.ciphers"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Writer: os.Stdout,
|
Writer: os.Stdout,
|
||||||
|
39
plugin.go
39
plugin.go
@ -30,6 +30,7 @@ type (
|
|||||||
Password string
|
Password string
|
||||||
Host []string
|
Host []string
|
||||||
Port int
|
Port int
|
||||||
|
Fingerprint string
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
CommandTimeout time.Duration
|
CommandTimeout time.Duration
|
||||||
Script []string
|
Script []string
|
||||||
@ -55,25 +56,27 @@ func escapeArg(arg string) string {
|
|||||||
func (p Plugin) exec(host string, wg *sync.WaitGroup, errChannel chan error) {
|
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.
|
// Create MakeConfig instance with remote username, server address and path to private key.
|
||||||
ssh := &easyssh.MakeConfig{
|
ssh := &easyssh.MakeConfig{
|
||||||
Server: host,
|
Server: host,
|
||||||
User: p.Config.Username,
|
User: p.Config.Username,
|
||||||
Password: p.Config.Password,
|
Password: p.Config.Password,
|
||||||
Port: strconv.Itoa(p.Config.Port),
|
Port: strconv.Itoa(p.Config.Port),
|
||||||
Key: p.Config.Key,
|
Key: p.Config.Key,
|
||||||
KeyPath: p.Config.KeyPath,
|
KeyPath: p.Config.KeyPath,
|
||||||
Passphrase: p.Config.Passphrase,
|
Passphrase: p.Config.Passphrase,
|
||||||
Timeout: p.Config.Timeout,
|
Timeout: p.Config.Timeout,
|
||||||
Ciphers: p.Config.Ciphers,
|
Ciphers: p.Config.Ciphers,
|
||||||
|
Fingerprint: p.Config.Fingerprint,
|
||||||
Proxy: easyssh.DefaultConfig{
|
Proxy: easyssh.DefaultConfig{
|
||||||
Server: p.Config.Proxy.Server,
|
Server: p.Config.Proxy.Server,
|
||||||
User: p.Config.Proxy.User,
|
User: p.Config.Proxy.User,
|
||||||
Password: p.Config.Proxy.Password,
|
Password: p.Config.Proxy.Password,
|
||||||
Port: p.Config.Proxy.Port,
|
Port: p.Config.Proxy.Port,
|
||||||
Key: p.Config.Proxy.Key,
|
Key: p.Config.Proxy.Key,
|
||||||
KeyPath: p.Config.Proxy.KeyPath,
|
KeyPath: p.Config.Proxy.KeyPath,
|
||||||
Passphrase: p.Config.Proxy.Passphrase,
|
Passphrase: p.Config.Proxy.Passphrase,
|
||||||
Timeout: p.Config.Proxy.Timeout,
|
Timeout: p.Config.Proxy.Timeout,
|
||||||
Ciphers: p.Config.Proxy.Ciphers,
|
Ciphers: p.Config.Proxy.Ciphers,
|
||||||
|
Fingerprint: p.Config.Proxy.Fingerprint,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
@ -11,6 +12,7 @@ import (
|
|||||||
|
|
||||||
"github.com/appleboy/easyssh-proxy"
|
"github.com/appleboy/easyssh-proxy"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"golang.org/x/crypto/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMissingHostOrUser(t *testing.T) {
|
func TestMissingHostOrUser(t *testing.T) {
|
||||||
@ -384,6 +386,80 @@ func TestCommandOutput(t *testing.T) {
|
|||||||
assert.Equal(t, unindent(expected), unindent(buffer.String()))
|
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) {
|
func TestScriptStop(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
buffer bytes.Buffer
|
buffer bytes.Buffer
|
||||||
|
Loading…
Reference in New Issue
Block a user