From: Remi Gacogne Date: Thu, 10 Jul 2025 15:11:08 +0000 (+0200) Subject: dnsdist: Allow registering NMG objects from YAML X-Git-Tag: rec-5.4.0-alpha0~19^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f158a09f2d82c305a8297cd36713decb2cadb8f0;p=thirdparty%2Fpdns.git dnsdist: Allow registering NMG objects from YAML Signed-off-by: Remi Gacogne --- diff --git a/pdns/dnsdistdist/dnsdist-configuration-yaml.cc b/pdns/dnsdistdist/dnsdist-configuration-yaml.cc index e6f109054a..a78f295ab6 100644 --- a/pdns/dnsdistdist/dnsdist-configuration-yaml.cc +++ b/pdns/dnsdistdist/dnsdist-configuration-yaml.cc @@ -1782,6 +1782,26 @@ void registerKVSObjects([[maybe_unused]] const KeyValueStoresConfiguration& conf #endif /* defined(HAVE_LMDB) || defined(HAVE_CDB) */ } +void registerNMGObjects(const ::rust::Vec& nmgs) +{ + for (const auto& netmaskGroup : nmgs) { + std::shared_ptr nmg; + bool registered = true; + nmg = dnsdist::configuration::yaml::getRegisteredTypeByName(std::string(netmaskGroup.name)); + if (!nmg) { + nmg = std::make_shared(); + registered = false; + } + + for (const auto& netmask : netmaskGroup.netmasks) { + nmg->addMask(std::string(netmask)); + } + if (!registered) { + dnsdist::configuration::yaml::registerType(nmg, netmaskGroup.name); + } + } +} + std::shared_ptr getLuaSelector(const LuaSelectorConfiguration& config) { dnsdist::selectors::LuaSelectorFunction function; diff --git a/pdns/dnsdistdist/dnsdist-rust-bridge.hh b/pdns/dnsdistdist/dnsdist-rust-bridge.hh index 8ac417839a..73071aea56 100644 --- a/pdns/dnsdistdist/dnsdist-rust-bridge.hh +++ b/pdns/dnsdistdist/dnsdist-rust-bridge.hh @@ -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& nmgs); #include "dnsdist-rust-bridge-actions-generated.hh" #include "dnsdist-rust-bridge-selectors-generated.hh" diff --git a/pdns/dnsdistdist/dnsdist-rust-lib/rust-middle-in.rs b/pdns/dnsdistdist/dnsdist-rust-lib/rust-middle-in.rs index 6dea566732..8e12ed8e78 100644 --- a/pdns/dnsdistdist/dnsdist-rust-lib/rust-middle-in.rs +++ b/pdns/dnsdistdist/dnsdist-rust-lib/rust-middle-in.rs @@ -15,6 +15,7 @@ fn registerProtobufLogger(config: &ProtobufLoggerConfiguration); fn registerDnstapLogger(config: &DnstapLoggerConfiguration); fn registerKVSObjects(config: &KeyValueStoresConfiguration); + fn registerNMGObjects(nmgs: &Vec); } } diff --git a/pdns/dnsdistdist/dnsdist-rust-lib/rust-post-in.rs b/pdns/dnsdistdist/dnsdist-rust-lib/rust-post-in.rs index 4b1d269c00..0b5c5123d5 100644 --- a/pdns/dnsdistdist/dnsdist-rust-lib/rust-post-in.rs +++ b/pdns/dnsdistdist/dnsdist-rust-lib/rust-post-in.rs @@ -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)?; diff --git a/pdns/dnsdistdist/dnsdist-settings-definitions.yml b/pdns/dnsdistdist/dnsdist-settings-definitions.yml index 133094e503..7848e86a49 100644 --- a/pdns/dnsdistdist/dnsdist-settings-definitions.yml +++ b/pdns/dnsdistdist/dnsdist-settings-definitions.yml @@ -73,6 +73,10 @@ global: type: "MetricsConfiguration" default: true description: "Metrics-related settings" + - name: "netmask_groups" + type: "Vec" + default: true + description: "Netmask groups definitions" - name: "packet_caches" type: "Vec" 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" + default: "" + description: "List of netmasks" + packet_cache: description: "Packet-cache settings" parameters: diff --git a/regression-tests.dnsdist/test_Yaml.py b/regression-tests.dnsdist/test_Yaml.py index fc98fc46c3..3d4d63d4d0 100644 --- a/regression-tests.dnsdist/test_Yaml.py +++ b/regression-tests.dnsdist/test_Yaml.py @@ -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)