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  }