Переглянути джерело

chore(api): move PDNS business to pdns.py, don't use private API

Nils Wisiol 2 роки тому
батько
коміт
2ef603f3a2
2 змінених файлів з 91 додано та 72 видалено
  1. 81 0
      api/desecapi/pdns.py
  2. 10 72
      api/desecapi/pdns_change_tracker.py

+ 81 - 0
api/desecapi/pdns.py

@@ -1,5 +1,6 @@
 import json
 import re
+import socket
 from hashlib import sha1
 
 import requests
@@ -191,6 +192,86 @@ def get_rrset_datas(domain):
     ]
 
 
+def update_catalog(zone, delete=False):
+    """
+    Updates the catalog zone information (`settings.CATALOG_ZONE`) for the given zone.
+    """
+    content = _pdns_patch(
+        NSMASTER,
+        "/zones/" + pdns_id(settings.CATALOG_ZONE),
+        {"rrsets": [construct_catalog_rrset(zone=zone, delete=delete)]},
+    )
+    metrics.get("desecapi_pdns_catalog_updated").inc()
+    return content
+
+
+def create_zone_lord(name):
+    name = name.rstrip(".") + "."
+    _pdns_post(
+        NSLORD,
+        "/zones?rrsets=false",
+        {
+            "name": name,
+            "kind": "MASTER",
+            "dnssec": True,
+            "nsec3param": "1 0 0 -",
+            "nameservers": settings.DEFAULT_NS,
+            "rrsets": [
+                {
+                    "name": name,
+                    "type": "SOA",
+                    # SOA RRset TTL: 300 (used as TTL for negative replies including NSEC3 records)
+                    "ttl": 300,
+                    "records": [
+                        {
+                            # SOA refresh: 1 day (only needed for nslord --> nsmaster replication after RRSIG rotation)
+                            # SOA retry = 1h
+                            # SOA expire: 4 weeks (all signatures will have expired anyways)
+                            # SOA minimum: 3600 (for CDS, CDNSKEY, DNSKEY, NSEC3PARAM)
+                            "content": "get.desec.io. get.desec.io. 1 86400 3600 2419200 3600",
+                            "disabled": False,
+                        }
+                    ],
+                }
+            ],
+        },
+    )
+
+
+def create_zone_master(name):
+    name = name.rstrip(".") + "."
+    _pdns_post(
+        NSMASTER,
+        "/zones?rrsets=false",
+        {
+            "name": name,
+            "kind": "SLAVE",
+            "masters": [socket.gethostbyname("nslord")],
+            "master_tsig_key_ids": ["default"],
+        },
+    )
+
+
+def delete_zone(name, server):
+    _pdns_delete(server, "/zones/" + pdns_id(name))
+
+
+def delete_zone_lord(name):
+    _pdns_delete(NSLORD, "/zones/" + pdns_id(name))
+
+
+def delete_zone_master(name):
+    _pdns_delete(NSMASTER, "/zones/" + pdns_id(name))
+
+
+def update_zone(name, data):
+    _pdns_patch(NSLORD, "/zones/" + pdns_id(name), data)
+
+
+def axfr_to_master(zone):
+    _pdns_put(NSMASTER, "/zones/%s/axfr-retrieve" % pdns_id(zone))
+
+
 def construct_catalog_rrset(
     zone=None, delete=False, subname=None, qtype="PTR", rdata=None
 ):

+ 10 - 72
api/desecapi/pdns_change_tracker.py

@@ -1,13 +1,11 @@
-import socket
-
 from django.conf import settings
 from django.db.models.signals import post_save, post_delete
 from django.db.transaction import atomic
 from django.utils import timezone
 
-from desecapi import metrics, pch
+from desecapi import pch, pdns
 from desecapi.models import RRset, RR, Domain
