]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
First stab at converting api managed files
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Wed, 27 Sep 2023 12:56:14 +0000 (14:56 +0200)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Thu, 12 Oct 2023 07:17:30 +0000 (09:17 +0200)
pdns/recursordist/rec-main.cc
pdns/recursordist/settings/cxxsettings.hh
pdns/recursordist/settings/cxxsupport.cc

index 25e6d7d74c7c7ebeae5610fa8ef02553d1fb3d23..f61c81968396df121510e1a1aa7384316130ff81 100644 (file)
@@ -1288,6 +1288,7 @@ void parseACLs()
         throw runtime_error("Error processing '" + configName + "': " + msg);
         break;
       case pdns::settings::rec::YamlSettingsStatus::OK:
+        pdns::settings::rec::processAPIDir(arg()["include-dir"], settings, log);
         // Does *not* set include-dir
         pdns::settings::rec::setArgsForACLRelatedSettings(settings);
         break;
@@ -3384,6 +3385,7 @@ int main(int argc, char** argv)
       g_yamlSettings = true;
       SLOG(g_log << Logger::Notice << "YAML config found and processed for configname '" << yamlconfigname << "'" << endl,
            startupLog->info(Logr::Notice, "YAML config found and processed", "configname", Logging::Loggable(yamlconfigname)));
+      pdns::settings::rec::processAPIDir(arg()["include-dir"], settings, startupLog);
       pdns::settings::rec::bridgeStructToOldStyleSettings(settings);
       break;
     }
