1
0
mirror of https://github.com/rancher/rke.git synced 2025-08-01 23:33:39 +00:00

Leverage global SSHAgentAuth setting

This addresses users issues in being unable to use RKE command line
using SSH_AUTH_SOCK. On OSX the socket env var is set, but nothing
is listening. Also, Linux users have reported issues. To address this
the default mode is to not use SSH Agent Auth. A user must set it
explicitly in either the config file or on the CLI. The only way
to use a passphrase protected key file is with a properly configured
SSH Agent and using SSH Agent Auth.
This commit is contained in:
Bill Maxwell 2018-03-05 17:52:43 -07:00
parent f76f954b42
commit ad0bc6c0aa
6 changed files with 74 additions and 24 deletions

View File

@ -46,6 +46,7 @@ func (c *Cluster) setClusterDefaults(ctx context.Context) {
if len(c.SSHKeyPath) == 0 { if len(c.SSHKeyPath) == 0 {
c.SSHKeyPath = DefaultClusterSSHKeyPath c.SSHKeyPath = DefaultClusterSSHKeyPath
} }
for i, host := range c.Nodes { for i, host := range c.Nodes {
if len(host.InternalAddress) == 0 { if len(host.InternalAddress) == 0 {
c.Nodes[i].InternalAddress = c.Nodes[i].Address c.Nodes[i].InternalAddress = c.Nodes[i].Address
@ -60,7 +61,11 @@ func (c *Cluster) setClusterDefaults(ctx context.Context) {
if len(host.Port) == 0 { if len(host.Port) == 0 {
c.Nodes[i].Port = DefaultSSHPort 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 { if len(c.Authorization.Mode) == 0 {
c.Authorization.Mode = DefaultAuthorizationMode c.Authorization.Mode = DefaultAuthorizationMode
} }

View File

@ -6,9 +6,17 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/rancher/types/apis/management.cattle.io/v3"
"github.com/urfave/cli" "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) { func resolveClusterFile(ctx *cli.Context) (string, string, error) {
clusterFile := ctx.String("config") clusterFile := ctx.String("config")
fp, err := filepath.Abs(clusterFile) fp, err := filepath.Abs(clusterFile)
@ -27,3 +35,11 @@ func resolveClusterFile(ctx *cli.Context) (string, string, error) {
clusterFileBuff := string(buf) clusterFileBuff := string(buf)
return clusterFileBuff, clusterFile, nil 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
}

View File

@ -34,6 +34,9 @@ func RemoveCommand() cli.Command {
Usage: "Deploy Kubernetes cluster locally", Usage: "Deploy Kubernetes cluster locally",
}, },
} }
removeFlags = append(removeFlags, sshCliOptions...)
return cli.Command{ return cli.Command{
Name: "remove", Name: "remove",
Usage: "Teardown the cluster and clean cluster nodes", Usage: "Teardown the cluster and clean cluster nodes",
@ -96,6 +99,12 @@ func clusterRemoveFromCli(ctx *cli.Context) error {
if err != nil { if err != nil {
return fmt.Errorf("Failed to parse cluster file: %v", err) 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, "") 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.Nodes = []v3.RKEConfigNode{*cluster.GetLocalRKENodeConfig()}
} }
rkeConfig, err = setOptionsFromCLI(ctx, rkeConfig)
if err != nil {
return err
}
return ClusterRemove(context.Background(), rkeConfig, nil, nil, true, "") return ClusterRemove(context.Background(), rkeConfig, nil, nil, true, "")
} }

View File

@ -29,6 +29,9 @@ func UpCommand() cli.Command {
Usage: "Deploy Kubernetes cluster locally", Usage: "Deploy Kubernetes cluster locally",
}, },
} }
upFlags = append(upFlags, sshCliOptions...)
return cli.Command{ return cli.Command{
Name: "up", Name: "up",
Usage: "Bring the cluster up", Usage: "Bring the cluster up",
@ -139,6 +142,12 @@ func clusterUpFromCli(ctx *cli.Context) error {
if err != nil { if err != nil {
return fmt.Errorf("Failed to parse cluster file: %v", err) 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, "") _, _, _, _, err = ClusterUp(context.Background(), rkeConfig, nil, nil, nil, false, "")
return err return err
} }

View File

@ -11,23 +11,25 @@ import (
type DialerFactory func(h *Host) (func(network, address string) (net.Conn, error), error) type DialerFactory func(h *Host) (func(network, address string) (net.Conn, error), error)
type dialer struct { type dialer struct {
signer ssh.Signer signer ssh.Signer
sshKeyString string sshKeyString string
sshAddress string sshAddress string
sshPassphrase []byte sshPassphrase []byte
username string username string
netConn string netConn string
dockerSocket string dockerSocket string
useSSHAgentAuth bool
} }
func newDialer(h *Host, kind string) (*dialer, error) { func newDialer(h *Host, kind string) (*dialer, error) {
dialer := &dialer{ dialer := &dialer{
sshAddress: fmt.Sprintf("%s:%s", h.Address, h.Port), sshAddress: fmt.Sprintf("%s:%s", h.Address, h.Port),
username: h.User, username: h.User,
dockerSocket: h.DockerSocket, dockerSocket: h.DockerSocket,
sshKeyString: h.SSHKey, sshKeyString: h.SSHKey,
netConn: "unix", netConn: "unix",
sshPassphrase: []byte(h.SavedKeyPhrase), sshPassphrase: []byte(h.SavedKeyPhrase),
useSSHAgentAuth: h.SSHAgentAuth,
} }
if dialer.sshKeyString == "" { if dialer.sshKeyString == "" {
@ -84,7 +86,7 @@ func (d *dialer) Dial(network, addr string) (net.Conn, error) {
} }
func (d *dialer) getSSHTunnelConnection() (*ssh.Client, 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 { if err != nil {
return nil, fmt.Errorf("Error configuring SSH: %v", err) return nil, fmt.Errorf("Error configuring SSH: %v", err)
} }

View File

@ -82,22 +82,25 @@ func parsePrivateKeyWithPassPhrase(keyBuff string, passphrase []byte) (ssh.Signe
return ssh.ParsePrivateKeyWithPassphrase([]byte(keyBuff), passphrase) 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{ config := &ssh.ClientConfig{
User: username, User: username,
HostKeyCallback: ssh.InsecureIgnoreHostKey(), HostKeyCallback: ssh.InsecureIgnoreHostKey(),
} }
if sshAgentSock := os.Getenv("SSH_AUTH_SOCK"); sshAgentSock != "" { // Kind of a double check now.
sshAgent, err := net.Dial("unix", sshAgentSock) if useAgentAuth {
if err != nil { if sshAgentSock := os.Getenv("SSH_AUTH_SOCK"); sshAgentSock != "" {
return config, fmt.Errorf("Cannot connect to SSH Auth socket %q: %s", sshAgentSock, err) 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) signer, err := getPrivateKeySigner(sshPrivateKeyString, passphrase)