]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Disable Lua configuration directives in YAML mode
authorRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 13 Feb 2025 12:17:02 +0000 (13:17 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 13 Feb 2025 16:13:14 +0000 (17:13 +0100)
This commit restricts the Lua directives available to a Lua script
loaded alongside with a YAML configuration, disabling all Lua
configuration directives. This prevents a mess when settings are
set to different values in YAML and Lua, and make it clear that the
when a YAML configuration is used, any Lua file should only be used
to provide functions to the YAML configuration.
This behaviour can be reverted via the `enableLuaConfiguration`
directive if really needed.

pdns/dnsdistdist/dnsdist-console.cc
pdns/dnsdistdist/dnsdist-lua.cc
pdns/dnsdistdist/dnsdist-lua.hh
pdns/dnsdistdist/dnsdist-rust-lib/dnsdist-settings-documentation-generator.py
pdns/dnsdistdist/dnsdist.cc
pdns/dnsdistdist/docs/reference/config.rst
pdns/dnsdistdist/docs/reference/yaml-settings.rst

index b5581ac76243aa096f84a827e98a8c95f8ef985b..94ea4d2194b6b6493262eb305ca398a38eca4db4 100644 (file)
@@ -529,6 +529,7 @@ static const std::vector<dnsdist::console::ConsoleKeyword> s_consoleKeywords{
   {"dynBlockRulesGroup", true, "", "return a new DynBlockRulesGroup object"},
   {"EDNSVersionRule", true, "version", "matches queries with the specified EDNS version"},
   {"EDNSOptionRule", true, "optcode", "matches queries with the specified EDNS0 option present"},
+  {"enableLuaConfiguration", true, "", "Enable using Lua configuration directives along with a YAML configuration file. It is strongly advised not to use this directive unless absolutely necessary, and to prefer doing all the configuration in either Lua or YAML"},
   {"ERCodeAction", true, "ercode", "Reply immediately by turning the query into a response with the specified EDNS extended rcode"},
   {"ERCodeRule", true, "rcode", "matches responses with the specified extended rcode (EDNS0)"},
   {"exceedNXDOMAINs", true, "rate, seconds", "get set of addresses that exceed `rate` NXDOMAIN/s over `seconds` seconds"},
index 464f0192251d5d6a1eb3677b18a0d7a46d20f3ed..810fa4aba82124b4ecb33e86a06dde97e1b4f747 100644 (file)
@@ -411,14 +411,6 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
 {
   dnsdist::lua::setupConfigurationItems(luaCtx);
 
-  luaCtx.writeFunction("inClientStartup", [client]() {
-    return client && !dnsdist::configuration::isImmutableConfigurationDone();
-  });
-
-  luaCtx.writeFunction("inConfigCheck", [configCheck]() {
-    return configCheck;
-  });
-
   luaCtx.writeFunction("newServer",
                        [client, configCheck](boost::variant<string, newserver_t> pvars, boost::optional<int> qps) {
                          setLuaSideEffect();
@@ -3165,10 +3157,20 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
 
 namespace dnsdist::lua
 {
-void setupLua(LuaContext& luaCtx, bool client, bool configCheck)
+void setupLuaBindingsOnly(LuaContext& luaCtx, bool client, bool configCheck)
 {
-  setupLuaActions(luaCtx);
-  setupLuaConfig(luaCtx, client, configCheck);
+  luaCtx.writeFunction("inClientStartup", [client]() {
+    return client && !dnsdist::configuration::isImmutableConfigurationDone();
+  });
+
+  luaCtx.writeFunction("inConfigCheck", [configCheck]() {
+    return configCheck;
+  });
+
+  luaCtx.writeFunction("enableLuaConfiguration", [&luaCtx, client, configCheck]() {
+    setupLuaConfigurationOptions(luaCtx, client, configCheck);
+  });
+
   setupLuaBindings(luaCtx, client, configCheck);
   setupLuaBindingsDNSCrypt(luaCtx, client);
   setupLuaBindingsDNSParser(luaCtx);
@@ -3179,9 +3181,7 @@ void setupLua(LuaContext& luaCtx, bool client, bool configCheck)
   setupLuaBindingsPacketCache(luaCtx, client);
   setupLuaBindingsProtoBuf(luaCtx, client, configCheck);
   setupLuaBindingsRings(luaCtx, client);
-  dnsdist::lua::hooks::setupLuaHooks(luaCtx);
   setupLuaInspection(luaCtx);
-  setupLuaRules(luaCtx);
   setupLuaVars(luaCtx);
   setupLuaWeb(luaCtx);
 
@@ -3189,6 +3189,25 @@ void setupLua(LuaContext& luaCtx, bool client, bool configCheck)
   luaCtx.executeCode(getLuaFFIWrappers());
 #endif
 }
+
+void setupLuaConfigurationOptions(LuaContext& luaCtx, bool client, bool configCheck)
+{
+  static std::atomic<bool> s_initialized{false};
+  if (s_initialized.exchange(true)) {
+    return;
+  }
+
+  setupLuaConfig(luaCtx, client, configCheck);
+  setupLuaActions(luaCtx);
+  setupLuaRules(luaCtx);
+  dnsdist::lua::hooks::setupLuaHooks(luaCtx);
+}
+
+void setupLua(LuaContext& luaCtx, bool client, bool configCheck)
+{
+  setupLuaBindingsOnly(luaCtx, client, configCheck);
+  setupLuaConfigurationOptions(luaCtx, client, configCheck);
+}
 }
 
 namespace dnsdist::configuration::lua
index 09d18a643b005cba97376ff0fd94dfc69fcf55df..fc70190d72b60a20a425319a7b7b6b6cda80763a 100644 (file)
@@ -65,6 +65,8 @@ void setupLuaLoadBalancingContext(LuaContext& luaCtx);
 namespace dnsdist::lua
 {
 void setupLua(LuaContext& luaCtx, bool client, bool configCheck);
+void setupLuaBindingsOnly(LuaContext& luaCtx, bool client, bool configCheck);
+void setupLuaConfigurationOptions(LuaContext& luaCtx, bool client, bool configCheck);
 void setupConfigurationItems(LuaContext& luaCtx);
 
 template <class FunctionType>
index 4eef23a3b224063d7877e4f71e96f416116a92cf..c6c220375d64e9f865f4723b70b6cbf7173194b0 100644 (file)
@@ -138,6 +138,8 @@ Since 2.0.0, :program:`dnsdist` supports the YAML configuration format in additi
 
 If the configuration file passed to :program:`dnsdist` via the ``-C`` command-line switch ends in ``.yml``, it is assumed to be in the new YAML format, and an attempt to load a Lua configuration file with the same name but the ``.lua`` will be done before loading the YAML configuration. If the names ends in ``.lua``, there will also be an attempt to find a file with the same name but ending in ``.yml``. Otherwise the existing Lua configuration format is assumed.
 
+By default, when a YAML configuration file is used, any Lua configuration file used along the YAML configuration should only contain functions, and ideally even those should be defined either inline in the YAML file or in separate files included from the YAML configuration, for clarity. It is however possible to change this behaviour using the :func:`enableLuaConfiguration` directive to enable Lua configuration directives, but it is strongly advised not to use this directive unless absolutely necessary, and to prefer doing all the configuration in either Lua or YAML but to not mix them.
+
 A YAML configuration file contains several sections, that are described below.
 
 .. code-block:: yaml\n
index 4482fba142092f6fed89a38b26de8465acbc4037..b09bb0a734fcdf614993643eb13a0523976fd693 100644 (file)
@@ -3289,11 +3289,20 @@ static bool loadConfigurationFromFile(const std::string& configurationFile, bool
   if (boost::ends_with(configurationFile, ".yml")) {
     if (auto tentativeLuaConfFile = lookForTentativeConfigurationFileWithExtension(configurationFile, "lua")) {
       vinfolog("Loading configuration from auto-discovered Lua file %s", *tentativeLuaConfFile);
+      dnsdist::lua::setupLuaBindingsOnly(*(g_lua.lock()), isClient, configCheck);
       dnsdist::configuration::lua::loadLuaConfigurationFile(*(g_lua.lock()), *tentativeLuaConfFile, configCheck);
     }
     vinfolog("Loading configuration from YAML file %s", configurationFile);
-    return dnsdist::configuration::yaml::loadConfigurationFromFile(configurationFile, isClient, configCheck);
+    if (!dnsdist::configuration::yaml::loadConfigurationFromFile(configurationFile, isClient, configCheck)) {
+      return false;
+    }
+    if (!isClient && !configCheck) {
+      dnsdist::lua::setupLuaConfigurationOptions(*(g_lua.lock()), false, false);
+    }
+    return true;
   }
+
+  dnsdist::lua::setupLua(*(g_lua.lock()), isClient, configCheck);
   if (boost::ends_with(configurationFile, ".lua")) {
     vinfolog("Loading configuration from Lua file %s", configurationFile);
     dnsdist::configuration::lua::loadLuaConfigurationFile(*(g_lua.lock()), configurationFile, configCheck);
@@ -3358,7 +3367,6 @@ int main(int argc, char** argv)
     });
 
     if (cmdLine.beClient || !cmdLine.command.empty()) {
-      dnsdist::lua::setupLua(*(g_lua.lock()), true, false);
       if (!loadConfigurationFromFile(cmdLine.config, true, false)) {
 #ifdef COVERAGE
         exit(EXIT_FAILURE);
@@ -3395,7 +3403,6 @@ int main(int argc, char** argv)
     dnsdist::webserver::registerBuiltInWebHandlers();
 
     if (cmdLine.checkConfig) {
-      dnsdist::lua::setupLua(*(g_lua.lock()), false, true);
       if (!loadConfigurationFromFile(cmdLine.config, false, true)) {
 #ifdef COVERAGE
         exit(EXIT_FAILURE);
@@ -3420,7 +3427,6 @@ int main(int argc, char** argv)
     /* create the default pool no matter what */
     createPoolIfNotExists("");
 
-    dnsdist::lua::setupLua(*(g_lua.lock()), false, false);
     if (!loadConfigurationFromFile(cmdLine.config, false, false)) {
 #ifdef COVERAGE
       exit(EXIT_FAILURE);
index 11521e1be42b8d17efa1a0392f056af709711a98..4855fd87bbbaa9fb9893e682f1cac731fce9754d 100644 (file)
@@ -46,6 +46,13 @@ Global configuration
   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.
 
+.. function:: enableLuaConfiguration()
+
+  .. versionadded:: 2.0.0
+
+  Enable using Lua configuration directives along with a YAML configuration file. By default, when a YAML configuration file is used, any Lua configuration file used along the YAML configuration should only contain functions, and ideally even those should be defined either inline in the YAML file or in separate files included from the YAML configuration, for clarity.
+  It is strongly advised not to use this directive unless absolutely necessary, and to prefer doing all the configuration in either Lua or YAML but to not mix them.
+
 .. function:: includeDirectory(path)
 
   Include configuration files from ``path``.
index ccdf76da8f6cc9ac580b01820b28fdb18e9ef4a7..f02d2d29f940429ca2f49ec228e5a5ebe202ce00 100644 (file)
@@ -11,6 +11,8 @@ Since 2.0.0, :program:`dnsdist` supports the YAML configuration format in additi
 
 If the configuration file passed to :program:`dnsdist` via the ``-C`` command-line switch ends in ``.yml``, it is assumed to be in the new YAML format, and an attempt to load a Lua configuration file with the same name but the ``.lua`` will be done before loading the YAML configuration. If the names ends in ``.lua``, there will also be an attempt to find a file with the same name but ending in ``.yml``. Otherwise the existing Lua configuration format is assumed.
 
+By default, when a YAML configuration file is used, any Lua configuration file used along the YAML configuration should only contain functions, and ideally even those should be defined either inline in the YAML file or in separate files included from the YAML configuration, for clarity. It is however possible to change this behaviour using the :func:`enableLuaConfiguration` directive to enable Lua configuration directives, but it is strongly advised not to use this directive unless absolutely necessary, and to prefer doing all the configuration in either Lua or YAML but to not mix them.
+
 A YAML configuration file contains several sections, that are described below.
 
 .. code-block:: yaml