at 25.11-pre 5.2 kB view raw
1{ lib, hostPkgs, ... }: 2{ 3 name = "haproxy"; 4 nodes = { 5 server = 6 { pkgs, ... }: 7 { 8 services.haproxy = { 9 enable = true; 10 config = '' 11 global 12 limited-quic 13 14 defaults 15 mode http 16 timeout connect 10s 17 timeout client 10s 18 timeout server 10s 19 20 log /dev/log local0 debug err 21 option logasap 22 option httplog 23 option httpslog 24 25 backend http_server 26 server httpd [::1]:8000 alpn http/1.1 27 28 frontend http 29 bind :80 30 bind :443 ssl strict-sni crt /etc/ssl/fullchain.pem alpn h2,http/1.1 31 bind quic4@:443 ssl strict-sni crt /etc/ssl/fullchain.pem alpn h3 allow-0rtt 32 33 http-after-response add-header alt-svc 'h3=":443"; ma=60' if { ssl_fc } 34 35 http-request use-service prometheus-exporter if { path /metrics } 36 use_backend http_server 37 38 frontend http-cert-auth 39 bind :8443 ssl strict-sni crt /etc/ssl/fullchain.pem verify required ca-file /etc/ssl/cacert.crt 40 bind quic4@:8443 ssl strict-sni crt /etc/ssl/fullchain.pem verify required ca-file /etc/ssl/cacert.crt alpn h3 41 42 use_backend http_server 43 ''; 44 }; 45 services.httpd = { 46 enable = true; 47 virtualHosts.localhost = { 48 documentRoot = pkgs.writeTextDir "index.txt" "We are all good!"; 49 adminAddr = "notme@yourhost.local"; 50 listen = [ 51 { 52 ip = "::1"; 53 port = 8000; 54 } 55 ]; 56 }; 57 }; 58 networking.firewall.allowedTCPPorts = [ 59 80 60 443 61 8443 62 ]; 63 networking.firewall.allowedUDPPorts = [ 64 443 65 8443 66 ]; 67 }; 68 client = 69 { pkgs, ... }: 70 { 71 environment.systemPackages = [ pkgs.curlHTTP3 ]; 72 }; 73 }; 74 testScript = '' 75 # Helpers 76 def cmd(command): 77 print(f"+{command}") 78 r = os.system(command) 79 if r != 0: 80 raise Exception(f"Command {command} failed with exit code {r}") 81 82 def openssl(command): 83 cmd(f"${lib.getExe hostPkgs.openssl} {command}") 84 85 # Generate CA. 86 openssl("req -new -newkey rsa:4096 -nodes -x509 -days 7 -subj '/C=ZZ/ST=Cloud/L=Unspecified/O=NixOS/OU=Tests/CN=CA Certificate' -keyout cacert.key -out cacert.crt") 87 88 # Generate and sign Server. 89 openssl("req -newkey rsa:4096 -nodes -subj '/CN=server/OU=Tests/O=NixOS' -keyout server.key -out server.csr") 90 openssl("x509 -req -in server.csr -out server.crt -CA cacert.crt -CAkey cacert.key -days 7") 91 cmd("cat server.crt server.key > fullchain.pem") 92 93 # Generate and sign Client. 94 openssl("req -newkey rsa:4096 -nodes -subj '/CN=client/OU=Tests/O=NixOS' -keyout client.key -out client.csr") 95 openssl("x509 -req -in client.csr -out client.crt -CA cacert.crt -CAkey cacert.key -days 7") 96 cmd("cat client.crt client.key > client.pem") 97 98 # Start the actual test. 99 start_all() 100 server.copy_from_host("fullchain.pem", "/etc/ssl/fullchain.pem") 101 server.copy_from_host("cacert.crt", "/etc/ssl/cacert.crt") 102 server.succeed("chmod 0644 /etc/ssl/fullchain.pem /etc/ssl/cacert.crt") 103 104 client.copy_from_host("cacert.crt", "/etc/ssl/cacert.crt") 105 client.copy_from_host("client.pem", "/root/client.pem") 106 107 server.wait_for_unit("multi-user.target") 108 server.wait_for_unit("haproxy.service") 109 server.wait_for_unit("httpd.service") 110 111 assert "We are all good!" in client.succeed("curl -f http://server/index.txt") 112 assert "haproxy_process_pool_allocated_bytes" in client.succeed("curl -f http://server/metrics") 113 114 with subtest("https"): 115 assert "We are all good!" in client.succeed("curl -f --cacert /etc/ssl/cacert.crt https://server/index.txt") 116 117 with subtest("https-cert-auth"): 118 # Client must succeed in authenticating with the right certificate. 119 assert "We are all good!" in client.succeed("curl -f --cacert /etc/ssl/cacert.crt --cert-type pem --cert /root/client.pem https://server:8443/index.txt") 120 # Client must fail without certificate. 121 client.fail("curl --cacert /etc/ssl/cacert.crt https://server:8443/index.txt") 122 123 with subtest("h3"): 124 assert "We are all good!" in client.succeed("curl -f --http3-only --cacert /etc/ssl/cacert.crt https://server/index.txt") 125 126 with subtest("h3-cert-auth"): 127 # Client must succeed in authenticating with the right certificate. 128 assert "We are all good!" in client.succeed("curl -f --http3-only --cacert /etc/ssl/cacert.crt --cert-type pem --cert /root/client.pem https://server:8443/index.txt") 129 # Client must fail without certificate. 130 client.fail("curl -f --http3-only --cacert /etc/ssl/cacert.crt https://server:8443/index.txt") 131 132 with subtest("reload"): 133 server.succeed("systemctl reload haproxy") 134 # wait some time to ensure the following request hits the reloaded haproxy 135 server.sleep(5) 136 assert "We are all good!" in client.succeed("curl -f http://server/index.txt") 137 ''; 138}