From dda6c02f8c9205a4accce268bd094c9b508170cf Mon Sep 17 00:00:00 2001 From: jr0me Date: Mon, 7 Oct 2024 18:54:37 -0300 Subject: [PATCH 01/18] feat: add boilerplate files for CentralizedConfiguration --- src/modules/CMakeLists.txt | 1 + .../centralized_configuration/CMakeLists.txt | 19 +++++++++++++++++++ .../include/centralized_configuration.hpp | 8 ++++++++ .../src/centralized_configuration.cpp | 2 ++ .../tests/CMakeLists.txt | 7 +++++++ .../tests/centralized_configuration_tests.cpp | 18 ++++++++++++++++++ 6 files changed, 55 insertions(+) create mode 100644 src/modules/centralized_configuration/CMakeLists.txt create mode 100644 src/modules/centralized_configuration/include/centralized_configuration.hpp create mode 100644 src/modules/centralized_configuration/src/centralized_configuration.cpp create mode 100644 src/modules/centralized_configuration/tests/CMakeLists.txt create mode 100644 src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index 43a3e3815c..657dc241ae 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -5,6 +5,7 @@ project(ModuleManager) include(../cmake/CommonSettings.cmake) set_common_settings() +add_subdirectory(centralized_configuration) add_subdirectory(inventory) add_library(ModuleManager src/moduleManager.cpp) diff --git a/src/modules/centralized_configuration/CMakeLists.txt b/src/modules/centralized_configuration/CMakeLists.txt new file mode 100644 index 0000000000..ac3d74d9d7 --- /dev/null +++ b/src/modules/centralized_configuration/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.22) + +project(CentralizedConfiguration) + +include(../../cmake/CommonSettings.cmake) +set_common_settings() + +include_directories(${CMAKE_SOURCE_DIR}/common/logger/include) + +add_library(CentralizedConfiguration src/centralized_configuration.cpp) +target_include_directories(CentralizedConfiguration PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) + +include(../../cmake/ConfigureTarget.cmake) +configure_target(CentralizedConfiguration) + +if(BUILD_TESTS) + enable_testing() + add_subdirectory(tests) +endif() diff --git a/src/modules/centralized_configuration/include/centralized_configuration.hpp b/src/modules/centralized_configuration/include/centralized_configuration.hpp new file mode 100644 index 0000000000..e8af20e430 --- /dev/null +++ b/src/modules/centralized_configuration/include/centralized_configuration.hpp @@ -0,0 +1,8 @@ +#pragma once + +namespace centralized_configuration +{ + class CentralizedConfiguration + { + }; +} // namespace centralized_configuration diff --git a/src/modules/centralized_configuration/src/centralized_configuration.cpp b/src/modules/centralized_configuration/src/centralized_configuration.cpp new file mode 100644 index 0000000000..43305b96fc --- /dev/null +++ b/src/modules/centralized_configuration/src/centralized_configuration.cpp @@ -0,0 +1,2 @@ +#include + diff --git a/src/modules/centralized_configuration/tests/CMakeLists.txt b/src/modules/centralized_configuration/tests/CMakeLists.txt new file mode 100644 index 0000000000..6e6f6a990f --- /dev/null +++ b/src/modules/centralized_configuration/tests/CMakeLists.txt @@ -0,0 +1,7 @@ +find_package(GTest CONFIG REQUIRED) + +add_executable(centralized_configuration_test centralized_configuration_tests.cpp) +configure_target(centralized_configuration_test) +target_include_directories(centralized_configuration_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include) +target_link_libraries(centralized_configuration_test PRIVATE CentralizedConfiguration GTest::gtest GTest::gmock) +add_test(NAME CentralizedConfiguration COMMAND centralized_configuration_test) diff --git a/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp new file mode 100644 index 0000000000..1a03059cb1 --- /dev/null +++ b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp @@ -0,0 +1,18 @@ +#include + +#include + +using centralized_configuration::CentralizedConfiguration; + +TEST(CentralizedConfiguration, Constructor) +{ + EXPECT_NO_THROW( + [[maybe_unused]] CentralizedConfiguration centralizedConfiguration + ); +} + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} From c28f3028f3f2cb88085fe166a6593ee79a60fbdf Mon Sep 17 00:00:00 2001 From: jr0me Date: Tue, 8 Oct 2024 17:51:58 -0300 Subject: [PATCH 02/18] feat: add module wrapper interface methods to CentralizedConfiguration At the moment just Start, Stop and Name. This class will not be performing any specific actions on start and stop, at least for this PR. --- .../include/centralized_configuration.hpp | 6 ++++++ .../src/centralized_configuration.cpp | 15 +++++++++++++++ .../tests/centralized_configuration_tests.cpp | 8 ++++++++ 3 files changed, 29 insertions(+) diff --git a/src/modules/centralized_configuration/include/centralized_configuration.hpp b/src/modules/centralized_configuration/include/centralized_configuration.hpp index e8af20e430..391a147b77 100644 --- a/src/modules/centralized_configuration/include/centralized_configuration.hpp +++ b/src/modules/centralized_configuration/include/centralized_configuration.hpp @@ -1,8 +1,14 @@ #pragma once +#include + namespace centralized_configuration { class CentralizedConfiguration { + public: + void Start() const; + void Stop() const; + std::string Name() const; }; } // namespace centralized_configuration diff --git a/src/modules/centralized_configuration/src/centralized_configuration.cpp b/src/modules/centralized_configuration/src/centralized_configuration.cpp index 43305b96fc..d04bab13ab 100644 --- a/src/modules/centralized_configuration/src/centralized_configuration.cpp +++ b/src/modules/centralized_configuration/src/centralized_configuration.cpp @@ -1,2 +1,17 @@ #include +namespace centralized_configuration +{ + void CentralizedConfiguration::Start() const + { + } + + void CentralizedConfiguration::Stop() const + { + } + + std::string CentralizedConfiguration::Name() const + { + return "CentralizedConfiguration"; + } +} // namespace centralized_configuration diff --git a/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp index 1a03059cb1..84ddd22cb7 100644 --- a/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp +++ b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp @@ -11,6 +11,14 @@ TEST(CentralizedConfiguration, Constructor) ); } +TEST(CentralizedConfiguration, ImplementsModuleWrapperInterface) +{ + CentralizedConfiguration centralizedConfiguration; + EXPECT_NO_THROW(centralizedConfiguration.Start()); + EXPECT_NO_THROW(centralizedConfiguration.Stop()); + EXPECT_NO_THROW(centralizedConfiguration.Name()); +} + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); From 8c3687752b76256d4b91277dbfbd4c1c5e506f17 Mon Sep 17 00:00:00 2001 From: jr0me Date: Wed, 9 Oct 2024 09:24:57 -0300 Subject: [PATCH 03/18] feat: implement CentralizedConfiguration::Setup It's not necessary to set any configuration at the moment --- src/modules/centralized_configuration/CMakeLists.txt | 1 + .../include/centralized_configuration.hpp | 4 ++++ .../src/centralized_configuration.cpp | 4 ++++ .../tests/centralized_configuration_tests.cpp | 5 +++++ 4 files changed, 14 insertions(+) diff --git a/src/modules/centralized_configuration/CMakeLists.txt b/src/modules/centralized_configuration/CMakeLists.txt index ac3d74d9d7..ee86ac84f3 100644 --- a/src/modules/centralized_configuration/CMakeLists.txt +++ b/src/modules/centralized_configuration/CMakeLists.txt @@ -9,6 +9,7 @@ include_directories(${CMAKE_SOURCE_DIR}/common/logger/include) add_library(CentralizedConfiguration src/centralized_configuration.cpp) target_include_directories(CentralizedConfiguration PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_link_libraries(CentralizedConfiguration PUBLIC ConfigurationParser) include(../../cmake/ConfigureTarget.cmake) configure_target(CentralizedConfiguration) diff --git a/src/modules/centralized_configuration/include/centralized_configuration.hpp b/src/modules/centralized_configuration/include/centralized_configuration.hpp index 391a147b77..1cf628f3bb 100644 --- a/src/modules/centralized_configuration/include/centralized_configuration.hpp +++ b/src/modules/centralized_configuration/include/centralized_configuration.hpp @@ -1,5 +1,8 @@ #pragma once +#include + +#include #include namespace centralized_configuration @@ -8,6 +11,7 @@ namespace centralized_configuration { public: void Start() const; + void Setup(const configuration::ConfigurationParser&) const; void Stop() const; std::string Name() const; }; diff --git a/src/modules/centralized_configuration/src/centralized_configuration.cpp b/src/modules/centralized_configuration/src/centralized_configuration.cpp index d04bab13ab..c9bfc1f34c 100644 --- a/src/modules/centralized_configuration/src/centralized_configuration.cpp +++ b/src/modules/centralized_configuration/src/centralized_configuration.cpp @@ -6,6 +6,10 @@ namespace centralized_configuration { } + void CentralizedConfiguration::Setup(const configuration::ConfigurationParser&) const + { + } + void CentralizedConfiguration::Stop() const { } diff --git a/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp index 84ddd22cb7..d5c92f54f6 100644 --- a/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp +++ b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp @@ -1,6 +1,7 @@ #include #include +#include using centralized_configuration::CentralizedConfiguration; @@ -17,6 +18,10 @@ TEST(CentralizedConfiguration, ImplementsModuleWrapperInterface) EXPECT_NO_THROW(centralizedConfiguration.Start()); EXPECT_NO_THROW(centralizedConfiguration.Stop()); EXPECT_NO_THROW(centralizedConfiguration.Name()); + + const std::string emptyConfig; + configuration::ConfigurationParser configurationParser(emptyConfig); + EXPECT_NO_THROW(centralizedConfiguration.Setup(configurationParser)); } int main(int argc, char** argv) From 0b85dc5e0b1e3ad58319d840121e718304c594e5 Mon Sep 17 00:00:00 2001 From: jr0me Date: Wed, 9 Oct 2024 09:34:25 -0300 Subject: [PATCH 04/18] fix: toml and Logger are public dependencies of ConfigurationParser They are included and used in its public header --- src/agent/configuration_parser/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/agent/configuration_parser/CMakeLists.txt b/src/agent/configuration_parser/CMakeLists.txt index 64925cdee2..4931bfa182 100644 --- a/src/agent/configuration_parser/CMakeLists.txt +++ b/src/agent/configuration_parser/CMakeLists.txt @@ -14,7 +14,7 @@ find_package(toml11 CONFIG REQUIRED) add_library(ConfigurationParser src/configuration_parser.cpp) target_include_directories(ConfigurationParser PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) -target_link_libraries(ConfigurationParser PRIVATE toml11::toml11 Logger) +target_link_libraries(ConfigurationParser PUBLIC toml11::toml11 Logger) include(../../cmake/ConfigureTarget.cmake) configure_target(ConfigurationParser) From 079723baa39e0ee5af10b1dd7fafe465ddd7b267 Mon Sep 17 00:00:00 2001 From: jr0me Date: Wed, 9 Oct 2024 09:52:26 -0300 Subject: [PATCH 05/18] feat: introduce ExecuteCommand in CentralizedConfiguration It's currently a placeholder for the future implementation --- .../centralized_configuration/CMakeLists.txt | 2 +- .../include/centralized_configuration.hpp | 2 ++ .../src/centralized_configuration.cpp | 11 +++++++ .../tests/centralized_configuration_tests.cpp | 32 +++++++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/modules/centralized_configuration/CMakeLists.txt b/src/modules/centralized_configuration/CMakeLists.txt index ee86ac84f3..cecaf1890a 100644 --- a/src/modules/centralized_configuration/CMakeLists.txt +++ b/src/modules/centralized_configuration/CMakeLists.txt @@ -9,7 +9,7 @@ include_directories(${CMAKE_SOURCE_DIR}/common/logger/include) add_library(CentralizedConfiguration src/centralized_configuration.cpp) target_include_directories(CentralizedConfiguration PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) -target_link_libraries(CentralizedConfiguration PUBLIC ConfigurationParser) +target_link_libraries(CentralizedConfiguration PUBLIC ConfigurationParser ModuleManager) include(../../cmake/ConfigureTarget.cmake) configure_target(CentralizedConfiguration) diff --git a/src/modules/centralized_configuration/include/centralized_configuration.hpp b/src/modules/centralized_configuration/include/centralized_configuration.hpp index 1cf628f3bb..c00eb901b4 100644 --- a/src/modules/centralized_configuration/include/centralized_configuration.hpp +++ b/src/modules/centralized_configuration/include/centralized_configuration.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -13,6 +14,7 @@ namespace centralized_configuration void Start() const; void Setup(const configuration::ConfigurationParser&) const; void Stop() const; + Co_CommandExecutionResult ExecuteCommand(std::string command); std::string Name() const; }; } // namespace centralized_configuration diff --git a/src/modules/centralized_configuration/src/centralized_configuration.cpp b/src/modules/centralized_configuration/src/centralized_configuration.cpp index c9bfc1f34c..a7fb0fd052 100644 --- a/src/modules/centralized_configuration/src/centralized_configuration.cpp +++ b/src/modules/centralized_configuration/src/centralized_configuration.cpp @@ -1,5 +1,7 @@ #include +#include + namespace centralized_configuration { void CentralizedConfiguration::Start() const @@ -14,6 +16,15 @@ namespace centralized_configuration { } + // NOLINTNEXTLINE(performance-unnecessary-value-param) + Co_CommandExecutionResult CentralizedConfiguration::ExecuteCommand(const std::string) + { + co_return module_command::CommandExecutionResult{ + module_command::Status::FAILURE, + "Not yet implemented" + }; + } + std::string CentralizedConfiguration::Name() const { return "CentralizedConfiguration"; diff --git a/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp index d5c92f54f6..07aa84b7bc 100644 --- a/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp +++ b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp @@ -3,8 +3,26 @@ #include #include +#include +#include +#include +#include +#include + using centralized_configuration::CentralizedConfiguration; +namespace +{ + // NOLINTNEXTLINE(cppcoreguidelines-avoid-reference-coroutine-parameters) + boost::asio::awaitable TestExecuteCommandUnrecognized(CentralizedConfiguration& centralizedConfiguration) + { + const std::string command = R"({"command": "unknown-command"})"; + const auto commandResult = co_await centralizedConfiguration.ExecuteCommand(command); + + EXPECT_EQ(commandResult.ErrorCode, module_command::Status::FAILURE); + } +} + TEST(CentralizedConfiguration, Constructor) { EXPECT_NO_THROW( @@ -24,6 +42,20 @@ TEST(CentralizedConfiguration, ImplementsModuleWrapperInterface) EXPECT_NO_THROW(centralizedConfiguration.Setup(configurationParser)); } +TEST(CentralizedConfiguration, ExecuteCommandReturnsFailureOnUnrecognizedCommand) +{ + CentralizedConfiguration centralizedConfiguration; + + boost::asio::io_context io_context; + boost::asio::co_spawn( + io_context, + TestExecuteCommandUnrecognized(centralizedConfiguration), + boost::asio::detached + ); + + io_context.run(); +} + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); From c0fdbf2857ccc36a8213e22cd24d4681c66d9079 Mon Sep 17 00:00:00 2001 From: jr0me Date: Wed, 9 Oct 2024 10:19:13 -0300 Subject: [PATCH 06/18] feat: add basic handling of CentralizedConfiguration commands --- .../src/centralized_configuration.cpp | 23 ++++++++++- .../tests/centralized_configuration_tests.cpp | 39 +++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/modules/centralized_configuration/src/centralized_configuration.cpp b/src/modules/centralized_configuration/src/centralized_configuration.cpp index a7fb0fd052..d688e239b4 100644 --- a/src/modules/centralized_configuration/src/centralized_configuration.cpp +++ b/src/modules/centralized_configuration/src/centralized_configuration.cpp @@ -2,6 +2,8 @@ #include +#include + namespace centralized_configuration { void CentralizedConfiguration::Start() const @@ -17,11 +19,28 @@ namespace centralized_configuration } // NOLINTNEXTLINE(performance-unnecessary-value-param) - Co_CommandExecutionResult CentralizedConfiguration::ExecuteCommand(const std::string) + Co_CommandExecutionResult CentralizedConfiguration::ExecuteCommand(const std::string command) { + const auto commnandAsJson = nlohmann::json::parse(command); + + if (commnandAsJson["command"] == "set-group") + { + co_return module_command::CommandExecutionResult{ + module_command::Status::SUCCESS, + "CentralizedConfiguration group set" + }; + } + else if (commnandAsJson["command"] == "update-group") + { + co_return module_command::CommandExecutionResult{ + module_command::Status::SUCCESS, + "CentralizedConfiguration group updated" + }; + } + co_return module_command::CommandExecutionResult{ module_command::Status::FAILURE, - "Not yet implemented" + "CentralizedConfiguration command not recognized" }; } diff --git a/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp index 07aa84b7bc..d04bb9de1d 100644 --- a/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp +++ b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp @@ -13,6 +13,24 @@ using centralized_configuration::CentralizedConfiguration; namespace { + // NOLINTNEXTLINE(cppcoreguidelines-avoid-reference-coroutine-parameters) + boost::asio::awaitable TestExecuteCommandSetGroup(CentralizedConfiguration& centralizedConfiguration) + { + const std::string command = R"({"command": "set-group"})"; + const auto commandResult = co_await centralizedConfiguration.ExecuteCommand(command); + + EXPECT_EQ(commandResult.ErrorCode, module_command::Status::SUCCESS); + } + + // NOLINTNEXTLINE(cppcoreguidelines-avoid-reference-coroutine-parameters) + boost::asio::awaitable TestExecuteCommandUpdateGroup(CentralizedConfiguration& centralizedConfiguration) + { + const std::string command = R"({"command": "update-group"})"; + const auto commandResult = co_await centralizedConfiguration.ExecuteCommand(command); + + EXPECT_EQ(commandResult.ErrorCode, module_command::Status::SUCCESS); + } + // NOLINTNEXTLINE(cppcoreguidelines-avoid-reference-coroutine-parameters) boost::asio::awaitable TestExecuteCommandUnrecognized(CentralizedConfiguration& centralizedConfiguration) { @@ -56,6 +74,27 @@ TEST(CentralizedConfiguration, ExecuteCommandReturnsFailureOnUnrecognizedCommand io_context.run(); } +TEST(CentralizedConfiguration, ExecuteCommandHandlesRecognizedCommands) +{ + CentralizedConfiguration centralizedConfiguration; + + boost::asio::io_context io_context; + + boost::asio::co_spawn( + io_context, + TestExecuteCommandSetGroup(centralizedConfiguration), + boost::asio::detached + ); + + boost::asio::co_spawn( + io_context, + TestExecuteCommandUpdateGroup(centralizedConfiguration), + boost::asio::detached + ); + + io_context.run(); +} + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); From a547707fe069d1e8be24090c494b48508d8bd6d6 Mon Sep 17 00:00:00 2001 From: jr0me Date: Thu, 10 Oct 2024 10:09:39 -0300 Subject: [PATCH 07/18] feat: add SetGroupIdFunction to CentralizedConfiguration This commit adds a new method, SetGroupIdFunction, to the CentralizedConfiguration class. This method allows the user to set a function that takes a vector of integers as input and returns a boolean value. The function is used to set the group ID in the CentralizedConfiguration module. If the function returns true, the group ID is set successfully, otherwise, it returns a failure status. The SetGroupIdFunction method is implemented in the CentralizedConfiguration class and takes a std::function object as input. This function can be used to perform custom logic for setting the group ID. This commit also includes a test case which verifies that the SetGroupIdFunction method is called and returns the correct result. --- .../include/centralized_configuration.hpp | 6 +++ .../src/centralized_configuration.cpp | 27 +++++++++++-- .../tests/centralized_configuration_tests.cpp | 40 +++++++++++++++++++ 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/modules/centralized_configuration/include/centralized_configuration.hpp b/src/modules/centralized_configuration/include/centralized_configuration.hpp index c00eb901b4..3ba70610e1 100644 --- a/src/modules/centralized_configuration/include/centralized_configuration.hpp +++ b/src/modules/centralized_configuration/include/centralized_configuration.hpp @@ -5,6 +5,7 @@ #include #include +#include namespace centralized_configuration { @@ -16,5 +17,10 @@ namespace centralized_configuration void Stop() const; Co_CommandExecutionResult ExecuteCommand(std::string command); std::string Name() const; + + void SetGroupIdFunction(std::function&)> setGroupIdFunction); + + private: + std::function&)> m_setGroupIdFunction; }; } // namespace centralized_configuration diff --git a/src/modules/centralized_configuration/src/centralized_configuration.cpp b/src/modules/centralized_configuration/src/centralized_configuration.cpp index d688e239b4..c7b59a3e5f 100644 --- a/src/modules/centralized_configuration/src/centralized_configuration.cpp +++ b/src/modules/centralized_configuration/src/centralized_configuration.cpp @@ -25,10 +25,24 @@ namespace centralized_configuration if (commnandAsJson["command"] == "set-group") { - co_return module_command::CommandExecutionResult{ - module_command::Status::SUCCESS, - "CentralizedConfiguration group set" - }; + if (m_setGroupIdFunction) + { + std::vector groupIds; + + m_setGroupIdFunction(groupIds); + + co_return module_command::CommandExecutionResult{ + module_command::Status::SUCCESS, + "CentralizedConfiguration group set" + }; + } + else + { + co_return module_command::CommandExecutionResult{ + module_command::Status::FAILURE, + "CentralizedConfiguration group set failed, no function set" + }; + } } else if (commnandAsJson["command"] == "update-group") { @@ -48,4 +62,9 @@ namespace centralized_configuration { return "CentralizedConfiguration"; } + + void CentralizedConfiguration::SetGroupIdFunction(std::function&)> setGroupIdFunction) + { + m_setGroupIdFunction = std::move(setGroupIdFunction); + } } // namespace centralized_configuration diff --git a/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp index d04bb9de1d..2634e2b873 100644 --- a/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp +++ b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp @@ -39,6 +39,18 @@ namespace EXPECT_EQ(commandResult.ErrorCode, module_command::Status::FAILURE); } + + // NOLINTNEXTLINE(cppcoreguidelines-avoid-reference-coroutine-parameters) + boost::asio::awaitable TestSetGroupIdFunction(CentralizedConfiguration& centralizedConfiguration, bool& wasSetGroupIdFunctionCalled) + { + EXPECT_FALSE(wasSetGroupIdFunctionCalled); + + const std::string command = R"({"command": "set-group"})"; + const auto commandResult = co_await centralizedConfiguration.ExecuteCommand(command); + + EXPECT_EQ(commandResult.ErrorCode, module_command::Status::SUCCESS); + EXPECT_TRUE(wasSetGroupIdFunctionCalled); + } } TEST(CentralizedConfiguration, Constructor) @@ -77,6 +89,11 @@ TEST(CentralizedConfiguration, ExecuteCommandReturnsFailureOnUnrecognizedCommand TEST(CentralizedConfiguration, ExecuteCommandHandlesRecognizedCommands) { CentralizedConfiguration centralizedConfiguration; + centralizedConfiguration.SetGroupIdFunction( + [](const std::vector&) + { + } + ); boost::asio::io_context io_context; @@ -95,6 +112,29 @@ TEST(CentralizedConfiguration, ExecuteCommandHandlesRecognizedCommands) io_context.run(); } +TEST(CentralizedConfiguration, SetGroupIdFunctionIsCalledAndReturnsCorrectResult) +{ + CentralizedConfiguration centralizedConfiguration; + bool wasSetGroupIdFunctionCalled = false; + + centralizedConfiguration.SetGroupIdFunction( + [&wasSetGroupIdFunctionCalled](const std::vector&) + { + wasSetGroupIdFunctionCalled = true; + } + ); + + boost::asio::io_context io_context; + + boost::asio::co_spawn( + io_context, + TestSetGroupIdFunction(centralizedConfiguration, wasSetGroupIdFunctionCalled), + boost::asio::detached + ); + + io_context.run(); +} + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); From b28ba088f09252e9cc8b6dd845610033f4f47d5c Mon Sep 17 00:00:00 2001 From: jr0me Date: Thu, 10 Oct 2024 10:32:22 -0300 Subject: [PATCH 08/18] refactor: CentralizedConfiguration tests for better readability and maintainability --- .../tests/centralized_configuration_tests.cpp | 49 +++++++------------ 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp index 2634e2b873..03c29e0cda 100644 --- a/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp +++ b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp @@ -13,44 +13,31 @@ using centralized_configuration::CentralizedConfiguration; namespace { - // NOLINTNEXTLINE(cppcoreguidelines-avoid-reference-coroutine-parameters) - boost::asio::awaitable TestExecuteCommandSetGroup(CentralizedConfiguration& centralizedConfiguration) + // NOLINTBEGIN(cppcoreguidelines-avoid-reference-coroutine-parameters) + boost::asio::awaitable TestExecuteCommand( + CentralizedConfiguration& centralizedConfiguration, + const std::string& command, + module_command::Status expectedErrorCode) { - const std::string command = R"({"command": "set-group"})"; const auto commandResult = co_await centralizedConfiguration.ExecuteCommand(command); - - EXPECT_EQ(commandResult.ErrorCode, module_command::Status::SUCCESS); - } - - // NOLINTNEXTLINE(cppcoreguidelines-avoid-reference-coroutine-parameters) - boost::asio::awaitable TestExecuteCommandUpdateGroup(CentralizedConfiguration& centralizedConfiguration) - { - const std::string command = R"({"command": "update-group"})"; - const auto commandResult = co_await centralizedConfiguration.ExecuteCommand(command); - - EXPECT_EQ(commandResult.ErrorCode, module_command::Status::SUCCESS); + EXPECT_EQ(commandResult.ErrorCode, expectedErrorCode); } - // NOLINTNEXTLINE(cppcoreguidelines-avoid-reference-coroutine-parameters) - boost::asio::awaitable TestExecuteCommandUnrecognized(CentralizedConfiguration& centralizedConfiguration) - { - const std::string command = R"({"command": "unknown-command"})"; - const auto commandResult = co_await centralizedConfiguration.ExecuteCommand(command); - - EXPECT_EQ(commandResult.ErrorCode, module_command::Status::FAILURE); - } - - // NOLINTNEXTLINE(cppcoreguidelines-avoid-reference-coroutine-parameters) - boost::asio::awaitable TestSetGroupIdFunction(CentralizedConfiguration& centralizedConfiguration, bool& wasSetGroupIdFunctionCalled) + boost::asio::awaitable TestSetGroupIdFunction( + CentralizedConfiguration& centralizedConfiguration, + bool& wasSetGroupIdFunctionCalled) { EXPECT_FALSE(wasSetGroupIdFunctionCalled); - const std::string command = R"({"command": "set-group"})"; - const auto commandResult = co_await centralizedConfiguration.ExecuteCommand(command); + co_await TestExecuteCommand( + centralizedConfiguration, + R"({"command": "set-group"})", + module_command::Status::SUCCESS + ); - EXPECT_EQ(commandResult.ErrorCode, module_command::Status::SUCCESS); EXPECT_TRUE(wasSetGroupIdFunctionCalled); } + // NOLINTEND(cppcoreguidelines-avoid-reference-coroutine-parameters) } TEST(CentralizedConfiguration, Constructor) @@ -79,7 +66,7 @@ TEST(CentralizedConfiguration, ExecuteCommandReturnsFailureOnUnrecognizedCommand boost::asio::io_context io_context; boost::asio::co_spawn( io_context, - TestExecuteCommandUnrecognized(centralizedConfiguration), + TestExecuteCommand(centralizedConfiguration, R"({"command": "unknown-command"})", module_command::Status::FAILURE), boost::asio::detached ); @@ -99,13 +86,13 @@ TEST(CentralizedConfiguration, ExecuteCommandHandlesRecognizedCommands) boost::asio::co_spawn( io_context, - TestExecuteCommandSetGroup(centralizedConfiguration), + TestExecuteCommand(centralizedConfiguration, R"({"command": "set-group"})", module_command::Status::SUCCESS), boost::asio::detached ); boost::asio::co_spawn( io_context, - TestExecuteCommandUpdateGroup(centralizedConfiguration), + TestExecuteCommand(centralizedConfiguration, R"({"command": "update-group"})", module_command::Status::SUCCESS), boost::asio::detached ); From c0fd320460f0d9d182a7c441934270a44ab05c47 Mon Sep 17 00:00:00 2001 From: jr0me Date: Mon, 14 Oct 2024 11:28:24 -0300 Subject: [PATCH 09/18] feat: test failure when SetGroupIdFunction is not set --- .../tests/centralized_configuration_tests.cpp | 55 ++++++++++--------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp index 03c29e0cda..4a3e3bfcbb 100644 --- a/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp +++ b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp @@ -22,21 +22,6 @@ namespace const auto commandResult = co_await centralizedConfiguration.ExecuteCommand(command); EXPECT_EQ(commandResult.ErrorCode, expectedErrorCode); } - - boost::asio::awaitable TestSetGroupIdFunction( - CentralizedConfiguration& centralizedConfiguration, - bool& wasSetGroupIdFunctionCalled) - { - EXPECT_FALSE(wasSetGroupIdFunctionCalled); - - co_await TestExecuteCommand( - centralizedConfiguration, - R"({"command": "set-group"})", - module_command::Status::SUCCESS - ); - - EXPECT_TRUE(wasSetGroupIdFunctionCalled); - } // NOLINTEND(cppcoreguidelines-avoid-reference-coroutine-parameters) } @@ -101,21 +86,39 @@ TEST(CentralizedConfiguration, ExecuteCommandHandlesRecognizedCommands) TEST(CentralizedConfiguration, SetGroupIdFunctionIsCalledAndReturnsCorrectResult) { - CentralizedConfiguration centralizedConfiguration; - bool wasSetGroupIdFunctionCalled = false; - - centralizedConfiguration.SetGroupIdFunction( - [&wasSetGroupIdFunctionCalled](const std::vector&) - { - wasSetGroupIdFunctionCalled = true; - } - ); - boost::asio::io_context io_context; boost::asio::co_spawn( io_context, - TestSetGroupIdFunction(centralizedConfiguration, wasSetGroupIdFunctionCalled), + [] () -> boost::asio::awaitable + { + CentralizedConfiguration centralizedConfiguration; + + co_await TestExecuteCommand( + centralizedConfiguration, + R"({"command": "set-group"})", + module_command::Status::FAILURE + ); + + bool wasSetGroupIdFunctionCalled = false; + + centralizedConfiguration.SetGroupIdFunction( + [&wasSetGroupIdFunctionCalled](const std::vector&) + { + wasSetGroupIdFunctionCalled = true; + } + ); + + EXPECT_FALSE(wasSetGroupIdFunctionCalled); + + co_await TestExecuteCommand( + centralizedConfiguration, + R"({"command": "set-group"})", + module_command::Status::SUCCESS + ); + + EXPECT_TRUE(wasSetGroupIdFunctionCalled); + }(), boost::asio::detached ); From 964a82d280997ff49bc1af63b85838520c3af5e7 Mon Sep 17 00:00:00 2001 From: jr0me Date: Mon, 14 Oct 2024 17:56:16 -0300 Subject: [PATCH 10/18] feat: catch json parsing errors --- .../src/centralized_configuration.cpp | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/src/modules/centralized_configuration/src/centralized_configuration.cpp b/src/modules/centralized_configuration/src/centralized_configuration.cpp index c7b59a3e5f..3e8363a44a 100644 --- a/src/modules/centralized_configuration/src/centralized_configuration.cpp +++ b/src/modules/centralized_configuration/src/centralized_configuration.cpp @@ -21,34 +21,44 @@ namespace centralized_configuration // NOLINTNEXTLINE(performance-unnecessary-value-param) Co_CommandExecutionResult CentralizedConfiguration::ExecuteCommand(const std::string command) { - const auto commnandAsJson = nlohmann::json::parse(command); - - if (commnandAsJson["command"] == "set-group") + try { - if (m_setGroupIdFunction) + const auto commnandAsJson = nlohmann::json::parse(command); + + if (commnandAsJson["command"] == "set-group") { - std::vector groupIds; + if (m_setGroupIdFunction) + { + std::vector groupIds; - m_setGroupIdFunction(groupIds); + m_setGroupIdFunction(groupIds); - co_return module_command::CommandExecutionResult{ - module_command::Status::SUCCESS, - "CentralizedConfiguration group set" - }; + co_return module_command::CommandExecutionResult{ + module_command::Status::SUCCESS, + "CentralizedConfiguration group set" + }; + } + else + { + co_return module_command::CommandExecutionResult{ + module_command::Status::FAILURE, + "CentralizedConfiguration group set failed, no function set" + }; + } } - else + else if (commnandAsJson["command"] == "update-group") { co_return module_command::CommandExecutionResult{ - module_command::Status::FAILURE, - "CentralizedConfiguration group set failed, no function set" + module_command::Status::SUCCESS, + "CentralizedConfiguration group updated" }; } } - else if (commnandAsJson["command"] == "update-group") + catch (const nlohmann::json::exception&) { co_return module_command::CommandExecutionResult{ - module_command::Status::SUCCESS, - "CentralizedConfiguration group updated" + module_command::Status::FAILURE, + "CentralizedConfiguration error while parsing command" }; } From 7ff5e348477f5a59e8b8b365bc556cdbea1cc69e Mon Sep 17 00:00:00 2001 From: jr0me Date: Tue, 15 Oct 2024 10:59:21 -0300 Subject: [PATCH 11/18] feat: add function setter to configure how to download group configuration files --- .../include/centralized_configuration.hpp | 3 +++ .../src/centralized_configuration.cpp | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/src/modules/centralized_configuration/include/centralized_configuration.hpp b/src/modules/centralized_configuration/include/centralized_configuration.hpp index 3ba70610e1..537a7cf5c7 100644 --- a/src/modules/centralized_configuration/include/centralized_configuration.hpp +++ b/src/modules/centralized_configuration/include/centralized_configuration.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -19,8 +20,10 @@ namespace centralized_configuration std::string Name() const; void SetGroupIdFunction(std::function&)> setGroupIdFunction); + void SetDownloadGroupFilesFunction(std::function downloadGroupFilesFunction); private: std::function&)> m_setGroupIdFunction; + std::function m_downloadGroupFilesFunction; }; } // namespace centralized_configuration diff --git a/src/modules/centralized_configuration/src/centralized_configuration.cpp b/src/modules/centralized_configuration/src/centralized_configuration.cpp index 3e8363a44a..7d80eeb7c9 100644 --- a/src/modules/centralized_configuration/src/centralized_configuration.cpp +++ b/src/modules/centralized_configuration/src/centralized_configuration.cpp @@ -77,4 +77,9 @@ namespace centralized_configuration { m_setGroupIdFunction = std::move(setGroupIdFunction); } + + void CentralizedConfiguration::SetDownloadGroupFilesFunction(std::function downloadGroupFilesFunction) + { + m_downloadGroupFilesFunction = std::move(downloadGroupFilesFunction); + } } // namespace centralized_configuration From 1e903e43fc48c51b6b396e4d175f395e4fc2621d Mon Sep 17 00:00:00 2001 From: jr0me Date: Thu, 17 Oct 2024 18:56:19 -0300 Subject: [PATCH 12/18] refactor: use type alias to improve readability --- .../include/centralized_configuration.hpp | 11 +++++++---- .../src/centralized_configuration.cpp | 4 ++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/modules/centralized_configuration/include/centralized_configuration.hpp b/src/modules/centralized_configuration/include/centralized_configuration.hpp index 537a7cf5c7..b20fab000c 100644 --- a/src/modules/centralized_configuration/include/centralized_configuration.hpp +++ b/src/modules/centralized_configuration/include/centralized_configuration.hpp @@ -13,17 +13,20 @@ namespace centralized_configuration class CentralizedConfiguration { public: + using SetGroupIdFunctionType = std::function&)>; + using DownloadGroupFilesFunctionType = std::function; + void Start() const; void Setup(const configuration::ConfigurationParser&) const; void Stop() const; Co_CommandExecutionResult ExecuteCommand(std::string command); std::string Name() const; - void SetGroupIdFunction(std::function&)> setGroupIdFunction); - void SetDownloadGroupFilesFunction(std::function downloadGroupFilesFunction); + void SetGroupIdFunction(SetGroupIdFunctionType setGroupIdFunction); + void SetDownloadGroupFilesFunction(DownloadGroupFilesFunctionType downloadGroupFilesFunction); private: - std::function&)> m_setGroupIdFunction; - std::function m_downloadGroupFilesFunction; + SetGroupIdFunctionType m_setGroupIdFunction; + DownloadGroupFilesFunctionType m_downloadGroupFilesFunction; }; } // namespace centralized_configuration diff --git a/src/modules/centralized_configuration/src/centralized_configuration.cpp b/src/modules/centralized_configuration/src/centralized_configuration.cpp index 7d80eeb7c9..19bb973842 100644 --- a/src/modules/centralized_configuration/src/centralized_configuration.cpp +++ b/src/modules/centralized_configuration/src/centralized_configuration.cpp @@ -73,12 +73,12 @@ namespace centralized_configuration return "CentralizedConfiguration"; } - void CentralizedConfiguration::SetGroupIdFunction(std::function&)> setGroupIdFunction) + void CentralizedConfiguration::SetGroupIdFunction(SetGroupIdFunctionType setGroupIdFunction) { m_setGroupIdFunction = std::move(setGroupIdFunction); } - void CentralizedConfiguration::SetDownloadGroupFilesFunction(std::function downloadGroupFilesFunction) + void CentralizedConfiguration::SetDownloadGroupFilesFunction(DownloadGroupFilesFunctionType downloadGroupFilesFunction) { m_downloadGroupFilesFunction = std::move(downloadGroupFilesFunction); } From 021499b17462e5ea7ec549488510c279c69fd8d6 Mon Sep 17 00:00:00 2001 From: jr0me Date: Thu, 17 Oct 2024 18:57:28 -0300 Subject: [PATCH 13/18] feat: use download group config files and udpate tests --- .../src/centralized_configuration.cpp | 16 +++- .../tests/centralized_configuration_tests.cpp | 75 ++++++++++++++----- 2 files changed, 70 insertions(+), 21 deletions(-) diff --git a/src/modules/centralized_configuration/src/centralized_configuration.cpp b/src/modules/centralized_configuration/src/centralized_configuration.cpp index 19bb973842..add32ae92a 100644 --- a/src/modules/centralized_configuration/src/centralized_configuration.cpp +++ b/src/modules/centralized_configuration/src/centralized_configuration.cpp @@ -4,6 +4,8 @@ #include +#include + namespace centralized_configuration { void CentralizedConfiguration::Start() const @@ -27,12 +29,22 @@ namespace centralized_configuration if (commnandAsJson["command"] == "set-group") { - if (m_setGroupIdFunction) + if (m_setGroupIdFunction && m_downloadGroupFilesFunction) { - std::vector groupIds; + const auto groupIds = commnandAsJson["groups"].get>(); m_setGroupIdFunction(groupIds); + for (const auto& groupId : groupIds) + { + m_downloadGroupFilesFunction( + groupId, + std::filesystem::temp_directory_path().string() + ); + } + + // TODO validate groupFiles, apply configuration + co_return module_command::CommandExecutionResult{ module_command::Status::SUCCESS, "CentralizedConfiguration group set" diff --git a/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp index 4a3e3bfcbb..ad1f195ee8 100644 --- a/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp +++ b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp @@ -46,12 +46,19 @@ TEST(CentralizedConfiguration, ImplementsModuleWrapperInterface) TEST(CentralizedConfiguration, ExecuteCommandReturnsFailureOnUnrecognizedCommand) { - CentralizedConfiguration centralizedConfiguration; - boost::asio::io_context io_context; + boost::asio::co_spawn( io_context, - TestExecuteCommand(centralizedConfiguration, R"({"command": "unknown-command"})", module_command::Status::FAILURE), + [] () -> boost::asio::awaitable + { + CentralizedConfiguration centralizedConfiguration; + co_await TestExecuteCommand( + centralizedConfiguration, + R"({"command": "unknown-command"})", + module_command::Status::FAILURE + ); + }(), boost::asio::detached ); @@ -60,31 +67,50 @@ TEST(CentralizedConfiguration, ExecuteCommandReturnsFailureOnUnrecognizedCommand TEST(CentralizedConfiguration, ExecuteCommandHandlesRecognizedCommands) { - CentralizedConfiguration centralizedConfiguration; - centralizedConfiguration.SetGroupIdFunction( - [](const std::vector&) - { - } - ); - boost::asio::io_context io_context; boost::asio::co_spawn( io_context, - TestExecuteCommand(centralizedConfiguration, R"({"command": "set-group"})", module_command::Status::SUCCESS), - boost::asio::detached - ); + [] () -> boost::asio::awaitable + { + CentralizedConfiguration centralizedConfiguration; + centralizedConfiguration.SetGroupIdFunction( + [](const std::vector&) + { + } + ); + centralizedConfiguration.SetDownloadGroupFilesFunction( + [](const std::string&, const std::string&) + { + return true; + } + ); - boost::asio::co_spawn( - io_context, - TestExecuteCommand(centralizedConfiguration, R"({"command": "update-group"})", module_command::Status::SUCCESS), + co_await TestExecuteCommand( + centralizedConfiguration, + R"({"command": "set-group", "groups": ["group1", "group2"]})", + module_command::Status::SUCCESS + ); + + co_await TestExecuteCommand( + centralizedConfiguration, + R"({"command": "update-group"})", + module_command::Status::SUCCESS + ); + + co_await TestExecuteCommand( + centralizedConfiguration, + R"({"command": "unknown-command"})", + module_command::Status::FAILURE + ); + }(), boost::asio::detached ); io_context.run(); } -TEST(CentralizedConfiguration, SetGroupIdFunctionIsCalledAndReturnsCorrectResult) +TEST(CentralizedConfiguration, SetFunctionsAreCalledAndReturnsCorrectResults) { boost::asio::io_context io_context; @@ -96,11 +122,12 @@ TEST(CentralizedConfiguration, SetGroupIdFunctionIsCalledAndReturnsCorrectResult co_await TestExecuteCommand( centralizedConfiguration, - R"({"command": "set-group"})", + R"({"command": "set-group", "groups": ["group1", "group2"]})", module_command::Status::FAILURE ); bool wasSetGroupIdFunctionCalled = false; + bool wasDownloadGroupFilesFunctionCalled = false; centralizedConfiguration.SetGroupIdFunction( [&wasSetGroupIdFunctionCalled](const std::vector&) @@ -109,15 +136,25 @@ TEST(CentralizedConfiguration, SetGroupIdFunctionIsCalledAndReturnsCorrectResult } ); + centralizedConfiguration.SetDownloadGroupFilesFunction( + [&wasDownloadGroupFilesFunctionCalled](const std::string&, const std::string&) + { + wasDownloadGroupFilesFunctionCalled = true; + return wasDownloadGroupFilesFunctionCalled; + } + ); + EXPECT_FALSE(wasSetGroupIdFunctionCalled); + EXPECT_FALSE(wasDownloadGroupFilesFunctionCalled); co_await TestExecuteCommand( centralizedConfiguration, - R"({"command": "set-group"})", + R"({"command": "set-group", "groups": ["group1", "group2"]})", module_command::Status::SUCCESS ); EXPECT_TRUE(wasSetGroupIdFunctionCalled); + EXPECT_TRUE(wasDownloadGroupFilesFunctionCalled); }(), boost::asio::detached ); From c87707e281176b39c87ae84b36a7ba9bf71620f8 Mon Sep 17 00:00:00 2001 From: jr0me Date: Tue, 15 Oct 2024 18:13:48 -0300 Subject: [PATCH 14/18] feat: GetGroupIdFunction and update tests This function is used for the update-group command, which will fetch the groups the agent belongs to, download their configuration files, and apply them. --- .../include/centralized_configuration.hpp | 3 + .../src/centralized_configuration.cpp | 35 +++++++++-- .../tests/centralized_configuration_tests.cpp | 61 ++++++++++++++++++- 3 files changed, 94 insertions(+), 5 deletions(-) diff --git a/src/modules/centralized_configuration/include/centralized_configuration.hpp b/src/modules/centralized_configuration/include/centralized_configuration.hpp index b20fab000c..0687f0d2be 100644 --- a/src/modules/centralized_configuration/include/centralized_configuration.hpp +++ b/src/modules/centralized_configuration/include/centralized_configuration.hpp @@ -14,6 +14,7 @@ namespace centralized_configuration { public: using SetGroupIdFunctionType = std::function&)>; + using GetGroupIdFunctionType = std::function()>; using DownloadGroupFilesFunctionType = std::function; void Start() const; @@ -23,10 +24,12 @@ namespace centralized_configuration std::string Name() const; void SetGroupIdFunction(SetGroupIdFunctionType setGroupIdFunction); + void GetGroupIdFunction(GetGroupIdFunctionType getGroupIdFunction); void SetDownloadGroupFilesFunction(DownloadGroupFilesFunctionType downloadGroupFilesFunction); private: SetGroupIdFunctionType m_setGroupIdFunction; + GetGroupIdFunctionType m_getGroupIdFunction; DownloadGroupFilesFunctionType m_downloadGroupFilesFunction; }; } // namespace centralized_configuration diff --git a/src/modules/centralized_configuration/src/centralized_configuration.cpp b/src/modules/centralized_configuration/src/centralized_configuration.cpp index add32ae92a..a41e04c973 100644 --- a/src/modules/centralized_configuration/src/centralized_configuration.cpp +++ b/src/modules/centralized_configuration/src/centralized_configuration.cpp @@ -60,10 +60,32 @@ namespace centralized_configuration } else if (commnandAsJson["command"] == "update-group") { - co_return module_command::CommandExecutionResult{ - module_command::Status::SUCCESS, - "CentralizedConfiguration group updated" - }; + if (m_getGroupIdFunction && m_downloadGroupFilesFunction) + { + const auto groupIds = m_getGroupIdFunction(); + + for (const auto& groupId : groupIds) + { + m_downloadGroupFilesFunction( + groupId, + std::filesystem::temp_directory_path().string() + ); + } + + // TODO validate groupFiles, apply configuration + + co_return module_command::CommandExecutionResult{ + module_command::Status::SUCCESS, + "CentralizedConfiguration group updated" + }; + } + else + { + co_return module_command::CommandExecutionResult{ + module_command::Status::FAILURE, + "CentralizedConfiguration group set failed, no function set" + }; + } } } catch (const nlohmann::json::exception&) @@ -90,6 +112,11 @@ namespace centralized_configuration m_setGroupIdFunction = std::move(setGroupIdFunction); } + void CentralizedConfiguration::GetGroupIdFunction(GetGroupIdFunctionType getGroupIdFunction) + { + m_getGroupIdFunction = std::move(getGroupIdFunction); + } + void CentralizedConfiguration::SetDownloadGroupFilesFunction(DownloadGroupFilesFunctionType downloadGroupFilesFunction) { m_downloadGroupFilesFunction = std::move(downloadGroupFilesFunction); diff --git a/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp index ad1f195ee8..56dfdaad8d 100644 --- a/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp +++ b/src/modules/centralized_configuration/tests/centralized_configuration_tests.cpp @@ -79,6 +79,12 @@ TEST(CentralizedConfiguration, ExecuteCommandHandlesRecognizedCommands) { } ); + centralizedConfiguration.GetGroupIdFunction( + []() + { + return std::vector{"group1", "group2"}; + } + ); centralizedConfiguration.SetDownloadGroupFilesFunction( [](const std::string&, const std::string&) { @@ -110,7 +116,7 @@ TEST(CentralizedConfiguration, ExecuteCommandHandlesRecognizedCommands) io_context.run(); } -TEST(CentralizedConfiguration, SetFunctionsAreCalledAndReturnsCorrectResults) +TEST(CentralizedConfiguration, SetFunctionsAreCalledAndReturnsCorrectResultsForSetGroup) { boost::asio::io_context io_context; @@ -162,6 +168,59 @@ TEST(CentralizedConfiguration, SetFunctionsAreCalledAndReturnsCorrectResults) io_context.run(); } +TEST(CentralizedConfiguration, SetFunctionsAreCalledAndReturnsCorrectResultsForUpdateGroup) +{ + boost::asio::io_context io_context; + + boost::asio::co_spawn( + io_context, + [] () -> boost::asio::awaitable + { + CentralizedConfiguration centralizedConfiguration; + + co_await TestExecuteCommand( + centralizedConfiguration, + R"({"command": "update-group"})", + module_command::Status::FAILURE + ); + + bool wasGetGroupIdFunctionCalled = false; + bool wasDownloadGroupFilesFunctionCalled = false; + + centralizedConfiguration.GetGroupIdFunction( + [&wasGetGroupIdFunctionCalled]() + { + wasGetGroupIdFunctionCalled = true; + return std::vector{"group1", "group2"}; + } + ); + + centralizedConfiguration.SetDownloadGroupFilesFunction( + [&wasDownloadGroupFilesFunctionCalled](const std::string&, const std::string&) + { + wasDownloadGroupFilesFunctionCalled = true; + return wasDownloadGroupFilesFunctionCalled; + } + ); + + EXPECT_FALSE(wasGetGroupIdFunctionCalled); + EXPECT_FALSE(wasDownloadGroupFilesFunctionCalled); + + co_await TestExecuteCommand( + centralizedConfiguration, + R"({"command": "update-group"})", + module_command::Status::SUCCESS + ); + + EXPECT_TRUE(wasGetGroupIdFunctionCalled); + EXPECT_TRUE(wasDownloadGroupFilesFunctionCalled); + }(), + boost::asio::detached + ); + + io_context.run(); +} + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); From c4d0b6b96a7843edff0b4fe616f1d1cb783ae9ea Mon Sep 17 00:00:00 2001 From: jr0me Date: Wed, 16 Oct 2024 09:18:29 -0300 Subject: [PATCH 15/18] feat: add SetMessageQueue method to CentralizedConfiguration The ModuleManager imposes this requirement, although it doesn't need it. --- src/modules/centralized_configuration/CMakeLists.txt | 2 +- .../include/centralized_configuration.hpp | 2 ++ .../src/centralized_configuration.cpp | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/modules/centralized_configuration/CMakeLists.txt b/src/modules/centralized_configuration/CMakeLists.txt index cecaf1890a..67446ac014 100644 --- a/src/modules/centralized_configuration/CMakeLists.txt +++ b/src/modules/centralized_configuration/CMakeLists.txt @@ -9,7 +9,7 @@ include_directories(${CMAKE_SOURCE_DIR}/common/logger/include) add_library(CentralizedConfiguration src/centralized_configuration.cpp) target_include_directories(CentralizedConfiguration PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) -target_link_libraries(CentralizedConfiguration PUBLIC ConfigurationParser ModuleManager) +target_link_libraries(CentralizedConfiguration PUBLIC ConfigurationParser ModuleManager MultiTypeQueue) include(../../cmake/ConfigureTarget.cmake) configure_target(CentralizedConfiguration) diff --git a/src/modules/centralized_configuration/include/centralized_configuration.hpp b/src/modules/centralized_configuration/include/centralized_configuration.hpp index 0687f0d2be..d523ed85ac 100644 --- a/src/modules/centralized_configuration/include/centralized_configuration.hpp +++ b/src/modules/centralized_configuration/include/centralized_configuration.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -22,6 +23,7 @@ namespace centralized_configuration void Stop() const; Co_CommandExecutionResult ExecuteCommand(std::string command); std::string Name() const; + void SetMessageQueue(const std::shared_ptr); void SetGroupIdFunction(SetGroupIdFunctionType setGroupIdFunction); void GetGroupIdFunction(GetGroupIdFunctionType getGroupIdFunction); diff --git a/src/modules/centralized_configuration/src/centralized_configuration.cpp b/src/modules/centralized_configuration/src/centralized_configuration.cpp index a41e04c973..cc97fdfce6 100644 --- a/src/modules/centralized_configuration/src/centralized_configuration.cpp +++ b/src/modules/centralized_configuration/src/centralized_configuration.cpp @@ -107,6 +107,10 @@ namespace centralized_configuration return "CentralizedConfiguration"; } + void CentralizedConfiguration::SetMessageQueue(const std::shared_ptr) + { + } + void CentralizedConfiguration::SetGroupIdFunction(SetGroupIdFunctionType setGroupIdFunction) { m_setGroupIdFunction = std::move(setGroupIdFunction); From e6d4b4901f060079d9fbecdda3e26bef87aa9a6f Mon Sep 17 00:00:00 2001 From: jr0me Date: Wed, 16 Oct 2024 09:20:09 -0300 Subject: [PATCH 16/18] feat: add CentralizedConfiguration module to ModuleManager --- src/agent/CMakeLists.txt | 17 ++++++++++++++++- src/agent/include/agent.hpp | 2 ++ src/agent/src/agent.cpp | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/agent/CMakeLists.txt b/src/agent/CMakeLists.txt index 657e960495..2a6d2fa426 100644 --- a/src/agent/CMakeLists.txt +++ b/src/agent/CMakeLists.txt @@ -49,7 +49,22 @@ list(APPEND SOURCES add_library(Agent ${SOURCES}) target_include_directories(Agent PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) -target_link_libraries(Agent PUBLIC ConfigurationParser Communicator AgentInfo CommandHandler MultiTypeQueue ModuleManager ModuleCommand PRIVATE OpenSSL::SSL OpenSSL::Crypto Boost::asio Boost::beast) +target_link_libraries(Agent + PUBLIC + ConfigurationParser + Communicator + AgentInfo + CommandHandler + MultiTypeQueue + ModuleManager + ModuleCommand + CentralizedConfiguration + PRIVATE + OpenSSL::SSL + OpenSSL::Crypto + Boost::asio + Boost::beast +) include(../cmake/ConfigureTarget.cmake) configure_target(Agent) diff --git a/src/agent/include/agent.hpp b/src/agent/include/agent.hpp index fab41be87a..eb08e6791b 100644 --- a/src/agent/include/agent.hpp +++ b/src/agent/include/agent.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -32,4 +33,5 @@ class Agent communicator::Communicator m_communicator; command_handler::CommandHandler m_commandHandler; ModuleManager m_moduleManager; + centralized_configuration::CentralizedConfiguration m_centralizedConfiguration; }; diff --git a/src/agent/src/agent.cpp b/src/agent/src/agent.cpp index c1ef43d5c9..042b1551e9 100644 --- a/src/agent/src/agent.cpp +++ b/src/agent/src/agent.cpp @@ -55,6 +55,7 @@ void Agent::Run() { return DispatchCommand(cmd, m_moduleManager.GetModule(cmd.Module), m_messageQueue); })); m_moduleManager.AddModule(Inventory::Instance()); + m_moduleManager.AddModule(m_centralizedConfiguration); m_moduleManager.Setup(); m_taskManager.EnqueueTask([this]() { m_moduleManager.Start(); }); From 9e3bc2029c2bae459d553ba8f09b589fe817fd7e Mon Sep 17 00:00:00 2001 From: jr0me Date: Thu, 17 Oct 2024 19:10:37 -0300 Subject: [PATCH 17/18] feat: set CentralizedConfiguration functions to set and get groups and download configuration files for them --- src/agent/src/agent.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/agent/src/agent.cpp b/src/agent/src/agent.cpp index 042b1551e9..77bd000d4e 100644 --- a/src/agent/src/agent.cpp +++ b/src/agent/src/agent.cpp @@ -23,6 +23,15 @@ Agent::Agent(const std::string& configPath, std::unique_ptr sign { return m_configurationParser.GetConfig(std::move(table), std::move(key)); }) , m_moduleManager(m_messageQueue, m_configurationParser) { + m_centralizedConfiguration.SetGroupIdFunction([this](const std::vector& groups) + { return m_agentInfo.SetGroups(groups); }); + + m_centralizedConfiguration.GetGroupIdFunction([this]() { return m_agentInfo.GetGroups(); }); + + m_centralizedConfiguration.SetDownloadGroupFilesFunction( + [this](const std::string& groupId, const std::string& destinationPath) + { return m_communicator.GetGroupConfigurationFromManager(groupId, destinationPath); }); + m_taskManager.Start(std::thread::hardware_concurrency()); } From 32dc10f1c7f97fd95f37d90ea08c39e626696404 Mon Sep 17 00:00:00 2001 From: jr0me Date: Fri, 18 Oct 2024 12:41:35 -0300 Subject: [PATCH 18/18] feat: add documentation to the CentralizedConfiguration --- .../include/centralized_configuration.hpp | 63 ++++++++++++++++++- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/src/modules/centralized_configuration/include/centralized_configuration.hpp b/src/modules/centralized_configuration/include/centralized_configuration.hpp index d523ed85ac..78631159fb 100644 --- a/src/modules/centralized_configuration/include/centralized_configuration.hpp +++ b/src/modules/centralized_configuration/include/centralized_configuration.hpp @@ -14,19 +14,76 @@ namespace centralized_configuration class CentralizedConfiguration { public: - using SetGroupIdFunctionType = std::function&)>; + using SetGroupIdFunctionType = std::function& groupList)>; using GetGroupIdFunctionType = std::function()>; - using DownloadGroupFilesFunctionType = std::function; + using DownloadGroupFilesFunctionType = std::function; + /** + * @brief Starts the centralized configuration process. + * @details This is a no-op function, required by the ModuleWrapper interface + * to be used within the ModuleManager. + */ void Start() const; + + /** + * @brief Configures the centralized configuration system. + * @param configParser The configuration parser containing settings to be applied. + * @details This is a no-op function, required by the ModuleWrapper interface + * to be used within the ModuleManager. + */ void Setup(const configuration::ConfigurationParser&) const; + + /** + * @brief Stops the centralized configuration process. + * @details This is a no-op function, required by the ModuleWrapper interface + * to be used within the ModuleManager. + */ void Stop() const; + + /** + * @brief Executes a command for the centralized configuration system. + * @param command A string containing a JSON command to execute. + * @details Required by the ModuleWrapper interface to be used within the ModuleManager + * @return Co_CommandExecutionResult The result of executing the command, either success or failure. + */ Co_CommandExecutionResult ExecuteCommand(std::string command); + + /** + * @brief Gets the name of the centralized configuration system. + * @details Required by the ModuleWrapper interface to be used within the ModuleManager + * @return A string representing the name. + */ std::string Name() const; - void SetMessageQueue(const std::shared_ptr); + /** + * @brief Sets the message queue for the system. + * @param queue A shared pointer to the message queue used for communication. + * @details This is a no-op function, required by the ModuleWrapper interface + * to be used within the ModuleManager. + */ + void SetMessageQueue(const std::shared_ptr queue); + + /** + * @brief Sets the function to assign group IDs. + * @details The "set-group" commands requires such function to be set. + * @param setGroupIdFunction A function to set group IDs. + */ void SetGroupIdFunction(SetGroupIdFunctionType setGroupIdFunction); + + /** + * @brief Sets the function to retrieve group IDs. + * @details The "update-group" commands requires such function to be set. + * @param getGroupIdFunction A function to get group IDs. + */ void GetGroupIdFunction(GetGroupIdFunctionType getGroupIdFunction); + + /** + * @brief Sets the function to download group configuration files. + * @details Configures how and where to download group configuration files. + * These will be used to set and update the Agent groups via the "set-group" and "update-group" + * commands. + * @param downloadGroupFilesFunction A function to download files for a given group ID. + */ void SetDownloadGroupFilesFunction(DownloadGroupFilesFunctionType downloadGroupFilesFunction); private: