How to mock DNS CAA record lookups in Python

Parse and filter DNS CAA records with a mock lookup function, demonstrating how certificate authorities validate domain authorization.

Medium Python 3.9+ Aug 9, 2026 Auth & security at scale 18 views 0 copies

Requires third-party packages — install first
pip install dnslib

Python code

36 lines
Python 3.9+
import dnslib

def parse_caa_record(record_string):
    """Parse a DNS CAA record string into its components."""
    parts = record_string.split()
    flags = int(parts[0])
    tag = parts[1]
    value = parts[2]
    return flags, tag, value

def mock_caa_lookup(domain, caa_records):
    """Mock DNS CAA lookup that returns a filtered list of CAA records."""
    records = caa_records.get(domain, [])
    results = []
    for record in records:
        flags, tag, value = parse_caa_record(record)
        # Only return records that are allowed for lookup (simplified logic)
        if flags == 0 and tag in ("issue", "issuewild", "iodef"):
            results.append((tag, value, flags))
    return results

if __name__ == "__main__":
    # Mock DNS zone data
    zone_data = {
        "example.com": [
            "0 issue \"letsencrypt.org\"",
            "0 issuewild \"comodoca.com\"",
            "0 iodef \"mailto:security@example.com\"",
            "128 issue \"untrusted-ca.org\""  # This one should be filtered out
        ]
    }
    
    domain = "example.com"
    print(f"CAA records for {domain}:")
    for tag, value, flags in mock_caa_lookup(domain, zone_data):
        print(f"  {tag} = {value} (flags: {flags})")

Output

stdout
CAA records for example.com:
  issue = letsencrypt.org (flags: 0)
  issuewild = comodoca.com (flags: 0)
  iodef = mailto:security@example.com (flags: 0)

How it works

The parse_caa_record function splits the record string into flags, tag, and value components. The mock lookup filters records by flags equal to 0 and tags relevant to certificate issuance. Real DNS lookups would use dnslib's resolver to query authoritative servers — this mock simulates that contract. The flags field indicates critical vs. non-critical records; flags of 0 mean the record is non-critical and can be ignored if unknown. Filtering by tag (issue, issuewild, iodef) keeps only the records that matter for CA decision-making.

Common mistakes

  • Forgetting that dnslib is a third-party package requiring installation
  • Not handling malformed CAA record strings that lack exactly three parts
  • Ignoring the flags field when determining which records are critical

Variations

  1. Use dnslib's actual resolver API to perform real CAA lookups instead of mocking
  2. Implement the lookup as a generator expression for more concise code

Real-world use cases

  • Verify domain authorization before issuing TLS certificates in a CA infrastructure.
  • Test ACME client logic by simulating CAA policy responses from a DNS provider.
  • Audit domain security by enumerating allowed certificate authorities from existing CAA records.

Sponsored

Run locally

This sample needs third-party packages, so it cannot run in the browser IDE. Copy the code above, install the packages shown at the top, then run it in your own Python environment.

More from Auth & security at scale

Related tutorials and quizzes for this topic.