Source code for octodns.zone.caa

#
#
#

from .base import Zone
from .validator import ValidationReason, ZoneValidator


[docs] class CaaZoneValidator(ZoneValidator): """ Comprehensive best-practice validator for CAA records. Checks: 1. **Presence of ``issue`` or ``issuewild``** — At least one CAA record must contain an ``issue`` or ``issuewild`` tag to explicitly authorize which Certificate Authorities may issue certificates. 2. **Explicit wildcard policy** — If an ``issue`` tag is present but no ``issuewild`` tag exists, wildcard certificate issuance falls back to the ``issue`` policy. This validator recommends adding an explicit ``issuewild`` record to make the wildcard-issuance policy clear. Can operate in two modes: 'optional' (default) and 'required'. In 'optional' mode, the validator only runs if CAA records are present. In 'required' mode, a CAA record MUST be present at the zone apex. Regardless of mode, if CAA records are found (at the apex or at sub-domains) they will be validated against best practices. Enabled as part of the ``best-practice`` validator set:: manager: enabled: - best-practice Examples: Common configuration for Let's Encrypt:: - flags: 0 tag: issue value: letsencrypt.org - flags: 0 tag: issuewild value: letsencrypt.org Configuration for non-issuance (restricting all issuance):: - flags: 0 tag: issue value: ";" References: - https://datatracker.ietf.org/doc/html/rfc8659 - https://datatracker.ietf.org/doc/html/rfc9495 """
[docs] def __init__(self, id, presence='optional', sets=None): super().__init__(id, sets=sets) if presence not in ('optional', 'required'): raise ValueError(f'Unknown presence "{presence}"') self.presence = presence
[docs] def validate(self, zone): reasons = [] apex_caa = zone.get_type('', 'CAA') if not apex_caa and self.presence == 'required': reasons.append( ValidationReason( f'zone "{zone.decoded_name}" has no CAA records at the ' 'apex', set(), ) ) # Collect all CAA records in the zone. caa_records = [r for r in zone.records if r._type == 'CAA'] for record in caa_records: # Collect all tags from all record values. tags = {value.tag for value in record.values} has_issue = 'issue' in tags has_issuewild = 'issuewild' in tags # Check 1: must have at least one issuance policy if not has_issue and not has_issuewild: reasons.append( ValidationReason( f'CAA record "{record.fqdn}" has no ``issue`` ' 'or ``issuewild`` tag; having only ``iodef`` means any ' 'CA can issue certificates', [record], ) ) # Check 2: if issue exists without issuewild, recommend explicit # wildcard policy if has_issue and not has_issuewild: reasons.append( ValidationReason( f'CAA record "{record.fqdn}" has ``issue`` but ' 'no ``issuewild``; consider adding an explicit ' '``issuewild`` to define wildcard certificate policy', [record], ) ) return reasons
Zone.register_zone_validator( CaaZoneValidator('caa-best-practices', sets={'best-practice'}) )