Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Let the agent's CLI key option be optional #252

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/agent/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ add_subdirectory(command_store)

find_package(OpenSSL REQUIRED)
find_package(Boost REQUIRED COMPONENTS asio beast)
find_package(fmt REQUIRED)


if(WIN32)
Expand Down Expand Up @@ -66,6 +67,7 @@ target_link_libraries(Agent
OpenSSL::Crypto
Boost::asio
Boost::beast
fmt::fmt
)

include(../cmake/ConfigureTarget.cmake)
Expand Down
45 changes: 43 additions & 2 deletions src/agent/agent_info/include/agent_info.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,64 @@
#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,
/// 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();
AgentInfo(std::string name, std::string key, std::string uuid);

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

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

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

/// @brief Gets the agent's groups.
/// @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);
void SetKey(const std::string& key);

/// @brief Sets the agent's key.
/// @param key The agent's new key.
/// @return True if the key was successfully set, false otherwise.
bool SetKey(const std::string& key);

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

/// @brief Sets the agent's groups.
/// @param groupList A vector of the agent's new groups.
void SetGroups(const std::vector<std::string>& groupList);

private:
/// @brief Creates a random key for the agent.
///
/// The key is 32 alphanumeric characters.
///
/// @return A randomly generated key.
std::string CreateKey();
TomasTurina marked this conversation as resolved.
Show resolved Hide resolved

/// @brief Validates a given key.
/// @param key The key to validate.
/// @return True if the key is valid (32 alphanumeric characters), false
/// otherwise.
bool ValidateKey(const std::string& key);

std::string m_name;
std::string m_key;
std::string m_uuid;
Expand Down
60 changes: 46 additions & 14 deletions src/agent/agent_info/src/agent_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <random>
#include <utility>

namespace
{
constexpr size_t KEY_LENGTH = 32;
}

AgentInfo::AgentInfo()
{
AgentInfoPersistance agentInfoPersistance;
Expand All @@ -22,17 +28,6 @@ AgentInfo::AgentInfo()
}
}

AgentInfo::AgentInfo(std::string name, std::string key, std::string uuid)
: m_name(std::move(name))
, m_key(std::move(key))
, m_uuid(std::move(uuid))
{
AgentInfoPersistance agentInfoPersistance;
agentInfoPersistance.SetName(m_name);
agentInfoPersistance.SetKey(m_key);
agentInfoPersistance.SetUUID(m_uuid);
}

std::string AgentInfo::GetName() const
{
return m_name;
Expand Down Expand Up @@ -60,11 +55,26 @@ void AgentInfo::SetName(const std::string& name)
m_name = name;
}

void AgentInfo::SetKey(const std::string& key)
bool AgentInfo::SetKey(const std::string& key)
{
AgentInfoPersistance agentInfoPersistance;
agentInfoPersistance.SetKey(key);
m_key = key;

if (!key.empty())
{
if (!ValidateKey(key))
{
return false;
}
m_key = key;
}
else
{
m_key = CreateKey();
}

agentInfoPersistance.SetKey(m_key);

return true;
}

void AgentInfo::SetUUID(const std::string& uuid)
Expand All @@ -80,3 +90,25 @@ void AgentInfo::SetGroups(const std::vector<std::string>& groupList)
agentInfoPersistance.SetGroups(groupList);
m_groups = groupList;
}

std::string AgentInfo::CreateKey()
{
constexpr std::string_view charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

std::random_device rd;
std::mt19937 generator(rd());
std::uniform_int_distribution<size_t> distribution(0, charset.size() - 1);

std::string key;
for (size_t i = 0; i < KEY_LENGTH; ++i)
{
key += charset[distribution(generator)];
}

return key;
}

bool AgentInfo::ValidateKey(const std::string& key)
{
return key.length() == KEY_LENGTH && std::ranges::all_of(key, ::isalnum);
}
43 changes: 28 additions & 15 deletions src/agent/agent_info/tests/agent_info_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,15 @@ TEST_F(AgentInfoTest, TestDefaultConstructorDefaultValues)
EXPECT_NE(agentInfo.GetUUID(), "");
}

TEST_F(AgentInfoTest, TestParameterizedConstructor)
{
const std::string name = "new_name";
const std::string key = "new_key";
const std::string uuid = "new_uuid";

const AgentInfo agentInfo(name, key, uuid);
EXPECT_EQ(agentInfo.GetName(), name);
EXPECT_EQ(agentInfo.GetKey(), key);
EXPECT_EQ(agentInfo.GetUUID(), uuid);
}

TEST_F(AgentInfoTest, TestPersistedValues)
{
const AgentInfo agentInfo("test_name", "test_key", "test_uuid");
AgentInfo agentInfo;
agentInfo.SetName("test_name");
agentInfo.SetKey("4GhT7uFm1zQa9c2Vb7Lk8pYsX0WqZrNj");
agentInfo.SetUUID("test_uuid");
const AgentInfo agentInfoReloaded;
EXPECT_EQ(agentInfoReloaded.GetName(), "test_name");
EXPECT_EQ(agentInfoReloaded.GetKey(), "test_key");
EXPECT_EQ(agentInfoReloaded.GetKey(), "4GhT7uFm1zQa9c2Vb7Lk8pYsX0WqZrNj");
EXPECT_EQ(agentInfoReloaded.GetUUID(), "test_uuid");
}

