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