From f2acfa9492d9352edeb722ba625adaf86bcdee7e Mon Sep 17 00:00:00 2001 From: Maksim Malchuk Date: Sat, 26 Mar 2016 00:02:41 +0300 Subject: [PATCH] Correct error handling for external SSH client In some cases, (e.g. private key not accessible or has incorrect permissions) docker-machine failed with error "Something went wrong running an SSH command!". This commit will add the correct debug messages and show the correct errors for the bad private keys. Signed-off-by: Maksim Malchuk --- libmachine/ssh/client.go | 13 +++++++++++++ libmachine/ssh/client_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/libmachine/ssh/client.go b/libmachine/ssh/client.go index 7ff2b110b7..c54a080bfe 100644 --- a/libmachine/ssh/client.go +++ b/libmachine/ssh/client.go @@ -321,6 +321,19 @@ func NewExternalClient(sshBinaryPath, user, host string, port int, auth *Auth) ( // Specify which private keys to use to authorize the SSH request. for _, privateKeyPath := range auth.Keys { if privateKeyPath != "" { + // Check each private key before use it + fi, err := os.Stat(privateKeyPath) + if err != nil { + // Abort if key not accessible + return nil, err + } + mode := fi.Mode() + log.Debugf("Using SSH private key: %s (%s)", privateKeyPath, mode) + // Private key file should have strict permissions + if mode != 0600 { + // Abort with correct message + return nil, fmt.Errorf("Permissions %#o for '%s' are too open.", mode, privateKeyPath) + } args = append(args, "-i", privateKeyPath) } } diff --git a/libmachine/ssh/client_test.go b/libmachine/ssh/client_test.go index 65d35becd9..55765d6d94 100644 --- a/libmachine/ssh/client_test.go +++ b/libmachine/ssh/client_test.go @@ -43,3 +43,36 @@ func TestGetSSHCmdArgs(t *testing.T) { assert.Equal(t, cmd.Args, c.expectedArgs) } } + +func TestNewExternalClient(t *testing.T) { + cases := []struct { + sshBinaryPath string + user string + host string + port int + auth *Auth + expectedError string + }{ + { + sshBinaryPath: "/usr/local/bin/ssh", + user: "docker", + host: "localhost", + port: 22, + auth: &Auth{Keys: []string{"/tmp/private-key-not-exist"}}, + expectedError: "stat /tmp/private-key-not-exist: no such file or directory", + }, + { + sshBinaryPath: "/usr/local/bin/ssh", + user: "docker", + host: "localhost", + port: 22, + auth: &Auth{Keys: []string{"/dev/null"}}, + expectedError: "Permissions 0410000666 for '/dev/null' are too open.", + }, + } + + for _, c := range cases { + _, err := NewExternalClient(c.sshBinaryPath, c.user, c.host, c.port, c.auth) + assert.EqualError(t, err, c.expectedError) + } +}