diff options
Diffstat (limited to 'nixos/tests/schleuder.nix')
-rw-r--r-- | nixos/tests/schleuder.nix | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/nixos/tests/schleuder.nix b/nixos/tests/schleuder.nix new file mode 100644 index 0000000000000..a9e4cc325bc76 --- /dev/null +++ b/nixos/tests/schleuder.nix @@ -0,0 +1,128 @@ +let + certs = import ./common/acme/server/snakeoil-certs.nix; + domain = certs.domain; +in +import ./make-test-python.nix { + name = "schleuder"; + nodes.machine = { pkgs, ... }: { + imports = [ ./common/user-account.nix ]; + services.postfix = { + enable = true; + enableSubmission = true; + tlsTrustedAuthorities = "${certs.ca.cert}"; + sslCert = "${certs.${domain}.cert}"; + sslKey = "${certs.${domain}.key}"; + inherit domain; + destination = [ domain ]; + localRecipients = [ "root" "alice" "bob" ]; + }; + services.schleuder = { + enable = true; + # Don't do it like this in production! The point of this setting + # is to allow loading secrets from _outside_ the world-readable + # Nix store. + extraSettingsFile = pkgs.writeText "schleuder-api-keys.yml" '' + api: + valid_api_keys: + - fnord + ''; + lists = [ "security@${domain}" ]; + settings.api = { + tls_cert_file = "${certs.${domain}.cert}"; + tls_key_file = "${certs.${domain}.key}"; + }; + }; + + environment.systemPackages = [ + pkgs.gnupg + pkgs.msmtp + (pkgs.writeScriptBin "do-test" '' + #!${pkgs.runtimeShell} + set -exuo pipefail + + # Generate a GPG key with no passphrase and export it + sudo -u alice gpg --passphrase-fd 0 --batch --yes --quick-generate-key 'alice@${domain}' rsa4096 sign,encr < <(echo) + sudo -u alice gpg --armor --export alice@${domain} > alice.asc + # Create a new mailing list with alice as the owner, and alice's key + schleuder-cli list new security@${domain} alice@${domain} alice.asc + + # 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. + msmtp --auto-from security@${domain} --host=${domain} --port=25 --tls --tls-starttls <<EOF + Subject: really big security issue!! + From: root@${domain} + + I found a big security problem! + EOF + + # Wait for delivery + (set +o pipefail; journalctl -f -n 1000 -u postfix | grep -m 1 'delivered to maildir') + + # There should be exactly one email + mail=(/var/spool/mail/alice/new/*) + [[ "''${#mail[@]}" = 1 ]] + + # Find the fingerprint of the mailing list key + read list_key_fp address < <(schleuder-cli keys list security@${domain} | grep security@) + schleuder-cli keys export security@${domain} $list_key_fp > list.asc + + # Import the key into alice's keyring, so we can verify it as well as decrypting + sudo -u alice gpg --import <list.asc + # And perform the decryption. + sudo -u alice gpg -d $mail >decrypted + # And check that the text matches. + grep "big security problem" decrypted + '') + + # For debugging: + # pkgs.vim pkgs.openssl pkgs.sqliteinteractive + ]; + + security.pki.certificateFiles = [ certs.ca.cert ]; + + # Since we don't have internet here, use dnsmasq to provide MX records from /etc/hosts + services.dnsmasq = { + enable = true; + extraConfig = '' + selfmx + ''; + }; + + networking.extraHosts = '' + 127.0.0.1 ${domain} + ''; + + # schleuder-cli's config is not quite optimal in several ways: + # - A fingerprint _must_ be pinned, it doesn't even have an option + # to trust the PKI + # - It compares certificate fingerprints rather than key + # fingerprints, so renewals break the pin (though that's not + # relevant for this test) + # - It compares them as strings, which means we need to match the + # expected format exactly. This means removing the :s and + # lowercasing it. + # Refs: + # https://0xacab.org/schleuder/schleuder-cli/-/issues/16 + # https://0xacab.org/schleuder/schleuder-cli/-/blob/f8895b9f47083d8c7b99a2797c93f170f3c6a3c0/lib/schleuder-cli/helper.rb#L230-238 + systemd.tmpfiles.rules = let cliconfig = pkgs.runCommand "schleuder-cli.yml" + { + nativeBuildInputs = [ pkgs.jq pkgs.openssl ]; + } '' + fp=$(openssl x509 -in ${certs.${domain}.cert} -noout -fingerprint -sha256 | cut -d = -f 2 | tr -d : | tr 'A-Z' 'a-z') + cat > $out <<EOF + host: localhost + port: 4443 + tls_fingerprint: "$fp" + api_key: fnord + EOF + ''; in + [ + "L+ /root/.schleuder-cli/schleuder-cli.yml - - - - ${cliconfig}" + ]; + }; + + testScript = '' + machine.wait_for_unit("multi-user.target") + machine.wait_until_succeeds("nc -z localhost 4443") + machine.succeed("do-test") + ''; +} |