1{ hostPkgs, lib, ... }:
2
3let
4 domain = "acme.test";
5 port = 8443;
6
7 hello_txt =
8 name:
9 hostPkgs.writeTextFile {
10 name = "/hello_${name}.txt";
11 text = "Hello, ${name}!";
12 };
13
14 mkH2OServer =
15 recommendations:
16 { pkgs, lib, ... }:
17 {
18 services.h2o = {
19 enable = true;
20 package = pkgs.h2o.override (
21 lib.optionalAttrs
22 (builtins.elem recommendations [
23 "intermediate"
24 "old"
25 ])
26 {
27 openssl = pkgs.openssl_legacy;
28 }
29 );
30 defaultTLSRecommendations = "modern"; # prove overridden
31 hosts = {
32 "${domain}" = {
33 tls = {
34 inherit port recommendations;
35 policy = "force";
36 identity = [
37 {
38 key-file = ../../common/acme/server/acme.test.key.pem;
39 certificate-file = ../../common/acme/server/acme.test.cert.pem;
40 }
41 ];
42 extraSettings = {
43 # when using common ACME certs, disable talking to CA
44 ocsp-update-interval = 0;
45 };
46 };
47 settings = {
48 paths."/"."file.file" = "${hello_txt recommendations}";
49 };
50 };
51 };
52 settings = {
53 ssl-offload = "kernel";
54 };
55 };
56
57 security.pki.certificates = [
58 (builtins.readFile ../../common/acme/server/ca.cert.pem)
59 ];
60
61 networking = {
62 firewall.allowedTCPPorts = [ port ];
63 extraHosts = "127.0.0.1 ${domain}";
64 };
65 };
66in
67{
68 name = "h2o-tls-recommendations";
69
70 meta = {
71 maintainers = with lib.maintainers; [ toastal ];
72 };
73
74 nodes = {
75 server_modern = mkH2OServer "modern";
76 server_intermediate = mkH2OServer "intermediate";
77 server_old = mkH2OServer "old";
78 };
79
80 testScript =
81 let
82 portStr = builtins.toString port;
83 in
84 # python
85 ''
86 curl_basic = "curl -v --tlsv1.3 --http2 'https://${domain}:${portStr}/'"
87 curl_head = "curl -v --head 'https://${domain}:${portStr}/'"
88 curl_max_tls1_2 ="curl -v --tlsv1.0 --tls-max 1.2 'https://${domain}:${portStr}/'"
89 curl_max_tls1_2_intermediate_cipher ="curl -v --tlsv1.0 --tls-max 1.2 --ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256' 'https://${domain}:${portStr}/'"
90 curl_max_tls1_2_old_cipher ="curl -v --tlsv1.0 --tls-max 1.2 --ciphers 'ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256' 'https://${domain}:${portStr}/'"
91
92 server_modern.wait_for_unit("h2o.service")
93 server_modern.wait_for_open_port(${portStr})
94 modern_response = server_modern.succeed(curl_basic)
95 assert "Hello, modern!" in modern_response
96 modern_head = server_modern.succeed(curl_head)
97 assert "strict-transport-security" in modern_head
98 server_modern.fail(curl_max_tls1_2)
99
100 server_intermediate.wait_for_unit("h2o.service")
101 server_intermediate.wait_for_open_port(${portStr})
102 intermediate_response = server_intermediate.succeed(curl_basic)
103 assert "Hello, intermediate!" in intermediate_response
104 intermediate_head = server_modern.succeed(curl_head)
105 assert "strict-transport-security" in intermediate_head
106 server_intermediate.succeed(curl_max_tls1_2)
107 server_intermediate.succeed(curl_max_tls1_2_intermediate_cipher)
108 server_intermediate.fail(curl_max_tls1_2_old_cipher)
109
110 server_old.wait_for_unit("h2o.service")
111 server_old.wait_for_open_port(${portStr})
112 old_response = server_old.succeed(curl_basic)
113 assert "Hello, old!" in old_response
114 old_head = server_modern.succeed(curl_head)
115 assert "strict-transport-security" in old_head
116 server_old.succeed(curl_max_tls1_2)
117 server_old.succeed(curl_max_tls1_2_intermediate_cipher)
118 server_old.succeed(curl_max_tls1_2_old_cipher)
119 '';
120}