index 7577e86d320f0cf81ab6b8b915719d09120f2fc2..ad21578da1ee64a3ef5846764c8551f60e494a36 100644 (file)
@@ -43,6 +43,7 @@ bool oldKVToBridgeStruct(string& key, const string& value, ::rust::String& secti
 std::string oldStyleSettingsFileToYaml(const string& fname, bool mainFile);
 std::string defaultsToYaml();
 YamlSettingsStatus readYamlSettings(const std::string& configname, const std::string& includeDirOnCommandLine, rust::settings::rec::Recursorsettings& settings, std::string& msg, Logr::log_t log);
+void processAPIDir(const string& includeDirOnCommandLine, pdns::rust::settings::rec::Recursorsettings& settings, Logr::log_t log);
 void bridgeStructToOldStyleSettings(const pdns::rust::settings::rec::Recursorsettings& settings);
 void readYamlForwardZonesFile(const std::string& filename, ::rust::Vec<pdns::rust::settings::rec::ForwardZone>& vec, Logr::log_t log);
 void readYamlAllowFromFile(const std::string& filename, ::rust::Vec<::rust::String>& vec, Logr::log_t log);
index bde1a244a3aef7f217d88fe60022e7b1909a8c8f..b6db21383cc8598fa3d0aa34e583e15756c9a328 100644 (file)
@@ -22,6 +22,9 @@
 
 #include <fstream>
 #include <regex>
+#include <unistd.h>
+#include <cstdio>
+#include <libgen.h>
 
 #include "namespaces.hh"
 #include "arguments.hh"
@@ -131,6 +134,122 @@ static void mergeYamlSubFile(const std::string& configname, Recursorsettings& se
   pdns::rust::settings::rec::merge(settings, data);
 }
 
+static void convertACLFile(const string& includeDir, const string& apiDir, const std::string& filename)
+{
+  auto path = includeDir;
+  path.append("/").append(filename).append(".conf");
+  auto file = ifstream(path);
+  if (!file.is_open()) {
+    cerr << "Cannot open " << path << endl;
+    return;
+  }
+  rust::vec<rust::string> result;
+  std::string line;
+  while (getline(file, line)) {
+    auto pos = line.find('#');
+    if (pos != string::npos) {
+      line.resize(pos);
+    }
+    boost::trim(line);
+    if (line.empty()) {
+      continue;
+    }
+    auto plusis = line.find("+=");
+    if (plusis != string::npos) {
+      auto val = line.substr(plusis + 2);
+      boost::trim(val);
+      result.emplace_back(val);
+    }
+  }
+  rust::string yaml;
+  if (filename == "allow-from") {
+    yaml = pdns::rust::settings::rec::allow_from_to_yaml_string_incoming("allow_from", "allow_from_file", result);
+  }
+  else {
+    yaml = pdns::rust::settings::rec::allow_from_to_yaml_string_incoming("allow_notify_from", "allow_notify_from_file", result);
+  }
+  string yamlfilename =  apiDir;
+  yamlfilename.append("/").append(filename).append(".yml");
+  ofstream ofconf(yamlfilename + ".tmp");
+  if (!ofconf) {
+    throw runtime_error("Could not open config file '" + yamlfilename + "' for writing: " + stringerror());
+  }
+  ofconf << "# Generated by pdns-recursor REST API, DO NOT EDIT" << endl;
+  ofconf << yaml << endl;
+  ofconf.close();
+  cerr << "Converted " << path << " to " << yamlfilename <<endl;
+  if (rename(path.c_str(), (path + ".converted").c_str()) != 0) {
+    // LOGGING
+    unlink(yamlfilename.c_str());
+  }
+  // ERROR CHECKS AND LOG
+  rename((yamlfilename + ".tmp").c_str(), yamlfilename.c_str());
+}
+
+static void convertForwardsandAuths(const std::string& includeDir, const std::string& apiDir, Logr::log_t log)
+{
+  std::vector<std::string> forwardFiles;
+  ::arg().gatherIncludes(includeDir, "..conf", forwardFiles);
+  pdns::rust::settings::rec::Recursorsettings settings;
+  for (const auto& file : forwardFiles) {
+    auto yaml = pdns::settings::rec::oldStyleSettingsFileToYaml(file, false);
+    cerr << "Converted YAML for " << file << endl;
+    cerr << yaml << endl;
+    pdns::rust::settings::rec::merge(settings, yaml);
+  }
+  const string yamlAPiZonesFile = apiDir + "/apizones";
+
+  for (auto& zone : settings.recursor.auth_zones) {
+    const std::string origName(zone.file);
+    std::string newName(zone.file);
+    newName.replace(0, includeDir.length(), apiDir);
+    cerr << "Rename " << origName << ' ' << newName << ' ';
+    auto ret = rename(origName.c_str(), newName.c_str());
+    cerr << ret << ' ' << stringerror() << endl;
+    zone.file = ::rust::String(newName);
+    api_add_auth_zone(yamlAPiZonesFile, zone);
+  }
+  for (const auto& zone : settings.recursor.forward_zones) {
+    api_add_forward_zone(yamlAPiZonesFile, zone);
+  }
+  for (const auto& zone : settings.recursor.forward_zones_recurse) {
+    api_add_forward_zone(yamlAPiZonesFile, zone);
+  }
+  for (const auto& file : forwardFiles) {
+    rename(file.c_str(), (file + ".converted").c_str());
+  }
+}
+
+void pdns::settings::rec::processAPIDir(const string& includeDirOnCommandLine, pdns::rust::settings::rec::Recursorsettings& settings, Logr::log_t log)
+{
+  auto apiDir = std::string(settings.webservice.api_dir);
+  if (apiDir.empty()) {
+    return;
+  }
+  auto includeDir = std::string(settings.recursor.include_dir);
+  if (!includeDirOnCommandLine.empty()) {
+    includeDir = includeDirOnCommandLine;
+  }
+  if (includeDir == apiDir) {
+    throw runtime_error("Active YAML settings do not allow include_dir to be equal to api_dir");
+  }
+  const std::array<std::string, 2> aclFiles = {
+    "allow-from",
+    "allow-notify-from"
+  };
+  for (const auto& file : aclFiles) {
+    convertACLFile(includeDir, apiDir, file);
+    auto path = apiDir;
+    path.append("/").append(file).append(".yml");
+    try {
+      mergeYamlSubFile(path, settings, log);
+    }
+    catch (const runtime_error& err) {
+    }
+  }
+  convertForwardsandAuths(includeDir, apiDir, log);
+}
+
 pdns::settings::rec::YamlSettingsStatus pdns::settings::rec::readYamlSettings(const std::string& configname, const std::string& includeDirOnCommandLine, Recursorsettings& settings, std::string& msg, Logr::log_t log)
 {
   auto file = ifstream(configname);