]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Allow registering NMG objects from YAML
authorRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 10 Jul 2025 15:11:08 +0000 (17:11 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 16 Jul 2025 16:12:17 +0000 (18:12 +0200)
Signed-off-by: Remi Gacogne <remi.gacogne@powerdns.com>
(cherry picked from commit f158a09f2d82c305a8297cd36713decb2cadb8f0)

pdns/dnsdistdist/dnsdist-configuration-yaml.cc
pdns/dnsdistdist/dnsdist-rust-bridge.hh
pdns/dnsdistdist/dnsdist-rust-lib/rust-middle-in.rs
pdns/dnsdistdist/dnsdist-rust-lib/rust-post-in.rs
pdns/dnsdistdist/dnsdist-settings-definitions.yml
regression-tests.dnsdist/test_Yaml.py

index 8efc581c64ca5b4730f4feca5b50372745174c78..1bb21caf3f842c52d962223273245372f66dc46c 100644 (file)
@@ -1782,6 +1782,26 @@ void registerKVSObjects([[maybe_unused]] const KeyValueStoresConfiguration& conf
 #endif /* defined(HAVE_LMDB) || defined(HAVE_CDB) */
 }
 
+void registerNMGObjects(const ::rust::Vec<NetmaskGroupConfiguration>& nmgs)
+{
+  for (const auto& netmaskGroup : nmgs) {
+    std::shared_ptr<NetmaskGroup> nmg;
+    bool registered = true;
+    nmg = dnsdist::configuration::yaml::getRegisteredTypeByName<NetmaskGroup>(std::string(netmaskGroup.name));
+    if (!nmg) {
+      nmg = std::make_shared<NetmaskGroup>();
+      registered = false;
+    }
+
+    for (const auto& netmask : netmaskGroup.netmasks) {
+      nmg->addMask(std::string(netmask));
+    }
+    if (!registered) {
+      dnsdist::configuration::yaml::registerType<NetmaskGroup>(nmg, netmaskGroup.name);
+    }
+  }
+}
+
 std::shared_ptr<DNSSelector> getLuaSelector(const LuaSelectorConfiguration& config)
 {
   dnsdist::selectors::LuaSelectorFunction function;
index 8ac417839a324559fb302966feb98d9d396b95df..73071aea5671af3b1ea9a52134b07437b45f1853 100644 (file)
@@ -33,10 +33,12 @@ struct DNSResponseActionWrapper
 struct ProtobufLoggerConfiguration;
 struct DnstapLoggerConfiguration;
 struct KeyValueStoresConfiguration;
+struct NetmaskGroupConfiguration;
 
 void registerProtobufLogger(const ProtobufLoggerConfiguration& config);
 void registerDnstapLogger(const DnstapLoggerConfiguration& config);
 void registerKVSObjects(const KeyValueStoresConfiguration& config);
+void registerNMGObjects(const ::rust::Vec<NetmaskGroupConfiguration>& nmgs);
 
 #include "dnsdist-rust-bridge-actions-generated.hh"
 #include "dnsdist-rust-bridge-selectors-generated.hh"
index 6dea5667323d68fecd46f3e69c1bb3b2a916a73b..8e12ed8e78a072712c1fdc993a27d6409a75b0cf 100644 (file)
@@ -15,6 +15,7 @@
         fn registerProtobufLogger(config: &ProtobufLoggerConfiguration);
         fn registerDnstapLogger(config: &DnstapLoggerConfiguration);
         fn registerKVSObjects(config: &KeyValueStoresConfiguration);
+        fn registerNMGObjects(nmgs: &Vec<NetmaskGroupConfiguration>);
     }
 }
 
