about summary refs log tree commit diff stats
path: root/tests/by-name/em/email-http
diff options
context:
space:
mode:
Diffstat (limited to 'tests/by-name/em/email-http')
-rw-r--r--tests/by-name/em/email-http/nodes/mail_server.nix57
-rw-r--r--tests/by-name/em/email-http/nodes/user.nix26
-rw-r--r--tests/by-name/em/email-http/test.nix100
3 files changed, 183 insertions, 0 deletions
diff --git a/tests/by-name/em/email-http/nodes/mail_server.nix b/tests/by-name/em/email-http/nodes/mail_server.nix
new file mode 100644
index 0000000..e94c4e9
--- /dev/null
+++ b/tests/by-name/em/email-http/nodes/mail_server.nix
@@ -0,0 +1,57 @@
+{
+  extraModules,
+  pkgs,
+  vhackPackages,
+}: {
+  mkMailServer = serverName: principal: {
+    config,
+    lib,
+    nodes,
+    ...
+  }: {
+    imports =
+      extraModules
+      ++ [
+        ../../../../../modules
+        ../../../../common/acme/client.nix
+      ];
+
+    environment.systemPackages = [
+      pkgs.bind
+      pkgs.openssl
+    ];
+
+    networking.nameservers = lib.mkForce [
+      nodes.name_server.networking.primaryIPAddress
+      nodes.name_server.networking.primaryIPv6Address
+    ];
+
+    age.identityPaths = ["${../../../../common/email/hostKey}"];
+
+    vhack = {
+      stalwart-mail = {
+        enable = true;
+        fqdn = "${serverName}.server.com";
+        admin = "admin@${serverName}.server.com";
+        security = {
+          dkimKeys = let
+            loadKey = name: {
+              dkimPublicKey = builtins.readFile (../../../../common/email/dkim + "/${name}/public");
+              dkimPrivateKeyPath = ../../../../common/email/dkim + "/${name}/private.age";
+              keyAlgorithm = "ed25519-sha256";
+            };
+          in {
+            "mail.server.com" = loadKey "mail1.server.com";
+            "bob.com" = loadKey "bob.com";
+          };
+          verificationMode = "strict";
+        };
+        openFirewall = true;
+        principals =
+          if principal == null
+          then null
+          else [principal];
+      };
+    };
+  };
+}
diff --git a/tests/by-name/em/email-http/nodes/user.nix b/tests/by-name/em/email-http/nodes/user.nix
new file mode 100644
index 0000000..73b9ff7
--- /dev/null
+++ b/tests/by-name/em/email-http/nodes/user.nix
@@ -0,0 +1,26 @@
+{
+  pkgs,
+  vhackPackages,
+}: {
+  mkUser = user: serverName: {
+    nodes,
+    lib,
+    ...
+  }: {
+    imports = [
+      ../../../../common/acme/client.nix
+    ];
+
+    environment.systemPackages = [
+      pkgs.bind
+      pkgs.openssl
+    ];
+
+    networking.nameservers = lib.mkForce [
+      nodes.name_server.networking.primaryIPAddress
+      nodes.name_server.networking.primaryIPv6Address
+    ];
+
+    users.users."${user}" = {isNormalUser = true;};
+  };
+}
diff --git a/tests/by-name/em/email-http/test.nix b/tests/by-name/em/email-http/test.nix
new file mode 100644
index 0000000..82b4c45
--- /dev/null
+++ b/tests/by-name/em/email-http/test.nix
@@ -0,0 +1,100 @@
+{
+  nixos-lib,
+  pkgsUnstable,
+  nixpkgs-unstable,
+  vhackPackages,
+  pkgs,
+  extraModules,
+  nixLib,
+  ...
+}: let
+  mail_server = import ./nodes/mail_server.nix {inherit extraModules pkgs vhackPackages;};
+  inherit (mail_server) mkMailServer;
+  user = import ./nodes/user.nix {inherit pkgs vhackPackages;};
+  inherit (user) mkUser;
+in
+  nixos-lib.runTest {
+    hostPkgs = pkgs; # the Nixpkgs package set used outside the VMs
+
+    name = "email-http";
+
+    node = {
+      specialArgs = {inherit pkgsUnstable vhackPackages nixpkgs-unstable nixLib;};
+
+      # Use the nixpkgs as constructed by the `nixpkgs.*` options
+      pkgs = null;
+    };
+
+    nodes = {
+      acme = {
+        nodes,
+        lib,
+        ...
+      }: {
+        imports = [
+          ../../../common/acme/server.nix
+          ../../../common/dns/client.nix
+        ];
+      };
+
+      name_server = {nodes, ...}: {
+        imports =
+          extraModules
+          ++ [
+            ../../../common/acme/client.nix
+            ../../../common/dns/server.nix
+          ];
+
+        vhack.dns.zones = {
+          "mail.server.com" = {
+            SOA = {
+              nameServer = "ns";
+              adminEmail = "admin@server.com";
+              serial = 2025012301;
+            };
+            useOrigin = false;
+
+            A = [
+              nodes.mail_server.networking.primaryIPAddress
+            ];
+            AAAA = [
+              nodes.mail_server.networking.primaryIPv6Address
+            ];
+          };
+        };
+      };
+
+      mail_server = mkMailServer "mail" null;
+
+      bob = mkUser "bob" "mail";
+    };
+
+    # TODO(@bpeetz): This test should also test the http JMAP features of stalwart-mail. <2025-04-12>
+    testScript = _: let
+      acme = import ../../../common/acme {inherit pkgs;};
+    in
+      acme.prepare ["mail_server" "bob"]
+      # Python
+      ''
+        mail_server.wait_for_unit("stalwart-mail.service")
+        mail_server.wait_for_open_port(993) # imap
+        mail_server.wait_for_open_port(465) # smtp
+
+        bob.wait_for_unit("multi-user.target")
+
+        with subtest("The mailserver successfully started all services"):
+          import json
+          def all_services_running(host):
+            (status, output) = host.systemctl("list-units --state=failed --plain --no-pager --output=json")
+            host_failed = json.loads(output)
+            assert len(host_failed) == 0, f"Expected zero failing services, but found: {json.dumps(host_failed, indent=4)}"
+          all_services_running(mail_server)
+
+        with subtest("Bob can use the self-service interface"):
+          bob.succeed("${pkgs.writeShellScript "check-self-service" ''
+          curl mail.server.com --location --output /home/bob/output.html;
+        ''}")
+
+        bob.copy_from_vm("/home/bob", "")
+      '';
+  }