about summary refs log tree commit diff
path: root/nixos/tests/haproxy.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/tests/haproxy.nix')
-rw-r--r--nixos/tests/haproxy.nix109
1 files changed, 90 insertions, 19 deletions
diff --git a/nixos/tests/haproxy.nix b/nixos/tests/haproxy.nix
index 555474d7f2999..1730938737577 100644
--- a/nixos/tests/haproxy.nix
+++ b/nixos/tests/haproxy.nix
@@ -1,22 +1,42 @@
-import ./make-test-python.nix ({ pkgs, ...}: {
+import ./make-test-python.nix ({ lib, pkgs, ...}: {
   name = "haproxy";
   nodes = {
-    machine = { ... }: {
-      services.haproxy = {
+    server = { ... }: {
+     services.haproxy = {
         enable = true;
         config = ''
+          global
+            limited-quic
+
           defaults
+            mode http
             timeout connect 10s
+            timeout client 10s
+            timeout server 10s
+
+            log /dev/log local0 debug err
+            option logasap
+            option httplog
+            option httpslog
 
           backend http_server
-            mode http
-            server httpd [::1]:8000
+            server httpd [::1]:8000 alpn http/1.1
 
           frontend http
-            bind *:80
-            mode http
+            bind :80
+            bind :443 ssl strict-sni crt /etc/ssl/fullchain.pem alpn h2,http/1.1
+            bind quic4@:443 ssl strict-sni crt /etc/ssl/fullchain.pem alpn h3 allow-0rtt
+
+            http-after-response add-header alt-svc 'h3=":443"; ma=60' if { ssl_fc }
+
             http-request use-service prometheus-exporter if { path /metrics }
             use_backend http_server
+
+          frontend http-cert-auth
+            bind :8443 ssl strict-sni crt /etc/ssl/fullchain.pem verify required ca-file /etc/ssl/cacert.crt
+            bind quic4@:8443 ssl strict-sni crt /etc/ssl/fullchain.pem verify required ca-file /etc/ssl/cacert.crt alpn h3
+
+            use_backend http_server
         '';
       };
       services.httpd = {
@@ -30,24 +50,75 @@ import ./make-test-python.nix ({ pkgs, ...}: {
           }];
         };
       };
+      networking.firewall.allowedTCPPorts = [ 80 443 8443 ];
+      networking.firewall.allowedUDPPorts = [ 443 8443 ];
+     };
+    client = { ... }: {
+      environment.systemPackages = [ pkgs.curlHTTP3 ];
     };
   };
   testScript = ''
+    # Helpers
+    def cmd(command):
+      print(f"+{command}")
+      r = os.system(command)
+      if r != 0:
+        raise Exception(f"Command {command} failed with exit code {r}")
+
+    def openssl(command):
+      cmd(f"${pkgs.openssl}/bin/openssl {command}")
+
+    # Generate CA.
+    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")
+
+    # Generate and sign Server.
+    openssl("req -newkey rsa:4096 -nodes -subj '/CN=server/OU=Tests/O=NixOS' -keyout server.key -out server.csr")
+    openssl("x509 -req -in server.csr -out server.crt -CA cacert.crt -CAkey cacert.key -days 7")
+    cmd("cat server.crt server.key > fullchain.pem")
+
+    # Generate and sign Client.
+    openssl("req -newkey rsa:4096 -nodes -subj '/CN=client/OU=Tests/O=NixOS' -keyout client.key -out client.csr")
+    openssl("x509 -req -in client.csr -out client.crt -CA cacert.crt -CAkey cacert.key -days 7")
+    cmd("cat client.crt client.key > client.pem")
+
+    # Start the actual test.
     start_all()
-    machine.wait_for_unit("multi-user.target")
-    machine.wait_for_unit("haproxy.service")
-    machine.wait_for_unit("httpd.service")
-    assert "We are all good!" in machine.succeed("curl -fk http://localhost:80/index.txt")
-    assert "haproxy_process_pool_allocated_bytes" in machine.succeed(
-        "curl -fk http://localhost:80/metrics"
-    )
+    server.copy_from_host("fullchain.pem", "/etc/ssl/fullchain.pem")
+    server.copy_from_host("cacert.crt", "/etc/ssl/cacert.crt")
+    server.succeed("chmod 0644 /etc/ssl/fullchain.pem /etc/ssl/cacert.crt")
+
+    client.copy_from_host("cacert.crt", "/etc/ssl/cacert.crt")
+    client.copy_from_host("client.pem", "/root/client.pem")
+
+    server.wait_for_unit("multi-user.target")
+    server.wait_for_unit("haproxy.service")
+    server.wait_for_unit("httpd.service")
+
+    assert "We are all good!" in client.succeed("curl -f http://server/index.txt")
+    assert "haproxy_process_pool_allocated_bytes" in client.succeed("curl -f http://server/metrics")
+
+    with subtest("https"):
+      assert "We are all good!" in client.succeed("curl -f --cacert /etc/ssl/cacert.crt https://server/index.txt")
+
+    with subtest("https-cert-auth"):
+      # Client must succeed in authenticating with the right certificate.
+      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")
+      # Client must fail without certificate.
+      client.fail("curl --cacert /etc/ssl/cacert.crt https://server:8443/index.txt")
+
+    with subtest("h3"):
+      assert "We are all good!" in client.succeed("curl -f --http3-only --cacert /etc/ssl/cacert.crt https://server/index.txt")
+
+    with subtest("h3-cert-auth"):
+      # Client must succeed in authenticating with the right certificate.
+      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")
+      # Client must fail without certificate.
+      client.fail("curl -f --http3-only --cacert /etc/ssl/cacert.crt https://server:8443/index.txt")
 
     with subtest("reload"):
-        machine.succeed("systemctl reload haproxy")
+        server.succeed("systemctl reload haproxy")
         # wait some time to ensure the following request hits the reloaded haproxy
-        machine.sleep(5)
-        assert "We are all good!" in machine.succeed(
-            "curl -fk http://localhost:80/index.txt"
-        )
+        server.sleep(5)
+        assert "We are all good!" in client.succeed("curl -f http://server/index.txt")
   '';
 })