]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
{3831] Logger output path restricted
authorThomas Markwalder <tmark@isc.org>
Mon, 12 May 2025 20:04:23 +0000 (16:04 -0400)
committerAndrei Pavel <andrei@isc.org>
Fri, 16 May 2025 09:20:43 +0000 (12:20 +0300)
Initial implementaion, still need docs and
autotools changes

meson.build
    Appended "kea" to LOGDIR

/src/bin/agent/tests/ca_process_tests.sh.in
/src/bin/d2/tests/d2_process_tests.sh.in
/src/bin/dhcp4/tests/dhcp4_process_tests.sh.in
/src/bin/dhcp6/tests/dhcp6_process_tests.sh.in
    export KEA_LOG_FILE_DIR

/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc
/src/bin/dhcp4/tests/http_control_socket_unittest.cc
/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc
/src/bin/dhcp6/tests/http_control_socket_unittest.cc
    Updated tests

/src/bin/dhcp6/tests/dhcp6_test_utils.*
    Added log path stuff to BaseServerTest

/src/bin/keactrl/tests/keactrl_tests.sh.in
/src/bin/shell/tests/ca_basic_auth_tests.sh.in
/src/bin/shell/tests/d2_basic_auth_tests.sh.in
/src/bin/shell/tests/dhcp4_basic_auth_tests.sh.in
/src/bin/shell/tests/dhcp6_basic_auth_tests.sh.in
/src/bin/shell/tests/shell_ca_process_tests.sh.in
/src/bin/shell/tests/shell_d2_process_tests.sh.in
/src/bin/shell/tests/tls_ca_process_tests.sh.in
/src/bin/shell/tests/tls_d2_process_tests.sh.in
/src/bin/shell/tests/tls_dhcp4_process_tests.sh.in
/src/bin/shell/tests/tls_dhcp6_process_tests.sh.in

/src/lib/process/log_parser.*
    Added  PathChecker singleton,
    LogConfigParser::getLogPath()
    LogConfigParser::validatePath()
    LogConfigParser::parseOutputOptions() - throws if
    output uses an invalid path

/src/lib/process/meson.build
    Defines LOGFILE_DIR

/src/lib/process/tests/log_parser_unittests.cc
    Updated tests

26 files changed:
meson.build
src/bin/agent/tests/ca_process_tests.sh.in
src/bin/d2/tests/d2_process_tests.sh.in
src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc
src/bin/dhcp4/tests/dhcp4_process_tests.sh.in
src/bin/dhcp4/tests/http_control_socket_unittest.cc
src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc
src/bin/dhcp6/tests/dhcp6_process_tests.sh.in
src/bin/dhcp6/tests/dhcp6_test_utils.cc
src/bin/dhcp6/tests/dhcp6_test_utils.h
src/bin/dhcp6/tests/http_control_socket_unittest.cc
src/bin/keactrl/tests/keactrl_tests.sh.in
src/bin/shell/tests/ca_basic_auth_tests.sh.in
src/bin/shell/tests/d2_basic_auth_tests.sh.in
src/bin/shell/tests/dhcp4_basic_auth_tests.sh.in
src/bin/shell/tests/dhcp6_basic_auth_tests.sh.in
src/bin/shell/tests/shell_ca_process_tests.sh.in
src/bin/shell/tests/shell_d2_process_tests.sh.in
src/bin/shell/tests/tls_ca_process_tests.sh.in
src/bin/shell/tests/tls_d2_process_tests.sh.in
src/bin/shell/tests/tls_dhcp4_process_tests.sh.in
src/bin/shell/tests/tls_dhcp6_process_tests.sh.in
src/lib/process/log_parser.cc
src/lib/process/log_parser.h
src/lib/process/meson.build
src/lib/process/tests/log_parser_unittests.cc

index c1faf1e6b19b04ab33e9712d211df1d3a48f70ca..f763eb99687d5409f2acefacae9265c228b8a5d5 100644 (file)
@@ -67,7 +67,7 @@ KEA_ADMIN_BUILT = TOP_BUILD_DIR / 'src/bin/admin/kea-admin'
 KEA_ADMIN_INSTALLED = PREFIX / SBINDIR / 'kea-admin'
 KEA_LFC_BUILT = TOP_BUILD_DIR / 'src/bin/lfc/kea-lfc'
 KEA_LFC_INSTALLED = PREFIX / SBINDIR / 'kea-lfc'
-LOGDIR = LOCALSTATEDIR / 'log'
+LOGDIR = LOCALSTATEDIR / 'log/kea'
 LOGDIR_INSTALLED = PREFIX / LOGDIR
 RUNSTATEDIR = LOCALSTATEDIR / 'run/kea'
 RUNSTATEDIR_INSTALLED = PREFIX / RUNSTATEDIR
