about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVika <vika@fireburn.ru>2023-07-22 16:23:54 +0300
committerVika <vika@fireburn.ru>2023-07-22 16:23:54 +0300
commit22e5f4894e532203c78c140895851d3c1d6c86df (patch)
treed826eb746b7aa4e7fece60416e52e01970e0e8db
parent50c8f7d8f5f04c717ef4e72d873bf994c03efda0 (diff)
Add a NixOS test for receiving webmentions
-rw-r--r--flake.nix1
-rw-r--r--nixos-tests/tls/another.test-key.pem5
-rw-r--r--nixos-tests/tls/another.test.pem14
-rw-r--r--nixos-tests/tls/kittybox.test-key.pem5
-rw-r--r--nixos-tests/tls/kittybox.test.pem14
-rw-r--r--nixos-tests/tls/rootCA-key.pem5
-rw-r--r--nixos-tests/tls/rootCA.pem14
-rw-r--r--nixos-tests/webmention-test.nix161
-rw-r--r--nixos-tests/webmention-test/index.html17
9 files changed, 236 insertions, 0 deletions
diff --git a/flake.nix b/flake.nix
index ec4d07e..c844c23 100644
--- a/flake.nix
+++ b/flake.nix
@@ -45,6 +45,7 @@
       distributed-test = pkgs.nixosTest (import ./nixos-tests/distributed-test.nix self);
       nixos-test = pkgs.nixosTest (import ./nixos-tests/smoke-test.nix self);
       nixos-test-postgres = pkgs.nixosTest (import ./nixos-tests/postgres-smoke-test.nix self);
