github.com/adamar/terraform@v0.2.2-0.20141016210445-2e703afdad0e/helper/ssh/communicator_test.go (about)

     1  // +build !race
     2  
     3  package ssh
     4  
     5  import (
     6  	"bytes"
     7  	"code.google.com/p/go.crypto/ssh"
     8  	"fmt"
     9  	"net"
    10  	"testing"
    11  )
    12  
    13  // private key for mock server
    14  const testServerPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
    15  MIIEpAIBAAKCAQEA19lGVsTqIT5iiNYRgnoY1CwkbETW5cq+Rzk5v/kTlf31XpSU
    16  70HVWkbTERECjaYdXM2gGcbb+sxpq6GtXf1M3kVomycqhxwhPv4Cr6Xp4WT/jkFx
    17  9z+FFzpeodGJWjOH6L2H5uX1Cvr9EDdQp9t9/J32/qBFntY8GwoUI/y/1MSTmMiF
    18  tupdMODN064vd3gyMKTwrlQ8tZM6aYuyOPsutLlUY7M5x5FwMDYvnPDSeyT/Iw0z
    19  s3B+NCyqeeMd2T7YzQFnRATj0M7rM5LoSs7DVqVriOEABssFyLj31PboaoLhOKgc
    20  qoM9khkNzr7FHVvi+DhYM2jD0DwvqZLN6NmnLwIDAQABAoIBAQCGVj+kuSFOV1lT
    21  +IclQYA6bM6uY5mroqcSBNegVxCNhWU03BxlW//BE9tA/+kq53vWylMeN9mpGZea
    22  riEMIh25KFGWXqXlOOioH8bkMsqA8S7sBmc7jljyv+0toQ9vCCtJ+sueNPhxQQxH
    23  D2YvUjfzBQ04I9+wn30BByDJ1QA/FoPsunxIOUCcRBE/7jxuLYcpR+JvEF68yYIh
    24  atXRld4W4in7T65YDR8jK1Uj9XAcNeDYNpT/M6oFLx1aPIlkG86aCWRO19S1jLPT
    25  b1ZAKHHxPMCVkSYW0RqvIgLXQOR62D0Zne6/2wtzJkk5UCjkSQ2z7ZzJpMkWgDgN
    26  ifCULFPBAoGBAPoMZ5q1w+zB+knXUD33n1J+niN6TZHJulpf2w5zsW+m2K6Zn62M
    27  MXndXlVAHtk6p02q9kxHdgov34Uo8VpuNjbS1+abGFTI8NZgFo+bsDxJdItemwC4
    28  KJ7L1iz39hRN/ZylMRLz5uTYRGddCkeIHhiG2h7zohH/MaYzUacXEEy3AoGBANz8
    29  e/msleB+iXC0cXKwds26N4hyMdAFE5qAqJXvV3S2W8JZnmU+sS7vPAWMYPlERPk1
    30  D8Q2eXqdPIkAWBhrx4RxD7rNc5qFNcQWEhCIxC9fccluH1y5g2M+4jpMX2CT8Uv+
    31  3z+NoJ5uDTXZTnLCfoZzgZ4nCZVZ+6iU5U1+YXFJAoGBANLPpIV920n/nJmmquMj
    32  orI1R/QXR9Cy56cMC65agezlGOfTYxk5Cfl5Ve+/2IJCfgzwJyjWUsFx7RviEeGw
    33  64o7JoUom1HX+5xxdHPsyZ96OoTJ5RqtKKoApnhRMamau0fWydH1yeOEJd+TRHhc
    34  XStGfhz8QNa1dVFvENczja1vAoGABGWhsd4VPVpHMc7lUvrf4kgKQtTC2PjA4xoc
    35  QJ96hf/642sVE76jl+N6tkGMzGjnVm4P2j+bOy1VvwQavKGoXqJBRd5Apppv727g
    36  /SM7hBXKFc/zH80xKBBgP/i1DR7kdjakCoeu4ngeGywvu2jTS6mQsqzkK+yWbUxJ
    37  I7mYBsECgYB/KNXlTEpXtz/kwWCHFSYA8U74l7zZbVD8ul0e56JDK+lLcJ0tJffk
    38  gqnBycHj6AhEycjda75cs+0zybZvN4x65KZHOGW/O/7OAWEcZP5TPb3zf9ned3Hl
    39  NsZoFj52ponUM6+99A2CmezFCN16c4mbA//luWF+k3VVqR6BpkrhKw==
    40  -----END RSA PRIVATE KEY-----`
    41  
    42  var serverConfig = &ssh.ServerConfig{
    43  	PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
    44  		if c.User() == "user" && string(pass) == "pass" {
    45  			return nil, nil
    46  		}
    47  		return nil, fmt.Errorf("password rejected for %q", c.User())
    48  	},
    49  }
    50  
    51  func init() {
    52  	// Parse and set the private key of the server, required to accept connections
    53  	signer, err := ssh.ParsePrivateKey([]byte(testServerPrivateKey))
    54  	if err != nil {
    55  		panic("unable to parse private key: " + err.Error())
    56  	}
    57  	serverConfig.AddHostKey(signer)
    58  }
    59  
    60  func newMockLineServer(t *testing.T) string {
    61  	l, err := net.Listen("tcp", "127.0.0.1:0")
    62  	if err != nil {
    63  		t.Fatalf("Unable to listen for connection: %s", err)
    64  	}
    65  
    66  	go func() {
    67  		defer l.Close()
    68  		c, err := l.Accept()
    69  		if err != nil {
    70  			t.Errorf("Unable to accept incoming connection: %s", err)
    71  		}
    72  		defer c.Close()
    73  		conn, chans, _, err := ssh.NewServerConn(c, serverConfig)
    74  		if err != nil {
    75  			t.Logf("Handshaking error: %v", err)
    76  		}
    77  		t.Log("Accepted SSH connection")
    78  		for newChannel := range chans {
    79  			channel, _, err := newChannel.Accept()
    80  			if err != nil {
    81  				t.Errorf("Unable to accept channel.")
    82  			}
    83  			t.Log("Accepted channel")
    84  
    85  			go func(newChannel ssh.NewChannel) {
    86  				defer channel.Close()
    87  				conn.OpenChannel(newChannel.ChannelType(), nil)
    88  			}(newChannel)
    89  		}
    90  		conn.Close()
    91  	}()
    92  
    93  	return l.Addr().String()
    94  }
    95  
    96  func TestNew_Invalid(t *testing.T) {
    97  	clientConfig := &ssh.ClientConfig{
    98  		User: "user",
    99  		Auth: []ssh.AuthMethod{
   100  			ssh.Password("i-am-invalid"),
   101  		},
   102  	}
   103  
   104  	address := newMockLineServer(t)
   105  	conn := func() (net.Conn, error) {
   106  		conn, err := net.Dial("tcp", address)
   107  		if err != nil {
   108  			t.Errorf("Unable to accept incoming connection: %v", err)
   109  		}
   110  		return conn, err
   111  	}
   112  
   113  	config := &Config{
   114  		Connection: conn,
   115  		SSHConfig:  clientConfig,
   116  	}
   117  
   118  	_, err := New(address, config)
   119  	if err == nil {
   120  		t.Fatal("should have had an error connecting")
   121  	}
   122  }
   123  
   124  func TestStart(t *testing.T) {
   125  	clientConfig := &ssh.ClientConfig{
   126  		User: "user",
   127  		Auth: []ssh.AuthMethod{
   128  			ssh.Password("pass"),
   129  		},
   130  	}
   131  
   132  	address := newMockLineServer(t)
   133  	conn := func() (net.Conn, error) {
   134  		conn, err := net.Dial("tcp", address)
   135  		if err != nil {
   136  			t.Fatalf("unable to dial to remote side: %s", err)
   137  		}
   138  		return conn, err
   139  	}
   140  
   141  	config := &Config{
   142  		Connection: conn,
   143  		SSHConfig:  clientConfig,
   144  	}
   145  
   146  	client, err := New(address, config)
   147  	if err != nil {
   148  		t.Fatalf("error connecting to SSH: %s", err)
   149  	}
   150  
   151  	var cmd RemoteCmd
   152  	stdout := new(bytes.Buffer)
   153  	cmd.Command = "echo foo"
   154  	cmd.Stdout = stdout
   155  
   156  	client.Start(&cmd)
   157  }