107 lines
2.8 KiB
Python
107 lines
2.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Offline regression tests for the selective SRS DNS preflight helper.
|
|
|
|
All DNS responses are mocked. No live DNS queries, Postfix changes,
|
|
or SRS installation operations are performed.
|
|
"""
|
|
|
|
import contextlib
|
|
import io
|
|
import runpy
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
HELPER = ROOT / "helpers/srs-dns-check.py"
|
|
|
|
module = runpy.run_path(str(HELPER))
|
|
check_server = module["check_server"]
|
|
|
|
|
|
class TestSrsDnsSpf(unittest.TestCase):
|
|
|
|
DOMAIN = "srs.example.org"
|
|
HOSTNAME = "mail.example.org"
|
|
IPV4 = "192.0.2.25"
|
|
IPV6 = "2001:db8::25"
|
|
|
|
def check_with_spf(self, txt_records):
|
|
answers = {
|
|
(self.DOMAIN, "TXT"): txt_records,
|
|
(self.DOMAIN, "MX"): [
|
|
f"10 {self.HOSTNAME}."
|
|
],
|
|
(self.HOSTNAME, "A"): [
|
|
self.IPV4
|
|
],
|
|
(self.HOSTNAME, "AAAA"): [
|
|
self.IPV6
|
|
],
|
|
}
|
|
|
|
def fake_dig(server, name, kind, authoritative=False):
|
|
self.assertEqual(server, "192.0.2.53")
|
|
self.assertTrue(
|
|
authoritative,
|
|
"DNS checks must query authoritative nameservers"
|
|
)
|
|
return answers.get((name, kind), [])
|
|
|
|
output = io.StringIO()
|
|
|
|
with patch.dict(
|
|
check_server.__globals__,
|
|
{"dig": fake_dig}
|
|
):
|
|
with contextlib.redirect_stdout(output):
|
|
result = check_server(
|
|
"ns.example.org",
|
|
"192.0.2.53",
|
|
self.DOMAIN,
|
|
self.HOSTNAME,
|
|
self.IPV4,
|
|
self.IPV6,
|
|
)
|
|
|
|
return result, output.getvalue()
|
|
|
|
def test_valid_spf(self):
|
|
result, output = self.check_with_spf(
|
|
['"v=spf1 mx -all"']
|
|
)
|
|
|
|
self.assertEqual(result, (True, True))
|
|
self.assertIn("[ ok ]", output)
|
|
|
|
def test_missing_spf(self):
|
|
result, output = self.check_with_spf([])
|
|
|
|
self.assertEqual(result, (False, False))
|
|
self.assertIn("SPF is not the approved", output)
|
|
self.assertIn("[ failed ]", output)
|
|
|
|
def test_invalid_spf(self):
|
|
result, output = self.check_with_spf(
|
|
['"v=spf1 -all"']
|
|
)
|
|
|
|
self.assertEqual(result, (False, False))
|
|
self.assertIn("SPF is not the approved", output)
|
|
self.assertIn("[ failed ]", output)
|
|
|
|
def test_multiple_spf_records(self):
|
|
result, output = self.check_with_spf([
|
|
'"v=spf1 mx -all"',
|
|
'"v=spf1 ip4:192.0.2.1 -all"',
|
|
])
|
|
|
|
self.assertEqual(result, (False, False))
|
|
self.assertIn("SPF is not the approved", output)
|
|
self.assertIn("[ failed ]", output)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main(verbosity=2)
|