From 00c01b07f995662b1629c8fd226aa014598864b3 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Sat, 2 May 2020 23:54:57 +0200 Subject: [PATCH 01/15] tls: enable the selection of more TLS settings Signed-off-by: Julien Pivotto --- https/README.md | 73 +++++++++++- .../tls_config_noAuth_allCiphers.good.yml | 26 +++++ .../tls_config_noAuth_allCurves.good.yml | 10 ++ .../tls_config_noAuth_inventedCiphers.bad.yml | 8 ++ .../tls_config_noAuth_inventedCurves.bad.yml | 7 ++ .../tls_config_noAuth_noHTTP2.good.yml | 9 ++ .../tls_config_noAuth_noHTTP2Cipher.bad.yml | 8 ++ .../tls_config_noAuth_someCiphers.good.yml | 11 ++ .../tls_config_noAuth_someCurves.good.yml | 8 ++ https/tls_ciphers.go | 43 +++++++ https/tls_config.go | 109 ++++++++++++++++-- https/tls_config_test.go | 94 +++++++++++++-- https/tls_version.go | 53 +++++++++ https/tls_version_go111.go | 49 ++++++++ 14 files changed, 488 insertions(+), 20 deletions(-) create mode 100644 https/testdata/tls_config_noAuth_allCiphers.good.yml create mode 100644 https/testdata/tls_config_noAuth_allCurves.good.yml create mode 100644 https/testdata/tls_config_noAuth_inventedCiphers.bad.yml create mode 100644 https/testdata/tls_config_noAuth_inventedCurves.bad.yml create mode 100644 https/testdata/tls_config_noAuth_noHTTP2.good.yml create mode 100644 https/testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml create mode 100644 https/testdata/tls_config_noAuth_someCiphers.good.yml create mode 100644 https/testdata/tls_config_noAuth_someCurves.good.yml create mode 100644 https/tls_ciphers.go create mode 100644 https/tls_version.go create mode 100644 https/tls_version_go111.go diff --git a/https/README.md b/https/README.md index 70b321ea4d..919d428e60 100644 --- a/https/README.md +++ b/https/README.md @@ -15,17 +15,47 @@ The config file should be written in YAML format, and is reloaded on each connec ``` tls_config: - # Certificate and key files for server to use to authenticate to client + # Certificate and key files for server to use to authenticate to client. cert_file: key_file: - # Server policy for client authentication. Maps to ClientAuth Policies + # Server policy for client authentication. Maps to ClientAuth Policies. # For more detail on clientAuth options: [ClientAuthType](https://golang.org/pkg/crypto/tls/#ClientAuthType) [ client_auth_type: | default = "NoClientCert" ] - # CA certificate for client certificate authentication to the server + # CA certificate for client certificate authentication to the server. [ client_ca_file: ] + # Minimum TLS version that is acceptable. + [ min_version: | default = "TLS1.2" ] + + # Maximum TLS version that is acceptable. + [ max_version: | default = "TLS1.3" ] + + # List of supported cipher suites for TLS versions up to TLS 1.2. If empty, + # Go default cipher suites are used. Available cipher suites are documented + # below. + [ cipher_suites: + - ] ] + + # Disable HTTP/2 support. This can not be toggled on the fly. + [ disable_http2: | default = false ] + + # prefer_server_cipher_suites controls whether the server selects the + # client's most preferred ciphersuite, or the server's most preferred + # ciphersuite. If true then the server's preference, as expressed in + # the order of elements in CipherSuites, is used. + [ prefer_server_cipher_suites: | default = false ] + + # session_tickets_disabled may be set to true to disable session ticket and + # PSK (resumption) support. + [ session_tickets_disabled: | default = false ] + + # Elliptic curves that will be used in an ECDHE handshake, in preference + # order. Available supported groups are documented below. + [ supported_groups: + - ] ] + # List of usernames and hashed passwords that have full access to the web # server via basic authentication. If empty, no basic authentication is # required. Passwords are hashed with bcrypt. @@ -49,3 +79,40 @@ hash. A higher cost will en up slowing down the authentication process. Depending on the machine, a cost of 10 will take about ~70ms where a cost of 18 can take up to a few seconds. That hash will be computed on every password-protected request. + + +## Available cipher suites + +List of available cipher suites for TLS up to 1.2 (we only permit +ciphersuites marked by go as 'secure'): + +- TLS_RSA_WITH_3DES_EDE_CBC_SHA +- TLS_RSA_WITH_AES_128_CBC_SHA +- TLS_RSA_WITH_AES_256_CBC_SHA +- TLS_RSA_WITH_AES_128_GCM_SHA256 +- TLS_RSA_WITH_AES_256_GCM_SHA384 +- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA +- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA +- TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA +- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA +- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 +- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 +- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 +- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + +List of available cipher suites for TLS 1.3 (TLS 1.3 ciphersuites are not +configurable): + +- TLS_AES_128_GCM_SHA256 +- TLS_AES_256_GCM_SHA384 +- TLS_CHACHA20_POLY1305_SHA256 + +## Available supported groups + +- CurveP256 +- CurveP384 +- CurveP521 +- X25519 diff --git a/https/testdata/tls_config_noAuth_allCiphers.good.yml b/https/testdata/tls_config_noAuth_allCiphers.good.yml new file mode 100644 index 0000000000..cb49515ac6 --- /dev/null +++ b/https/testdata/tls_config_noAuth_allCiphers.good.yml @@ -0,0 +1,26 @@ +tls_config : + cert_file : "testdata/server.crt" + key_file : "testdata/server.key" + client_auth_type : "VerifyClientCertIfGiven" + client_ca_file : "testdata/tls-ca-chain.pem" + cipher_suites: + - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + - TLS_AES_128_GCM_SHA256 + - TLS_AES_256_GCM_SHA384 + - TLS_CHACHA20_POLY1305_SHA256 + - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + - TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + - TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + - TLS_RSA_WITH_3DES_EDE_CBC_SHA + - TLS_RSA_WITH_AES_128_CBC_SHA + - TLS_RSA_WITH_AES_256_CBC_SHA + - TLS_RSA_WITH_AES_128_GCM_SHA256 + - TLS_RSA_WITH_AES_256_GCM_SHA384 + diff --git a/https/testdata/tls_config_noAuth_allCurves.good.yml b/https/testdata/tls_config_noAuth_allCurves.good.yml new file mode 100644 index 0000000000..1c9d4baee4 --- /dev/null +++ b/https/testdata/tls_config_noAuth_allCurves.good.yml @@ -0,0 +1,10 @@ +tls_config : + cert_file : "testdata/server.crt" + key_file : "testdata/server.key" + client_auth_type : "VerifyClientCertIfGiven" + client_ca_file : "testdata/tls-ca-chain.pem" + supported_groups: + - CurveP256 + - CurveP384 + - CurveP521 + - X25519 diff --git a/https/testdata/tls_config_noAuth_inventedCiphers.bad.yml b/https/testdata/tls_config_noAuth_inventedCiphers.bad.yml new file mode 100644 index 0000000000..f809e6d74d --- /dev/null +++ b/https/testdata/tls_config_noAuth_inventedCiphers.bad.yml @@ -0,0 +1,8 @@ +tls_config : + cert_file : "testdata/server.crt" + key_file : "testdata/server.key" + client_auth_type : "VerifyClientCertIfGiven" + client_ca_file : "testdata/tls-ca-chain.pem" + cipher_suites: + - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA2048 + diff --git a/https/testdata/tls_config_noAuth_inventedCurves.bad.yml b/https/testdata/tls_config_noAuth_inventedCurves.bad.yml new file mode 100644 index 0000000000..7d30c889ab --- /dev/null +++ b/https/testdata/tls_config_noAuth_inventedCurves.bad.yml @@ -0,0 +1,7 @@ +tls_config : + cert_file : "testdata/server.crt" + key_file : "testdata/server.key" + client_auth_type : "VerifyClientCertIfGiven" + client_ca_file : "testdata/tls-ca-chain.pem" + supported_groups: + - CurveP257 diff --git a/https/testdata/tls_config_noAuth_noHTTP2.good.yml b/https/testdata/tls_config_noAuth_noHTTP2.good.yml new file mode 100644 index 0000000000..6b38478411 --- /dev/null +++ b/https/testdata/tls_config_noAuth_noHTTP2.good.yml @@ -0,0 +1,9 @@ +tls_config : + cert_file : "testdata/server.crt" + key_file : "testdata/server.key" + client_auth_type : "VerifyClientCertIfGiven" + client_ca_file : "testdata/tls-ca-chain.pem" + cipher_suites: + - TLS_RSA_WITH_AES_128_CBC_SHA + max_version: TLS1.2 + disable_http2: true diff --git a/https/testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml b/https/testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml new file mode 100644 index 0000000000..2eb82f4ed6 --- /dev/null +++ b/https/testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml @@ -0,0 +1,8 @@ +tls_config : + cert_file : "testdata/server.crt" + key_file : "testdata/server.key" + client_auth_type : "VerifyClientCertIfGiven" + client_ca_file : "testdata/tls-ca-chain.pem" + cipher_suites: + - TLS_RSA_WITH_AES_128_CBC_SHA + max_version: TLS1.2 diff --git a/https/testdata/tls_config_noAuth_someCiphers.good.yml b/https/testdata/tls_config_noAuth_someCiphers.good.yml new file mode 100644 index 0000000000..2347449322 --- /dev/null +++ b/https/testdata/tls_config_noAuth_someCiphers.good.yml @@ -0,0 +1,11 @@ +tls_config : + cert_file : "testdata/server.crt" + key_file : "testdata/server.key" + client_auth_type : "VerifyClientCertIfGiven" + client_ca_file : "testdata/tls-ca-chain.pem" + cipher_suites: + - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + - TLS_CHACHA20_POLY1305_SHA256 + min_version: TLS1.2 + max_version: TLS1.2 diff --git a/https/testdata/tls_config_noAuth_someCurves.good.yml b/https/testdata/tls_config_noAuth_someCurves.good.yml new file mode 100644 index 0000000000..07e5646df1 --- /dev/null +++ b/https/testdata/tls_config_noAuth_someCurves.good.yml @@ -0,0 +1,8 @@ +tls_config : + cert_file : "testdata/server.crt" + key_file : "testdata/server.key" + client_auth_type : "VerifyClientCertIfGiven" + client_ca_file : "testdata/tls-ca-chain.pem" + min_version: TLS1.3 + supported_groups: + - CurveP521 diff --git a/https/tls_ciphers.go b/https/tls_ciphers.go new file mode 100644 index 0000000000..1773fa19b6 --- /dev/null +++ b/https/tls_ciphers.go @@ -0,0 +1,43 @@ +// Copyright 2020 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build go1.14 + +package https + +import ( + "crypto/tls" + "strings" + + "github.com/pkg/errors" +) + +func (c *cipher) UnmarshalYAML(unmarshal func(interface{}) error) error { + var s string + err := unmarshal((*string)(&s)) + if err != nil { + return err + } + s = strings.ToUpper(s) + for _, cs := range tls.CipherSuites() { + if cs.Name == s { + *c = (cipher)(cs.ID) + return nil + } + } + return errors.New("unknown cipher: " + s) +} + +func (c cipher) MarshalYAML() (interface{}, error) { + return tls.CipherSuiteName((uint16)(c)), nil +} diff --git a/https/tls_config.go b/https/tls_config.go index 44e57e9bd2..9e1884baa8 100644 --- a/https/tls_config.go +++ b/https/tls_config.go @@ -17,8 +17,10 @@ package https import ( "crypto/tls" "crypto/x509" + "fmt" "io/ioutil" "net/http" + "strings" "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" @@ -37,10 +39,17 @@ type Config struct { } type TLSStruct struct { - TLSCertPath string `yaml:"cert_file"` - TLSKeyPath string `yaml:"key_file"` - ClientAuth string `yaml:"client_auth_type"` - ClientCAs string `yaml:"client_ca_file"` + TLSCertPath string `yaml:"cert_file"` + TLSKeyPath string `yaml:"key_file"` + ClientAuth string `yaml:"client_auth_type"` + ClientCAs string `yaml:"client_ca_file"` + CipherSuites []cipher `yaml:"cipher_suites"` + CurveIDs []curve `yaml:"supported_groups"` + MinVersion string `yaml:"min_version"` + MaxVersion string `yaml:"max_version"` + PreferServerCipherSuites bool `yaml:"prefer_server_cipher_suites"` + DisableHTTP2 bool `yaml:"disable_http2"` + SessionTicketsDisabled bool `yaml:"session_tickets_disabled"` } func getConfig(configPath string) (*Config, error) { @@ -73,9 +82,7 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) { if c.TLSKeyPath == "" { return nil, errors.New("missing key_file") } - cfg := &tls.Config{ - MinVersion: tls.VersionTLS12, - } + loadCert := func() (*tls.Certificate, error) { cert, err := tls.LoadX509KeyPair(c.TLSCertPath, c.TLSKeyPath) if err != nil { @@ -83,6 +90,24 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) { } return &cert, nil } + + minVersion, err := pickMinVersion(c.MinVersion) + if err != nil { + return nil, err + } + + maxVersion, err := pickMaxVersion(c.MaxVersion) + if err != nil { + return nil, err + } + + cfg := &tls.Config{ + MinVersion: minVersion, + MaxVersion: maxVersion, + PreferServerCipherSuites: c.PreferServerCipherSuites, + SessionTicketsDisabled: c.SessionTicketsDisabled, + } + // Confirm that certificate and key paths are valid. if _, err := loadCert(); err != nil { return nil, err @@ -91,6 +116,22 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) { return loadCert() } + var cf []uint16 + for _, c := range c.CipherSuites { + cf = append(cf, (uint16)(c)) + } + if len(cf) > 0 { + cfg.CipherSuites = cf + } + + var sg []tls.CurveID + for _, c := range c.CurveIDs { + sg = append(sg, (tls.CurveID)(c)) + } + if len(sg) > 0 { + cfg.CurvePreferences = sg + } + if c.ClientCAs != "" { clientCAPool := x509.NewCertPool() clientCAFile, err := ioutil.ReadFile(c.ClientCAs) @@ -145,11 +186,20 @@ func Listen(server *http.Server, tlsConfigPath string, logger log.Logger) error handler: handler, } - config, err := getTLSConfig(tlsConfigPath) + c, err := getConfig(tlsConfigPath) + if err != nil { + return err + } + config, err := ConfigToTLSConfig(&c.TLSConfig) switch err { case nil: + withHTTP2 := "with HTTP/2 support" + if c.TLSConfig.DisableHTTP2 { + withHTTP2 = "without HTTP/2 support" + server.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler)) + } // Valid TLS config. - level.Info(logger).Log("msg", "TLS is enabled and it cannot be disabled on the fly.") + level.Info(logger).Log("msg", "TLS "+withHTTP2+" is enabled and it cannot be disabled on the fly.") case errNoTLSConfig: // No TLS config, back to plain HTTP. level.Info(logger).Log("msg", "TLS is disabled and it cannot be enabled on the fly.") @@ -168,3 +218,44 @@ func Listen(server *http.Server, tlsConfigPath string, logger log.Logger) error } return server.ListenAndServeTLS("", "") } + +// For go1.14, unmarshalling is done properly in tls_ciphers.go. +type cipher uint16 + +type curve tls.CurveID + +func (c *curve) UnmarshalYAML(unmarshal func(interface{}) error) error { + var s string + err := unmarshal((*string)(&s)) + if err != nil { + return err + } + switch strings.ToUpper(s) { + case "CURVEP256": + *c = (curve)(tls.CurveP256) + case "CURVEP384": + *c = (curve)(tls.CurveP384) + case "CURVEP521": + *c = (curve)(tls.CurveP521) + case "X25519": + *c = (curve)(tls.X25519) + default: + return errors.New("unknown supported group: " + s) + } + return nil +} + +func (c curve) MarshalYAML() (interface{}, error) { + switch c { + case (curve)(tls.CurveP256): + return "CurveP256", nil + case (curve)(tls.CurveP384): + return "CurveP384", nil + case (curve)(tls.CurveP521): + return "CurveP521", nil + case (curve)(tls.X25519): + return "X25519", nil + default: + return fmt.Sprintf("%v", c), nil + } +} diff --git a/https/tls_config_test.go b/https/tls_config_test.go index 07f412a515..2d92ae5192 100644 --- a/https/tls_config_test.go +++ b/https/tls_config_test.go @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// +build go1.14 + package https import ( @@ -45,6 +47,10 @@ var ( "Bad password": regexp.MustCompile(`hashedSecret too short to be a bcrypted password`), "Unauthorized": regexp.MustCompile(`Unauthorized`), "Forbidden": regexp.MustCompile(`Forbidden`), + "Handshake failure": regexp.MustCompile(`handshake failure`), + "Unknown cipher": regexp.MustCompile(`unknown cipher`), + "Unknown supported group": regexp.MustCompile(`unknown supported group`), + "No HTTP2 cipher": regexp.MustCompile(`TLSConfig.CipherSuites is missing an HTTP/2-required`), } ) @@ -65,14 +71,16 @@ func getPort() string { } type TestInputs struct { - Name string - Server func() *http.Server - UseNilServer bool - YAMLConfigPath string - ExpectedError *regexp.Regexp - UseTLSClient bool - Username string - Password string + Name string + Server func() *http.Server + UseNilServer bool + YAMLConfigPath string + ExpectedError *regexp.Regexp + UseTLSClient bool + CipherSuites []uint16 + CurvePreferences []tls.CurveID + Username string + Password string } func TestYAMLFiles(t *testing.T) { @@ -142,6 +150,16 @@ func TestYAMLFiles(t *testing.T) { YAMLConfigPath: "testdata/tls_config_auth_user_list_invalid.bad.yml", ExpectedError: ErrorMap["Bad password"], }, + { + Name: `invalid config yml (bas cipher)`, + YAMLConfigPath: "testdata/tls_config_noAuth_inventedCiphers.bad.yml", + ExpectedError: ErrorMap["Unknown cipher"], + }, + { + Name: `invalid config yml (bas curves)`, + YAMLConfigPath: "testdata/tls_config_noAuth_inventedCurves.bad.yml", + ExpectedError: ErrorMap["Unknown supported group"], + }, } for _, testInputs := range testTables { t.Run(testInputs.Name, testInputs.Test) @@ -172,6 +190,58 @@ func TestServerBehaviour(t *testing.T) { UseTLSClient: true, ExpectedError: nil, }, + { + Name: `valid tls config yml with all ciphers`, + YAMLConfigPath: "testdata/tls_config_noAuth_allCiphers.good.yml", + UseTLSClient: true, + ExpectedError: nil, + }, + { + Name: `valid tls config yml with some ciphers`, + YAMLConfigPath: "testdata/tls_config_noAuth_someCiphers.good.yml", + UseTLSClient: true, + CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, + ExpectedError: nil, + }, + { + Name: `valid tls config yml with no common cipher`, + YAMLConfigPath: "testdata/tls_config_noAuth_someCiphers.good.yml", + UseTLSClient: true, + CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, + ExpectedError: ErrorMap["Handshake failure"], + }, + { + Name: `valid tls config yml with all curves`, + YAMLConfigPath: "testdata/tls_config_noAuth_allCurves.good.yml", + UseTLSClient: true, + ExpectedError: nil, + }, + { + Name: `valid tls config yml with some curves`, + YAMLConfigPath: "testdata/tls_config_noAuth_someCurves.good.yml", + UseTLSClient: true, + CurvePreferences: []tls.CurveID{tls.CurveP521}, + ExpectedError: nil, + }, + { + Name: `valid tls config yml with no common curves`, + YAMLConfigPath: "testdata/tls_config_noAuth_someCurves.good.yml", + UseTLSClient: true, + CurvePreferences: []tls.CurveID{tls.CurveP384}, + ExpectedError: ErrorMap["Handshake failure"], + }, + { + Name: `valid tls config yml with non-http2 ciphers`, + YAMLConfigPath: "testdata/tls_config_noAuth_noHTTP2.good.yml", + UseTLSClient: true, + ExpectedError: nil, + }, + { + Name: `valid tls config yml with non-http2 ciphers but http2 enabled`, + YAMLConfigPath: "testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml", + UseTLSClient: true, + ExpectedError: ErrorMap["No HTTP2 cipher"], + }, } for _, testInputs := range testTables { t.Run(testInputs.Name, testInputs.Test) @@ -297,6 +367,14 @@ func (test *TestInputs) Test(t *testing.T) { var proto string if test.UseTLSClient { client = getTLSClient() + if len(test.CipherSuites) > 0 { + t := client.Transport.(*http.Transport) + t.TLSClientConfig.CipherSuites = test.CipherSuites + } + if len(test.CurvePreferences) > 0 { + t := client.Transport.(*http.Transport) + t.TLSClientConfig.CurvePreferences = test.CurvePreferences + } proto = "https" } else { client = http.DefaultClient diff --git a/https/tls_version.go b/https/tls_version.go new file mode 100644 index 0000000000..e07320ae6c --- /dev/null +++ b/https/tls_version.go @@ -0,0 +1,53 @@ +// Copyright 2020 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build go1.12 + +package https + +import ( + "crypto/tls" + "strings" + + "github.com/pkg/errors" +) + +func pickMinVersion(s string) (uint16, error) { + switch strings.ToUpper(s) { + case "TLS1.3": + return tls.VersionTLS13, nil + case "TLS1.2", "": + return tls.VersionTLS12, nil + case "TLS1.1": + return tls.VersionTLS11, nil + case "TLS1.0": + return tls.VersionTLS10, nil + default: + return 0, errors.New("unknown min_version: " + s) + } +} + +func pickMaxVersion(s string) (uint16, error) { + switch strings.ToUpper(s) { + case "TLS1.3", "": + return tls.VersionTLS13, nil + case "TLS1.2": + return tls.VersionTLS12, nil + case "TLS1.1": + return tls.VersionTLS11, nil + case "TLS1.0": + return tls.VersionTLS10, nil + default: + return 0, errors.New("unknown max_version: " + s) + } +} diff --git a/https/tls_version_go111.go b/https/tls_version_go111.go new file mode 100644 index 0000000000..57b8f79439 --- /dev/null +++ b/https/tls_version_go111.go @@ -0,0 +1,49 @@ +// Copyright 2020 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !go1.12 + +package https + +import ( + "crypto/tls" + "strings" + + "github.com/pkg/errors" +) + +func pickMinVersion(s string) (uint16, error) { + switch strings.ToUpper(s) { + case "TLS1.2", "": + return tls.VersionTLS12, nil + case "TLS1.1": + return tls.VersionTLS11, nil + case "TLS1.0": + return tls.VersionTLS10, nil + default: + return 0, errors.New("unknown min_version: " + s) + } +} + +func pickMaxVersion(s string) (uint16, error) { + switch strings.ToUpper(s) { + case "TLS1.2", "": + return tls.VersionTLS12, nil + case "TLS1.1": + return tls.VersionTLS11, nil + case "TLS1.0": + return tls.VersionTLS10, nil + default: + return 0, errors.New("unknown max_version: " + s) + } +} From b8dcf86d23f3c7b44559dce4aa79e995dcf554e7 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Mon, 4 May 2020 20:56:51 +0200 Subject: [PATCH 02/15] Update based on Brian's feedback Signed-off-by: Julien Pivotto --- https/README.md | 8 +-- .../tls_config_noAuth_allCurves.good.yml | 2 +- .../tls_config_noAuth_inventedCurves.bad.yml | 2 +- .../tls_config_noAuth_noHTTP2.good.yml | 1 + .../tls_config_noAuth_someCurves.good.yml | 2 +- https/tls_config.go | 40 ++++++++------- https/tls_config_test.go | 4 +- https/tls_version.go | 6 +-- https/tls_version_go111.go | 49 ------------------- 9 files changed, 37 insertions(+), 77 deletions(-) delete mode 100644 https/tls_version_go111.go diff --git a/https/README.md b/https/README.md index 919d428e60..9b86a501d2 100644 --- a/https/README.md +++ b/https/README.md @@ -38,9 +38,6 @@ tls_config: [ cipher_suites: - ] ] - # Disable HTTP/2 support. This can not be toggled on the fly. - [ disable_http2: | default = false ] - # prefer_server_cipher_suites controls whether the server selects the # client's most preferred ciphersuite, or the server's most preferred # ciphersuite. If true then the server's preference, as expressed in @@ -56,6 +53,11 @@ tls_config: [ supported_groups: - ] ] +http_config: + # Disable HTTP/2 support. HTTP is always disabled in HTTP. This can not be + # toggled on the fly. + [ disable_http2: | default = false ] + # List of usernames and hashed passwords that have full access to the web # server via basic authentication. If empty, no basic authentication is # required. Passwords are hashed with bcrypt. diff --git a/https/testdata/tls_config_noAuth_allCurves.good.yml b/https/testdata/tls_config_noAuth_allCurves.good.yml index 1c9d4baee4..54ccf8b2c1 100644 --- a/https/testdata/tls_config_noAuth_allCurves.good.yml +++ b/https/testdata/tls_config_noAuth_allCurves.good.yml @@ -3,7 +3,7 @@ tls_config : key_file : "testdata/server.key" client_auth_type : "VerifyClientCertIfGiven" client_ca_file : "testdata/tls-ca-chain.pem" - supported_groups: + curve_preferences: - CurveP256 - CurveP384 - CurveP521 diff --git a/https/testdata/tls_config_noAuth_inventedCurves.bad.yml b/https/testdata/tls_config_noAuth_inventedCurves.bad.yml index 7d30c889ab..e7af52467b 100644 --- a/https/testdata/tls_config_noAuth_inventedCurves.bad.yml +++ b/https/testdata/tls_config_noAuth_inventedCurves.bad.yml @@ -3,5 +3,5 @@ tls_config : key_file : "testdata/server.key" client_auth_type : "VerifyClientCertIfGiven" client_ca_file : "testdata/tls-ca-chain.pem" - supported_groups: + curve_preferences: - CurveP257 diff --git a/https/testdata/tls_config_noAuth_noHTTP2.good.yml b/https/testdata/tls_config_noAuth_noHTTP2.good.yml index 6b38478411..e1db9e1b95 100644 --- a/https/testdata/tls_config_noAuth_noHTTP2.good.yml +++ b/https/testdata/tls_config_noAuth_noHTTP2.good.yml @@ -6,4 +6,5 @@ tls_config : cipher_suites: - TLS_RSA_WITH_AES_128_CBC_SHA max_version: TLS1.2 +http_config: disable_http2: true diff --git a/https/testdata/tls_config_noAuth_someCurves.good.yml b/https/testdata/tls_config_noAuth_someCurves.good.yml index 07e5646df1..86aea710da 100644 --- a/https/testdata/tls_config_noAuth_someCurves.good.yml +++ b/https/testdata/tls_config_noAuth_someCurves.good.yml @@ -4,5 +4,5 @@ tls_config : client_auth_type : "VerifyClientCertIfGiven" client_ca_file : "testdata/tls-ca-chain.pem" min_version: TLS1.3 - supported_groups: + curve_preferences: - CurveP521 diff --git a/https/tls_config.go b/https/tls_config.go index 9e1884baa8..a9abfdd3db 100644 --- a/https/tls_config.go +++ b/https/tls_config.go @@ -34,8 +34,9 @@ var ( ) type Config struct { - TLSConfig TLSStruct `yaml:"tls_config"` - Users map[string]config_util.Secret `yaml:"basic_auth_users"` + TLSConfig TLSStruct `yaml:"tls_config"` + HTTPConfig HTTPStruct `yaml:"http_config"` + Users map[string]config_util.Secret `yaml:"basic_auth_users"` } type TLSStruct struct { @@ -44,14 +45,17 @@ type TLSStruct struct { ClientAuth string `yaml:"client_auth_type"` ClientCAs string `yaml:"client_ca_file"` CipherSuites []cipher `yaml:"cipher_suites"` - CurveIDs []curve `yaml:"supported_groups"` + CurvePreferences []curve `yaml:"curve_preferences"` MinVersion string `yaml:"min_version"` MaxVersion string `yaml:"max_version"` PreferServerCipherSuites bool `yaml:"prefer_server_cipher_suites"` - DisableHTTP2 bool `yaml:"disable_http2"` SessionTicketsDisabled bool `yaml:"session_tickets_disabled"` } +type HTTPStruct struct { + DisableHTTP2 bool `yaml:"disable_http2"` +} + func getConfig(configPath string) (*Config, error) { content, err := ioutil.ReadFile(configPath) if err != nil { @@ -79,6 +83,7 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) { if c.TLSCertPath == "" { return nil, errors.New("missing cert_file") } + if c.TLSKeyPath == "" { return nil, errors.New("missing key_file") } @@ -91,6 +96,11 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) { return &cert, nil } + // Confirm that certificate and key paths are valid. + if _, err := loadCert(); err != nil { + return nil, err + } + minVersion, err := pickMinVersion(c.MinVersion) if err != nil { return nil, err @@ -108,10 +118,6 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) { SessionTicketsDisabled: c.SessionTicketsDisabled, } - // Confirm that certificate and key paths are valid. - if _, err := loadCert(); err != nil { - return nil, err - } cfg.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) { return loadCert() } @@ -124,12 +130,12 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) { cfg.CipherSuites = cf } - var sg []tls.CurveID - for _, c := range c.CurveIDs { - sg = append(sg, (tls.CurveID)(c)) + var cp []tls.CurveID + for _, c := range c.CurvePreferences { + cp = append(cp, (tls.CurveID)(c)) } - if len(sg) > 0 { - cfg.CurvePreferences = sg + if len(cp) > 0 { + cfg.CurvePreferences = cp } if c.ClientCAs != "" { @@ -193,13 +199,13 @@ func Listen(server *http.Server, tlsConfigPath string, logger log.Logger) error config, err := ConfigToTLSConfig(&c.TLSConfig) switch err { case nil: - withHTTP2 := "with HTTP/2 support" - if c.TLSConfig.DisableHTTP2 { - withHTTP2 = "without HTTP/2 support" + withHTTP2 := "enabled" + if c.HTTPConfig.DisableHTTP2 { + withHTTP2 = "disabled" server.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler)) } // Valid TLS config. - level.Info(logger).Log("msg", "TLS "+withHTTP2+" is enabled and it cannot be disabled on the fly.") + level.Info(logger).Log("msg", "TLS is enabled and it cannot be disabled on the fly.", "http2", withHTTP2) case errNoTLSConfig: // No TLS config, back to plain HTTP. level.Info(logger).Log("msg", "TLS is disabled and it cannot be enabled on the fly.") diff --git a/https/tls_config_test.go b/https/tls_config_test.go index 2d92ae5192..716b426b01 100644 --- a/https/tls_config_test.go +++ b/https/tls_config_test.go @@ -151,12 +151,12 @@ func TestYAMLFiles(t *testing.T) { ExpectedError: ErrorMap["Bad password"], }, { - Name: `invalid config yml (bas cipher)`, + Name: `invalid config yml (bad cipher)`, YAMLConfigPath: "testdata/tls_config_noAuth_inventedCiphers.bad.yml", ExpectedError: ErrorMap["Unknown cipher"], }, { - Name: `invalid config yml (bas curves)`, + Name: `invalid config yml (bad curves)`, YAMLConfigPath: "testdata/tls_config_noAuth_inventedCurves.bad.yml", ExpectedError: ErrorMap["Unknown supported group"], }, diff --git a/https/tls_version.go b/https/tls_version.go index e07320ae6c..3471480eb8 100644 --- a/https/tls_version.go +++ b/https/tls_version.go @@ -11,8 +11,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build go1.12 - package https import ( @@ -23,10 +21,11 @@ import ( ) func pickMinVersion(s string) (uint16, error) { - switch strings.ToUpper(s) { + switch s { case "TLS1.3": return tls.VersionTLS13, nil case "TLS1.2", "": + // This is the default value. return tls.VersionTLS12, nil case "TLS1.1": return tls.VersionTLS11, nil @@ -40,6 +39,7 @@ func pickMinVersion(s string) (uint16, error) { func pickMaxVersion(s string) (uint16, error) { switch strings.ToUpper(s) { case "TLS1.3", "": + // This is the default value. return tls.VersionTLS13, nil case "TLS1.2": return tls.VersionTLS12, nil diff --git a/https/tls_version_go111.go b/https/tls_version_go111.go deleted file mode 100644 index 57b8f79439..0000000000 --- a/https/tls_version_go111.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2020 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// +build !go1.12 - -package https - -import ( - "crypto/tls" - "strings" - - "github.com/pkg/errors" -) - -func pickMinVersion(s string) (uint16, error) { - switch strings.ToUpper(s) { - case "TLS1.2", "": - return tls.VersionTLS12, nil - case "TLS1.1": - return tls.VersionTLS11, nil - case "TLS1.0": - return tls.VersionTLS10, nil - default: - return 0, errors.New("unknown min_version: " + s) - } -} - -func pickMaxVersion(s string) (uint16, error) { - switch strings.ToUpper(s) { - case "TLS1.2", "": - return tls.VersionTLS12, nil - case "TLS1.1": - return tls.VersionTLS11, nil - case "TLS1.0": - return tls.VersionTLS10, nil - default: - return 0, errors.New("unknown max_version: " + s) - } -} From 857b9310bd2f66d3e9091a50e2818c011e899b97 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Mon, 4 May 2020 21:02:05 +0200 Subject: [PATCH 03/15] Address more comments Signed-off-by: Julien Pivotto --- https/README.md | 49 +++++++------------------------------------- https/tls_ciphers.go | 2 -- https/tls_version.go | 3 +-- 3 files changed, 8 insertions(+), 46 deletions(-) diff --git a/https/README.md b/https/README.md index 9b86a501d2..42a0520fad 100644 --- a/https/README.md +++ b/https/README.md @@ -34,9 +34,10 @@ tls_config: # List of supported cipher suites for TLS versions up to TLS 1.2. If empty, # Go default cipher suites are used. Available cipher suites are documented - # below. + # in the go documentation: + # https://golang.org/pkg/crypto/tls/#pkg-constants [ cipher_suites: - - ] ] + [ - ] ] # prefer_server_cipher_suites controls whether the server selects the # client's most preferred ciphersuite, or the server's most preferred @@ -49,9 +50,10 @@ tls_config: [ session_tickets_disabled: | default = false ] # Elliptic curves that will be used in an ECDHE handshake, in preference - # order. Available supported groups are documented below. - [ supported_groups: - - ] ] + # order. Available curves are documented in the go documentation: + # https://golang.org/pkg/crypto/tls/#CurveID + [ curve_preferences: + [ - ] ] http_config: # Disable HTTP/2 support. HTTP is always disabled in HTTP. This can not be @@ -81,40 +83,3 @@ hash. A higher cost will en up slowing down the authentication process. Depending on the machine, a cost of 10 will take about ~70ms where a cost of 18 can take up to a few seconds. That hash will be computed on every password-protected request. - - -## Available cipher suites - -List of available cipher suites for TLS up to 1.2 (we only permit -ciphersuites marked by go as 'secure'): - -- TLS_RSA_WITH_3DES_EDE_CBC_SHA -- TLS_RSA_WITH_AES_128_CBC_SHA -- TLS_RSA_WITH_AES_256_CBC_SHA -- TLS_RSA_WITH_AES_128_GCM_SHA256 -- TLS_RSA_WITH_AES_256_GCM_SHA384 -- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA -- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA -- TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA -- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA -- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA -- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 -- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 -- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 -- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 -- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 -- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 - -List of available cipher suites for TLS 1.3 (TLS 1.3 ciphersuites are not -configurable): - -- TLS_AES_128_GCM_SHA256 -- TLS_AES_256_GCM_SHA384 -- TLS_CHACHA20_POLY1305_SHA256 - -## Available supported groups - -- CurveP256 -- CurveP384 -- CurveP521 -- X25519 diff --git a/https/tls_ciphers.go b/https/tls_ciphers.go index 1773fa19b6..7dd01dbc9b 100644 --- a/https/tls_ciphers.go +++ b/https/tls_ciphers.go @@ -17,7 +17,6 @@ package https import ( "crypto/tls" - "strings" "github.com/pkg/errors" ) @@ -28,7 +27,6 @@ func (c *cipher) UnmarshalYAML(unmarshal func(interface{}) error) error { if err != nil { return err } - s = strings.ToUpper(s) for _, cs := range tls.CipherSuites() { if cs.Name == s { *c = (cipher)(cs.ID) diff --git a/https/tls_version.go b/https/tls_version.go index 3471480eb8..a933cbf342 100644 --- a/https/tls_version.go +++ b/https/tls_version.go @@ -15,7 +15,6 @@ package https import ( "crypto/tls" - "strings" "github.com/pkg/errors" ) @@ -37,7 +36,7 @@ func pickMinVersion(s string) (uint16, error) { } func pickMaxVersion(s string) (uint16, error) { - switch strings.ToUpper(s) { + switch s { case "TLS1.3", "": // This is the default value. return tls.VersionTLS13, nil From ac546eb78e35f187068526238cc304f7e1f6581b Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Mon, 4 May 2020 21:04:46 +0200 Subject: [PATCH 04/15] Use go names Signed-off-by: Julien Pivotto --- https/README.md | 4 ++-- .../testdata/tls_config_noAuth_noHTTP2.good.yml | 2 +- .../tls_config_noAuth_noHTTP2Cipher.bad.yml | 2 +- .../tls_config_noAuth_someCiphers.good.yml | 4 ++-- .../tls_config_noAuth_someCurves.good.yml | 2 +- https/tls_version.go | 16 ++++++++-------- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/https/README.md b/https/README.md index 42a0520fad..7c945fe246 100644 --- a/https/README.md +++ b/https/README.md @@ -27,10 +27,10 @@ tls_config: [ client_ca_file: ] # Minimum TLS version that is acceptable. - [ min_version: | default = "TLS1.2" ] + [ min_version: | default = "TLS12" ] # Maximum TLS version that is acceptable. - [ max_version: | default = "TLS1.3" ] + [ max_version: | default = "TLS13" ] # List of supported cipher suites for TLS versions up to TLS 1.2. If empty, # Go default cipher suites are used. Available cipher suites are documented diff --git a/https/testdata/tls_config_noAuth_noHTTP2.good.yml b/https/testdata/tls_config_noAuth_noHTTP2.good.yml index e1db9e1b95..b850a506fe 100644 --- a/https/testdata/tls_config_noAuth_noHTTP2.good.yml +++ b/https/testdata/tls_config_noAuth_noHTTP2.good.yml @@ -5,6 +5,6 @@ tls_config : client_ca_file : "testdata/tls-ca-chain.pem" cipher_suites: - TLS_RSA_WITH_AES_128_CBC_SHA - max_version: TLS1.2 + max_version: TLS12 http_config: disable_http2: true diff --git a/https/testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml b/https/testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml index 2eb82f4ed6..da66a7dc36 100644 --- a/https/testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml +++ b/https/testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml @@ -5,4 +5,4 @@ tls_config : client_ca_file : "testdata/tls-ca-chain.pem" cipher_suites: - TLS_RSA_WITH_AES_128_CBC_SHA - max_version: TLS1.2 + max_version: TLS12 diff --git a/https/testdata/tls_config_noAuth_someCiphers.good.yml b/https/testdata/tls_config_noAuth_someCiphers.good.yml index 2347449322..c74a267293 100644 --- a/https/testdata/tls_config_noAuth_someCiphers.good.yml +++ b/https/testdata/tls_config_noAuth_someCiphers.good.yml @@ -7,5 +7,5 @@ tls_config : - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - TLS_CHACHA20_POLY1305_SHA256 - min_version: TLS1.2 - max_version: TLS1.2 + min_version: TLS12 + max_version: TLS12 diff --git a/https/testdata/tls_config_noAuth_someCurves.good.yml b/https/testdata/tls_config_noAuth_someCurves.good.yml index 86aea710da..43439894db 100644 --- a/https/testdata/tls_config_noAuth_someCurves.good.yml +++ b/https/testdata/tls_config_noAuth_someCurves.good.yml @@ -3,6 +3,6 @@ tls_config : key_file : "testdata/server.key" client_auth_type : "VerifyClientCertIfGiven" client_ca_file : "testdata/tls-ca-chain.pem" - min_version: TLS1.3 + min_version: TLS13 curve_preferences: - CurveP521 diff --git a/https/tls_version.go b/https/tls_version.go index a933cbf342..cb7053ac96 100644 --- a/https/tls_version.go +++ b/https/tls_version.go @@ -21,14 +21,14 @@ import ( func pickMinVersion(s string) (uint16, error) { switch s { - case "TLS1.3": + case "TLS13": return tls.VersionTLS13, nil - case "TLS1.2", "": + case "TLS12", "": // This is the default value. return tls.VersionTLS12, nil - case "TLS1.1": + case "TLS11": return tls.VersionTLS11, nil - case "TLS1.0": + case "TLS10": return tls.VersionTLS10, nil default: return 0, errors.New("unknown min_version: " + s) @@ -37,14 +37,14 @@ func pickMinVersion(s string) (uint16, error) { func pickMaxVersion(s string) (uint16, error) { switch s { - case "TLS1.3", "": + case "TLS13", "": // This is the default value. return tls.VersionTLS13, nil - case "TLS1.2": + case "TLS12": return tls.VersionTLS12, nil - case "TLS1.1": + case "TLS11": return tls.VersionTLS11, nil - case "TLS1.0": + case "TLS10": return tls.VersionTLS10, nil default: return 0, errors.New("unknown max_version: " + s) From c55df317939e0313eea16de41571151d3f0e0324 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Tue, 5 May 2020 21:45:44 +0200 Subject: [PATCH 05/15] Address Brian's comments Signed-off-by: Julien Pivotto --- https/README.md | 6 +- .../tls_config_noAuth_noHTTP2.good.yml | 2 +- https/tls_ciphers.go | 41 ------------ https/tls_config.go | 64 +++++++++++-------- https/tls_config_test.go | 4 +- 5 files changed, 43 insertions(+), 74 deletions(-) delete mode 100644 https/tls_ciphers.go diff --git a/https/README.md b/https/README.md index 7c945fe246..15c4c3d356 100644 --- a/https/README.md +++ b/https/README.md @@ -55,9 +55,9 @@ tls_config: [ curve_preferences: [ - ] ] -http_config: - # Disable HTTP/2 support. HTTP is always disabled in HTTP. This can not be - # toggled on the fly. +http_server_config: + # Disable HTTP/2 support. Note that HTTP/2 is only supported with TLS. + # This can not be changed on the fly. [ disable_http2: | default = false ] # List of usernames and hashed passwords that have full access to the web diff --git a/https/testdata/tls_config_noAuth_noHTTP2.good.yml b/https/testdata/tls_config_noAuth_noHTTP2.good.yml index b850a506fe..77ece0232c 100644 --- a/https/testdata/tls_config_noAuth_noHTTP2.good.yml +++ b/https/testdata/tls_config_noAuth_noHTTP2.good.yml @@ -6,5 +6,5 @@ tls_config : cipher_suites: - TLS_RSA_WITH_AES_128_CBC_SHA max_version: TLS12 -http_config: +http_server_config: disable_http2: true diff --git a/https/tls_ciphers.go b/https/tls_ciphers.go deleted file mode 100644 index 7dd01dbc9b..0000000000 --- a/https/tls_ciphers.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2020 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// +build go1.14 - -package https - -import ( - "crypto/tls" - - "github.com/pkg/errors" -) - -func (c *cipher) UnmarshalYAML(unmarshal func(interface{}) error) error { - var s string - err := unmarshal((*string)(&s)) - if err != nil { - return err - } - for _, cs := range tls.CipherSuites() { - if cs.Name == s { - *c = (cipher)(cs.ID) - return nil - } - } - return errors.New("unknown cipher: " + s) -} - -func (c cipher) MarshalYAML() (interface{}, error) { - return tls.CipherSuiteName((uint16)(c)), nil -} diff --git a/https/tls_config.go b/https/tls_config.go index a9abfdd3db..77ca84cbb5 100644 --- a/https/tls_config.go +++ b/https/tls_config.go @@ -20,7 +20,6 @@ import ( "fmt" "io/ioutil" "net/http" - "strings" "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" @@ -35,7 +34,7 @@ var ( type Config struct { TLSConfig TLSStruct `yaml:"tls_config"` - HTTPConfig HTTPStruct `yaml:"http_config"` + HTTPConfig HTTPStruct `yaml:"http_server_config"` Users map[string]config_util.Secret `yaml:"basic_auth_users"` } @@ -225,43 +224,54 @@ func Listen(server *http.Server, tlsConfigPath string, logger log.Logger) error return server.ListenAndServeTLS("", "") } -// For go1.14, unmarshalling is done properly in tls_ciphers.go. type cipher uint16 +func (c *cipher) UnmarshalYAML(unmarshal func(interface{}) error) error { + var s string + err := unmarshal((*string)(&s)) + if err != nil { + return err + } + for _, cs := range tls.CipherSuites() { + if cs.Name == s { + *c = (cipher)(cs.ID) + return nil + } + } + return errors.New("unknown cipher: " + s) +} + +func (c cipher) MarshalYAML() (interface{}, error) { + return tls.CipherSuiteName((uint16)(c)), nil +} + type curve tls.CurveID +var curves = map[string]curve{ + "CurveP256": (curve)(tls.CurveP256), + "CurveP384": (curve)(tls.CurveP384), + "CurveP521": (curve)(tls.CurveP521), + "X25519": (curve)(tls.X25519), +} + func (c *curve) UnmarshalYAML(unmarshal func(interface{}) error) error { var s string err := unmarshal((*string)(&s)) if err != nil { return err } - switch strings.ToUpper(s) { - case "CURVEP256": - *c = (curve)(tls.CurveP256) - case "CURVEP384": - *c = (curve)(tls.CurveP384) - case "CURVEP521": - *c = (curve)(tls.CurveP521) - case "X25519": - *c = (curve)(tls.X25519) - default: - return errors.New("unknown supported group: " + s) + if curveid, ok := curves[s]; ok { + *c = curveid + return nil } - return nil + return errors.New("unknown curve: " + s) } -func (c curve) MarshalYAML() (interface{}, error) { - switch c { - case (curve)(tls.CurveP256): - return "CurveP256", nil - case (curve)(tls.CurveP384): - return "CurveP384", nil - case (curve)(tls.CurveP521): - return "CurveP521", nil - case (curve)(tls.X25519): - return "X25519", nil - default: - return fmt.Sprintf("%v", c), nil +func (c *curve) MarshalYAML() (interface{}, error) { + for s, curveid := range curves { + if *c == curveid { + return s, nil + } } + return fmt.Sprintf("%v", c), nil } diff --git a/https/tls_config_test.go b/https/tls_config_test.go index 716b426b01..ffd6d29f1f 100644 --- a/https/tls_config_test.go +++ b/https/tls_config_test.go @@ -49,7 +49,7 @@ var ( "Forbidden": regexp.MustCompile(`Forbidden`), "Handshake failure": regexp.MustCompile(`handshake failure`), "Unknown cipher": regexp.MustCompile(`unknown cipher`), - "Unknown supported group": regexp.MustCompile(`unknown supported group`), + "Unknown curve": regexp.MustCompile(`unknown curve`), "No HTTP2 cipher": regexp.MustCompile(`TLSConfig.CipherSuites is missing an HTTP/2-required`), } ) @@ -158,7 +158,7 @@ func TestYAMLFiles(t *testing.T) { { Name: `invalid config yml (bad curves)`, YAMLConfigPath: "testdata/tls_config_noAuth_inventedCurves.bad.yml", - ExpectedError: ErrorMap["Unknown supported group"], + ExpectedError: ErrorMap["Unknown curve"], }, } for _, testInputs := range testTables { From 881d633756fbe76996e067eb7ed6d27ec14f7b7f Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Wed, 6 May 2020 10:35:40 +0200 Subject: [PATCH 06/15] Rename to tls_server_config Signed-off-by: Julien Pivotto --- https/README.md | 2 +- https/testdata/tls_config_auth_clientCAs_invalid.bad.yml | 2 +- https/testdata/tls_config_auth_clientCAs_missing.bad.yml | 2 +- https/testdata/tls_config_auth_user_list_invalid.bad.yml | 2 +- https/testdata/tls_config_junk_key.yml | 2 +- https/testdata/tls_config_noAuth.bad.yml | 2 +- https/testdata/tls_config_noAuth.good.blocking.yml | 2 +- https/testdata/tls_config_noAuth.good.yml | 2 +- https/testdata/tls_config_noAuth_allCiphers.good.yml | 2 +- https/testdata/tls_config_noAuth_allCurves.good.yml | 2 +- https/testdata/tls_config_noAuth_certPath_empty.bad.yml | 2 +- https/testdata/tls_config_noAuth_certPath_invalid.bad.yml | 2 +- https/testdata/tls_config_noAuth_certPath_keyPath_empty.bad.yml | 2 +- .../testdata/tls_config_noAuth_certPath_keyPath_invalid.bad.yml | 2 +- https/testdata/tls_config_noAuth_inventedCiphers.bad.yml | 2 +- https/testdata/tls_config_noAuth_inventedCurves.bad.yml | 2 +- https/testdata/tls_config_noAuth_keyPath_empty.bad.yml | 2 +- https/testdata/tls_config_noAuth_keyPath_invalid.bad.yml | 2 +- https/testdata/tls_config_noAuth_noHTTP2.good.yml | 2 +- https/testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml | 2 +- https/testdata/tls_config_noAuth_someCiphers.good.yml | 2 +- https/testdata/tls_config_noAuth_someCurves.good.yml | 2 +- https/testdata/tls_config_users.good.yml | 2 +- https/tls_config.go | 2 +- 24 files changed, 24 insertions(+), 24 deletions(-) diff --git a/https/README.md b/https/README.md index 15c4c3d356..1b094d79cc 100644 --- a/https/README.md +++ b/https/README.md @@ -14,7 +14,7 @@ The config file should be written in YAML format, and is reloaded on each connec ## Sample Config ``` -tls_config: +tls_server_config: # Certificate and key files for server to use to authenticate to client. cert_file: key_file: diff --git a/https/testdata/tls_config_auth_clientCAs_invalid.bad.yml b/https/testdata/tls_config_auth_clientCAs_invalid.bad.yml index 742889fbf0..91ec706862 100644 --- a/https/testdata/tls_config_auth_clientCAs_invalid.bad.yml +++ b/https/testdata/tls_config_auth_clientCAs_invalid.bad.yml @@ -1,4 +1,4 @@ -tls_config : +tls_server_config : cert_file : "testdata/server.crt" key_file : "testdata/server.key" client_ca_file : "somefile" \ No newline at end of file diff --git a/https/testdata/tls_config_auth_clientCAs_missing.bad.yml b/https/testdata/tls_config_auth_clientCAs_missing.bad.yml index 5f172a96a3..fea2a67f89 100644 --- a/https/testdata/tls_config_auth_clientCAs_missing.bad.yml +++ b/https/testdata/tls_config_auth_clientCAs_missing.bad.yml @@ -1,4 +1,4 @@ -tls_config : +tls_server_config : cert_file : "testdata/server.crt" key_file : "testdata/server.key" client_auth_type : "RequireAndVerifyClientCert" \ No newline at end of file diff --git a/https/testdata/tls_config_auth_user_list_invalid.bad.yml b/https/testdata/tls_config_auth_user_list_invalid.bad.yml index 90c1d959ed..7324573175 100644 --- a/https/testdata/tls_config_auth_user_list_invalid.bad.yml +++ b/https/testdata/tls_config_auth_user_list_invalid.bad.yml @@ -1,4 +1,4 @@ -tls_config : +tls_server_config : cert_file : "testdata/server.crt" key_file : "testdata/server.key" basic_auth_users: diff --git a/https/testdata/tls_config_junk_key.yml b/https/testdata/tls_config_junk_key.yml index acb2cc3dfa..77f553469f 100644 --- a/https/testdata/tls_config_junk_key.yml +++ b/https/testdata/tls_config_junk_key.yml @@ -1,2 +1,2 @@ -tls_config : +tls_server_config : cert_filse: "testdata/server.crt" diff --git a/https/testdata/tls_config_noAuth.bad.yml b/https/testdata/tls_config_noAuth.bad.yml index afba27713e..f309180681 100644 --- a/https/testdata/tls_config_noAuth.bad.yml +++ b/https/testdata/tls_config_noAuth.bad.yml @@ -1,4 +1,4 @@ -tls_config : +tls_server_config : cert_file : "testdata/server.crt" key_file : "testdata/server.key" client_ca_file : "testdata/tls-ca-chain.pem" diff --git a/https/testdata/tls_config_noAuth.good.blocking.yml b/https/testdata/tls_config_noAuth.good.blocking.yml index 3a21424252..43e47ca817 100644 --- a/https/testdata/tls_config_noAuth.good.blocking.yml +++ b/https/testdata/tls_config_noAuth.good.blocking.yml @@ -1,4 +1,4 @@ -tls_config : +tls_server_config : cert_file : "testdata/server.crt" key_file : "testdata/server.key" client_auth_type : "RequireAndVerifyClientCert" diff --git a/https/testdata/tls_config_noAuth.good.yml b/https/testdata/tls_config_noAuth.good.yml index d762d8e67d..33b6a680d9 100644 --- a/https/testdata/tls_config_noAuth.good.yml +++ b/https/testdata/tls_config_noAuth.good.yml @@ -1,4 +1,4 @@ -tls_config : +tls_server_config : cert_file : "testdata/server.crt" key_file : "testdata/server.key" client_auth_type : "VerifyClientCertIfGiven" diff --git a/https/testdata/tls_config_noAuth_allCiphers.good.yml b/https/testdata/tls_config_noAuth_allCiphers.good.yml index cb49515ac6..e16aec15af 100644 --- a/https/testdata/tls_config_noAuth_allCiphers.good.yml +++ b/https/testdata/tls_config_noAuth_allCiphers.good.yml @@ -1,4 +1,4 @@ -tls_config : +tls_server_config : cert_file : "testdata/server.crt" key_file : "testdata/server.key" client_auth_type : "VerifyClientCertIfGiven" diff --git a/https/testdata/tls_config_noAuth_allCurves.good.yml b/https/testdata/tls_config_noAuth_allCurves.good.yml index 54ccf8b2c1..e727402a5f 100644 --- a/https/testdata/tls_config_noAuth_allCurves.good.yml +++ b/https/testdata/tls_config_noAuth_allCurves.good.yml @@ -1,4 +1,4 @@ -tls_config : +tls_server_config : cert_file : "testdata/server.crt" key_file : "testdata/server.key" client_auth_type : "VerifyClientCertIfGiven" diff --git a/https/testdata/tls_config_noAuth_certPath_empty.bad.yml b/https/testdata/tls_config_noAuth_certPath_empty.bad.yml index f7aaa942f3..b9739c04f1 100644 --- a/https/testdata/tls_config_noAuth_certPath_empty.bad.yml +++ b/https/testdata/tls_config_noAuth_certPath_empty.bad.yml @@ -1,3 +1,3 @@ -tls_config : +tls_server_config : cert_file : "" key_file : "testdata/server.key" \ No newline at end of file diff --git a/https/testdata/tls_config_noAuth_certPath_invalid.bad.yml b/https/testdata/tls_config_noAuth_certPath_invalid.bad.yml index 09344f94d5..b2f46d93e3 100644 --- a/https/testdata/tls_config_noAuth_certPath_invalid.bad.yml +++ b/https/testdata/tls_config_noAuth_certPath_invalid.bad.yml @@ -1,3 +1,3 @@ -tls_config : +tls_server_config : cert_file : "somefile" key_file : "testdata/server.key" \ No newline at end of file diff --git a/https/testdata/tls_config_noAuth_certPath_keyPath_empty.bad.yml b/https/testdata/tls_config_noAuth_certPath_keyPath_empty.bad.yml index 1511b5a77b..4e366adfc4 100644 --- a/https/testdata/tls_config_noAuth_certPath_keyPath_empty.bad.yml +++ b/https/testdata/tls_config_noAuth_certPath_keyPath_empty.bad.yml @@ -1,4 +1,4 @@ -tls_config : +tls_server_config : cert_file : "" key_file : "" client_auth_type: "x" diff --git a/https/testdata/tls_config_noAuth_certPath_keyPath_invalid.bad.yml b/https/testdata/tls_config_noAuth_certPath_keyPath_invalid.bad.yml index 972e4574a6..ab0a262e31 100644 --- a/https/testdata/tls_config_noAuth_certPath_keyPath_invalid.bad.yml +++ b/https/testdata/tls_config_noAuth_certPath_keyPath_invalid.bad.yml @@ -1,3 +1,3 @@ -tls_config : +tls_server_config : cert_file : "somefile" key_file : "somefile" \ No newline at end of file diff --git a/https/testdata/tls_config_noAuth_inventedCiphers.bad.yml b/https/testdata/tls_config_noAuth_inventedCiphers.bad.yml index f809e6d74d..1c5b28e1bb 100644 --- a/https/testdata/tls_config_noAuth_inventedCiphers.bad.yml +++ b/https/testdata/tls_config_noAuth_inventedCiphers.bad.yml @@ -1,4 +1,4 @@ -tls_config : +tls_server_config : cert_file : "testdata/server.crt" key_file : "testdata/server.key" client_auth_type : "VerifyClientCertIfGiven" diff --git a/https/testdata/tls_config_noAuth_inventedCurves.bad.yml b/https/testdata/tls_config_noAuth_inventedCurves.bad.yml index e7af52467b..16de7381e0 100644 --- a/https/testdata/tls_config_noAuth_inventedCurves.bad.yml +++ b/https/testdata/tls_config_noAuth_inventedCurves.bad.yml @@ -1,4 +1,4 @@ -tls_config : +tls_server_config : cert_file : "testdata/server.crt" key_file : "testdata/server.key" client_auth_type : "VerifyClientCertIfGiven" diff --git a/https/testdata/tls_config_noAuth_keyPath_empty.bad.yml b/https/testdata/tls_config_noAuth_keyPath_empty.bad.yml index 87a52652d0..d9970298d5 100644 --- a/https/testdata/tls_config_noAuth_keyPath_empty.bad.yml +++ b/https/testdata/tls_config_noAuth_keyPath_empty.bad.yml @@ -1,3 +1,3 @@ -tls_config : +tls_server_config : cert_file : "testdata/server.crt" key_file : "" \ No newline at end of file diff --git a/https/testdata/tls_config_noAuth_keyPath_invalid.bad.yml b/https/testdata/tls_config_noAuth_keyPath_invalid.bad.yml index b3985f37b7..2b9d37f787 100644 --- a/https/testdata/tls_config_noAuth_keyPath_invalid.bad.yml +++ b/https/testdata/tls_config_noAuth_keyPath_invalid.bad.yml @@ -1,3 +1,3 @@ -tls_config : +tls_server_config : cert_file : "testdata/server.cert" key_file : "somefile" \ No newline at end of file diff --git a/https/testdata/tls_config_noAuth_noHTTP2.good.yml b/https/testdata/tls_config_noAuth_noHTTP2.good.yml index 77ece0232c..724eb0293c 100644 --- a/https/testdata/tls_config_noAuth_noHTTP2.good.yml +++ b/https/testdata/tls_config_noAuth_noHTTP2.good.yml @@ -1,4 +1,4 @@ -tls_config : +tls_server_config : cert_file : "testdata/server.crt" key_file : "testdata/server.key" client_auth_type : "VerifyClientCertIfGiven" diff --git a/https/testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml b/https/testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml index da66a7dc36..2d6723a721 100644 --- a/https/testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml +++ b/https/testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml @@ -1,4 +1,4 @@ -tls_config : +tls_server_config : cert_file : "testdata/server.crt" key_file : "testdata/server.key" client_auth_type : "VerifyClientCertIfGiven" diff --git a/https/testdata/tls_config_noAuth_someCiphers.good.yml b/https/testdata/tls_config_noAuth_someCiphers.good.yml index c74a267293..a3c57ce06e 100644 --- a/https/testdata/tls_config_noAuth_someCiphers.good.yml +++ b/https/testdata/tls_config_noAuth_someCiphers.good.yml @@ -1,4 +1,4 @@ -tls_config : +tls_server_config : cert_file : "testdata/server.crt" key_file : "testdata/server.key" client_auth_type : "VerifyClientCertIfGiven" diff --git a/https/testdata/tls_config_noAuth_someCurves.good.yml b/https/testdata/tls_config_noAuth_someCurves.good.yml index 43439894db..2e860fc8db 100644 --- a/https/testdata/tls_config_noAuth_someCurves.good.yml +++ b/https/testdata/tls_config_noAuth_someCurves.good.yml @@ -1,4 +1,4 @@ -tls_config : +tls_server_config : cert_file : "testdata/server.crt" key_file : "testdata/server.key" client_auth_type : "VerifyClientCertIfGiven" diff --git a/https/testdata/tls_config_users.good.yml b/https/testdata/tls_config_users.good.yml index 278177d0b4..8c686fc152 100644 --- a/https/testdata/tls_config_users.good.yml +++ b/https/testdata/tls_config_users.good.yml @@ -1,4 +1,4 @@ -tls_config : +tls_server_config : cert_file : "testdata/server.crt" key_file : "testdata/server.key" basic_auth_users: diff --git a/https/tls_config.go b/https/tls_config.go index 77ca84cbb5..9b36b87316 100644 --- a/https/tls_config.go +++ b/https/tls_config.go @@ -33,7 +33,7 @@ var ( ) type Config struct { - TLSConfig TLSStruct `yaml:"tls_config"` + TLSConfig TLSStruct `yaml:"tls_server_config"` HTTPConfig HTTPStruct `yaml:"http_server_config"` Users map[string]config_util.Secret `yaml:"basic_auth_users"` } From 55802bab0e714ab1a3b6eed6d91bf2c27b4d226d Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Wed, 6 May 2020 10:44:05 +0200 Subject: [PATCH 07/15] rm tls_version Signed-off-by: Julien Pivotto --- https/tls_config.go | 68 ++++++++++++++++++++++++++++++++++++++++++-- https/tls_version.go | 52 --------------------------------- 2 files changed, 66 insertions(+), 54 deletions(-) delete mode 100644 https/tls_version.go diff --git a/https/tls_config.go b/https/tls_config.go index 9b36b87316..7dc168d266 100644 --- a/https/tls_config.go +++ b/https/tls_config.go @@ -100,12 +100,12 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) { return nil, err } - minVersion, err := pickMinVersion(c.MinVersion) + minVersion, err := pickMinTLSVersion(c.MinVersion) if err != nil { return nil, err } - maxVersion, err := pickMaxVersion(c.MaxVersion) + maxVersion, err := pickMaxTLSVersion(c.MaxVersion) if err != nil { return nil, err } @@ -275,3 +275,67 @@ func (c *curve) MarshalYAML() (interface{}, error) { } return fmt.Sprintf("%v", c), nil } + +func pickMinTLSVersion(s string) (uint16, error) { + switch s { + case "TLS13": + return tls.VersionTLS13, nil + case "TLS12", "": + // This is the default value. + return tls.VersionTLS12, nil + case "TLS11": + return tls.VersionTLS11, nil + case "TLS10": + return tls.VersionTLS10, nil + default: + return 0, errors.New("unknown min_version: " + s) + } +} + +func pickMaxTLSVersion(s string) (uint16, error) { + switch s { + case "TLS13", "": + // This is the default value. + return tls.VersionTLS13, nil + case "TLS12": + return tls.VersionTLS12, nil + case "TLS11": + return tls.VersionTLS11, nil + case "TLS10": + return tls.VersionTLS10, nil + default: + return 0, errors.New("unknown max_version: " + s) + } +} + +func pickMinVersion(s string) (uint16, error) { + switch s { + case "TLS13": + return tls.VersionTLS13, nil + case "TLS12", "": + // This is the default value. + return tls.VersionTLS12, nil + case "TLS11": + return tls.VersionTLS11, nil + case "TLS10": + return tls.VersionTLS10, nil + default: + return 0, errors.New("unknown min_version: " + s) + } +} + +func pickMaxVersion(s string) (uint16, error) { + switch s { + case "TLS13", "": + // This is the default value. + return tls.VersionTLS13, nil + case "TLS12": + return tls.VersionTLS12, nil + case "TLS11": + return tls.VersionTLS11, nil + case "TLS10": + return tls.VersionTLS10, nil + default: + return 0, errors.New("unknown max_version: " + s) + } +} diff --git a/https/tls_version.go b/https/tls_version.go deleted file mode 100644 index cb7053ac96..0000000000 --- a/https/tls_version.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2020 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package https - -import ( - "crypto/tls" - - "github.com/pkg/errors" -) - -func pickMinVersion(s string) (uint16, error) { - switch s { - case "TLS13": - return tls.VersionTLS13, nil - case "TLS12", "": - // This is the default value. - return tls.VersionTLS12, nil - case "TLS11": - return tls.VersionTLS11, nil - case "TLS10": - return tls.VersionTLS10, nil - default: - return 0, errors.New("unknown min_version: " + s) - } -} - -func pickMaxVersion(s string) (uint16, error) { - switch s { - case "TLS13", "": - // This is the default value. - return tls.VersionTLS13, nil - case "TLS12": - return tls.VersionTLS12, nil - case "TLS11": - return tls.VersionTLS11, nil - case "TLS10": - return tls.VersionTLS10, nil - default: - return 0, errors.New("unknown max_version: " + s) - } -} From 671ea73269157dae62af4b0cf6d6cca10ac34576 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Wed, 6 May 2020 10:45:52 +0200 Subject: [PATCH 08/15] removed unused function Signed-off-by: Julien Pivotto --- https/tls_config.go | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/https/tls_config.go b/https/tls_config.go index 7dc168d266..7d28300271 100644 --- a/https/tls_config.go +++ b/https/tls_config.go @@ -307,35 +307,3 @@ func pickMaxTLSVersion(s string) (uint16, error) { return 0, errors.New("unknown max_version: " + s) } } - -func pickMinVersion(s string) (uint16, error) { - switch s { - case "TLS13": - return tls.VersionTLS13, nil - case "TLS12", "": - // This is the default value. - return tls.VersionTLS12, nil - case "TLS11": - return tls.VersionTLS11, nil - case "TLS10": - return tls.VersionTLS10, nil - default: - return 0, errors.New("unknown min_version: " + s) - } -} - -func pickMaxVersion(s string) (uint16, error) { - switch s { - case "TLS13", "": - // This is the default value. - return tls.VersionTLS13, nil - case "TLS12": - return tls.VersionTLS12, nil - case "TLS11": - return tls.VersionTLS11, nil - case "TLS10": - return tls.VersionTLS10, nil - default: - return 0, errors.New("unknown max_version: " + s) - } -} From b9749cf94c140dcb2b3d43d04c3f2d9f691f2525 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Wed, 6 May 2020 12:02:32 +0200 Subject: [PATCH 09/15] log http2 as bool Signed-off-by: Julien Pivotto --- https/tls_config.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/https/tls_config.go b/https/tls_config.go index 7d28300271..7aa5ad34c4 100644 --- a/https/tls_config.go +++ b/https/tls_config.go @@ -172,7 +172,7 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) { // Listen starts the server on the given address. If tlsConfigPath isn't empty the server connection will be started using TLS. func Listen(server *http.Server, tlsConfigPath string, logger log.Logger) error { if tlsConfigPath == "" { - level.Info(logger).Log("msg", "TLS is disabled and it cannot be enabled on the fly.") + level.Info(logger).Log("msg", "TLS is disabled and it cannot be enabled on the fly.", "http2", false) return server.ListenAndServe() } @@ -198,16 +198,14 @@ func Listen(server *http.Server, tlsConfigPath string, logger log.Logger) error config, err := ConfigToTLSConfig(&c.TLSConfig) switch err { case nil: - withHTTP2 := "enabled" if c.HTTPConfig.DisableHTTP2 { - withHTTP2 = "disabled" server.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler)) } // Valid TLS config. - level.Info(logger).Log("msg", "TLS is enabled and it cannot be disabled on the fly.", "http2", withHTTP2) + level.Info(logger).Log("msg", "TLS is enabled and it cannot be disabled on the fly.", "http2", !c.HTTPConfig.DisableHTTP2) case errNoTLSConfig: // No TLS config, back to plain HTTP. - level.Info(logger).Log("msg", "TLS is disabled and it cannot be enabled on the fly.") + level.Info(logger).Log("msg", "TLS is disabled and it cannot be enabled on the fly.", "http2", false) return server.ListenAndServe() default: // Invalid TLS config. From c3c3ba937236c22ff04539aed4922bf838e1bbc7 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Thu, 7 May 2020 15:57:05 +0200 Subject: [PATCH 10/15] remove session tickets Signed-off-by: Julien Pivotto --- https/README.md | 6 +----- https/tls_config.go | 2 -- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/https/README.md b/https/README.md index 1b094d79cc..0c8c4cb4d4 100644 --- a/https/README.md +++ b/https/README.md @@ -42,13 +42,9 @@ tls_server_config: # prefer_server_cipher_suites controls whether the server selects the # client's most preferred ciphersuite, or the server's most preferred # ciphersuite. If true then the server's preference, as expressed in - # the order of elements in CipherSuites, is used. + # the order of elements in cipher_suites, is used. [ prefer_server_cipher_suites: | default = false ] - # session_tickets_disabled may be set to true to disable session ticket and - # PSK (resumption) support. - [ session_tickets_disabled: | default = false ] - # Elliptic curves that will be used in an ECDHE handshake, in preference # order. Available curves are documented in the go documentation: # https://golang.org/pkg/crypto/tls/#CurveID diff --git a/https/tls_config.go b/https/tls_config.go index 7aa5ad34c4..e3bd285765 100644 --- a/https/tls_config.go +++ b/https/tls_config.go @@ -48,7 +48,6 @@ type TLSStruct struct { MinVersion string `yaml:"min_version"` MaxVersion string `yaml:"max_version"` PreferServerCipherSuites bool `yaml:"prefer_server_cipher_suites"` - SessionTicketsDisabled bool `yaml:"session_tickets_disabled"` } type HTTPStruct struct { @@ -114,7 +113,6 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) { MinVersion: minVersion, MaxVersion: maxVersion, PreferServerCipherSuites: c.PreferServerCipherSuites, - SessionTicketsDisabled: c.SessionTicketsDisabled, } cfg.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) { From 1ab1f5b2d8378445b8b6719026ca395b767155d0 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Thu, 7 May 2020 16:25:32 +0200 Subject: [PATCH 11/15] Default to prefer_server_cipher_suites Signed-off-by: Julien Pivotto --- https/README.md | 6 ------ https/tls_config.go | 19 +++++++++---------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/https/README.md b/https/README.md index 0c8c4cb4d4..f7d809e491 100644 --- a/https/README.md +++ b/https/README.md @@ -39,12 +39,6 @@ tls_server_config: [ cipher_suites: [ - ] ] - # prefer_server_cipher_suites controls whether the server selects the - # client's most preferred ciphersuite, or the server's most preferred - # ciphersuite. If true then the server's preference, as expressed in - # the order of elements in cipher_suites, is used. - [ prefer_server_cipher_suites: | default = false ] - # Elliptic curves that will be used in an ECDHE handshake, in preference # order. Available curves are documented in the go documentation: # https://golang.org/pkg/crypto/tls/#CurveID diff --git a/https/tls_config.go b/https/tls_config.go index e3bd285765..7f4ab83a0b 100644 --- a/https/tls_config.go +++ b/https/tls_config.go @@ -39,15 +39,14 @@ type Config struct { } type TLSStruct struct { - TLSCertPath string `yaml:"cert_file"` - TLSKeyPath string `yaml:"key_file"` - ClientAuth string `yaml:"client_auth_type"` - ClientCAs string `yaml:"client_ca_file"` - CipherSuites []cipher `yaml:"cipher_suites"` - CurvePreferences []curve `yaml:"curve_preferences"` - MinVersion string `yaml:"min_version"` - MaxVersion string `yaml:"max_version"` - PreferServerCipherSuites bool `yaml:"prefer_server_cipher_suites"` + TLSCertPath string `yaml:"cert_file"` + TLSKeyPath string `yaml:"key_file"` + ClientAuth string `yaml:"client_auth_type"` + ClientCAs string `yaml:"client_ca_file"` + CipherSuites []cipher `yaml:"cipher_suites"` + CurvePreferences []curve `yaml:"curve_preferences"` + MinVersion string `yaml:"min_version"` + MaxVersion string `yaml:"max_version"` } type HTTPStruct struct { @@ -112,7 +111,7 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) { cfg := &tls.Config{ MinVersion: minVersion, MaxVersion: maxVersion, - PreferServerCipherSuites: c.PreferServerCipherSuites, + PreferServerCipherSuites: true, } cfg.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) { From 0bce4e100c22af45517af4e8b73ed8c78c415f9c Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Thu, 7 May 2020 17:13:45 +0200 Subject: [PATCH 12/15] Use true bool for http2 Signed-off-by: Julien Pivotto --- https/README.md | 4 ++-- https/testdata/tls_config_noAuth_noHTTP2.good.yml | 2 +- https/tls_config.go | 10 ++++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/https/README.md b/https/README.md index f7d809e491..dd579d7b4d 100644 --- a/https/README.md +++ b/https/README.md @@ -46,9 +46,9 @@ tls_server_config: [ - ] ] http_server_config: - # Disable HTTP/2 support. Note that HTTP/2 is only supported with TLS. + # Enable HTTP/2 support. Note that HTTP/2 is only supported with TLS. # This can not be changed on the fly. - [ disable_http2: | default = false ] + [ http2: | default = true ] # List of usernames and hashed passwords that have full access to the web # server via basic authentication. If empty, no basic authentication is diff --git a/https/testdata/tls_config_noAuth_noHTTP2.good.yml b/https/testdata/tls_config_noAuth_noHTTP2.good.yml index 724eb0293c..d962c3d07c 100644 --- a/https/testdata/tls_config_noAuth_noHTTP2.good.yml +++ b/https/testdata/tls_config_noAuth_noHTTP2.good.yml @@ -7,4 +7,4 @@ tls_server_config : - TLS_RSA_WITH_AES_128_CBC_SHA max_version: TLS12 http_server_config: - disable_http2: true + http2: false diff --git a/https/tls_config.go b/https/tls_config.go index 7f4ab83a0b..1fa23cee9c 100644 --- a/https/tls_config.go +++ b/https/tls_config.go @@ -50,7 +50,7 @@ type TLSStruct struct { } type HTTPStruct struct { - DisableHTTP2 bool `yaml:"disable_http2"` + HTTP2 bool `yaml:"http2"` } func getConfig(configPath string) (*Config, error) { @@ -58,7 +58,9 @@ func getConfig(configPath string) (*Config, error) { if err != nil { return nil, err } - c := &Config{} + c := &Config{ + HTTPConfig: HTTPStruct{HTTP2: true}, + } err = yaml.UnmarshalStrict(content, c) return c, err } @@ -195,11 +197,11 @@ func Listen(server *http.Server, tlsConfigPath string, logger log.Logger) error config, err := ConfigToTLSConfig(&c.TLSConfig) switch err { case nil: - if c.HTTPConfig.DisableHTTP2 { + if !c.HTTPConfig.HTTP2 { server.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler)) } // Valid TLS config. - level.Info(logger).Log("msg", "TLS is enabled and it cannot be disabled on the fly.", "http2", !c.HTTPConfig.DisableHTTP2) + level.Info(logger).Log("msg", "TLS is enabled and it cannot be disabled on the fly.", "http2", c.HTTPConfig.HTTP2) case errNoTLSConfig: // No TLS config, back to plain HTTP. level.Info(logger).Log("msg", "TLS is disabled and it cannot be enabled on the fly.", "http2", false) From d1389e26bdb1bbcc5ea89c2247716d7c176b0a59 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Thu, 7 May 2020 18:22:11 +0200 Subject: [PATCH 13/15] Change the unmarshalling of TLS config Signed-off-by: Julien Pivotto --- .../tls_config_noAuth_wrongTLSVersion.bad.yml | 6 ++ https/tls_config.go | 85 +++++++++---------- https/tls_config_test.go | 39 ++++++--- 3 files changed, 72 insertions(+), 58 deletions(-) create mode 100644 https/testdata/tls_config_noAuth_wrongTLSVersion.bad.yml diff --git a/https/testdata/tls_config_noAuth_wrongTLSVersion.bad.yml b/https/testdata/tls_config_noAuth_wrongTLSVersion.bad.yml new file mode 100644 index 0000000000..51a0d6a60d --- /dev/null +++ b/https/testdata/tls_config_noAuth_wrongTLSVersion.bad.yml @@ -0,0 +1,6 @@ +tls_server_config : + cert_file : "testdata/server.crt" + key_file : "testdata/server.key" + client_auth_type : "VerifyClientCertIfGiven" + client_ca_file : "testdata/tls-ca-chain.pem" + min_version: TLS111 diff --git a/https/tls_config.go b/https/tls_config.go index 1fa23cee9c..94239b3a91 100644 --- a/https/tls_config.go +++ b/https/tls_config.go @@ -39,14 +39,14 @@ type Config struct { } type TLSStruct struct { - TLSCertPath string `yaml:"cert_file"` - TLSKeyPath string `yaml:"key_file"` - ClientAuth string `yaml:"client_auth_type"` - ClientCAs string `yaml:"client_ca_file"` - CipherSuites []cipher `yaml:"cipher_suites"` - CurvePreferences []curve `yaml:"curve_preferences"` - MinVersion string `yaml:"min_version"` - MaxVersion string `yaml:"max_version"` + TLSCertPath string `yaml:"cert_file"` + TLSKeyPath string `yaml:"key_file"` + ClientAuth string `yaml:"client_auth_type"` + ClientCAs string `yaml:"client_ca_file"` + CipherSuites []cipher `yaml:"cipher_suites"` + CurvePreferences []curve `yaml:"curve_preferences"` + MinVersion tlsVersion `yaml:"min_version"` + MaxVersion tlsVersion `yaml:"max_version"` } type HTTPStruct struct { @@ -59,6 +59,10 @@ func getConfig(configPath string) (*Config, error) { return nil, err } c := &Config{ + TLSConfig: TLSStruct{ + MinVersion: tls.VersionTLS12, + MaxVersion: tls.VersionTLS13, + }, HTTPConfig: HTTPStruct{HTTP2: true}, } err = yaml.UnmarshalStrict(content, c) @@ -100,19 +104,9 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) { return nil, err } - minVersion, err := pickMinTLSVersion(c.MinVersion) - if err != nil { - return nil, err - } - - maxVersion, err := pickMaxTLSVersion(c.MaxVersion) - if err != nil { - return nil, err - } - cfg := &tls.Config{ - MinVersion: minVersion, - MaxVersion: maxVersion, + MinVersion: (uint16)(c.MinVersion), + MaxVersion: (uint16)(c.MaxVersion), PreferServerCipherSuites: true, } @@ -273,34 +267,33 @@ func (c *curve) MarshalYAML() (interface{}, error) { return fmt.Sprintf("%v", c), nil } -func pickMinTLSVersion(s string) (uint16, error) { - switch s { - case "TLS13": - return tls.VersionTLS13, nil - case "TLS12", "": - // This is the default value. - return tls.VersionTLS12, nil - case "TLS11": - return tls.VersionTLS11, nil - case "TLS10": - return tls.VersionTLS10, nil - default: - return 0, errors.New("unknown min_version: " + s) +type tlsVersion uint16 + +var tlsVersions = map[string]tlsVersion{ + "TLS13": (tlsVersion)(tls.VersionTLS13), + "TLS12": (tlsVersion)(tls.VersionTLS12), + "TLS11": (tlsVersion)(tls.VersionTLS11), + "TLS10": (tlsVersion)(tls.VersionTLS10), +} + +func (tv *tlsVersion) UnmarshalYAML(unmarshal func(interface{}) error) error { + var s string + err := unmarshal((*string)(&s)) + if err != nil { + return err } + if v, ok := tlsVersions[s]; ok { + *tv = v + return nil + } + return errors.New("unknown TLS version: " + s) } -func pickMaxTLSVersion(s string) (uint16, error) { - switch s { - case "TLS13", "": - // This is the default value. - return tls.VersionTLS13, nil - case "TLS12": - return tls.VersionTLS12, nil - case "TLS11": - return tls.VersionTLS11, nil - case "TLS10": - return tls.VersionTLS10, nil - default: - return 0, errors.New("unknown max_version: " + s) +func (tv *tlsVersion) MarshalYAML() (interface{}, error) { + for s, v := range tlsVersions { + if *tv == v { + return s, nil + } } + return fmt.Sprintf("%v", tv), nil } diff --git a/https/tls_config_test.go b/https/tls_config_test.go index ffd6d29f1f..2cee72919b 100644 --- a/https/tls_config_test.go +++ b/https/tls_config_test.go @@ -50,7 +50,9 @@ var ( "Handshake failure": regexp.MustCompile(`handshake failure`), "Unknown cipher": regexp.MustCompile(`unknown cipher`), "Unknown curve": regexp.MustCompile(`unknown curve`), + "Unknown TLS version": regexp.MustCompile(`unknown TLS version`), "No HTTP2 cipher": regexp.MustCompile(`TLSConfig.CipherSuites is missing an HTTP/2-required`), + "Incompatible TLS version": regexp.MustCompile(`protocol version not supported`), } ) @@ -71,16 +73,17 @@ func getPort() string { } type TestInputs struct { - Name string - Server func() *http.Server - UseNilServer bool - YAMLConfigPath string - ExpectedError *regexp.Regexp - UseTLSClient bool - CipherSuites []uint16 - CurvePreferences []tls.CurveID - Username string - Password string + Name string + Server func() *http.Server + UseNilServer bool + YAMLConfigPath string + ExpectedError *regexp.Regexp + UseTLSClient bool + ClientMaxTLSVersion uint16 + CipherSuites []uint16 + CurvePreferences []tls.CurveID + Username string + Password string } func TestYAMLFiles(t *testing.T) { @@ -160,6 +163,11 @@ func TestYAMLFiles(t *testing.T) { YAMLConfigPath: "testdata/tls_config_noAuth_inventedCurves.bad.yml", ExpectedError: ErrorMap["Unknown curve"], }, + { + Name: `invalid config yml (bad TLS version)`, + YAMLConfigPath: "testdata/tls_config_noAuth_wrongTLSVersion.bad.yml", + ExpectedError: ErrorMap["Unknown TLS version"], + }, } for _, testInputs := range testTables { t.Run(testInputs.Name, testInputs.Test) @@ -190,6 +198,13 @@ func TestServerBehaviour(t *testing.T) { UseTLSClient: true, ExpectedError: nil, }, + { + Name: `valid tls config yml with TLS 1.1 client`, + YAMLConfigPath: "testdata/tls_config_noAuth.good.yml", + UseTLSClient: true, + ClientMaxTLSVersion: tls.VersionTLS11, + ExpectedError: ErrorMap["Incompatible TLS version"], + }, { Name: `valid tls config yml with all ciphers`, YAMLConfigPath: "testdata/tls_config_noAuth_allCiphers.good.yml", @@ -367,12 +382,12 @@ func (test *TestInputs) Test(t *testing.T) { var proto string if test.UseTLSClient { client = getTLSClient() + t := client.Transport.(*http.Transport) + t.TLSClientConfig.MaxVersion = test.ClientMaxTLSVersion if len(test.CipherSuites) > 0 { - t := client.Transport.(*http.Transport) t.TLSClientConfig.CipherSuites = test.CipherSuites } if len(test.CurvePreferences) > 0 { - t := client.Transport.(*http.Transport) t.TLSClientConfig.CurvePreferences = test.CurvePreferences } proto = "https" From 2664fb45f23eacd7d118b9b54e9410cc0114ad37 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Fri, 8 May 2020 16:52:15 +0200 Subject: [PATCH 14/15] Add PreferServerCipherSuites Signed-off-by: Julien Pivotto --- https/README.md | 6 ++++++ https/tls_config.go | 24 +++++++++++++----------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/https/README.md b/https/README.md index dd579d7b4d..dd0fa405ad 100644 --- a/https/README.md +++ b/https/README.md @@ -39,6 +39,12 @@ tls_server_config: [ cipher_suites: [ - ] ] + # prefer_server_cipher_suites controls whether the server selects the + # client's most preferred ciphersuite, or the server's most preferred + # ciphersuite. If true then the server's preference, as expressed in + # the order of elements in cipher_suites, is used. + [ prefer_server_cipher_suites: | default = true ] + # Elliptic curves that will be used in an ECDHE handshake, in preference # order. Available curves are documented in the go documentation: # https://golang.org/pkg/crypto/tls/#CurveID diff --git a/https/tls_config.go b/https/tls_config.go index 94239b3a91..e7cc6321b1 100644 --- a/https/tls_config.go +++ b/https/tls_config.go @@ -39,14 +39,15 @@ type Config struct { } type TLSStruct struct { - TLSCertPath string `yaml:"cert_file"` - TLSKeyPath string `yaml:"key_file"` - ClientAuth string `yaml:"client_auth_type"` - ClientCAs string `yaml:"client_ca_file"` - CipherSuites []cipher `yaml:"cipher_suites"` - CurvePreferences []curve `yaml:"curve_preferences"` - MinVersion tlsVersion `yaml:"min_version"` - MaxVersion tlsVersion `yaml:"max_version"` + TLSCertPath string `yaml:"cert_file"` + TLSKeyPath string `yaml:"key_file"` + ClientAuth string `yaml:"client_auth_type"` + ClientCAs string `yaml:"client_ca_file"` + CipherSuites []cipher `yaml:"cipher_suites"` + CurvePreferences []curve `yaml:"curve_preferences"` + MinVersion tlsVersion `yaml:"min_version"` + MaxVersion tlsVersion `yaml:"max_version"` + PreferServerCipherSuites bool `yaml:"prefer_server_cipher_suites"` } type HTTPStruct struct { @@ -60,8 +61,9 @@ func getConfig(configPath string) (*Config, error) { } c := &Config{ TLSConfig: TLSStruct{ - MinVersion: tls.VersionTLS12, - MaxVersion: tls.VersionTLS13, + MinVersion: tls.VersionTLS12, + MaxVersion: tls.VersionTLS13, + PreferServerCipherSuites: true, }, HTTPConfig: HTTPStruct{HTTP2: true}, } @@ -107,7 +109,7 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) { cfg := &tls.Config{ MinVersion: (uint16)(c.MinVersion), MaxVersion: (uint16)(c.MaxVersion), - PreferServerCipherSuites: true, + PreferServerCipherSuites: c.PreferServerCipherSuites, } cfg.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) { From ac38593afc4006debe3825b01a368747cabda3d2 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Sun, 10 May 2020 12:42:21 +0200 Subject: [PATCH 15/15] Test PreferServerCipherSuites Signed-off-by: Julien Pivotto --- .../tls_config_noAuth_someCiphers.good.yml | 3 +- ...config_noAuth_someCiphers_noOrder.good.yml | 11 ++++++ https/tls_config_test.go | 35 +++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 https/testdata/tls_config_noAuth_someCiphers_noOrder.good.yml diff --git a/https/testdata/tls_config_noAuth_someCiphers.good.yml b/https/testdata/tls_config_noAuth_someCiphers.good.yml index a3c57ce06e..aae1e65896 100644 --- a/https/testdata/tls_config_noAuth_someCiphers.good.yml +++ b/https/testdata/tls_config_noAuth_someCiphers.good.yml @@ -4,8 +4,7 @@ tls_server_config : client_auth_type : "VerifyClientCertIfGiven" client_ca_file : "testdata/tls-ca-chain.pem" cipher_suites: - - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - - TLS_CHACHA20_POLY1305_SHA256 min_version: TLS12 max_version: TLS12 diff --git a/https/testdata/tls_config_noAuth_someCiphers_noOrder.good.yml b/https/testdata/tls_config_noAuth_someCiphers_noOrder.good.yml new file mode 100644 index 0000000000..d21c6be070 --- /dev/null +++ b/https/testdata/tls_config_noAuth_someCiphers_noOrder.good.yml @@ -0,0 +1,11 @@ +tls_server_config : + cert_file : "testdata/server.crt" + key_file : "testdata/server.key" + client_auth_type : "VerifyClientCertIfGiven" + client_ca_file : "testdata/tls-ca-chain.pem" + cipher_suites: + - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + prefer_server_cipher_suites: false + min_version: TLS12 + max_version: TLS12 diff --git a/https/tls_config_test.go b/https/tls_config_test.go index 2cee72919b..ccc7a992a2 100644 --- a/https/tls_config_test.go +++ b/https/tls_config_test.go @@ -81,6 +81,7 @@ type TestInputs struct { UseTLSClient bool ClientMaxTLSVersion uint16 CipherSuites []uint16 + ActualCipher uint16 CurvePreferences []tls.CurveID Username string Password string @@ -225,6 +226,28 @@ func TestServerBehaviour(t *testing.T) { CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, ExpectedError: ErrorMap["Handshake failure"], }, + { + Name: `valid tls config yml with multiple client ciphers`, + YAMLConfigPath: "testdata/tls_config_noAuth_someCiphers.good.yml", + UseTLSClient: true, + CipherSuites: []uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + }, + ActualCipher: tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + ExpectedError: nil, + }, + { + Name: `valid tls config yml with multiple client ciphers, client chooses cipher`, + YAMLConfigPath: "testdata/tls_config_noAuth_someCiphers_noOrder.good.yml", + UseTLSClient: true, + CipherSuites: []uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + }, + ActualCipher: tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + ExpectedError: nil, + }, { Name: `valid tls config yml with all curves`, YAMLConfigPath: "testdata/tls_config_noAuth_allCurves.good.yml", @@ -411,6 +434,18 @@ func (test *TestInputs) Test(t *testing.T) { recordConnectionError(err) return } + + if test.ActualCipher != 0 { + if r.TLS.CipherSuite != test.ActualCipher { + recordConnectionError( + fmt.Errorf("bad cipher suite selected. Expected: %s, got: %s", + tls.CipherSuiteName(r.TLS.CipherSuite), + tls.CipherSuiteName(test.ActualCipher), + ), + ) + } + } + body, err := ioutil.ReadAll(r.Body) if err != nil { recordConnectionError(err)