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