aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Pivotto <roidelapluie@inuits.eu>2020-05-13 20:26:01 +0200
committerGitHub <noreply@github.com>2020-05-13 20:26:01 +0200
commitf87e566df9c790938be2c6e5a64f7b58ea0cefb9 (patch)
tree810eaba738dbc4062470f269babad1cc4663137d
parent0c532984b7a6a00d67de07a9794aacfeec2c11d3 (diff)
downloadprometheus_node_collector-f87e566df9c790938be2c6e5a64f7b58ea0cefb9.tar.bz2
prometheus_node_collector-f87e566df9c790938be2c6e5a64f7b58ea0cefb9.tar.xz
prometheus_node_collector-f87e566df9c790938be2c6e5a64f7b58ea0cefb9.zip
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>
-rw-r--r--https/README.md38
-rw-r--r--https/testdata/tls_config_auth_clientCAs_invalid.bad.yml2
-rw-r--r--https/testdata/tls_config_auth_clientCAs_missing.bad.yml2
-rw-r--r--https/testdata/tls_config_auth_user_list_invalid.bad.yml2
-rw-r--r--https/testdata/tls_config_junk_key.yml2
-rw-r--r--https/testdata/tls_config_noAuth.bad.yml2
-rw-r--r--https/testdata/tls_config_noAuth.good.blocking.yml2
-rw-r--r--https/testdata/tls_config_noAuth.good.yml2
-rw-r--r--https/testdata/tls_config_noAuth_allCiphers.good.yml26
-rw-r--r--https/testdata/tls_config_noAuth_allCurves.good.yml10
-rw-r--r--https/testdata/tls_config_noAuth_certPath_empty.bad.yml2
-rw-r--r--https/testdata/tls_config_noAuth_certPath_invalid.bad.yml2
-rw-r--r--https/testdata/tls_config_noAuth_certPath_keyPath_empty.bad.yml2
-rw-r--r--https/testdata/tls_config_noAuth_certPath_keyPath_invalid.bad.yml2
-rw-r--r--https/testdata/tls_config_noAuth_inventedCiphers.bad.yml8
-rw-r--r--https/testdata/tls_config_noAuth_inventedCurves.bad.yml7
-rw-r--r--https/testdata/tls_config_noAuth_keyPath_empty.bad.yml2
-rw-r--r--https/testdata/tls_config_noAuth_keyPath_invalid.bad.yml2
-rw-r--r--https/testdata/tls_config_noAuth_noHTTP2.good.yml10
-rw-r--r--https/testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml8
-rw-r--r--https/testdata/tls_config_noAuth_someCiphers.good.yml10
-rw-r--r--https/testdata/tls_config_noAuth_someCiphers_noOrder.good.yml11
-rw-r--r--https/testdata/tls_config_noAuth_someCurves.good.yml8
-rw-r--r--https/testdata/tls_config_noAuth_wrongTLSVersion.bad.yml6
-rw-r--r--https/testdata/tls_config_users.good.yml2
-rw-r--r--https/tls_config.go159
-rw-r--r--https/tls_config_test.go144
27 files changed, 433 insertions, 40 deletions
diff --git a/https/README.md b/https/README.md
index 70b321e..dd0fa40 100644
--- a/https/README.md
+++ b/https/README.md
@@ -14,18 +14,48 @@ The config file should be written in YAML format, and is reloaded on each connec
14## Sample Config 14## Sample Config
15 15
16``` 16```
17tls_config: 17tls_server_config:
18 # Certificate and key files for server to use to authenticate to client 18 # Certificate and key files for server to use to authenticate to client.
19 cert_file: <filename> 19 cert_file: <filename>
20 key_file: <filename> 20 key_file: <filename>
21 21
22 # Server policy for client authentication. Maps to ClientAuth Policies 22 # Server policy for client authentication. Maps to ClientAuth Policies.
23 # For more detail on clientAuth options: [ClientAuthType](https://golang.org/pkg/crypto/tls/#ClientAuthType) 23 # For more detail on clientAuth options: [ClientAuthType](https://golang.org/pkg/crypto/tls/#ClientAuthType)
24 [ client_auth_type: <string> | default = "NoClientCert" ] 24 [ client_auth_type: <string> | default = "NoClientCert" ]
25 25
26 # CA certificate for client certificate authentication to the server 26 # CA certificate for client certificate authentication to the server.
27 [ client_ca_file: <filename> ] 27 [ client_ca_file: <filename> ]
28 28
29 # Minimum TLS version that is acceptable.
30 [ min_version: <string> | default = "TLS12" ]
31
32 # Maximum TLS version that is acceptable.
33 [ max_version: <string> | default = "TLS13" ]
34
35 # List of supported cipher suites for TLS versions up to TLS 1.2. If empty,
36 # Go default cipher suites are used. Available cipher suites are documented
37 # in the go documentation:
38 # https://golang.org/pkg/crypto/tls/#pkg-constants
39 [ cipher_suites:
40 [ - <string> ] ]
41
42 # prefer_server_cipher_suites controls whether the server selects the
43 # client's most preferred ciphersuite, or the server's most preferred
44 # ciphersuite. If true then the server's preference, as expressed in
45 # the order of elements in cipher_suites, is used.
46 [ prefer_server_cipher_suites: <bool> | default = true ]
47
48 # Elliptic curves that will be used in an ECDHE handshake, in preference
49 # order. Available curves are documented in the go documentation:
50 # https://golang.org/pkg/crypto/tls/#CurveID
51 [ curve_preferences:
52 [ - <string> ] ]
53
54http_server_config:
55 # Enable HTTP/2 support. Note that HTTP/2 is only supported with TLS.
56 # This can not be changed on the fly.
57 [ http2: <bool> | default = true ]
58
29# List of usernames and hashed passwords that have full access to the web 59# List of usernames and hashed passwords that have full access to the web
30# server via basic authentication. If empty, no basic authentication is 60# server via basic authentication. If empty, no basic authentication is
31# required. Passwords are hashed with bcrypt. 61# required. Passwords are hashed with bcrypt.
diff --git a/https/testdata/tls_config_auth_clientCAs_invalid.bad.yml b/https/testdata/tls_config_auth_clientCAs_invalid.bad.yml
index 742889f..91ec706 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 @@
1tls_config : 1tls_server_config :
2 cert_file : "testdata/server.crt" 2 cert_file : "testdata/server.crt"
3 key_file : "testdata/server.key" 3 key_file : "testdata/server.key"
4 client_ca_file : "somefile" \ No newline at end of file 4 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 5f172a9..fea2a67 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 @@
1tls_config : 1tls_server_config :
2 cert_file : "testdata/server.crt" 2 cert_file : "testdata/server.crt"
3 key_file : "testdata/server.key" 3 key_file : "testdata/server.key"
4 client_auth_type : "RequireAndVerifyClientCert" \ No newline at end of file 4 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 90c1d95..7324573 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 @@
1tls_config : 1tls_server_config :
2 cert_file : "testdata/server.crt" 2 cert_file : "testdata/server.crt"
3 key_file : "testdata/server.key" 3 key_file : "testdata/server.key"
4basic_auth_users: 4basic_auth_users:
diff --git a/https/testdata/tls_config_junk_key.yml b/https/testdata/tls_config_junk_key.yml
index acb2cc3..77f5534 100644
--- a/https/testdata/tls_config_junk_key.yml
+++ b/https/testdata/tls_config_junk_key.yml
@@ -1,2 +1,2 @@
1tls_config : 1tls_server_config :
2 cert_filse: "testdata/server.crt" 2 cert_filse: "testdata/server.crt"
diff --git a/https/testdata/tls_config_noAuth.bad.yml b/https/testdata/tls_config_noAuth.bad.yml
index afba277..f309180 100644
--- a/https/testdata/tls_config_noAuth.bad.yml
+++ b/https/testdata/tls_config_noAuth.bad.yml
@@ -1,4 +1,4 @@
1tls_config : 1tls_server_config :
2 cert_file : "testdata/server.crt" 2 cert_file : "testdata/server.crt"
3 key_file : "testdata/server.key" 3 key_file : "testdata/server.key"
4 client_ca_file : "testdata/tls-ca-chain.pem" 4 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 3a21424..43e47ca 100644
--- a/https/testdata/tls_config_noAuth.good.blocking.yml
+++ b/https/testdata/tls_config_noAuth.good.blocking.yml
@@ -1,4 +1,4 @@
1tls_config : 1tls_server_config :
2 cert_file : "testdata/server.crt" 2 cert_file : "testdata/server.crt"
3 key_file : "testdata/server.key" 3 key_file : "testdata/server.key"
4 client_auth_type : "RequireAndVerifyClientCert" 4 client_auth_type : "RequireAndVerifyClientCert"
diff --git a/https/testdata/tls_config_noAuth.good.yml b/https/testdata/tls_config_noAuth.good.yml
index d762d8e..33b6a68 100644
--- a/https/testdata/tls_config_noAuth.good.yml
+++ b/https/testdata/tls_config_noAuth.good.yml
@@ -1,4 +1,4 @@
1tls_config : 1tls_server_config :
2 cert_file : "testdata/server.crt" 2 cert_file : "testdata/server.crt"
3 key_file : "testdata/server.key" 3 key_file : "testdata/server.key"
4 client_auth_type : "VerifyClientCertIfGiven" 4 client_auth_type : "VerifyClientCertIfGiven"
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 0000000..e16aec1
--- /dev/null
+++ b/https/testdata/tls_config_noAuth_allCiphers.good.yml
@@ -0,0 +1,26 @@
1tls_server_config :
2 cert_file : "testdata/server.crt"
3 key_file : "testdata/server.key"
4 client_auth_type : "VerifyClientCertIfGiven"
5 client_ca_file : "testdata/tls-ca-chain.pem"
6 cipher_suites:
7 - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
8 - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
9 - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
10 - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
11 - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
12 - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
13 - TLS_AES_128_GCM_SHA256
14 - TLS_AES_256_GCM_SHA384
15 - TLS_CHACHA20_POLY1305_SHA256
16 - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
17 - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
18 - TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
19 - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
20 - TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
21 - TLS_RSA_WITH_3DES_EDE_CBC_SHA
22 - TLS_RSA_WITH_AES_128_CBC_SHA
23 - TLS_RSA_WITH_AES_256_CBC_SHA
24 - TLS_RSA_WITH_AES_128_GCM_SHA256
25 - TLS_RSA_WITH_AES_256_GCM_SHA384
26
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 0000000..e727402
--- /dev/null
+++ b/https/testdata/tls_config_noAuth_allCurves.good.yml
@@ -0,0 +1,10 @@
1tls_server_config :
2 cert_file : "testdata/server.crt"
3 key_file : "testdata/server.key"
4 client_auth_type : "VerifyClientCertIfGiven"
5 client_ca_file : "testdata/tls-ca-chain.pem"
6 curve_preferences:
7 - CurveP256
8 - CurveP384
9 - CurveP521
10 - X25519
diff --git a/https/testdata/tls_config_noAuth_certPath_empty.bad.yml b/https/testdata/tls_config_noAuth_certPath_empty.bad.yml
index f7aaa94..b9739c0 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 @@
1tls_config : 1tls_server_config :
2 cert_file : "" 2 cert_file : ""
3 key_file : "testdata/server.key" \ No newline at end of file 3 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 09344f9..b2f46d9 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 @@
1tls_config : 1tls_server_config :
2 cert_file : "somefile" 2 cert_file : "somefile"
3 key_file : "testdata/server.key" \ No newline at end of file 3 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 1511b5a..4e366ad 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 @@
1tls_config : 1tls_server_config :
2 cert_file : "" 2 cert_file : ""
3 key_file : "" 3 key_file : ""
4 client_auth_type: "x" 4 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 972e457..ab0a262 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 @@
1tls_config : 1tls_server_config :
2 cert_file : "somefile" 2 cert_file : "somefile"
3 key_file : "somefile" \ No newline at end of file 3 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
new file mode 100644
index 0000000..1c5b28e
--- /dev/null
+++ b/https/testdata/tls_config_noAuth_inventedCiphers.bad.yml
@@ -0,0 +1,8 @@
1tls_server_config :
2 cert_file : "testdata/server.crt"
3 key_file : "testdata/server.key"
4 client_auth_type : "VerifyClientCertIfGiven"
5 client_ca_file : "testdata/tls-ca-chain.pem"
6 cipher_suites:
7 - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA2048
8
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 0000000..16de738
--- /dev/null
+++ b/https/testdata/tls_config_noAuth_inventedCurves.bad.yml
@@ -0,0 +1,7 @@
1tls_server_config :
2 cert_file : "testdata/server.crt"
3 key_file : "testdata/server.key"
4 client_auth_type : "VerifyClientCertIfGiven"
5 client_ca_file : "testdata/tls-ca-chain.pem"
6 curve_preferences:
7 - CurveP257
diff --git a/https/testdata/tls_config_noAuth_keyPath_empty.bad.yml b/https/testdata/tls_config_noAuth_keyPath_empty.bad.yml
index 87a5265..d997029 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 @@
1tls_config : 1tls_server_config :
2 cert_file : "testdata/server.crt" 2 cert_file : "testdata/server.crt"
3 key_file : "" \ No newline at end of file 3 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 b3985f3..2b9d37f 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 @@
1tls_config : 1tls_server_config :
2 cert_file : "testdata/server.cert" 2 cert_file : "testdata/server.cert"
3 key_file : "somefile" \ No newline at end of file 3 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
new file mode 100644
index 0000000..d962c3d
--- /dev/null
+++ b/https/testdata/tls_config_noAuth_noHTTP2.good.yml
@@ -0,0 +1,10 @@
1tls_server_config :
2 cert_file : "testdata/server.crt"
3 key_file : "testdata/server.key"
4 client_auth_type : "VerifyClientCertIfGiven"
5 client_ca_file : "testdata/tls-ca-chain.pem"
6 cipher_suites:
7 - TLS_RSA_WITH_AES_128_CBC_SHA
8 max_version: TLS12
9http_server_config:
10 http2: false
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 0000000..2d6723a
--- /dev/null
+++ b/https/testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml
@@ -0,0 +1,8 @@
1tls_server_config :
2 cert_file : "testdata/server.crt"
3 key_file : "testdata/server.key"
4 client_auth_type : "VerifyClientCertIfGiven"
5 client_ca_file : "testdata/tls-ca-chain.pem"
6 cipher_suites:
7 - TLS_RSA_WITH_AES_128_CBC_SHA
8 max_version: TLS12
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 0000000..aae1e65
--- /dev/null
+++ b/https/testdata/tls_config_noAuth_someCiphers.good.yml
@@ -0,0 +1,10 @@
1tls_server_config :
2 cert_file : "testdata/server.crt"
3 key_file : "testdata/server.key"
4 client_auth_type : "VerifyClientCertIfGiven"
5 client_ca_file : "testdata/tls-ca-chain.pem"
6 cipher_suites:
7 - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
8 - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
9 min_version: TLS12
10 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 0000000..d21c6be
--- /dev/null
+++ b/https/testdata/tls_config_noAuth_someCiphers_noOrder.good.yml
@@ -0,0 +1,11 @@
1tls_server_config :
2 cert_file : "testdata/server.crt"
3 key_file : "testdata/server.key"
4 client_auth_type : "VerifyClientCertIfGiven"
5 client_ca_file : "testdata/tls-ca-chain.pem"
6 cipher_suites:
7 - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
8 - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
9 prefer_server_cipher_suites: false
10 min_version: TLS12
11 max_version: TLS12
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 0000000..2e860fc
--- /dev/null
+++ b/https/testdata/tls_config_noAuth_someCurves.good.yml
@@ -0,0 +1,8 @@
1tls_server_config :
2 cert_file : "testdata/server.crt"
3 key_file : "testdata/server.key"
4 client_auth_type : "VerifyClientCertIfGiven"
5 client_ca_file : "testdata/tls-ca-chain.pem"
6 min_version: TLS13
7 curve_preferences:
8 - CurveP521
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 0000000..51a0d6a
--- /dev/null
+++ b/https/testdata/tls_config_noAuth_wrongTLSVersion.bad.yml
@@ -0,0 +1,6 @@
1tls_server_config :
2 cert_file : "testdata/server.crt"
3 key_file : "testdata/server.key"
4 client_auth_type : "VerifyClientCertIfGiven"
5 client_ca_file : "testdata/tls-ca-chain.pem"
6 min_version: TLS111
diff --git a/https/testdata/tls_config_users.good.yml b/https/testdata/tls_config_users.good.yml
index 278177d..8c686fc 100644
--- a/https/testdata/tls_config_users.good.yml
+++ b/https/testdata/tls_config_users.good.yml
@@ -1,4 +1,4 @@
1tls_config : 1tls_server_config :
2 cert_file : "testdata/server.crt" 2 cert_file : "testdata/server.crt"
3 key_file : "testdata/server.key" 3 key_file : "testdata/server.key"
4basic_auth_users: 4basic_auth_users:
diff --git a/https/tls_config.go b/https/tls_config.go
index 44e57e9..e7cc632 100644
--- a/https/tls_config.go
+++ b/https/tls_config.go
@@ -17,6 +17,7 @@ package https
17import ( 17import (
18 "crypto/tls" 18 "crypto/tls"
19 "crypto/x509" 19 "crypto/x509"
20 "fmt"
20 "io/ioutil" 21 "io/ioutil"
21 "net/http" 22 "net/http"
22 23
@@ -32,15 +33,25 @@ var (
32) 33)
33 34
34type Config struct { 35type Config struct {
35 TLSConfig TLSStruct `yaml:"tls_config"` 36 TLSConfig TLSStruct `yaml:"tls_server_config"`
36 Users map[string]config_util.Secret `yaml:"basic_auth_users"` 37 HTTPConfig HTTPStruct `yaml:"http_server_config"`
38 Users map[string]config_util.Secret `yaml:"basic_auth_users"`
37} 39}
38 40
39type TLSStruct struct { 41type TLSStruct struct {
40 TLSCertPath string `yaml:"cert_file"` 42 TLSCertPath string `yaml:"cert_file"`
41 TLSKeyPath string `yaml:"key_file"` 43 TLSKeyPath string `yaml:"key_file"`
42 ClientAuth string `yaml:"client_auth_type"` 44 ClientAuth string `yaml:"client_auth_type"`
43 ClientCAs string `yaml:"client_ca_file"` 45 ClientCAs string `yaml:"client_ca_file"`
46 CipherSuites []cipher `yaml:"cipher_suites"`
47 CurvePreferences []curve `yaml:"curve_preferences"`
48 MinVersion tlsVersion `yaml:"min_version"`
49 MaxVersion tlsVersion `yaml:"max_version"`
50 PreferServerCipherSuites bool `yaml:"prefer_server_cipher_suites"`
51}
52
53type HTTPStruct struct {
54 HTTP2 bool `yaml:"http2"`
44} 55}
45 56
46func getConfig(configPath string) (*Config, error) { 57func getConfig(configPath string) (*Config, error) {
@@ -48,7 +59,14 @@ func getConfig(configPath string) (*Config, error) {
48 if err != nil { 59 if err != nil {
49 return nil, err 60 return nil, err
50 } 61 }
51 c := &Config{} 62 c := &Config{
63 TLSConfig: TLSStruct{
64 MinVersion: tls.VersionTLS12,
65 MaxVersion: tls.VersionTLS13,
66 PreferServerCipherSuites: true,
67 },
68 HTTPConfig: HTTPStruct{HTTP2: true},
69 }
52 err = yaml.UnmarshalStrict(content, c) 70 err = yaml.UnmarshalStrict(content, c)
53 return c, err 71 return c, err
54} 72}
@@ -70,12 +88,11 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) {
70 if c.TLSCertPath == "" { 88 if c.TLSCertPath == "" {
71 return nil, errors.New("missing cert_file") 89 return nil, errors.New("missing cert_file")
72 } 90 }
91
73 if c.TLSKeyPath == "" { 92 if c.TLSKeyPath == "" {
74 return nil, errors.New("missing key_file") 93 return nil, errors.New("missing key_file")
75 } 94 }
76 cfg := &tls.Config{ 95
77 MinVersion: tls.VersionTLS12,
78 }
79 loadCert := func() (*tls.Certificate, error) { 96 loadCert := func() (*tls.Certificate, error) {
80 cert, err := tls.LoadX509KeyPair(c.TLSCertPath, c.TLSKeyPath) 97 cert, err := tls.LoadX509KeyPair(c.TLSCertPath, c.TLSKeyPath)
81 if err != nil { 98 if err != nil {
@@ -83,14 +100,38 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) {
83 } 100 }
84 return &cert, nil 101 return &cert, nil
85 } 102 }
103
86 // Confirm that certificate and key paths are valid. 104 // Confirm that certificate and key paths are valid.
87 if _, err := loadCert(); err != nil { 105 if _, err := loadCert(); err != nil {
88 return nil, err 106 return nil, err
89 } 107 }
108
109 cfg := &tls.Config{
110 MinVersion: (uint16)(c.MinVersion),
111 MaxVersion: (uint16)(c.MaxVersion),
112 PreferServerCipherSuites: c.PreferServerCipherSuites,
113 }
114
90 cfg.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) { 115 cfg.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
91 return loadCert() 116 return loadCert()
92 } 117 }
93 118
119 var cf []uint16
120 for _, c := range c.CipherSuites {
121 cf = append(cf, (uint16)(c))
122 }
123 if len(cf) > 0 {
124 cfg.CipherSuites = cf
125 }
126
127 var cp []tls.CurveID
128 for _, c := range c.CurvePreferences {
129 cp = append(cp, (tls.CurveID)(c))
130 }
131 if len(cp) > 0 {
132 cfg.CurvePreferences = cp
133 }
134
94 if c.ClientCAs != "" { 135 if c.ClientCAs != "" {
95 clientCAPool := x509.NewCertPool() 136 clientCAPool := x509.NewCertPool()
96 clientCAFile, err := ioutil.ReadFile(c.ClientCAs) 137 clientCAFile, err := ioutil.ReadFile(c.ClientCAs)
@@ -126,7 +167,7 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) {
126// Listen starts the server on the given address. If tlsConfigPath isn't empty the server connection will be started using TLS. 167// Listen starts the server on the given address. If tlsConfigPath isn't empty the server connection will be started using TLS.
127func Listen(server *http.Server, tlsConfigPath string, logger log.Logger) error { 168func Listen(server *http.Server, tlsConfigPath string, logger log.Logger) error {
128 if tlsConfigPath == "" { 169 if tlsConfigPath == "" {
129 level.Info(logger).Log("msg", "TLS is disabled and it cannot be enabled on the fly.") 170 level.Info(logger).Log("msg", "TLS is disabled and it cannot be enabled on the fly.", "http2", false)
130 return server.ListenAndServe() 171 return server.ListenAndServe()
131 } 172 }
132 173
@@ -145,14 +186,21 @@ func Listen(server *http.Server, tlsConfigPath string, logger log.Logger) error
145 handler: handler, 186 handler: handler,
146 } 187 }
147 188
148 config, err := getTLSConfig(tlsConfigPath) 189 c, err := getConfig(tlsConfigPath)
190 if err != nil {
191 return err
192 }
193 config, err := ConfigToTLSConfig(&c.TLSConfig)
149 switch err { 194 switch err {
150 case nil: 195 case nil:
196 if !c.HTTPConfig.HTTP2 {
197 server.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler))
198 }
151 // Valid TLS config. 199 // Valid TLS config.
152 level.Info(logger).Log("msg", "TLS is enabled and it cannot be disabled on the fly.") 200 level.Info(logger).Log("msg", "TLS is enabled and it cannot be disabled on the fly.", "http2", c.HTTPConfig.HTTP2)
153 case errNoTLSConfig: 201 case errNoTLSConfig:
154 // No TLS config, back to plain HTTP. 202 // No TLS config, back to plain HTTP.
155 level.Info(logger).Log("msg", "TLS is disabled and it cannot be enabled on the fly.") 203 level.Info(logger).Log("msg", "TLS is disabled and it cannot be enabled on the fly.", "http2", false)
156 return server.ListenAndServe() 204 return server.ListenAndServe()
157 default: 205 default:
158 // Invalid TLS config. 206 // Invalid TLS config.
@@ -168,3 +216,86 @@ func Listen(server *http.Server, tlsConfigPath string, logger log.Logger) error
168 } 216 }
169 return server.ListenAndServeTLS("", "") 217 return server.ListenAndServeTLS("", "")
170} 218}
219
220type cipher uint16
221
222func (c *cipher) UnmarshalYAML(unmarshal func(interface{}) error) error {
223 var s string
224 err := unmarshal((*string)(&s))
225 if err != nil {
226 return err
227 }
228 for _, cs := range tls.CipherSuites() {
229 if cs.Name == s {
230 *c = (cipher)(cs.ID)
231 return nil
232 }
233 }
234 return errors.New("unknown cipher: " + s)
235}
236
237func (c cipher) MarshalYAML() (interface{}, error) {
238 return tls.CipherSuiteName((uint16)(c)), nil
239}
240
241type curve tls.CurveID
242
243var curves = map[string]curve{
244 "CurveP256": (curve)(tls.CurveP256),
245 "CurveP384": (curve)(tls.CurveP384),
246 "CurveP521": (curve)(tls.CurveP521),
247 "X25519": (curve)(tls.X25519),
248}
249
250func (c *curve) UnmarshalYAML(unmarshal func(interface{}) error) error {
251 var s string
252 err := unmarshal((*string)(&s))
253 if err != nil {
254 return err
255 }
256 if curveid, ok := curves[s]; ok {
257 *c = curveid
258 return nil
259 }
260 return errors.New("unknown curve: " + s)
261}
262
263func (c *curve) MarshalYAML() (interface{}, error) {
264 for s, curveid := range curves {
265 if *c == curveid {
266 return s, nil
267 }
268 }
269 return fmt.Sprintf("%v", c), nil
270}
271
272type tlsVersion uint16
273
274var tlsVersions = map[string]tlsVersion{
275 "TLS13": (tlsVersion)(tls.VersionTLS13),
276 "TLS12": (tlsVersion)(tls.VersionTLS12),
277 "TLS11": (tlsVersion)(tls.VersionTLS11),
278 "TLS10": (tlsVersion)(tls.VersionTLS10),
279}
280
281func (tv *tlsVersion) UnmarshalYAML(unmarshal func(interface{}) error) error {
282 var s string
283 err := unmarshal((*string)(&s))
284 if err != nil {
285 return err
286 }
287 if v, ok := tlsVersions[s]; ok {
288 *tv = v
289 return nil
290 }
291 return errors.New("unknown TLS version: " + s)
292}
293
294func (tv *tlsVersion) MarshalYAML() (interface{}, error) {
295 for s, v := range tlsVersions {
296 if *tv == v {
297 return s, nil
298 }
299 }
300 return fmt.Sprintf("%v", tv), nil
301}
diff --git a/https/tls_config_test.go b/https/tls_config_test.go
index 07f412a..ccc7a99 100644
--- a/https/tls_config_test.go
+++ b/https/tls_config_test.go
@@ -11,6 +11,8 @@
11// See the License for the specific language governing permissions and 11// See the License for the specific language governing permissions and
12// limitations under the License. 12// limitations under the License.
13 13
14// +build go1.14
15
14package https 16package https
15 17
16import ( 18import (
@@ -45,6 +47,12 @@ var (
45 "Bad password": regexp.MustCompile(`hashedSecret too short to be a bcrypted password`), 47 "Bad password": regexp.MustCompile(`hashedSecret too short to be a bcrypted password`),
46 "Unauthorized": regexp.MustCompile(`Unauthorized`), 48 "Unauthorized": regexp.MustCompile(`Unauthorized`),
47 "Forbidden": regexp.MustCompile(`Forbidden`), 49 "Forbidden": regexp.MustCompile(`Forbidden`),
50 "Handshake failure": regexp.MustCompile(`handshake failure`),
51 "Unknown cipher": regexp.MustCompile(`unknown cipher`),
52 "Unknown curve": regexp.MustCompile(`unknown curve`),
53 "Unknown TLS version": regexp.MustCompile(`unknown TLS version`),
54 "No HTTP2 cipher": regexp.MustCompile(`TLSConfig.CipherSuites is missing an HTTP/2-required`),
55 "Incompatible TLS version": regexp.MustCompile(`protocol version not supported`),
48 } 56 }
49) 57)
50 58
@@ -65,14 +73,18 @@ func getPort() string {
65} 73}
66 74
67type TestInputs struct { 75type TestInputs struct {
68 Name string 76 Name string
69 Server func() *http.Server 77 Server func() *http.Server
70 UseNilServer bool 78 UseNilServer bool
71 YAMLConfigPath string 79 YAMLConfigPath string
72 ExpectedError *regexp.Regexp 80 ExpectedError *regexp.Regexp
73 UseTLSClient bool 81 UseTLSClient bool
74 Username string 82 ClientMaxTLSVersion uint16
75 Password string 83 CipherSuites []uint16
84 ActualCipher uint16
85 CurvePreferences []tls.CurveID
86 Username string
87 Password string
76} 88}
77 89
78func TestYAMLFiles(t *testing.T) { 90func TestYAMLFiles(t *testing.T) {
@@ -142,6 +154,21 @@ func TestYAMLFiles(t *testing.T) {
142 YAMLConfigPath: "testdata/tls_config_auth_user_list_invalid.bad.yml", 154 YAMLConfigPath: "testdata/tls_config_auth_user_list_invalid.bad.yml",
143 ExpectedError: ErrorMap["Bad password"], 155 ExpectedError: ErrorMap["Bad password"],
144 }, 156 },
157 {
158 Name: `invalid config yml (bad cipher)`,
159 YAMLConfigPath: "testdata/tls_config_noAuth_inventedCiphers.bad.yml",
160 ExpectedError: ErrorMap["Unknown cipher"],
161 },
162 {
163 Name: `invalid config yml (bad curves)`,
164 YAMLConfigPath: "testdata/tls_config_noAuth_inventedCurves.bad.yml",
165 ExpectedError: ErrorMap["Unknown curve"],
166 },
167 {
168 Name: `invalid config yml (bad TLS version)`,
169 YAMLConfigPath: "testdata/tls_config_noAuth_wrongTLSVersion.bad.yml",
170 ExpectedError: ErrorMap["Unknown TLS version"],
171 },
145 } 172 }
146 for _, testInputs := range testTables { 173 for _, testInputs := range testTables {
147 t.Run(testInputs.Name, testInputs.Test) 174 t.Run(testInputs.Name, testInputs.Test)
@@ -172,6 +199,87 @@ func TestServerBehaviour(t *testing.T) {
172 UseTLSClient: true, 199 UseTLSClient: true,
173 ExpectedError: nil, 200 ExpectedError: nil,
174 }, 201 },
202 {
203 Name: `valid tls config yml with TLS 1.1 client`,
204 YAMLConfigPath: "testdata/tls_config_noAuth.good.yml",
205 UseTLSClient: true,
206 ClientMaxTLSVersion: tls.VersionTLS11,
207 ExpectedError: ErrorMap["Incompatible TLS version"],
208 },
209 {
210 Name: `valid tls config yml with all ciphers`,
211 YAMLConfigPath: "testdata/tls_config_noAuth_allCiphers.good.yml",
212 UseTLSClient: true,
213 ExpectedError: nil,
214 },
215 {
216 Name: `valid tls config yml with some ciphers`,
217 YAMLConfigPath: "testdata/tls_config_noAuth_someCiphers.good.yml",
218 UseTLSClient: true,
219 CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
220 ExpectedError: nil,
221 },
222 {
223 Name: `valid tls config yml with no common cipher`,
224 YAMLConfigPath: "testdata/tls_config_noAuth_someCiphers.good.yml",
225 UseTLSClient: true,
226 CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
227 ExpectedError: ErrorMap["Handshake failure"],
228 },
229 {
230 Name: `valid tls config yml with multiple client ciphers`,
231 YAMLConfigPath: "testdata/tls_config_noAuth_someCiphers.good.yml",
232 UseTLSClient: true,
233 CipherSuites: []uint16{
234 tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
235 tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
236 },
237 ActualCipher: tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
238 ExpectedError: nil,
239 },
240 {
241 Name: `valid tls config yml with multiple client ciphers, client chooses cipher`,
242 YAMLConfigPath: "testdata/tls_config_noAuth_someCiphers_noOrder.good.yml",
243 UseTLSClient: true,
244 CipherSuites: []uint16{
245 tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
246 tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
247 },
248 ActualCipher: tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
249 ExpectedError: nil,
250 },
251 {
252 Name: `valid tls config yml with all curves`,
253 YAMLConfigPath: "testdata/tls_config_noAuth_allCurves.good.yml",
254 UseTLSClient: true,
255 ExpectedError: nil,
256 },
257 {
258 Name: `valid tls config yml with some curves`,
259 YAMLConfigPath: "testdata/tls_config_noAuth_someCurves.good.yml",
260 UseTLSClient: true,
261 CurvePreferences: []tls.CurveID{tls.CurveP521},
262 ExpectedError: nil,
263 },
264 {
265 Name: `valid tls config yml with no common curves`,
266 YAMLConfigPath: "testdata/tls_config_noAuth_someCurves.good.yml",
267 UseTLSClient: true,
268 CurvePreferences: []tls.CurveID{tls.CurveP384},
269 ExpectedError: ErrorMap["Handshake failure"],
270 },
271 {
272 Name: `valid tls config yml with non-http2 ciphers`,
273 YAMLConfigPath: "testdata/tls_config_noAuth_noHTTP2.good.yml",
274 UseTLSClient: true,
275 ExpectedError: nil,
276 },
277 {
278 Name: `valid tls config yml with non-http2 ciphers but http2 enabled`,
279 YAMLConfigPath: "testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml",
280 UseTLSClient: true,
281 ExpectedError: ErrorMap["No HTTP2 cipher"],
282 },
175 } 283 }
176 for _, testInputs := range testTables { 284 for _, testInputs := range testTables {
177 t.Run(testInputs.Name, testInputs.Test) 285 t.Run(testInputs.Name, testInputs.Test)
@@ -297,6 +405,14 @@ func (test *TestInputs) Test(t *testing.T) {
297 var proto string 405 var proto string
298 if test.UseTLSClient { 406 if test.UseTLSClient {
299 client = getTLSClient() 407 client = getTLSClient()
408 t := client.Transport.(*http.Transport)
409 t.TLSClientConfig.MaxVersion = test.ClientMaxTLSVersion
410 if len(test.CipherSuites) > 0 {
411 t.TLSClientConfig.CipherSuites = test.CipherSuites
412 }
413 if len(test.CurvePreferences) > 0 {
414 t.TLSClientConfig.CurvePreferences = test.CurvePreferences
415 }
300 proto = "https" 416 proto = "https"
301 } else { 417 } else {
302 client = http.DefaultClient 418 client = http.DefaultClient
@@ -318,6 +434,18 @@ func (test *TestInputs) Test(t *testing.T) {
318 recordConnectionError(err) 434 recordConnectionError(err)
319 return 435 return
320 } 436 }
437
438 if test.ActualCipher != 0 {
439 if r.TLS.CipherSuite != test.ActualCipher {
440 recordConnectionError(
441 fmt.Errorf("bad cipher suite selected. Expected: %s, got: %s",
442 tls.CipherSuiteName(r.TLS.CipherSuite),
443 tls.CipherSuiteName(test.ActualCipher),
444 ),
445 )
446 }
447 }
448
321 body, err := ioutil.ReadAll(r.Body) 449 body, err := ioutil.ReadAll(r.Body)
322 if err != nil { 450 if err != nil {
323 recordConnectionError(err) 451 recordConnectionError(err)