github.com/alexissmirnov/terraform@v0.4.3-0.20150423153700-1ef9731a2f14/helper/ssh/communicator_test.go (about)

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