Expand All @@ -63,7 +54,7 @@ TEST_F(AgentInfoTest, TestSetName)
TEST_F(AgentInfoTest, TestSetKey)
{
AgentInfo agentInfo;
const std::string newKey = "new_key";
const std::string newKey = "4GhT7uFm1zQa9c2Vb7Lk8pYsX0WqZrNj";

agentInfo.SetKey(newKey);
EXPECT_EQ(agentInfo.GetKey(), newKey);
Expand All @@ -72,6 +63,28 @@ TEST_F(AgentInfoTest, TestSetKey)
EXPECT_EQ(agentInfoReloaded.GetKey(), newKey);
}

TEST_F(AgentInfoTest, TestSetBadKey)
{
AgentInfo agentInfo;
const std::string newKey1 = "4GhT7uFm";
const std::string newKey2 = "4GhT7uFm1zQa9c2Vb7Lk8pYsX0WqZrN=";

ASSERT_FALSE(agentInfo.SetKey(newKey1));
ASSERT_FALSE(agentInfo.SetKey(newKey2));
}

TEST_F(AgentInfoTest, TestSetEmptyKey)
{
AgentInfo agentInfo;
const std::string newKey;

agentInfo.SetKey(newKey);
EXPECT_NE(agentInfo.GetKey(), newKey);

const AgentInfo agentInfoReloaded;
EXPECT_NE(agentInfoReloaded.GetKey(), newKey);
}

TEST_F(AgentInfoTest, TestSetUUID)
{
AgentInfo agentInfo;
Expand Down
18 changes: 18 additions & 0 deletions src/agent/include/agent_registration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,38 @@

namespace agent_registration
{
/// @struct UserCredentials
/// @brief Stores the user's credentials.
struct UserCredentials
{
std::string user;
std::string password;
};

/// @brief Registers an agent with a manager.
///
/// This class provides methods for registering the agent and storing its
/// configuration.
class AgentRegistration
{
public:
///@brief Constructor for the AgentRegistration class.
///
/// @param user The user's username.
/// @param password The user's password.
/// @param key The agent's key.
/// @param name The agent's name.
/// @param configFile The path to the configuration file.
AgentRegistration(std::string user,
std::string password,
const std::string& key,
const std::string& name,
std::optional<std::string> configFile);

/// @brief Registers the agent with the manager.
///
/// @param httpClient The HTTP client to use for registration.
/// @return True if the registration was successful, false otherwise.
bool Register(http_client::IHttpClient& httpClient);

private:
Expand Down
21 changes: 10 additions & 11 deletions src/agent/src/agent_registration.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#include <agent_registration.hpp>

#include <logger.hpp>

#include <boost/beast/http.hpp>
#include <iostream>
#include <nlohmann/json.hpp>

namespace http = boost::beast::http;
Expand All @@ -21,7 +20,11 @@ namespace agent_registration
, m_user(std::move(user))
, m_password(std::move(password))
{
m_agentInfo.SetKey(key);
if (!m_agentInfo.SetKey(key))
{
throw std::invalid_argument("--key argument must be alphanumeric and 32 characters in length");
}

if (!name.empty())
{
m_agentInfo.SetName(name);
Expand All @@ -38,16 +41,12 @@ namespace agent_registration

if (!token.has_value())
{
LogError("Failed to authenticate with the manager");
std::cout << "Failed to authenticate with the manager\n";
return false;
}

nlohmann::json bodyJson = {{"id", m_agentInfo.GetUUID()}, {"key", m_agentInfo.GetKey()}};

if (!m_agentInfo.GetName().empty())
{
bodyJson["name"] = m_agentInfo.GetName();
}
nlohmann::json bodyJson = {
{"id", m_agentInfo.GetUUID()}, {"key", m_agentInfo.GetKey()}, {"name", m_agentInfo.GetName()}};

const auto reqParams = http_client::HttpRequestParams(
http::verb::post, m_serverUrl, "/agents", token.value(), "", bodyJson.dump());
Expand All @@ -56,7 +55,7 @@ namespace agent_registration

if (res.result() != http::status::ok)
{
LogError("Registration error: {}.", res.result_int());
std::cout << "Registration error: " << res.result_int() << ".\n";
return false;
}

Expand Down
28 changes: 18 additions & 10 deletions src/agent/src/process_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

#include <agent.hpp>
#include <agent_registration.hpp>
#include <fmt/format.h>

#include <iostream>
#include <string>
Expand All @@ -13,22 +12,31 @@ void RegisterAgent(const std::string& user,
const std::string& name,
const std::string& configFile)
{
if (!user.empty() && !password.empty() && !key.empty())
if (!user.empty() && !password.empty())
{
agent_registration::AgentRegistration reg(user, password, key, name, configFile);

http_client::HttpClient httpClient;
if (reg.Register(httpClient))
try
{
std::cout << "wazuh-agent registered\n";
std::cout << "Starting wazuh-agent registration\n";

agent_registration::AgentRegistration reg(user, password, key, name, configFile);

http_client::HttpClient httpClient;
if (reg.Register(httpClient))
{
std::cout << "wazuh-agent registered\n";
}
else
{
std::cout << "wazuh-agent registration failed\n";
}
}
else
catch (const std::exception& e)
{
std::cout << "wazuh-agent registration failed\n";
std::cerr << "Error: " << e.what() << '\n';
}
}
else
{
std::cout << fmt::format("{}, {}, and {} args are mandatory\n", OPT_USER, OPT_PASSWORD, OPT_KEY);
std::cout << OPT_USER << " and " << OPT_PASSWORD << " args are mandatory\n";
}
}
Loading
Loading