index 4b1d269c006eca844d5af87cc728c5194c9649c4..0b5c5123d5fb964df1e199ff2f135eab4e06f77f 100644 (file)
@@ -74,6 +74,7 @@ fn get_global_configuration_from_serde(
     config.load_balancing_policies = serde.load_balancing_policies;
     config.logging = serde.logging;
     config.metrics = serde.metrics;
+    config.netmask_groups = serde.netmask_groups;
     config.packet_caches = serde.packet_caches;
     config.pools = serde.pools;
     config.proxy_protocol = serde.proxy_protocol;
@@ -89,6 +90,8 @@ fn get_global_configuration_from_serde(
     register_remote_loggers(&config.remote_logging);
     // this needs to be done before the rules so that they can refer to the KVS objects
     dnsdistsettings::registerKVSObjects(&config.key_value_stores);
+    // this needs to be done before the rules so that they can refer to the NMG objects
+    dnsdistsettings::registerNMGObjects(&config.netmask_groups);
     // this needs to be done BEFORE the rules so that they can refer to the selectors
     // by name
     config.selectors = get_selectors_from_serde(&serde.selectors)?;
index e496355c0a5dc1c25887ab29ee82debb247d93db..7ec8ad856e463935ec3fa5f4528bfd14636bfdbf 100644 (file)
@@ -73,6 +73,10 @@ global:
       type: "MetricsConfiguration"
       default: true
       description: "Metrics-related settings"
+    - name: "netmask_groups"
+      type: "Vec<NetmaskGroupConfiguration>"
+      default: true
+      description: "Netmask groups definitions"
     - name: "packet_caches"
       type: "Vec<PacketCacheConfiguration>"
       default: true
@@ -1874,6 +1878,17 @@ general:
                      Note that this does not grant the capabilities to the process, doing so might be done by running it as root which we don't advise, or by adding capabilities via the systemd unit file, for example.
                      Please also be aware that switching to a different user via ``--uid`` will still drop all capabilities."
 
+netmask_group:
+  description: "Group of netmasks"
+  parameters:
+    - name: "name"
+      type: "String"
+      description: "The name of this netmask group"
+    - name: "netmasks"
+      type: "Vec<String>"
+      default: ""
+      description: "List of netmasks"
+
 packet_cache:
   description: "Packet-cache settings"
   parameters:
index 4e4e79f653a72fb32f29eb841c2fde6d7b6cdebc..11056330f63f84dce971896af6fb008cdfdf205f 100644 (file)
@@ -257,3 +257,129 @@ addAction(QNameRule("notimp-lua.yaml-lua-mix.test.powerdns.com."), RCodeAction(D
             sender = getattr(self, method)
             (_, receivedResponse) = sender(query, response=None, useQueue=False)
             self.assertEqual(receivedResponse, expectedResponse)
+
+class TestYamlNMGRule(DNSDistTest):
+
+    _yaml_config_template = """---
+binds:
+  - listen_address: "127.0.0.1:%d"
+    protocol: Do53
+
+backends:
+  - address: "127.0.0.1:%d"
+    protocol: Do53
+
+query_rules:
+  - name: "refuse queries from non-allowed netmasks"
+    selector:
+      type: "Not"
+      selector:
+        type: "NetmaskGroup"
+        netmasks:
+          - "192.0.2.1/32"
+    action:
+      type: "RCode"
+      rcode: "5"
+"""
+    _yaml_config_params = ['_dnsDistPort', '_testServerPort']
+    _config_params = []
+
+    def testYamlNMGRule(self):
+        """
+        YAML: NMGRule should refuse our queries
+        """
+        name = 'nmgrule.yaml.tests.powerdns.com.'
+        query = dns.message.make_query(name, 'A', 'IN')
+        query.flags &= ~dns.flags.RD
+        expectedResponse = dns.message.make_response(query)
+        expectedResponse.set_rcode(dns.rcode.REFUSED)
+
+        for method in ("sendUDPQuery", "sendTCPQuery"):
+            sender = getattr(self, method)
+            (_, receivedResponse) = sender(query, response=None, useQueue=False)
+            self.assertEqual(receivedResponse, expectedResponse)
+
+class TestYamlNMGRule(DNSDistTest):
+
+    _yaml_config_template = """---
+binds:
+  - listen_address: "127.0.0.1:%d"
+    protocol: Do53
+
+backends:
+  - address: "127.0.0.1:%d"
+    protocol: Do53
+
+query_rules:
+  - name: "refuse queries from non-allowed netmasks"
+    selector:
+      type: "Not"
+      selector:
+        type: "NetmaskGroup"
+        netmasks:
+          - "192.0.2.1/32"
+    action:
+      type: "RCode"
+      rcode: "5"
+"""
+    _yaml_config_params = ['_dnsDistPort', '_testServerPort']
+    _config_params = []
+
+    def testYamlNMGRule(self):
+        """
+        YAML: NMGRule should refuse our queries
+        """
+        name = 'nmgrule.yaml.tests.powerdns.com.'
+        query = dns.message.make_query(name, 'A', 'IN')
+        query.flags &= ~dns.flags.RD
+        expectedResponse = dns.message.make_response(query)
+        expectedResponse.set_rcode(dns.rcode.REFUSED)
+
+        for method in ("sendUDPQuery", "sendTCPQuery"):
+            sender = getattr(self, method)
+            (_, receivedResponse) = sender(query, response=None, useQueue=False)
+            self.assertEqual(receivedResponse, expectedResponse)
+
+class TestYamlNMGRuleObject(DNSDistTest):
+
+    _yaml_config_template = """---
+binds:
+  - listen_address: "127.0.0.1:%d"
+    protocol: Do53
+
+backends:
+  - address: "127.0.0.1:%d"
+    protocol: Do53
+
+netmask_groups:
+  - name: "my-mng"
+    netmasks:
+      - "192.0.2.1/32"
+      - "127.0.0.1/32"
+
+query_rules:
+  - name: "refuse queries from specific netmasks"
+    selector:
+      type: "NetmaskGroup"
+      netmask_group_name: "my-mng"
+    action:
+      type: "RCode"
+      rcode: "5"
+"""
+    _yaml_config_params = ['_dnsDistPort', '_testServerPort']
+    _config_params = []
+
+    def testYamlNMGRule(self):
+        """
+        YAML: NMGRule (via a NMG object) should refuse our queries
+        """
+        name = 'nmgrule-object.yaml.tests.powerdns.com.'
+        query = dns.message.make_query(name, 'A', 'IN')
+        query.flags &= ~dns.flags.RD
+        expectedResponse = dns.message.make_response(query)
+        expectedResponse.set_rcode(dns.rcode.REFUSED)
+
+        for method in ("sendUDPQuery", "sendTCPQuery"):
+            sender = getattr(self, method)
+            (_, receivedResponse) = sender(query, response=None, useQueue=False)
+            self.assertEqual(receivedResponse, expectedResponse)