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 }