14287: Refactor controller to use strong types in API handlers.
[arvados.git] / lib / dispatchcloud / ssh_executor / executor_test.go
index 526840b137c776529ec23ba2fc0710b1e6581ef4..e7c023586b4bb3c09ac8968c35c2cc3f1ed01ee2 100644 (file)
@@ -6,6 +6,7 @@ package ssh_executor
 
 import (
        "bytes"
+       "fmt"
        "io"
        "io/ioutil"
        "net"
@@ -52,15 +53,50 @@ func (tt *testTarget) Port() string {
        return p
 }
 
+type mitmTarget struct {
+       test.SSHService
+}
+
+func (*mitmTarget) VerifyHostKey(key ssh.PublicKey, client *ssh.Client) error {
+       return fmt.Errorf("host key failed verification: %#v", key)
+}
+
 type ExecutorSuite struct{}
 
+func (s *ExecutorSuite) TestBadHostKey(c *check.C) {
+       _, hostpriv := test.LoadTestKey(c, "../test/sshkey_vm")
+       clientpub, clientpriv := test.LoadTestKey(c, "../test/sshkey_dispatch")
+       target := &mitmTarget{
+               SSHService: test.SSHService{
+                       Exec: func(map[string]string, string, io.Reader, io.Writer, io.Writer) uint32 {
+                               c.Error("Target Exec func called even though host key verification failed")
+                               return 0
+                       },
+                       HostKey:        hostpriv,
+                       AuthorizedUser: "username",
+                       AuthorizedKeys: []ssh.PublicKey{clientpub},
+               },
+       }
+
+       err := target.Start()
+       c.Check(err, check.IsNil)
+       c.Logf("target address %q", target.Address())
+       defer target.Close()
+
+       exr := New(target)
+       exr.SetSigners(clientpriv)
+
+       _, _, err = exr.Execute(nil, "true", nil)
+       c.Check(err, check.ErrorMatches, "host key failed verification: .*")
+}
+
 func (s *ExecutorSuite) TestExecute(c *check.C) {
        command := `foo 'bar' "baz"`
        stdinData := "foobar\nbaz\n"
        _, hostpriv := test.LoadTestKey(c, "../test/sshkey_vm")
        clientpub, clientpriv := test.LoadTestKey(c, "../test/sshkey_dispatch")
        for _, exitcode := range []int{0, 1, 2} {
-               srv := &testTarget{
+               target := &testTarget{
                        SSHService: test.SSHService{
                                Exec: func(env map[string]string, cmd string, stdin io.Reader, stdout, stderr io.Writer) uint32 {
                                        c.Check(env["TESTVAR"], check.Equals, "test value")
@@ -86,15 +122,16 @@ func (s *ExecutorSuite) TestExecute(c *check.C) {
                                        return uint32(exitcode)
                                },
                                HostKey:        hostpriv,
+                               AuthorizedUser: "username",
                                AuthorizedKeys: []ssh.PublicKey{clientpub},
                        },
                }
-               err := srv.Start()
+               err := target.Start()
                c.Check(err, check.IsNil)
-               c.Logf("srv address %q", srv.Address())
-               defer srv.Close()
+               c.Logf("target address %q", target.Address())
+               defer target.Close()
 
-               exr := New(srv)
+               exr := New(target)
                exr.SetSigners(clientpriv)
 
                // Use the default target port (ssh). Execute will
@@ -111,7 +148,7 @@ func (s *ExecutorSuite) TestExecute(c *check.C) {
                c.Check(err, check.ErrorMatches, `.*connection refused.*`)
 
                // Use the test server's listening port.
-               exr.SetTargetPort(srv.Port())
+               exr.SetTargetPort(target.Port())
 
                done := make(chan bool)
                go func() {