209 lines
6.4 KiB
C++
209 lines
6.4 KiB
C++
/*
|
|
* This is an auditd plugin for sending auditd data
|
|
* to clickhouse DB.
|
|
* Copyright (C) 2020 Aleksei Nikiforov <darktemplar@basealt.ru>
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdexcept>
|
|
#include <sstream>
|
|
#include <memory>
|
|
|
|
#include <boost/property_tree/ptree.hpp>
|
|
#include <boost/property_tree/json_parser.hpp>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include "auditd-record.hpp"
|
|
|
|
static AuditRecord generateTestRecord()
|
|
{
|
|
AuditRecord original_record;
|
|
|
|
original_record.time = 12345678;
|
|
original_record.milliseconds = 9876;
|
|
original_record.serial = 12345;
|
|
original_record.node = "test node name";
|
|
|
|
original_record.filename = "some random file name";
|
|
|
|
auto string_field = InterpretedStringRecordField::createRecord("string_record");
|
|
string_field->setStringValue(std::string("string_record_value"));
|
|
original_record.fields[string_field->getName()] = string_field;
|
|
|
|
auto integer_field = IntegerRecordField::createRecord("integer_record");
|
|
integer_field->setIntValue(500);
|
|
integer_field->setStringValue(std::string("five hundred"));
|
|
original_record.fields[integer_field->getName()] = integer_field;
|
|
|
|
auto array_field = InterpretedStringArrayRecordField::createRecord("array_record");
|
|
array_field->setArrays({"first name", "second name"}, {"first value", "second value"});
|
|
original_record.fields[array_field->getName()] = array_field;
|
|
|
|
return original_record;
|
|
}
|
|
|
|
TEST(AuditRecord, Serialization)
|
|
{
|
|
AuditRecord original_record = generateTestRecord();
|
|
|
|
boost::property_tree::ptree ptree_data = original_record.toPtree();
|
|
std::stringstream stream_data;
|
|
|
|
boost::property_tree::write_json(stream_data, ptree_data);
|
|
|
|
boost::property_tree::ptree ptree_restored_data;
|
|
|
|
boost::property_tree::read_json(stream_data, ptree_restored_data);
|
|
|
|
auto restored_record = AuditRecord::fromPtree(ptree_restored_data);
|
|
|
|
ASSERT_TRUE(restored_record);
|
|
|
|
EXPECT_EQ(original_record.time, restored_record->time);
|
|
EXPECT_EQ(original_record.milliseconds, restored_record->milliseconds);
|
|
EXPECT_EQ(original_record.serial, restored_record->serial);
|
|
EXPECT_EQ(original_record.node, restored_record->node);
|
|
|
|
EXPECT_FALSE(original_record.filename.empty());
|
|
EXPECT_TRUE(restored_record->filename.empty());
|
|
|
|
EXPECT_EQ(original_record.fields.size(), restored_record->fields.size());
|
|
|
|
for (auto iter = original_record.fields.begin(); iter != original_record.fields.end(); ++iter)
|
|
{
|
|
auto second_iter = restored_record->fields.find(iter->first);
|
|
EXPECT_TRUE(second_iter != restored_record->fields.end());
|
|
|
|
if (second_iter == restored_record->fields.end())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
EXPECT_EQ(iter->second->getType(), second_iter->second->getType());
|
|
|
|
if (iter->second->getType() != second_iter->second->getType())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
EXPECT_EQ(iter->second->getName(), second_iter->second->getName());
|
|
|
|
switch (iter->second->getType())
|
|
{
|
|
case AbstractRecordField::Type::Int:
|
|
{
|
|
auto original_field = std::dynamic_pointer_cast<IntegerRecordField>(iter->second);
|
|
auto restored_field = std::dynamic_pointer_cast<IntegerRecordField>(second_iter->second);
|
|
|
|
EXPECT_TRUE(original_field);
|
|
EXPECT_TRUE(restored_field);
|
|
|
|
if ((!original_field) || (!restored_field))
|
|
{
|
|
break;
|
|
}
|
|
|
|
EXPECT_EQ(original_field->getIntValue(), restored_field->getIntValue());
|
|
EXPECT_EQ(original_field->getStringValue(), restored_field->getStringValue());
|
|
}
|
|
break;
|
|
|
|
case AbstractRecordField::Type::String:
|
|
{
|
|
auto original_field = std::dynamic_pointer_cast<StringRecordField>(iter->second);
|
|
auto restored_field = std::dynamic_pointer_cast<StringRecordField>(second_iter->second);
|
|
|
|
EXPECT_TRUE(original_field);
|
|
EXPECT_TRUE(restored_field);
|
|
|
|
if ((!original_field) || (!restored_field))
|
|
{
|
|
break;
|
|
}
|
|
|
|
EXPECT_EQ(original_field->getStringValue(), restored_field->getStringValue());
|
|
}
|
|
break;
|
|
|
|
case AbstractRecordField::Type::InterpretedString:
|
|
{
|
|
auto original_field = std::dynamic_pointer_cast<InterpretedStringRecordField>(iter->second);
|
|
auto restored_field = std::dynamic_pointer_cast<InterpretedStringRecordField>(second_iter->second);
|
|
|
|
EXPECT_TRUE(original_field);
|
|
EXPECT_TRUE(restored_field);
|
|
|
|
if ((!original_field) || (!restored_field))
|
|
{
|
|
break;
|
|
}
|
|
|
|
EXPECT_EQ(original_field->getStringValue(), restored_field->getStringValue());
|
|
}
|
|
break;
|
|
|
|
case AbstractRecordField::Type::InterpretedStringArray:
|
|
{
|
|
auto original_field = std::dynamic_pointer_cast<InterpretedStringArrayRecordField>(iter->second);
|
|
auto restored_field = std::dynamic_pointer_cast<InterpretedStringArrayRecordField>(second_iter->second);
|
|
|
|
EXPECT_TRUE(original_field);
|
|
EXPECT_TRUE(restored_field);
|
|
|
|
if ((!original_field) || (!restored_field))
|
|
{
|
|
break;
|
|
}
|
|
|
|
auto original_names = original_field->getNamesArray();
|
|
auto original_values = original_field->getValuesArray();
|
|
auto restored_names = restored_field->getNamesArray();
|
|
auto restored_values = restored_field->getValuesArray();
|
|
|
|
EXPECT_EQ(original_names.size(), restored_names.size());
|
|
|
|
if (original_names.size() == restored_names.size())
|
|
{
|
|
auto original_iter = original_names.begin();
|
|
auto restored_iter = restored_names.begin();
|
|
|
|
for ( ; (original_iter != original_names.end()) && (restored_iter != restored_names.end()); ++original_iter, ++restored_iter)
|
|
{
|
|
EXPECT_EQ(*original_iter, *restored_iter);
|
|
}
|
|
}
|
|
|
|
EXPECT_EQ(original_values.size(), restored_values.size());
|
|
|
|
if (original_values.size() == restored_values.size())
|
|
{
|
|
auto original_iter = original_values.begin();
|
|
auto restored_iter = restored_values.begin();
|
|
|
|
for ( ; (original_iter != original_values.end()) && (restored_iter != restored_values.end()); ++original_iter, ++restored_iter)
|
|
{
|
|
EXPECT_EQ(*original_iter, *restored_iter);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|