github.com/outbrain/consul@v1.4.5/tlsutil/config_test.go (about)

     1  package tlsutil
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/tls"
     6  	"crypto/x509"
     7  	"fmt"
     8  	"io"
     9  	"io/ioutil"
    10  	"log"
    11  	"net"
    12  	"reflect"
    13  	"strings"
    14  	"testing"
    15  
    16  	"github.com/hashicorp/yamux"
    17  	"github.com/stretchr/testify/require"
    18  )
    19  
    20  func startTLSServer(config *Config) (net.Conn, chan error) {
    21  	errc := make(chan error, 1)
    22  
    23  	c, err := NewConfigurator(*config, nil)
    24  	if err != nil {
    25  		errc <- err
    26  		return nil, errc
    27  	}
    28  	tlsConfigServer := c.IncomingRPCConfig()
    29  	client, server := net.Pipe()
    30  
    31  	// Use yamux to buffer the reads, otherwise it's easy to deadlock
    32  	muxConf := yamux.DefaultConfig()
    33  	serverSession, _ := yamux.Server(server, muxConf)
    34  	clientSession, _ := yamux.Client(client, muxConf)
    35  	clientConn, _ := clientSession.Open()
    36  	serverConn, _ := serverSession.Accept()
    37  
    38  	go func() {
    39  		tlsServer := tls.Server(serverConn, tlsConfigServer)
    40  		if err := tlsServer.Handshake(); err != nil {
    41  			errc <- err
    42  		}
    43  		close(errc)
    44  
    45  		// Because net.Pipe() is unbuffered, if both sides
    46  		// Close() simultaneously, we will deadlock as they
    47  		// both send an alert and then block. So we make the
    48  		// server read any data from the client until error or
    49  		// EOF, which will allow the client to Close(), and
    50  		// *then* we Close() the server.
    51  		io.Copy(ioutil.Discard, tlsServer)
    52  		tlsServer.Close()
    53  	}()
    54  	return clientConn, errc
    55  }
    56  
    57  func TestConfigurator_outgoingWrapper_OK(t *testing.T) {
    58  	config := Config{
    59  		CAFile:               "../test/hostname/CertAuth.crt",
    60  		CertFile:             "../test/hostname/Alice.crt",
    61  		KeyFile:              "../test/hostname/Alice.key",
    62  		VerifyServerHostname: true,
    63  		VerifyOutgoing:       true,
    64  		Domain:               "consul",
    65  	}
    66  
    67  	client, errc := startTLSServer(&config)
    68  	if client == nil {
    69  		t.Fatalf("startTLSServer err: %v", <-errc)
    70  	}
    71  
    72  	c, err := NewConfigurator(config, nil)
    73  	require.NoError(t, err)
    74  	wrap := c.OutgoingRPCWrapper()
    75  	require.NotNil(t, wrap)
    76  
    77  	tlsClient, err := wrap("dc1", client)
    78  	require.NoError(t, err)
    79  
    80  	defer tlsClient.Close()
    81  	err = tlsClient.(*tls.Conn).Handshake()
    82  	require.NoError(t, err)
    83  
    84  	err = <-errc
    85  	require.NoError(t, err)
    86  }
    87  
    88  func TestConfigurator_outgoingWrapper_noverify_OK(t *testing.T) {
    89  	config := Config{
    90  		CAFile:   "../test/hostname/CertAuth.crt",
    91  		CertFile: "../test/hostname/Alice.crt",
    92  		KeyFile:  "../test/hostname/Alice.key",
    93  		Domain:   "consul",
    94  	}
    95  
    96  	client, errc := startTLSServer(&config)
    97  	if client == nil {
    98  		t.Fatalf("startTLSServer err: %v", <-errc)
    99  	}
   100  
   101  	c, err := NewConfigurator(config, nil)
   102  	require.NoError(t, err)
   103  	wrap := c.OutgoingRPCWrapper()
   104  	require.NotNil(t, wrap)
   105  
   106  	tlsClient, err := wrap("dc1", client)
   107  	require.NoError(t, err)
   108  
   109  	defer tlsClient.Close()
   110  	err = tlsClient.(*tls.Conn).Handshake()
   111  	require.NoError(t, err)
   112  
   113  	err = <-errc
   114  	require.NoError(t, err)
   115  }
   116  
   117  func TestConfigurator_outgoingWrapper_BadDC(t *testing.T) {
   118  	config := Config{
   119  		CAFile:               "../test/hostname/CertAuth.crt",
   120  		CertFile:             "../test/hostname/Alice.crt",
   121  		KeyFile:              "../test/hostname/Alice.key",
   122  		VerifyServerHostname: true,
   123  		VerifyOutgoing:       true,
   124  		Domain:               "consul",
   125  	}
   126  
   127  	client, errc := startTLSServer(&config)
   128  	if client == nil {
   129  		t.Fatalf("startTLSServer err: %v", <-errc)
   130  	}
   131  
   132  	c, err := NewConfigurator(config, nil)
   133  	require.NoError(t, err)
   134  	wrap := c.OutgoingRPCWrapper()
   135  
   136  	tlsClient, err := wrap("dc2", client)
   137  	require.NoError(t, err)
   138  
   139  	err = tlsClient.(*tls.Conn).Handshake()
   140  	_, ok := err.(x509.HostnameError)
   141  	require.True(t, ok)
   142  	tlsClient.Close()
   143  
   144  	<-errc
   145  }
   146  
   147  func TestConfigurator_outgoingWrapper_BadCert(t *testing.T) {
   148  	config := Config{
   149  		CAFile:               "../test/ca/root.cer",
   150  		CertFile:             "../test/key/ourdomain.cer",
   151  		KeyFile:              "../test/key/ourdomain.key",
   152  		VerifyServerHostname: true,
   153  		VerifyOutgoing:       true,
   154  		Domain:               "consul",
   155  	}
   156  
   157  	client, errc := startTLSServer(&config)
   158  	if client == nil {
   159  		t.Fatalf("startTLSServer err: %v", <-errc)
   160  	}
   161  
   162  	c, err := NewConfigurator(config, nil)
   163  	require.NoError(t, err)
   164  	wrap := c.OutgoingRPCWrapper()
   165  
   166  	tlsClient, err := wrap("dc1", client)
   167  	require.NoError(t, err)
   168  
   169  	err = tlsClient.(*tls.Conn).Handshake()
   170  	if _, ok := err.(x509.HostnameError); !ok {
   171  		t.Fatalf("should get hostname err: %v", err)
   172  	}
   173  	tlsClient.Close()
   174  
   175  	<-errc
   176  }
   177  
   178  func TestConfigurator_wrapTLS_OK(t *testing.T) {
   179  	config := Config{
   180  		CAFile:         "../test/ca/root.cer",
   181  		CertFile:       "../test/key/ourdomain.cer",
   182  		KeyFile:        "../test/key/ourdomain.key",
   183  		VerifyOutgoing: true,
   184  	}
   185  
   186  	client, errc := startTLSServer(&config)
   187  	if client == nil {
   188  		t.Fatalf("startTLSServer err: %v", <-errc)
   189  	}
   190  
   191  	c, err := NewConfigurator(config, nil)
   192  	require.NoError(t, err)
   193  
   194  	tlsClient, err := c.wrapTLSClient("dc1", client)
   195  	require.NoError(t, err)
   196  
   197  	tlsClient.Close()
   198  	err = <-errc
   199  	require.NoError(t, err)
   200  }
   201  
   202  func TestConfigurator_wrapTLS_BadCert(t *testing.T) {
   203  	serverConfig := &Config{
   204  		CertFile: "../test/key/ssl-cert-snakeoil.pem",
   205  		KeyFile:  "../test/key/ssl-cert-snakeoil.key",
   206  	}
   207  
   208  	client, errc := startTLSServer(serverConfig)
   209  	if client == nil {
   210  		t.Fatalf("startTLSServer err: %v", <-errc)
   211  	}
   212  
   213  	clientConfig := Config{
   214  		CAFile:         "../test/ca/root.cer",
   215  		VerifyOutgoing: true,
   216  	}
   217  
   218  	c, err := NewConfigurator(clientConfig, nil)
   219  	require.NoError(t, err)
   220  	tlsClient, err := c.wrapTLSClient("dc1", client)
   221  	require.Error(t, err)
   222  	require.Nil(t, tlsClient)
   223  
   224  	err = <-errc
   225  	require.NoError(t, err)
   226  }
   227  
   228  func TestConfig_ParseCiphers(t *testing.T) {
   229  	testOk := strings.Join([]string{
   230  		"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
   231  		"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
   232  		"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
   233  		"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
   234  		"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
   235  		"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
   236  		"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
   237  		"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
   238  		"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
   239  		"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
   240  		"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
   241  		"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
   242  		"TLS_RSA_WITH_AES_128_GCM_SHA256",
   243  		"TLS_RSA_WITH_AES_256_GCM_SHA384",
   244  		"TLS_RSA_WITH_AES_128_CBC_SHA256",
   245  		"TLS_RSA_WITH_AES_128_CBC_SHA",
   246  		"TLS_RSA_WITH_AES_256_CBC_SHA",
   247  		"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
   248  		"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
   249  		"TLS_RSA_WITH_RC4_128_SHA",
   250  		"TLS_ECDHE_RSA_WITH_RC4_128_SHA",
   251  		"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
   252  	}, ",")
   253  	ciphers := []uint16{
   254  		tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
   255  		tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
   256  		tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
   257  		tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
   258  		tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
   259  		tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
   260  		tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
   261  		tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
   262  		tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
   263  		tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
   264  		tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
   265  		tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
   266  		tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
   267  		tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
   268  		tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
   269  		tls.TLS_RSA_WITH_AES_128_CBC_SHA,
   270  		tls.TLS_RSA_WITH_AES_256_CBC_SHA,
   271  		tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
   272  		tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
   273  		tls.TLS_RSA_WITH_RC4_128_SHA,
   274  		tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
   275  		tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
   276  	}
   277  	v, err := ParseCiphers(testOk)
   278  	require.NoError(t, err)
   279  	if got, want := v, ciphers; !reflect.DeepEqual(got, want) {
   280  		t.Fatalf("got ciphers %#v want %#v", got, want)
   281  	}
   282  
   283  	_, err = ParseCiphers("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,cipherX")
   284  	require.Error(t, err)
   285  
   286  	v, err = ParseCiphers("")
   287  	require.NoError(t, err)
   288  	require.Equal(t, []uint16{}, v)
   289  }
   290  
   291  func TestConfigurator_loadKeyPair(t *testing.T) {
   292  	type variant struct {
   293  		cert, key string
   294  		shoulderr bool
   295  		isnil     bool
   296  	}
   297  	variants := []variant{
   298  		{"", "", false, true},
   299  		{"bogus", "", false, true},
   300  		{"", "bogus", false, true},
   301  		{"../test/key/ourdomain.cer", "", false, true},
   302  		{"", "../test/key/ourdomain.key", false, true},
   303  		{"bogus", "bogus", true, true},
   304  		{"../test/key/ourdomain.cer", "../test/key/ourdomain.key",
   305  			false, false},
   306  	}
   307  	for _, v := range variants {
   308  		cert1, err1 := loadKeyPair(v.cert, v.key)
   309  		config := &Config{CertFile: v.cert, KeyFile: v.key}
   310  		cert2, err2 := config.KeyPair()
   311  		if v.shoulderr {
   312  			require.Error(t, err1)
   313  			require.Error(t, err2)
   314  		} else {
   315  			require.NoError(t, err1)
   316  			require.NoError(t, err2)
   317  		}
   318  		if v.isnil {
   319  			require.Nil(t, cert1)
   320  			require.Nil(t, cert2)
   321  		} else {
   322  			require.NotNil(t, cert1)
   323  			require.NotNil(t, cert2)
   324  		}
   325  	}
   326  }
   327  
   328  func TestConfig_SpecifyDC(t *testing.T) {
   329  	require.Nil(t, SpecificDC("", nil))
   330  	dcwrap := func(dc string, conn net.Conn) (net.Conn, error) { return nil, nil }
   331  	wrap := SpecificDC("", dcwrap)
   332  	require.NotNil(t, wrap)
   333  	conn, err := wrap(nil)
   334  	require.NoError(t, err)
   335  	require.Nil(t, conn)
   336  }
   337  
   338  func TestConfigurator_NewConfigurator(t *testing.T) {
   339  	buf := bytes.Buffer{}
   340  	logger := log.New(&buf, "logger: ", log.Lshortfile)
   341  	c, err := NewConfigurator(Config{}, logger)
   342  	require.NoError(t, err)
   343  	require.NotNil(t, c)
   344  	require.Equal(t, logger, c.logger)
   345  
   346  	c, err = NewConfigurator(Config{VerifyOutgoing: true}, nil)
   347  	require.Error(t, err)
   348  	require.Nil(t, c)
   349  }
   350  
   351  func TestConfigurator_ErrorPropagation(t *testing.T) {
   352  	type variant struct {
   353  		config       Config
   354  		shouldErr    bool
   355  		excludeCheck bool
   356  	}
   357  	cafile := "../test/ca/root.cer"
   358  	capath := "../test/ca_path"
   359  	certfile := "../test/key/ourdomain.cer"
   360  	keyfile := "../test/key/ourdomain.key"
   361  	variants := []variant{
   362  		{Config{}, false, false},
   363  		{Config{TLSMinVersion: "tls9"}, true, false},
   364  		{Config{TLSMinVersion: ""}, false, false},
   365  		{Config{TLSMinVersion: "tls10"}, false, false},
   366  		{Config{TLSMinVersion: "tls11"}, false, false},
   367  		{Config{TLSMinVersion: "tls12"}, false, false},
   368  		{Config{VerifyOutgoing: true, CAFile: "", CAPath: ""}, true, false},
   369  		{Config{VerifyOutgoing: false, CAFile: "", CAPath: ""}, false, false},
   370  		{Config{VerifyOutgoing: false, CAFile: cafile, CAPath: ""},
   371  			false, false},
   372  		{Config{VerifyOutgoing: false, CAFile: "", CAPath: capath},
   373  			false, false},
   374  		{Config{VerifyOutgoing: false, CAFile: cafile, CAPath: capath},
   375  			false, false},
   376  		{Config{VerifyOutgoing: true, CAFile: cafile, CAPath: ""},
   377  			false, false},
   378  		{Config{VerifyOutgoing: true, CAFile: "", CAPath: capath},
   379  			false, false},
   380  		{Config{VerifyOutgoing: true, CAFile: cafile, CAPath: capath},
   381  			false, false},
   382  		{Config{VerifyIncoming: true, CAFile: "", CAPath: ""}, true, false},
   383  		{Config{VerifyIncomingRPC: true, CAFile: "", CAPath: ""},
   384  			true, false},
   385  		{Config{VerifyIncomingHTTPS: true, CAFile: "", CAPath: ""},
   386  			true, false},
   387  		{Config{VerifyIncoming: true, CAFile: cafile, CAPath: ""}, true, false},
   388  		{Config{VerifyIncoming: true, CAFile: "", CAPath: capath}, true, false},
   389  		{Config{VerifyIncoming: true, CAFile: "", CAPath: capath,
   390  			CertFile: certfile, KeyFile: keyfile}, false, false},
   391  		{Config{CertFile: "bogus", KeyFile: "bogus"}, true, true},
   392  		{Config{CAFile: "bogus"}, true, true},
   393  		{Config{CAPath: "bogus"}, true, true},
   394  	}
   395  
   396  	c := &Configurator{}
   397  	for i, v := range variants {
   398  		info := fmt.Sprintf("case %d", i)
   399  		_, err1 := NewConfigurator(v.config, nil)
   400  		err2 := c.Update(v.config)
   401  
   402  		var err3 error
   403  		if !v.excludeCheck {
   404  			cert, err := v.config.KeyPair()
   405  			require.NoError(t, err, info)
   406  			cas, _ := loadCAs(v.config.CAFile, v.config.CAPath)
   407  			require.NoError(t, err, info)
   408  			err3 = c.check(v.config, cas, cert)
   409  		}
   410  		if v.shouldErr {
   411  			require.Error(t, err1, info)
   412  			require.Error(t, err2, info)
   413  			if !v.excludeCheck {
   414  				require.Error(t, err3, info)
   415  			}
   416  		} else {
   417  			require.NoError(t, err1, info)
   418  			require.NoError(t, err2, info)
   419  			if !v.excludeCheck {
   420  				require.NoError(t, err3, info)
   421  			}
   422  		}
   423  	}
   424  }
   425  
   426  func TestConfigurator_CommonTLSConfigServerNameNodeName(t *testing.T) {
   427  	type variant struct {
   428  		config Config
   429  		result string
   430  	}
   431  	variants := []variant{
   432  		{config: Config{NodeName: "node", ServerName: "server"},
   433  			result: "server"},
   434  		{config: Config{ServerName: "server"},
   435  			result: "server"},
   436  		{config: Config{NodeName: "node"},
   437  			result: "node"},
   438  	}
   439  	for _, v := range variants {
   440  		c, err := NewConfigurator(v.config, nil)
   441  		require.NoError(t, err)
   442  		tlsConf := c.commonTLSConfig(false)
   443  		require.Empty(t, tlsConf.ServerName)
   444  	}
   445  }
   446  
   447  func TestConfigurator_loadCAs(t *testing.T) {
   448  	type variant struct {
   449  		cafile, capath string
   450  		shouldErr      bool
   451  		isNil          bool
   452  		count          int
   453  	}
   454  	variants := []variant{
   455  		{"", "", false, true, 0},
   456  		{"bogus", "", true, true, 0},
   457  		{"", "bogus", true, true, 0},
   458  		{"", "../test/bin", true, true, 0},
   459  		{"../test/ca/root.cer", "", false, false, 1},
   460  		{"", "../test/ca_path", false, false, 2},
   461  		{"../test/ca/root.cer", "../test/ca_path", false, false, 1},
   462  	}
   463  	for i, v := range variants {
   464  		cas, err := loadCAs(v.cafile, v.capath)
   465  		info := fmt.Sprintf("case %d", i)
   466  		if v.shouldErr {
   467  			require.Error(t, err, info)
   468  		} else {
   469  			require.NoError(t, err, info)
   470  		}
   471  		if v.isNil {
   472  			require.Nil(t, cas, info)
   473  		} else {
   474  			require.NotNil(t, cas, info)
   475  			require.Len(t, cas.Subjects(), v.count, info)
   476  		}
   477  	}
   478  }
   479  
   480  func TestConfigurator_CommonTLSConfigInsecureSkipVerify(t *testing.T) {
   481  	c, err := NewConfigurator(Config{}, nil)
   482  	require.NoError(t, err)
   483  	tlsConf := c.commonTLSConfig(false)
   484  	require.True(t, tlsConf.InsecureSkipVerify)
   485  
   486  	require.NoError(t, c.Update(Config{VerifyServerHostname: false}))
   487  	tlsConf = c.commonTLSConfig(false)
   488  	require.True(t, tlsConf.InsecureSkipVerify)
   489  
   490  	require.NoError(t, c.Update(Config{VerifyServerHostname: true}))
   491  	tlsConf = c.commonTLSConfig(false)
   492  	require.False(t, tlsConf.InsecureSkipVerify)
   493  }
   494  
   495  func TestConfigurator_CommonTLSConfigPreferServerCipherSuites(t *testing.T) {
   496  	c, err := NewConfigurator(Config{}, nil)
   497  	require.NoError(t, err)
   498  	tlsConf := c.commonTLSConfig(false)
   499  	require.False(t, tlsConf.PreferServerCipherSuites)
   500  
   501  	require.NoError(t, c.Update(Config{PreferServerCipherSuites: false}))
   502  	tlsConf = c.commonTLSConfig(false)
   503  	require.False(t, tlsConf.PreferServerCipherSuites)
   504  
   505  	require.NoError(t, c.Update(Config{PreferServerCipherSuites: true}))
   506  	tlsConf = c.commonTLSConfig(false)
   507  	require.True(t, tlsConf.PreferServerCipherSuites)
   508  }
   509  
   510  func TestConfigurator_CommonTLSConfigCipherSuites(t *testing.T) {
   511  	c, err := NewConfigurator(Config{}, nil)
   512  	require.NoError(t, err)
   513  	tlsConf := c.commonTLSConfig(false)
   514  	require.Empty(t, tlsConf.CipherSuites)
   515  
   516  	conf := Config{CipherSuites: []uint16{
   517  		tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305}}
   518  	require.NoError(t, c.Update(conf))
   519  	tlsConf = c.commonTLSConfig(false)
   520  	require.Equal(t, conf.CipherSuites, tlsConf.CipherSuites)
   521  }
   522  
   523  func TestConfigurator_CommonTLSConfigGetClientCertificate(t *testing.T) {
   524  	c, err := NewConfigurator(Config{}, nil)
   525  	require.NoError(t, err)
   526  
   527  	cert, err := c.commonTLSConfig(false).GetCertificate(nil)
   528  	require.NoError(t, err)
   529  	require.Nil(t, cert)
   530  
   531  	c.cert = &tls.Certificate{}
   532  	cert, err = c.commonTLSConfig(false).GetCertificate(nil)
   533  	require.NoError(t, err)
   534  	require.Equal(t, c.cert, cert)
   535  
   536  	cert, err = c.commonTLSConfig(false).GetClientCertificate(nil)
   537  	require.NoError(t, err)
   538  	require.Equal(t, c.cert, cert)
   539  }
   540  
   541  func TestConfigurator_CommonTLSConfigCAs(t *testing.T) {
   542  	c, err := NewConfigurator(Config{}, nil)
   543  	require.NoError(t, err)
   544  	require.Nil(t, c.commonTLSConfig(false).ClientCAs)
   545  	require.Nil(t, c.commonTLSConfig(false).RootCAs)
   546  
   547  	c.cas = &x509.CertPool{}
   548  	require.Equal(t, c.cas, c.commonTLSConfig(false).ClientCAs)
   549  	require.Equal(t, c.cas, c.commonTLSConfig(false).RootCAs)
   550  }
   551  
   552  func TestConfigurator_CommonTLSConfigTLSMinVersion(t *testing.T) {
   553  	c, err := NewConfigurator(Config{TLSMinVersion: ""}, nil)
   554  	require.NoError(t, err)
   555  	require.Equal(t, c.commonTLSConfig(false).MinVersion, TLSLookup["tls10"])
   556  
   557  	tlsVersions := []string{"tls10", "tls11", "tls12"}
   558  	for _, version := range tlsVersions {
   559  		require.NoError(t, c.Update(Config{TLSMinVersion: version}))
   560  		require.Equal(t, c.commonTLSConfig(false).MinVersion,
   561  			TLSLookup[version])
   562  	}
   563  
   564  	require.Error(t, c.Update(Config{TLSMinVersion: "tlsBOGUS"}))
   565  }
   566  
   567  func TestConfigurator_CommonTLSConfigVerifyIncoming(t *testing.T) {
   568  	c := Configurator{base: &Config{}}
   569  	type variant struct {
   570  		verify     bool
   571  		additional bool
   572  		expected   tls.ClientAuthType
   573  	}
   574  	variants := []variant{
   575  		{false, false, tls.NoClientCert},
   576  		{true, false, tls.RequireAndVerifyClientCert},
   577  		{false, true, tls.RequireAndVerifyClientCert},
   578  		{true, true, tls.RequireAndVerifyClientCert},
   579  	}
   580  	for _, v := range variants {
   581  		c.base.VerifyIncoming = v.verify
   582  		require.Equal(t, v.expected,
   583  			c.commonTLSConfig(v.additional).ClientAuth)
   584  	}
   585  }
   586  
   587  func TestConfigurator_OutgoingRPCTLSDisabled(t *testing.T) {
   588  	c := Configurator{base: &Config{}}
   589  	type variant struct {
   590  		verify   bool
   591  		file     string
   592  		path     string
   593  		expected bool
   594  	}
   595  	cafile := "../test/ca/root.cer"
   596  	capath := "../test/ca_path"
   597  	variants := []variant{
   598  		{false, "", "", true},
   599  		{false, cafile, "", false},
   600  		{false, "", capath, false},
   601  		{false, cafile, capath, false},
   602  		{true, "", "", false},
   603  		{true, cafile, "", false},
   604  		{true, "", capath, false},
   605  		{true, cafile, capath, false},
   606  	}
   607  	for i, v := range variants {
   608  		info := fmt.Sprintf("case %d", i)
   609  		cas, err := loadCAs(v.file, v.path)
   610  		require.NoError(t, err, info)
   611  		c.cas = cas
   612  		c.base.VerifyOutgoing = v.verify
   613  		require.Equal(t, v.expected, c.outgoingRPCTLSDisabled(), info)
   614  	}
   615  }
   616  
   617  func TestConfigurator_SomeValuesFromConfig(t *testing.T) {
   618  	c := Configurator{base: &Config{
   619  		VerifyServerHostname: true,
   620  		VerifyOutgoing:       true,
   621  		Domain:               "abc.de",
   622  	}}
   623  	one, two, three := c.someValuesFromConfig()
   624  	require.Equal(t, c.base.VerifyServerHostname, one)
   625  	require.Equal(t, c.base.VerifyOutgoing, two)
   626  	require.Equal(t, c.base.Domain, three)
   627  }
   628  
   629  func TestConfigurator_VerifyIncomingRPC(t *testing.T) {
   630  	c := Configurator{base: &Config{
   631  		VerifyIncomingRPC: true,
   632  	}}
   633  	verify := c.verifyIncomingRPC()
   634  	require.Equal(t, c.base.VerifyIncomingRPC, verify)
   635  }
   636  
   637  func TestConfigurator_VerifyIncomingHTTPS(t *testing.T) {
   638  	c := Configurator{base: &Config{
   639  		VerifyIncomingHTTPS: true,
   640  	}}
   641  	verify := c.verifyIncomingHTTPS()
   642  	require.Equal(t, c.base.VerifyIncomingHTTPS, verify)
   643  }
   644  
   645  func TestConfigurator_EnableAgentTLSForChecks(t *testing.T) {
   646  	c := Configurator{base: &Config{
   647  		EnableAgentTLSForChecks: true,
   648  	}}
   649  	enabled := c.enableAgentTLSForChecks()
   650  	require.Equal(t, c.base.EnableAgentTLSForChecks, enabled)
   651  }
   652  
   653  func TestConfigurator_IncomingRPCConfig(t *testing.T) {
   654  	c, err := NewConfigurator(Config{
   655  		VerifyIncomingRPC: true,
   656  		CAFile:            "../test/ca/root.cer",
   657  		CertFile:          "../test/key/ourdomain.cer",
   658  		KeyFile:           "../test/key/ourdomain.key",
   659  	}, nil)
   660  	require.NoError(t, err)
   661  	tlsConf := c.IncomingRPCConfig()
   662  	require.Equal(t, tls.RequireAndVerifyClientCert, tlsConf.ClientAuth)
   663  	require.NotNil(t, tlsConf.GetConfigForClient)
   664  	tlsConf, err = tlsConf.GetConfigForClient(nil)
   665  	require.NoError(t, err)
   666  	require.Equal(t, tls.RequireAndVerifyClientCert, tlsConf.ClientAuth)
   667  }
   668  
   669  func TestConfigurator_IncomingHTTPSConfig(t *testing.T) {
   670  	c := Configurator{base: &Config{}}
   671  	require.Equal(t, []string{"h2", "http/1.1"}, c.IncomingHTTPSConfig().NextProtos)
   672  }
   673  
   674  func TestConfigurator_OutgoingTLSConfigForChecks(t *testing.T) {
   675  	c := Configurator{base: &Config{
   676  		TLSMinVersion:           "tls12",
   677  		EnableAgentTLSForChecks: false,
   678  	}}
   679  	tlsConf := c.OutgoingTLSConfigForCheck(true)
   680  	require.Equal(t, true, tlsConf.InsecureSkipVerify)
   681  	require.Equal(t, uint16(0), tlsConf.MinVersion)
   682  
   683  	c.base.EnableAgentTLSForChecks = true
   684  	c.base.ServerName = "servername"
   685  	tlsConf = c.OutgoingTLSConfigForCheck(true)
   686  	require.Equal(t, true, tlsConf.InsecureSkipVerify)
   687  	require.Equal(t, TLSLookup[c.base.TLSMinVersion], tlsConf.MinVersion)
   688  	require.Equal(t, c.base.ServerName, tlsConf.ServerName)
   689  }
   690  
   691  func TestConfigurator_OutgoingRPCConfig(t *testing.T) {
   692  	c := Configurator{base: &Config{}}
   693  	require.Nil(t, c.OutgoingRPCConfig())
   694  	c.base.VerifyOutgoing = true
   695  	require.NotNil(t, c.OutgoingRPCConfig())
   696  }
   697  
   698  func TestConfigurator_OutgoingRPCWrapper(t *testing.T) {
   699  	c := Configurator{base: &Config{}}
   700  	require.Nil(t, c.OutgoingRPCWrapper())
   701  	c.base.VerifyOutgoing = true
   702  	wrap := c.OutgoingRPCWrapper()
   703  	require.NotNil(t, wrap)
   704  	t.Log("TODO: actually call wrap here eventually")
   705  }
   706  
   707  func TestConfigurator_UpdateChecks(t *testing.T) {
   708  	c, err := NewConfigurator(Config{}, nil)
   709  	require.NoError(t, err)
   710  	require.NoError(t, c.Update(Config{}))
   711  	require.Error(t, c.Update(Config{VerifyOutgoing: true}))
   712  	require.Error(t, c.Update(Config{VerifyIncoming: true,
   713  		CAFile: "../test/ca/root.cer"}))
   714  	require.False(t, c.base.VerifyIncoming)
   715  	require.False(t, c.base.VerifyOutgoing)
   716  	require.Equal(t, c.version, 2)
   717  }
   718  
   719  func TestConfigurator_UpdateSetsStuff(t *testing.T) {
   720  	c, err := NewConfigurator(Config{}, nil)
   721  	require.NoError(t, err)
   722  	require.Nil(t, c.cas)
   723  	require.Nil(t, c.cert)
   724  	require.Equal(t, c.base, &Config{})
   725  	require.Equal(t, 1, c.version)
   726  
   727  	require.Error(t, c.Update(Config{VerifyOutgoing: true}))
   728  	require.Equal(t, c.version, 1)
   729  
   730  	config := Config{
   731  		CAFile:   "../test/ca/root.cer",
   732  		CertFile: "../test/key/ourdomain.cer",
   733  		KeyFile:  "../test/key/ourdomain.key",
   734  	}
   735  	require.NoError(t, c.Update(config))
   736  	require.NotNil(t, c.cas)
   737  	require.Len(t, c.cas.Subjects(), 1)
   738  	require.NotNil(t, c.cert)
   739  	require.Equal(t, c.base, &config)
   740  	require.Equal(t, 2, c.version)
   741  }
   742  
   743  func TestConfigurator_ServerNameOrNodeName(t *testing.T) {
   744  	c := Configurator{base: &Config{}}
   745  	type variant struct {
   746  		server, node, expected string
   747  	}
   748  	variants := []variant{
   749  		{"", "", ""},
   750  		{"a", "", "a"},
   751  		{"", "b", "b"},
   752  		{"a", "b", "a"},
   753  	}
   754  	for _, v := range variants {
   755  		c.base.ServerName = v.server
   756  		c.base.NodeName = v.node
   757  		require.Equal(t, v.expected, c.serverNameOrNodeName())
   758  	}
   759  }