]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
auth: add default-soa-edit-api setting for API zone creation 16807/head
authorSeena Fallah <seenafallah@gmail.com>
Tue, 3 Feb 2026 17:13:39 +0000 (18:13 +0100)
committerSeena Fallah <seenafallah@gmail.com>
Wed, 4 Feb 2026 12:04:38 +0000 (13:04 +0100)
Add a configurable default-soa-edit-api setting that sets the
SOA-EDIT-API metadata for zones created via the API when the
zone creation request does not include the soa_edit_api field.

Signed-off-by: Seena Fallah <seenafallah@gmail.com>
docs/settings.rst
pdns/auth-main.cc
pdns/ws-auth.cc
regression-tests.api/runtests.py
regression-tests.api/test_Zones.py

index b600683fc7524a6cc12d0d6e9b2741f68509ca42..5f63f00c3922c57ad9e33e6c87d264379acdda3d 100644 (file)
@@ -483,6 +483,22 @@ Use this soa-edit value for all signed zones if no
 :ref:`metadata-soa-edit` metadata value is set.
 Overrides :ref:`setting-default-soa-edit`
 
+.. _setting-default-soa-edit-api:
+
+``default-soa-edit-api``
+------------------------
+
+-  String
+-  Default: DEFAULT
+
+.. versionadded:: 5.2.0
+
+The default :ref:`metadata-soa-edit-api` metadata value for zones created via
+the API when the zone creation request does not include the ``soa_edit_api`` field.
+Set to empty string to disable automatic SOA serial updates via the API.
+
+See :ref:`metadata-soa-edit-api` for the list of possible values.
+
 .. _setting-default-soa-mail:
 
 ``default-soa-mail``
index 44b3c5208c5a5a3b4858371a0ef58d4e512534e7..e9a2294b5d9fd8df6ba551481ae5955d279d64b6 100644 (file)
@@ -265,6 +265,7 @@ static void declareArguments()
   ::arg().set("default-soa-content", "Default SOA content") = "a.misconfigured.dns.server.invalid hostmaster.@ 0 10800 3600 604800 3600";
   ::arg().set("default-soa-edit", "Default SOA-EDIT value") = "";
   ::arg().set("default-soa-edit-signed", "Default SOA-EDIT value for signed zones") = "";
+  ::arg().set("default-soa-edit-api", "Default SOA-EDIT-API value for new zones") = "DEFAULT";
   ::arg().set("dnssec-key-cache-ttl", "Seconds to cache DNSSEC keys from the database") = "30";
   ::arg().set("domain-metadata-cache-ttl", "Seconds to cache zone metadata from the database") = "";
   ::arg().set("zone-metadata-cache-ttl", "Seconds to cache zone metadata from the database") = "60";
index fc00b560c7f8005f0e1aaaae54a93265ebf0849f..310c2ea23828851d6958b76fbcaae2ef0952e4a2 100644 (file)
@@ -2094,7 +2094,10 @@ static void apiServerZonesPOST(HttpRequest* req, HttpResponse* resp)
 
   try {
     // will be overridden by updateDomainSettingsFromDocument, if given in document.
-    domainInfo.backend->setDomainMetadataOne(zonename, "SOA-EDIT-API", "DEFAULT");
+    const string defaultSOAEditAPI = ::arg()["default-soa-edit-api"];
+    if (!defaultSOAEditAPI.empty()) {
+      domainInfo.backend->setDomainMetadataOne(zonename, "SOA-EDIT-API", defaultSOAEditAPI);
+    }
 
     for (auto& resourceRecord : new_records) {
       resourceRecord.domain_id = static_cast<int>(domainInfo.id);
index 8fd736450c4f9c2afb5b465857febeaf6fe5a16d..3b6c751cc91454239d0277b622170e5d5acdd3f6 100755 (executable)
@@ -73,6 +73,7 @@ views
 AUTH_COMMON_TPL = """
 module-dir=../regression-tests/modules
 default-soa-edit=INCEPTION-INCREMENT
+default-soa-edit-api=EPOCH
 launch+=bind
 bind-config=bindbackend.conf
 loglevel=5
index bd1642257a25cfd4a2cd3384872c7a2ce830c4d9..372b1cc6710777df1ce4f04bad9b5c7533fffe0e 100644 (file)
@@ -275,9 +275,38 @@ class AuthZones(ZonesApiTestCase, AuthZonesHelperMixin):
         self.assertEqual(data['catalog'], "default-catalog.example.com.")
 
     def test_create_zone_default_soa_edit_api(self):
+        """Test that zones created without soa_edit_api get the configured default-soa-edit-api value."""
         name, payload, data = self.create_zone()
         print(data)
-        self.assertEqual(data['soa_edit_api'], 'DEFAULT')
+        # default-soa-edit-api is set to EPOCH in the test config
+        self.assertEqual(data['soa_edit_api'], 'EPOCH')
+
+    def test_create_zone_override_soa_edit_api(self):
+        """Test that explicitly setting soa_edit_api overrides the default."""
+        name, payload, data = self.create_zone(soa_edit_api='SOA-EDIT-INCREASE')
+        print(data)
+        self.assertEqual(data['soa_edit_api'], 'SOA-EDIT-INCREASE')
+
+    def test_create_zone_empty_soa_edit_api(self):
+        """Test that explicitly setting soa_edit_api to empty does not use default."""
+        name, payload, data = self.create_zone(soa_edit_api='')
+        print(data)
+        self.assertEqual(data['soa_edit_api'], '')
+
+    def test_update_zone_does_not_override_soa_edit_api(self):
+        """Test that updating a zone does not change existing soa_edit_api to default."""
+        # Create zone with empty soa_edit_api
+        name, payload, data = self.create_zone(soa_edit_api='')
+        self.assertEqual(data['soa_edit_api'], '')
+        # Update zone without specifying soa_edit_api - it should remain empty
+        update_payload = {
+            'kind': 'Master',
+            'masters': ['192.0.2.1']
+        }
+        self.put_zone(name, update_payload)
+        data = self.get_zone(name)
+        # Verify soa_edit_api was NOT changed to the default value
+        self.assertEqual(data['soa_edit_api'], '')
 
     def test_create_zone_exists(self):
         name, payload, data = self.create_zone()
@@ -693,7 +722,8 @@ class AuthZones(ZonesApiTestCase, AuthZonesHelperMixin):
         Create a zone, then set and unset "dnssec", then check if the serial was increased
         after every step
         """
-        name, payload, data = self.create_zone()
+        # Use soa_edit_api='DEFAULT' to get predictable INCEPTION-INCREMENT serials
+        name, payload, data = self.create_zone(soa_edit_api='DEFAULT')
 
         soa_serial = get_first_rec(data, name, 'SOA')['content'].split(' ')[2]
         self.assertEqual(soa_serial[-2:], '01')