mirror of
https://github.com/domainaware/parsedmarc.git
synced 2026-07-31 20:52:17 +00:00
Cover the remaining gsecops.py branches with sample-driven tests
Bring parsedmarc/gsecops.py from 96% to 100% coverage: - principal hostname from an enriched source reverse DNS name - the literal "none" placeholder in policy_override_reasons / policy_override_comments is dropped from additional (samples/aggregate/empty_reason.xml) - SMTP TLS failure details map sending-mta-ip to principal.ip and receiving-ip to target.ip (the RFC 8460 Appendix B sample) - target hostname falls back to receiving-mx-hostname when a report carries an empty policy-domain Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
7ce8b63688
commit
ae5a5043ab
@@ -1,5 +1,6 @@
|
||||
"""Tests for parsedmarc.gsecops"""
|
||||
|
||||
import copy
|
||||
import unittest
|
||||
from typing import Any, cast
|
||||
from unittest.mock import MagicMock, patch
|
||||
@@ -104,6 +105,28 @@ class TestAggregateUdmEvents(unittest.TestCase):
|
||||
self.assertNotIn("dmarc_testing", additional)
|
||||
self.assertNotIn("dkim_domains", additional)
|
||||
|
||||
def test_additional_drops_literal_none_policy_overrides(self):
|
||||
"""parsedmarc writes the literal string "none" for
|
||||
policy_override_reasons / policy_override_comments when a record has
|
||||
no overrides; that placeholder must not reach the API."""
|
||||
report = cast(
|
||||
AggregateReport, _parse_sample("samples/aggregate/empty_reason.xml")
|
||||
)
|
||||
events = aggregate_report_to_udm_events(report)
|
||||
additional = events[0]["udm"]["additional"]
|
||||
self.assertNotIn("policy_override_reasons", additional)
|
||||
self.assertNotIn("policy_override_comments", additional)
|
||||
|
||||
def test_principal_hostname_from_reverse_dns(self):
|
||||
"""When enrichment resolved a reverse DNS name for the source IP, it
|
||||
becomes the principal hostname."""
|
||||
report = copy.deepcopy(_aggregate_report())
|
||||
report["records"][0]["source"]["reverse_dns"] = "mail.example.net"
|
||||
events = aggregate_report_to_udm_events(report)
|
||||
principal = events[0]["udm"]["principal"]
|
||||
self.assertEqual(principal["hostname"], "mail.example.net")
|
||||
self.assertEqual(principal["ip"], ["12.20.127.122"])
|
||||
|
||||
|
||||
class TestFailureUdmEvents(unittest.TestCase):
|
||||
def test_event_shape(self):
|
||||
@@ -172,6 +195,31 @@ class TestSmtpTlsUdmEvents(unittest.TestCase):
|
||||
"bad https response code: 404",
|
||||
)
|
||||
|
||||
def test_failure_detail_mta_nouns(self):
|
||||
"""Failure details carry the sending MTA IP as the principal and the
|
||||
receiving IP alongside the policy domain in the target (RFC 8460
|
||||
Appendix B sample)."""
|
||||
report = cast(SMTPTLSReport, _parse_sample("samples/smtp_tls/rfc8460.json"))
|
||||
events = smtp_tls_report_to_udm_events(report)
|
||||
# one policy summary row + three failure details
|
||||
self.assertEqual(len(events), 4)
|
||||
starttls = events[2]["udm"]
|
||||
self.assertEqual(starttls["principal"]["ip"], ["2001:db8:abcd:0013::1"])
|
||||
self.assertEqual(starttls["target"]["hostname"], "company-y.example")
|
||||
self.assertEqual(starttls["target"]["ip"], ["203.0.113.56"])
|
||||
|
||||
def test_target_hostname_falls_back_to_receiving_mx(self):
|
||||
"""A report whose policy carries an empty policy-domain (violating
|
||||
RFC 8460 §4.2, but accepted by the parser) still gets a target
|
||||
hostname on failure details, from receiving-mx-hostname."""
|
||||
report = copy.deepcopy(
|
||||
cast(SMTPTLSReport, _parse_sample("samples/smtp_tls/rfc8460.json"))
|
||||
)
|
||||
report["policies"][0]["policy_domain"] = ""
|
||||
events = smtp_tls_report_to_udm_events(report)
|
||||
starttls = events[2]["udm"]
|
||||
self.assertEqual(starttls["target"]["hostname"], "mx2.mail.company-y.example")
|
||||
|
||||
|
||||
def _client() -> tuple[GoogleSecOpsClient, MagicMock]:
|
||||
"""Builds a client with mocked Google credentials and returns it along
|
||||
|
||||
Reference in New Issue
Block a user