X Tutup
Skip to content

Commit d29a42e

Browse files
Merge pull request docker-archive-public#1299 from hairyhenderson/ssh-agent-support-1291
Allowing generic driver to use ssh-agent to get identities
2 parents 104b04d + cf6136f commit d29a42e

File tree

5 files changed

+70
-35
lines changed

5 files changed

+70
-35
lines changed

docs/drivers/generic.md

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,20 @@ Options:
3333
3434
Environment variables and default values:
3535

36-
| CLI option | Environment variable | Default |
37-
| -------------------------- | -------------------- | ------------------- |
38-
| **`--generic-ip-address`** | `GENERIC_IP_ADDRESS` | - |
39-
| `--generic-ssh-key` | `GENERIC_SSH_KEY` | `$HOME/.ssh/id_rsa` |
40-
| `--generic-ssh-user` | `GENERIC_SSH_USER` | `root` |
41-
| `--generic-ssh-port` | `GENERIC_SSH_PORT` | `22` |
36+
| CLI option | Environment variable | Default |
37+
|----------------------------|----------------------|---------------------------|
38+
| **`--generic-ip-address`** | `GENERIC_IP_ADDRESS` | - |
39+
| `--generic-ssh-key` | `GENERIC_SSH_KEY` | _(defers to `ssh-agent`)_ |
40+
| `--generic-ssh-user` | `GENERIC_SSH_USER` | `root` |
41+
| `--generic-ssh-port` | `GENERIC_SSH_PORT` | `22` |
42+
43+
##### Interaction with SSH Agents
44+
45+
When an SSH identity is not provided (with the `--generic-ssh-key` flag),
46+
the SSH agent (if running) will be consulted. This makes it possible to
47+
easily use password-protected SSH keys.
48+
49+
Note that this usage is _only_ supported if you're using the external SSH client,
50+
which is the default behaviour when the `ssh` binary is available. If you're
51+
using the native client (with `--native-ssh`), using the SSH agent is not yet
52+
supported.

drivers/generic/generic.go

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"fmt"
66
"net"
77
"os"
8-
"path/filepath"
98
"strconv"
109
"time"
1110

@@ -25,10 +24,6 @@ const (
2524
defaultTimeout = 1 * time.Second
2625
)
2726

28-
var (
29-
defaultSourceSSHKey = filepath.Join(mcnutils.GetHomeDir(), ".ssh", "id_rsa")
30-
)
31-
3227
// GetCreateFlags registers the flags this driver adds to
3328
// "docker hosts create"
3429
func (d *Driver) GetCreateFlags() []mcnflag.Flag {
@@ -46,8 +41,8 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag {
4641
},
4742
mcnflag.StringFlag{
4843
Name: "generic-ssh-key",
49-
Usage: "SSH private key path",
50-
Value: defaultSourceSSHKey,
44+
Usage: "SSH private key path (if not provided, identities in ssh-agent will be used)",
45+
Value: "",
5146
EnvVar: "GENERIC_SSH_KEY",
5247
},
5348
mcnflag.IntFlag{
@@ -66,7 +61,6 @@ func NewDriver(hostName, storePath string) drivers.Driver {
6661
MachineName: hostName,
6762
StorePath: storePath,
6863
},
69-
SSHKey: defaultSourceSSHKey,
7064
}
7165
}
7266

@@ -83,6 +77,17 @@ func (d *Driver) GetSSHUsername() string {
8377
return d.SSHUser
8478
}
8579

80+
func (d *Driver) GetSSHKeyPath() string {
81+
if d.SSHKey == "" {
82+
return ""
83+
}
84+
85+
if d.SSHKeyPath == "" {
86+
d.SSHKeyPath = d.ResolveStorePath("id_rsa")
87+
}
88+
return d.SSHKeyPath
89+
}
90+
8691
func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
8792
d.IPAddress = flags.String("generic-ip-address")
8893
d.SSHUser = flags.String("generic-ssh-user")
@@ -93,31 +98,33 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
9398
return errors.New("generic driver requires the --generic-ip-address option")
9499
}
95100

96-
if d.SSHKey == "" {
97-
return errors.New("generic driver requires the --generic-ssh-key option")
98-
}
99-
100101
return nil
101102
}
102103

