2 certs = import ./common/acme/server/snakeoil-certs.nix;
5 import ./make-test-python.nix {
7 nodes.machine = { pkgs, ... }: {
8 imports = [ ./common/user-account.nix ];
11 enableSubmission = true;
12 tlsTrustedAuthorities = "${certs.ca.cert}";
13 sslCert = "${certs.${domain}.cert}";
14 sslKey = "${certs.${domain}.key}";
16 destination = [ domain ];
17 localRecipients = [ "root" "alice" "bob" ];
19 services.schleuder = {
21 # Don't do it like this in production! The point of this setting
22 # is to allow loading secrets from _outside_ the world-readable
24 extraSettingsFile = pkgs.writeText "schleuder-api-keys.yml" ''
29 lists = [ "security@${domain}" ];
31 tls_cert_file = "${certs.${domain}.cert}";
32 tls_key_file = "${certs.${domain}.key}";
36 environment.systemPackages = [
39 (pkgs.writeScriptBin "do-test" ''
40 #!${pkgs.runtimeShell}
43 # Generate a GPG key with no passphrase and export it
44 sudo -u alice gpg --passphrase-fd 0 --batch --yes --quick-generate-key 'alice@${domain}' rsa4096 sign,encr < <(echo)
45 sudo -u alice gpg --armor --export alice@${domain} > alice.asc
46 # Create a new mailing list with alice as the owner, and alice's key
47 schleuder-cli list new security@${domain} alice@${domain} alice.asc
49 # Send an email from a non-member of the list. Use --auto-from so we don't have to specify who it's from twice.
50 msmtp --auto-from security@${domain} --host=${domain} --port=25 --tls --tls-starttls <<EOF
51 Subject: really big security issue!!
54 I found a big security problem!
58 (set +o pipefail; journalctl -f -n 1000 -u postfix | grep -m 1 'delivered to maildir')
60 # There should be exactly one email
61 mail=(/var/spool/mail/alice/new/*)
62 [[ "''${#mail[@]}" = 1 ]]
64 # Find the fingerprint of the mailing list key
65 read list_key_fp address < <(schleuder-cli keys list security@${domain} | grep security@)
66 schleuder-cli keys export security@${domain} $list_key_fp > list.asc
68 # Import the key into alice's keyring, so we can verify it as well as decrypting
69 sudo -u alice gpg --import <list.asc
70 # And perform the decryption.
71 sudo -u alice gpg -d $mail >decrypted
72 # And check that the text matches.
73 grep "big security problem" decrypted
77 # pkgs.vim pkgs.openssl pkgs.sqliteinteractive
80 security.pki.certificateFiles = [ certs.ca.cert ];
82 # Since we don't have internet here, use dnsmasq to provide MX records from /etc/hosts
85 settings.selfmx = true;
88 networking.extraHosts = ''
92 # schleuder-cli's config is not quite optimal in several ways:
93 # - A fingerprint _must_ be pinned, it doesn't even have an option
95 # - It compares certificate fingerprints rather than key
96 # fingerprints, so renewals break the pin (though that's not
97 # relevant for this test)
98 # - It compares them as strings, which means we need to match the
99 # expected format exactly. This means removing the :s and
102 # https://0xacab.org/schleuder/schleuder-cli/-/issues/16
103 # https://0xacab.org/schleuder/schleuder-cli/-/blob/f8895b9f47083d8c7b99a2797c93f170f3c6a3c0/lib/schleuder-cli/helper.rb#L230-238
104 systemd.tmpfiles.rules = let cliconfig = pkgs.runCommand "schleuder-cli.yml"
106 nativeBuildInputs = [ pkgs.jq pkgs.openssl ];
108 fp=$(openssl x509 -in ${certs.${domain}.cert} -noout -fingerprint -sha256 | cut -d = -f 2 | tr -d : | tr 'A-Z' 'a-z')
112 tls_fingerprint: "$fp"
117 "L+ /root/.schleuder-cli/schleuder-cli.yml - - - - ${cliconfig}"
122 machine.wait_for_unit("multi-user.target")
123 machine.wait_until_succeeds("nc -z localhost 4443")
124 machine.succeed("do-test")