Skip to content

Commit f2acfa9

Browse files
committed
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 <maksim.malchuk@gmail.com>
1 parent 8141874 commit f2acfa9

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

libmachine/ssh/client.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,19 @@ func NewExternalClient(sshBinaryPath, user, host string, port int, auth *Auth) (
321321
// Specify which private keys to use to authorize the SSH request.
322322
for _, privateKeyPath := range auth.Keys {
323323
if privateKeyPath != "" {
324+
// Check each private key before use it
325+
fi, err := os.Stat(privateKeyPath)
326+
if err != nil {
327+
// Abort if key not accessible
328+
return nil, err
329+
}
330+
mode := fi.Mode()
331+
log.Debugf("Using SSH private key: %s (%s)", privateKeyPath, mode)
332+
// Private key file should have strict permissions
333+
if mode != 0600 {
334+
// Abort with correct message
335+
return nil, fmt.Errorf("Permissions %#o for '%s' are too open.", mode, privateKeyPath)
336+
}
324337
args = append(args, "-i", privateKeyPath)
325338
}
326339
}

libmachine/ssh/client_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,36 @@ func TestGetSSHCmdArgs(t *testing.T) {
4343
assert.Equal(t, cmd.Args, c.expectedArgs)
4444
}
4545
}
46+
47+
func TestNewExternalClient(t *testing.T) {
48+
cases := []struct {
49+
sshBinaryPath string
50+
user string
51+
host string
52+
port int
53+
auth *Auth
54+
expectedError string
55+
}{
56+
{
57+
sshBinaryPath: "/usr/local/bin/ssh",
58+
user: "docker",
59+
host: "localhost",
60+
port: 22,
61+
auth: &Auth{Keys: []string{"/tmp/private-key-not-exist"}},
62+
expectedError: "stat /tmp/private-key-not-exist: no such file or directory",
63+
},
64+
{
65+
sshBinaryPath: "/usr/local/bin/ssh",
66+
user: "docker",
67+
host: "localhost",
68+
port: 22,
69+
auth: &Auth{Keys: []string{"/dev/null"}},
70+
expectedError: "Permissions 0410000666 for '/dev/null' are too open.",
71+
},
72+
}
73+
74+
for _, c := range cases {
75+
_, err := NewExternalClient(c.sshBinaryPath, c.user, c.host, c.port, c.auth)
76+
assert.EqualError(t, err, c.expectedError)
77+
}
78+
}

0 commit comments

Comments
 (0)