align-catalog-zone.py 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. from django.conf import settings
  2. from django.core.management import BaseCommand
  3. from desecapi.exceptions import PDNSException
  4. from desecapi.pdns import _pdns_delete, _pdns_get, _pdns_post, NSLORD, NSMASTER, pdns_id, construct_catalog_rrset
  5. class Command(BaseCommand):
  6. # https://tools.ietf.org/html/draft-muks-dnsop-dns-catalog-zones-04
  7. help = 'Generate a catalog zone on nsmaster, based on zones known on nslord.'
  8. def add_arguments(self, parser):
  9. pass
  10. def handle(self, *args, **options):
  11. catalog_zone_id = pdns_id(settings.CATALOG_ZONE)
  12. # Fetch zones from NSLORD
  13. response = _pdns_get(NSLORD, '/zones').json()
  14. zones = {zone['name'] for zone in response}
  15. # Retrieve catalog zone serial (later reused for recreating the catalog zone, for allow for smooth rollover)
  16. try:
  17. response = _pdns_get(NSMASTER, f'/zones/{catalog_zone_id}')
  18. serial = response.json()['serial']
  19. except PDNSException as e:
  20. if e.response.status_code == 404:
  21. serial = None
  22. else:
  23. raise e
  24. # Purge catalog zone if exists
  25. try:
  26. _pdns_delete(NSMASTER, f'/zones/{catalog_zone_id}')
  27. except PDNSException as e:
  28. if e.response.status_code != 404:
  29. raise e
  30. # Create new catalog zone
  31. rrsets = [
  32. construct_catalog_rrset(subname='', qtype='NS', rdata='invalid.'), # as per the specification
  33. construct_catalog_rrset(subname='version', qtype='TXT', rdata='"2"'), # as per the specification
  34. *(construct_catalog_rrset(zone=zone) for zone in zones)
  35. ]
  36. data = {
  37. 'name': settings.CATALOG_ZONE + '.',
  38. 'kind': 'MASTER',
  39. 'dnssec': False, # as per the specification
  40. 'nameservers': [],
  41. 'rrsets': rrsets,
  42. }
  43. if serial is not None:
  44. data['serial'] = serial + 1 # actually, pdns does increase this as well, but let's not rely on this
  45. _pdns_post(NSMASTER, '/zones', data)
  46. print(f'Aligned catalog zone ({len(zones)} member zones).')