From d46e78fd76f9b27bc3b8203dc16aa21371ea1bbd Mon Sep 17 00:00:00 2001 From: talyz Date: Wed, 2 Jun 2021 18:19:37 +0200 Subject: [PATCH] nixos/parsedmarc: Add test --- nixos/tests/all-tests.nix | 1 + nixos/tests/parsedmarc/default.nix | 224 ++++++++++++++++++ .../python-modules/parsedmarc/default.nix | 2 + 3 files changed, 227 insertions(+) create mode 100644 nixos/tests/parsedmarc/default.nix diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 6baa986b2bda..dab99dd8d043 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -336,6 +336,7 @@ in pam-u2f = handleTest ./pam-u2f.nix {}; pantheon = handleTest ./pantheon.nix {}; paperless-ng = handleTest ./paperless-ng.nix {}; + parsedmarc = handleTest ./parsedmarc {}; pdns-recursor = handleTest ./pdns-recursor.nix {}; peerflix = handleTest ./peerflix.nix {}; pgjwt = handleTest ./pgjwt.nix {}; diff --git a/nixos/tests/parsedmarc/default.nix b/nixos/tests/parsedmarc/default.nix new file mode 100644 index 000000000000..d838d3b6a39c --- /dev/null +++ b/nixos/tests/parsedmarc/default.nix @@ -0,0 +1,224 @@ +# This tests parsedmarc by sending a report to its monitored email +# address and reading the results out of Elasticsearch. + +{ pkgs, ... }@args: +let + inherit (import ../../lib/testing-python.nix args) makeTest; + + dmarcTestReport = builtins.fetchurl { + name = "dmarc-test-report"; + url = "https://github.com/domainaware/parsedmarc/raw/f45ab94e0608088e0433557608d9f4e9517d3afe/samples/aggregate/estadocuenta1.infonacot.gob.mx!example.com!1536853302!1536939702!2940.xml.zip"; + sha256 = "0dq64cj49711kbja27pjl2hy0d3azrjxg91kqrh40x46fkn1dwkx"; + }; + + sendEmail = address: + pkgs.writeScriptBin "send-email" '' + #!${pkgs.python3.interpreter} + import smtplib + from email import encoders + from email.mime.base import MIMEBase + from email.mime.multipart import MIMEMultipart + from email.mime.text import MIMEText + + sender_email = "dmarc_tester@fake.domain" + receiver_email = "${address}" + + message = MIMEMultipart() + message["From"] = sender_email + message["To"] = receiver_email + message["Subject"] = "DMARC test" + + message.attach(MIMEText("Testing parsedmarc", "plain")) + + attachment = MIMEBase("application", "zip") + + with open("${dmarcTestReport}", "rb") as report: + attachment.set_payload(report.read()) + + encoders.encode_base64(attachment) + + attachment.add_header( + "Content-Disposition", + "attachment; filename= estadocuenta1.infonacot.gob.mx!example.com!1536853302!1536939702!2940.xml.zip", + ) + + message.attach(attachment) + text = message.as_string() + + with smtplib.SMTP('localhost') as server: + server.sendmail(sender_email, receiver_email, text) + server.quit() + ''; +in +{ + localMail = makeTest + { + name = "parsedmarc-local-mail"; + meta = with pkgs.lib.maintainers; { + maintainers = [ talyz ]; + }; + + nodes.parsedmarc = + { nodes, ... }: + { + virtualisation.memorySize = 2048; + + services.postfix = { + enableSubmission = true; + enableSubmissions = true; + submissionsOptions = { + smtpd_sasl_auth_enable = "yes"; + smtpd_client_restrictions = "permit"; + }; + }; + + services.parsedmarc = { + enable = true; + provision = { + geoIp = false; + localMail = { + enable = true; + hostname = "localhost"; + }; + }; + }; + + services.elasticsearch.package = pkgs.elasticsearch7-oss; + + environment.systemPackages = [ + (sendEmail "dmarc@localhost") + pkgs.jq + ]; + }; + + testScript = { nodes }: + let + esPort = toString nodes.parsedmarc.config.services.elasticsearch.port; + in '' + parsedmarc.start() + parsedmarc.wait_for_unit("postfix.service") + parsedmarc.wait_for_unit("dovecot2.service") + parsedmarc.wait_for_unit("parsedmarc.service") + parsedmarc.wait_until_succeeds( + "curl -sS -f http://localhost:${esPort}" + ) + + parsedmarc.fail( + "curl -sS -f http://localhost:${esPort}/_search?q=report_id:2940 | jq -e 'if .hits.total.value > 0 then true else null end'" + ) + parsedmarc.succeed("send-email") + parsedmarc.wait_until_succeeds( + "curl -sS -f http://localhost:${esPort}/_search?q=report_id:2940 | jq -e 'if .hits.total.value > 0 then true else null end'" + ) + ''; + }; + + externalMail = + let + certs = import ../common/acme/server/snakeoil-certs.nix; + mailDomain = certs.domain; + parsedmarcDomain = "parsedmarc.fake.domain"; + in + makeTest { + name = "parsedmarc-external-mail"; + meta = with pkgs.lib.maintainers; { + maintainers = [ talyz ]; + }; + + nodes = { + parsedmarc = + { nodes, ... }: + { + virtualisation.memorySize = 2048; + + security.pki.certificateFiles = [ + certs.ca.cert + ]; + + networking.extraHosts = '' + 127.0.0.1 ${parsedmarcDomain} + ${nodes.mail.config.networking.primaryIPAddress} ${mailDomain} + ''; + + services.parsedmarc = { + enable = true; + provision.geoIp = false; + settings.imap = { + host = mailDomain; + port = 993; + ssl = true; + user = "alice"; + password = "${pkgs.writeText "imap-password" "foobar"}"; + watch = true; + }; + }; + + services.elasticsearch.package = pkgs.elasticsearch7-oss; + + environment.systemPackages = [ + pkgs.jq + ]; + }; + + mail = + { nodes, ... }: + { + imports = [ ../common/user-account.nix ]; + + networking.extraHosts = '' + 127.0.0.1 ${mailDomain} + ${nodes.parsedmarc.config.networking.primaryIPAddress} ${parsedmarcDomain} + ''; + + services.dovecot2 = { + enable = true; + protocols = [ "imap" ]; + sslCACert = "${certs.ca.cert}"; + sslServerCert = "${certs.${mailDomain}.cert}"; + sslServerKey = "${certs.${mailDomain}.key}"; + }; + + services.postfix = { + enable = true; + origin = mailDomain; + config = { + myhostname = mailDomain; + mydestination = mailDomain; + }; + enableSubmission = true; + enableSubmissions = true; + submissionsOptions = { + smtpd_sasl_auth_enable = "yes"; + smtpd_client_restrictions = "permit"; + }; + }; + environment.systemPackages = [ (sendEmail "alice@${mailDomain}") ]; + + networking.firewall.allowedTCPPorts = [ 993 ]; + }; + }; + + testScript = { nodes }: + let + esPort = toString nodes.parsedmarc.config.services.elasticsearch.port; + in '' + mail.start() + mail.wait_for_unit("postfix.service") + mail.wait_for_unit("dovecot2.service") + + parsedmarc.start() + parsedmarc.wait_for_unit("parsedmarc.service") + parsedmarc.wait_until_succeeds( + "curl -sS -f http://localhost:${esPort}" + ) + + parsedmarc.fail( + "curl -sS -f http://localhost:${esPort}/_search?q=report_id:2940 | jq -e 'if .hits.total.value > 0 then true else null end'" + ) + mail.succeed("send-email") + parsedmarc.wait_until_succeeds( + "curl -sS -f http://localhost:${esPort}/_search?q=report_id:2940 | jq -e 'if .hits.total.value > 0 then true else null end'" + ) + ''; + }; +} diff --git a/pkgs/development/python-modules/parsedmarc/default.nix b/pkgs/development/python-modules/parsedmarc/default.nix index a19c00b004a6..b9fb35016c3b 100644 --- a/pkgs/development/python-modules/parsedmarc/default.nix +++ b/pkgs/development/python-modules/parsedmarc/default.nix @@ -3,6 +3,7 @@ , fetchurl , pythonOlder , lib +, nixosTests # pythonPackages , tqdm @@ -61,6 +62,7 @@ buildPythonPackage rec { passthru = { inherit dashboard; + tests = nixosTests.parsedmarc; }; meta = {