github.com/technosophos/deis@v1.7.1-0.20150915173815-f9005256004b/builder/sshd/server_test.go (about)

     1  package sshd
     2  
     3  import (
     4  	"net"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/Masterminds/cookoo"
     9  	"golang.org/x/crypto/ssh"
    10  )
    11  
    12  var testingServerAddr = "127.0.0.1:2244"
    13  
    14  // TestServer tests the SSH server.
    15  //
    16  // This listens on the non-standard port 2244 of localhost. This will generate
    17  // an entry in your known_hosts file, and will tie that to the testing key
    18  // used here. It's not recommended that you try to start another SSH server on
    19  // the same port (at a later time) or else you will have key issues that you
    20  // must manually resolve.
    21  func TestServer(t *testing.T) {
    22  	key, err := sshTestingHostKey()
    23  	if err != nil {
    24  		t.Fatal(err)
    25  	}
    26  
    27  	cfg := ssh.ServerConfig{
    28  		NoClientAuth: true,
    29  	}
    30  	cfg.AddHostKey(key)
    31  
    32  	cxt := runServer(&cfg, t)
    33  
    34  	// Give server time to initialize.
    35  	time.Sleep(200 * time.Millisecond)
    36  
    37  	// Connect to the server and issue env var set. This should return true.
    38  	client, err := ssh.Dial("tcp", testingServerAddr, &ssh.ClientConfig{})
    39  	if err != nil {
    40  		t.Fatalf("Failed to connect client to local server: %s", err)
    41  	}
    42  	sess, err := client.NewSession()
    43  	if err != nil {
    44  		t.Fatalf("Failed to create client session: %s", err)
    45  	}
    46  	defer sess.Close()
    47  
    48  	if err := sess.Setenv("HELLO", "world"); err != nil {
    49  		t.Fatal(err)
    50  	}
    51  
    52  	if out, err := sess.Output("ping"); err != nil {
    53  		t.Errorf("Output '%s' Error %s", out, err)
    54  	} else if string(out) != "pong" {
    55  		t.Errorf("Expected 'pong', got '%s'", out)
    56  	}
    57  
    58  	// Create a new session because the success of the last one closed the
    59  	// connection.
    60  	sess, err = client.NewSession()
    61  	if err != nil {
    62  		t.Fatalf("Failed to create client session: %s", err)
    63  	}
    64  	if err := sess.Run("illegal"); err == nil {
    65  		t.Fatalf("expected a failed run with command 'illegal'")
    66  	}
    67  	if err := sess.Run("illegal command"); err == nil {
    68  		t.Fatalf("expected a failed run with command 'illegal command'")
    69  	}
    70  
    71  	closer := cxt.Get("sshd.Closer", nil).(chan interface{})
    72  	closer <- true
    73  }
    74  
    75  // sshTestingHostKey loads the testing key.
    76  func sshTestingHostKey() (ssh.Signer, error) {
    77  	return ssh.ParsePrivateKey([]byte(testingHostKey))
    78  }
    79  
    80  func sshTestingClientKey() (ssh.Signer, error) {
    81  	return ssh.ParsePrivateKey([]byte(testingClientKey))
    82  }
    83  
    84  func runServer(config *ssh.ServerConfig, t *testing.T) cookoo.Context {
    85  	reg, router, cxt := cookoo.Cookoo()
    86  	cxt.Put(ServerConfig, config)
    87  	cxt.Put(Address, testingServerAddr)
    88  	cxt.Put("cookoo.Router", router)
    89  
    90  	reg.AddRoute(cookoo.Route{
    91  		Name: "sshPing",
    92  		Help: "Handles an ssh exec ping.",
    93  		Does: cookoo.Tasks{
    94  			cookoo.Cmd{
    95  				Name: "ping",
    96  				Fn:   Ping,
    97  				Using: []cookoo.Param{
    98  					{Name: "request", From: "cxt:request"},
    99  					{Name: "channel", From: "cxt:channel"},
   100  				},
   101  			},
   102  		},
   103  	})
   104  
   105  	go func() {
   106  		if err := Serve(reg, router, cxt); err != nil {
   107  			t.Fatalf("Failed serving with %s", err)
   108  		}
   109  	}()
   110  
   111  	return cxt
   112  
   113  }
   114  
   115  // connMetadata mocks ssh.ConnMetadata for authentication.
   116  type connMetadata struct{}
   117  
   118  func (cm *connMetadata) User() string          { return "deis" }
   119  func (cm *connMetadata) SessionID() []byte     { return []byte("1") }
   120  func (cm *connMetadata) ClientVersion() []byte { return []byte("2.3.4") }
   121  func (cm *connMetadata) ServerVersion() []byte { return []byte("2.3.4") }
   122  func (cm *connMetadata) RemoteAddr() net.Addr  { return cm.localhost() }
   123  func (cm *connMetadata) LocalAddr() net.Addr   { return cm.localhost() }
   124  func (cm *connMetadata) localhost() net.Addr {
   125  	addrs, err := net.InterfaceAddrs()
   126  	if err != nil {
   127  		panic(err)
   128  	}
   129  	return addrs[0]
   130  }
   131  
   132  var (
   133  	testingHostKey = `-----BEGIN RSA PRIVATE KEY-----
   134  MIIEpAIBAAKCAQEA0xOK/wubqj+e4HNp+yAdK4WJnLZCvcjS2DwaxwF+E968kSeU
   135  27SOqiol7Y0UwLGLpB6rpIBnSqXo70xiMUSrnteKmMejddzfbGkvnyvo0dwE4nDd
   136  vnbz64I25xfjTldb4RtNvpk6ymr0soq0EEYssLmdnt7pIgHT71n9RNtu+RPpRe5n
   137  B2ImVeeEsQBhxFsIkkT21JqBhZQRVpeAAOHwainWpkP2MF2ajYUoirs5qOkPxxaw
   138  Mc4i5CSvmFDkWjqkNt84QH9M9M/ws8qX76nImYOPHiF0KRbxamWsYjvdHJCSckdC
   139  mOM7UtsQs8wC3E0xpuPEI0pNRTHCsgH7+KGxmwIDAQABAoIBAAOQufFS7d8zUeiy
   140  qmCeiz+X8todzgTMppsWcNFZuhp10bOV+pK3ew1uxtM7ZdVXamdsSTPvI0+Ee+nG
   141  3YW9hjSZqXKpNJ6iC3gWUsKaiEU7NS3qACTed4JL4ceHhMRm/1tPDcIhbnfK1LVL
   142  WH1J4ileCUaMt11msIDDgV6vYjF81733O+8kPnh5BaFLIOuPdmAPfsZC2WQfBTka
   143  6F5bhe9mcraQohWOGC/NKBbV9o6Ua2GT5ZJILtyPwfx8ctnQHLfmlTOI7qpRyMCU
   144  1hGwlWxyvZRyY4loZehy0c7DaEWJqWS1AST9AbUcNXciYSt/5pUP76W0L6NzwJdh
   145  C1jIY2ECgYEA+JwlIzhsZRsN0jA3A2qWRt3WGdliujAqDvVj4e8E+QnlTh/MDVKF
   146  x3F+w58DHRKJrH7d1nD1fq2id6vh3Sl7xGHZiztOpolY0xlOt71X+2anX+QTEX5Q
   147  d1jB/zQliUsxzIjqn31dKUlAfoI5XiWrxuP1Py8gZSTnnBl8bkdKZysCgYEA2VnG
   148  +bhBdw/0RJVsleyHBrq0+MnQ80dxj6XatKvniVDqjHQefq088W2ULeI5wVjdMy59
   149  CVnDVS6759pLkWu5br7Agb+NGyVKd3o0CT0Jn6JJj9kq1Wq7iOedJF+GtabVp4gk
   150  efIYECkS7BKe1GFH5vRM8FbyyepRFBCgrH1ep1ECgYEAiRojaO7+6CspThcE379y
   151  LJa+MfcueRuCtkkh0kFsbqLEcHccouQ1nq26iMsyfl/wyM4WLOKSoE/FX1XM85ij
   152  BsQnop8MWs83ywMT5ERpNt1/xGQVF/qfCZJLOiBZ6wMq7W88ZMRQEiqxhJLwbDk+
   153  KCsi3rtwlBbsG6v6cR6jq40CgYAzH4nMvQkw7yC+bQMgdIUCETJ1/kpWnqxYZGN/
   154  8ZtBUjYJGVr+4tKd2u9qp3Z8QuGsozen1mQ6igaKr27s4pC4Osfe/OY8x1Wvqp/I
   155  uIGl+a8h1avcjQFVX1036/wsh/RjNoOV51q/mlmoC20ueT9HVJkwQtNSqPmvJYYV
   156  bFuyMQKBgQCsRVEJ6eqai+Pz4bY2UfBnkU6ZHdySI+fQB/T770p0/SbrYMBxNrPQ
   157  v3+ZZfZMlci4pxBtXqrnoyj4uUoqZtR3ENLz53SN1i0vpT7DtC6gMnEF1UWiaoJ6
   158  6mGH5/bxCg9wpV7qpqR0EbFM/dhQFZmmnirOS8x+00hJvc1HFiuN/A==
   159  -----END RSA PRIVATE KEY-----
   160  `
   161  	testingClientKey = `-----BEGIN RSA PRIVATE KEY-----
   162  MIIEowIBAAKCAQEAvziJnoiaaVyUGPnyqVC49XLzNRS+TPW63Nw4qovCG8lVbxKG
   163  DIHC64tJrCDiZd0ppEhY+RQDGaPwrMInHnV8IwdS1wX22UTRuXA/oXmHcIxO2zmU
   164  nrjFDlpKm2o+2Xd167ifdV9AiqNBtquO0M882RaGy99LbNPcl9ugAnxo5DVI1jES
   165  l5vYqtiOAnRSvmJn2c+hkJfKXryH7hU4y+blDK5Vz44eSsC7bgG3ZbKfKGR9mlf2
   166  ozVlzMNi2ACZ58vDBxn5WVLb1bPV1LHpicJ00fU3TDRnK3MkwvvAnqp78bNzi+ou
   167  YIAwYSZ41iHNd596LQJchr1vs3Fo8qbgYaLY8wIDAQABAoIBAEJgQL0ME/Vw0mOd
   168  F5OYVqu0vCF30trqDXQu6Wih3L5Cc+p7Vpau0Fds4STjwVK0o4jIKEJFpRHYa2m8
   169  d1HGXFHYb/P9uQMQNXCWOzA0/EOgIJtOcH1sC9MAmpc6GRjps8AgNRHL/55gLyZW
   170  hNuMpEWC4UWRfCAJpq/7554VS1+zWK0vy1GszikROjsZnopLTshMV+/7217tSk4O
   171  1GY9ucNJX5iX3M83pmBOJX0ce8fqxeNnAdQIaAtp+ytm5TRzyaQtTjMlq0oqP8+7
   172  Zx9aZKT11IpbOKBSIc6twRArlV1dT9kEI15zS9hfbWuvguB0zuhbhejS4wmZb9Tt
   173  X8rGL4ECgYEA+MZcRzxpBKL+VNuQ4iSwF3RUYL1FIglJV7AM8UdM2hiNeiKidhD5
   174  kmNXVf9C6XWg3OIHCno7HetBo0WZIPmOQMy4CDGC2bWEnQN+/bf3xsKzbECCLtH+
   175  DALXSztihGGiY2zSoOCwTe7WZjGaF9s4C2rVkhsU/9di4qbapGTaWMECgYEAxMZD
   176  c/sVTTT+/thdcLbBDhAfy6RMQwAy/1IPxNVR4C4O+l/rspbKxvV7JyaErP66g871
   177  dBwrOGMfEsYoOOsUBFaj2/jJZdHvQj9jY/kdsfMBivHzkWEFte09NROOThbq+sgX
   178  5bIPwS+IcVCgcA4We+aBv+rYKdvk05RJ8owPSrMCgYBjz4H6erxPxe1wsl8gvEOC
   179  RYQNBCMWks9ARTwMGeU1o6AvnnG8GPdoyj6iHDYGYNFXjb/xbjUFvfupvCTB3B48
   180  1WYIs4SiQHeiX2K1/PeGYVuHVSJmEo5w1zr1zi+qmVmDtoeTUFKsEeUnP0NpyuRj
   181  gEuLwR3dv9bGxNb4GhaYgQKBgDNQCFL8TMe/ZCeMwIEeByXlqoTuKTznlmTiP15y
   182  ylENcbZ0wP/nNqW/aggBkWOTYYvxsiw/FD42CupYZjDBjIy9EynPrKUyo5PA9+gg
   183  FFBNMD/NbFii1lxkqytmGBvg+hG/kAvD7TvRa2ExR0UxR0e0Cm3Dje8MepV5+/aV
   184  837lAoGBAPcvnrDFWKUy8dlrw05+9esiuZgCrCzZPw5xIxhrnRPcBOBl+QdpMscP
   185  eWVutcVy5Frxl5tTf71WK/YhGPgWBt/CQz73Bf1+CX80CeApWWAqiAr240NED5a0
   186  dBAFNBWp8IdHnQmdp9HKvxEXSK+RgOzPNLrpaRv+FPuiD6OtvhmD
   187  -----END RSA PRIVATE KEY-----`
   188  
   189  	testingClientPubKey      = `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/OImeiJppXJQY+fKpULj1cvM1FL5M9brc3Diqi8IbyVVvEoYMgcLri0msIOJl3SmkSFj5FAMZo/CswicedXwjB1LXBfbZRNG5cD+heYdwjE7bOZSeuMUOWkqbaj7Zd3XruJ91X0CKo0G2q47QzzzZFobL30ts09yX26ACfGjkNUjWMRKXm9iq2I4CdFK+YmfZz6GQl8pevIfuFTjL5uUMrlXPjh5KwLtuAbdlsp8oZH2aV/ajNWXMw2LYAJnny8MHGflZUtvVs9XUsemJwnTR9TdMNGcrcyTC+8Ceqnvxs3OL6i5ggDBhJnjWIc13n3otAlyGvW+zcWjypuBhotjz donotuse`
   190  	testingClientFingerprint = `78:b9:21:20:1a:ed:e6:10:05:35:47:da:d4:1f:b6:73`
   191  )