+      webmention-test = pkgs.nixosTest (import ./nixos-tests/webmention-test.nix self);
       dockerContainer = pkgs.callPackage ./docker.nix {
         inherit (self.packages.${system}) kittybox;
         rev = self.rev or "development";
diff --git a/nixos-tests/tls/another.test-key.pem b/nixos-tests/tls/another.test-key.pem
new file mode 100644
index 0000000..c2cbb5c
--- /dev/null
+++ b/nixos-tests/tls/another.test-key.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQguhPE9xYvArHAkSHP
+8BCrmiOd7rOGrxtGqyJQSD1pbvGhRANCAASNKi1rW9F6tXil0YKUWYVLTpqTAtKV
+wQ7RJwlwDDRgaxSMk0QxECFTEQUes7n1vU0mKbIQUeefGf8KPPptCffV
+-----END PRIVATE KEY-----
diff --git a/nixos-tests/tls/another.test.pem b/nixos-tests/tls/another.test.pem
new file mode 100644
index 0000000..478b458
--- /dev/null
+++ b/nixos-tests/tls/another.test.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAc6gAwIBAgIRANLB7mtbSrkcOqQcryKmOrkwCgYIKoZIzj0EAwIwdzEe
+MBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMSYwJAYDVQQLDB12aWthQGh5
+ZHJhbmdlYSAoVmlrYSBTaGxlaW5hKTEtMCsGA1UEAwwkbWtjZXJ0IHZpa2FAaHlk
+cmFuZ2VhIChWaWthIFNobGVpbmEpMB4XDTIzMDcyMjEyMjE1NFoXDTI1MTAyMjEy
+MjE1NFowUTEnMCUGA1UEChMebWtjZXJ0IGRldmVsb3BtZW50IGNlcnRpZmljYXRl
+MSYwJAYDVQQLDB12aWthQGh5ZHJhbmdlYSAoVmlrYSBTaGxlaW5hKTBZMBMGByqG
+SM49AgEGCCqGSM49AwEHA0IABI0qLWtb0Xq1eKXRgpRZhUtOmpMC0pXBDtEnCXAM
+NGBrFIyTRDEQIVMRBR6zufW9TSYpshBR558Z/wo8+m0J99WjYTBfMA4GA1UdDwEB
+/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAfBgNVHSMEGDAWgBTGE8Lizwk4
+Nhorkp+p0ekQaAwUUTAXBgNVHREEEDAOggxhbm90aGVyLnRlc3QwCgYIKoZIzj0E
+AwIDSAAwRQIgHCz9Uc4hEXC/kuM39og6lo/8KvPBGwODAFFYXve2VTICIQDXFPN/
+1ktPe2JN6YjQcsx9yyWoEddnNO5tMB9qYMTrIQ==
+-----END CERTIFICATE-----
diff --git a/nixos-tests/tls/kittybox.test-key.pem b/nixos-tests/tls/kittybox.test-key.pem
new file mode 100644
index 0000000..fa6bad9
--- /dev/null
+++ b/nixos-tests/tls/kittybox.test-key.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgfMGO8coQcyljcqqj
+oNhOmli9sgCROzmuZFrQEV2urSWhRANCAAQ8M/VbDZMqE6/XX33wCp53zg8nowbR
+s8KEcVQxzskwZVAvtZZ0x2ew5KFQ8edHgeaa940PY4ht/D4WVQp7Bsw2
+-----END PRIVATE KEY-----
diff --git a/nixos-tests/tls/kittybox.test.pem b/nixos-tests/tls/kittybox.test.pem
new file mode 100644
index 0000000..b966689
--- /dev/null
+++ b/nixos-tests/tls/kittybox.test.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKTCCAc+gAwIBAgIRAPThX+61LRz19hh72+NfcbYwCgYIKoZIzj0EAwIwdzEe
+MBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMSYwJAYDVQQLDB12aWthQGh5
+ZHJhbmdlYSAoVmlrYSBTaGxlaW5hKTEtMCsGA1UEAwwkbWtjZXJ0IHZpa2FAaHlk
+cmFuZ2VhIChWaWthIFNobGVpbmEpMB4XDTIzMDcyMjEyMjE1MFoXDTI1MTAyMjEy
+MjE1MFowUTEnMCUGA1UEChMebWtjZXJ0IGRldmVsb3BtZW50IGNlcnRpZmljYXRl
+MSYwJAYDVQQLDB12aWthQGh5ZHJhbmdlYSAoVmlrYSBTaGxlaW5hKTBZMBMGByqG
+SM49AgEGCCqGSM49AwEHA0IABDwz9VsNkyoTr9dfffAKnnfODyejBtGzwoRxVDHO
+yTBlUC+1lnTHZ7DkoVDx50eB5pr3jQ9jiG38PhZVCnsGzDajYjBgMA4GA1UdDwEB
+/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAfBgNVHSMEGDAWgBTGE8Lizwk4
+Nhorkp+p0ekQaAwUUTAYBgNVHREEETAPgg1raXR0eWJveC50ZXN0MAoGCCqGSM49
+BAMCA0gAMEUCIQCK88zCbTPtun5I2WUVEZVks/f72ZMwMoTiVbgEawOZ1wIgNYJj
+0TICe9+pHF+X+lVeRD5XQkNPMZ01yX7xkZ4MFIc=
+-----END CERTIFICATE-----
diff --git a/nixos-tests/tls/rootCA-key.pem b/nixos-tests/tls/rootCA-key.pem
new file mode 100644
index 0000000..85afa50
--- /dev/null
+++ b/nixos-tests/tls/rootCA-key.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg7f8suVXaG0xCp1dF
+V1SyPIhRqzSb5g/AySCLp8Bsb4uhRANCAAThxEpowhTWa/nRg9dnumEejfXSbEqr
+kVG44TM5b4ajIT3136i0zGckd6LUHdDVDdyWrMWsA2qh2zuGNR0eoA7A
+-----END PRIVATE KEY-----
diff --git a/nixos-tests/tls/rootCA.pem b/nixos-tests/tls/rootCA.pem
new file mode 100644
index 0000000..d587f0f
--- /dev/null
+++ b/nixos-tests/tls/rootCA.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICMTCCAdegAwIBAgIQcKvCMHSr70sFBFi31Pu0+TAKBggqhkjOPQQDAjB3MR4w
+HAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExJjAkBgNVBAsMHXZpa2FAaHlk
+cmFuZ2VhIChWaWthIFNobGVpbmEpMS0wKwYDVQQDDCRta2NlcnQgdmlrYUBoeWRy
+YW5nZWEgKFZpa2EgU2hsZWluYSkwHhcNMjMwNzIyMTIyMTUwWhcNMzMwNzIyMTIy
+MTUwWjB3MR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExJjAkBgNVBAsM
+HXZpa2FAaHlkcmFuZ2VhIChWaWthIFNobGVpbmEpMS0wKwYDVQQDDCRta2NlcnQg
+dmlrYUBoeWRyYW5nZWEgKFZpa2EgU2hsZWluYSkwWTATBgcqhkjOPQIBBggqhkjO
+PQMBBwNCAAThxEpowhTWa/nRg9dnumEejfXSbEqrkVG44TM5b4ajIT3136i0zGck
+d6LUHdDVDdyWrMWsA2qh2zuGNR0eoA7Ao0UwQzAOBgNVHQ8BAf8EBAMCAgQwEgYD
+VR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUxhPC4s8JODYaK5KfqdHpEGgMFFEw
+CgYIKoZIzj0EAwIDSAAwRQIhAJPi574bAnDUl5Kq6sEUltFMNkux88UjJm5nv54Q
+UTAeAiABVoRLoYBeF4sNKJVZ6oyfLiCCGyqxrI3C88IJsAgizg==
+-----END CERTIFICATE-----
diff --git a/nixos-tests/webmention-test.nix b/nixos-tests/webmention-test.nix
new file mode 100644
index 0000000..2161e88
--- /dev/null
+++ b/nixos-tests/webmention-test.nix
@@ -0,0 +1,161 @@
+kittybox:
+{ lib, ... }: let
+  hosts = ''
+    192.168.2.101 kittybox.test
+    192.168.2.102 another.test
+  '';
+in {
+  name = "nixos-kittybox";
+
+  nodes = {
+    kittybox = { config, pkgs, lib, ... }: {
+      imports = [ kittybox.nixosModules.default ];
+
+      services.postgresql = {
+        enable = true;
+        ensureDatabases = ["kittybox"];
+        ensureUsers = [ {
+          name = "kittybox";
+          ensurePermissions = {
+            "DATABASE kittybox" = "ALL PRIVILEGES";
+          };
+        } ];
+      };
+
+      networking = {
+        interfaces.eth1 = {
+          ipv4.addresses = [
+            { address = "192.168.2.101"; prefixLength = 24; }
+          ];
+        };
+        extraHosts = hosts;
+        firewall.allowedTCPPorts = [ 443 ];
+        firewall.allowedUDPPorts = [ 443 ];
+      };
+
+      
+      services.kittybox = {
+        enable = true;
+        logLevel = "info,kittybox=debug,retainer::cache=warn,h2=warn,rustls=warn";
+        backendUri = "postgres://localhost?host=/run/postgresql&dbname=kittybox";
+        jobQueueUri = config.services.kittybox.backendUri;
+      };
+
+      systemd.services.kittybox.wants = [ "postgresql.service" ];
+      systemd.services.kittybox.after = [ "postgresql.service" ];
+      systemd.services.kittybox.environment = {
+        "KITTYBOX_CUSTOM_PKI_ROOTS" = ./tls/rootCA.pem;
+      };
+
+      environment.systemPackages = with pkgs; [
+        xh
+      ];
+
+      services.nginx = {
+        enable = true;
+        recommendedProxySettings = true;
+        virtualHosts = {
+          "kittybox.test" = {
+            forceSSL = true;
+            sslCertificate = ./tls/kittybox.test.pem;
+            sslCertificateKey = ./tls/kittybox.test-key.pem;
+            locations = {
+              "/" = {
+                proxyPass = "http://localhost:8080";
+              };
+            };
+          };
+        };
+      };
+
+      security.pki.certificates = [
+        (builtins.readFile ./tls/rootCA.pem)
+      ];
+    };
+
+    another = { config, pkgs, lib, ... }: {
+      networking = {
+        interfaces.eth1 = {
+          ipv4.addresses = [
+            { address = "192.168.2.102"; prefixLength = 24; }
+          ];
+        };
+        extraHosts = hosts;
+        firewall.allowedTCPPorts = [ 443 ];
+        firewall.allowedUDPPorts = [ 443 ];
+      };
+
+      services.nginx = {
+        enable = true;
+        virtualHosts = {
+          "another.test" = {
+            forceSSL = true;
+            sslCertificate = ./tls/another.test.pem;
+            sslCertificateKey = ./tls/another.test-key.pem;
+            locations = {
+              "/" = {
+                root = ./webmention-test;
+              };
+            };
+          };
+        };
+      };
+
+      environment.systemPackages = with pkgs; [
+        xh
+      ];
+
+      security.pki.certificates = [
+        (builtins.readFile ./tls/rootCA.pem)
+      ];
+    };
+  };
+
+  testScript = ''
+    import json
+    import shlex
+    import time
+
+    post_mf2 = {
+        "type": ["h-entry"],
+        "properties": {
+            "uid": ["https://kittybox.test/posts/test-post"],
+            "url": ["https://kittybox.test/posts/test-post"],
+            "published": ["2023-07-22T14:04:53+0300"],
+            "content": [{"html": "<p>Hello! This is a test post.</p>"}],
+            "author": ["https://kittybox.test/"],
+        }
+    }
+
+    start_all()
+
+    with subtest("Verify that Kittybox started correctly..."):
+        kittybox.wait_for_unit("default.target")
+        kittybox.succeed("xh --no-check-status https://kittybox.test/.kittybox/micropub")
+
+    with subtest("Onboarding should correctly work..."):
+        kittybox.copy_from_host("${./onboarding.json}", "/root/onboarding.json")
+        kittybox.succeed("xh --follow https://kittybox.test/.kittybox/onboarding -j @/root/onboarding.json")
+        # Testing for a known string is the easiest way to determine that the onboarding worked
+        kittybox.succeed("xh https://kittybox.test/ | grep 'vestige of the past long gone'")
+
+    with subtest("The other host should also be reachable..."):
+        another.wait_for_unit("default.target")
+        another.succeed("xh https://another.test/ | grep 'This is a test webmention.'")
+
+    with subtest("Kittybox accepts a webmention to a valid post..."):
+        # Note: we don't really have a way to "authenticate" here.
+        # Let's insert the post manually.
+        print(kittybox.succeed("sudo -u postgres psql kittybox -c \"INSERT INTO kittybox.mf2_json (uid, mf2, owner) VALUES ('https://kittybox.test/posts/test-post', '" + json.dumps(post_mf2).replace("\"", "\\\"").replace("'", "'" * 2) + "', 'kittybox.test') RETURNING uid\""))
+        print(kittybox.succeed("sudo -u postgres psql -A kittybox -c \"SELECT mf2 FROM kittybox.mf2_json WHERE uid = 'https://kittybox.test/posts/test-post'\""))
+        kittybox.succeed("xh --verify ${./tls/rootCA.pem} https://kittybox.test/posts/test-post")
+
+        another.succeed("xh --verify ${./tls/rootCA.pem} https://kittybox.test/.kittybox/webmention --form source=https://another.test/index.html target=https://kittybox.test/posts/test-post")
+        # Wait a while to let the async tasks settle...
+        time.sleep(2)
+        # Ensure the webmention has propagated
+        # Kittybox doesn't fully render them yet, but the counters are there
+        kittybox.succeed("xh --verify ${./tls/rootCA.pem} https://kittybox.test/posts/test-post | grep " + shlex.quote('<span class="icon" aria-label="replies">💬</span><span class="counter">1</span>'))
+        
+'';
+}
diff --git a/nixos-tests/webmention-test/index.html b/nixos-tests/webmention-test/index.html
new file mode 100644
index 0000000..d5694cd
--- /dev/null
+++ b/nixos-tests/webmention-test/index.html
@@ -0,0 +1,17 @@
+<html>
+  <head>
+    <title>Test webmention</title>
+  </head>
+
+  <body>
+    <article class="h-entry">
+      <h1><a href="https://another.test/index.html" class="u-url u-uid p-name">Test webmention</a></h1>
+      <p>In reply to: <a class="u-in-reply-to" href="https://kittybox.test/posts/test-post"></p>
+      <p>Published on: <time class="dt-published" datetime="2023-07-22T13:49:22+0300">2023-07-22 13:49:22 MSK</time></p>
+
+      <main class="e-content">
+        <p>Hello! This is a test webmention.</p>
+      </main>
+    </article>
+  </body>
+</html>