mirror of
				https://github.com/prometheus/node_exporter.git
				synced 2025-08-20 18:33:52 -07:00 
			
		
		
		
	tls: enable the selection of more TLS settings (#1695)
tls: enable the selection of more TLS settings * Rename `tls_config` to `tls_server_config`. * Add new http server config with HTTP/2 enabled by default. Signed-off-by: Julien Pivotto <roidelapluie@inuits.eu>
This commit is contained in:
		
							parent
							
								
									0c532984b7
								
							
						
					
					
						commit
						f87e566df9
					
				| 
						 | 
				
			
			@ -14,18 +14,48 @@ The config file should be written in YAML format, and is reloaded on each connec
 | 
			
		|||
## Sample Config
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
tls_config:
 | 
			
		||||
  # Certificate and key files for server to use to authenticate to client
 | 
			
		||||
tls_server_config:
 | 
			
		||||
  # Certificate and key files for server to use to authenticate to client.
 | 
			
		||||
  cert_file: <filename>
 | 
			
		||||
  key_file: <filename>
 | 
			
		||||
 | 
			
		||||
  # 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: <string> | default = "NoClientCert" ]
 | 
			
		||||
 | 
			
		||||
  # CA certificate for client certificate authentication to the server
 | 
			
		||||
  # CA certificate for client certificate authentication to the server.
 | 
			
		||||
  [ client_ca_file: <filename> ]
 | 
			
		||||
 | 
			
		||||
  # Minimum TLS version that is acceptable.
 | 
			
		||||
  [ min_version: <string> | default = "TLS12" ]
 | 
			
		||||
 | 
			
		||||
  # Maximum TLS version that is acceptable.
 | 
			
		||||
  [ max_version: <string> | 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
 | 
			
		||||
  # in the go documentation:
 | 
			
		||||
  # https://golang.org/pkg/crypto/tls/#pkg-constants
 | 
			
		||||
  [ cipher_suites:
 | 
			
		||||
    [ - <string> ] ]
 | 
			
		||||
 | 
			
		||||
  # 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: <bool> | 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
 | 
			
		||||
  [ curve_preferences:
 | 
			
		||||
    [ - <string> ] ]
 | 
			
		||||
 | 
			
		||||
http_server_config:
 | 
			
		||||
  # Enable HTTP/2 support. Note that HTTP/2 is only supported with TLS.
 | 
			
		||||
  # This can not be changed on the fly.
 | 
			
		||||
  [ http2: <bool> | 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
 | 
			
		||||
# required. Passwords are hashed with bcrypt.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
tls_config :
 | 
			
		||||
tls_server_config :
 | 
			
		||||
  cert_file : "testdata/server.crt"
 | 
			
		||||
  key_file : "testdata/server.key"
 | 
			
		||||
  client_ca_file : "somefile"
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
tls_config :
 | 
			
		||||
tls_server_config :
 | 
			
		||||
  cert_file : "testdata/server.crt"
 | 
			
		||||
  key_file : "testdata/server.key"
 | 
			
		||||
  client_auth_type : "RequireAndVerifyClientCert"
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
tls_config :
 | 
			
		||||
tls_server_config :
 | 
			
		||||
  cert_file : "testdata/server.crt"
 | 
			
		||||
  key_file : "testdata/server.key"
 | 
			
		||||
basic_auth_users:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								https/testdata/tls_config_junk_key.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								https/testdata/tls_config_junk_key.yml
									
									
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,2 +1,2 @@
 | 
			
		|||
tls_config :
 | 
			
		||||
tls_server_config :
 | 
			
		||||
  cert_filse: "testdata/server.crt"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								https/testdata/tls_config_noAuth.bad.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								https/testdata/tls_config_noAuth.bad.yml
									
									
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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" 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
tls_config :
 | 
			
		||||
tls_server_config :
 | 
			
		||||
  cert_file : "testdata/server.crt"
 | 
			
		||||
  key_file : "testdata/server.key"
 | 
			
		||||
  client_auth_type : "RequireAndVerifyClientCert"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								https/testdata/tls_config_noAuth.good.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								https/testdata/tls_config_noAuth.good.yml
									
									
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
tls_config :
 | 
			
		||||
tls_server_config :
 | 
			
		||||
  cert_file : "testdata/server.crt"
 | 
			
		||||
  key_file : "testdata/server.key"
 | 
			
		||||
  client_auth_type : "VerifyClientCertIfGiven"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										26
									
								
								https/testdata/tls_config_noAuth_allCiphers.good.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								https/testdata/tls_config_noAuth_allCiphers.good.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
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_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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								https/testdata/tls_config_noAuth_allCurves.good.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								https/testdata/tls_config_noAuth_allCurves.good.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
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"
 | 
			
		||||
  curve_preferences:
 | 
			
		||||
    - CurveP256
 | 
			
		||||
    - CurveP384
 | 
			
		||||
    - CurveP521
 | 
			
		||||
    - X25519
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,3 @@
 | 
			
		|||
tls_config :
 | 
			
		||||
tls_server_config :
 | 
			
		||||
  cert_file : ""
 | 
			
		||||
  key_file : "testdata/server.key"
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,3 @@
 | 
			
		|||
tls_config :
 | 
			
		||||
tls_server_config :
 | 
			
		||||
  cert_file : "somefile"
 | 
			
		||||
  key_file : "testdata/server.key"
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
tls_config :
 | 
			
		||||
tls_server_config :
 | 
			
		||||
  cert_file : ""
 | 
			
		||||
  key_file : ""
 | 
			
		||||
  client_auth_type: "x"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,3 @@
 | 
			
		|||
tls_config :
 | 
			
		||||
tls_server_config :
 | 
			
		||||
  cert_file : "somefile"
 | 
			
		||||
  key_file : "somefile"
 | 
			
		||||
							
								
								
									
										8
									
								
								https/testdata/tls_config_noAuth_inventedCiphers.bad.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								https/testdata/tls_config_noAuth_inventedCiphers.bad.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
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_ECDSA_WITH_AES_128_GCM_SHA2048
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										7
									
								
								https/testdata/tls_config_noAuth_inventedCurves.bad.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								https/testdata/tls_config_noAuth_inventedCurves.bad.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
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"
 | 
			
		||||
  curve_preferences:
 | 
			
		||||
    - CurveP257
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,3 @@
 | 
			
		|||
tls_config :
 | 
			
		||||
tls_server_config :
 | 
			
		||||
  cert_file : "testdata/server.crt"
 | 
			
		||||
  key_file : ""
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,3 @@
 | 
			
		|||
tls_config :
 | 
			
		||||
tls_server_config :
 | 
			
		||||
  cert_file : "testdata/server.cert"
 | 
			
		||||
  key_file : "somefile"
 | 
			
		||||
							
								
								
									
										10
									
								
								https/testdata/tls_config_noAuth_noHTTP2.good.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								https/testdata/tls_config_noAuth_noHTTP2.good.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
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_RSA_WITH_AES_128_CBC_SHA
 | 
			
		||||
  max_version: TLS12
 | 
			
		||||
http_server_config:
 | 
			
		||||
  http2: false
 | 
			
		||||
							
								
								
									
										8
									
								
								https/testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								https/testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
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_RSA_WITH_AES_128_CBC_SHA
 | 
			
		||||
  max_version: TLS12
 | 
			
		||||
							
								
								
									
										10
									
								
								https/testdata/tls_config_noAuth_someCiphers.good.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								https/testdata/tls_config_noAuth_someCiphers.good.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
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
 | 
			
		||||
  min_version: TLS12
 | 
			
		||||
  max_version: TLS12
 | 
			
		||||
							
								
								
									
										11
									
								
								https/testdata/tls_config_noAuth_someCiphers_noOrder.good.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								https/testdata/tls_config_noAuth_someCiphers_noOrder.good.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
							
								
								
									
										8
									
								
								https/testdata/tls_config_noAuth_someCurves.good.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								https/testdata/tls_config_noAuth_someCurves.good.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
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: TLS13
 | 
			
		||||
  curve_preferences:
 | 
			
		||||
  - CurveP521
 | 
			
		||||
							
								
								
									
										6
									
								
								https/testdata/tls_config_noAuth_wrongTLSVersion.bad.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								https/testdata/tls_config_noAuth_wrongTLSVersion.bad.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
							
								
								
									
										2
									
								
								https/testdata/tls_config_users.good.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								https/testdata/tls_config_users.good.yml
									
									
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
tls_config :
 | 
			
		||||
tls_server_config :
 | 
			
		||||
  cert_file : "testdata/server.crt"
 | 
			
		||||
  key_file : "testdata/server.key"
 | 
			
		||||
basic_auth_users:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,6 +17,7 @@ package https
 | 
			
		|||
import (
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"crypto/x509"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"net/http"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +33,8 @@ 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"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -41,6 +43,15 @@ type TLSStruct struct {
 | 
			
		|||
	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 {
 | 
			
		||||
	HTTP2 bool `yaml:"http2"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getConfig(configPath string) (*Config, error) {
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +59,14 @@ func getConfig(configPath string) (*Config, error) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	c := &Config{}
 | 
			
		||||
	c := &Config{
 | 
			
		||||
		TLSConfig: TLSStruct{
 | 
			
		||||
			MinVersion:               tls.VersionTLS12,
 | 
			
		||||
			MaxVersion:               tls.VersionTLS13,
 | 
			
		||||
			PreferServerCipherSuites: true,
 | 
			
		||||
		},
 | 
			
		||||
		HTTPConfig: HTTPStruct{HTTP2: true},
 | 
			
		||||
	}
 | 
			
		||||
	err = yaml.UnmarshalStrict(content, c)
 | 
			
		||||
	return c, err
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -70,12 +88,11 @@ 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")
 | 
			
		||||
	}
 | 
			
		||||
	cfg := &tls.Config{
 | 
			
		||||
		MinVersion: tls.VersionTLS12,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	loadCert := func() (*tls.Certificate, error) {
 | 
			
		||||
		cert, err := tls.LoadX509KeyPair(c.TLSCertPath, c.TLSKeyPath)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -83,14 +100,38 @@ 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
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cfg := &tls.Config{
 | 
			
		||||
		MinVersion:               (uint16)(c.MinVersion),
 | 
			
		||||
		MaxVersion:               (uint16)(c.MaxVersion),
 | 
			
		||||
		PreferServerCipherSuites: c.PreferServerCipherSuites,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cfg.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
 | 
			
		||||
		return loadCert()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var cf []uint16
 | 
			
		||||
	for _, c := range c.CipherSuites {
 | 
			
		||||
		cf = append(cf, (uint16)(c))
 | 
			
		||||
	}
 | 
			
		||||
	if len(cf) > 0 {
 | 
			
		||||
		cfg.CipherSuites = cf
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var cp []tls.CurveID
 | 
			
		||||
	for _, c := range c.CurvePreferences {
 | 
			
		||||
		cp = append(cp, (tls.CurveID)(c))
 | 
			
		||||
	}
 | 
			
		||||
	if len(cp) > 0 {
 | 
			
		||||
		cfg.CurvePreferences = cp
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if c.ClientCAs != "" {
 | 
			
		||||
		clientCAPool := x509.NewCertPool()
 | 
			
		||||
		clientCAFile, err := ioutil.ReadFile(c.ClientCAs)
 | 
			
		||||
| 
						 | 
				
			
			@ -126,7 +167,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()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -145,14 +186,21 @@ 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:
 | 
			
		||||
		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.")
 | 
			
		||||
		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.")
 | 
			
		||||
		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.
 | 
			
		||||
| 
						 | 
				
			
			@ -168,3 +216,86 @@ func Listen(server *http.Server, tlsConfigPath string, logger log.Logger) error
 | 
			
		|||
	}
 | 
			
		||||
	return server.ListenAndServeTLS("", "")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
	}
 | 
			
		||||
	if curveid, ok := curves[s]; ok {
 | 
			
		||||
		*c = curveid
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return errors.New("unknown curve: " + s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *curve) MarshalYAML() (interface{}, error) {
 | 
			
		||||
	for s, curveid := range curves {
 | 
			
		||||
		if *c == curveid {
 | 
			
		||||
			return s, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return fmt.Sprintf("%v", c), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 (tv *tlsVersion) MarshalYAML() (interface{}, error) {
 | 
			
		||||
	for s, v := range tlsVersions {
 | 
			
		||||
		if *tv == v {
 | 
			
		||||
			return s, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return fmt.Sprintf("%v", tv), nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,12 @@ 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 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,6 +79,10 @@ type TestInputs struct {
 | 
			
		|||
	YAMLConfigPath      string
 | 
			
		||||
	ExpectedError       *regexp.Regexp
 | 
			
		||||
	UseTLSClient        bool
 | 
			
		||||
	ClientMaxTLSVersion uint16
 | 
			
		||||
	CipherSuites        []uint16
 | 
			
		||||
	ActualCipher        uint16
 | 
			
		||||
	CurvePreferences    []tls.CurveID
 | 
			
		||||
	Username            string
 | 
			
		||||
	Password            string
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -142,6 +154,21 @@ func TestYAMLFiles(t *testing.T) {
 | 
			
		|||
			YAMLConfigPath: "testdata/tls_config_auth_user_list_invalid.bad.yml",
 | 
			
		||||
			ExpectedError:  ErrorMap["Bad password"],
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			Name:           `invalid config yml (bad cipher)`,
 | 
			
		||||
			YAMLConfigPath: "testdata/tls_config_noAuth_inventedCiphers.bad.yml",
 | 
			
		||||
			ExpectedError:  ErrorMap["Unknown cipher"],
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			Name:           `invalid config yml (bad curves)`,
 | 
			
		||||
			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)
 | 
			
		||||
| 
						 | 
				
			
			@ -172,6 +199,87 @@ 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",
 | 
			
		||||
			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 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",
 | 
			
		||||
			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 +405,14 @@ 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.TLSClientConfig.CipherSuites = test.CipherSuites
 | 
			
		||||
			}
 | 
			
		||||
			if len(test.CurvePreferences) > 0 {
 | 
			
		||||
				t.TLSClientConfig.CurvePreferences = test.CurvePreferences
 | 
			
		||||
			}
 | 
			
		||||
			proto = "https"
 | 
			
		||||
		} else {
 | 
			
		||||
			client = http.DefaultClient
 | 
			
		||||
| 
						 | 
				
			
			@ -318,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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue