]> granicus.if.org Git - pdns/commitdiff
auth-api: increase serial after dnssec related updates
authorKees Monshouwer <mind04@monshouwer.org>
Thu, 3 May 2018 22:56:51 +0000 (00:56 +0200)
committermind04 <mind04@monshouwer.org>
Fri, 4 May 2018 09:52:18 +0000 (11:52 +0200)
pdns/ws-auth.cc
regression-tests.api/test_Zones.py

index 0afd0c4f9f5f6d4ac8620902fe35ccea9053ccf7..4ec9e3bf1f794727f7dd2e2063ee358532c8e9d0 100644 (file)
@@ -552,7 +552,7 @@ static void throwUnableToSecure(const DNSName& zonename) {
       + "capable backends are loaded, or because the backends have DNSSEC disabled. Check your configuration.");
 }
 
-static void updateDomainSettingsFromDocument(UeberBackend& B, const DomainInfo& di, const DNSName& zonename, const Json document) {
+static void updateDomainSettingsFromDocument(UeberBackend& B, const DomainInfo& di, const DNSName& zonename, const Json document, HttpResponse* resp) {
   string zonemaster;
   bool shouldRectify = false;
   for(auto value : document["masters"].array_items()) {
@@ -660,13 +660,41 @@ static void updateDomainSettingsFromDocument(UeberBackend& B, const DomainInfo&
     }
   }
 
-  string api_rectify;
-  di.backend->getDomainMetadataOne(zonename, "API-RECTIFY", api_rectify);
-  if (shouldRectify && dk.isSecuredZone(zonename) && !dk.isPresigned(zonename) && api_rectify == "1") {
-    string info;
-    string error_msg = "";
-    if (!dk.rectifyZone(zonename, error_msg, info, true))
-      throw ApiException("Failed to rectify '" + zonename.toString() + "' " + error_msg);
+  if (shouldRectify && !dk.isPresigned(zonename)) {
+    // Rectify
+    string api_rectify;
+    di.backend->getDomainMetadataOne(zonename, "API-RECTIFY", api_rectify);
+    if (api_rectify == "1") {
+      string info;
+      string error_msg;
+      if (!dk.rectifyZone(zonename, error_msg, info, true)) {
+        throw ApiException("Failed to rectify '" + zonename.toString() + "' " + error_msg);
+      }
+    }
+
+    // Increase serial
+    string soa_edit_api_kind;
+    di.backend->getDomainMetadataOne(zonename, "SOA-EDIT-API", soa_edit_api_kind);
+    if (!soa_edit_api_kind.empty()) {
+      SOAData sd;
+      if (!B.getSOAUncached(zonename, sd, true))
+        return;
+
+      string soa_edit_kind;
+      di.backend->getDomainMetadataOne(zonename, "SOA-EDIT", soa_edit_kind);
+
+      DNSResourceRecord rr;
+      if (makeIncreasedSOARecord(sd, soa_edit_api_kind, soa_edit_kind, rr)) {
+        if (!di.backend->replaceRRSet(di.id, rr.qname, rr.qtype, vector<DNSResourceRecord>(1, rr))) {
+          throw ApiException("Hosting backend does not support editing records.");
+        }
+      }
+
+      // return old and new serials in headers
+      resp->headers["X-PDNS-Old-Serial"] = std::to_string(sd.serial);
+      fillSOAData(rr.content, sd);
+      resp->headers["X-PDNS-New-Serial"] = std::to_string(sd.serial);
+    }
   }
 }
 
@@ -1343,7 +1371,7 @@ static void apiServerZones(HttpRequest* req, HttpResponse* resp) {
       di.backend->feedComment(c);
     }
 
-    updateDomainSettingsFromDocument(B, di, zonename, document);
+    updateDomainSettingsFromDocument(B, di, zonename, document, resp);
 
     di.backend->commitTransaction();
 
@@ -1379,7 +1407,7 @@ static void apiServerZoneDetail(HttpRequest* req, HttpResponse* resp) {
   if(req->method == "PUT" && !::arg().mustDo("api-readonly")) {
     // update domain settings
 
-    updateDomainSettingsFromDocument(B, di, zonename, req->json());
+    updateDomainSettingsFromDocument(B, di, zonename, req->json(), resp);
 
     resp->body = "";
     resp->status = 204; // No Content, but indicate success
index 29f1645968cc73f2022f72cd0e00bcfb2a064ee8..250d8bafed2caf8a9cb2b9412da8b5253e6ee0c1 100644 (file)
@@ -485,6 +485,37 @@ class AuthZones(ApiTestCase, AuthZonesHelperMixin):
         self.assertEquals(data['kind'], 'NSEC3NARROW')
         self.assertEquals(data['metadata'][0], '1')
 
+    def test_create_zone_dnssec_serial(self):
+        """
+        Create a zone set/unset "dnssec" and see if the serial was increased
+        after every step
+        """
+        name = unique_zone_name()
+        name, payload, data = self.create_zone()
+
+        soa_serial = get_first_rec(data, name, 'SOA')['content'].split(' ')[2]
+        self.assertEquals(soa_serial[-2:], '01')
+
+        self.session.put(self.url("/api/v1/servers/localhost/zones/" + name),
+                         data=json.dumps({'dnssec': True}))
+        r = self.session.get(self.url("/api/v1/servers/localhost/zones/" + name))
+
+        data = r.json()
+        soa_serial = get_first_rec(data, name, 'SOA')['content'].split(' ')[2]
+
+        self.assertEquals(r.status_code, 200)
+        self.assertEquals(soa_serial[-2:], '02')
+
+        self.session.put(self.url("/api/v1/servers/localhost/zones/" + name),
+                         data=json.dumps({'dnssec': False}))
+        r = self.session.get(self.url("/api/v1/servers/localhost/zones/" + name))
+
+        data = r.json()
+        soa_serial = get_first_rec(data, name, 'SOA')['content'].split(' ')[2]
+
+        self.assertEquals(r.status_code, 200)
+        self.assertEquals(soa_serial[-2:], '03')
+
     def test_zone_absolute_url(self):
         name, payload, data = self.create_zone()
         r = self.session.get(self.url("/api/v1/servers/localhost/zones"))