Skip to content

Commit

Permalink
feat: convert GenerateStatelessEvent to a class
Browse files Browse the repository at this point in the history
  • Loading branch information
cborla committed Jan 16, 2025
1 parent fb7a810 commit 8763302
Show file tree
Hide file tree
Showing 7 changed files with 264 additions and 157 deletions.
3 changes: 2 additions & 1 deletion src/modules/inventory/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ find_package(Boost REQUIRED COMPONENTS asio beast)
add_library(Inventory
src/inventory.cpp
src/inventoryImp.cpp
src/inventoryNormalizer.cpp)
src/inventoryNormalizer.cpp
src/statelessEvent.cpp)

if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
target_compile_options(Inventory PRIVATE /WX-)
Expand Down
159 changes: 3 additions & 156 deletions src/modules/inventory/src/inventoryImp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,11 @@
#include <hashHelper.h>
#include <timeHelper.h>
#include "commonDefs.h"
#include "statelessEvent.hpp"

constexpr std::time_t INVENTORY_DEFAULT_INTERVAL { 3600000 };
constexpr size_t MAX_ID_SIZE = 512;

constexpr int BYTES_IN_KILOBYTE = 1024;
constexpr int KILOBYTES_IN_MEGABYTE = 1024;
constexpr int BYTES_IN_MEGABYTE = BYTES_IN_KILOBYTE * KILOBYTES_IN_MEGABYTE;

