github.com/diptanu/nomad@v0.5.7-0.20170516172507-d72e86cbe3d9/helper/tlsutil/config_test.go (about) 1 package tlsutil 2 3 import ( 4 "crypto/tls" 5 "crypto/x509" 6 "io" 7 "io/ioutil" 8 "net" 9 "testing" 10 11 "github.com/hashicorp/yamux" 12 ) 13 14 const ( 15 // See README.md for documentation 16 cacert = "./testdata/ca.pem" 17 foocert = "./testdata/nomad-foo.pem" 18 fookey = "./testdata/nomad-foo-key.pem" 19 badcert = "./testdata/nomad-bad.pem" 20 badkey = "./testdata/nomad-bad-key.pem" 21 ) 22 23 func TestConfig_AppendCA_None(t *testing.T) { 24 conf := &Config{} 25 pool := x509.NewCertPool() 26 err := conf.AppendCA(pool) 27 if err != nil { 28 t.Fatalf("err: %v", err) 29 } 30 if len(pool.Subjects()) != 0 { 31 t.Fatalf("bad: %v", pool.Subjects()) 32 } 33 } 34 35 func TestConfig_CACertificate_Valid(t *testing.T) { 36 conf := &Config{ 37 CAFile: cacert, 38 } 39 pool := x509.NewCertPool() 40 err := conf.AppendCA(pool) 41 if err != nil { 42 t.Fatalf("err: %v", err) 43 } 44 if len(pool.Subjects()) == 0 { 45 t.Fatalf("expected cert") 46 } 47 } 48 49 func TestConfig_KeyPair_None(t *testing.T) { 50 conf := &Config{} 51 cert, err := conf.KeyPair() 52 if err != nil { 53 t.Fatalf("err: %v", err) 54 } 55 if cert != nil { 56 t.Fatalf("bad: %v", cert) 57 } 58 } 59 60 func TestConfig_KeyPair_Valid(t *testing.T) { 61 conf := &Config{ 62 CertFile: foocert, 63 KeyFile: fookey, 64 } 65 cert, err := conf.KeyPair() 66 if err != nil { 67 t.Fatalf("err: %v", err) 68 } 69 if cert == nil { 70 t.Fatalf("expected cert") 71 } 72 } 73 74 func TestConfig_OutgoingTLS_MissingCA(t *testing.T) { 75 conf := &Config{ 76 VerifyOutgoing: true, 77 } 78 tls, err := conf.OutgoingTLSConfig() 79 if err == nil { 80 t.Fatalf("expected err") 81 } 82 if tls != nil { 83 t.Fatalf("bad: %v", tls) 84 } 85 } 86 87 func TestConfig_OutgoingTLS_OnlyCA(t *testing.T) { 88 conf := &Config{ 89 CAFile: cacert, 90 } 91 tls, err := conf.OutgoingTLSConfig() 92 if err != nil { 93 t.Fatalf("err: %v", err) 94 } 95 if tls != nil { 96 t.Fatalf("expected no config") 97 } 98 } 99 100 func TestConfig_OutgoingTLS_VerifyOutgoing(t *testing.T) { 101 conf := &Config{ 102 VerifyOutgoing: true, 103 CAFile: cacert, 104 } 105 tls, err := conf.OutgoingTLSConfig() 106 if err != nil { 107 t.Fatalf("err: %v", err) 108 } 109 if tls == nil { 110 t.Fatalf("expected config") 111 } 112 if len(tls.RootCAs.Subjects()) != 1 { 113 t.Fatalf("expect root cert") 114 } 115 if !tls.InsecureSkipVerify { 116 t.Fatalf("should skip built-in verification") 117 } 118 } 119 120 func TestConfig_OutgoingTLS_VerifyHostname(t *testing.T) { 121 conf := &Config{ 122 VerifyServerHostname: true, 123 CAFile: cacert, 124 } 125 tls, err := conf.OutgoingTLSConfig() 126 if err != nil { 127 t.Fatalf("err: %v", err) 128 } 129 if tls == nil { 130 t.Fatalf("expected config") 131 } 132 if len(tls.RootCAs.Subjects()) != 1 { 133 t.Fatalf("expect root cert") 134 } 135 if tls.InsecureSkipVerify { 136 t.Fatalf("should not skip built-in verification") 137 } 138 } 139 140 func TestConfig_OutgoingTLS_WithKeyPair(t *testing.T) { 141 conf := &Config{ 142 VerifyOutgoing: true, 143 CAFile: cacert, 144 CertFile: foocert, 145 KeyFile: fookey, 146 } 147 tls, err := conf.OutgoingTLSConfig() 148 if err != nil { 149 t.Fatalf("err: %v", err) 150 } 151 if tls == nil { 152 t.Fatalf("expected config") 153 } 154 if len(tls.RootCAs.Subjects()) != 1 { 155 t.Fatalf("expect root cert") 156 } 157 if !tls.InsecureSkipVerify { 158 t.Fatalf("should skip verification") 159 } 160 if len(tls.Certificates) != 1 { 161 t.Fatalf("expected client cert") 162 } 163 } 164 165 func startTLSServer(config *Config) (net.Conn, chan error) { 166 errc := make(chan error, 1) 167 168 tlsConfigServer, err := config.IncomingTLSConfig() 169 if err != nil { 170 errc <- err 171 return nil, errc 172 } 173 174 client, server := net.Pipe() 175 176 // Use yamux to buffer the reads, otherwise it's easy to deadlock 177 muxConf := yamux.DefaultConfig() 178 serverSession, _ := yamux.Server(server, muxConf) 179 clientSession, _ := yamux.Client(client, muxConf) 180 clientConn, _ := clientSession.Open() 181 serverConn, _ := serverSession.Accept() 182 183 go func() { 184 tlsServer := tls.Server(serverConn, tlsConfigServer) 185 if err := tlsServer.Handshake(); err != nil { 186 errc <- err 187 } 188 close(errc) 189 // Because net.Pipe() is unbuffered, if both sides 190 // Close() simultaneously, we will deadlock as they 191 // both send an alert and then block. So we make the 192 // server read any data from the client until error or 193 // EOF, which will allow the client to Close(), and 194 // *then* we Close() the server. 195 io.Copy(ioutil.Discard, tlsServer) 196 tlsServer.Close() 197 }() 198 return clientConn, errc 199 } 200 201 // TODO sign the certificates for "server.regionFoo.nomad 202 func TestConfig_outgoingWrapper_OK(t *testing.T) { 203 config := &Config{ 204 CAFile: cacert, 205 CertFile: foocert, 206 KeyFile: fookey, 207 VerifyServerHostname: true, 208 VerifyOutgoing: true, 209 } 210 211 client, errc := startTLSServer(config) 212 if client == nil { 213 t.Fatalf("startTLSServer err: %v", <-errc) 214 } 215 216 wrap, err := config.OutgoingTLSWrapper() 217 if err != nil { 218 t.Fatalf("OutgoingTLSWrapper err: %v", err) 219 } 220 221 tlsClient, err := wrap("regionFoo", client) 222 if err != nil { 223 t.Fatalf("wrapTLS err: %v", err) 224 } 225 defer tlsClient.Close() 226 if err := tlsClient.(*tls.Conn).Handshake(); err != nil { 227 t.Fatalf("write err: %v", err) 228 } 229 230 err = <-errc 231 if err != nil { 232 t.Fatalf("server: %v", err) 233 } 234 } 235 236 func TestConfig_outgoingWrapper_BadCert(t *testing.T) { 237 // TODO this test is currently hanging, need to investigate more. 238 t.SkipNow() 239 config := &Config{ 240 CAFile: cacert, 241 CertFile: foocert, 242 KeyFile: fookey, 243 VerifyServerHostname: true, 244 VerifyOutgoing: true, 245 } 246 247 client, errc := startTLSServer(config) 248 if client == nil { 249 t.Fatalf("startTLSServer err: %v", <-errc) 250 } 251 252 wrap, err := config.OutgoingTLSWrapper() 253 if err != nil { 254 t.Fatalf("OutgoingTLSWrapper err: %v", err) 255 } 256 257 tlsClient, err := wrap("regionFoo", client) 258 if err != nil { 259 t.Fatalf("wrapTLS err: %v", err) 260 } 261 defer tlsClient.Close() 262 err = tlsClient.(*tls.Conn).Handshake() 263 264 if _, ok := err.(x509.HostnameError); !ok { 265 t.Fatalf("should get hostname err: %v", err) 266 } 267 268 <-errc 269 } 270 271 func TestConfig_wrapTLS_OK(t *testing.T) { 272 config := &Config{ 273 CAFile: cacert, 274 CertFile: foocert, 275 KeyFile: fookey, 276 VerifyOutgoing: true, 277 } 278 279 client, errc := startTLSServer(config) 280 if client == nil { 281 t.Fatalf("startTLSServer err: %v", <-errc) 282 } 283 284 clientConfig, err := config.OutgoingTLSConfig() 285 if err != nil { 286 t.Fatalf("OutgoingTLSConfig err: %v", err) 287 } 288 289 tlsClient, err := WrapTLSClient(client, clientConfig) 290 if err != nil { 291 t.Fatalf("wrapTLS err: %v", err) 292 } else { 293 tlsClient.Close() 294 } 295 err = <-errc 296 if err != nil { 297 t.Fatalf("server: %v", err) 298 } 299 } 300 301 func TestConfig_wrapTLS_BadCert(t *testing.T) { 302 serverConfig := &Config{ 303 CAFile: cacert, 304 CertFile: badcert, 305 KeyFile: badkey, 306 } 307 308 client, errc := startTLSServer(serverConfig) 309 if client == nil { 310 t.Fatalf("startTLSServer err: %v", <-errc) 311 } 312 313 clientConfig := &Config{ 314 CAFile: cacert, 315 VerifyOutgoing: true, 316 } 317 318 clientTLSConfig, err := clientConfig.OutgoingTLSConfig() 319 if err != nil { 320 t.Fatalf("OutgoingTLSConfig err: %v", err) 321 } 322 323 tlsClient, err := WrapTLSClient(client, clientTLSConfig) 324 if err == nil { 325 t.Fatalf("wrapTLS no err") 326 } 327 if tlsClient != nil { 328 t.Fatalf("returned a client") 329 } 330 331 err = <-errc 332 if err != nil { 333 t.Fatalf("server: %v", err) 334 } 335 } 336 337 func TestConfig_IncomingTLS(t *testing.T) { 338 conf := &Config{ 339 VerifyIncoming: true, 340 CAFile: cacert, 341 CertFile: foocert, 342 KeyFile: fookey, 343 } 344 tlsC, err := conf.IncomingTLSConfig() 345 if err != nil { 346 t.Fatalf("err: %v", err) 347 } 348 if tlsC == nil { 349 t.Fatalf("expected config") 350 } 351 if len(tlsC.ClientCAs.Subjects()) != 1 { 352 t.Fatalf("expect client cert") 353 } 354 if tlsC.ClientAuth != tls.RequireAndVerifyClientCert { 355 t.Fatalf("should not skip verification") 356 } 357 if len(tlsC.Certificates) != 1 { 358 t.Fatalf("expected client cert") 359 } 360 } 361 362 func TestConfig_IncomingTLS_MissingCA(t *testing.T) { 363 conf := &Config{ 364 VerifyIncoming: true, 365 CertFile: foocert, 366 KeyFile: fookey, 367 } 368 _, err := conf.IncomingTLSConfig() 369 if err == nil { 370 t.Fatalf("expected err") 371 } 372 } 373 374 func TestConfig_IncomingTLS_MissingKey(t *testing.T) { 375 conf := &Config{ 376 VerifyIncoming: true, 377 CAFile: cacert, 378 } 379 _, err := conf.IncomingTLSConfig() 380 if err == nil { 381 t.Fatalf("expected err") 382 } 383 } 384 385 func TestConfig_IncomingTLS_NoVerify(t *testing.T) { 386 conf := &Config{} 387 tlsC, err := conf.IncomingTLSConfig() 388 if err != nil { 389 t.Fatalf("err: %v", err) 390 } 391 if tlsC == nil { 392 t.Fatalf("expected config") 393 } 394 if len(tlsC.ClientCAs.Subjects()) != 0 { 395 t.Fatalf("do not expect client cert") 396 } 397 if tlsC.ClientAuth != tls.NoClientCert { 398 t.Fatalf("should skip verification") 399 } 400 if len(tlsC.Certificates) != 0 { 401 t.Fatalf("unexpected client cert") 402 } 403 }