]> 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:03:05 +0000 (18:03 +0200)
Signed-off-by: Remi Gacogne <remi.gacogne@powerdns.com>
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 e6f109054a58b381c493f543919cb3123aeb77ec..a78f295ab6a3af77e7093beec4e465f950b16b6d 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 133094e503b67bf755a18e43ef6cda2acdaeb964..7848e86a491f9046216ec6146372892ff5733960 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 fc98fc46c309f90abd6308ae6aafba83b739b364..3d4d63d4d0ff27c6eb8e1e776fa9be8ad4166b8f 100644 (file)
@@ -301,3 +301,47 @@ query_rules:
             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)