"""Tests for the crt.sh certificate transparency plugin.""" import importlib.util import sys from datetime import datetime, timezone from pathlib import Path # plugins/ is not a Python package -- load the module from file path _spec = importlib.util.spec_from_file_location( "plugins.crtsh", Path(__file__).resolve().parent.parent / "plugins" / "crtsh.py", ) _mod = importlib.util.module_from_spec(_spec) sys.modules[_spec.name] = _mod _spec.loader.exec_module(_mod) from plugins.crtsh import ( # noqa: E402 deduplicate, format_result, is_expired, is_live_cert_expired, parse_crtsh_ts, ) class TestDeduplicate: def test_removes_duplicate_serials(self): certs = [ {"serial_number": "AAA", "common_name": "a.example.com"}, {"serial_number": "BBB", "common_name": "b.example.com"}, {"serial_number": "AAA", "common_name": "a.example.com (dup)"}, ] result = deduplicate(certs) assert len(result) == 2 serials = {c["serial_number"] for c in result} assert serials == {"AAA", "BBB"} def test_keeps_first_occurrence(self): certs = [ {"serial_number": "AAA", "common_name": "first"}, {"serial_number": "AAA", "common_name": "second"}, ] result = deduplicate(certs) assert result[0]["common_name"] == "first" def test_empty_input(self): assert deduplicate([]) == [] def test_no_serial_field(self): certs = [{"common_name": "no-serial"}, {"serial_number": "", "common_name": "empty"}] result = deduplicate(certs) assert len(result) == 0 def test_all_unique(self): certs = [ {"serial_number": "A", "common_name": "a"}, {"serial_number": "B", "common_name": "b"}, {"serial_number": "C", "common_name": "c"}, ] assert len(deduplicate(certs)) == 3 class TestExpiredCheck: def test_expired_cert(self): cert = {"not_after": "2020-01-01T00:00:00"} assert is_expired(cert) is True def test_valid_cert(self): cert = {"not_after": "2099-12-31T23:59:59"} assert is_expired(cert) is False def test_missing_not_after(self): assert is_expired({}) is False assert is_expired({"not_after": ""}) is False def test_fractional_seconds(self): cert = {"not_after": "2020-06-15T12:30:45.123"} assert is_expired(cert) is True def test_parse_timestamp_basic(self): dt = parse_crtsh_ts("2024-03-15T10:30:00") assert dt == datetime(2024, 3, 15, 10, 30, 0, tzinfo=timezone.utc) def test_parse_timestamp_fractional(self): dt = parse_crtsh_ts("2024-03-15T10:30:00.500") assert dt.microsecond == 500000 class TestLiveCertExpired: def test_expired_live_cert(self): cert = {"notAfter": "Jan 1 00:00:00 2020 GMT"} assert is_live_cert_expired(cert) is True def test_valid_live_cert(self): cert = {"notAfter": "Dec 31 23:59:59 2099 GMT"} assert is_live_cert_expired(cert) is False def test_missing_field(self): assert is_live_cert_expired({}) is False class TestFormatResult: def test_basic(self): line = format_result("example.com", 100, 10, 90, None) assert line == "example.com -- 100 certs (10 expired, 90 valid)" def test_live_expired(self): line = format_result("bad.com", 50, 5, 45, True) assert "live cert EXPIRED" in line def test_live_ok_with_expired_certs(self): line = format_result("ok.com", 50, 5, 45, False) assert "live cert ok" in line def test_live_ok_no_expired(self): """No live check annotation when zero expired certs.""" line = format_result("clean.com", 50, 0, 50, False) assert "live cert" not in line def test_zero_certs(self): line = format_result("empty.com", 0, 0, 0, None) assert line == "empty.com -- 0 certs (0 expired, 0 valid)"