Skip to content

Commit

Permalink
dnsdist: Properly register the KVS objects before processing the rules
Browse files Browse the repository at this point in the history
  • Loading branch information
rgacogne committed Dec 13, 2024
1 parent c245829 commit ee84ff4
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 39 deletions.
82 changes: 43 additions & 39 deletions pdns/dnsdistdist/dnsdist-configuration-yaml.cc
Original file line number Diff line number Diff line change
Expand Up @@ -555,37 +555,6 @@ bool loadConfigurationFromFile(const std::string& fileName, bool isClient, bool
});
}

#if defined(HAVE_LMDB)
for (const auto& lmdb : globalConfig.key_value_stores.lmdb) {
auto store = std::shared_ptr<KeyValueStore>(std::make_shared<LMDBKVStore>(std::string(lmdb.file_name), std::string(lmdb.database_name), lmdb.no_lock));
registerType<KeyValueStore>(store, lmdb.name);
}
#endif /* defined(HAVE_LMDB) */
#if defined(HAVE_CDB)
for (const auto& cdb : globalConfig.key_value_stores.cdb) {
auto store = std::shared_ptr<KeyValueStore>(std::make_shared<CDBKVStore>(std::string(cdb.file_name), cdb.refresh_delay));
registerType<KeyValueStore>(store, cdb.name);
}
#endif /* defined(HAVE_CDB) */
#if defined(HAVE_LMDB) || defined(HAVE_CDB)
for (const auto& key : globalConfig.key_value_stores.lookup_keys.source_ip_keys) {
auto lookup = std::shared_ptr<KeyValueLookupKey>(std::make_shared<KeyValueLookupKeySourceIP>(key.v4_mask, key.v6_mask, key.include_port));
registerType<KeyValueLookupKey>(lookup, key.name);
}
for (const auto& key : globalConfig.key_value_stores.lookup_keys.qname_keys) {
auto lookup = std::shared_ptr<KeyValueLookupKey>(std::make_shared<KeyValueLookupKeyQName>(key.wire_format));
registerType<KeyValueLookupKey>(lookup, key.name);
}
for (const auto& key : globalConfig.key_value_stores.lookup_keys.suffix_keys) {
auto lookup = std::shared_ptr<KeyValueLookupKey>(std::make_shared<KeyValueLookupKeySuffix>(key.minimum_labels, key.wire_format));
registerType<KeyValueLookupKey>(lookup, key.name);
}
for (const auto& key : globalConfig.key_value_stores.lookup_keys.tag_keys) {
auto lookup = std::shared_ptr<KeyValueLookupKey>(std::make_shared<KeyValueLookupKeyTag>(std::string(key.tag)));
registerType<KeyValueLookupKey>(lookup, key.name);
}
#endif /* defined(HAVE_LMDB) || defined(HAVE_CDB) */