index 627f70ac0fbf4e32521543590b80cabc3e5c8bf7..f01fff23f58f1072d569c1c25874c4da19079854 100755 (executable)
@@ -21,6 +21,9 @@ LOG_FILE="@abs_top_builddir@/src/bin/agent/tests/test.log"
 # Set env KEA_HOOKS_PATH  to override DEFAULT_HOOKS_PATH
 export KEA_HOOKS_PATH="@abs_top_builddir@/src/bin/agent/tests/@dotlibs@"
 
+# Set env KEA_LOG_FILE_DIR to override default log path
+export KEA_LOG_FILE_DIR="@abs_top_builddir@/src/bin/agent/tests"
+
 # Control Agent configuration to be stored in the configuration file.
 CONFIG="{
     \"Control-agent\":
index dc9cf746aa633706d05e56009151bbbd60cfd80e..71cd4b22d40576f850e7d57d36eab1b3cdce188a 100755 (executable)
@@ -17,6 +17,10 @@ LOG_FILE="@abs_top_builddir@/src/bin/d2/tests/test.log"
 # D2 configuration to be stored in the configuration file.
 # Set env KEA_HOOKS_PATH  to override DEFAULT_HOOKS_PATH
 export KEA_HOOKS_PATH="@abs_top_builddir@/src/bin/d2/tests/@dotlibs@"
