From 322367d476b5c1cfcfcbd5bc509747063227a038 Mon Sep 17 00:00:00 2001 From: Hans Hasselberg Date: Wed, 19 Feb 2020 23:22:31 +0100 Subject: [PATCH] tls: support tls 1.3 (#7325) --- agent/config/runtime.go | 3 ++- tlsutil/config.go | 23 ++++++++++++++++++++--- tlsutil/config_test.go | 14 +++++++++----- website/source/docs/agent/options.html.md | 4 ++-- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/agent/config/runtime.go b/agent/config/runtime.go index 4d8619193..d18fcfee6 100644 --- a/agent/config/runtime.go +++ b/agent/config/runtime.go @@ -1423,7 +1423,8 @@ type RuntimeConfig struct { TLSCipherSuites []uint16 // TLSMinVersion is used to set the minimum TLS version used for TLS - // connections. Should be either "tls10", "tls11", or "tls12". + // connections. Should be either "tls10", "tls11", "tls12" or "tls13". + // Defaults to tls12. // // hcl: tls_min_version = string TLSMinVersion string diff --git a/tlsutil/config.go b/tlsutil/config.go index 36046ee66..86707abd0 100644 --- a/tlsutil/config.go +++ b/tlsutil/config.go @@ -4,15 +4,17 @@ import ( "crypto/tls" "crypto/x509" "fmt" - "github.com/hashicorp/consul/logging" - "github.com/hashicorp/go-hclog" "io/ioutil" "net" "os" "path/filepath" + "sort" "strings" "sync" "time" + + "github.com/hashicorp/consul/logging" + "github.com/hashicorp/go-hclog" ) // DCWrapper is a function that is used to wrap a non-TLS connection @@ -30,8 +32,12 @@ var TLSLookup = map[string]uint16{ "tls10": tls.VersionTLS10, "tls11": tls.VersionTLS11, "tls12": tls.VersionTLS12, + "tls13": tls.VersionTLS13, } +// TLSVersions has all the keys from the map above. +var TLSVersions = strings.Join(tlsVersions(), ", ") + // Config used to create tls.Config type Config struct { // VerifyIncoming is used to verify the authenticity of incoming @@ -120,6 +126,17 @@ type Config struct { AutoEncryptTLS bool } +func tlsVersions() []string { + versions := []string{} + for v := range TLSLookup { + if v != "" { + versions = append(versions, v) + } + } + sort.Strings(versions) + return versions +} + // KeyPair is used to open and parse a certificate and key file func (c *Config) KeyPair() (*tls.Certificate, error) { return loadKeyPair(c.CertFile, c.KeyFile) @@ -323,7 +340,7 @@ func (c *Configurator) check(config Config, pool *x509.CertPool, cert *tls.Certi // Check if a minimum TLS version was set if config.TLSMinVersion != "" { if _, ok := TLSLookup[config.TLSMinVersion]; !ok { - return fmt.Errorf("TLSMinVersion: value %s not supported, please specify one of [tls10,tls11,tls12]", config.TLSMinVersion) + return fmt.Errorf("TLSMinVersion: value %s not supported, please specify one of [%s]", config.TLSMinVersion, TLSVersions) } } diff --git a/tlsutil/config_test.go b/tlsutil/config_test.go index 72a8aa874..51e8b25ae 100644 --- a/tlsutil/config_test.go +++ b/tlsutil/config_test.go @@ -360,9 +360,6 @@ func TestConfigurator_ErrorPropagation(t *testing.T) { {Config{}, false, false}, // 1 {Config{TLSMinVersion: "tls9"}, true, false}, // 1 {Config{TLSMinVersion: ""}, false, false}, // 2 - {Config{TLSMinVersion: "tls10"}, false, false}, // 3 - {Config{TLSMinVersion: "tls11"}, false, false}, // 4 - {Config{TLSMinVersion: "tls12"}, false, false}, // 5 {Config{VerifyOutgoing: true, CAFile: "", CAPath: ""}, true, false}, // 6 {Config{VerifyOutgoing: false, CAFile: "", CAPath: ""}, false, false}, // 7 {Config{VerifyOutgoing: false, CAFile: cafile, CAPath: ""}, @@ -390,6 +387,9 @@ func TestConfigurator_ErrorPropagation(t *testing.T) { {Config{CAFile: "bogus"}, true, true}, // 21 {Config{CAPath: "bogus"}, true, true}, // 22 } + for _, v := range tlsVersions() { + variants = append(variants, variant{Config{TLSMinVersion: v}, false, false}) + } c := Configurator{autoEncrypt: &autoEncrypt{}, manual: &manual{}} for i, v := range variants { @@ -590,8 +590,7 @@ func TestConfigurator_CommonTLSConfigTLSMinVersion(t *testing.T) { require.NoError(t, err) require.Equal(t, c.commonTLSConfig(false).MinVersion, TLSLookup["tls10"]) - tlsVersions := []string{"tls10", "tls11", "tls12"} - for _, version := range tlsVersions { + for _, version := range tlsVersions() { require.NoError(t, c.Update(Config{TLSMinVersion: version})) require.Equal(t, c.commonTLSConfig(false).MinVersion, TLSLookup[version]) @@ -839,3 +838,8 @@ func TestConfigurator_AutoEncrytCertExpired(t *testing.T) { c.autoEncrypt.cert = cert require.False(t, c.AutoEncryptCertExpired()) } + +func TestConfig_tlsVersions(t *testing.T) { + require.Equal(t, []string{"tls10", "tls11", "tls12", "tls13"}, tlsVersions()) + require.Equal(t, strings.Join(tlsVersions(), ", "), TLSVersions) +} diff --git a/website/source/docs/agent/options.html.md b/website/source/docs/agent/options.html.md index 0aa7b54fe..e2559b098 100644 --- a/website/source/docs/agent/options.html.md +++ b/website/source/docs/agent/options.html.md @@ -1830,8 +1830,8 @@ to the old fragment --> facility messages are sent. By default, `LOCAL0` will be used. * `tls_min_version` Added in Consul - 0.7.4, this specifies the minimum supported version of TLS. Accepted values are "tls10", "tls11" - or "tls12". This defaults to "tls12". WARNING: TLS 1.1 and lower are generally considered less + 0.7.4, this specifies the minimum supported version of TLS. Accepted values are "tls10", "tls11", + "tls12", or "tls13". This defaults to "tls12". WARNING: TLS 1.1 and lower are generally considered less secure; avoid using these if possible. * `tls_cipher_suites` Added in Consul