#ifndef DISABLE_CARBON
if (!globalConfig.metrics.carbon.empty()) {
dnsdist::configuration::updateRuntimeConfiguration([&globalConfig](dnsdist::configuration::RuntimeConfiguration& config) {
Expand Down Expand Up @@ -1119,11 +1088,11 @@ std::shared_ptr<DNSSelector> getNetmaskGroupSelector(const NetmaskGroupSelectorC
std::shared_ptr<DNSActionWrapper> getKeyValueStoreLookupAction(const KeyValueStoreLookupActionConfiguration& config)
{
auto kvs = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueStore>(std::string(config.kvs_name));
if (!kvs) {
if (!kvs && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
throw std::runtime_error("Unable to find the key-value store named '" + std::string(config.kvs_name) + "'");
}
auto lookupKey = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueLookupKey>(std::string(config.lookup_key_name));
if (!lookupKey) {
if (!lookupKey && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
throw std::runtime_error("Unable to find the key-value lookup key named '" + std::string(config.lookup_key_name) + "'");
}
auto action = dnsdist::actions::getKeyValueStoreLookupAction(kvs, lookupKey, std::string(config.destination_tag));
Expand All @@ -1133,11 +1102,11 @@ std::shared_ptr<DNSActionWrapper> getKeyValueStoreLookupAction(const KeyValueSto
std::shared_ptr<DNSActionWrapper> getKeyValueStoreRangeLookupAction(const KeyValueStoreRangeLookupActionConfiguration& config)
{
auto kvs = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueStore>(std::string(config.kvs_name));
if (!kvs) {
if (!kvs && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
throw std::runtime_error("Unable to find the key-value store named '" + std::string(config.kvs_name) + "'");
}
auto lookupKey = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueLookupKey>(std::string(config.lookup_key_name));
if (!lookupKey) {
if (!lookupKey && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
throw std::runtime_error("Unable to find the key-value lookup key named '" + std::string(config.lookup_key_name) + "'");
}
auto action = dnsdist::actions::getKeyValueStoreRangeLookupAction(kvs, lookupKey, std::string(config.destination_tag));
Expand All @@ -1147,11 +1116,11 @@ std::shared_ptr<DNSActionWrapper> getKeyValueStoreRangeLookupAction(const KeyVal
std::shared_ptr<DNSSelector> getKeyValueStoreLookupSelector(const KeyValueStoreLookupSelectorConfiguration& config)
{
auto kvs = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueStore>(std::string(config.kvs_name));
if (!kvs) {
if (!kvs && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
throw std::runtime_error("Unable to find the key-value store named '" + std::string(config.kvs_name) + "'");
}
auto lookupKey = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueLookupKey>(std::string(config.lookup_key_name));
if (!lookupKey) {
if (!lookupKey && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
throw std::runtime_error("Unable to find the key-value lookup key named '" + std::string(config.lookup_key_name) + "'");
}
auto selector = dnsdist::selectors::getKeyValueStoreLookupSelector(kvs, lookupKey);
Expand All @@ -1161,11 +1130,11 @@ std::shared_ptr<DNSSelector> getKeyValueStoreLookupSelector(const KeyValueStoreL
std::shared_ptr<DNSSelector> getKeyValueStoreRangeLookupSelector(const KeyValueStoreRangeLookupSelectorConfiguration& config)
{
auto kvs = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueStore>(std::string(config.kvs_name));
if (!kvs) {
if (!kvs && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
throw std::runtime_error("Unable to find the key-value store named '" + std::string(config.kvs_name) + "'");
}
auto lookupKey = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueLookupKey>(std::string(config.lookup_key_name));
if (!lookupKey) {
if (!lookupKey && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
throw std::runtime_error("Unable to find the key-value lookup key named '" + std::string(config.lookup_key_name) + "'");
}
auto selector = dnsdist::selectors::getKeyValueStoreRangeLookupSelector(kvs, lookupKey);
Expand Down Expand Up @@ -1321,6 +1290,41 @@ void registerDnstapLogger(const DnstapLoggersConfiguration& config)
#endif
}

void registerKVSObjects(const KeyValueStoresConfiguration& config)
{
bool createObjects = !dnsdist::configuration::yaml::s_inClientMode && !dnsdist::configuration::yaml::s_inConfigCheckMode;
#if defined(HAVE_LMDB)
for (const auto& lmdb : config.lmdb) {
auto store = createObjects ? std::shared_ptr<KeyValueStore>(std::make_shared<LMDBKVStore>(std::string(lmdb.file_name), std::string(lmdb.database_name), lmdb.no_lock)) : std::shared_ptr<KeyValueStore>();
dnsdist::configuration::yaml::registerType<KeyValueStore>(store, lmdb.name);
}
#endif /* defined(HAVE_LMDB) */
#if defined(HAVE_CDB)
for (const auto& cdb : config.cdb) {
auto store = createObjects ? std::shared_ptr<KeyValueStore>(std::make_shared<CDBKVStore>(std::string(cdb.file_name), cdb.refresh_delay)) : std::shared_ptr<KeyValueStore>();
dnsdist::configuration::yaml::registerType<KeyValueStore>(store, cdb.name);
}
#endif /* defined(HAVE_CDB) */
#if defined(HAVE_LMDB) || defined(HAVE_CDB)
for (const auto& key : config.lookup_keys.source_ip_keys) {
auto lookup = createObjects ? std::shared_ptr<KeyValueLookupKey>(std::make_shared<KeyValueLookupKeySourceIP>(key.v4_mask, key.v6_mask, key.include_port)) : std::shared_ptr<KeyValueLookupKey>();
dnsdist::configuration::yaml::registerType<KeyValueLookupKey>(lookup, key.name);
}
for (const auto& key : config.lookup_keys.qname_keys) {
auto lookup = createObjects ? std::shared_ptr<KeyValueLookupKey>(std::make_shared<KeyValueLookupKeyQName>(key.wire_format)) : std::shared_ptr<KeyValueLookupKey>();
dnsdist::configuration::yaml::registerType<KeyValueLookupKey>(lookup, key.name);
}
for (const auto& key : config.lookup_keys.suffix_keys) {
auto lookup = createObjects ? std::shared_ptr<KeyValueLookupKey>(std::make_shared<KeyValueLookupKeySuffix>(key.minimum_labels, key.wire_format)) : std::shared_ptr<KeyValueLookupKey>();
dnsdist::configuration::yaml::registerType<KeyValueLookupKey>(lookup, key.name);
}
for (const auto& key : config.lookup_keys.tag_keys) {
auto lookup = createObjects ? std::shared_ptr<KeyValueLookupKey>(std::make_shared<KeyValueLookupKeyTag>(std::string(key.tag))) : std::shared_ptr<KeyValueLookupKey>();
dnsdist::configuration::yaml::registerType<KeyValueLookupKey>(lookup, key.name);
}
#endif /* defined(HAVE_LMDB) || defined(HAVE_CDB) */
}

std::shared_ptr<DNSSelector> getAndSelector(const AndSelectorConfiguration& config)
{
std::vector<std::shared_ptr<DNSRule>> selectors;
Expand Down
2 changes: 2 additions & 0 deletions pdns/dnsdistdist/dnsdist-rust-bridge.hh
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ struct DNSResponseActionWrapper

struct ProtobufLoggersConfiguration;
struct DnstapLoggersConfiguration;
struct KeyValueStoresConfiguration;

void registerProtobufLogger(const ProtobufLoggersConfiguration& config);
void registerDnstapLogger(const DnstapLoggersConfiguration& config);
void registerKVSObjects(const KeyValueStoresConfiguration& config);

#include "dnsdist-rust-bridge-actions-generated.hh"
#include "dnsdist-rust-bridge-selectors-generated.hh"
Expand Down
1 change: 1 addition & 0 deletions pdns/dnsdistdist/dnsdist-rust-lib/rust-middle-in.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
type DNSResponseActionWrapper;
fn registerProtobufLogger(config: &ProtobufLoggersConfiguration);
fn registerDnstapLogger(config: &DnstapLoggersConfiguration);
fn registerKVSObjects(config: &KeyValueStoresConfiguration);
}
}

Expand Down
2 changes: 2 additions & 0 deletions pdns/dnsdistdist/dnsdist-rust-lib/rust-post-in.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ fn get_global_configuration_from_serde(
config.tuning = serde.tuning;
// this needs to be done before the rules so that they can refer to the loggers
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 selectors
// by name
config.selectors = get_selectors_from_serde(&serde.selectors);
Expand Down
3 changes: 3 additions & 0 deletions pdns/dnsdistdist/dnsdist-rust-lib/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2129,6 +2129,7 @@ mod dnsdistsettings {
type DNSResponseActionWrapper;
fn registerProtobufLogger(config: &ProtobufLoggersConfiguration);
fn registerDnstapLogger(config: &DnstapLoggersConfiguration);
fn registerKVSObjects(config: &KeyValueStoresConfiguration);
}
}

Expand Down Expand Up @@ -4143,6 +4144,8 @@ fn get_global_configuration_from_serde(
config.tuning = serde.tuning;
// this needs to be done before the rules so that they can refer to the loggers
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 selectors
// by name
config.selectors = get_selectors_from_serde(&serde.selectors);
Expand Down
138 changes: 138 additions & 0 deletions regression-tests.dnsdist/test_LMDB.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,144 @@ def testLMDBKeyValueStoreLookupRule(self):
self.assertTrue(receivedResponse)
self.assertEqual(expectedResponse, receivedResponse)

class TestLMDBYaml(TestLMDB):

_lmdbFileName = '/tmp/test-lmdb-db'
_lmdbDBName = 'db-name'
_config_template = ""
_config_params = []
_yaml_config_template = """---
backends:
- address: "127.0.0.1:%d"
protocol: Do53
key-value-stores:
lmdb:
- name: "lmdb-kvs"
file-name: "%s"
database-name: "%s"
lookup-keys:
source-ip-keys:
- name: "lookup-source-ip"
qname-keys:
- name: "lookup-qname"
- name: "lookup-qname-plaintext"
wire-format: false
suffix-keys:
- name: "lookup-suffix"
tag-keys:
- name: "lookup-tag-qname-result"
tag: "kvs-qname-result"
query-rules:
- name: "qname as key"
selector:
type: "And"
selectors:
- type: "QName"
qname: "kvs-rule.lmdb.tests.powerdns.com."
- type: "KeyValueStoreLookup"
kvs-name: "lmdb-kvs"
lookup-key-name: "lookup-qname-plaintext"
action:
type: "Spoof"
ips:
- "13.14.15.16"
- name: "source IP as key"
selector:
type: "All"
action:
type: "KeyValueStoreLookup"
kvs-name: "lmdb-kvs"
lookup-key-name: "lookup-source-ip"
destination-tag: "kvs-sourceip-result"
- name: "plaintext qname as key"
selector:
type: "All"
action:
type: "KeyValueStoreLookup"
kvs-name: "lmdb-kvs"
lookup-key-name: "lookup-qname-plaintext"
destination-tag: "kvs-plain-text-result"
- name: "plaintext qname tag check"
selector:
type: "Tag"
tag: "kvs-plain-text-result"
value: "this is the value of the plaintext tag"
action:
type: "Spoof"
ips:
- "9.10.11.12"
- name: "wire qname as key"
selector:
type: "All"
action:
type: "KeyValueStoreLookup"
kvs-name: "lmdb-kvs"
lookup-key-name: "lookup-qname"
destination-tag: "kvs-qname-result"
- name: "wire qname tag check"
selector:
type: "Tag"
tag: "kvs-qname-result"
value: "this is the value of the qname tag"
action:
type: "KeyValueStoreLookup"
kvs-name: "lmdb-kvs"
lookup-key-name: "lookup-tag-qname-result"
destination-tag: "kvs-tag-result"
- name: "source IP as key"
selector:
type: "All"
action:
type: "KeyValueStoreLookup"
kvs-name: "lmdb-kvs"
lookup-key-name: "lookup-source-ip"
destination-tag: "kvs-sourceip-result"
- name: "qname suffix as key"
selector:
type: "All"
action:
type: "KeyValueStoreLookup"
kvs-name: "lmdb-kvs"
lookup-key-name: "lookup-suffix"
destination-tag: "kvs-suffix-result"
- name: "tag check"
selector:
type: "Tag"
tag: "kvs-tag-result"
value: "this is the value of the second tag"
action:
type: "Spoof"
ips:
- "1.2.3.4"
- name: "suffix tag check"
selector:
type: "Tag"
tag: "kvs-suffix-result"
value: "this is the value of the suffix tag"
action:
type: "Spoof"
ips:
- "42.42.42.42"
- name: "source IP tag check"
selector:
type: "Tag"
tag: "kvs-sourceip-result"
value: "this is the value of the source address tag"
action:
type: "Spoof"
ips:
- "5.6.7.8"
- name: "otherwise"
selector:
type: "All"
action:
type: "Spoof"
ips:
- "9.9.9.9"
"""
_yaml_config_params = ['_testServerPort', '_lmdbFileName', '_lmdbDBName']

class TestLMDBIPInRange(DNSDistTest):

_lmdbFileName = '/tmp/test-lmdb-range-1-db'
Expand Down

0 comments on commit ee84ff4

Please sign in to comment.