Skip to content

Commit

Permalink
feat: receiving old windows events, pending live WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
LucioDonda committed Jan 3, 2025
1 parent bb1d0da commit db0acba
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 59 deletions.
4 changes: 2 additions & 2 deletions src/cmake/config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ set(DEFAULT_FILE_WAIT 500 CACHE STRING "Default Logcollector file reading interv

set(DEFAULT_RELOAD_INTERVAL 60000 CACHE STRING "Default Logcollector reload interval (1m)")

set(DEFAULT_RECONNECT_TIME 5000 CACHE STRING "Default Logcollector reconnect time (5000ms)")
set(CHANNEL_REFRESH_INTERVAL 5000 CACHE STRING "Default Logcollector reconnect time (5000ms)")

set(DEFAULT_USE_BOOKMARK false CACHE BOOL "Default Logcollector windows bookmark enabled (false)")
set(DEFAULT_USE_BOOKMARK true CACHE BOOL "Default Logcollector windows bookmark enabled (false)")

set(DEFAULT_INVENTORY_ENABLED true CACHE BOOL "Default inventory enabled")

Expand Down
2 changes: 1 addition & 1 deletion src/common/config/include/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace config
constexpr auto DEFAULT_FILE_WAIT = @DEFAULT_FILE_WAIT@;
constexpr auto DEFAULT_RELOAD_INTERVAL = @DEFAULT_RELOAD_INTERVAL@;
constexpr auto DEFAULT_LOCALFILES = "/var/log/auth.log";
constexpr auto DEFAULT_RECONNECT_TIME = @DEFAULT_RECONNECT_TIME@;
constexpr auto CHANNEL_REFRESH_INTERVAL = @CHANNEL_REFRESH_INTERVAL@;
constexpr auto DEFAULT_USE_BOOKMARK = @DEFAULT_USE_BOOKMARK@;
}

Expand Down
14 changes: 9 additions & 5 deletions src/modules/logcollector/src/logcollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ void Logcollector::Setup(std::shared_ptr<const configuration::ConfigurationParse
}

SetupFileReader(configurationParser);
#ifdef _WIN32
SetupWEReader(configurationParser);
#endif
}