-from desecapi import pdns
+
 
 class PDNSChangeTracker:
     """
@@ -51,14 +49,6 @@ class PDNSChangeTracker:
         def domain_name(self):
             return self._domain_name
 
-        @property
-        def domain_name_normalized(self):
-            return self._domain_name + "."
-
-        @property
-        def domain_pdns_id(self):
-            return pdns.pdns_id(self._domain_name)
-
         @property
         def axfr_required(self):
             raise NotImplementedError()
@@ -72,67 +62,15 @@ class PDNSChangeTracker:
         def pch_do(self):
             raise NotImplementedError()
 
-        def update_catalog(self, delete=False):
-            content = pdns._pdns_patch(
-                pdns.NSMASTER,
-                "/zones/" + pdns.pdns_id(settings.CATALOG_ZONE),
-                {
-                    "rrsets": [
-                        pdns.construct_catalog_rrset(zone=self.domain_name, delete=delete)
-                    ]
-                },
-            )
-            metrics.get("desecapi_pdns_catalog_updated").inc()
-            return content
-
     class CreateDomain(PDNSChange):
         @property
         def axfr_required(self):
             return True
 
         def pdns_do(self):
-            pdns._pdns_post(
-                pdns.NSLORD,
-                "/zones?rrsets=false",
-                {
-                    "name": self.domain_name_normalized,
-                    "kind": "MASTER",
-                    "dnssec": True,
-                    "nsec3param": "1 0 0 -",
-                    "nameservers": settings.DEFAULT_NS,
-                    "rrsets": [
-                        {
-                            "name": self.domain_name_normalized,
-                            "type": "SOA",
-                            # SOA RRset TTL: 300 (used as TTL for negative replies including NSEC3 records)
-                            "ttl": 300,
-                            "records": [
-                                {
-                                    # SOA refresh: 1 day (only needed for nslord --> nsmaster replication after RRSIG rotation)
-                                    # SOA retry = 1h
-                                    # SOA expire: 4 weeks (all signatures will have expired anyways)
-                                    # SOA minimum: 3600 (for CDS, CDNSKEY, DNSKEY, NSEC3PARAM)
-                                    "content": "get.desec.io. get.desec.io. 1 86400 3600 2419200 3600",
-                                    "disabled": False,
-                                }
-                            ],
-                        }
-                    ],
-                },
-            )
-
-            pdns._pdns_post(
-                pdns.NSMASTER,
-                "/zones?rrsets=false",
-                {
-                    "name": self.domain_name_normalized,
-                    "kind": "SLAVE",
-                    "masters": [socket.gethostbyname("nslord")],
-                    "master_tsig_key_ids": ["default"],
-                },
-            )
-
-            self.update_catalog()
+            pdns.create_zone_lord(self.domain_name)
+            pdns.create_zone_master(self.domain_name)
+            pdns.update_catalog(self.domain_name)
 
         def api_do(self):
             rr_set = RRset(
@@ -158,9 +96,9 @@ class PDNSChangeTracker:
             return False
 
         def pdns_do(self):
-            pdns._pdns_delete(pdns.NSLORD, "/zones/" + self.domain_pdns_id)
-            pdns._pdns_delete(pdns.NSMASTER, "/zones/" + self.domain_pdns_id)
-            self.update_catalog(delete=True)
+            pdns.delete_zone_lord(self.domain_name)
+            pdns.delete_zone_master(self.domain_name)
+            pdns.update_catalog(self.domain_name, delete=True)
 
         def api_do(self):
             pass
@@ -217,7 +155,7 @@ class PDNSChangeTracker:
             }
 
             if data["rrsets"]:
-                pdns._pdns_patch(pdns.NSLORD, "/zones/" + self.domain_pdns_id, data)
+                pdns.update_zone(self.domain_name, data)
 
         def api_do(self):
             pass
@@ -320,7 +258,7 @@ class PDNSChangeTracker:
         self.transaction.__exit__(None, None, None)
 
         for name in axfr_required:
-            pdns._pdns_put(pdns.NSMASTER, "/zones/%s/axfr-retrieve" % pdns.pdns_id(name))
+            pdns.axfr_to_master(name)
         Domain.objects.filter(name__in=axfr_required).update(published=timezone.now())
 
     def _compute_changes(self):