mirror of https://github.com/docker/docs.git
				
				
				
			Allowing generic driver to use ssh-agent to get identities
Signed-off-by: Dave Henderson <dhenderson@gmail.com>
This commit is contained in:
		
							parent
							
								
									c2ed9e3f1c
								
							
						
					
					
						commit
						cf6136fed0
					
				|  | @ -33,9 +33,20 @@ Options: | |||
| 
 | ||||
| Environment variables and default values: | ||||
| 
 | ||||
| | CLI option                 | Environment variable | Default             | | ||||
| | -------------------------- | -------------------- | ------------------- | | ||||
| | **`--generic-ip-address`** | `GENERIC_IP_ADDRESS` | -                   | | ||||
| | `--generic-ssh-key`        | `GENERIC_SSH_KEY`    | `$HOME/.ssh/id_rsa` | | ||||
| | `--generic-ssh-user`       | `GENERIC_SSH_USER`   | `root`              | | ||||
| | `--generic-ssh-port`       | `GENERIC_SSH_PORT`   | `22`                | | ||||
| | CLI option                 | Environment variable | Default                   | | ||||
| |----------------------------|----------------------|---------------------------| | ||||
| | **`--generic-ip-address`** | `GENERIC_IP_ADDRESS` | -                         | | ||||
| | `--generic-ssh-key`        | `GENERIC_SSH_KEY`    | _(defers to `ssh-agent`)_ | | ||||
| | `--generic-ssh-user`       | `GENERIC_SSH_USER`   | `root`                    | | ||||
| | `--generic-ssh-port`       | `GENERIC_SSH_PORT`   | `22`                      | | ||||
| 
 | ||||
| ##### Interaction with SSH Agents | ||||
| 
 | ||||
| When an SSH identity is not provided (with the `--generic-ssh-key` flag), | ||||
| the SSH agent (if running) will be consulted. This makes it possible to | ||||
| easily use password-protected SSH keys. | ||||
| 
 | ||||