+
+# Set env KEA_LOG_FILE_DIR to override default log path
+export KEA_LOG_FILE_DIR="@abs_top_builddir@/src/bin/d2/tests"
+
 CONFIG="{
     \"DhcpDdns\":
     {
index 4b53a26e8d9ca7c68da5657652306e4750f03ac5..06539f3dd882bd48eec470bd6c6f9841ee24efe8 100644 (file)
@@ -23,6 +23,7 @@
 #include <dhcp4/tests/dhcp4_test_utils.h>
 #include <hooks/hooks_manager.h>
 #include <log/logger_support.h>
+#include <process/log_parser.h>
 #include <stats/stats_mgr.h>
 #include <util/multi_threading_mgr.h>
 #include <util/chrono_time_utils.h>
@@ -54,6 +55,7 @@ using namespace isc::hooks;
 using namespace isc::stats;
 using namespace isc::test;
 using namespace isc::util;
+using namespace isc::process;
 namespace ph = std::placeholders;
 
 namespace {
@@ -120,6 +122,7 @@ public:
     ///
     /// Sets socket path to its default value.
     CtrlChannelDhcpv4SrvTest() : interfaces_("\"*\"") {
+        resetLogPath();
         const char* env = getenv("KEA_SOCKET_TEST_DIR");
         if (env) {
             socket_path_ = string(env) + "/kea4.sock";
@@ -134,6 +137,7 @@ public:
 
     /// @brief Destructor
     ~CtrlChannelDhcpv4SrvTest() {
+        resetLogPath();
         if (test_timer_) {
             test_timer_->cancel();
             getIOService()->stopAndPoll();
@@ -154,6 +158,18 @@ public:
         IfaceMgr::instance().detectIfaces();
     }
 
+    /// @brief Sets the log path where log output may be written.
+    /// @param explicit_path path to use as the log path.
+    void setLogTestPath(const std::string explicit_path = "") {
+        LogConfigParser::getLogPath(true, (!explicit_path.empty() ?
+                                           explicit_path : TEST_DATA_BUILDDIR));
+    }
+
+    /// @brief Resets the log path to TEST_DATA_BUILDDIR.
+    void resetLogPath() {
+        LogConfigParser::getLogPath(true);
+    }
+
     /// @brief Returns pointer to the server's IO service.
     ///
     /// @return Pointer to the server's IO service or null pointer if the server
@@ -675,6 +691,7 @@ TEST_F(CtrlChannelDhcpv4SrvTest, controlChannelStats) {
 
 // Check that the "config-set" command will replace current configuration
 TEST_F(CtrlChannelDhcpv4SrvTest, configSet) {
+    setLogTestPath("/dev");
     createUnixChannelServer();
 
     // Define strings to permutate the config arguments
@@ -913,6 +930,7 @@ TEST_F(CtrlChannelDhcpv4SrvTest, configHashGet) {
 
 // Verify that the "config-test" command will do what we expect.
 TEST_F(CtrlChannelDhcpv4SrvTest, configTest) {
+    setLogTestPath("/dev");
     createUnixChannelServer();
 
     // Define strings to permutate the config arguments
index 1b6b87f595183b75832fcd6d41f980911e4ecf57..ada74d9d1d9de1269b8f05f897011382f88ce65f 100755 (executable)
@@ -27,6 +27,9 @@ HOOK_FAIL_POLL_PATH="@abs_top_builddir@/src/bin/dhcp4/tests/@dotlibs@libco4.so"
 # Set env KEA_HOOKS_PATH  to override DEFAULT_HOOKS_PATH
 export KEA_HOOKS_PATH="@abs_top_builddir@/src/bin/dhcp4/tests/@dotlibs@"
 
+# Set env KEA_LOG_FILE_DIR to override default log path.
+export KEA_LOG_FILE_DIR="@abs_top_builddir@/src/bin/dhcp4/tests"
+
 # Kea configuration to be stored in the configuration file.
 CONFIG="{
     \"Dhcp4\":
index b4b717906a7752a729f16c8e2c30ba8f3d7b1573..a947c683eb4d385d33d700e4e668bc845d1f9b8a 100644 (file)
@@ -27,6 +27,7 @@
 #include <http/response_parser.h>
 #include <http/testutils/test_http_client.h>
 #include <log/logger_support.h>
+#include <process/log_parser.h>
 #include <stats/stats_mgr.h>
 #include <util/chrono_time_utils.h>
 
@@ -56,6 +57,7 @@ using namespace isc::hooks;
 using namespace isc::http;
 using namespace isc::stats;
 using namespace isc::util;
+using namespace isc::process;
 namespace ph = std::placeholders;
 
 namespace {
@@ -99,6 +101,7 @@ public:
         IfaceMgr::instance().setTestMode(false);
         IfaceMgr::instance().setDetectCallback(std::bind(&IfaceMgr::checkDetectIfaces,
                                                IfaceMgr::instancePtr().get(), ph::_1));
+        setLogTestPath("/dev");
     }
 
     /// @brief Destructor
@@ -117,6 +120,19 @@ public:
         IfaceMgr::instance().clearIfaces();
         IfaceMgr::instance().closeSockets();
         IfaceMgr::instance().detectIfaces();
+        resetLogPath();
+    }
+
+    /// @brief Sets the log path where log output may be written.
+    /// @param explicit_path path to use as the log path.
+    void setLogTestPath(const std::string explicit_path = "") {
+        LogConfigParser::getLogPath(true, (!explicit_path.empty() ?
+                                           explicit_path : TEST_DATA_BUILDDIR));
+    }
+
+    /// @brief Resets the log path to TEST_DATA_BUILDDIR.
+    void resetLogPath() {
+        LogConfigParser::getLogPath(true);
     }
 
     /// @brief Returns pointer to the server's IO service.
index 4cd19b9e5e6e9a63de4840c2045f1acbe4ede259..be1d1fa9e8d2e300826546f7cf9be648e5fca183 100644 (file)
@@ -707,6 +707,7 @@ TEST_F(CtrlChannelDhcpv6SrvTest, controlChannelStats) {
 
 // Check that the "config-set" command will replace current configuration
 TEST_F(CtrlChannelDhcpv6SrvTest, configSet) {
+    setLogTestPath("/dev");
     createUnixChannelServer();
 
     // Define strings to permutate the config arguments
@@ -946,6 +947,7 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configHashGet) {
 
 // Verify that the "config-test" command will do what we expect.
 TEST_F(CtrlChannelDhcpv6SrvTest, configTest) {
+    setLogTestPath("/dev");
     createUnixChannelServer();
 
     // Define strings to permutate the config arguments
index 06356538de5f0728e5272211e543da08410cad21..b84afc8eb21155ce32e6c63f06dccdc1c27cc88c 100755 (executable)
@@ -26,6 +26,9 @@ HOOK_FAIL_POLL_PATH="@abs_top_builddir@/src/bin/dhcp6/tests/@dotlibs@libco4.so"
 # Set env KEA_HOOKS_PATH  to override DEFAULT_HOOKS_PATH
 export KEA_HOOKS_PATH="@abs_top_builddir@/src/bin/dhcp6/tests/@dotlibs@"
 
+# Set env KEA_LOG_FILE_DIR to override default log path
+export KEA_LOG_FILE_DIR="@abs_top_builddir@/src/bin/dhcp6/tests"
+
 # Kea configuration to be stored in the configuration file.
 CONFIG="{
     \"Dhcp6\":
index ddb291b28bcbf8f49193918efa22115d5416ff69..fc8d3915ff9cec564aaa36bea09bcea1921458bc 100644 (file)
@@ -14,6 +14,7 @@
 #include <dhcp6/tests/dhcp6_test_utils.h>
 #include <dhcp6/json_config_parser.h>
 #include <log/logger_support.h>
+#include <process/log_parser.h>
 #include <stats/stats_mgr.h>
 #include <util/pointer_util.h>
 #include <cstdio>
@@ -25,6 +26,7 @@ using namespace isc::dhcp;
 using namespace isc::asiolink;
 using namespace isc::stats;
 using namespace isc::util;
+using namespace isc::process;
 using namespace boost::posix_time;
 
 namespace isc {
@@ -38,6 +40,7 @@ BaseServerTest::BaseServerTest() {
     CfgMgr::instance().setFamily(AF_INET6);
     original_datadir_ = CfgMgr::instance().getDataDir();
     CfgMgr::instance().getDataDir(true, TEST_DATA_BUILDDIR);
+    resetLogPath();
 }
 
 BaseServerTest::~BaseServerTest() {
@@ -56,6 +59,18 @@ BaseServerTest::~BaseServerTest() {
 
     // Revert to unit test logging, in case the test reconfigured it.
     isc::log::initLogger();
+    resetLogPath();
+}
+
+void
+BaseServerTest::setLogTestPath(const std::string explicit_path /* = "" */) {
+    LogConfigParser::getLogPath(true, (!explicit_path.empty() ?
+                                       explicit_path : TEST_DATA_BUILDDIR));
+}
+
+void
+BaseServerTest::resetLogPath() {
+    LogConfigParser::getLogPath(true);
 }
 
 Dhcpv6SrvTest::Dhcpv6SrvTest()
index 86980c09d71bbc37f661a4baab3612f3f9ce5144..4d950723e6171171f4ac487b9d7fc0483bd24ec6 100644 (file)
@@ -126,6 +126,13 @@ public:
     /// @brief Destructor.
     virtual ~BaseServerTest();
 
+    /// @brief Sets the log path where log output may be written.
+    /// @param explicit_path path to use as the log path.
+    void setLogTestPath(const std::string explicit_path = "");
+
+    /// @brief Resets the log path to TEST_DATA_BUILDDIR.
+    void resetLogPath();
+
 private:
 
     /// @brief Holds the original data directory.
index 70aa9776ceeaf035580135f55835b7f7a3627d7b..cf1552b40b2dc816f44e009c2e72647f486156d7 100644 (file)
@@ -91,6 +91,7 @@ public:
     HttpCtrlDhcpv6Test()
         : BaseServerTest() {
         reset();
+        setLogTestPath("/dev");
     }
 
     virtual ~HttpCtrlDhcpv6Test() {
index cd69b39633102dd594e914e5fac5241de6a85d6b..d95b74241aaeefae30e8c7bf6f64aa8a712d5cd2 100755 (executable)
@@ -59,6 +59,10 @@ KEACTRL_BUILD_DIR="@abs_top_builddir@"
 KEACTRL_CFG_FILE="@abs_top_builddir@/src/bin/keactrl/tests/keactrl_test.conf"
 # Path to the Kea log file.
 LOG_FILE="@abs_top_builddir@/src/bin/keactrl/tests/test.log"
+
+# Set env KEA_LOG_FILE_DIR to override default log path
+export KEA_LOG_FILE_DIR="@abs_top_builddir@/src/bin/keactrl/tests"
+
 # Binaries' names
 wildcard_name="kea-"
 kea4_name="${wildcard_name}dhcp4"
index dae5f46832742d31334043202e874e9730d4af7e..287a15c1a6fd8b5c215a36726ebfb83a2f98ca72 100755 (executable)
@@ -22,6 +22,9 @@ CFG_FILE="@abs_top_builddir@/src/bin/shell/tests/test_config.json"
 # Path to the Control Agent log file.
 LOG_FILE="@abs_top_builddir@/src/bin/shell/tests/test.log"
 
+# Set env KEA_LOG_FILE_DIR to override default log path.
+export KEA_LOG_FILE_DIR="@abs_top_builddir@/src/bin/shell/tests"
+
 # Control Agent configuration to be stored in the configuration file.
 # todo: use actual configuration once we support it.
 CONFIG="{
index c9ceb76f33150ab5df89c3fb19001fab08c1b2ac..aac0631dec046506971e981f3319243d4f574521 100755 (executable)
@@ -22,6 +22,9 @@ CFG_FILE="@abs_top_builddir@/src/bin/shell/tests/test_config.json"
 # Path to the D2 Server log file.
 LOG_FILE="@abs_top_builddir@/src/bin/shell/tests/test.log"
 
+# Set env KEA_LOG_FILE_DIR to override default log path.
+export KEA_LOG_FILE_DIR="@abs_top_builddir@/src/bin/shell/tests"
+
 # D2 Server configuration to be stored in the configuration file.
 # todo: use actual configuration once we support it.
 CONFIG="{
index 33b737ec8fabf5744a67829a2049fce606561714..9e07744956caf4e10444a4ef00aac8b4a5154a97 100755 (executable)
@@ -26,6 +26,9 @@ LEASE_FILE="@abs_top_builddir@/src/bin/shell/tests/test_leases.csv"
 # Path to the Dhcp4 Server log file.
 LOG_FILE="@abs_top_builddir@/src/bin/shell/tests/test.log"
 
+# Set env KEA_LOG_FILE_DIR to override default log path.
+export KEA_LOG_FILE_DIR="@abs_top_builddir@/src/bin/shell/tests"
+
 # Dhcp4 Server configuration to be stored in the configuration file.
 # todo: use actual configuration once we support it.
 CONFIG="{
index 07bf165077cdfcb5905c6d0856a99d38b8d663e6..311ee365e261bfa2042d58ce6fd3c5dcca0aeac0 100755 (executable)
@@ -26,6 +26,9 @@ LEASE_FILE="@abs_top_builddir@/src/bin/shell/tests/test_leases.csv"
 # Path to the Dhcp6 Server log file.
 LOG_FILE="@abs_top_builddir@/src/bin/shell/tests/test.log"
 
+# Set env KEA_LOG_FILE_DIR to override default log path.
+export KEA_LOG_FILE_DIR="@abs_top_builddir@/src/bin/shell/tests"
+
 # Dhcp6 Server configuration to be stored in the configuration file.
 # todo: use actual configuration once we support it.
 CONFIG="{
index 57a47a6c1bc571046385e9bb6037e41308ac6bf8..952bfcf69a35d29bc4d80732d5b988b6ff130c14 100755 (executable)
@@ -22,6 +22,9 @@ CFG_FILE="@abs_top_builddir@/src/bin/shell/tests/test_config.json"
 # Path to the Control Agent log file.
 LOG_FILE="@abs_top_builddir@/src/bin/shell/tests/test.log"
 
+# Set env KEA_LOG_FILE_DIR to override default log path.
+export KEA_LOG_FILE_DIR="@abs_top_builddir@/src/bin/shell/tests"
+
 # Control Agent configuration to be stored in the configuration file.
 # todo: use actual configuration once we support it.
 CONFIG="{
index cfe8dd171d4f0d56bce85a2a88f9187d72577ac7..902af94806cab826a75bffc38401de834358e0c6 100755 (executable)
@@ -22,6 +22,9 @@ CFG_FILE="@abs_top_builddir@/src/bin/shell/tests/test_config.json"
 # Path to the D2 Server log file.
 LOG_FILE="@abs_top_builddir@/src/bin/shell/tests/test.log"
 
+# Set env KEA_LOG_FILE_DIR to override default log path.
+export KEA_LOG_FILE_DIR="@abs_top_builddir@/src/bin/shell/tests"
+
 # D2 Server configuration to be stored in the configuration file.
 # todo: use actual configuration once we support it.
 CONFIG="{
index 8989f76403b5186021e33436c8f7c9013684a088..84a5300a085cd3ed28873026b849f91da2ec727d 100755 (executable)
@@ -23,6 +23,9 @@ CFG_FILE="@abs_top_builddir@/src/bin/shell/tests/test_config.json"
 # Path to the Control Agent log file.
 LOG_FILE="@abs_top_builddir@/src/bin/shell/tests/test.log"
 
+# Set env KEA_LOG_FILE_DIR to override default log path.
+export KEA_LOG_FILE_DIR="@abs_top_builddir@/src/bin/shell/tests"
+
 # Path to the test certificate authority directory.
 TEST_CA_DIR="@abs_top_srcdir@/src/lib/asiolink/testutils/ca"
 
index 70a5856400da0a0d4b7d0e933f768dfcbeccd41d..ffa7e1c3659e42e61ae65c03b6038e9bc6a41399 100755 (executable)
@@ -23,6 +23,9 @@ CFG_FILE="@abs_top_builddir@/src/bin/shell/tests/test_config.json"
 # Path to the D2 Server log file.
 LOG_FILE="@abs_top_builddir@/src/bin/shell/tests/test.log"
 
+# Set env KEA_LOG_FILE_DIR to override default log path.
+export KEA_LOG_FILE_DIR="@abs_top_builddir@/src/bin/shell/tests"
+
 # Path to the test certificate authority directory.
 TEST_CA_DIR="@abs_top_srcdir@/src/lib/asiolink/testutils/ca"
 
index 7e200994de5ad92bcb1087a82005a36ccd0f6b82..24cb1e8c027cd46b2e981e95958d85692f3d2dc8 100755 (executable)
@@ -27,6 +27,9 @@ LEASE_FILE="@abs_top_builddir@/src/bin/shell/tests/test_leases.csv"
 # Path to the Dhcp4 Server log file.
 LOG_FILE="@abs_top_builddir@/src/bin/shell/tests/test.log"
 
+# Set env KEA_LOG_FILE_DIR to override default log path.
+export KEA_LOG_FILE_DIR="@abs_top_builddir@/src/bin/shell/tests"
+
 # Path to the test certificate authority directory.
 TEST_CA_DIR="@abs_top_srcdir@/src/lib/asiolink/testutils/ca"
 
index 7f5269d9f7e436cdfb1d331e64032d62407b2d89..29c419a7af1301c7f98dc8e8cb7ae9517a13c439 100755 (executable)
@@ -27,6 +27,9 @@ LEASE_FILE="@abs_top_builddir@/src/bin/shell/tests/test_leases.csv"
 # Path to the Dhcp6 Server log file.
 LOG_FILE="@abs_top_builddir@/src/bin/shell/tests/test.log"
 
+# Set env KEA_LOG_FILE_DIR to override default log path.
+export KEA_LOG_FILE_DIR="@abs_top_builddir@/src/bin/shell/tests"
+
 # Path to the test certificate authority directory.
 TEST_CA_DIR="@abs_top_srcdir@/src/lib/asiolink/testutils/ca"
 
index c0cc19683d42ae9be8b80f112f10ce50e55526c5..53a37bcd77216aea733d82f49d61c349ce5ccf41 100644 (file)
 #include <log/logger_support.h>
 #include <log/logger_manager.h>
 #include <log/logger_name.h>
+#include <util/filesystem.h>
 
 using namespace isc::data;
 using namespace isc::log;
+using namespace isc::util::file;
 
 namespace isc {
 namespace process {
 
+namespace {
+    // Singleton PathChecker to set and hold valid log file path.
+    PathCheckerPtr log_path_checker_;
+};
+
 LogConfigParser::LogConfigParser(const ConfigPtr& storage)
     :config_(storage), verbose_(false) {
     if (!storage) {
@@ -126,6 +133,29 @@ void LogConfigParser::parseConfigEntry(isc::data::ConstElementPtr entry) {
     config_->addLoggingInfo(info);
 }
 
+std::string
+LogConfigParser::getLogPath(bool reset /* = false */, const std::string explicit_path /* = "" */) {
+    if (!log_path_checker_ || reset) {
+        log_path_checker_.reset(new PathChecker(LOGFILE_DIR, "KEA_LOG_FILE_DIR"));
+        if (!explicit_path.empty()) {
+            log_path_checker_->getPath(true, explicit_path);
+        }
+    }
+
+    return (log_path_checker_->getPath());
+}
+
+std::string
+LogConfigParser::validatePath(const std::string logpath,
+                                   bool enforce_path /* = true */) {
+    if (!log_path_checker_) {
+        getLogPath();
+    }
+
+    return (log_path_checker_->validatePath(logpath, enforce_path));
+}
+
+
 void LogConfigParser::parseOutputOptions(std::vector<LoggingDestination>& destination,
                                          isc::data::ConstElementPtr output_options) {
     if (!output_options) {
@@ -141,7 +171,20 @@ void LogConfigParser::parseOutputOptions(std::vector<LoggingDestination>& destin
             isc_throw(BadValue, "output-options entry does not have a mandatory 'output' "
                       "element (" << output_option->getPosition() << ")");
         }
-        dest.output_ = output->stringValue();
+
+        auto output_str = output->stringValue();
+        if ((output_str == "stdout") ||
+            (output_str == "stderr") ||
+            (output_str == "syslog")) {
+            dest.output_ = output_str;
+        } else {
+            try {
+                dest.output_ = validatePath(output_str);
+            } catch (const std::exception& ex) {
+                isc_throw(BadValue, "invalid path in `output`: " << ex.what() 
+                          <<  " (" << output_option->getPosition() << ")");
+            }
+        }
 
         isc::data::ConstElementPtr maxver_ptr = output_option->get("maxver");
         if (maxver_ptr) {
index bfb80d0ddc2ae8e311527d073f890fd4596b0289..bf9e913d84364d3a3ba7f7c2424c15b9ca329fb1 100644 (file)
@@ -58,6 +58,29 @@ public:
     void parseConfiguration(const isc::data::ConstElementPtr& log_config,
                             bool verbose = false);
 
+    /// @brief Fetches the supported log file path. 
+    ///
+    /// The first call to this function with no arguments will set the default
+    /// hooks path to either the value of LOGFILE_DIR or the environment
+    /// variable KEA_LOG_FILE_DIR if it is defined. Subsequent calls with no
+    /// arguments will simply return this value.
+    ///
+    /// @param reset recalculate when true, defaults to false.
+    /// @param explicit_path set default log path to this value. This is
+    /// for testing purposes only.
+    ///
+    /// @return String containing the default log file path.
+    static std::string getLogPath(bool reset = false, const std::string explicit_path = "");
+
+    /// @brief Validates a library path against the supported path for log files.
+    ///
+    /// @param logpath path to validate.
+    /// @param enforce_path enables validation against the supported path.
+    /// If false verifies only that the path contains a file name.
+    ///
+    /// @return validated path
+    static std::string validatePath(const std::string logpath, bool enforce_path = true);
+   
 private:
 
     /// @brief Parses one JSON structure in Server/loggers" array
index ba4968a5a73de2d98419595fa5efaa0f0db806f6..f25652d0372584ea2b0831223a0612806bd21cd0 100644 (file)
@@ -12,7 +12,10 @@ kea_process_lib = shared_library(
     'log_parser.cc',
     'process_messages.cc',
     'redact_config.cc',
-    cpp_args: [f'-DPIDFILE_DIR="@RUNSTATEDIR_INSTALLED@"'],
+    cpp_args: [
+        f'-DPIDFILE_DIR="@RUNSTATEDIR_INSTALLED@"',
+        f'-DLOGFILE_DIR="@LOGDIR_INSTALLED@"'
+    ],
     include_directories: [include_directories('.')] + INCLUDES,
     install: true,
     install_dir: LIBDIR,
index a09c4c2fa4d706a64ba91e884a114edfea7a01d9..c9f907447dce8b821d195c13efaa02c358e033f0 100644 (file)
@@ -32,7 +32,9 @@ namespace {
 class LoggingTest : public ::testing::Test {
     public:
         /// @brief Constructor
-        LoggingTest() {}
+        LoggingTest() {
+            resetLogPath();
+        }
 
         /// @brief Destructor
         ///
@@ -40,6 +42,7 @@ class LoggingTest : public ::testing::Test {
         ~LoggingTest() {
             isc::log::initLogger();
             wipeFiles();
+            resetLogPath();
         }
 
     /// @brief Generates a log file name suffixed with a rotation number
@@ -63,6 +66,19 @@ class LoggingTest : public ::testing::Test {
         static_cast<void>(remove(os.str().c_str()));
     }
 
+    /// @brief Sets the Hooks path from which hooks can be loaded.
+    /// @param explicit_path path to use as the hooks path.
+    void setLogTestPath(const std::string explicit_path = "") {
+        LogConfigParser::getLogPath(true,
+                                     (!explicit_path.empty() ?
+                                      explicit_path : TEST_DATA_BUILDDIR));
+    }
+
+    /// @brief Resets the log path to default.
+    void resetLogPath() {
+        LogConfigParser::getLogPath(true);
+    }
+
     /// @brief Name of the log file
     static const char* TEST_LOG_NAME;
 
@@ -115,7 +131,7 @@ TEST_F(LoggingTest, parsingConsoleOutput) {
 
     // We need to parse properly formed JSON and then extract
     // "loggers" element from it. For some reason fromJSON is
-    // throwing at opening square bracket
+    // throwing at openin0 square bracket
     ConstElementPtr config = Element::fromJSON(config_txt);
     config = config->get("loggers");
 
@@ -309,7 +325,8 @@ TEST_F(LoggingTest, parsingFile) {
     EXPECT_EQ(isc::log::INFO, storage->getLoggingInfo()[0].severity_);
 
     ASSERT_EQ(1, storage->getLoggingInfo()[0].destinations_.size());
-    EXPECT_EQ("logfile.txt" , storage->getLoggingInfo()[0].destinations_[0].output_);
+    EXPECT_EQ(LogConfigParser::validatePath("logfile.txt"),
+              storage->getLoggingInfo()[0].destinations_[0].output_);
     // Default for immediate flush is true
     EXPECT_TRUE(storage->getLoggingInfo()[0].destinations_[0].flush_);
 
@@ -365,14 +382,15 @@ TEST_F(LoggingTest, multipleLoggers) {
     EXPECT_EQ(0, storage->getLoggingInfo()[0].debuglevel_);
     EXPECT_EQ(isc::log::INFO, storage->getLoggingInfo()[0].severity_);
     ASSERT_EQ(1, storage->getLoggingInfo()[0].destinations_.size());
-    EXPECT_EQ("logfile.txt" , storage->getLoggingInfo()[0].destinations_[0].output_);
+    EXPECT_EQ(LogConfigParser::validatePath("logfile.txt"),
+              storage->getLoggingInfo()[0].destinations_[0].output_);
     EXPECT_TRUE(storage->getLoggingInfo()[0].destinations_[0].flush_);
-
     EXPECT_EQ("wombat", storage->getLoggingInfo()[1].name_);
     EXPECT_EQ(99, storage->getLoggingInfo()[1].debuglevel_);
     EXPECT_EQ(isc::log::DEBUG, storage->getLoggingInfo()[1].severity_);
     ASSERT_EQ(1, storage->getLoggingInfo()[1].destinations_.size());
-    EXPECT_EQ("logfile2.txt" , storage->getLoggingInfo()[1].destinations_[0].output_);
+    EXPECT_EQ(LogConfigParser::validatePath("logfile2.txt"),
+              storage->getLoggingInfo()[1].destinations_[0].output_);
     EXPECT_FALSE(storage->getLoggingInfo()[1].destinations_[0].flush_);
 }
 
@@ -380,7 +398,7 @@ TEST_F(LoggingTest, multipleLoggers) {
 // into Configuration usable by log4cplus. This test checks that more than
 // one logging destination can be configured.
 TEST_F(LoggingTest, multipleLoggingDestinations) {
-
+    setLogTestPath();
     const char* config_txt =
     "{ \"loggers\": ["
     "    {"
@@ -415,7 +433,8 @@ TEST_F(LoggingTest, multipleLoggingDestinations) {
     EXPECT_EQ(0, storage->getLoggingInfo()[0].debuglevel_);
     EXPECT_EQ(isc::log::INFO, storage->getLoggingInfo()[0].severity_);
     ASSERT_EQ(2, storage->getLoggingInfo()[0].destinations_.size());
-    EXPECT_EQ("logfile.txt" , storage->getLoggingInfo()[0].destinations_[0].output_);
+    EXPECT_EQ(LogConfigParser::validatePath("logfile.txt"),
+              storage->getLoggingInfo()[0].destinations_[0].output_);
     EXPECT_TRUE(storage->getLoggingInfo()[0].destinations_[0].flush_);
     EXPECT_EQ("stdout" , storage->getLoggingInfo()[0].destinations_[1].output_);
     EXPECT_TRUE(storage->getLoggingInfo()[0].destinations_[1].flush_);
@@ -427,6 +446,7 @@ TEST_F(LoggingTest, multipleLoggingDestinations) {
 // we can correctly configure logging such that rotation occurs as
 // expected.
 TEST_F(LoggingTest, logRotate) {
+    setLogTestPath();
     wipeFiles();
 
     std::ostringstream os;
@@ -467,7 +487,7 @@ TEST_F(LoggingTest, logRotate) {
     EXPECT_EQ(TEST_MAX_VERS, server_cfg->getLoggingInfo()[0].destinations_[0].maxver_);
 
     // Make sure we have the initial log file.
-    ASSERT_TRUE(isc::test::fileExists(TEST_LOG_NAME));
+    ASSERT_TRUE(isc::test::fileExists(LogConfigParser::validatePath(TEST_LOG_NAME)));
 
     // Now generate a log we know will be large enough to force a rotation.
     // We borrow a one argument log message for the test.
@@ -477,7 +497,7 @@ TEST_F(LoggingTest, logRotate) {
     for (int i = 1; i < TEST_MAX_VERS + 1; i++) {
         // Output the big log and make sure we get the expected rotation file.
         LOG_INFO(logger, DCTL_CONFIG_COMPLETE).arg(big_arg);
-        EXPECT_TRUE(isc::test::fileExists(logName(i).c_str()));
+        EXPECT_TRUE(isc::test::fileExists(LogConfigParser::validatePath(logName(i).c_str())));
     }
 
     // Clean up.
@@ -604,6 +624,7 @@ void testMaxSize(uint64_t maxsize_candidate, uint64_t expected_maxsize) {
 
 // Test that maxsize can be configured with high values.
 TEST_F(LoggingTest, maxsize) {
+    setLogTestPath();
     testMaxSize(TEST_MAX_SIZE, TEST_MAX_SIZE);
     testMaxSize(std::numeric_limits<int32_t>::max(), std::numeric_limits<int32_t>::max());
     testMaxSize(std::numeric_limits<uint32_t>::max(), std::numeric_limits<uint32_t>::max());