103104
func (d *Driver) PreCreateCheck() error {
104-
if _, err := os.Stat(d.SSHKey); os.IsNotExist(err) {
105-
return fmt.Errorf("Ssh key does not exist: %q", d.SSHKey)
105+
if d.SSHKey != "" {
106+
if _, err := os.Stat(d.SSHKey); os.IsNotExist(err) {
107+
return fmt.Errorf("Ssh key does not exist: %q", d.SSHKey)
108+
}
106109
}
107110

108111
return nil
109112
}
110113

111114
func (d *Driver) Create() error {
112-
log.Info("Importing SSH key...")
113-
114-
// TODO: validate the key is a valid key
115-
if err := mcnutils.CopyFile(d.SSHKey, d.GetSSHKeyPath()); err != nil {
116-
return fmt.Errorf("unable to copy ssh key: %s", err)
117-
}
118-
119-
if err := os.Chmod(d.GetSSHKeyPath(), 0600); err != nil {
120-
return fmt.Errorf("unable to set permissions on the ssh key: %s", err)
115+
if d.SSHKey == "" {
116+
log.Info("No SSH key specified. Connecting to this machine now and in the" +
117+
" future will require the ssh agent to contain the appropriate key.")
118+
} else {
119+
log.Info("Importing SSH key...")
120+
// TODO: validate the key is a valid key
121+
if err := mcnutils.CopyFile(d.SSHKey, d.GetSSHKeyPath()); err != nil {
122+
return fmt.Errorf("unable to copy ssh key: %s", err)
123+
}
124+
125+
if err := os.Chmod(d.GetSSHKeyPath(), 0600); err != nil {
126+
return fmt.Errorf("unable to set permissions on the ssh key: %s", err)
127+
}
121128
}
122129

123130
log.Debugf("IP: %s", d.IPAddress)

libmachine/drivers/utils.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,13 @@ func GetSSHClientFromDriver(d Driver) (ssh.Client, error) {
1919
return nil, err
2020
}
2121

22-
auth := &ssh.Auth{
23-
Keys: []string{d.GetSSHKeyPath()},
22+
var auth *ssh.Auth
23+
if d.GetSSHKeyPath() == "" {
24+
auth = &ssh.Auth{}
25+
} else {
26+
auth = &ssh.Auth{
27+
Keys: []string{d.GetSSHKeyPath()},
28+
}
2429
}
2530

2631
client, err := ssh.NewClient(d.GetSSHUsername(), address, port, auth)

libmachine/host/host.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,13 @@ func (h *Host) CreateSSHClient() (ssh.Client, error) {
7070
return ssh.ExternalClient{}, err
7171
}
7272

73-
auth := &ssh.Auth{
74-
Keys: []string{h.Driver.GetSSHKeyPath()},
73+
var auth *ssh.Auth
74+
if h.Driver.GetSSHKeyPath() == "" {
75+
auth = &ssh.Auth{}
76+
} else {
77+
auth = &ssh.Auth{
78+
Keys: []string{h.Driver.GetSSHKeyPath()},
79+
}
7580
}
7681

7782
return ssh.NewClient(h.Driver.GetSSHUsername(), addr, port, auth)

libmachine/ssh/client.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ const (
4949
var (
5050
baseSSHArgs = []string{
5151
"-o", "PasswordAuthentication=no",
52-
"-o", "IdentitiesOnly=yes",
5352
"-o", "StrictHostKeyChecking=no",
5453
"-o", "UserKnownHostsFile=/dev/null",
5554
"-o", "LogLevel=quiet", // suppress "Warning: Permanently added '[localhost]:2022' (ECDSA) to the list of known hosts."
@@ -262,9 +261,17 @@ func NewExternalClient(sshBinaryPath, user, host string, port int, auth *Auth) (
262261

263262
args := append(baseSSHArgs, fmt.Sprintf("%s@%s", user, host))
264263

264+
// If no identities are explicitly provided, also look at the identities
265+
// offered by ssh-agent
266+
if len(auth.Keys) > 0 {
267+
args = append(args, "-o", "IdentitiesOnly=yes")
268+
}
269+
265270
// Specify which private keys to use to authorize the SSH request.
266271
for _, privateKeyPath := range auth.Keys {
267-
args = append(args, "-i", privateKeyPath)
272+
if privateKeyPath != "" {
273+
args = append(args, "-i", privateKeyPath)
274+
}
268275
}
269276

270277
// Set which port to use for SSH.

0 commit comments

Comments
 (0)
X Tutup