| Note that this usage is _only_ supported if you're using the external SSH client, | ||||
| which is the default behaviour when the `ssh` binary is available. If you're | ||||
| using the native client (with `--native-ssh`), using the SSH agent is not yet | ||||
| supported. | ||||
|  |  | |||
|  | @ -5,7 +5,6 @@ import ( | |||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strconv" | ||||
| 	"time" | ||||
| 
 | ||||
|  | @ -25,10 +24,6 @@ const ( | |||
| 	defaultTimeout = 1 * time.Second | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	defaultSourceSSHKey = filepath.Join(mcnutils.GetHomeDir(), ".ssh", "id_rsa") | ||||
| ) | ||||
| 
 | ||||
| // GetCreateFlags registers the flags this driver adds to
 | ||||
| // "docker hosts create"
 | ||||
| func (d *Driver) GetCreateFlags() []mcnflag.Flag { | ||||
|  | @ -46,8 +41,8 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag { | |||
| 		}, | ||||
| 		mcnflag.StringFlag{ | ||||
| 			Name:   "generic-ssh-key", | ||||
| 			Usage:  "SSH private key path", | ||||
| 			Value:  defaultSourceSSHKey, | ||||
| 			Usage:  "SSH private key path (if not provided, identities in ssh-agent will be used)", | ||||
| 			Value:  "", | ||||
| 			EnvVar: "GENERIC_SSH_KEY", | ||||
| 		}, | ||||
| 		mcnflag.IntFlag{ | ||||
|  | @ -66,7 +61,6 @@ func NewDriver(hostName, storePath string) drivers.Driver { | |||
| 			MachineName: hostName, | ||||
| 			StorePath:   storePath, | ||||
| 		}, | ||||
| 		SSHKey: defaultSourceSSHKey, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -83,6 +77,17 @@ func (d *Driver) GetSSHUsername() string { | |||
| 	return d.SSHUser | ||||
| } | ||||
| 
 | ||||
| func (d *Driver) GetSSHKeyPath() string { | ||||
| 	if d.SSHKey == "" { | ||||
| 		return "" | ||||
| 	} | ||||
| 
 | ||||
| 	if d.SSHKeyPath == "" { | ||||
| 		d.SSHKeyPath = d.ResolveStorePath("id_rsa") | ||||
| 	} | ||||
| 	return d.SSHKeyPath | ||||
| } | ||||
| 
 | ||||
| func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error { | ||||
| 	d.IPAddress = flags.String("generic-ip-address") | ||||
| 	d.SSHUser = flags.String("generic-ssh-user") | ||||
|  | @ -93,31 +98,33 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error { | |||
| 		return errors.New("generic driver requires the --generic-ip-address option") | ||||
| 	} | ||||
| 
 | ||||
| 	if d.SSHKey == "" { | ||||
| 		return errors.New("generic driver requires the --generic-ssh-key option") | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (d *Driver) PreCreateCheck() error { | ||||
| 	if _, err := os.Stat(d.SSHKey); os.IsNotExist(err) { | ||||
| 		return fmt.Errorf("Ssh key does not exist: %q", d.SSHKey) | ||||
| 	if d.SSHKey != "" { | ||||
| 		if _, err := os.Stat(d.SSHKey); os.IsNotExist(err) { | ||||
| 			return fmt.Errorf("Ssh key does not exist: %q", d.SSHKey) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (d *Driver) Create() error { | ||||
| 	log.Info("Importing SSH key...") | ||||
| 	if d.SSHKey == "" { | ||||
| 		log.Info("No SSH key specified. Connecting to this machine now and in the" + | ||||
| 			" future will require the ssh agent to contain the appropriate key.") | ||||
| 	} else { | ||||
| 		log.Info("Importing SSH key...") | ||||
| 		// TODO: validate the key is a valid key
 | ||||
| 		if err := mcnutils.CopyFile(d.SSHKey, d.GetSSHKeyPath()); err != nil { | ||||
| 			return fmt.Errorf("unable to copy ssh key: %s", err) | ||||
| 		} | ||||
| 
 | ||||
| 	// TODO: validate the key is a valid key
 | ||||
| 	if err := mcnutils.CopyFile(d.SSHKey, d.GetSSHKeyPath()); err != nil { | ||||
| 		return fmt.Errorf("unable to copy ssh key: %s", err) | ||||
| 	} | ||||
| 
 | ||||
| 	if err := os.Chmod(d.GetSSHKeyPath(), 0600); err != nil { | ||||
| 		return fmt.Errorf("unable to set permissions on the ssh key: %s", err) | ||||
| 		if err := os.Chmod(d.GetSSHKeyPath(), 0600); err != nil { | ||||
| 			return fmt.Errorf("unable to set permissions on the ssh key: %s", err) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	log.Debugf("IP: %s", d.IPAddress) | ||||
|  |  | |||
|  | @ -19,8 +19,13 @@ func GetSSHClientFromDriver(d Driver) (ssh.Client, error) { | |||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	auth := &ssh.Auth{ | ||||
| 		Keys: []string{d.GetSSHKeyPath()}, | ||||
| 	var auth *ssh.Auth | ||||
| 	if d.GetSSHKeyPath() == "" { | ||||
| 		auth = &ssh.Auth{} | ||||
| 	} else { | ||||
| 		auth = &ssh.Auth{ | ||||
| 			Keys: []string{d.GetSSHKeyPath()}, | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	client, err := ssh.NewClient(d.GetSSHUsername(), address, port, auth) | ||||
|  |  | |||
|  | @ -69,8 +69,13 @@ func (h *Host) CreateSSHClient() (ssh.Client, error) { | |||
| 		return ssh.ExternalClient{}, err | ||||
| 	} | ||||
| 
 | ||||
| 	auth := &ssh.Auth{ | ||||
| 		Keys: []string{h.Driver.GetSSHKeyPath()}, | ||||
| 	var auth *ssh.Auth | ||||
| 	if h.Driver.GetSSHKeyPath() == "" { | ||||
| 		auth = &ssh.Auth{} | ||||
| 	} else { | ||||
| 		auth = &ssh.Auth{ | ||||
| 			Keys: []string{h.Driver.GetSSHKeyPath()}, | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return ssh.NewClient(h.Driver.GetSSHUsername(), addr, port, auth) | ||||
|  |  | |||
|  | @ -49,7 +49,6 @@ const ( | |||
| var ( | ||||
| 	baseSSHArgs = []string{ | ||||
| 		"-o", "PasswordAuthentication=no", | ||||
| 		"-o", "IdentitiesOnly=yes", | ||||
| 		"-o", "StrictHostKeyChecking=no", | ||||
| 		"-o", "UserKnownHostsFile=/dev/null", | ||||
| 		"-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) ( | |||
| 
 | ||||
| 	args := append(baseSSHArgs, fmt.Sprintf("%s@%s", user, host)) | ||||
| 
 | ||||
| 	// If no identities are explicitly provided, also look at the identities
 | ||||
| 	// offered by ssh-agent
 | ||||
| 	if len(auth.Keys) > 0 { | ||||
| 		args = append(args, "-o", "IdentitiesOnly=yes") | ||||
| 	} | ||||
| 
 | ||||
| 	// Specify which private keys to use to authorize the SSH request.
 | ||||
| 	for _, privateKeyPath := range auth.Keys { | ||||
| 		args = append(args, "-i", privateKeyPath) | ||||
| 		if privateKeyPath != "" { | ||||
| 			args = append(args, "-i", privateKeyPath) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Set which port to use for SSH.
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue