at master 7.3 kB view raw
1# This tests parsedmarc by sending a report to its monitored email 2# address and reading the results out of Elasticsearch. 3 4{ pkgs, ... }@args: 5let 6 inherit (import ../../lib/testing-python.nix args) makeTest; 7 inherit (pkgs) lib; 8 9 dmarcTestReport = builtins.fetchurl { 10 name = "dmarc-test-report"; 11 url = "https://github.com/domainaware/parsedmarc/raw/f45ab94e0608088e0433557608d9f4e9517d3afe/samples/aggregate/estadocuenta1.infonacot.gob.mx!example.com!1536853302!1536939702!2940.xml.zip"; 12 sha256 = "0dq64cj49711kbja27pjl2hy0d3azrjxg91kqrh40x46fkn1dwkx"; 13 }; 14 15 sendEmail = 16 address: 17 pkgs.writeScriptBin "send-email" '' 18 #!${pkgs.python3.interpreter} 19 import smtplib 20 from email import encoders 21 from email.mime.base import MIMEBase 22 from email.mime.multipart import MIMEMultipart 23 from email.mime.text import MIMEText 24 25 sender_email = "dmarc_tester@fake.domain" 26 receiver_email = "${address}" 27 28 message = MIMEMultipart() 29 message["From"] = sender_email 30 message["To"] = receiver_email 31 message["Subject"] = "DMARC test" 32 33 message.attach(MIMEText("Testing parsedmarc", "plain")) 34 35 attachment = MIMEBase("application", "zip") 36 37 with open("${dmarcTestReport}", "rb") as report: 38 attachment.set_payload(report.read()) 39 40 encoders.encode_base64(attachment) 41 42 attachment.add_header( 43 "Content-Disposition", 44 "attachment; filename= estadocuenta1.infonacot.gob.mx!example.com!1536853302!1536939702!2940.xml.zip", 45 ) 46 47 message.attach(attachment) 48 text = message.as_string() 49 50 with smtplib.SMTP('localhost') as server: 51 server.sendmail(sender_email, receiver_email, text) 52 server.quit() 53 ''; 54in 55{ 56 localMail = makeTest { 57 name = "parsedmarc-local-mail"; 58 meta = with lib.maintainers; { 59 maintainers = [ talyz ]; 60 }; 61 62 nodes.parsedmarc = 63 { nodes, ... }: 64 { 65 virtualisation.memorySize = 2048; 66 67 services.postfix = { 68 enableSubmission = true; 69 enableSubmissions = true; 70 submissionsOptions = { 71 smtpd_sasl_auth_enable = "yes"; 72 smtpd_client_restrictions = "permit"; 73 }; 74 }; 75 76 services.parsedmarc = { 77 enable = true; 78 provision = { 79 geoIp = false; 80 localMail = { 81 enable = true; 82 hostname = "localhost"; 83 }; 84 }; 85 }; 86 87 environment.systemPackages = [ 88 (sendEmail "dmarc@localhost") 89 pkgs.jq 90 ]; 91 }; 92 93 testScript = 94 { nodes }: 95 let 96 esPort = toString nodes.parsedmarc.config.services.elasticsearch.port; 97 valueObject = lib.optionalString (lib.versionAtLeast nodes.parsedmarc.config.services.elasticsearch.package.version "7") ".value"; 98 in 99 '' 100 parsedmarc.start() 101 parsedmarc.wait_for_unit("postfix.service") 102 parsedmarc.wait_for_unit("dovecot2.service") 103 parsedmarc.wait_for_unit("parsedmarc.service") 104 parsedmarc.wait_until_succeeds( 105 "curl -sS -f http://localhost:${esPort}" 106 ) 107 108 parsedmarc.fail( 109 "curl -sS -f http://localhost:${esPort}/_search?q=report_id:2940" 110 + " | tee /dev/console" 111 + " | jq -es 'if . == [] then null else .[] | .hits.total${valueObject} > 0 end'" 112 ) 113 parsedmarc.succeed("send-email") 114 parsedmarc.wait_until_succeeds( 115 "curl -sS -f http://localhost:${esPort}/_search?q=report_id:2940" 116 + " | tee /dev/console" 117 + " | jq -es 'if . == [] then null else .[] | .hits.total${valueObject} > 0 end'" 118 ) 119 ''; 120 }; 121 122 externalMail = 123 let 124 certs = import ../common/acme/server/snakeoil-certs.nix; 125 mailDomain = certs.domain; 126 parsedmarcDomain = "parsedmarc.fake.domain"; 127 in 128 makeTest { 129 name = "parsedmarc-external-mail"; 130 meta = with lib.maintainers; { 131 maintainers = [ talyz ]; 132 }; 133 134 nodes = { 135 parsedmarc = 136 { nodes, ... }: 137 { 138 virtualisation.memorySize = 2048; 139 140 security.pki.certificateFiles = [ 141 certs.ca.cert 142 ]; 143 144 networking.extraHosts = '' 145 127.0.0.1 ${parsedmarcDomain} 146 ${nodes.mail.config.networking.primaryIPAddress} ${mailDomain} 147 ''; 148 149 services.parsedmarc = { 150 enable = true; 151 provision.geoIp = false; 152 settings.imap = { 153 host = mailDomain; 154 port = 993; 155 ssl = true; 156 user = "alice"; 157 password = "${pkgs.writeText "imap-password" "foobar"}"; 158 }; 159 }; 160 161 environment.systemPackages = [ 162 pkgs.jq 163 ]; 164 }; 165 166 mail = 167 { nodes, ... }: 168 { 169 imports = [ ../common/user-account.nix ]; 170 171 networking.extraHosts = '' 172 127.0.0.1 ${mailDomain} 173 ${nodes.parsedmarc.config.networking.primaryIPAddress} ${parsedmarcDomain} 174 ''; 175 176 services.dovecot2 = { 177 enable = true; 178 protocols = [ "imap" ]; 179 sslCACert = "${certs.ca.cert}"; 180 sslServerCert = "${certs.${mailDomain}.cert}"; 181 sslServerKey = "${certs.${mailDomain}.key}"; 182 }; 183 184 services.postfix = { 185 enable = true; 186 origin = mailDomain; 187 settings.main = { 188 myhostname = mailDomain; 189 mydestination = mailDomain; 190 }; 191 enableSubmission = true; 192 enableSubmissions = true; 193 submissionsOptions = { 194 smtpd_sasl_auth_enable = "yes"; 195 smtpd_client_restrictions = "permit"; 196 }; 197 }; 198 environment.systemPackages = [ (sendEmail "alice@${mailDomain}") ]; 199 200 networking.firewall.allowedTCPPorts = [ 993 ]; 201 }; 202 }; 203 204 testScript = 205 { nodes }: 206 let 207 esPort = toString nodes.parsedmarc.config.services.elasticsearch.port; 208 valueObject = lib.optionalString (lib.versionAtLeast nodes.parsedmarc.config.services.elasticsearch.package.version "7") ".value"; 209 in 210 '' 211 mail.start() 212 mail.wait_for_unit("postfix.service") 213 mail.wait_for_unit("dovecot2.service") 214 215 parsedmarc.start() 216 parsedmarc.wait_for_unit("parsedmarc.service") 217 parsedmarc.wait_until_succeeds( 218 "curl -sS -f http://localhost:${esPort}" 219 ) 220 221 parsedmarc.fail( 222 "curl -sS -f http://localhost:${esPort}/_search?q=report_id:2940" 223 + " | tee /dev/console" 224 + " | jq -es 'if . == [] then null else .[] | .hits.total${valueObject} > 0 end'" 225 ) 226 mail.succeed("send-email") 227 parsedmarc.wait_until_succeeds( 228 "curl -sS -f http://localhost:${esPort}/_search?q=report_id:2940" 229 + " | tee /dev/console" 230 + " | jq -es 'if . == [] then null else .[] | .hits.total${valueObject} > 0 end'" 231 ) 232 ''; 233 }; 234}