-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #386 from wazuh/enhancement/77-add-support-agent-s…
…elf-restarting Add support for agent self-restarting on Linux
- Loading branch information
Showing
15 changed files
with
278 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
cmake_minimum_required(VERSION 3.22) | ||
|
||
project(RestartHandler) | ||
|
||
include(../../cmake/CommonSettings.cmake) | ||
set_common_settings() | ||
|
||
find_package(Boost REQUIRED COMPONENTS asio) | ||
|
||
if(WIN32) | ||
set(SOURCES src/restart_handler_win.cpp) | ||
else() | ||
set(SOURCES src/restart_handler_unix.cpp) | ||
endif() | ||
|
||
add_library(RestartHandler ${SOURCES}) | ||
target_include_directories(RestartHandler PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) | ||
target_link_libraries(RestartHandler PUBLIC Boost::asio CommandEntry PRIVATE Logger) | ||
|
||
include(../../cmake/ConfigureTarget.cmake) | ||
configure_target(RestartHandler) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
#pragma once | ||
|
||
#include <command_entry.hpp> | ||
|
||
#include <boost/asio/awaitable.hpp> | ||
|
||
#include <vector> | ||
|
||
namespace restart_handler | ||
{ | ||
/// @brief Class for handling service restarts. | ||
class RestartHandler | ||
{ | ||
public: | ||
/// @brief A list of command line arguments used to restart the agent process. | ||
static std::vector<char*> startupCmdLineArgs; | ||
|
||
/// @brief RestartHandler class. | ||
explicit RestartHandler(); | ||
|
||
/// @brief Stores the command-line arguments passed to the agent. | ||
/// @param argc Number of arguments. | ||
/// @param argv Array of arguments. | ||
static void SetCommandLineArguments(int argc, char* argv[]) | ||
{ | ||
for (int i = 0; i < argc; ++i) | ||
{ | ||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) | ||
RestartHandler::startupCmdLineArgs.emplace_back(argv[i]); | ||
} | ||
// Add a nullptr to terminate the argument list, as required by execve. | ||
RestartHandler::startupCmdLineArgs.emplace_back(nullptr); | ||
} | ||
|
||
/// @brief Executes the restart command. | ||
/// @return Result of the restart command execution. | ||
static boost::asio::awaitable<module_command::CommandExecutionResult> RestartCommand(); | ||
}; | ||
} // namespace restart_handler |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
#include "restart_handler_unix.hpp" | ||
#include <fstream> | ||
#include <logger.hpp> | ||
|
||
#include <chrono> | ||
#include <thread> | ||
|
||
namespace restart_handler | ||
{ | ||
|
||
std::vector<char*> RestartHandler::startupCmdLineArgs; | ||
|
||
bool UsingSystemctl() | ||
{ | ||
return (0 == std::system("which systemctl > /dev/null 2>&1") && nullptr != std::getenv("INVOCATION_ID")); | ||
} | ||
|
||
boost::asio::awaitable<module_command::CommandExecutionResult> RestartWithSystemd() | ||
{ | ||
LogInfo("Systemctl restarting wazuh agent service."); | ||
if (std::system("systemctl restart wazuh-agent") != 0) | ||
{ | ||
co_return module_command::CommandExecutionResult {module_command::Status::IN_PROGRESS, | ||
"Systemctl restart execution"}; | ||
} | ||
else | ||
{ | ||
LogError("Failed using systemctl."); | ||
co_return module_command::CommandExecutionResult {module_command::Status::FAILURE, | ||
"Systemctl restart failed"}; | ||
} | ||
} | ||
|
||
void StopAgent() | ||
{ | ||
const int timeoutInSecs = 30; | ||
const time_t startTime = time(nullptr); | ||
|
||
pid_t pid = getppid(); | ||
|
||
// Shutdown Gracefully | ||
kill(pid, SIGTERM); | ||
|
||
while (true) | ||
{ | ||
if (kill(pid, 0) != 0) | ||
{ | ||
LogInfo("Agent gracefully stopped."); | ||
break; | ||
} | ||
|
||
if (difftime(time(nullptr), startTime) > timeoutInSecs) | ||
{ | ||
LogError("Timeout reached! Forcing agent process termination."); | ||
kill(pid, SIGKILL); | ||
} | ||
|
||
std::this_thread::sleep_for(std::chrono::seconds(1)); | ||
} | ||
} | ||
|
||
boost::asio::awaitable<module_command::CommandExecutionResult> RestartWithFork() | ||
{ | ||
pid_t pid = fork(); | ||
|
||
if (pid < 0) | ||
{ | ||
LogError("Fork failed."); | ||
} | ||
else if (pid == 0) | ||
{ | ||
// Child process | ||
StopAgent(); | ||
|
||
LogInfo("Starting wazuh agent in a new process."); | ||
|
||
if (execve(RestartHandler::startupCmdLineArgs[0], RestartHandler::startupCmdLineArgs.data(), nullptr) == -1) | ||
{ | ||
LogError("Failed to spawn new Wazuh agent process."); | ||
} | ||
} | ||
|
||
co_return module_command::CommandExecutionResult {module_command::Status::IN_PROGRESS, | ||
"Pending restart execution"}; | ||
} | ||
|
||
boost::asio::awaitable<module_command::CommandExecutionResult> RestartHandler::RestartCommand() | ||
{ | ||
|
||
if (UsingSystemctl()) | ||
{ | ||
return RestartWithSystemd(); | ||
} | ||
else | ||
{ | ||
return RestartWithFork(); | ||
} | ||
} | ||
|
||
} // namespace restart_handler |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
#pragma once | ||
#include <boost/asio/awaitable.hpp> | ||
#include <command_entry.hpp> | ||
#include <restart_handler.hpp> | ||
#include <vector> | ||
|
||
namespace restart_handler | ||
{ | ||
|
||
/// @brief Checks if systemctl is available and running as a systemd service. | ||
/// | ||
/// Determines if systemctl can be used in the current environment. | ||
/// @return true if systemctl is available and running as a systemd service, otherwise returns false. | ||
bool UsingSystemctl(); | ||
|
||
/// @brief Stops the agent by terminating the child process. | ||
/// | ||
/// This function sends a SIGTERM signal to the agent process to stop it. If the agent process | ||
/// does not stop within a specified timeout period (30 seconds), it forces termination with a SIGKILL signal. | ||
void StopAgent(); | ||
|
||
/// @brief Restarts the module by forking a new process. | ||
/// | ||
/// This function restarts the module by creating a new child process. | ||
/// | ||
/// @return A boost::asio::awaitable containing the result of the command execution. | ||
boost::asio::awaitable<module_command::CommandExecutionResult> RestartWithFork(); | ||
|
||
/// @brief Restarts the module using systemd service management. | ||
/// | ||
/// This function restarts the module via systemd, ensuring the module is properly restarted using | ||
/// system service management mechanisms. | ||
/// | ||
/// @return A boost::asio::awaitable containing the result of the command execution. | ||
boost::asio::awaitable<module_command::CommandExecutionResult> RestartWithSystemd(); | ||
|
||
} // namespace restart_handler |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#include <boost/asio/awaitable.hpp> | ||
#include <logger.hpp> | ||
#include <restart_handler.hpp> | ||
|
||
namespace restart_handler | ||
{ | ||
|
||
std::vector<char*> RestartHandler::startupCmdLineArgs; | ||
|
||
boost::asio::awaitable<module_command::CommandExecutionResult> RestartHandler::RestartCommand() | ||
{ | ||
// TODO | ||
co_return module_command::CommandExecutionResult {module_command::Status::FAILURE, | ||
"RestartHandler is not implemented yet"}; | ||
} | ||
|
||
} // namespace restart_handler |
Oops, something went wrong.