# 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; inherit (pkgs) lib; 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 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.elasticsearch-oss; environment.systemPackages = [ (sendEmail "dmarc@localhost") pkgs.jq ]; }; testScript = { nodes }: let esPort = toString nodes.parsedmarc.config.services.elasticsearch.port; valueObject = lib.optionalString (lib.versionAtLeast nodes.parsedmarc.config.services.elasticsearch.package.version "7") ".value"; 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" + " | tee /dev/console" + " | jq -es 'if . == [] then null else .[] | .hits.total${valueObject} > 0 end'" ) parsedmarc.succeed("send-email") parsedmarc.wait_until_succeeds( "curl -sS -f http://localhost:${esPort}/_search?q=report_id:2940" + " | tee /dev/console" + " | jq -es 'if . == [] then null else .[] | .hits.total${valueObject} > 0 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 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.elasticsearch-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; valueObject = lib.optionalString (lib.versionAtLeast nodes.parsedmarc.config.services.elasticsearch.package.version "7") ".value"; 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" + " | tee /dev/console" + " | jq -es 'if . == [] then null else .[] | .hits.total${valueObject} > 0 end'" ) mail.succeed("send-email") parsedmarc.wait_until_succeeds( "curl -sS -f http://localhost:${esPort}/_search?q=report_id:2940" + " | tee /dev/console" + " | jq -es 'if . == [] then null else .[] | .hits.total${valueObject} > 0 end'" ) ''; }; }