void Logcollector::SetupFileReader(const std::shared_ptr<const configuration::ConfigurationParser> configurationParser)
Expand All @@ -69,9 +72,9 @@ void Logcollector::SetupFileReader(const std::shared_ptr<const configuration::Co
#ifdef _WIN32
void Logcollector::SetupWEReader(const std::shared_ptr<const configuration::ConfigurationParser> configurationParser)
{
const auto reconnectTime = configurationParser->GetConfig<time_t>("logcollector", "reconnect-time").value_or(config::logcollector::DEFAULT_RECONNECT_TIME);
const auto refreshInterval = configurationParser->GetConfig<time_t>("logcollector", "channel_refresh").value_or(config::logcollector::CHANNEL_REFRESH_INTERVAL);

const auto bookmarkEnabled = configurationParser->GetConfig<bool>("logcollector", "use-bookmark").value_or(config::logcollector::DEFAULT_USE_BOOKMARK);
const auto bookmarkEnabled = configurationParser->GetConfig<bool>("logcollector", "use_bookmark").value_or(config::logcollector::DEFAULT_USE_BOOKMARK);

const auto windowsConfig = configurationParser->GetConfig<std::vector<std::map<std::string, std::string>>>("logcollector", "windows").value_or(
std::vector<std::map<std::string, std::string>> {});
Expand All @@ -81,11 +84,11 @@ void Logcollector::SetupWEReader(const std::shared_ptr<const configuration::Conf
for (auto& entry : windowsConfig)
{
auto channel = entry.at("channel");
channelsList.emplace_back(channel);
auto query = entry.at("query");
channelsList.emplace_back(channel);
queriesList.emplace_back(query);
}
AddReader(std::make_shared<WindowsEventTracerReader>(*this, channelsList, queriesList, reconnectTime, bookmarkEnabled));
AddReader(std::make_shared<WindowsEventTracerReader>(*this, channelsList, queriesList, refreshInterval, bookmarkEnabled));
}
#endif

Expand Down Expand Up @@ -126,7 +129,8 @@ void Logcollector::SendMessage(const std::string& location, const std::string& l
auto message = Message(MessageType::STATELESS, data, m_moduleName, collectorType, metadata.dump());
m_pushMessage(message);

LogTrace("Message pushed: '{}':'{}'", location, log);
//TODO: undo
LogInfo("Message pushed: '{}':'{}'", location, log);
}

void Logcollector::AddReader(std::shared_ptr<IReader> reader)
Expand Down
117 changes: 78 additions & 39 deletions src/modules/logcollector/src/we_reader_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,63 +17,80 @@ WindowsEventTracerReader::WindowsEventTracerReader(Logcollector &logcollector,

Awaitable WindowsEventTracerReader::Run()
{
// TODO: add lambda for loop break
while (true)
{
for (size_t i = 0; i < m_channelsList.size(); i++)
{
QueryEvents(m_channelsList.at(i), m_queriesList.at(i));
}
//TODO: find a clearer way of connecting this with outside modules
bool keepRunning = true;
std::function<bool()> shouldContinue = [&keepRunning]() { return keepRunning; };

co_await m_logcollector.Wait(std::chrono::milliseconds(m_ChannelsRefreshInterval));
for (size_t i = 0; i < m_channelsList.size(); i++)
{
m_logcollector.EnqueueTask(QueryEvents(m_channelsList.at(i), m_queriesList.at(i), shouldContinue));
}
co_return;
}

Awaitable WindowsEventTracerReader::QueryEvents(const std::string channel, const std::string query)
Awaitable WindowsEventTracerReader::QueryEvents(const std::string channel, const std::string query, std::function<bool()> shouldContinue)
{
// Load bookmark if exists
EVT_HANDLE bookmarkHandle = LoadBookmark();

//TODO: rework this casting
std::wstring wide_string_channel = std::wstring(channel.begin(), channel.end());
std::wstring wide_string_query = std::wstring(query.begin(), query.end());
EVT_HANDLE eventQueryHandle = EvtQuery( NULL, wide_string_channel.c_str(), wide_string_query.c_str(),
EvtQueryChannelPath | EvtQueryReverseDirection);
std::wstring wideStringChannel = std::wstring(channel.begin(), channel.end());
std::wstring wideStringQuery = std::wstring(query.begin(), query.end());

EVT_HANDLE eventQueryHandle = EvtQuery( NULL, wideStringChannel.c_str(), wideStringQuery.c_str(),
EvtQueryChannelPath | EvtQueryForwardDirection);

if (eventQueryHandle == NULL)
{
// TODO: Logging fix
// LogError("Failed to query event log: {}", GetLastError());
std::cerr << "Failed to query event log: " << GetLastError() << std::endl;
LogError("Failed to query event log: {}", std::to_string(GetLastError()));
co_return;
}

LogInfo("Querying events for {} channel with query: '{}'", channel, query);

EVT_HANDLE events[10];
DWORD eventCount = 0;

while (EvtNext(eventQueryHandle, 10, events, INFINITE, 0, &eventCount))
while (shouldContinue())
{
for (DWORD i = 0; i < eventCount; ++i)
if (EvtNext(eventQueryHandle, 10, events, 1000, 0, &eventCount))
{
ProcessEvent(events[i], channel);

if(m_bookmarkEnabled)
for (DWORD i = 0; i < eventCount; ++i)
{
ProcessEvent(events[i], channel);
if(m_bookmarkEnabled)
{
bookmarkHandle = CreateBookmark(events[i], bookmarkHandle);
SaveBookmark(bookmarkHandle);
}
EvtClose(events[i]);
}
}
else
{
DWORD error = GetLastError();
if (error == ERROR_NO_MORE_ITEMS)
{
//TODO: delete or make it trace
LogInfo("No more events. Waiting for new events...");
co_await m_logcollector.Wait(std::chrono::milliseconds(m_ChannelsRefreshInterval));
}
else
{
// Save the last event as a bookmark
bookmarkHandle = CreateBookmark(events[i], bookmarkHandle);
SaveBookmark(bookmarkHandle);
LogError("EvtNext failed with error: {}" , std::to_string(error));
break;
}
EvtClose(events[i]);
}
//TODO: check using logcollec
co_await m_logcollector.Wait(std::chrono::milliseconds(m_eventsProcessingInterval));
}

EvtClose(eventQueryHandle);
if (bookmarkHandle)
{
EvtClose(bookmarkHandle);
}

if (eventQueryHandle)
{
EvtClose(eventQueryHandle);
}
}

void WindowsEventTracerReader::ProcessEvent(EVT_HANDLE event, const std::string channel)
Expand All @@ -88,11 +105,17 @@ void WindowsEventTracerReader::ProcessEvent(EVT_HANDLE event, const std::string
std::vector<wchar_t> buffer(bufferUsed);
if (EvtRender(NULL, event, EvtRenderEventXml, bufferUsed, buffer.data(), &bufferUsed, &propertyCount))
{
// TODO: Logging fix
// LogTrace("Event: {}",buffer.data());
std::wcout << L"Event: " << buffer.data() << std::endl;
const std::string log {};
// m_logcollector.SendMessage(channel, log, m_collectorType);
std::string logString;
try
{
logString = WcharVecToString(buffer);
}
catch(const std::exception& e)
{
LogError("Cannot convert utf16 string: {}", e.what());
return;
}
m_logcollector.SendMessage(channel, logString, m_collectorType);
}
}
}
Expand All @@ -102,9 +125,7 @@ EVT_HANDLE WindowsEventTracerReader::CreateBookmark(EVT_HANDLE event, EVT_HANDLE
EVT_HANDLE bookmark = existingBookmark ? existingBookmark : EvtCreateBookmark(NULL);
if (!EvtUpdateBookmark(bookmark, event))
{
// TODO: Logging fix
// LogError("Failed to update bookmark: {}", GetLastError());
std::cerr << "Failed to update bookmark: " << GetLastError() << std::endl;
LogError("Failed to update bookmark: {}", std::to_string(GetLastError()));
}
return bookmark;
}
Expand All @@ -117,7 +138,7 @@ void WindowsEventTracerReader::SaveBookmark(EVT_HANDLE bookmarkHandle)
std::vector<wchar_t> buffer(bufferUsed);
if (EvtRender(NULL, bookmarkHandle, EvtRenderBookmark, bufferUsed, buffer.data(), &bufferUsed, NULL))
{
std::wofstream file(bookmarkFile_);
std::wofstream file(m_bookmarkFile);
if (file.is_open())
{
file.write(buffer.data(), bufferUsed / sizeof(wchar_t));
Expand All @@ -130,17 +151,35 @@ EVT_HANDLE WindowsEventTracerReader::LoadBookmark()
{
if(m_bookmarkEnabled)
{
std::wifstream file(bookmarkFile_);
std::wifstream file(m_bookmarkFile);
if (file.is_open())
{
std::wstringstream buffer;
buffer << file.rdbuf();
std::wstring bookmarkXML = buffer.str();
file.close();
//TODO: delete later
LogInfo("Creating bookark");
return EvtCreateBookmark(bookmarkXML.c_str());
}
else
{
LogError("Couldn't open bookmark file: {}", m_bookmarkFile);
}
}

return NULL;
}

std::string WindowsEventTracerReader::WcharVecToString(std::vector<wchar_t>& buffer)
{
buffer.erase(std::remove(buffer.begin(), buffer.end(), L'\0'), buffer.end());
std::wstring wstr(buffer.begin(), buffer.end());
std::string result;
result.reserve(wstr.size() * sizeof(wchar_t));
std::transform(wstr.begin(), wstr.end(), std::back_inserter(result),
[](wchar_t wc) -> char {
return static_cast<char>(wc);
});
return result;
}
20 changes: 8 additions & 12 deletions src/modules/logcollector/src/we_reader_win.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#pragma once

#include <ctime>
#include <codecvt>
#include <fstream>
#include <iostream>
#include <memory>
Expand Down Expand Up @@ -33,15 +34,15 @@ class WindowsEventTracerReader : public IReader
WindowsEventTracerReader(Logcollector &logcollector,
const std::vector<std::string> channels,
const std::vector<std::string> queries,
const std::time_t reloadInterval,
const std::time_t channelRefreshInterval,
bool bookmarkEnabled);

/// @brief Runs the file reader
/// @return Awaitable result
Awaitable Run() override;

// Main function to execute the event query with bookmarks and filters
Awaitable QueryEvents(const std::string channel, const std::string query);
Awaitable QueryEvents(const std::string channel, const std::string query, std::function<bool()> shouldContinue);

private:
// Process an individual event and print its XML representation
Expand All @@ -56,26 +57,21 @@ class WindowsEventTracerReader : public IReader
// Load bookmark from file (if it exists)
EVT_HANDLE LoadBookmark();

//TODO: doc
std::string WcharVecToString(std::vector<wchar_t>& buffer);

std::vector<std::string> m_channelsList;

std::vector<std::string> m_queriesList;

std::wstring bookmarkFile_;

std::string m_channel;

std::string m_query;
//TODO: change to configurable
std::string m_bookmarkFile = "bookmark.xml";

/// @brief
std::time_t m_ChannelsRefreshInterval;

/// @brief
std::time_t m_eventsProcessingInterval;

bool m_bookmarkEnabled;

int m_availableEvents = 0;

const std::string m_collectorType = "eventchannel";
};
} // namespace logcollector
Expand Down

0 comments on commit db0acba

Please sign in to comment.