constexpr auto QUEUE_SIZE
{
4096
Expand Down Expand Up @@ -1298,156 +1295,6 @@ nlohmann::json Inventory::AddPreviousFields(nlohmann::json& current, const nlohm
}

nlohmann::json Inventory::GenerateStatelessEvent(const std::string& operation, const std::string& type, const nlohmann::json& data) {
nlohmann::json event;
std::string action, reason;
std::string created = m_scanTime;

if (type == "packages") {
std::string packageName = data["package"]["name"];
std::string version = data["package"]["version"];

if (operation == "create") {
action = "package-installed";
reason = "Package " + packageName + " (version " + version + ") was installed";
} else if (operation == "update") {
reason = "Package " + packageName + " updated";
action = "package-updated";
} else if (operation == "remove") {
action = "package-removed";
reason = "Package " + packageName + " (version " + version + ") was removed";
}

event["event"] = {
{"action", action},
{"category", {"package"}},
{"type", {operation == "create" ? "installation" : operation == "update" ? "change" : "deletion"}},
{"created", created},
{"reason", reason}
};
} else if (type == "ports") {
int srcPort = data["source"]["port"];
int destPort = data["destination"]["port"];

if (operation == "create") {
action = "port-detected";
reason = "New connection established from source port " + std::to_string(srcPort) + " to destination port " + std::to_string(destPort);
} else if (operation == "update") {
action = "port-updated";
reason = "Change for the connection from source port " + std::to_string(srcPort) + " to destination port " + std::to_string(destPort);
} else if (operation == "remove") {
action = "port-closed";
reason = "Connection from source port " + std::to_string(srcPort) + " to destination port " + std::to_string(destPort) + " was closed";
}

event["event"] = {
{"action", action},
{"category", {"network"}},
{"type", {operation == "create" ? "connection" : operation == "update" ? "change" : "end"}},
{"created", created},
{"reason", reason}
};
} else if (type == "hardware") {
std::string cpuName = data["host"]["cpu"]["name"];
int memoryTotalGB = data["host"]["memory"]["total"].get<int>() / BYTES_IN_MEGABYTE;
std::string serialNumber = data["observer"]["serial_number"];

if (operation == "create") {
action = "hardware-detected";
reason = "New hardware detected: " + cpuName + " with " + std::to_string(memoryTotalGB) + " GB memory";
} else if (operation == "update") {
action = "hardware-updated";
reason = "Hardware changed";
} else if (operation == "remove") {
action = "hardware-removed";
reason = "Hardware with serial number " + serialNumber + " was removed";
}

event["event"] = {
{"action", action},
{"category", {"host"}},
{"type", {operation == "create" ? "info" : operation == "update" ? "change" : "deletion"}},
{"created", created},
{"reason", reason}
};
} else if (type == "networks") {
std::string interface = data["observer"]["ingress"]["interface"]["name"];

if (operation == "create") {
action = "network-interface-detected";
reason = "New network interface " + interface + " detected";
} else if (operation == "update") {
action = "network-interface-updated";
reason = "Network interface " + interface + "updated";
} else if (operation == "remove") {
action = "network-interface-removed";
reason = "Network interface " + interface + " was removed";
}

event["event"] = {
{"action", action},
{"category", {"network"}},
{"type", {operation == "create" ? "info" : operation == "update" ? "change" : "deletion"}},
{"created", created},
{"reason", reason}
};
} else if (type == "processes") {
std::string processName = data["process"]["name"];
std::string pid = data["process"]["pid"];

if (operation == "create") {
action = "process-started";
reason = "Process " + processName + " (PID: " + pid + ") was started";
} else if (operation == "update") {
action = "process-updated";
reason = "Process " + processName + " (PID: " + pid + ") was updated";
} else if (operation == "remove") {
action = "process-stopped";
reason = "Process " + processName + " (PID: " + pid + ") was stopped";
}

event["event"] = {
{"action", action},
{"category", {"process"}},
{"type", {operation == "create" ? "start" : operation == "update" ? "change" : "end"}},
{"created", created},
{"reason", reason}
};
} else if (type == "system") {
std::string hostname = data["host"]["hostname"];
std::string osVersion = data["host"]["os"]["version"];

action = (operation == "update") ? "system-updated" : "system-detected";
reason = "System " + hostname + " is running OS version " + osVersion;

event["event"] = {
{"action", action},
{"category", {"host"}},
{"type", {operation == "update" ? "change" : "info"}},
{"created", created},
{"reason", reason}
};
} else if (type == "hotfixes") {
std::string hotfixID = data["package"]["hotfix"]["name"];

if (operation == "create") {
action = "hotfix-installed";
reason = "Hotfix " + hotfixID + " was installed";
} else if (operation == "update") {
action = "hotfix-updated";
reason = "Hotfix " + hotfixID + " was updated";
} else if (operation == "remove") {
action = "hotfix-removed";
reason = "Hotfix " + hotfixID + " was removed";
}

event["event"] = {
{"action", action},
{"category", {"hotfix"}},
{"type", {operation == "create" ? "installation" : "deletion"}},
{"created", created},
{"reason", reason}
};
}

return event;
auto event = CreateEvent(type, operation, m_scanTime, data);
return event ? event->generate() : nlohmann::json{};
}
142 changes: 142 additions & 0 deletions src/modules/inventory/src/statelessEvent.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#include "statelessEvent.hpp"

constexpr int BYTES_IN_KILOBYTE = 1024;
constexpr int KILOBYTES_IN_MEGABYTE = 1024;
constexpr int BYTES_IN_MEGABYTE = BYTES_IN_KILOBYTE * KILOBYTES_IN_MEGABYTE;

StatelessEvent::StatelessEvent(std::string op, std::string time, nlohmann::json d)
: operation(std::move(op)), created(std::move(time)), data(std::move(d)) {}

nlohmann::json NetworkEvent::generate() const {
std::string interface = data["observer"]["ingress"]["interface"]["name"];
std::string action, reason;

if (operation == "create") {
action = "network-interface-detected";
reason = "New network interface " + interface + " detected";
} else if (operation == "update") {
action = "network-interface-updated";
reason = "Network interface " + interface + " updated";
} else {
action = "network-interface-removed";
reason = "Network interface " + interface + " was removed";
}

return {{"event", {{"action", action}, {"category", {"network"}}, {"type", {operation == "create" ? "info" : operation == "update" ? "change" : "deletion"}}, {"created", created}, {"reason", reason}}}};
}

nlohmann::json PackageEvent::generate() const {
std::string packageName = data["package"]["name"];
std::string version = data["package"]["version"];
std::string action, reason;

if (operation == "create") {
action = "package-installed";
reason = "Package " + packageName + " (version " + version + ") was installed";
} else if (operation == "update") {
action = "package-updated";
reason = "Package " + packageName + " updated";
} else {
action = "package-removed";
reason = "Package " + packageName + " (version " + version + ") was removed";
}

return {{"event", {{"action", action}, {"category", {"package"}}, {"type", {operation == "create" ? "installation" : operation == "update" ? "change" : "deletion"}}, {"created", created}, {"reason", reason}}}};
}

nlohmann::json HotfixEvent::generate() const {
std::string hotfixID = data["package"]["hotfix"]["name"];
std::string action, reason;

if (operation == "create") {
action = "hotfix-installed";
reason = "Hotfix " + hotfixID + " was installed";
} else if (operation == "update") {
action = "hotfix-updated";
reason = "Hotfix " + hotfixID + " was updated";
} else {
action = "hotfix-removed";
reason = "Hotfix " + hotfixID + " was removed";
}

return {{"event", {{"action", action}, {"category", {"hotfix"}}, {"type", {operation == "create" ? "installation" : "deletion"}}, {"created", created}, {"reason", reason}}}};
}

nlohmann::json PortEvent::generate() const {
int srcPort = data["source"]["port"];
int destPort = data["destination"]["port"];
std::string action, reason;

if (operation == "create") {
action = "port-detected";
reason = "New connection from source port " + std::to_string(srcPort) + " to destination port " + std::to_string(destPort);
} else if (operation == "update") {
action = "port-updated";
reason = "Updated connection from source port " + std::to_string(srcPort) + " to destination port " + std::to_string(destPort);
} else {
action = "port-closed";
reason = "Closed connection from source port " + std::to_string(srcPort) + " to destination port " + std::to_string(destPort);
}

return {{"event", {{"action", action}, {"category", {"network"}}, {"type", {operation == "create" ? "connection" : operation == "update" ? "change" : "end"}}, {"created", created}, {"reason", reason}}}};
}

nlohmann::json ProcessEvent::generate() const {
std::string processName = data["process"]["name"];
std::string pid = data["process"]["pid"];
std::string action, reason;

if (operation == "create") {
action = "process-started";
reason = "Process " + processName + " (PID: " + pid + ") was started";
} else if (operation == "update") {
action = "process-updated";
reason = "Process " + processName + " (PID: " + pid + ") was updated";
} else {
action = "process-stopped";
reason = "Process " + processName + " (PID: " + pid + ") was stopped";
}

return {{"event", {{"action", action}, {"category", {"process"}}, {"type", {operation == "create" ? "start" : operation == "update" ? "change" : "end"}}, {"created", created}, {"reason", reason}}}};
}

nlohmann::json SystemEvent::generate() const {
std::string hostname = data["host"]["hostname"];
std::string osVersion = data["host"]["os"]["version"];
std::string action = (operation == "update") ? "system-updated" : "system-detected";
std::string reason = "System " + hostname + " is running OS version " + osVersion;

return {{"event", {{"action", action}, {"category", {"host"}}, {"type", {operation == "update" ? "change" : "info"}}, {"created", created}, {"reason", reason}}}};
}

nlohmann::json HardwareEvent::generate() const {
std::string cpuName = data["host"]["cpu"]["name"];
int memoryTotalGB = data["host"]["memory"]["total"].get<int>() / BYTES_IN_MEGABYTE;
std::string serialNumber = data["observer"]["serial_number"];
std::string action, reason;

if (operation == "create") {
action = "hardware-detected";
reason = "New hardware detected: " + cpuName + " with " + std::to_string(memoryTotalGB) + " GB memory";
} else if (operation == "update") {
action = "hardware-updated";
reason = "Hardware changed";
} else if (operation == "remove") {
action = "hardware-removed";
reason = "Hardware with serial number " + serialNumber + " was removed";
}

return {{"event", {{"action", action}, {"category", {"host"}}, {"type", {operation == "create" ? "start" : operation == "update" ? "change" : "removed"}}, {"created", created}, {"reason", reason}}}};
}

std::unique_ptr<StatelessEvent> CreateEvent(const std::string& type, const std::string& operation, const std::string& created, const nlohmann::json& data) {
if (type == "networks") return std::make_unique<NetworkEvent>(operation, created, data);
if (type == "packages") return std::make_unique<PackageEvent>(operation, created, data);
if (type == "hotfixes") return std::make_unique<HotfixEvent>(operation, created, data);
if (type == "ports") return std::make_unique<PortEvent>(operation, created, data);
if (type == "processes") return std::make_unique<ProcessEvent>(operation, created, data);
if (type == "system") return std::make_unique<SystemEvent>(operation, created, data);
if (type == "hardware") return std::make_unique<HardwareEvent>(operation, created, data);

return nullptr;
}
27 changes: 27 additions & 0 deletions src/modules/inventory/src/statelessEvent.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#include <nlohmann/json.hpp>
#include <memory>
#include <string>

class StatelessEvent {
protected:
std::string operation;
std::string created;
nlohmann::json data;

public:
StatelessEvent(std::string op, std::string time, nlohmann::json d);
virtual nlohmann::json generate() const = 0;
virtual ~StatelessEvent() = default;
};

class NetworkEvent : public StatelessEvent { public: using StatelessEvent::StatelessEvent; nlohmann::json generate() const override; };
class PackageEvent : public StatelessEvent { public: using StatelessEvent::StatelessEvent; nlohmann::json generate() const override; };
class HotfixEvent : public StatelessEvent { public: using StatelessEvent::StatelessEvent; nlohmann::json generate() const override; };
class PortEvent : public StatelessEvent { public: using StatelessEvent::StatelessEvent; nlohmann::json generate() const override; };
class ProcessEvent : public StatelessEvent { public: using StatelessEvent::StatelessEvent; nlohmann::json generate() const override; };
class SystemEvent : public StatelessEvent { public: using StatelessEvent::StatelessEvent; nlohmann::json generate() const override; };
class HardwareEvent : public StatelessEvent { public: using StatelessEvent::StatelessEvent; nlohmann::json generate() const override; };

std::unique_ptr<StatelessEvent> CreateEvent(const std::string& type, const std::string& operation, const std::string& created, const nlohmann::json& data);
1 change: 1 addition & 0 deletions src/modules/inventory/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ project(unit_tests)
add_subdirectory(inventory)
add_subdirectory(inventoryImp)
add_subdirectory(invNormalizer)
add_subdirectory(statelessEvent)
11 changes: 11 additions & 0 deletions src/modules/inventory/tests/statelessEvent/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
find_package(GTest CONFIG REQUIRED)

add_executable(statelessEvent_unit_test statelessEvent_test.cpp)
configure_target(statelessEvent_unit_test)
target_include_directories(statelessEvent_unit_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include ${CMAKE_CURRENT_SOURCE_DIR}/../src/inventory/events)
target_link_libraries(statelessEvent_unit_test PRIVATE
Inventory
GTest::gtest
GTest::gtest_main
pthread)
add_test(NAME StatelessEventUnitTest COMMAND statelessEvent_unit_test)
Loading

0 comments on commit 8763302

Please sign in to comment.