]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Add a few missing settings to the YAML configuration
authorRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 16 Jan 2025 13:25:35 +0000 (14:25 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 16 Jan 2025 13:25:35 +0000 (14:25 +0100)
pdns/dnsdistdist/dnsdist-configuration-yaml.cc
pdns/dnsdistdist/dnsdist-lua.cc
pdns/dnsdistdist/dnsdist-rust-lib/dnsdist-configuration-yaml-items-generated.cc
pdns/dnsdistdist/dnsdist-rust-lib/rust/src/lib.rs
pdns/dnsdistdist/dnsdist-settings-definitions.yml
pdns/dnsdistdist/docs/reference/yaml-settings.rst
pdns/misc.cc
pdns/misc.hh

index 19f18bfcde1eb866a57c7b2371056b50466a1563..3719c2dfa93299b5b895bdffb15eac1d1e800c01 100644 (file)
@@ -807,6 +807,73 @@ static void loadCustomPolicies(const ::rust::Vec<dnsdist::rust::settings::Custom
   }
 }
 
+static void handleOpenSSLSettings(const dnsdist::rust::settings::TlsTuningConfiguration& tlsSettings)
+{
+  for (const auto& engine : tlsSettings.engines) {
+#if defined(HAVE_LIBSSL) && !defined(HAVE_TLS_PROVIDERS)
+    auto [success, error] = libssl_load_engine(std::string(engine.name), !engine.default_string.empty() ? std::optional<std::string>(engine.default_string) : std::nullopt);
+    if (!success) {
+      warnlog("Error while trying to load TLS engine '%s': %s", std::string(engine.name), error);
+    }
+#else
+    warnlog("Ignoring TLS engine '%s' because OpenSSL engine support is not compiled in", std::string(engine.name));
+#endif /* HAVE_LIBSSL && !HAVE_TLS_PROVIDERS */
+  }
+
+  for (const auto& provider : tlsSettings.providers) {
+#if defined(HAVE_LIBSSL) && OPENSSL_VERSION_MAJOR >= 3 && defined(HAVE_TLS_PROVIDERS)
+    auto [success, error] = libssl_load_provider(std::string(provider));
+    if (!success) {
+      warnlog("Error while trying to load TLS provider '%s': %s", std::string(provider), error);
+    }
+#else
+    warnlog("Ignoring TLS provider '%s' because OpenSSL provider support is not compiled in", std::string(provider));
+#endif /* HAVE_LIBSSL && OPENSSL_VERSION_MAJOR >= 3 && HAVE_TLS_PROVIDERS */
+  }
+}
+
+static void handleLoggingConfiguration(const dnsdist::rust::settings::LoggingConfiguration& settings)
+{
+  if (!settings.verbose_log_destination.empty()) {
+    auto dest = std::string(settings.verbose_log_destination);
+    try {
+      auto stream = std::ofstream(dest.c_str());
+      dnsdist::logging::LoggingConfiguration::setVerboseStream(std::move(stream));
+    }
+    catch (const std::exception& e) {
+      errlog("Error while opening the verbose logging destination file %s: %s", dest, e.what());
+    }
+  }
+
+  if (!settings.syslog_facility.empty()) {
+    auto facilityLevel = logFacilityFromString(std::string(settings.syslog_facility));
+    if (!facilityLevel) {
+      warnlog("Unknown facility '%s' passed to logging.syslog_facility", std::string(settings.syslog_facility));
+    }
+    else {
+      setSyslogFacility(*facilityLevel);
+    }
+  }
+
+  if (settings.structured.enabled) {
+    auto levelPrefix = std::string(settings.structured.level_prefix);
+    auto timeFormat = std::string(settings.structured.time_format);
+    if (!timeFormat.empty()) {
+      if (timeFormat == "numeric") {
+        dnsdist::logging::LoggingConfiguration::setStructuredTimeFormat(dnsdist::logging::LoggingConfiguration::TimeFormat::Numeric);
+      }
+      else if (timeFormat == "ISO8601") {
+        dnsdist::logging::LoggingConfiguration::setStructuredTimeFormat(dnsdist::logging::LoggingConfiguration::TimeFormat::ISO8601);
+      }
+      else {
+        warnlog("Unknown value '%s' to logging.structured.time_format parameter", timeFormat);
+      }
+    }
+
+    dnsdist::logging::LoggingConfiguration::setStructuredLogging(true, levelPrefix);
+  }
+}
+
 #endif /* defined(HAVE_YAML_CONFIGURATION) */
 
 bool loadConfigurationFromFile(const std::string& fileName, bool isClient, bool configCheck)
