2014-11-18 16:03:36 +00:00
|
|
|
package tlsutil
|
2014-04-07 20:05:43 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/tls"
|
2014-05-26 17:58:57 +00:00
|
|
|
"crypto/x509"
|
2014-06-30 01:11:32 +00:00
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
|
|
|
"net"
|
2017-04-27 08:29:39 +00:00
|
|
|
"reflect"
|
|
|
|
"strings"
|
2014-04-07 20:05:43 +00:00
|
|
|
"testing"
|
2015-05-11 23:05:39 +00:00
|
|
|
|
|
|
|
"github.com/hashicorp/yamux"
|
2018-12-17 17:56:18 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
2014-04-07 20:05:43 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestConfig_KeyPair_None(t *testing.T) {
|
|
|
|
conf := &Config{}
|
|
|
|
cert, err := conf.KeyPair()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if cert != nil {
|
|
|
|
t.Fatalf("bad: %v", cert)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfig_KeyPair_Valid(t *testing.T) {
|
|
|
|
conf := &Config{
|
|
|
|
CertFile: "../test/key/ourdomain.cer",
|
|
|
|
KeyFile: "../test/key/ourdomain.key",
|
|
|
|
}
|
|
|
|
cert, err := conf.KeyPair()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if cert == nil {
|
|
|
|
t.Fatalf("expected cert")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-26 15:52:07 +00:00
|
|
|
func TestConfigurator_OutgoingTLS_MissingCA(t *testing.T) {
|
2014-04-07 20:05:43 +00:00
|
|
|
conf := &Config{
|
|
|
|
VerifyOutgoing: true,
|
|
|
|
}
|
2019-02-26 15:52:07 +00:00
|
|
|
c := NewConfigurator(conf)
|
|
|
|
tlsConf, err := c.OutgoingRPCConfig()
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Nil(t, tlsConf)
|
2014-04-07 20:05:43 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 15:52:07 +00:00
|
|
|
func TestConfigurator_OutgoingTLS_OnlyCA(t *testing.T) {
|
2014-04-07 20:05:43 +00:00
|
|
|
conf := &Config{
|
|
|
|
CAFile: "../test/ca/root.cer",
|
|
|
|
}
|
2019-02-26 15:52:07 +00:00
|
|
|
c := NewConfigurator(conf)
|
|
|
|
tlsConf, err := c.OutgoingRPCConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, tlsConf)
|
2014-06-22 19:49:51 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 15:52:07 +00:00
|
|
|
func TestConfigurator_OutgoingTLS_VerifyOutgoing(t *testing.T) {
|
2014-06-22 19:49:51 +00:00
|
|
|
conf := &Config{
|
|
|
|
VerifyOutgoing: true,
|
|
|
|
CAFile: "../test/ca/root.cer",
|
|
|
|
}
|
2019-02-26 15:52:07 +00:00
|
|
|
c := NewConfigurator(conf)
|
|
|
|
tlsConf, err := c.OutgoingRPCConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, tlsConf)
|
2019-02-27 09:14:59 +00:00
|
|
|
require.Len(t, tlsConf.RootCAs.Subjects(), 1)
|
2019-02-26 15:52:07 +00:00
|
|
|
require.Empty(t, tlsConf.ServerName)
|
|
|
|
require.True(t, tlsConf.InsecureSkipVerify)
|
2014-04-07 20:05:43 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 15:52:07 +00:00
|
|
|
func TestConfigurator_OutgoingTLS_ServerName(t *testing.T) {
|
2014-04-07 20:05:43 +00:00
|
|
|
conf := &Config{
|
|
|
|
VerifyOutgoing: true,
|
|
|
|
CAFile: "../test/ca/root.cer",
|
2014-06-22 19:49:51 +00:00
|
|
|
ServerName: "consul.example.com",
|
2014-04-07 20:05:43 +00:00
|
|
|
}
|
2019-02-26 15:52:07 +00:00
|
|
|
c := NewConfigurator(conf)
|
|
|
|
tlsConf, err := c.OutgoingRPCConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, tlsConf)
|
2019-02-27 09:14:59 +00:00
|
|
|
require.Len(t, tlsConf.RootCAs.Subjects(), 1)
|
2019-02-26 15:52:07 +00:00
|
|
|
require.Equal(t, tlsConf.ServerName, "consul.example.com")
|
|
|
|
require.False(t, tlsConf.InsecureSkipVerify)
|
2014-04-07 20:05:43 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 15:52:07 +00:00
|
|
|
func TestConfigurator_OutgoingTLS_VerifyHostname(t *testing.T) {
|
2015-05-11 22:27:09 +00:00
|
|
|
conf := &Config{
|
2018-12-06 21:51:49 +00:00
|
|
|
VerifyOutgoing: true,
|
2015-05-11 22:27:09 +00:00
|
|
|
VerifyServerHostname: true,
|
|
|
|
CAFile: "../test/ca/root.cer",
|
|
|
|
}
|
2019-02-26 15:52:07 +00:00
|
|
|
c := NewConfigurator(conf)
|
|
|
|
tlsConf, err := c.OutgoingRPCConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, tlsConf)
|
2019-02-27 09:14:59 +00:00
|
|
|
require.Len(t, tlsConf.RootCAs.Subjects(), 1)
|
2019-02-26 15:52:07 +00:00
|
|
|
require.False(t, tlsConf.InsecureSkipVerify)
|
2015-05-11 22:27:09 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 15:52:07 +00:00
|
|
|
func TestConfigurator_OutgoingTLS_WithKeyPair(t *testing.T) {
|
2014-04-07 20:05:43 +00:00
|
|
|
conf := &Config{
|
|
|
|
VerifyOutgoing: true,
|
|
|
|
CAFile: "../test/ca/root.cer",
|
|
|
|
CertFile: "../test/key/ourdomain.cer",
|
|
|
|
KeyFile: "../test/key/ourdomain.key",
|
|
|
|
}
|
2019-02-26 15:52:07 +00:00
|
|
|
c := NewConfigurator(conf)
|
|
|
|
tlsConf, err := c.OutgoingRPCConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, tlsConf)
|
|
|
|
require.True(t, tlsConf.InsecureSkipVerify)
|
2019-02-27 09:14:59 +00:00
|
|
|
require.Len(t, tlsConf.Certificates, 1)
|
2014-04-07 20:05:43 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 15:52:07 +00:00
|
|
|
func TestConfigurator_OutgoingTLS_TLSMinVersion(t *testing.T) {
|
2017-02-01 20:52:04 +00:00
|
|
|
tlsVersions := []string{"tls10", "tls11", "tls12"}
|
|
|
|
for _, version := range tlsVersions {
|
|
|
|
conf := &Config{
|
|
|
|
VerifyOutgoing: true,
|
|
|
|
CAFile: "../test/ca/root.cer",
|
|
|
|
TLSMinVersion: version,
|
|
|
|
}
|
2019-02-26 15:52:07 +00:00
|
|
|
c := NewConfigurator(conf)
|
|
|
|
tlsConf, err := c.OutgoingRPCConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, tlsConf)
|
|
|
|
require.Equal(t, tlsConf.MinVersion, TLSLookup[version])
|
2017-02-01 20:52:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-27 09:14:59 +00:00
|
|
|
func TestConfig_SkipBuiltinVerify(t *testing.T) {
|
|
|
|
type variant struct {
|
|
|
|
config Config
|
|
|
|
result bool
|
|
|
|
}
|
|
|
|
table := []variant{
|
|
|
|
variant{Config{ServerName: "", VerifyServerHostname: true}, false},
|
|
|
|
variant{Config{ServerName: "", VerifyServerHostname: false}, true},
|
|
|
|
variant{Config{ServerName: "consul", VerifyServerHostname: true}, false},
|
|
|
|
variant{Config{ServerName: "consul", VerifyServerHostname: false}, false},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, v := range table {
|
|
|
|
require.Equal(t, v.result, v.config.skipBuiltinVerify())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-30 01:11:32 +00:00
|
|
|
func startTLSServer(config *Config) (net.Conn, chan error) {
|
|
|
|
errc := make(chan error, 1)
|
|
|
|
|
2019-02-26 15:52:07 +00:00
|
|
|
c := NewConfigurator(config)
|
|
|
|
tlsConfigServer, err := c.IncomingRPCConfig()
|
2014-06-30 01:11:32 +00:00
|
|
|
if err != nil {
|
|
|
|
errc <- err
|
|
|
|
return nil, errc
|
|
|
|
}
|
|
|
|
|
|
|
|
client, server := net.Pipe()
|
2015-05-11 23:05:39 +00:00
|
|
|
|
|
|
|
// Use yamux to buffer the reads, otherwise it's easy to deadlock
|
|
|
|
muxConf := yamux.DefaultConfig()
|
|
|
|
serverSession, _ := yamux.Server(server, muxConf)
|
|
|
|
clientSession, _ := yamux.Client(client, muxConf)
|
|
|
|
clientConn, _ := clientSession.Open()
|
|
|
|
serverConn, _ := serverSession.Accept()
|
|
|
|
|
2014-06-30 01:11:32 +00:00
|
|
|
go func() {
|
2015-05-11 23:05:39 +00:00
|
|
|
tlsServer := tls.Server(serverConn, tlsConfigServer)
|
2014-06-30 01:11:32 +00:00
|
|
|
if err := tlsServer.Handshake(); err != nil {
|
|
|
|
errc <- err
|
|
|
|
}
|
|
|
|
close(errc)
|
2016-11-08 02:15:26 +00:00
|
|
|
|
2014-06-30 01:11:32 +00:00
|
|
|
// Because net.Pipe() is unbuffered, if both sides
|
|
|
|
// Close() simultaneously, we will deadlock as they
|
|
|
|
// both send an alert and then block. So we make the
|
|
|
|
// server read any data from the client until error or
|
|
|
|
// EOF, which will allow the client to Close(), and
|
|
|
|
// *then* we Close() the server.
|
|
|
|
io.Copy(ioutil.Discard, tlsServer)
|
|
|
|
tlsServer.Close()
|
|
|
|
}()
|
2015-05-11 23:05:39 +00:00
|
|
|
return clientConn, errc
|
|
|
|
}
|
|
|
|
|
2019-02-26 15:52:07 +00:00
|
|
|
func TestConfigurator_outgoingWrapper_OK(t *testing.T) {
|
2015-05-11 23:05:39 +00:00
|
|
|
config := &Config{
|
|
|
|
CAFile: "../test/hostname/CertAuth.crt",
|
|
|
|
CertFile: "../test/hostname/Alice.crt",
|
|
|
|
KeyFile: "../test/hostname/Alice.key",
|
|
|
|
VerifyServerHostname: true,
|
2018-12-06 21:51:49 +00:00
|
|
|
VerifyOutgoing: true,
|
2015-05-11 23:05:39 +00:00
|
|
|
Domain: "consul",
|
|
|
|
}
|
|
|
|
|
|
|
|
client, errc := startTLSServer(config)
|
|
|
|
if client == nil {
|
|
|
|
t.Fatalf("startTLSServer err: %v", <-errc)
|
|
|
|
}
|
|
|
|
|
2019-02-26 15:52:07 +00:00
|
|
|
c := NewConfigurator(config)
|
|
|
|
wrap, err := c.OutgoingRPCWrapper()
|
|
|
|
require.NoError(t, err)
|
2015-05-11 23:05:39 +00:00
|
|
|
|
|
|
|
tlsClient, err := wrap("dc1", client)
|
2019-02-26 15:52:07 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2015-05-11 23:05:39 +00:00
|
|
|
defer tlsClient.Close()
|
2019-02-26 15:52:07 +00:00
|
|
|
err = tlsClient.(*tls.Conn).Handshake()
|
|
|
|
require.NoError(t, err)
|
2015-05-11 23:05:39 +00:00
|
|
|
|
|
|
|
err = <-errc
|
2019-02-26 15:52:07 +00:00
|
|
|
require.NoError(t, err)
|
2015-05-11 23:05:39 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 15:52:07 +00:00
|
|
|
func TestConfigurator_outgoingWrapper_BadDC(t *testing.T) {
|
2015-05-11 23:05:39 +00:00
|
|
|
config := &Config{
|
|
|
|
CAFile: "../test/hostname/CertAuth.crt",
|
|
|
|
CertFile: "../test/hostname/Alice.crt",
|
|
|
|
KeyFile: "../test/hostname/Alice.key",
|
|
|
|
VerifyServerHostname: true,
|
2018-12-06 21:51:49 +00:00
|
|
|
VerifyOutgoing: true,
|
2015-05-11 23:05:39 +00:00
|
|
|
Domain: "consul",
|
|
|
|
}
|
|
|
|
|
|
|
|
client, errc := startTLSServer(config)
|
|
|
|
if client == nil {
|
|
|
|
t.Fatalf("startTLSServer err: %v", <-errc)
|
|
|
|
}
|
|
|
|
|
2019-02-26 15:52:07 +00:00
|
|
|
c := NewConfigurator(config)
|
|
|
|
wrap, err := c.OutgoingRPCWrapper()
|
|
|
|
require.NoError(t, err)
|
2015-05-11 23:05:39 +00:00
|
|
|
|
|
|
|
tlsClient, err := wrap("dc2", client)
|
2019-02-26 15:52:07 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2015-05-11 23:05:39 +00:00
|
|
|
err = tlsClient.(*tls.Conn).Handshake()
|
2019-02-26 15:52:07 +00:00
|
|
|
_, ok := err.(x509.HostnameError)
|
|
|
|
require.True(t, ok)
|
2016-11-08 02:15:26 +00:00
|
|
|
tlsClient.Close()
|
2015-05-11 23:05:39 +00:00
|
|
|
|
|
|
|
<-errc
|
|
|
|
}
|
|
|
|
|
2019-02-26 15:52:07 +00:00
|
|
|
func TestConfigurator_outgoingWrapper_BadCert(t *testing.T) {
|
2015-05-11 23:05:39 +00:00
|
|
|
config := &Config{
|
|
|
|
CAFile: "../test/ca/root.cer",
|
|
|
|
CertFile: "../test/key/ourdomain.cer",
|
|
|
|
KeyFile: "../test/key/ourdomain.key",
|
|
|
|
VerifyServerHostname: true,
|
2018-12-06 21:51:49 +00:00
|
|
|
VerifyOutgoing: true,
|
2015-05-11 23:05:39 +00:00
|
|
|
Domain: "consul",
|
|
|
|
}
|
|
|
|
|
|
|
|
client, errc := startTLSServer(config)
|
|
|
|
if client == nil {
|
|
|
|
t.Fatalf("startTLSServer err: %v", <-errc)
|
|
|
|
}
|
|
|
|
|
2019-02-26 15:52:07 +00:00
|
|
|
c := NewConfigurator(config)
|
|
|
|
wrap, err := c.OutgoingRPCWrapper()
|
|
|
|
require.NoError(t, err)
|
2015-05-11 23:05:39 +00:00
|
|
|
|
|
|
|
tlsClient, err := wrap("dc1", client)
|
2019-02-26 15:52:07 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2015-05-11 23:05:39 +00:00
|
|
|
err = tlsClient.(*tls.Conn).Handshake()
|
|
|
|
if _, ok := err.(x509.HostnameError); !ok {
|
|
|
|
t.Fatalf("should get hostname err: %v", err)
|
|
|
|
}
|
2016-11-08 02:15:26 +00:00
|
|
|
tlsClient.Close()
|
2015-05-11 23:05:39 +00:00
|
|
|
|
|
|
|
<-errc
|
2014-06-30 01:11:32 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 15:52:07 +00:00
|
|
|
func TestConfigurator_wrapTLS_OK(t *testing.T) {
|
2014-06-30 01:11:32 +00:00
|
|
|
config := &Config{
|
|
|
|
CAFile: "../test/ca/root.cer",
|
|
|
|
CertFile: "../test/key/ourdomain.cer",
|
|
|
|
KeyFile: "../test/key/ourdomain.key",
|
|
|
|
VerifyOutgoing: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
client, errc := startTLSServer(config)
|
|
|
|
if client == nil {
|
|
|
|
t.Fatalf("startTLSServer err: %v", <-errc)
|
|
|
|
}
|
|
|
|
|
2019-02-26 15:52:07 +00:00
|
|
|
c := NewConfigurator(config)
|
|
|
|
clientConfig, err := c.OutgoingRPCConfig()
|
|
|
|
require.NoError(t, err)
|
2014-06-30 01:11:32 +00:00
|
|
|
|
2018-12-17 17:56:18 +00:00
|
|
|
tlsClient, err := config.wrapTLSClient(client, clientConfig)
|
2019-02-26 15:52:07 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
tlsClient.Close()
|
2014-06-30 01:11:32 +00:00
|
|
|
err = <-errc
|
2019-02-26 15:52:07 +00:00
|
|
|
require.NoError(t, err)
|
2014-06-30 01:11:32 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 15:52:07 +00:00
|
|
|
func TestConfigurator_wrapTLS_BadCert(t *testing.T) {
|
2014-06-30 01:11:32 +00:00
|
|
|
serverConfig := &Config{
|
|
|
|
CertFile: "../test/key/ssl-cert-snakeoil.pem",
|
|
|
|
KeyFile: "../test/key/ssl-cert-snakeoil.key",
|
|
|
|
}
|
|
|
|
|
|
|
|
client, errc := startTLSServer(serverConfig)
|
|
|
|
if client == nil {
|
|
|
|
t.Fatalf("startTLSServer err: %v", <-errc)
|
|
|
|
}
|
|
|
|
|
|
|
|
clientConfig := &Config{
|
|
|
|
CAFile: "../test/ca/root.cer",
|
|
|
|
VerifyOutgoing: true,
|
|
|
|
}
|
|
|
|
|
2019-02-26 15:52:07 +00:00
|
|
|
c := NewConfigurator(clientConfig)
|
|
|
|
clientTLSConfig, err := c.OutgoingRPCConfig()
|
|
|
|
require.NoError(t, err)
|
2014-06-30 01:11:32 +00:00
|
|
|
|
2018-12-17 17:56:18 +00:00
|
|
|
tlsClient, err := clientConfig.wrapTLSClient(client, clientTLSConfig)
|
2019-02-26 15:52:07 +00:00
|
|
|
require.Error(t, err)
|
|
|
|
require.Nil(t, tlsClient)
|
2014-06-30 01:11:32 +00:00
|
|
|
|
|
|
|
err = <-errc
|
2019-02-26 15:52:07 +00:00
|
|
|
require.NoError(t, err)
|
2017-02-01 20:52:04 +00:00
|
|
|
}
|
2017-04-27 08:29:39 +00:00
|
|
|
|
|
|
|
func TestConfig_ParseCiphers(t *testing.T) {
|
|
|
|
testOk := strings.Join([]string{
|
2018-03-13 16:50:41 +00:00
|
|
|
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
|
|
|
|
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
|
|
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
2017-04-27 08:29:39 +00:00
|
|
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
2018-03-13 16:50:41 +00:00
|
|
|
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
2017-04-27 08:29:39 +00:00
|
|
|
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
2018-03-13 16:50:41 +00:00
|
|
|
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
2017-04-27 08:29:39 +00:00
|
|
|
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
2018-03-13 16:50:41 +00:00
|
|
|
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
|
|
|
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
2017-04-27 08:29:39 +00:00
|
|
|
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
2018-03-13 16:50:41 +00:00
|
|
|
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
2017-04-27 08:29:39 +00:00
|
|
|
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
|
|
|
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
2018-03-13 16:50:41 +00:00
|
|
|
"TLS_RSA_WITH_AES_128_CBC_SHA256",
|
|
|
|
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
|
|
|
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
|
|
|
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
|
|
|
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
|
|
|
"TLS_RSA_WITH_RC4_128_SHA",
|
|
|
|
"TLS_ECDHE_RSA_WITH_RC4_128_SHA",
|
2018-03-13 17:30:18 +00:00
|
|
|
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
|
2017-04-27 08:29:39 +00:00
|
|
|
}, ",")
|
|
|
|
ciphers := []uint16{
|
2018-03-13 16:50:41 +00:00
|
|
|
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
|
|
|
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
|
|
|
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
2017-04-27 08:29:39 +00:00
|
|
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
2018-03-13 16:50:41 +00:00
|
|
|
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
2017-04-27 08:29:39 +00:00
|
|
|
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
2018-03-13 16:50:41 +00:00
|
|
|
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
2017-04-27 08:29:39 +00:00
|
|
|
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
2018-03-13 16:50:41 +00:00
|
|
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
|
|
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
2017-04-27 08:29:39 +00:00
|
|
|
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
2018-03-13 16:50:41 +00:00
|
|
|
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
2017-04-27 08:29:39 +00:00
|
|
|
tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
|
|
|
|
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
2018-03-13 16:50:41 +00:00
|
|
|
tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
|
|
|
|
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
|
|
|
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
|
|
|
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
|
|
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
|
|
tls.TLS_RSA_WITH_RC4_128_SHA,
|
|
|
|
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
2018-03-13 17:30:18 +00:00
|
|
|
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
2017-04-27 08:29:39 +00:00
|
|
|
}
|
|
|
|
v, err := ParseCiphers(testOk)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if got, want := v, ciphers; !reflect.DeepEqual(got, want) {
|
|
|
|
t.Fatalf("got ciphers %#v want %#v", got, want)
|
|
|
|
}
|
|
|
|
|
|
|
|
testBad := "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,cipherX"
|
|
|
|
if _, err := ParseCiphers(testBad); err == nil {
|
|
|
|
t.Fatal("should fail on unsupported cipherX")
|
|
|
|
}
|
|
|
|
}
|
2019-02-26 15:52:07 +00:00
|
|
|
|
|
|
|
func TestConfigurator_IncomingHTTPSConfig_CA_PATH(t *testing.T) {
|
|
|
|
conf := &Config{CAPath: "../test/ca_path"}
|
|
|
|
|
|
|
|
c := NewConfigurator(conf)
|
|
|
|
tlsConf, err := c.IncomingHTTPSConfig()
|
|
|
|
require.NoError(t, err)
|
2019-02-27 09:14:59 +00:00
|
|
|
require.Len(t, tlsConf.ClientCAs.Subjects(), 2)
|
2019-02-26 15:52:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigurator_IncomingHTTPS(t *testing.T) {
|
|
|
|
conf := &Config{
|
|
|
|
VerifyIncoming: true,
|
|
|
|
CAFile: "../test/ca/root.cer",
|
|
|
|
CertFile: "../test/key/ourdomain.cer",
|
|
|
|
KeyFile: "../test/key/ourdomain.key",
|
|
|
|
}
|
|
|
|
c := NewConfigurator(conf)
|
|
|
|
tlsConf, err := c.IncomingHTTPSConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, tlsConf)
|
2019-02-27 09:14:59 +00:00
|
|
|
require.Len(t, tlsConf.ClientCAs.Subjects(), 1)
|
2019-02-26 15:52:07 +00:00
|
|
|
require.Equal(t, tlsConf.ClientAuth, tls.RequireAndVerifyClientCert)
|
2019-02-27 09:14:59 +00:00
|
|
|
require.Len(t, tlsConf.Certificates, 1)
|
2019-02-26 15:52:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigurator_IncomingHTTPS_MissingCA(t *testing.T) {
|
|
|
|
conf := &Config{
|
|
|
|
VerifyIncoming: true,
|
|
|
|
CertFile: "../test/key/ourdomain.cer",
|
|
|
|
KeyFile: "../test/key/ourdomain.key",
|
|
|
|
}
|
|
|
|
c := NewConfigurator(conf)
|
|
|
|
_, err := c.IncomingHTTPSConfig()
|
|
|
|
require.Error(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigurator_IncomingHTTPS_MissingKey(t *testing.T) {
|
|
|
|
conf := &Config{
|
|
|
|
VerifyIncoming: true,
|
|
|
|
CAFile: "../test/ca/root.cer",
|
|
|
|
}
|
|
|
|
c := NewConfigurator(conf)
|
|
|
|
_, err := c.IncomingHTTPSConfig()
|
|
|
|
require.Error(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigurator_IncomingHTTPS_NoVerify(t *testing.T) {
|
|
|
|
conf := &Config{}
|
|
|
|
c := NewConfigurator(conf)
|
|
|
|
tlsConf, err := c.IncomingHTTPSConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, tlsConf)
|
2019-02-27 09:14:59 +00:00
|
|
|
require.Nil(t, tlsConf.ClientCAs)
|
2019-02-26 15:52:07 +00:00
|
|
|
require.Equal(t, tlsConf.ClientAuth, tls.NoClientCert)
|
2019-02-27 09:14:59 +00:00
|
|
|
require.Empty(t, tlsConf.Certificates)
|
2019-02-26 15:52:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigurator_IncomingHTTPS_TLSMinVersion(t *testing.T) {
|
|
|
|
tlsVersions := []string{"tls10", "tls11", "tls12"}
|
|
|
|
for _, version := range tlsVersions {
|
|
|
|
conf := &Config{
|
|
|
|
VerifyIncoming: true,
|
|
|
|
CAFile: "../test/ca/root.cer",
|
|
|
|
CertFile: "../test/key/ourdomain.cer",
|
|
|
|
KeyFile: "../test/key/ourdomain.key",
|
|
|
|
TLSMinVersion: version,
|
|
|
|
}
|
|
|
|
c := NewConfigurator(conf)
|
|
|
|
tlsConf, err := c.IncomingHTTPSConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, tlsConf)
|
|
|
|
require.Equal(t, tlsConf.MinVersion, TLSLookup[version])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigurator_IncomingHTTPSCAPath_Valid(t *testing.T) {
|
|
|
|
|
2019-02-27 09:14:59 +00:00
|
|
|
c := NewConfigurator(&Config{CAPath: "../test/ca_path"})
|
2019-02-26 15:52:07 +00:00
|
|
|
tlsConf, err := c.IncomingHTTPSConfig()
|
2019-02-27 09:14:59 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, tlsConf.ClientCAs.Subjects(), 2)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigurator_CommonTLSConfigNoBaseConfig(t *testing.T) {
|
|
|
|
c := NewConfigurator(nil)
|
|
|
|
_, err := c.commonTLSConfig(false)
|
|
|
|
require.Error(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigurator_CommonTLSConfigServerNameNodeName(t *testing.T) {
|
|
|
|
type variant struct {
|
|
|
|
config *Config
|
|
|
|
result string
|
|
|
|
}
|
|
|
|
variants := []variant{
|
|
|
|
{config: &Config{NodeName: "node", ServerName: "server"},
|
|
|
|
result: "server"},
|
|
|
|
{config: &Config{ServerName: "server"},
|
|
|
|
result: "server"},
|
|
|
|
{config: &Config{NodeName: "node"},
|
|
|
|
result: "node"},
|
|
|
|
}
|
|
|
|
for _, v := range variants {
|
|
|
|
c := NewConfigurator(v.config)
|
|
|
|
tlsConf, err := c.commonTLSConfig(false)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, v.result, tlsConf.ServerName)
|
2019-02-26 15:52:07 +00:00
|
|
|
}
|
2019-02-27 09:14:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigurator_CommonTLSConfigCipherSuites(t *testing.T) {
|
|
|
|
c := NewConfigurator(&Config{})
|
|
|
|
tlsConfig, err := c.commonTLSConfig(false)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Empty(t, tlsConfig.CipherSuites)
|
|
|
|
|
|
|
|
conf := &Config{CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305}}
|
|
|
|
c.Update(conf)
|
|
|
|
tlsConfig, err = c.commonTLSConfig(false)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, conf.CipherSuites, tlsConfig.CipherSuites)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigurator_CommonTLSConfigCertKey(t *testing.T) {
|
|
|
|
c := NewConfigurator(&Config{})
|
|
|
|
tlsConf, err := c.commonTLSConfig(false)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Empty(t, tlsConf.Certificates)
|
|
|
|
|
|
|
|
c.Update(&Config{CertFile: "/something/bogus", KeyFile: "/more/bogus"})
|
|
|
|
tlsConf, err = c.commonTLSConfig(false)
|
|
|
|
require.Error(t, err)
|
|
|
|
|
|
|
|
c.Update(&Config{CertFile: "../test/key/ourdomain.cer", KeyFile: "../test/key/ourdomain.key"})
|
|
|
|
tlsConf, err = c.commonTLSConfig(false)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, tlsConf.Certificates, 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigurator_CommonTLSConfigTLSMinVersion(t *testing.T) {
|
|
|
|
tlsVersions := []string{"tls10", "tls11", "tls12"}
|
|
|
|
for _, version := range tlsVersions {
|
|
|
|
c := NewConfigurator(&Config{TLSMinVersion: version})
|
|
|
|
tlsConf, err := c.commonTLSConfig(false)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, tlsConf.MinVersion, TLSLookup[version])
|
2019-02-26 15:52:07 +00:00
|
|
|
}
|
2019-02-27 09:14:59 +00:00
|
|
|
|
|
|
|
c := NewConfigurator(&Config{TLSMinVersion: "tlsBOGUS"})
|
|
|
|
_, err := c.commonTLSConfig(false)
|
|
|
|
require.Error(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigurator_CommonTLSConfigValidateVerifyOutgoingCA(t *testing.T) {
|
|
|
|
c := NewConfigurator(&Config{VerifyOutgoing: true})
|
|
|
|
_, err := c.commonTLSConfig(false)
|
|
|
|
require.Error(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigurator_CommonTLSConfigLoadCA(t *testing.T) {
|
|
|
|
c := NewConfigurator(&Config{})
|
|
|
|
tlsConf, err := c.commonTLSConfig(false)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Nil(t, tlsConf.RootCAs)
|
|
|
|
require.Nil(t, tlsConf.ClientCAs)
|
|
|
|
|
|
|
|
c.Update(&Config{CAFile: "/something/bogus"})
|
|
|
|
_, err = c.commonTLSConfig(false)
|
|
|
|
require.Error(t, err)
|
|
|
|
|
|
|
|
c.Update(&Config{CAPath: "/something/bogus/"})
|
|
|
|
_, err = c.commonTLSConfig(false)
|
|
|
|
require.Error(t, err)
|
|
|
|
|
|
|
|
c.Update(&Config{CAFile: "../test/ca/root.cer"})
|
|
|
|
tlsConf, err = c.commonTLSConfig(false)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, tlsConf.RootCAs.Subjects(), 1)
|
|
|
|
require.Len(t, tlsConf.ClientCAs.Subjects(), 1)
|
|
|
|
|
|
|
|
c.Update(&Config{CAPath: "../test/ca_path"})
|
|
|
|
tlsConf, err = c.commonTLSConfig(false)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, tlsConf.RootCAs.Subjects(), 2)
|
|
|
|
require.Len(t, tlsConf.ClientCAs.Subjects(), 2)
|
|
|
|
|
|
|
|
c.Update(&Config{CAFile: "../test/ca/root.cer", CAPath: "../test/ca_path"})
|
|
|
|
tlsConf, err = c.commonTLSConfig(false)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, tlsConf.RootCAs.Subjects(), 1)
|
|
|
|
require.Len(t, tlsConf.ClientCAs.Subjects(), 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigurator_CommonTLSConfigVerifyIncoming(t *testing.T) {
|
|
|
|
c := NewConfigurator(&Config{})
|
|
|
|
tlsConf, err := c.commonTLSConfig(false)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, tls.NoClientCert, tlsConf.ClientAuth)
|
|
|
|
|
|
|
|
c.Update(&Config{VerifyIncoming: true})
|
|
|
|
tlsConf, err = c.commonTLSConfig(false)
|
|
|
|
require.Error(t, err)
|
|
|
|
|
|
|
|
c.Update(&Config{VerifyIncoming: true, CAFile: "../test/ca/root.cer"})
|
|
|
|
tlsConf, err = c.commonTLSConfig(false)
|
|
|
|
require.Error(t, err)
|
|
|
|
|
|
|
|
c.Update(&Config{VerifyIncoming: true, CAFile: "../test/ca/root.cer", CertFile: "../test/cert/ourdomain.cer"})
|
|
|
|
tlsConf, err = c.commonTLSConfig(false)
|
|
|
|
require.Error(t, err)
|
|
|
|
|
|
|
|
c.Update(&Config{VerifyIncoming: true, CAFile: "../test/ca/root.cer", CertFile: "../test/key/ourdomain.cer", KeyFile: "../test/key/ourdomain.key"})
|
|
|
|
tlsConf, err = c.commonTLSConfig(false)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, tls.RequireAndVerifyClientCert, tlsConf.ClientAuth)
|
|
|
|
|
|
|
|
c.Update(&Config{VerifyIncoming: false, CAFile: "../test/ca/root.cer", CertFile: "../test/key/ourdomain.cer", KeyFile: "../test/key/ourdomain.key"})
|
|
|
|
tlsConf, err = c.commonTLSConfig(true)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, tls.RequireAndVerifyClientCert, tlsConf.ClientAuth)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigurator_IncomingRPCConfig(t *testing.T) {
|
|
|
|
c := NewConfigurator(&Config{})
|
|
|
|
tlsConf, err := c.IncomingRPCConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, tls.NoClientCert, tlsConf.ClientAuth)
|
|
|
|
|
|
|
|
c.Update(&Config{VerifyIncoming: true, CAFile: "../test/ca/root.cer", CertFile: "../test/key/ourdomain.cer", KeyFile: "../test/key/ourdomain.key"})
|
|
|
|
tlsConf, err = c.IncomingRPCConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, tls.RequireAndVerifyClientCert, tlsConf.ClientAuth)
|
|
|
|
|
|
|
|
c.Update(&Config{VerifyIncomingRPC: true, CAFile: "../test/ca/root.cer", CertFile: "../test/key/ourdomain.cer", KeyFile: "../test/key/ourdomain.key"})
|
|
|
|
tlsConf, err = c.IncomingRPCConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, tls.RequireAndVerifyClientCert, tlsConf.ClientAuth)
|
|
|
|
|
|
|
|
c.Update(&Config{VerifyIncomingHTTPS: true, CAFile: "../test/ca/root.cer", CertFile: "../test/key/ourdomain.cer", KeyFile: "../test/key/ourdomain.key"})
|
|
|
|
tlsConf, err = c.IncomingRPCConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, tls.NoClientCert, tlsConf.ClientAuth)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigurator_IncomingHTTPSConfig(t *testing.T) {
|
|
|
|
c := NewConfigurator(&Config{})
|
|
|
|
tlsConf, err := c.IncomingHTTPSConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, tls.NoClientCert, tlsConf.ClientAuth)
|
|
|
|
|
|
|
|
c.Update(&Config{VerifyIncoming: true, CAFile: "../test/ca/root.cer", CertFile: "../test/key/ourdomain.cer", KeyFile: "../test/key/ourdomain.key"})
|
|
|
|
tlsConf, err = c.IncomingHTTPSConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, tls.RequireAndVerifyClientCert, tlsConf.ClientAuth)
|
|
|
|
|
|
|
|
c.Update(&Config{VerifyIncomingHTTPS: true, CAFile: "../test/ca/root.cer", CertFile: "../test/key/ourdomain.cer", KeyFile: "../test/key/ourdomain.key"})
|
|
|
|
tlsConf, err = c.IncomingHTTPSConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, tls.RequireAndVerifyClientCert, tlsConf.ClientAuth)
|
|
|
|
|
|
|
|
c.Update(&Config{VerifyIncomingRPC: true, CAFile: "../test/ca/root.cer", CertFile: "../test/key/ourdomain.cer", KeyFile: "../test/key/ourdomain.key"})
|
|
|
|
tlsConf, err = c.IncomingHTTPSConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, tls.NoClientCert, tlsConf.ClientAuth)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigurator_OutgoingRPCConfig(t *testing.T) {
|
|
|
|
c := NewConfigurator(&Config{})
|
|
|
|
tlsConf, err := c.OutgoingRPCConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Nil(t, tlsConf)
|
|
|
|
|
|
|
|
c.Update(&Config{VerifyOutgoing: true})
|
|
|
|
tlsConf, err = c.OutgoingRPCConfig()
|
|
|
|
require.Error(t, err)
|
|
|
|
|
|
|
|
c.Update(&Config{VerifyOutgoing: true, CAFile: "../test/ca/root.cer"})
|
|
|
|
tlsConf, err = c.OutgoingRPCConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
c.Update(&Config{VerifyOutgoing: true, CAPath: "../test/ca_path"})
|
|
|
|
tlsConf, err = c.OutgoingRPCConfig()
|
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigurator_OutgoingTLSConfigForChecks(t *testing.T) {
|
|
|
|
c := NewConfigurator(&Config{})
|
|
|
|
tlsConf, err := c.OutgoingTLSConfigForCheck("")
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, tlsConf.InsecureSkipVerify)
|
|
|
|
|
|
|
|
c.Update(&Config{EnableAgentTLSForChecks: true})
|
|
|
|
tlsConf, err = c.OutgoingTLSConfigForCheck("")
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, tlsConf.InsecureSkipVerify)
|
|
|
|
|
|
|
|
c.AddCheck("c1", true)
|
|
|
|
c.Update(&Config{EnableAgentTLSForChecks: true})
|
|
|
|
tlsConf, err = c.OutgoingTLSConfigForCheck("c1")
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.True(t, tlsConf.InsecureSkipVerify)
|
|
|
|
|
|
|
|
c.AddCheck("c1", false)
|
|
|
|
c.Update(&Config{EnableAgentTLSForChecks: true})
|
|
|
|
tlsConf, err = c.OutgoingTLSConfigForCheck("c1")
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, tlsConf.InsecureSkipVerify)
|
|
|
|
|
|
|
|
c.AddCheck("c1", false)
|
|
|
|
c.Update(&Config{EnableAgentTLSForChecks: true})
|
|
|
|
tlsConf, err = c.OutgoingTLSConfigForCheck("c1")
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, tlsConf.InsecureSkipVerify)
|
2019-02-26 15:52:07 +00:00
|
|
|
}
|