Skip to content

Commit

Permalink
Merge pull request #277 from wazuh/feat/256-add-agent-information
Browse files Browse the repository at this point in the history
Adds agent information in requests to the server
  • Loading branch information
TomasTurina authored Nov 8, 2024
2 parents 6657451 + 5ca60e6 commit 4fb8806
Show file tree
Hide file tree
Showing 180 changed files with 1,291 additions and 455 deletions.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ if(ENABLE_LOGCOLLECTOR OR ENABLE_INVENTORY)
else()
add_subdirectory(common/logger)
add_subdirectory(common/utils)
add_subdirectory(common/data_provider)
endif()
add_subdirectory(modules)
add_subdirectory(agent)
Expand Down
5 changes: 4 additions & 1 deletion src/agent/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ list(APPEND SOURCES
)

add_library(Agent ${SOURCES})
target_include_directories(Agent PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_include_directories(Agent
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_link_libraries(Agent
PUBLIC
CentralizedConfiguration
Expand All @@ -62,6 +64,7 @@ target_link_libraries(Agent
ModuleCommand
CentralizedConfiguration
Boost::asio
sysinfo
PRIVATE
OpenSSL::SSL
OpenSSL::Crypto
Expand Down
7 changes: 5 additions & 2 deletions src/agent/agent_info/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ include(../../cmake/CommonSettings.cmake)
set_common_settings()

find_package(Boost REQUIRED COMPONENTS uuid)
find_package(nlohmann_json CONFIG REQUIRED)

add_library(AgentInfo src/agent_info.cpp src/agent_info_persistance.cpp)
target_include_directories(AgentInfo PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_link_libraries(AgentInfo PRIVATE SQLiteManager Boost::uuid Logger)
target_include_directories(AgentInfo PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src)
target_link_libraries(AgentInfo PUBLIC nlohmann_json::nlohmann_json PRIVATE SQLiteManager Boost::uuid Logger)

if(MSVC)
target_link_libraries(AgentInfo PRIVATE bcrypt)
Expand Down
77 changes: 65 additions & 12 deletions src/agent/agent_info/include/agent_info.hpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
#pragma once

#include <nlohmann/json.hpp>

#include <functional>
#include <string>
#include <vector>

/// @brief Stores and manages information about an agent.
///
/// This class provides methods for getting and setting the agent's name, key,
/// This class provides methods for getting and setting the agent's key,
/// UUID, and groups. It also includes private methods for creating and
/// validating the key.
class AgentInfo
{
public:
/// @brief Default constructor for the AgentInfo class.
AgentInfo();

/// @brief Gets the agent's name.
/// @return The agent's name.
std::string GetName() const;
/// @brief Constructs an AgentInfo object with OS and network information retrieval functions.
///
/// This constructor initializes the AgentInfo object by setting up OS and network
/// information retrieval functions. It also generates a UUID for the agent if one
/// does not already exist, and loads endpoint, metadata, and header information.
///
/// @param getOSInfo Function to retrieve OS information in JSON format.
/// @param getNetworksInfo Function to retrieve network information in JSON format.
AgentInfo(std::function<nlohmann::json()> getOSInfo = nullptr,
std::function<nlohmann::json()> getNetworksInfo = nullptr);

/// @brief Gets the agent's key.
/// @return The agent's key.
Expand All @@ -30,10 +37,6 @@ class AgentInfo
/// @return A vector of the agent's groups.
std::vector<std::string> GetGroups() const;

/// @brief Sets the agent's name.
/// @param name The agent's new name.
void SetName(const std::string& name);

/// @brief Sets the agent's key.
/// @param key The agent's new key.
/// @return True if the key was successfully set, false otherwise.
Expand All @@ -47,6 +50,23 @@ class AgentInfo
/// @param groupList A vector of the agent's new groups.
void SetGroups(const std::vector<std::string>& groupList);

/// @brief Gets the agent's type.
/// @return The agent's type.
std::string GetType() const;

/// @brief Gets the agent's version.
/// @return The agent's version.
std::string GetVersion() const;

/// @brief Gets the agent information for the request header.
/// @return A string with the information for the request header.
std::string GetHeaderInfo() const;

/// @brief Gets all the information about the agent.
/// @param agentIsRegistering Indicates if the agent is about to register.
/// @return A json object with all information about the agent.
nlohmann::json GetMetadataInfo(const bool agentIsRegistering) const;

private:
/// @brief Creates a random key for the agent.
///
Expand All @@ -61,8 +81,41 @@ class AgentInfo
/// otherwise.
bool ValidateKey(const std::string& key) const;

std::string m_name;
/// @brief Loads the endpoint information into `m_endpointInfo`.
void LoadEndpointInfo();

/// @brief Loads the metadata information into `m_metadataInfo`.
void LoadMetadataInfo();

/// @brief Loads the header information into `m_headerInfo`.
void LoadHeaderInfo();

/// @brief Extracts the active IP address from the network JSON data.
/// @param networksJson JSON object containing network interface information.
/// @return Optional string with the active IP address if found; otherwise, `std::nullopt`.
std::optional<std::string> GetActiveIPAddress(const nlohmann::json& networksJson) const;

/// @brief The agent's key.
std::string m_key;

/// @brief The agent's UUID.
std::string m_uuid;

/// @brief The agent's groups.
std::vector<std::string> m_groups;

/// @brief The agent's endpoint information.
nlohmann::json m_endpointInfo;

/// @brief The agent's metadata information.
nlohmann::json m_metadataInfo;

/// @brief The agent's header information.
std::string m_headerInfo;

/// @brief The OS information
std::function<nlohmann::json()> m_getOSInfo;

/// @brief The networks information
std::function<nlohmann::json()> m_getNetworksInfo;
};
137 changes: 123 additions & 14 deletions src/agent/agent_info/src/agent_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
namespace
{
constexpr size_t KEY_LENGTH = 32;
}
const std::string AGENT_TYPE = "Endpoint";
const std::string AGENT_VERSION = "5.0.0";
const std::string PRODUCT_NAME = "WazuhXDR";
} // namespace

AgentInfo::AgentInfo()
AgentInfo::AgentInfo(std::function<nlohmann::json()> getOSInfo, std::function<nlohmann::json()> getNetworksInfo)
{
AgentInfoPersistance agentInfoPersistance;
m_name = agentInfoPersistance.GetName();
m_key = agentInfoPersistance.GetKey();
m_uuid = agentInfoPersistance.GetUUID();
m_groups = agentInfoPersistance.GetGroups();
Expand All @@ -26,11 +28,20 @@ AgentInfo::AgentInfo()
m_uuid = boost::uuids::to_string(boost::uuids::random_generator()());
agentInfoPersistance.SetUUID(m_uuid);
}
}

std::string AgentInfo::GetName() const
{
return m_name;
if (getOSInfo != nullptr)
{
m_getOSInfo = std::move(getOSInfo);
}

if (getNetworksInfo != nullptr)
{
m_getNetworksInfo = std::move(getNetworksInfo);
}

LoadEndpointInfo();
LoadMetadataInfo();
LoadHeaderInfo();
}

std::string AgentInfo::GetKey() const
Expand All @@ -48,13 +59,6 @@ std::vector<std::string> AgentInfo::GetGroups() const
return m_groups;
}

void AgentInfo::SetName(const std::string& name)
{
AgentInfoPersistance agentInfoPersistance;
agentInfoPersistance.SetName(name);
m_name = name;
}

bool AgentInfo::SetKey(const std::string& key)
{
AgentInfoPersistance agentInfoPersistance;
Expand Down Expand Up @@ -112,3 +116,108 @@ bool AgentInfo::ValidateKey(const std::string& key) const
{
return key.length() == KEY_LENGTH && std::ranges::all_of(key, ::isalnum);
}

std::string AgentInfo::GetType() const
{
return AGENT_TYPE;
}

std::string AgentInfo::GetVersion() const
{
return AGENT_VERSION;
}

std::string AgentInfo::GetHeaderInfo() const
{
return m_headerInfo;
}

nlohmann::json AgentInfo::GetMetadataInfo(const bool agentIsRegistering) const
{
nlohmann::json metadataInfo;

metadataInfo["agent"] = m_metadataInfo;

if (agentIsRegistering)
{
metadataInfo["agent"]["key"] = GetKey();
}

return metadataInfo;
}

std::optional<std::string> AgentInfo::GetActiveIPAddress(const nlohmann::json& networksJson) const
{
if (networksJson.contains("iface"))
{
for (const auto& iface : networksJson["iface"])
{
if (iface.contains("state") && iface["state"] == "up")
{
if (iface.contains("IPv4") && !iface["IPv4"].empty())
{
return iface["IPv4"][0].value("address", "");
}
}
}
}
return std::nullopt;
}

void AgentInfo::LoadEndpointInfo()
{
if (m_getOSInfo != nullptr)
{
nlohmann::json osInfo = m_getOSInfo();
m_endpointInfo["hostname"] = osInfo.value("hostname", "Unknown");
m_endpointInfo["os"] = osInfo.value("os_name", "Unknown");
m_endpointInfo["platform"] = osInfo.value("sysname", "Unknown");
m_endpointInfo["architecture"] = osInfo.value("architecture", "Unknown");
}

if (m_getNetworksInfo != nullptr)
{
nlohmann::json networksInfo = m_getNetworksInfo();
auto ipAddress = GetActiveIPAddress(networksInfo);
m_endpointInfo["ip"] = ipAddress.value_or("Unknown");
}
}

void AgentInfo::LoadMetadataInfo()
{
m_metadataInfo["id"] = GetUUID();
m_metadataInfo["type"] = GetType();
m_metadataInfo["version"] = GetVersion();
m_metadataInfo["groups"] = GetGroups();

if (!m_endpointInfo.empty())
{
nlohmann::json host;
nlohmann::json os;

host["hostname"] = m_endpointInfo.value("hostname", "Unknown");
host["ip"] = m_endpointInfo.value("ip", "Unknown");
host["architecture"] = m_endpointInfo.value("architecture", "Unknown");

os["name"] = m_endpointInfo.value("os", "Unknown");
os["platform"] = m_endpointInfo.value("platform", "Unknown");

host["os"] = os;

m_metadataInfo["host"] = host;
}
}

void AgentInfo::LoadHeaderInfo()
{
if (!m_endpointInfo.empty())
{
m_headerInfo = PRODUCT_NAME + "/" + GetVersion() + " (" + GetType() + "; " +
m_endpointInfo.value("architecture", "Unknown") + "; " +
m_endpointInfo.value("platform", "Unknown") + ")";
}
else
{
m_headerInfo = PRODUCT_NAME + "/" + GetVersion() + " (" + GetType() + "; Unknown; Unknown)";
}
}
16 changes: 2 additions & 14 deletions src/agent/agent_info/src/agent_info_persistance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ void AgentInfoPersistance::CreateAgentInfoTable()
{
try
{
const std::vector<Column> columns = {Column("name", ColumnType::TEXT, true, false),
Column("key", ColumnType::TEXT, true, false),
const std::vector<Column> columns = {Column("key", ColumnType::TEXT, true, false),
Column("uuid", ColumnType::TEXT, true, false, true)};

m_db->CreateTable(AGENT_INFO_TABLE_NAME, columns);
Expand Down Expand Up @@ -93,8 +92,7 @@ void AgentInfoPersistance::InsertDefaultAgentInfo()

if (count == 0)
{
const std::vector<Column> columns = {Column("name", ColumnType::TEXT, ""),
Column("key", ColumnType::TEXT, ""),
const std::vector<Column> columns = {Column("key", ColumnType::TEXT, ""),
Column("uuid", ColumnType::TEXT, "")};

m_db->Insert(AGENT_INFO_TABLE_NAME, columns);
Expand Down Expand Up @@ -141,11 +139,6 @@ std::string AgentInfoPersistance::GetAgentInfoValue(const std::string& column) c
return value;
}

std::string AgentInfoPersistance::GetName() const
{
return GetAgentInfoValue("name");
}

std::string AgentInfoPersistance::GetKey() const
{
return GetAgentInfoValue("key");
Expand Down Expand Up @@ -181,11 +174,6 @@ std::vector<std::string> AgentInfoPersistance::GetGroups() const
return groupList;
}

void AgentInfoPersistance::SetName(const std::string& name)
{
SetAgentInfoValue("name", name);
}

void AgentInfoPersistance::SetKey(const std::string& key)
{
SetAgentInfoValue("key", key);
Expand Down
Loading

0 comments on commit 4fb8806

Please sign in to comment.