@@ -831,6 +898,8 @@ bool loadConfigurationFromFile(const std::string& fileName, bool isClient, bool
   try {
     auto globalConfig = dnsdist::rust::settings::from_yaml_string(*data);
 
+    handleLoggingConfiguration(globalConfig.logging);
+
     if (!globalConfig.console.listen_address.empty()) {
       const auto& consoleConf = globalConfig.console;
       dnsdist::configuration::updateRuntimeConfiguration([consoleConf](dnsdist::configuration::RuntimeConfiguration& config) {
@@ -857,6 +926,8 @@ bool loadConfigurationFromFile(const std::string& fileName, bool isClient, bool
       });
     }
 
+    handleOpenSSLSettings(globalConfig.tuning.tls);
+
 #if defined(HAVE_EBPF)
     if (!configCheck && globalConfig.ebpf.ipv4.max_entries > 0 && globalConfig.ebpf.ipv6.max_entries > 0 && globalConfig.ebpf.qnames.max_entries > 0) {
       BPFFilter::MapFormat format = globalConfig.ebpf.external ? BPFFilter::MapFormat::WithActions : BPFFilter::MapFormat::Legacy;
index 067cdd4006c84d8c428bb2472a1c54a7569b58c2..b9119ea4969c40c5980eea7ba579416333a5245b 100644 (file)
@@ -2104,57 +2104,13 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
     }
     setLuaSideEffect();
     if (facility.type() == typeid(std::string)) {
-      static std::map<std::string, int> const facilities = {
-        {"local0", LOG_LOCAL0},
-        {"log_local0", LOG_LOCAL0},
-        {"local1", LOG_LOCAL1},
-        {"log_local1", LOG_LOCAL1},
-        {"local2", LOG_LOCAL2},
-        {"log_local2", LOG_LOCAL2},
-        {"local3", LOG_LOCAL3},
-        {"log_local3", LOG_LOCAL3},
-        {"local4", LOG_LOCAL4},
-        {"log_local4", LOG_LOCAL4},
-        {"local5", LOG_LOCAL5},
-        {"log_local5", LOG_LOCAL5},
-        {"local6", LOG_LOCAL6},
-        {"log_local6", LOG_LOCAL6},
-        {"local7", LOG_LOCAL7},
-        {"log_local7", LOG_LOCAL7},
-        /* most of these likely make very little sense
-           for dnsdist, but why not? */
-        {"kern", LOG_KERN},
-        {"log_kern", LOG_KERN},
-        {"user", LOG_USER},
-        {"log_user", LOG_USER},
-        {"mail", LOG_MAIL},
-        {"log_mail", LOG_MAIL},
-        {"daemon", LOG_DAEMON},
-        {"log_daemon", LOG_DAEMON},
-        {"auth", LOG_AUTH},
-        {"log_auth", LOG_AUTH},
-        {"syslog", LOG_SYSLOG},
-        {"log_syslog", LOG_SYSLOG},
-        {"lpr", LOG_LPR},
-        {"log_lpr", LOG_LPR},
-        {"news", LOG_NEWS},
-        {"log_news", LOG_NEWS},
-        {"uucp", LOG_UUCP},
-        {"log_uucp", LOG_UUCP},
-        {"cron", LOG_CRON},
-        {"log_cron", LOG_CRON},
-        {"authpriv", LOG_AUTHPRIV},
-        {"log_authpriv", LOG_AUTHPRIV},
-        {"ftp", LOG_FTP},
-        {"log_ftp", LOG_FTP}};
       auto facilityStr = boost::get<std::string>(facility);
-      toLowerInPlace(facilityStr);
-      auto facilityIt = facilities.find(facilityStr);
-      if (facilityIt == facilities.end()) {
+      auto facilityLevel = logFacilityFromString(facilityStr);
+      if (!facilityLevel) {
         g_outputBuffer = "Unknown facility '" + facilityStr + "' passed to setSyslogFacility()!\n";
         return;
       }
-      setSyslogFacility(facilityIt->second);
+      setSyslogFacility(*facilityLevel);
     }
     else {
       setSyslogFacility(boost::get<int>(facility));
index 020f705c86739b6b61a70369e51a4b55da4a7cae..fa81278bbd107c1204045ea5354135277409c3e7 100644 (file)
@@ -88,6 +88,12 @@ void convertRuntimeFlatSettingsFromRust(const dnsdist::rust::settings::GlobalCon
   if (config.d_secPollSuffix == "secpoll.powerdns.com.") {
     config.d_secPollSuffix = std::string(yamlConfig.security_polling.suffix);
   }
+  if (config.d_verbose == false) {
+    config.d_verbose = yamlConfig.logging.verbose;
+  }
+  if (config.d_verboseHealthChecks == false) {
+    config.d_verboseHealthChecks = yamlConfig.logging.verbose_health_checks;
+  }
   if (config.d_payloadSizeSelfGenAnswers == 1232) {
     config.d_payloadSizeSelfGenAnswers = yamlConfig.general.edns_udp_payload_size_self_generated_answers;
   }
@@ -100,12 +106,6 @@ void convertRuntimeFlatSettingsFromRust(const dnsdist::rust::settings::GlobalCon
   if (config.d_fixupCase == false) {
     config.d_fixupCase = yamlConfig.general.fixup_case;
   }
-  if (config.d_verbose == false) {
-    config.d_verbose = yamlConfig.general.verbose;
-  }
-  if (config.d_verboseHealthChecks == false) {
-    config.d_verboseHealthChecks = yamlConfig.general.verbose_health_checks;
-  }
   if (config.d_allowEmptyResponse == false) {
     config.d_allowEmptyResponse = yamlConfig.general.allow_empty_responses;
   }
index b2af8f006e459122104585e80e94c286b1008825..bf4c00c63ef76a326b433ddaaab73191e3d521eb 100644 (file)
@@ -1140,6 +1140,7 @@ mod dnsdistsettings {
         general: GeneralConfiguration,
         key_value_stores: KeyValueStoresConfiguration,
         load_balancing_policies: LoadBalancingPoliciesConfiguration,
+        logging: LoggingConfiguration,
         metrics: MetricsConfiguration,
         packet_caches: Vec<PacketCacheConfiguration>,
         pools: Vec<PoolConfiguration>,
@@ -1903,6 +1904,14 @@ mod dnsdistsettings {
         randomize_ids_to_backend: bool,
     }
 
+    #[derive(Deserialize, Serialize, Debug, PartialEq)]
+    #[serde(deny_unknown_fields)]
+    struct TlsEngineConfiguration {
+        name: String,
+        #[serde(default, skip_serializing_if = "crate::is_default")]
+        default_string: String,
+    }
+
     #[derive(Deserialize, Serialize, Debug, PartialEq)]
     #[serde(deny_unknown_fields)]
     struct TlsTuningConfiguration {
@@ -1912,6 +1921,10 @@ mod dnsdistsettings {
         outgoing_tickets_cache_validity: u16,
         #[serde(default = "crate::U16::<20>::value", skip_serializing_if = "crate::U16::<20>::is_equal")]
         max_outgoing_tickets_per_backend: u16,
+        #[serde(default, skip_serializing_if = "crate::is_default")]
+        providers: Vec<String>,
+        #[serde(default, skip_serializing_if = "crate::is_default")]
+        engines: Vec<TlsEngineConfiguration>,
     }
 
     #[derive(Deserialize, Serialize, Debug, PartialEq)]
@@ -1947,6 +1960,32 @@ mod dnsdistsettings {
         suffix: String,
     }
 
+    #[derive(Deserialize, Serialize, Debug, PartialEq)]
+    #[serde(deny_unknown_fields)]
+    struct StructuredLoggingConfiguration {
+        #[serde(default, skip_serializing_if = "crate::is_default")]
+        enabled: bool,
+        #[serde(default = "crate::default_value_structured_logging_level_prefix", skip_serializing_if = "crate::default_value_equal_structured_logging_level_prefix")]
+        level_prefix: String,
+        #[serde(default = "crate::default_value_structured_logging_time_format", skip_serializing_if = "crate::default_value_equal_structured_logging_time_format")]
+        time_format: String,
+    }
+
+    #[derive(Deserialize, Serialize, Debug, PartialEq)]
+    #[serde(deny_unknown_fields)]
+    struct LoggingConfiguration {
+        #[serde(default, skip_serializing_if = "crate::is_default")]
+        verbose: bool,
+        #[serde(default, skip_serializing_if = "crate::is_default")]
+        verbose_health_checks: bool,
+        #[serde(default, skip_serializing_if = "crate::is_default")]
+        verbose_log_destination: String,
+        #[serde(default, skip_serializing_if = "crate::is_default")]
+        syslog_facility: String,
+        #[serde(default, skip_serializing_if = "crate::is_default")]
+        structured: StructuredLoggingConfiguration,
+    }
+
     #[derive(Deserialize, Serialize, Debug, PartialEq)]
     #[serde(deny_unknown_fields)]
     struct GeneralConfiguration {
@@ -1959,10 +1998,6 @@ mod dnsdistsettings {
         #[serde(default, skip_serializing_if = "crate::is_default")]
         fixup_case: bool,
         #[serde(default, skip_serializing_if = "crate::is_default")]
-        verbose: bool,
-        #[serde(default, skip_serializing_if = "crate::is_default")]
-        verbose_health_checks: bool,
-        #[serde(default, skip_serializing_if = "crate::is_default")]
         allow_empty_responses: bool,
         #[serde(default, skip_serializing_if = "crate::is_default")]
         drop_empty_queries: bool,
@@ -2355,6 +2390,8 @@ impl ResponseRuleConfigurationSerde {
         #[serde(default, skip_serializing_if = "crate::is_default")]
         load_balancing_policies: dnsdistsettings::LoadBalancingPoliciesConfiguration,
         #[serde(default, skip_serializing_if = "crate::is_default")]
+        logging: dnsdistsettings::LoggingConfiguration,
+        #[serde(default, skip_serializing_if = "crate::is_default")]
         metrics: dnsdistsettings::MetricsConfiguration,
         #[serde(default, skip_serializing_if = "crate::is_default")]
         packet_caches: Vec<dnsdistsettings::PacketCacheConfiguration>,
@@ -3042,6 +3079,14 @@ impl Default for dnsdistsettings::UdpTuningConfiguration {
 }
 
 
+impl Default for dnsdistsettings::TlsEngineConfiguration {
+    fn default() -> Self {
+        let deserialized: dnsdistsettings::TlsEngineConfiguration = serde_yaml::from_str("").unwrap();
+        deserialized
+    }
+}
+
+
 impl Default for dnsdistsettings::TlsTuningConfiguration {
     fn default() -> Self {
         let deserialized: dnsdistsettings::TlsTuningConfiguration = serde_yaml::from_str("").unwrap();
@@ -3083,6 +3128,40 @@ impl Default for dnsdistsettings::SecurityPollingConfiguration {
 }
 
 
+// DEFAULT HANDLING for structured_logging_level_prefix
+fn default_value_structured_logging_level_prefix() -> String {
+    String::from("prio")
+}
+fn default_value_equal_structured_logging_level_prefix(value: &str)-> bool {
+    value == default_value_structured_logging_level_prefix()
+}
+
+
+// DEFAULT HANDLING for structured_logging_time_format
+fn default_value_structured_logging_time_format() -> String {
+    String::from("numeric")
+}
+fn default_value_equal_structured_logging_time_format(value: &str)-> bool {
+    value == default_value_structured_logging_time_format()
+}
+
+
+impl Default for dnsdistsettings::StructuredLoggingConfiguration {
+    fn default() -> Self {
+        let deserialized: dnsdistsettings::StructuredLoggingConfiguration = serde_yaml::from_str("").unwrap();
+        deserialized
+    }
+}
+
+
+impl Default for dnsdistsettings::LoggingConfiguration {
+    fn default() -> Self {
+        let deserialized: dnsdistsettings::LoggingConfiguration = serde_yaml::from_str("").unwrap();
+        deserialized
+    }
+}
+
+
 impl Default for dnsdistsettings::GeneralConfiguration {
     fn default() -> Self {
         let deserialized: dnsdistsettings::GeneralConfiguration = serde_yaml::from_str("").unwrap();
@@ -3495,8 +3574,16 @@ impl dnsdistsettings::UdpTuningConfiguration {
         Ok(())
     }
 }
+impl dnsdistsettings::TlsEngineConfiguration {
+    fn validate(&self) -> Result<(), ValidationError> {
+        Ok(())
+    }
+}
 impl dnsdistsettings::TlsTuningConfiguration {
     fn validate(&self) -> Result<(), ValidationError> {
+        for sub_type in &self.engines {
+        sub_type.validate()?;
+    }
         Ok(())
     }
 }
@@ -3515,6 +3602,17 @@ impl dnsdistsettings::SecurityPollingConfiguration {
         Ok(())
     }
 }
+impl dnsdistsettings::StructuredLoggingConfiguration {
+    fn validate(&self) -> Result<(), ValidationError> {
+        Ok(())
+    }
+}
+impl dnsdistsettings::LoggingConfiguration {
+    fn validate(&self) -> Result<(), ValidationError> {
+        self.structured.validate()?;
+        Ok(())
+    }
+}
 impl dnsdistsettings::GeneralConfiguration {
     fn validate(&self) -> Result<(), ValidationError> {
         Ok(())
@@ -3591,6 +3689,7 @@ impl GlobalConfigurationSerde {
         self.general.validate()?;
         self.key_value_stores.validate()?;
         self.load_balancing_policies.validate()?;
+        self.logging.validate()?;
         self.metrics.validate()?;
         for sub_type in &self.packet_caches {
         sub_type.validate()?;
index 879ef731ce9afa19c84e82146e573fb748f987ff..55e53918d673a71cb088ac9014cf4ba92e998d9f 100644 (file)
@@ -65,6 +65,10 @@ global:
       type: "LoadBalancingPoliciesConfiguration"
       default: true
       description: "Load-balancing policies"
+    - name: "logging"
+      type: "LoggingConfiguration"
+      default: true
+      description: "Logging settings"
     - name: "metrics"
       type: "MetricsConfiguration"
       default: true
@@ -490,23 +494,23 @@ ebpf:
     - name: "ipv4"
       type: "EbpfMapConfiguration"
       default: true
-      description: "IPv4 maps"
+      description: "IPv4 map"
     - name: "ipv6"
       type: "EbpfMapConfiguration"
       default: true
-      description: "IPv6 maps"
+      description: "IPv6 map"
     - name: "cidr_ipv4"
       type: "EbpfMapConfiguration"
       default: true
-      description: "IPv4 subnets maps"
+      description: "IPv4 subnets map"
     - name: "cidr_ipv6"
       type: "EbpfMapConfiguration"
       default: true
-      description: "IPv6 subnets maps"
+      description: "IPv6 subnets map"
     - name: "qnames"
       type: "EbpfMapConfiguration"
       default: true
-      description: "DNS names maps"
+      description: "DNS names map"
     - name: "external"
       type: "bool"
       default: "false"
@@ -1546,6 +1550,17 @@ udp_tuning:
       internal-field-name: "d_randomizeIDsToBackend"
       runtime-configurable: false
 
+tls_engine:
+  description: "OpenSSL engine settings"
+  parameters:
+    - name: "name"
+      type: "String"
+      description: "The engine name"
+    - name: "default_string"
+      type: "String"
+      default: ""
+      description: "The default string to pass to the engine. The exact value depends on the engine but represents the algorithms to register with the engine, as a list of comma-separated keywords. For example 'RSA,EC,DSA,DH,PKEY,PKEY_CRYPTO,PKEY_ASN1'"
+
 tls_tuning:
   category: "tuning.tls"
   parameters:
@@ -1567,6 +1582,16 @@ tls_tuning:
       lua-name: "setOutgoingTLSSessionsCacheMaxTicketsPerBackend"
       internal-field-name: "d_tlsSessionCacheMaxSessionsPerBackend"
       runtime-configurable: true
+    - name: "providers"
+      type: "Vec<String>"
+      default: ""
+      lua-name: "loadTLSProvider"
+      description: "Load OpenSSL providers. Providers can be used to accelerate cryptographic operations, like for example Intel QAT. At the moment up to a maximum of 32 loaded providers are supported, and that support is experimental. Note that this feature is only available when building against OpenSSL version >= 3.0 and with the ``-–enable-tls-provider`` configure flag on. In other cases, ``engines`` should be used instead. Some providers might actually degrade performance unless the TLS asynchronous mode of OpenSSL is enabled. To enable it see the ``async_mode`` parameter of TLS frontends"
+    - name: "engines"
+      type: "Vec<TlsEngineConfiguration>"
+      default: true
+      lua-name: "loadTLSEngine"
+      description: "Load OpenSSL engines. Engines can be used to accelerate cryptographic operations, like for example Intel QAT. At the moment up to a maximum of 32 loaded engines are supported, and that support is experimental. Some engines might actually degrade performance unless the TLS asynchronous mode of OpenSSL is enabled. To enable it see the ``async_mode`` parameter of TLS frontends"
 
 doh_tuning:
   category: "tuning.doh"
@@ -1632,6 +1657,66 @@ security_polling:
       internal-field-name: "d_secPollSuffix"
       runtime-configurable: true
 
+structured_logging:
+  description: "Structured-like logging settings"
+  parameters:
+    - name: "enabled"
+      type: "bool"
+      default: "false"
+      description: |
+                   Set whether log messages should be in a structured-logging-like format. This is turned off by default.
+                   The resulting format looks like this (when timestamps are enabled via ``--log-timestamps`` and with ``level_prefix: prio`` and ``time_format: ISO8601``)::
+
+                       ts=\"2023-11-06T12:04:58+0100\" prio=\"Info\" msg=\"Added downstream server 127.0.0.1:53\"
+
+                   And with ``level_prefix: level`` and ``time_format: numeric``)::
+
+                       ts=\"1699268815.133\" level=\"Info\" msg=\"Added downstream server 127.0.0.1:53\"
+
+    - name: "level_prefix"
+      type: "String"
+      default: "prio"
+      description: "Set the key name for the log level. There is unfortunately no standard name for this key, so in some setups it might be useful to set this value to a different name to have consistency across products"
+    - name: "time_format"
+      type: "String"
+      default: "numeric"
+      description: "Set the time format"
+      supported-values:
+        - "ISO8601"
+        - "numeric"
+
+logging:
+  description: "Logging settings"
+  parameters:
+    - name: "verbose"
+      type: "bool"
+      default: "false"
+      lua-name: "setVerbose"
+      internal-field-name: "d_verbose"
+      runtime-configurable: true
+      description: "Set whether log messages issued at the verbose level should be logged"
+    - name: "verbose_health_checks"
+      type: "bool"
+      default: "false"
+      lua-name: "setVerboseHealthChecks"
+      internal-field-name: "d_verboseHealthChecks"
+      runtime-configurable: true
+      description: "Set whether health check errors should be logged"
+    - name: "verbose_log_destination"
+      type: "String"
+      default: ""
+      lua-name: "setVerboseLogDestination"
+      description: "Set a destination file to write the ‘verbose’ log messages to, instead of sending them to syslog and/or the standard output which is the default. Note that these messages will no longer be sent to syslog or the standard output once this option has been set. There is no rotation or file size limit. Only use this feature for debugging under active operator control"
+    - name: "syslog_facility"
+      type: "String"
+      default: ""
+      lua-name: "setSyslogFacility"
+      description: "Set the syslog logging facility to the supplied value (values with or without the ``log_`` prefix are supported)"
+      supported-values: [local0, log_local0, local1, log_local1, local2, log_local2, local3, log_local3, local4, log_local4, local5, log_local5, local6, log_local6, local7, log_local7, kern, log_kern, user, log_user, mail, log_mail, daemon, log_daemon, auth, log_auth, syslog, log_syslog, lpr, log_lpr, news, log_news, uucp, log_uucp, cron, log_cron, authpriv, log_authpriv, ftp, log_ftp]
+    - name: "structured"
+      type: "StructuredLoggingConfiguration"
+      default: true
+
 general:
   parameters:
     - name: "edns_udp_payload_size_self_generated_answers"
@@ -1658,18 +1743,6 @@ general:
       lua-name: "fixupCase"
       internal-field-name: "d_fixupCase"
       runtime-configurable: true
-    - name: "verbose"
-      type: "bool"
-      default: "false"
-      lua-name: "setVerbose"
-      internal-field-name: "d_verbose"
-      runtime-configurable: true
-    - name: "verbose_health_checks"
-      type: "bool"
-      default: "false"
-      lua-name: "setVerboseHealthChecks"
-      internal-field-name: "d_verboseHealthChecks"
-      runtime-configurable: true
     - name: "allow_empty_responses"
       type: "bool"
       default: "false"
index 1b6467ae4b47b9fab9eb8cd87abd503e07deba19..21e2241335f50a3be0803a94dbca403c9512e92f 100644 (file)
@@ -35,6 +35,7 @@ GlobalConfiguration
 - **general**: :ref:`GeneralConfiguration <yaml-settings-GeneralConfiguration>` - General settings
 - **key_value_stores**: :ref:`KeyValueStoresConfiguration <yaml-settings-KeyValueStoresConfiguration>` - Key-Value stores
 - **load_balancing_policies**: :ref:`LoadBalancingPoliciesConfiguration <yaml-settings-LoadBalancingPoliciesConfiguration>` - Load-balancing policies
+- **logging**: :ref:`LoggingConfiguration <yaml-settings-LoggingConfiguration>` - Logging settings
 - **metrics**: :ref:`MetricsConfiguration <yaml-settings-MetricsConfiguration>` - Metrics-related settings
 - **packet_caches**: Sequence of :ref:`PacketCacheConfiguration <yaml-settings-PacketCacheConfiguration>` - Packet-cache definitions
 - **pools**: Sequence of :ref:`PoolConfiguration <yaml-settings-PoolConfiguration>` - Pools of backends
@@ -276,11 +277,11 @@ EbpfConfiguration
 
 ``eBPF`` and ``XDP`` related settings
 
-- **ipv4**: :ref:`EbpfMapConfiguration <yaml-settings-EbpfMapConfiguration>` - IPv4 maps
-- **ipv6**: :ref:`EbpfMapConfiguration <yaml-settings-EbpfMapConfiguration>` - IPv6 maps
-- **cidr_ipv4**: :ref:`EbpfMapConfiguration <yaml-settings-EbpfMapConfiguration>` - IPv4 subnets maps
-- **cidr_ipv6**: :ref:`EbpfMapConfiguration <yaml-settings-EbpfMapConfiguration>` - IPv6 subnets maps
-- **qnames**: :ref:`EbpfMapConfiguration <yaml-settings-EbpfMapConfiguration>` - DNS names maps
+- **ipv4**: :ref:`EbpfMapConfiguration <yaml-settings-EbpfMapConfiguration>` - IPv4 map
+- **ipv6**: :ref:`EbpfMapConfiguration <yaml-settings-EbpfMapConfiguration>` - IPv6 map
+- **cidr_ipv4**: :ref:`EbpfMapConfiguration <yaml-settings-EbpfMapConfiguration>` - IPv4 subnets map
+- **cidr_ipv6**: :ref:`EbpfMapConfiguration <yaml-settings-EbpfMapConfiguration>` - IPv6 subnets map
+- **qnames**: :ref:`EbpfMapConfiguration <yaml-settings-EbpfMapConfiguration>` - DNS names map
 - **external**: Boolean ``(false)`` - If set to true, :program:`dnsdist` does not load the internal ``eBPF`` program. This is useful for ``AF_XDP`` and ``XDP`` maps
 
 
@@ -316,8 +317,6 @@ GeneralConfiguration
 - **add_edns_to_self_generated_answers**: Boolean ``(true)``
 - **truncate_tc_answers**: Boolean ``(false)``
 - **fixup_case**: Boolean ``(false)``
-- **verbose**: Boolean ``(false)``
-- **verbose_health_checks**: Boolean ``(false)``
 - **allow_empty_responses**: Boolean ``(false)``
 - **drop_empty_queries**: Boolean ``(false)``
 - **capabilities_to_retain**: Sequence of String ``("")``
@@ -621,6 +620,20 @@ LoadBalancingPoliciesConfiguration
 - **hash_perturbation**: Unsigned integer ``(0)``
 
 
+.. _yaml-settings-LoggingConfiguration:
+
+LoggingConfiguration
+--------------------
+
+Logging settings
+
+- **verbose**: Boolean ``(false)`` - Set whether log messages issued at the verbose level should be logged
+- **verbose_health_checks**: Boolean ``(false)`` - Set whether health check errors should be logged
+- **verbose_log_destination**: String ``("")`` - Set a destination file to write the ‘verbose’ log messages to, instead of sending them to syslog and/or the standard output which is the default. Note that these messages will no longer be sent to syslog or the standard output once this option has been set. There is no rotation or file size limit. Only use this feature for debugging under active operator control
+- **syslog_facility**: String ``("")`` - Set the syslog logging facility to the supplied value (values with or without the ``log_`` prefix are supported). Supported values are: local0, log_local0, local1, log_local1, local2, log_local2, local3, log_local3, local4, log_local4, local5, log_local5, local6, log_local6, local7, log_local7, kern, log_kern, user, log_user, mail, log_mail, daemon, log_daemon, auth, log_auth, syslog, log_syslog, lpr, log_lpr, news, log_news, uucp, log_uucp, cron, log_cron, authpriv, log_authpriv, ftp, log_ftp
+- **structured**: :ref:`StructuredLoggingConfiguration <yaml-settings-StructuredLoggingConfiguration>`
+
+
 .. _yaml-settings-MetricsConfiguration:
 
 MetricsConfiguration
@@ -850,6 +863,26 @@ SnmpConfiguration
 - **daemon_socket**: String ``("")``
 
 
+.. _yaml-settings-StructuredLoggingConfiguration:
+
+StructuredLoggingConfiguration
+------------------------------
+
+Structured-like logging settings
+
+- **enabled**: Boolean ``(false)`` - Set whether log messages should be in a structured-logging-like format. This is turned off by default.
+The resulting format looks like this (when timestamps are enabled via ``--log-timestamps`` and with ``level_prefix: prio`` and ``time_format: ISO8601``)::
+
+    ts=\"2023-11-06T12:04:58+0100\" prio=\"Info\" msg=\"Added downstream server 127.0.0.1:53\"
+
+And with ``level_prefix: level`` and ``time_format: numeric``)::
+
+    ts=\"1699268815.133\" level=\"Info\" msg=\"Added downstream server 127.0.0.1:53\"
+
+- **level_prefix**: String ``(prio)`` - Set the key name for the log level. There is unfortunately no standard name for this key, so in some setups it might be useful to set this value to a different name to have consistency across products
+- **time_format**: String ``(numeric)`` - Set the time format. Supported values are: ISO8601, numeric
+
+
 .. _yaml-settings-TcpTuningConfiguration:
 
 TcpTuningConfiguration
@@ -869,6 +902,17 @@ TcpTuningConfiguration
 - **fast_open_key**: String ``("")``
 
 
+.. _yaml-settings-TlsEngineConfiguration:
+
+TlsEngineConfiguration
+----------------------
+
+OpenSSL engine settings
+
+- **name**: String - The engine name
+- **default_string**: String ``("")`` - The default string to pass to the engine. The exact value depends on the engine but represents the algorithms to register with the engine, as a list of comma-separated keywords. For example 'RSA,EC,DSA,DH,PKEY,PKEY_CRYPTO,PKEY_ASN1'
+
+
 .. _yaml-settings-TlsTuningConfiguration:
 
 TlsTuningConfiguration
@@ -877,6 +921,8 @@ TlsTuningConfiguration
 - **outgoing_tickets_cache_cleanup_delay**: Unsigned integer ``(60)``
 - **outgoing_tickets_cache_validity**: Unsigned integer ``(600)``
 - **max_outgoing_tickets_per_backend**: Unsigned integer ``(20)``
+- **providers**: Sequence of String ``("")`` - Load OpenSSL providers. Providers can be used to accelerate cryptographic operations, like for example Intel QAT. At the moment up to a maximum of 32 loaded providers are supported, and that support is experimental. Note that this feature is only available when building against OpenSSL version >= 3.0 and with the ``-–enable-tls-provider`` configure flag on. In other cases, ``engines`` should be used instead. Some providers might actually degrade performance unless the TLS asynchronous mode of OpenSSL is enabled. To enable it see the ``async_mode`` parameter of TLS frontends
+- **engines**: Sequence of :ref:`TlsEngineConfiguration <yaml-settings-TlsEngineConfiguration>` - Load OpenSSL engines. Engines can be used to accelerate cryptographic operations, like for example Intel QAT. At the moment up to a maximum of 32 loaded engines are supported, and that support is experimental. Some engines might actually degrade performance unless the TLS asynchronous mode of OpenSSL is enabled. To enable it see the ``async_mode`` parameter of TLS frontends
 
 
 .. _yaml-settings-TuningConfiguration:
index 29adfc51fa1cd7d73ff2f4f48bd9535b317bd474..1cc6d5114b2c8069f7c003e6e4785eab40c8c24e 100644 (file)
@@ -729,6 +729,62 @@ int logFacilityToLOG(unsigned int facility)
   }
 }
 
+std::optional<int> logFacilityFromString(std::string facilityStr)
+{
+  static std::unordered_map<std::string, int> const s_facilities = {
+    {"local0", LOG_LOCAL0},
+    {"log_local0", LOG_LOCAL0},
+    {"local1", LOG_LOCAL1},
+    {"log_local1", LOG_LOCAL1},
+    {"local2", LOG_LOCAL2},
+    {"log_local2", LOG_LOCAL2},
+    {"local3", LOG_LOCAL3},
+    {"log_local3", LOG_LOCAL3},
+    {"local4", LOG_LOCAL4},
+    {"log_local4", LOG_LOCAL4},
+    {"local5", LOG_LOCAL5},
+    {"log_local5", LOG_LOCAL5},
+    {"local6", LOG_LOCAL6},
+    {"log_local6", LOG_LOCAL6},
+    {"local7", LOG_LOCAL7},
+    {"log_local7", LOG_LOCAL7},
+    /* most of these likely make very little sense
+       for us, but why not? */
+    {"kern", LOG_KERN},
+    {"log_kern", LOG_KERN},
+    {"user", LOG_USER},
+    {"log_user", LOG_USER},
+    {"mail", LOG_MAIL},
+    {"log_mail", LOG_MAIL},
+    {"daemon", LOG_DAEMON},
+    {"log_daemon", LOG_DAEMON},
+    {"auth", LOG_AUTH},
+    {"log_auth", LOG_AUTH},
+    {"syslog", LOG_SYSLOG},
+    {"log_syslog", LOG_SYSLOG},
+    {"lpr", LOG_LPR},
+    {"log_lpr", LOG_LPR},
+    {"news", LOG_NEWS},
+    {"log_news", LOG_NEWS},
+    {"uucp", LOG_UUCP},
+    {"log_uucp", LOG_UUCP},
+    {"cron", LOG_CRON},
+    {"log_cron", LOG_CRON},
+    {"authpriv", LOG_AUTHPRIV},
+    {"log_authpriv", LOG_AUTHPRIV},
+    {"ftp", LOG_FTP},
+    {"log_ftp", LOG_FTP}
+  };
+
+  toLowerInPlace(facilityStr);
+  auto facilityIt = s_facilities.find(facilityStr);
+  if (facilityIt == s_facilities.end()) {
+    return std::nullopt;
+  }
+
+  return facilityIt->second;
+}
+
 string stripDot(const string& dom)
 {
   if(dom.empty())
index 39fdb6c086807e81f4280ec312545b7d36259201..66dd0ccf3e33a85fc02ef1c360525077138e4f4d 100644 (file)
@@ -109,6 +109,7 @@ bool getTSIGHashEnum(const DNSName& algoName, TSIGHashEnum& algoEnum);
 DNSName getTSIGAlgoName(TSIGHashEnum& algoEnum);
 
 int logFacilityToLOG(unsigned int facility);
+std::optional<int> logFacilityFromString(std::string facilityStr);
 
 template<typename Container>
 void