aboutsummaryrefslogtreecommitdiff
path: root/https
diff options
context:
space:
mode:
authorksherryBAE <44226893+ksherryBAE@users.noreply.github.com>2019-11-15 23:12:57 +0000
committerBen Kochie <superq@gmail.com>2019-11-16 00:12:57 +0100
commitaede04172cbcd072629e0a5f43cd0435e26a28d4 (patch)
treeb8752e10fa80cc2b2ad0aa655529fb67223ad3f2 /https
parent20fe5bfb5be4caf3c8c11533b7fb35cb97d810f5 (diff)
downloadprometheus_node_collector-aede04172cbcd072629e0a5f43cd0435e26a28d4.tar.bz2
prometheus_node_collector-aede04172cbcd072629e0a5f43cd0435e26a28d4.tar.xz
prometheus_node_collector-aede04172cbcd072629e0a5f43cd0435e26a28d4.zip
Adding TLS to node exporter - cleaner version (#1277)
Add support for https connections. Signed-off-by: ksherryBAE <kieran.sherry@baesystems.com> Signed-off-by: James Ritchie <james.g.ritchie@baesystems.com> Signed-off-by: Simon Pasquier <spasquie@redhat.com> Signed-off-by: Ben RIdley <benridley29@gmail.com>
Diffstat (limited to 'https')
-rw-r--r--https/README.md24
-rw-r--r--https/testdata/server.crt96
-rw-r--r--https/testdata/server.key28
-rw-r--r--https/testdata/tls-ca-chain.pem173
-rw-r--r--https/testdata/tls_config_auth_clientCAs_invalid.bad.yml4
-rw-r--r--https/testdata/tls_config_auth_clientCAs_missing.bad.yml4
-rw-r--r--https/testdata/tls_config_empty.yml0
-rw-r--r--https/testdata/tls_config_junk.yml20
-rw-r--r--https/testdata/tls_config_noAuth.bad.yml4
-rw-r--r--https/testdata/tls_config_noAuth.good.blocking.yml5
-rw-r--r--https/testdata/tls_config_noAuth.good.yml5
-rw-r--r--https/testdata/tls_config_noAuth_certPath_empty.bad.yml3
-rw-r--r--https/testdata/tls_config_noAuth_certPath_invalid.bad.yml3
-rw-r--r--https/testdata/tls_config_noAuth_certPath_keyPath_empty.bad.yml3
-rw-r--r--https/testdata/tls_config_noAuth_certPath_keyPath_invalid.bad.yml3
-rw-r--r--https/testdata/tls_config_noAuth_keyPath_empty.bad.yml3
-rw-r--r--https/testdata/tls_config_noAuth_keyPath_invalid.bad.yml3
-rw-r--r--https/tls_config.go123
-rw-r--r--https/tls_config_test.go362
-rw-r--r--https/web-config.yml10
20 files changed, 876 insertions, 0 deletions
diff --git a/https/README.md b/https/README.md
new file mode 100644
index 0000000..b8c7ac4
--- /dev/null
+++ b/https/README.md
@@ -0,0 +1,24 @@
1# HTTPS Package for Prometheus
2
3The `https` directory contains a Go package and a sample configuration file for running `node_exporter` with HTTPS instead of HTTP.
4When running a server with TLS use the flag `--web.config`
5
6e.g. `./node_exporter --web.config="web-config.yml"`
7If the config is kept within the https directory.
8
9The config file should be written in YAML format, and is reloaded on each connection to check for new certificates and/or authentication policy.
10
11##Sample Config:
12```
13tlsConfig :
14 # Certificate and key files for server to use to authenticate to client
15 tlsCertPath : <filename>
16 tlsKeyPath : <filename>
17
18 # Server policy for client authentication. Maps to ClientAuth Policies
19 # For more detail on clientAuth options: [ClientAuthType](https://golang.org/pkg/crypto/tls/#ClientAuthType)
20 [ clientAuth : <string> | default = "NoClientCert" ]
21
22 # CA certificate for client certificate authentication to the server
23 [ clientCAs : <filename> ]
24```
diff --git a/https/testdata/server.crt b/https/testdata/server.crt
new file mode 100644
index 0000000..2ead969
--- /dev/null
+++ b/https/testdata/server.crt
@@ -0,0 +1,96 @@
1Certificate:
2 Data:
3 Version: 3 (0x2)
4 Serial Number: 1 (0x1)
5 Signature Algorithm: sha1WithRSAEncryption
6 Issuer: C=US, O=Prometheus, OU=Prometheus Certificate Authority, CN=Prometheus TLS CA
7 Validity
8 Not Before: Apr 5 08:06:57 2019 GMT
9 Not After : Mar 26 08:06:57 2059 GMT
10 Subject: C=US, O=Prometheus, CN=prometheus.example.com
11 Subject Public Key Info:
12 Public Key Algorithm: rsaEncryption
13 RSA Public-Key: (2048 bit)
14 Modulus:
15 00:bd:6c:b6:7f:d1:2f:be:e4:41:eb:5d:ff:50:78:
16 03:2b:76:03:da:01:48:20:13:90:66:c9:ce:6e:06:
17 e5:fa:2d:0d:c0:b0:46:28:44:10:a0:61:79:87:a2:
18 98:4c:29:fa:f9:bb:0f:44:c7:90:5c:5c:55:60:cd:
19 45:da:b8:e4:dd:28:72:c8:8b:a1:3e:4b:00:09:82:
20 b0:2c:dc:d6:17:c9:02:f4:cd:26:c7:11:28:f3:77:
21 b5:97:c2:76:c2:e0:07:d7:34:5b:e0:ed:1a:59:a5:
22 b4:b7:16:09:3d:35:bd:d9:03:07:9d:7c:3b:f0:63:
23 bd:5e:02:99:cf:32:e1:ac:4c:7a:3e:4c:b2:8e:98:
24 68:07:4f:59:dc:0d:bf:cc:83:04:5c:d8:90:f0:73:
25 da:2b:08:17:c4:36:a7:d8:94:3d:b6:c0:af:29:0a:
26 d3:19:5f:eb:7d:cc:4d:05:56:11:0a:ee:b1:f3:d7:
27 c9:5a:3c:8c:57:16:91:51:14:f8:20:4e:0f:29:9e:
28 04:21:e6:f1:e4:e8:44:af:d7:25:92:08:64:fc:2c:
29 1c:2e:4f:71:53:91:53:1d:e5:f9:7b:52:0f:21:da:
30 5c:dd:19:68:96:ca:70:6a:f1:c4:0d:07:af:f8:65:
31 13:92:e9:ef:65:b3:89:86:fd:c0:74:5c:a4:6b:49:
32 62:c5
33 Exponent: 65537 (0x10001)
34 X509v3 extensions:
35 X509v3 Key Usage: critical
36 Digital Signature, Key Encipherment
37 X509v3 Basic Constraints:
38 CA:FALSE
39 X509v3 Extended Key Usage:
40 TLS Web Server Authentication, TLS Web Client Authentication
41 X509v3 Subject Key Identifier:
42 00:61:01:AD:25:44:8A:EF:E1:2C:EC:83:5A:3A:3B:EA:A0:BD:E1:45
43 X509v3 Authority Key Identifier:
44 keyid:4D:02:BF:71:95:6A:AA:58:C5:9C:B8:83:67:5E:64:16:99:E1:2A:9E
45
46 Authority Information Access:
47 CA Issuers - URI:http://example.com/ca/tls-ca.cer
48
49 X509v3 CRL Distribution Points:
50
51 Full Name:
52 URI:http://example.com/ca/tls-ca.crl
53
54 X509v3 Subject Alternative Name:
55 IP Address:127.0.0.1, IP Address:127.0.0.0, DNS:localhost
56 Signature Algorithm: sha1WithRSAEncryption
57 77:97:e4:ef:db:10:8e:62:50:96:4a:6e:f5:a4:f9:1f:19:3b:
58 c8:a4:dd:b3:f6:11:41:1a:fb:e3:f8:dd:0e:64:e5:2b:00:b9:
59 e6:25:9f:2e:e1:d2:9a:cd:b6:f2:41:4d:27:dd:2c:9a:af:97:
60 79:e8:cf:61:fb:cf:be:25:c6:e1:19:a0:c8:90:44:a0:76:8a:
61 45:d4:37:22:e5:d4:80:b4:b3:0f:a8:33:08:24:ad:21:0b:b7:
62 98:46:93:90:8a:ae:77:0c:cb:b8:59:d3:3b:9b:fb:16:5a:22:
63 ca:c2:97:9d:78:1b:fc:23:fc:a0:42:54:40:de:88:4b:07:2b:
64 19:4e:0e:79:bf:c9:9f:01:a6:46:c5:55:fa:9f:c0:0d:8a:a6:
65 e1:47:16:a6:0e:be:23:c9:e9:58:d6:31:71:8c:80:9c:16:64:
66 f0:14:08:22:a1:23:7c:98:b9:62:d1:4a:ce:e3:5c:59:fb:41:
67 87:a5:3b:36:dd:3d:45:48:b0:b0:77:6f:de:58:2a:27:4d:56:
68 20:54:08:20:c8:6d:79:b5:b9:e6:3a:03:24:0f:6d:67:39:20:
69 78:10:2f:47:85:83:c1:4d:17:33:79:84:75:27:fa:47:67:59:
70 56:cc:33:7b:a5:77:aa:59:9a:98:30:10:1a:78:43:34:8f:ed:
71 c2:a1:a3:ea
72-----BEGIN CERTIFICATE-----
73MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET
74MBEGA1UECgwKUHJvbWV0aGV1czEpMCcGA1UECwwgUHJvbWV0aGV1cyBDZXJ0aWZp
75Y2F0ZSBBdXRob3JpdHkxGjAYBgNVBAMMEVByb21ldGhldXMgVExTIENBMCAXDTE5
76MDQwNTA4MDY1N1oYDzIwNTkwMzI2MDgwNjU3WjBDMQswCQYDVQQGEwJVUzETMBEG
77A1UECgwKUHJvbWV0aGV1czEfMB0GA1UEAwwWcHJvbWV0aGV1cy5leGFtcGxlLmNv
78bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL1stn/RL77kQetd/1B4
79Ayt2A9oBSCATkGbJzm4G5fotDcCwRihEEKBheYeimEwp+vm7D0THkFxcVWDNRdq4
805N0ocsiLoT5LAAmCsCzc1hfJAvTNJscRKPN3tZfCdsLgB9c0W+DtGlmltLcWCT01
81vdkDB518O/BjvV4Cmc8y4axMej5Mso6YaAdPWdwNv8yDBFzYkPBz2isIF8Q2p9iU
82PbbArykK0xlf633MTQVWEQrusfPXyVo8jFcWkVEU+CBODymeBCHm8eToRK/XJZII
83ZPwsHC5PcVORUx3l+XtSDyHaXN0ZaJbKcGrxxA0Hr/hlE5Lp72WziYb9wHRcpGtJ
84YsUCAwEAAaOCAREwggENMA4GA1UdDwEB/wQEAwIFoDAJBgNVHRMEAjAAMB0GA1Ud
85JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQUAGEBrSVEiu/hLOyD
86Wjo76qC94UUwHwYDVR0jBBgwFoAUTQK/cZVqqljFnLiDZ15kFpnhKp4wPAYIKwYB
87BQUHAQEEMDAuMCwGCCsGAQUFBzAChiBodHRwOi8vZXhhbXBsZS5jb20vY2EvdGxz
88LWNhLmNlcjAxBgNVHR8EKjAoMCagJKAihiBodHRwOi8vZXhhbXBsZS5jb20vY2Ev
89dGxzLWNhLmNybDAgBgNVHREEGTAXhwR/AAABhwR/AAAAgglsb2NhbGhvc3QwDQYJ
90KoZIhvcNAQEFBQADggEBAHeX5O/bEI5iUJZKbvWk+R8ZO8ik3bP2EUEa++P43Q5k
915SsAueYlny7h0prNtvJBTSfdLJqvl3noz2H7z74lxuEZoMiQRKB2ikXUNyLl1IC0
92sw+oMwgkrSELt5hGk5CKrncMy7hZ0zub+xZaIsrCl514G/wj/KBCVEDeiEsHKxlO
93Dnm/yZ8BpkbFVfqfwA2KpuFHFqYOviPJ6VjWMXGMgJwWZPAUCCKhI3yYuWLRSs7j
94XFn7QYelOzbdPUVIsLB3b95YKidNViBUCCDIbXm1ueY6AyQPbWc5IHgQL0eFg8FN
95FzN5hHUn+kdnWVbMM3uld6pZmpgwEBp4QzSP7cKho+o=
96-----END CERTIFICATE-----
diff --git a/https/testdata/server.key b/https/testdata/server.key
new file mode 100644
index 0000000..e1226c0
--- /dev/null
+++ b/https/testdata/server.key
@@ -0,0 +1,28 @@
1-----BEGIN PRIVATE KEY-----
2MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC9bLZ/0S++5EHr
3Xf9QeAMrdgPaAUggE5Bmyc5uBuX6LQ3AsEYoRBCgYXmHophMKfr5uw9Ex5BcXFVg
4zUXauOTdKHLIi6E+SwAJgrAs3NYXyQL0zSbHESjzd7WXwnbC4AfXNFvg7RpZpbS3
5Fgk9Nb3ZAwedfDvwY71eApnPMuGsTHo+TLKOmGgHT1ncDb/MgwRc2JDwc9orCBfE
6NqfYlD22wK8pCtMZX+t9zE0FVhEK7rHz18laPIxXFpFRFPggTg8pngQh5vHk6ESv
71yWSCGT8LBwuT3FTkVMd5fl7Ug8h2lzdGWiWynBq8cQNB6/4ZROS6e9ls4mG/cB0
8XKRrSWLFAgMBAAECggEAezQ0V1o11dEc1vuiTjJgzWnLA4aF5OcUquZjb8jo2Blp
9soR0fUgYEFiV9RRaPl+nr7ptKe0rBgfAOGALKUHNCdN/JNU8oQmjEoyADg3s6jeB
10xruQlzWgDwszf2uqVwHj16Nkhx1wYBKZQeQBSmCkBHwl/daKHcahqn3CkLOleKx+
11Qlc3BzWNaGte6qpJMs0It3by1FuxRwVz5VkL8uhzj0WIOYMA84t0gTnFH9gfRO3F
12licotxg/Nl5M36wWcfL8Jq++72AtaKcD1jUEwuQpogrVeqflmeHwn/TlL++Hv6Xe
13Lq0jt3OCUKUV40eq9c5uEgTmyrVHMDkfFdXzutdMAQKBgQDsSMXk7P4SX6u6uTjV
14In9eWw6ZyJ2aL6VB9co/NMsj49GrrFT8VX9d+JPe9P/n6tuGcFbymNep22njRksR
150ItpW1NFRR/R3g0kYe1EhkRpNm6fhY9oIuR9xhcNnPNYkqAKT3T/dxrzbwsNhomi
16X8aht/eCz4ZsK/KdOGTkPozxgQKBgQDNOvrclT1Wl4bxONp9pEV5XpRSD/qigfIp
17i5wxy7ihX/QY9RToIWJDnzMVLnEYe64RB2WB8/4WwNPOQcuaxXbFUFct/2NdhTnS
18ToJPgPe819zW9t1FLTf1fHtsRBpGFtbhdlUDOiOtJiMXYiwlRh2uyWFhjOo8TNUE
19qMwai0vLRQKBgQCDH4t6lC4W4jK5x2oLlT5bjWqX2uXjF8e8x/q5gsGspBPKEjOD
20aKrq6jSdSRbui73RaGxH6pvb7iBf+LVWKIYFLKIUUdzrqS9f3lw+Z8h1HrjbG9JO
21dvaX+aL3cf71S0E3F4sU7fLt3tSiZ+PfUQk424+mbyXox6a2qwIKS9AJgQKBgHCu
22dHROYJo9ojKpo5Ueb6K+4jLYYSV+sYZMCBtzHlFETNKzJaJ6SeiU7Ugw8pmdtqnU
235M/gNl8pymFR0MeOqbKWdPdlZJpBfsjQoE2kouEFqFRCwKStui7IBUAheEeJXLv3
24659U+aek69l35oMkp0GDgjs8UpN/H+pp/36Hgrr9AoGAftWU405rpStHEdRVrazP
25FibQesT9HOdJgmm1gNIhj+PnFs7lKER9p0Wdl79QnIqjwyhjCXL94TFerzTKLY2c
26IRj5dcRHiiT0iK8wq8bzGNYCqV73oQXaUFMiutNAArXwzwuvPFPWNBQsjLzeDLeC
27mcOsCcPAk8cLYtVfZo2sP3g=
28-----END PRIVATE KEY-----
diff --git a/https/testdata/tls-ca-chain.pem b/https/testdata/tls-ca-chain.pem
new file mode 100644
index 0000000..722264d
--- /dev/null
+++ b/https/testdata/tls-ca-chain.pem
@@ -0,0 +1,173 @@
1Certificate:
2 Data:
3 Version: 3 (0x2)
4 Serial Number: 2 (0x2)
5 Signature Algorithm: sha1WithRSAEncryption
6 Issuer: C=US, O=Prometheus, OU=Prometheus Certificate Authority, CN=Prometheus Root CA
7 Validity
8 Not Before: Apr 5 08:00:37 2019 GMT
9 Not After : Mar 26 08:00:37 2059 GMT
10 Subject: C=US, O=Prometheus, OU=Prometheus Certificate Authority, CN=Prometheus TLS CA
11 Subject Public Key Info:
12 Public Key Algorithm: rsaEncryption
13 RSA Public-Key: (2048 bit)
14 Modulus:
15 00:aa:d2:34:6b:ed:f1:f4:01:08:e5:00:9f:75:c8:
16 ba:fc:4b:72:c6:04:93:af:f1:f6:b5:ce:01:0d:c6:
17 bd:d3:16:98:9d:e5:51:56:12:58:16:ee:18:6e:f0:
18 68:a9:42:16:65:cf:e3:31:f5:90:79:9d:13:32:87:
19 3b:1f:65:fd:84:88:a4:56:3d:26:54:69:05:27:5a:
20 ea:89:02:e7:31:9b:7d:7f:76:93:54:70:bc:17:92:
21 06:9f:9f:90:4a:8a:cf:82:a7:7b:7c:71:c4:fa:34:
22 56:00:32:1a:85:c5:f8:e4:4a:63:43:37:9d:60:84:
23 4d:78:6e:87:12:c4:2b:1f:93:a5:fe:cc:5e:f1:df:
24 c1:97:ff:b7:3e:20:38:1d:71:15:11:ec:6c:7a:cc:
25 0e:87:52:31:b1:b9:74:c3:07:1c:42:4b:1e:c1:17:
26 bc:e4:13:b7:b0:20:2e:c4:07:93:bd:a8:11:f9:da:
27 a7:d0:df:4a:48:be:9b:6d:65:c3:ae:58:56:c0:9f:
28 17:c5:d8:32:b1:04:22:fb:5b:18:f6:20:10:50:ec:
29 2d:10:4f:cc:48:8f:f2:75:dd:33:a4:0e:f5:55:da:
30 2c:89:a1:3a:52:bb:11:11:0b:97:27:17:73:35:da:
31 10:71:b3:9f:a8:42:91:e6:3a:66:00:f9:e5:11:8f:
32 5b:57
33 Exponent: 65537 (0x10001)
34 X509v3 extensions:
35 X509v3 Key Usage: critical
36 Certificate Sign, CRL Sign
37 X509v3 Basic Constraints: critical
38 CA:TRUE, pathlen:0
39 X509v3 Subject Key Identifier:
40 4D:02:BF:71:95:6A:AA:58:C5:9C:B8:83:67:5E:64:16:99:E1:2A:9E
41 X509v3 Authority Key Identifier:
42 keyid:3C:1E:A8:C6:4C:05:4D:20:EC:88:DB:29:D4:7B:F9:12:5D:CE:EA:1A
43
44 Authority Information Access:
45 CA Issuers - URI:https://example.com/ca/root-ca.cer
46
47 X509v3 CRL Distribution Points:
48
49 Full Name:
50 URI:https://example.com/ca/root-ca.crl
51
52 Signature Algorithm: sha1WithRSAEncryption
53 63:fc:ba:30:a5:05:d6:76:14:f1:77:38:b1:41:6f:81:d9:b4:
54 02:fd:bc:e5:f6:d9:e6:73:e0:71:cf:4c:fb:13:b5:6b:bd:b9:
55 c6:f6:28:18:36:e1:8c:d9:93:b3:78:4a:3d:39:1b:f4:fb:69:
56 75:24:ae:e1:a0:2f:94:05:bf:10:3c:3e:d2:2b:a8:f3:31:25:
57 2e:ed:13:ad:60:5d:22:9a:26:15:20:86:98:73:4c:f6:4b:48:
58 b8:1f:67:ba:4e:c9:47:ed:85:dc:38:dc:02:0c:fb:54:d5:2e:
59 6c:b4:95:18:51:d1:ae:ea:e8:fb:b4:19:50:04:bc:31:7e:51:
60 9e:85:29:4d:c8:f7:26:d6:d6:8d:35:2d:9e:e2:06:16:38:e2:
61 56:80:ec:f3:a3:34:e3:28:c4:e8:10:d0:8a:a6:6f:20:9a:b9:
62 dc:b9:90:6b:ba:8a:27:2c:29:72:28:55:e7:59:a6:a7:90:ec:
63 32:e8:d0:26:4a:c1:44:dd:20:bf:dc:4d:1e:7e:cc:e5:a2:5b:
64 e8:df:3d:4b:01:aa:48:56:17:e9:29:d8:71:83:05:36:8c:11:
65 4f:77:b8:95:20:b7:c7:21:06:c2:87:97:b4:6b:d3:f7:23:ba:
66 4d:5f:15:d1:0c:4d:6e:f1:6a:9d:57:5c:02:6a:d7:31:18:ef:
67 5c:fc:f8:04
68-----BEGIN CERTIFICATE-----
69MIIELTCCAxWgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJVUzET
70MBEGA1UECgwKUHJvbWV0aGV1czEpMCcGA1UECwwgUHJvbWV0aGV1cyBDZXJ0aWZp
71Y2F0ZSBBdXRob3JpdHkxGzAZBgNVBAMMElByb21ldGhldXMgUm9vdCBDQTAgFw0x
72OTA0MDUwODAwMzdaGA8yMDU5MDMyNjA4MDAzN1owaTELMAkGA1UEBhMCVVMxEzAR
73BgNVBAoMClByb21ldGhldXMxKTAnBgNVBAsMIFByb21ldGhldXMgQ2VydGlmaWNh
74dGUgQXV0aG9yaXR5MRowGAYDVQQDDBFQcm9tZXRoZXVzIFRMUyBDQTCCASIwDQYJ
75KoZIhvcNAQEBBQADggEPADCCAQoCggEBAKrSNGvt8fQBCOUAn3XIuvxLcsYEk6/x
769rXOAQ3GvdMWmJ3lUVYSWBbuGG7waKlCFmXP4zH1kHmdEzKHOx9l/YSIpFY9JlRp
77BSda6okC5zGbfX92k1RwvBeSBp+fkEqKz4Kne3xxxPo0VgAyGoXF+ORKY0M3nWCE
78TXhuhxLEKx+Tpf7MXvHfwZf/tz4gOB1xFRHsbHrMDodSMbG5dMMHHEJLHsEXvOQT
79t7AgLsQHk72oEfnap9DfSki+m21lw65YVsCfF8XYMrEEIvtbGPYgEFDsLRBPzEiP
808nXdM6QO9VXaLImhOlK7ERELlycXczXaEHGzn6hCkeY6ZgD55RGPW1cCAwEAAaOB
813DCB2TAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4E
82FgQUTQK/cZVqqljFnLiDZ15kFpnhKp4wHwYDVR0jBBgwFoAUPB6oxkwFTSDsiNsp
831Hv5El3O6howPgYIKwYBBQUHAQEEMjAwMC4GCCsGAQUFBzAChiJodHRwczovL2V4
84YW1wbGUuY29tL2NhL3Jvb3QtY2EuY2VyMDMGA1UdHwQsMCowKKAmoCSGImh0dHBz
85Oi8vZXhhbXBsZS5jb20vY2Evcm9vdC1jYS5jcmwwDQYJKoZIhvcNAQEFBQADggEB
86AGP8ujClBdZ2FPF3OLFBb4HZtAL9vOX22eZz4HHPTPsTtWu9ucb2KBg24YzZk7N4
87Sj05G/T7aXUkruGgL5QFvxA8PtIrqPMxJS7tE61gXSKaJhUghphzTPZLSLgfZ7pO
88yUfthdw43AIM+1TVLmy0lRhR0a7q6Pu0GVAEvDF+UZ6FKU3I9ybW1o01LZ7iBhY4
894laA7POjNOMoxOgQ0IqmbyCaudy5kGu6iicsKXIoVedZpqeQ7DLo0CZKwUTdIL/c
90TR5+zOWiW+jfPUsBqkhWF+kp2HGDBTaMEU93uJUgt8chBsKHl7Rr0/cjuk1fFdEM
91TW7xap1XXAJq1zEY71z8+AQ=
92-----END CERTIFICATE-----
93Certificate:
94 Data:
95 Version: 3 (0x2)
96 Serial Number: 1 (0x1)
97 Signature Algorithm: sha1WithRSAEncryption
98 Issuer: C=US, O=Prometheus, OU=Prometheus Certificate Authority, CN=Prometheus Root CA
99 Validity
100 Not Before: Apr 5 07:55:00 2019 GMT
101 Not After : Mar 26 07:55:00 2059 GMT
102 Subject: C=US, O=Prometheus, OU=Prometheus Certificate Authority, CN=Prometheus Root CA
103 Subject Public Key Info:
104 Public Key Algorithm: rsaEncryption
105 RSA Public-Key: (2048 bit)
106 Modulus:
107 00:bf:b9:e2:ab:5f:61:22:e1:4e:cd:ee:da:b0:26:
108 2e:bb:b0:7e:1c:ce:10:be:16:29:35:0c:0c:1d:93:
109 01:29:2a:f6:f9:c2:6e:5c:10:44:ca:f8:dc:ad:7a:
110 06:64:0f:8a:18:ad:b2:a2:94:49:c9:ba:8c:45:94:
111 7c:d9:e0:11:45:d8:16:79:a2:20:9f:8c:63:60:72:
112 2a:5b:f9:66:80:ac:85:67:01:5a:eb:91:c1:d2:88:
113 87:9e:4c:18:c9:f2:f0:7a:18:c0:e6:ab:2c:78:de:
114 5f:b2:22:4e:94:9c:f5:cd:e6:e2:33:30:e9:20:10:
115 a6:a1:75:eb:59:ab:45:a9:f7:3e:54:40:ae:05:25:
116 be:74:c5:3a:fd:af:73:16:60:45:7c:4a:e0:0e:0d:
117 a1:15:7f:9a:1f:c2:a7:04:ad:ef:b3:e4:f6:00:2c:
118 4e:0b:04:90:49:ee:d3:db:a6:12:c4:91:0b:32:4f:
119 11:84:c7:c4:8a:ef:51:66:7a:b0:20:2f:cb:95:8d:
120 96:57:60:66:5e:f9:4f:5a:94:9c:71:ad:eb:ca:70:
121 3e:62:06:c2:3a:29:f8:9e:86:af:da:07:78:f8:31:
122 af:42:48:49:9e:4a:df:1b:27:1f:44:35:81:6d:fa:
123 7a:c5:6a:0a:35:23:c7:c4:d5:fe:c9:9e:61:c9:30:
124 cd:1f
125 Exponent: 65537 (0x10001)
126 X509v3 extensions:
127 X509v3 Key Usage: critical
128 Certificate Sign, CRL Sign
129 X509v3 Basic Constraints: critical
130 CA:TRUE
131 X509v3 Subject Key Identifier:
132 3C:1E:A8:C6:4C:05:4D:20:EC:88:DB:29:D4:7B:F9:12:5D:CE:EA:1A
133 X509v3 Authority Key Identifier:
134 keyid:3C:1E:A8:C6:4C:05:4D:20:EC:88:DB:29:D4:7B:F9:12:5D:CE:EA:1A
135
136 Signature Algorithm: sha1WithRSAEncryption
137 56:2f:79:e5:12:91:f5:19:a7:d1:32:28:fd:e3:9d:8f:e1:3c:
138 bb:a3:a5:f2:55:8a:03:ad:2c:1d:18:82:e1:7f:19:75:d9:47:
139 5b:e7:7c:e4:a5:e0:eb:dc:7e:24:a3:7d:99:1a:cf:39:ba:a5:
140 b4:b8:45:68:83:cf:70:ad:56:f2:34:73:65:fc:6c:b0:53:9a:
141 79:04:f7:3e:7e:4b:22:1b:e7:76:23:20:bc:9c:05:a2:5d:01:
142 d2:f0:09:49:17:b2:61:74:1a:5b:f4:e0:fd:ce:11:ba:13:4a:
143 e6:07:11:7d:30:e2:11:87:ee:33:1a:68:de:67:f4:ac:b5:58:
144 1a:ac:cf:7a:2d:fd:c3:44:5b:4b:cd:6c:ff:f6:49:b4:55:4a:
145 09:a0:92:2d:57:3b:69:85:54:3e:e9:ec:ef:b2:a5:7a:29:75:
146 2b:f8:eb:4b:d4:cf:68:ee:3e:c8:63:7e:12:eb:e4:2f:63:a3:
147 a7:c8:0f:e9:39:ff:5c:29:65:7f:25:f0:42:bf:07:ba:06:b8:
148 5e:d6:56:ba:f8:67:56:1b:42:aa:b3:04:d8:6e:88:10:a5:70:
149 b5:81:04:a4:90:a3:f0:83:4d:0c:6b:12:5d:a4:4c:83:5a:ff:
150 a8:7a:86:61:ff:0f:4c:e5:0f:17:d1:64:3c:bd:d9:22:7e:b7:
151 fa:9b:83:ba
152-----BEGIN CERTIFICATE-----
153MIIDtDCCApygAwIBAgIBATANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJVUzET
154MBEGA1UECgwKUHJvbWV0aGV1czEpMCcGA1UECwwgUHJvbWV0aGV1cyBDZXJ0aWZp
155Y2F0ZSBBdXRob3JpdHkxGzAZBgNVBAMMElByb21ldGhldXMgUm9vdCBDQTAgFw0x
156OTA0MDUwNzU1MDBaGA8yMDU5MDMyNjA3NTUwMFowajELMAkGA1UEBhMCVVMxEzAR
157BgNVBAoMClByb21ldGhldXMxKTAnBgNVBAsMIFByb21ldGhldXMgQ2VydGlmaWNh
158dGUgQXV0aG9yaXR5MRswGQYDVQQDDBJQcm9tZXRoZXVzIFJvb3QgQ0EwggEiMA0G
159CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/ueKrX2Ei4U7N7tqwJi67sH4czhC+
160Fik1DAwdkwEpKvb5wm5cEETK+NytegZkD4oYrbKilEnJuoxFlHzZ4BFF2BZ5oiCf
161jGNgcipb+WaArIVnAVrrkcHSiIeeTBjJ8vB6GMDmqyx43l+yIk6UnPXN5uIzMOkg
162EKahdetZq0Wp9z5UQK4FJb50xTr9r3MWYEV8SuAODaEVf5ofwqcEre+z5PYALE4L
163BJBJ7tPbphLEkQsyTxGEx8SK71FmerAgL8uVjZZXYGZe+U9alJxxrevKcD5iBsI6
164Kfiehq/aB3j4Ma9CSEmeSt8bJx9ENYFt+nrFago1I8fE1f7JnmHJMM0fAgMBAAGj
165YzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQ8
166HqjGTAVNIOyI2ynUe/kSXc7qGjAfBgNVHSMEGDAWgBQ8HqjGTAVNIOyI2ynUe/kS
167Xc7qGjANBgkqhkiG9w0BAQUFAAOCAQEAVi955RKR9Rmn0TIo/eOdj+E8u6Ol8lWK
168A60sHRiC4X8ZddlHW+d85KXg69x+JKN9mRrPObqltLhFaIPPcK1W8jRzZfxssFOa
169eQT3Pn5LIhvndiMgvJwFol0B0vAJSReyYXQaW/Tg/c4RuhNK5gcRfTDiEYfuMxpo
1703mf0rLVYGqzPei39w0RbS81s//ZJtFVKCaCSLVc7aYVUPuns77Kleil1K/jrS9TP
171aO4+yGN+EuvkL2Ojp8gP6Tn/XCllfyXwQr8Huga4XtZWuvhnVhtCqrME2G6IEKVw
172tYEEpJCj8INNDGsSXaRMg1r/qHqGYf8PTOUPF9FkPL3ZIn63+puDug==
173-----END CERTIFICATE-----
diff --git a/https/testdata/tls_config_auth_clientCAs_invalid.bad.yml b/https/testdata/tls_config_auth_clientCAs_invalid.bad.yml
new file mode 100644
index 0000000..c34cc4f
--- /dev/null
+++ b/https/testdata/tls_config_auth_clientCAs_invalid.bad.yml
@@ -0,0 +1,4 @@
1tlsConfig :
2 tlsCertPath : "testdata/server.crt"
3 tlsKeyPath : "testdata/server.key"
4 clientCAs : "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
new file mode 100644
index 0000000..fc92932
--- /dev/null
+++ b/https/testdata/tls_config_auth_clientCAs_missing.bad.yml
@@ -0,0 +1,4 @@
1tlsConfig :
2 tlsCertPath : "testdata/server.crt"
3 tlsKeyPath : "testdata/server.key"
4 clientAuth : "RequireAndVerifyClientCert" \ No newline at end of file
diff --git a/https/testdata/tls_config_empty.yml b/https/testdata/tls_config_empty.yml
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/https/testdata/tls_config_empty.yml
diff --git a/https/testdata/tls_config_junk.yml b/https/testdata/tls_config_junk.yml
new file mode 100644
index 0000000..568a7c4
--- /dev/null
+++ b/https/testdata/tls_config_junk.yml
@@ -0,0 +1,20 @@
1hWkNKCp3fvIx3jKnsaBI
2TuEjdwNS8A2vYdFbiKqr
3ay3RiOtykgt4m6m3KOol
4ZreGpJRGmpDSVV9cioiF
5r7kDOHhHU2frvv0nLcY2
6uQMQM4XgqFkCG6gFAIJZ
7g99tTkrZhN9b6pkJ6J2y
8rzdt729HrA2RblDGYfjs
9MW7GxrBdlCnliYJGPhfr
10g9kaXxMXcDwsw0C0rv0u
11637ZmfRGElb6VBVOtgqn
12RG0MRezjLYCJQBMUdRDE
13RzO4VicAzj7asVZAT3oo
14nPw267UONk7h7KBYRgch
15Alj38foWqjV3heXXdahm
16TrMzMgl6JIQ1x4OZB5i4
17qlrXFJoeV6Pr77nuiEh9
183yE5vMnnKHm2nImEfzMG
19bI01UDObHRSaoJLC0vTD
20G9tlcKU883NkQ6nsxJ8Y
diff --git a/https/testdata/tls_config_noAuth.bad.yml b/https/testdata/tls_config_noAuth.bad.yml
new file mode 100644
index 0000000..f0dd228
--- /dev/null
+++ b/https/testdata/tls_config_noAuth.bad.yml
@@ -0,0 +1,4 @@
1tlsConfig :
2 tlsCertPath : "testdata/server.crt"
3 tlsKeyPath : "testdata/server.key"
4 clientCAs : "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
new file mode 100644
index 0000000..f567693
--- /dev/null
+++ b/https/testdata/tls_config_noAuth.good.blocking.yml
@@ -0,0 +1,5 @@
1tlsConfig :
2 tlsCertPath : "testdata/server.crt"
3 tlsKeyPath : "testdata/server.key"
4 clientAuth : "RequireAndVerifyClientCert"
5 clientCAs: "testdata/tls-ca-chain.pem" \ No newline at end of file
diff --git a/https/testdata/tls_config_noAuth.good.yml b/https/testdata/tls_config_noAuth.good.yml
new file mode 100644
index 0000000..76e46cf
--- /dev/null
+++ b/https/testdata/tls_config_noAuth.good.yml
@@ -0,0 +1,5 @@
1tlsConfig :
2 tlsCertPath : "testdata/server.crt"
3 tlsKeyPath : "testdata/server.key"
4 clientAuth : "VerifyClientCertIfGiven"
5 clientCAs : "testdata/tls-ca-chain.pem"
diff --git a/https/testdata/tls_config_noAuth_certPath_empty.bad.yml b/https/testdata/tls_config_noAuth_certPath_empty.bad.yml
new file mode 100644
index 0000000..39c7abd
--- /dev/null
+++ b/https/testdata/tls_config_noAuth_certPath_empty.bad.yml
@@ -0,0 +1,3 @@
1tlsConfig :
2 tlsCertPath : ""
3 tlsKeyPath : "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
new file mode 100644
index 0000000..5bdbd1a
--- /dev/null
+++ b/https/testdata/tls_config_noAuth_certPath_invalid.bad.yml
@@ -0,0 +1,3 @@
1tlsConfig :
2 tlsCertPath : "somefile"
3 tlsKeyPath : "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
new file mode 100644
index 0000000..938e5d6
--- /dev/null
+++ b/https/testdata/tls_config_noAuth_certPath_keyPath_empty.bad.yml
@@ -0,0 +1,3 @@
1tlsConfig :
2 tlsCertPath : ""
3 tlsKeyPath : "" \ No newline at end of file
diff --git a/https/testdata/tls_config_noAuth_certPath_keyPath_invalid.bad.yml b/https/testdata/tls_config_noAuth_certPath_keyPath_invalid.bad.yml
new file mode 100644
index 0000000..b93ffd6
--- /dev/null
+++ b/https/testdata/tls_config_noAuth_certPath_keyPath_invalid.bad.yml
@@ -0,0 +1,3 @@
1tlsConfig :
2 tlsCertPath : "somefile"
3 tlsKeyPath : "somefile" \ No newline at end of file
diff --git a/https/testdata/tls_config_noAuth_keyPath_empty.bad.yml b/https/testdata/tls_config_noAuth_keyPath_empty.bad.yml
new file mode 100644
index 0000000..424f92f
--- /dev/null
+++ b/https/testdata/tls_config_noAuth_keyPath_empty.bad.yml
@@ -0,0 +1,3 @@
1tlsConfig :
2 tlsCertPath : "testdata/server.crt"
3 tlsKeyPath : "" \ 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
new file mode 100644
index 0000000..2625074
--- /dev/null
+++ b/https/testdata/tls_config_noAuth_keyPath_invalid.bad.yml
@@ -0,0 +1,3 @@
1tlsConfig :
2 tlsCertPath : "testdata/server.cert"
3 tlsKeyPath : "somefile" \ No newline at end of file
diff --git a/https/tls_config.go b/https/tls_config.go
new file mode 100644
index 0000000..dd473d8
--- /dev/null
+++ b/https/tls_config.go
@@ -0,0 +1,123 @@
1// Copyright 2019 The Prometheus Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// Package https allows the implementation of TLS.
15package https
16
17import (
18 "crypto/tls"
19 "crypto/x509"
20 "io/ioutil"
21 "net/http"
22
23 "github.com/pkg/errors"
24 "gopkg.in/yaml.v2"
25)
26
27type Config struct {
28 TLSConfig TLSStruct `yaml:"tlsConfig"`
29}
30
31type TLSStruct struct {
32 TLSCertPath string `yaml:"tlsCertPath"`
33 TLSKeyPath string `yaml:"tlsKeyPath"`
34 ClientAuth string `yaml:"clientAuth"`
35 ClientCAs string `yaml:"clientCAs"`
36}
37
38func getTLSConfig(configPath string) (*tls.Config, error) {
39 content, err := ioutil.ReadFile(configPath)
40 if err != nil {
41 return nil, err
42 }
43 c := &Config{}
44 err = yaml.Unmarshal(content, c)
45 if err != nil {
46 return nil, err
47 }
48 return configToTLSConfig(&c.TLSConfig)
49}
50
51func configToTLSConfig(c *TLSStruct) (*tls.Config, error) {
52 cfg := &tls.Config{}
53 if len(c.TLSCertPath) == 0 {
54 return nil, errors.New("missing TLSCertPath")
55 }
56 if len(c.TLSKeyPath) == 0 {
57 return nil, errors.New("missing TLSKeyPath")
58 }
59 loadCert := func() (*tls.Certificate, error) {
60 cert, err := tls.LoadX509KeyPair(c.TLSCertPath, c.TLSKeyPath)
61 if err != nil {
62 return nil, errors.Wrap(err, "failed to load X509KeyPair")
63 }
64 return &cert, nil
65 }
66 // Confirm that certificate and key paths are valid.
67 if _, err := loadCert(); err != nil {
68 return nil, err
69 }
70 cfg.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
71 return loadCert()
72 }
73
74 if len(c.ClientCAs) > 0 {
75 clientCAPool := x509.NewCertPool()
76 clientCAFile, err := ioutil.ReadFile(c.ClientCAs)
77 if err != nil {
78 return nil, err
79 }
80 clientCAPool.AppendCertsFromPEM(clientCAFile)
81 cfg.ClientCAs = clientCAPool
82 }
83 if len(c.ClientAuth) > 0 {
84 switch s := (c.ClientAuth); s {
85 case "NoClientCert":
86 cfg.ClientAuth = tls.NoClientCert
87 case "RequestClientCert":
88 cfg.ClientAuth = tls.RequestClientCert
89 case "RequireClientCert":
90 cfg.ClientAuth = tls.RequireAnyClientCert
91 case "VerifyClientCertIfGiven":
92 cfg.ClientAuth = tls.VerifyClientCertIfGiven
93 case "RequireAndVerifyClientCert":
94 cfg.ClientAuth = tls.RequireAndVerifyClientCert
95 case "":
96 cfg.ClientAuth = tls.NoClientCert
97 default:
98 return nil, errors.New("Invalid ClientAuth: " + s)
99 }
100 }
101 if len(c.ClientCAs) > 0 && cfg.ClientAuth == tls.NoClientCert {
102 return nil, errors.New("Client CA's have been configured without a Client Auth Policy")
103 }
104 return cfg, nil
105}
106
107// Listen starts the server on the given address. If tlsConfigPath isn't empty the server connection will be started using TLS.
108func Listen(server *http.Server, tlsConfigPath string) error {
109 if (tlsConfigPath) == "" {
110 return server.ListenAndServe()
111 }
112 var err error
113 server.TLSConfig, err = getTLSConfig(tlsConfigPath)
114 if err != nil {
115 return err
116 }
117 // Set the GetConfigForClient method of the HTTPS server so that the config
118 // and certs are reloaded on new connections.
119 server.TLSConfig.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) {
120 return getTLSConfig(tlsConfigPath)
121 }
122 return server.ListenAndServeTLS("", "")
123}
diff --git a/https/tls_config_test.go b/https/tls_config_test.go
new file mode 100644
index 0000000..717f201
--- /dev/null
+++ b/https/tls_config_test.go
@@ -0,0 +1,362 @@
1// Copyright 2019 The Prometheus Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14package https
15
16import (
17 "crypto/tls"
18 "crypto/x509"
19 "errors"
20 "fmt"
21 "io/ioutil"
22 "net"
23 "net/http"
24 "regexp"
25 "sync"
26 "testing"
27 "time"
28)
29
30var (
31 port = getPort()
32
33 ErrorMap = map[string]*regexp.Regexp{
34 "HTTP Response to HTTPS": regexp.MustCompile(`server gave HTTP response to HTTPS client`),
35 "No such file": regexp.MustCompile(`no such file`),
36 "Invalid argument": regexp.MustCompile(`invalid argument`),
37 "YAML error": regexp.MustCompile(`yaml`),
38 "Invalid ClientAuth": regexp.MustCompile(`invalid ClientAuth`),
39 "TLS handshake": regexp.MustCompile(`tls`),
40 "HTTP Request to HTTPS server": regexp.MustCompile(`HTTP`),
41 "Invalid CertPath": regexp.MustCompile(`missing TLSCertPath`),
42 "Invalid KeyPath": regexp.MustCompile(`missing TLSKeyPath`),
43 "ClientCA set without policy": regexp.MustCompile(`Client CA's have been configured without a Client Auth Policy`),
44 }
45)
46
47func getPort() string {
48 listener, err := net.Listen("tcp", ":0")
49 if err != nil {
50 panic(err)
51 }
52 defer listener.Close()
53 p := listener.Addr().(*net.TCPAddr).Port
54 return fmt.Sprintf(":%v", p)
55}
56
57type TestInputs struct {
58 Name string
59 Server func() *http.Server
60 UseNilServer bool
61 YAMLConfigPath string
62 ExpectedError *regexp.Regexp
63 UseTLSClient bool
64}
65
66func TestYAMLFiles(t *testing.T) {
67 testTables := []*TestInputs{
68 {
69 Name: `path to config yml invalid`,
70 YAMLConfigPath: "somefile",
71 ExpectedError: ErrorMap["No such file"],
72 },
73 {
74 Name: `empty config yml`,
75 YAMLConfigPath: "testdata/tls_config_empty.yml",
76 ExpectedError: ErrorMap["Invalid CertPath"],
77 },
78 {
79 Name: `invalid config yml (invalid structure)`,
80 YAMLConfigPath: "testdata/tls_config_junk.yml",
81 ExpectedError: ErrorMap["YAML error"],
82 },
83 {
84 Name: `invalid config yml (cert path empty)`,
85 YAMLConfigPath: "testdata/tls_config_noAuth_certPath_empty.bad.yml",
86 ExpectedError: ErrorMap["Invalid CertPath"],
87 },
88 {
89 Name: `invalid config yml (key path empty)`,
90 YAMLConfigPath: "testdata/tls_config_noAuth_keyPath_empty.bad.yml",
91 ExpectedError: ErrorMap["Invalid KeyPath"],
92 },
93 {
94 Name: `invalid config yml (cert path and key path empty)`,
95 YAMLConfigPath: "testdata/tls_config_noAuth_certPath_keyPath_empty.bad.yml",
96 ExpectedError: ErrorMap["Invalid CertPath"],
97 },
98 {
99 Name: `invalid config yml (cert path invalid)`,
100 YAMLConfigPath: "testdata/tls_config_noAuth_certPath_invalid.bad.yml",
101 ExpectedError: ErrorMap["No such file"],
102 },
103 {
104 Name: `invalid config yml (key path invalid)`,
105 YAMLConfigPath: "testdata/tls_config_noAuth_keyPath_invalid.bad.yml",
106 ExpectedError: ErrorMap["No such file"],
107 },
108 {
109 Name: `invalid config yml (cert path and key path invalid)`,
110 YAMLConfigPath: "testdata/tls_config_noAuth_certPath_keyPath_invalid.bad.yml",
111 ExpectedError: ErrorMap["No such file"],
112 },
113 {
114 Name: `invalid config yml (invalid ClientAuth)`,
115 YAMLConfigPath: "testdata/tls_config_noAuth.bad.yml",
116 ExpectedError: ErrorMap["ClientCA set without policy"],
117 },
118 {
119 Name: `invalid config yml (invalid ClientCAs filepath)`,
120 YAMLConfigPath: "testdata/tls_config_auth_clientCAs_invalid.bad.yml",
121 ExpectedError: ErrorMap["No such file"],
122 },
123 }
124 for _, testInputs := range testTables {
125 t.Run(testInputs.Name, testInputs.Test)
126 }
127}
128
129func TestServerBehaviour(t *testing.T) {
130 testTables := []*TestInputs{
131 {
132 Name: `empty string YAMLConfigPath and default client`,
133 YAMLConfigPath: "",
134 ExpectedError: nil,
135 },
136 {
137 Name: `empty string YAMLConfigPath and TLS client`,
138 YAMLConfigPath: "",
139 UseTLSClient: true,
140 ExpectedError: ErrorMap["HTTP Response to HTTPS"],
141 },
142 {
143 Name: `valid tls config yml and default client`,
144 YAMLConfigPath: "testdata/tls_config_noAuth.good.yml",
145 ExpectedError: ErrorMap["HTTP Request to HTTPS server"],
146 },
147 {
148 Name: `valid tls config yml and tls client`,
149 YAMLConfigPath: "testdata/tls_config_noAuth.good.yml",
150 UseTLSClient: true,
151 ExpectedError: nil,
152 },
153 }
154 for _, testInputs := range testTables {
155 t.Run(testInputs.Name, testInputs.Test)
156 }
157}
158
159func TestConfigReloading(t *testing.T) {
160 errorChannel := make(chan error, 1)
161 var once sync.Once
162 recordConnectionError := func(err error) {
163 once.Do(func() {
164 errorChannel <- err
165 })
166 }
167 defer func() {
168 if recover() != nil {
169 recordConnectionError(errors.New("Panic in test function"))
170 }
171 }()
172
173 goodYAMLPath := "testdata/tls_config_noAuth.good.yml"
174 badYAMLPath := "testdata/tls_config_noAuth.good.blocking.yml"
175
176 server := &http.Server{
177 Addr: port,
178 Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
179 w.Write([]byte("Hello World!"))
180 }),
181 }
182 defer func() {
183 server.Close()
184 }()
185
186 go func() {
187 defer func() {
188 if recover() != nil {
189 recordConnectionError(errors.New("Panic starting server"))
190 }
191 }()
192 err := Listen(server, badYAMLPath)
193 recordConnectionError(err)
194 }()
195
196 client := getTLSClient()
197
198 TestClientConnection := func() error {
199 time.Sleep(250 * time.Millisecond)
200 r, err := client.Get("https://localhost" + port)
201 if err != nil {
202 return (err)
203 }
204 body, err := ioutil.ReadAll(r.Body)
205 if err != nil {
206 return (err)
207 }
208 if string(body) != "Hello World!" {
209 return (errors.New(string(body)))
210 }
211 return (nil)
212 }
213
214 err := TestClientConnection()
215 if err == nil {
216 recordConnectionError(errors.New("Connection accepted but should have failed."))
217 } else {
218 swapFileContents(goodYAMLPath, badYAMLPath)
219 defer swapFileContents(goodYAMLPath, badYAMLPath)
220 err = TestClientConnection()
221 if err != nil {
222 recordConnectionError(errors.New("Connection failed but should have been accepted."))
223 } else {
224
225 recordConnectionError(nil)
226 }
227 }
228
229 err = <-errorChannel
230 if err != nil {
231 t.Errorf(" *** Failed test: %s *** Returned error: %v", "TestConfigReloading", err)
232 }
233}
234
235func (test *TestInputs) Test(t *testing.T) {
236 errorChannel := make(chan error, 1)
237 var once sync.Once
238 recordConnectionError := func(err error) {
239 once.Do(func() {
240 errorChannel <- err
241 })
242 }
243 defer func() {
244 if recover() != nil {
245 recordConnectionError(errors.New("Panic in test function"))
246 }
247 }()
248
249 var server *http.Server
250 if test.UseNilServer {
251 server = nil
252 } else {
253 server = &http.Server{
254 Addr: port,
255 Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
256 w.Write([]byte("Hello World!"))
257 }),
258 }
259 defer func() {
260 server.Close()
261 }()
262 }
263 go func() {
264 defer func() {
265 if recover() != nil {
266 recordConnectionError(errors.New("Panic starting server"))
267 }
268 }()
269 err := Listen(server, test.YAMLConfigPath)
270 recordConnectionError(err)
271 }()
272
273 var ClientConnection func() (*http.Response, error)
274 if test.UseTLSClient {
275 ClientConnection = func() (*http.Response, error) {
276 client := getTLSClient()
277 return client.Get("https://localhost" + port)
278 }
279 } else {
280 ClientConnection = func() (*http.Response, error) {
281 client := http.DefaultClient
282 return client.Get("http://localhost" + port)
283 }
284 }
285 go func() {
286 time.Sleep(250 * time.Millisecond)
287 r, err := ClientConnection()
288 if err != nil {
289 recordConnectionError(err)
290 return
291 }
292 body, err := ioutil.ReadAll(r.Body)
293 if err != nil {
294 recordConnectionError(err)
295 return
296 }
297 if string(body) != "Hello World!" {
298 recordConnectionError(errors.New(string(body)))
299 return
300 }
301 recordConnectionError(nil)
302 }()
303 err := <-errorChannel
304 if test.isCorrectError(err) == false {
305 if test.ExpectedError == nil {
306 t.Logf("Expected no error, got error: %v", err)
307 } else {
308 t.Logf("Expected error matching regular expression: %v", test.ExpectedError)
309 t.Logf("Got: %v", err)
310 }
311 t.Fail()
312 }
313}
314
315func (test *TestInputs) isCorrectError(returnedError error) bool {
316 switch {
317 case returnedError == nil && test.ExpectedError == nil:
318 case returnedError != nil && test.ExpectedError != nil && test.ExpectedError.MatchString(returnedError.Error()):
319 default:
320 return false
321 }
322 return true
323}
324
325func getTLSClient() *http.Client {
326 cert, err := ioutil.ReadFile("testdata/tls-ca-chain.pem")
327 if err != nil {
328 panic("Unable to start TLS client. Check cert path")
329 }
330 client := &http.Client{
331 Transport: &http.Transport{
332 TLSClientConfig: &tls.Config{
333 RootCAs: func() *x509.CertPool {
334 caCertPool := x509.NewCertPool()
335 caCertPool.AppendCertsFromPEM(cert)
336 return caCertPool
337 }(),
338 },
339 },
340 }
341 return client
342}
343
344func swapFileContents(file1, file2 string) error {
345 content1, err := ioutil.ReadFile(file1)
346 if err != nil {
347 return err
348 }
349 content2, err := ioutil.ReadFile(file2)
350 if err != nil {
351 return err
352 }
353 err = ioutil.WriteFile(file1, content2, 0644)
354 if err != nil {
355 return err
356 }
357 err = ioutil.WriteFile(file2, content1, 0644)
358 if err != nil {
359 return err
360 }
361 return nil
362}
diff --git a/https/web-config.yml b/https/web-config.yml
new file mode 100644
index 0000000..0f439da
--- /dev/null
+++ b/https/web-config.yml
@@ -0,0 +1,10 @@
1tlsConfig :
2 # Certificate and key files for server to use to authenticate to client
3 tlsCertPath : <filename>
4 tlsKeyPath : <filename>
5
6 # Server policy for client authentication. Maps to ClientAuth Policies
7 [ clientAuth : <string> ]
8
9 # CA certificate for client certificate authentication to the server
10 [ clientCAs : <filename> ]