From 020834539bf4d78a78f14f542d2a4725442d21a8 Mon Sep 17 00:00:00 2001 From: Timothy Berger <5579958+rasturic@users.noreply.github.com> Date: Fri, 10 May 2024 12:14:15 -1000 Subject: [PATCH] Fix add_record() lenient check to allow managed sub-zone DS records --- docs/records.md | 1 + octodns/zone.py | 6 +-- tests/test_octodns_zone.py | 85 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 3 deletions(-) diff --git a/docs/records.md b/docs/records.md index e3b878e..d5f2cc4 100644 --- a/docs/records.md +++ b/docs/records.md @@ -10,6 +10,7 @@ octoDNS supports the following record types: * `CAA` * `CNAME` * `DNAME` +* `DS` * `LOC` * `MX` * `NAPTR` diff --git a/octodns/zone.py b/octodns/zone.py index 4ac7823..2a623ae 100644 --- a/octodns/zone.py +++ b/octodns/zone.py @@ -150,10 +150,10 @@ class Zone(object): if not lenient: if name in self.sub_zones: # It's an exact match for a sub-zone - if not record._type == 'NS': - # and not a NS record, this should be in the sub + if not (record._type == 'NS' or record._type == 'DS'): + # and not a NS or DS record, this should be in the sub raise SubzoneRecordException( - f'Record {record.fqdn} is a managed sub-zone and not of type NS', + f'Record {record.fqdn} is a managed sub-zone and not of type NS or DS', record, ) else: diff --git a/tests/test_octodns_zone.py b/tests/test_octodns_zone.py index a01b6e9..735a0b0 100644 --- a/tests/test_octodns_zone.py +++ b/tests/test_octodns_zone.py @@ -346,6 +346,91 @@ class TestZone(TestCase): zone.add_record(record) self.assertEqual(1, len(zone.records)) + # DS record for exactly the sub is allowed + zone = Zone('unit.tests.', set(['sub', 'barred'])) + record = Record.new( + zone, + 'sub', + { + 'ttl': 3600, + 'type': 'DS', + 'values': [ + { + 'key_tag': 60485, + 'algorithm': 5, + 'digest_type': 1, + 'digest': '2BB183AF5F22588179A53B0A 98631FAD1A292118', + }, + { + 'key_tag': 60485, + 'algorithm': 5, + 'digest_type': 1, + 'digest': '2BB183AF5F22588179A53B0A 98631FAD1A292119', + }, + ], + }, + ) + zone.add_record(record) + self.assertEqual(set([record]), zone.records) + + # DS record for something below the sub is rejected + zone = Zone('unit.tests.', set(['sub', 'barred'])) + record = Record.new( + zone, + 'foo.bar.sub', + { + 'ttl': 3600, + 'type': 'DS', + 'values': [ + { + 'key_tag': 60485, + 'algorithm': 5, + 'digest_type': 1, + 'digest': '2BB183AF5F22588179A53B0A 98631FAD1A292118', + }, + { + 'key_tag': 60485, + 'algorithm': 5, + 'digest_type': 1, + 'digest': '2BB183AF5F22588179A53B0A 98631FAD1A292119', + }, + ], + }, + ) + with self.assertRaises(SubzoneRecordException) as ctx: + zone.add_record(record) + self.assertTrue('under a managed sub-zone', str(ctx.exception)) + # Can add it w/lenient + zone.add_record(record, lenient=True) + self.assertEqual(set([record]), zone.records) + + # DS record that happens to end with a string that matches a sub (no .) is OK + zone = Zone('unit.tests.', set(['sub', 'barred'])) + record = Record.new( + zone, + 'foo.bar_sub', + { + 'ttl': 3600, + 'type': 'DS', + 'values': [ + { + 'key_tag': 60485, + 'algorithm': 5, + 'digest_type': 1, + 'digest': '2BB183AF5F22588179A53B0A 98631FAD1A292118', + }, + { + 'key_tag': 60485, + 'algorithm': 5, + 'digest_type': 1, + 'digest': '2BB183AF5F22588179A53B0A 98631FAD1A292119', + }, + ], + }, + ) + zone.add_record(record) + self.assertEqual(1, len(zone.records)) + def test_ignored_records(self): zone_normal = Zone('unit.tests.', []) zone_ignored = Zone('unit.tests.', [])