Skip to content

Commit

Permalink
Add option to add the ssh-host key to known_hosts
Browse files Browse the repository at this point in the history
This matches the ssh-add command for identity keys,
it will add the host key to the ssh known_hosts file.

If a ssh key for the host already exists in the file,
it will not be added again so can be run multiple times.
  • Loading branch information
afbjorklund committed Dec 12, 2020
1 parent 29bb918 commit ce40816
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 11 deletions.
42 changes: 42 additions & 0 deletions cmd/minikube/cmd/ssh-host.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ package cmd
import (
"fmt"
"os"
"path/filepath"

"github.com/spf13/cobra"
"k8s.io/client-go/util/homedir"

"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/driver"
Expand All @@ -30,6 +32,11 @@ import (
"k8s.io/minikube/pkg/minikube/node"
"k8s.io/minikube/pkg/minikube/out"
"k8s.io/minikube/pkg/minikube/reason"
"k8s.io/minikube/pkg/minikube/sshutil"
)

var (
appendKnown bool
)

// sshHostCmd represents the sshHostCmd command
Expand Down Expand Up @@ -65,10 +72,45 @@ var sshHostCmd = &cobra.Command{
os.Exit(1)
}

if appendKnown {
addr, port, err := machine.GetSSHHostAddrPort(co.API, *co.Config, *n)
if err != nil {
out.ErrLn("GetSSHHostAddrPort: %v", err)
os.Exit(1)
}

host := addr
if port != 22 {
host = fmt.Sprintf("[%s]:%d", addr, port)
}
knownHosts := filepath.Join(homedir.HomeDir(), ".ssh", "known_hosts")

fmt.Fprintf(os.Stderr, "Host added: %s (%s)\n", knownHosts, host)
if sshutil.KnownHost(host, knownHosts) {
return
}

f, err := os.OpenFile(knownHosts, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
out.ErrLn("OpenFile: %v", err)
os.Exit(1)
}
defer f.Close()

_, err = f.WriteString(keys)
if err != nil {
out.ErrLn("WriteString: %v", err)
os.Exit(1)
}

return
}

fmt.Printf("%s", keys)
},
}

func init() {
sshHostCmd.Flags().StringVarP(&nodeName, "node", "n", "", "The node to ssh into. Defaults to the primary control plane.")
sshHostCmd.Flags().BoolVar(&appendKnown, "append-known", false, "Add host key to SSH known_hosts file")
}
28 changes: 18 additions & 10 deletions pkg/minikube/machine/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,31 +69,39 @@ func CreateSSHShell(api libmachine.API, cc config.ClusterConfig, n config.Node,
return client.Shell(args...)
}

// RunSSHHostCommand runs a command to the SSH host
func RunSSHHostCommand(api libmachine.API, cc config.ClusterConfig, n config.Node, command string, args []string) (string, error) {
func GetSSHHostAddrPort(api libmachine.API, cc config.ClusterConfig, n config.Node) (string, int, error) {
host, err := getHost(api, cc, n)
if err != nil {
return "", err
return "", 0, err
}

cmdPath, err := exec.LookPath(command)
addr, err := host.Driver.GetSSHHostname()
if err != nil {
return "", err
return "", 0, err
}

port, err := host.Driver.GetSSHPort()
if err != nil {
return "", err
return "", 0, err
}

args = append(args, "-p")
args = append(args, fmt.Sprintf("%d", port))
return addr, port, nil
}

addr, err := host.Driver.GetSSHHostname()
// RunSSHHostCommand runs a command to the SSH host
func RunSSHHostCommand(api libmachine.API, cc config.ClusterConfig, n config.Node, command string, args []string) (string, error) {
addr, port, err := GetSSHHostAddrPort(api, cc, n)
if err != nil {
return "", err
}

cmdPath, err := exec.LookPath(command)
if err != nil {
return "", err
}

args = append(args, "-p")
args = append(args, fmt.Sprintf("%d", port))

args = append(args, addr)

cmd := exec.Command(cmdPath, args...)
Expand Down
28 changes: 28 additions & 0 deletions pkg/minikube/sshutil/sshutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@ limitations under the License.
package sshutil

import (
"bufio"
"net"
"os"
"strconv"
"time"

"github.com/docker/machine/libmachine/drivers"
machinessh "github.com/docker/machine/libmachine/ssh"
"github.com/pkg/errors"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/knownhosts"
"k8s.io/klog/v2"

"k8s.io/minikube/pkg/util/retry"
Expand Down Expand Up @@ -89,3 +92,28 @@ func newSSHHost(d drivers.Driver) (*sshHost, error) {
Username: d.GetSSHUsername(),
}, nil
}

func KnownHost(host string, knownHosts string) bool {
fd, err := os.Open(knownHosts)
if err != nil {
return false
}
defer fd.Close()

hashhost := knownhosts.HashHostname(host)
scanner := bufio.NewScanner(fd)
for scanner.Scan() {
_, hosts, _, _, _, err := ssh.ParseKnownHosts(scanner.Bytes())
if err != nil {
continue
}

for _, h := range hosts {
if h == host || h == hashhost {
return true
}
}
}

return false
}
3 changes: 2 additions & 1 deletion site/content/en/docs/commands/ssh-host.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ minikube ssh-host [flags]
### Options

```
-n, --node string The node to ssh into. Defaults to the primary control plane.
--append-known Add host key to SSH known_hosts file
-n, --node string The node to ssh into. Defaults to the primary control plane.
```

### Options inherited from parent commands
Expand Down

0 comments on commit ce40816

Please sign in to comment.