diff --git a/cluster/defaults.go b/cluster/defaults.go index 7bdf3f73..a09126fd 100644 --- a/cluster/defaults.go +++ b/cluster/defaults.go @@ -46,6 +46,7 @@ func (c *Cluster) setClusterDefaults(ctx context.Context) { if len(c.SSHKeyPath) == 0 { c.SSHKeyPath = DefaultClusterSSHKeyPath } + for i, host := range c.Nodes { if len(host.InternalAddress) == 0 { c.Nodes[i].InternalAddress = c.Nodes[i].Address @@ -60,7 +61,11 @@ func (c *Cluster) setClusterDefaults(ctx context.Context) { if len(host.Port) == 0 { c.Nodes[i].Port = DefaultSSHPort } + + // For now, you can set at the global level only. + c.Nodes[i].SSHAgentAuth = c.SSHAgentAuth } + if len(c.Authorization.Mode) == 0 { c.Authorization.Mode = DefaultAuthorizationMode } diff --git a/cmd/common.go b/cmd/common.go index 6bab4ac0..80e6a1e0 100644 --- a/cmd/common.go +++ b/cmd/common.go @@ -6,9 +6,17 @@ import ( "os" "path/filepath" + "github.com/rancher/types/apis/management.cattle.io/v3" "github.com/urfave/cli" ) +var sshCliOptions = []cli.Flag{ + cli.BoolFlag{ + Name: "ssh-agent-auth", + Usage: "Use SSH Agent Auth defined by SSH_AUTH_SOCK", + }, +} + func resolveClusterFile(ctx *cli.Context) (string, string, error) { clusterFile := ctx.String("config") fp, err := filepath.Abs(clusterFile) @@ -27,3 +35,11 @@ func resolveClusterFile(ctx *cli.Context) (string, string, error) { clusterFileBuff := string(buf) return clusterFileBuff, clusterFile, nil } + +func setOptionsFromCLI(c *cli.Context, rkeConfig *v3.RancherKubernetesEngineConfig) (*v3.RancherKubernetesEngineConfig, error) { + // If true... override the file.. else let file value go through + if c.Bool("ssh-agent-auth") { + rkeConfig.SSHAgentAuth = c.Bool("ssh-agent-auth") + } + return rkeConfig, nil +} diff --git a/cmd/remove.go b/cmd/remove.go index 48d143ac..4ac38b8b 100644 --- a/cmd/remove.go +++ b/cmd/remove.go @@ -34,6 +34,9 @@ func RemoveCommand() cli.Command { Usage: "Deploy Kubernetes cluster locally", }, } + + removeFlags = append(removeFlags, sshCliOptions...) + return cli.Command{ Name: "remove", Usage: "Teardown the cluster and clean cluster nodes", @@ -96,6 +99,12 @@ func clusterRemoveFromCli(ctx *cli.Context) error { if err != nil { return fmt.Errorf("Failed to parse cluster file: %v", err) } + + rkeConfig, err = setOptionsFromCLI(ctx, rkeConfig) + if err != nil { + return err + } + return ClusterRemove(context.Background(), rkeConfig, nil, nil, false, "") } @@ -113,5 +122,11 @@ func clusterRemoveLocal(ctx *cli.Context) error { } rkeConfig.Nodes = []v3.RKEConfigNode{*cluster.GetLocalRKENodeConfig()} } + + rkeConfig, err = setOptionsFromCLI(ctx, rkeConfig) + if err != nil { + return err + } + return ClusterRemove(context.Background(), rkeConfig, nil, nil, true, "") } diff --git a/cmd/up.go b/cmd/up.go index d3ac91ff..e2dcec5b 100644 --- a/cmd/up.go +++ b/cmd/up.go @@ -29,6 +29,9 @@ func UpCommand() cli.Command { Usage: "Deploy Kubernetes cluster locally", }, } + + upFlags = append(upFlags, sshCliOptions...) + return cli.Command{ Name: "up", Usage: "Bring the cluster up", @@ -139,6 +142,12 @@ func clusterUpFromCli(ctx *cli.Context) error { if err != nil { return fmt.Errorf("Failed to parse cluster file: %v", err) } + + rkeConfig, err = setOptionsFromCLI(ctx, rkeConfig) + if err != nil { + return err + } + _, _, _, _, err = ClusterUp(context.Background(), rkeConfig, nil, nil, nil, false, "") return err } diff --git a/hosts/dialer.go b/hosts/dialer.go index 735c150d..a91d0609 100644 --- a/hosts/dialer.go +++ b/hosts/dialer.go @@ -11,23 +11,25 @@ import ( type DialerFactory func(h *Host) (func(network, address string) (net.Conn, error), error) type dialer struct { - signer ssh.Signer - sshKeyString string - sshAddress string - sshPassphrase []byte - username string - netConn string - dockerSocket string + signer ssh.Signer + sshKeyString string + sshAddress string + sshPassphrase []byte + username string + netConn string + dockerSocket string + useSSHAgentAuth bool } func newDialer(h *Host, kind string) (*dialer, error) { dialer := &dialer{ - sshAddress: fmt.Sprintf("%s:%s", h.Address, h.Port), - username: h.User, - dockerSocket: h.DockerSocket, - sshKeyString: h.SSHKey, - netConn: "unix", - sshPassphrase: []byte(h.SavedKeyPhrase), + sshAddress: fmt.Sprintf("%s:%s", h.Address, h.Port), + username: h.User, + dockerSocket: h.DockerSocket, + sshKeyString: h.SSHKey, + netConn: "unix", + sshPassphrase: []byte(h.SavedKeyPhrase), + useSSHAgentAuth: h.SSHAgentAuth, } if dialer.sshKeyString == "" { @@ -84,7 +86,7 @@ func (d *dialer) Dial(network, addr string) (net.Conn, error) { } func (d *dialer) getSSHTunnelConnection() (*ssh.Client, error) { - cfg, err := getSSHConfig(d.username, d.sshKeyString, d.sshPassphrase) + cfg, err := getSSHConfig(d.username, d.sshKeyString, d.sshPassphrase, d.useSSHAgentAuth) if err != nil { return nil, fmt.Errorf("Error configuring SSH: %v", err) } diff --git a/hosts/tunnel.go b/hosts/tunnel.go index 5eeff356..87ef5f3a 100644 --- a/hosts/tunnel.go +++ b/hosts/tunnel.go @@ -82,22 +82,25 @@ func parsePrivateKeyWithPassPhrase(keyBuff string, passphrase []byte) (ssh.Signe return ssh.ParsePrivateKeyWithPassphrase([]byte(keyBuff), passphrase) } -func getSSHConfig(username, sshPrivateKeyString string, passphrase []byte) (*ssh.ClientConfig, error) { +func getSSHConfig(username, sshPrivateKeyString string, passphrase []byte, useAgentAuth bool) (*ssh.ClientConfig, error) { config := &ssh.ClientConfig{ User: username, HostKeyCallback: ssh.InsecureIgnoreHostKey(), } - if sshAgentSock := os.Getenv("SSH_AUTH_SOCK"); sshAgentSock != "" { - sshAgent, err := net.Dial("unix", sshAgentSock) - if err != nil { - return config, fmt.Errorf("Cannot connect to SSH Auth socket %q: %s", sshAgentSock, err) + // Kind of a double check now. + if useAgentAuth { + if sshAgentSock := os.Getenv("SSH_AUTH_SOCK"); sshAgentSock != "" { + sshAgent, err := net.Dial("unix", sshAgentSock) + if err != nil { + return config, fmt.Errorf("Cannot connect to SSH Auth socket %q: %s", sshAgentSock, err) + } + + config.Auth = append(config.Auth, ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers)) + + logrus.Debugf("using %q SSH_AUTH_SOCK", sshAgentSock) + return config, nil } - - config.Auth = append(config.Auth, ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers)) - - logrus.Debugf("using %q SSH_AUTH_SOCK", sshAgentSock) - return config, nil } signer, err := getPrivateKeySigner(sshPrivateKeyString, passphrase)