diff --git a/netbox_dns/models.py b/netbox_dns/models.py index baefae85..606245d6 100644 --- a/netbox_dns/models.py +++ b/netbox_dns/models.py @@ -7,6 +7,7 @@ from dns import rdata, rdatatype, rdataclass from dns import name as dns_name from dns.rdtypes.ANY import SOA +from dns.exception import DNSException from netaddr import IPNetwork, AddrFormatError, IPAddress @@ -484,6 +485,16 @@ def clean(self, *args, **kwargs): } ) from None + try: + soa_rname = dns_name.from_text(self.soa_rname, origin=dns_name.root) + validate_fqdn(self.soa_rname) + except (DNSException, ValidationError) as exc: + raise ValidationError( + { + "soa_rname": exc, + } + ) from None + if self.soa_serial is None and not self.soa_serial_auto: raise ValidationError( { diff --git a/netbox_dns/tests/zone/test_rname_validation.py b/netbox_dns/tests/zone/test_rname_validation.py new file mode 100644 index 00000000..c2f0f75d --- /dev/null +++ b/netbox_dns/tests/zone/test_rname_validation.py @@ -0,0 +1,51 @@ +from django.test import TestCase +from django.core.exceptions import ValidationError + +from netbox_dns.models import NameServer, Zone + + +class RNameValidationTest(TestCase): + zone_data = { + "default_ttl": 86400, + "soa_refresh": 172800, + "soa_retry": 7200, + "soa_expire": 2592000, + "soa_ttl": 86400, + "soa_minimum": 3600, + "soa_serial": 1, + "soa_serial_auto": False, + } + + @classmethod + def setUpTestData(cls): + cls.nameserver = NameServer.objects.create(name="ns1.example.com") + + def test_rname_validation_ok(self): + rnames = ( + "hostmaster.example.com", + "hostmaster.example.com.", + ) + + for index, rname in enumerate(rnames): + zone = Zone.objects.create( + name=f"zone{index}.example.com", + soa_rname=rname, + **self.zone_data, + soa_mname=self.nameserver, + ) + self.assertEqual(zone.soa_rname, rname) + + def test_rname_validation_failure(self): + rnames = ( + "hostmaster", # Not an FQDN + "hostmaster@example.com", # E-Mail address not converted to FQDN + ) + + for index, rname in enumerate(rnames): + with self.assertRaises(ValidationError): + Zone.objects.create( + name=f"zone{index}.example.com", + soa_rname=rname, + **self.zone_data, + soa_mname=self.nameserver, + )