mirror of
https://github.com/openappsec/openappsec.git
synced 2025-09-29 11:16:30 +03:00
My 11th 2023 update
This commit is contained in:
@@ -21,6 +21,11 @@
|
||||
#include "rest.h"
|
||||
#include "cereal/external/rapidjson/document.h"
|
||||
|
||||
#include "customized_cereal_map.h"
|
||||
#include "cereal/archives/json.hpp"
|
||||
#include "cereal/types/vector.hpp"
|
||||
#include "cereal/types/string.hpp"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
@@ -28,6 +33,31 @@ using namespace rapidjson;
|
||||
|
||||
USE_DEBUG_FLAG(D_ORCHESTRATOR);
|
||||
|
||||
// LCOV_EXCL_START Reason: WA for NSaaS upgrade
|
||||
class TenantProfileMap
|
||||
{
|
||||
public:
|
||||
void
|
||||
load(const string &raw_value)
|
||||
{
|
||||
vector<string> tenants_and_profiles;
|
||||
{
|
||||
stringstream string_stream(raw_value);
|
||||
cereal::JSONInputArchive archive(string_stream);
|
||||
cereal::load(archive, tenants_and_profiles);
|
||||
}
|
||||
for (const auto &tenant_profile_pair : tenants_and_profiles) {
|
||||
value.push_back(tenant_profile_pair);
|
||||
}
|
||||
}
|
||||
|
||||
const vector<string> & getValue() const { return value; }
|
||||
private:
|
||||
vector<string> value;
|
||||
};
|
||||
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
class Downloader::Impl : Singleton::Provide<I_Downloader>::From<Downloader>
|
||||
{
|
||||
public:
|
||||
@@ -51,6 +81,9 @@ public:
|
||||
const string &service_name
|
||||
) const override;
|
||||
|
||||
void createTenantProfileMap();
|
||||
string getProfileFromMap(const string &tenant_id) const override;
|
||||
|
||||
private:
|
||||
Maybe<string> downloadFileFromFogByHTTP(
|
||||
const GetResourceFile &resourse_file,
|
||||
@@ -74,6 +107,7 @@ private:
|
||||
tuple<string, string> splitQuery(const string &query) const;
|
||||
string vectorToPath(const vector<string> &vec) const;
|
||||
string dir_path;
|
||||
map<string, string> tenant_profile_map;
|
||||
};
|
||||
|
||||
void
|
||||
@@ -111,6 +145,42 @@ Downloader::Impl::downloadFileFromFog(
|
||||
return file_path;
|
||||
}
|
||||
|
||||
void
|
||||
Downloader::Impl::createTenantProfileMap()
|
||||
{
|
||||
dbgFlow(D_ORCHESTRATOR) << "Creating a tenant-profile map from the agent settings";
|
||||
tenant_profile_map.clear();
|
||||
auto maybe_tenant_profile_map = getProfileAgentSetting<TenantProfileMap>("TenantProfileMap");
|
||||
if (maybe_tenant_profile_map.ok()) {
|
||||
dbgTrace(D_ORCHESTRATOR) << "Managed to read the TenantProfileMap agent settings";
|
||||
TenantProfileMap tpm = maybe_tenant_profile_map.unpack();
|
||||
for (const string &str : tpm.getValue()) {
|
||||
string delimiter = ":";
|
||||
string tenant = str.substr(0, str.find(delimiter));
|
||||
string profile = str.substr(str.find(delimiter) + 1);
|
||||
dbgTrace(D_ORCHESTRATOR)
|
||||
<< "Loading into the map. Tenant: "
|
||||
<< tenant
|
||||
<< " Profile: "
|
||||
<< profile;
|
||||
tenant_profile_map[tenant] = profile;
|
||||
}
|
||||
} else {
|
||||
dbgTrace(D_ORCHESTRATOR) << "Couldn't load the TenantProfileMap agent settings";
|
||||
}
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START Reason: NSaaS old profiles support
|
||||
string
|
||||
Downloader::Impl::getProfileFromMap(const string &tenant_id) const
|
||||
{
|
||||
if (tenant_profile_map.find(tenant_id) == tenant_profile_map.end()) {
|
||||
return "";
|
||||
}
|
||||
return tenant_profile_map.at(tenant_id);
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
Maybe<map<pair<string, string>, string>>
|
||||
Downloader::Impl::downloadVirtualFileFromFog(
|
||||
const GetResourceFile &resourse_file,
|
||||
@@ -130,8 +200,10 @@ Downloader::Impl::downloadVirtualFileFromFog(
|
||||
|
||||
Document document;
|
||||
document.Parse(downloaded_data.unpack().c_str());
|
||||
if (document.HasParseError()) return genError("JSON file is not valid.");
|
||||
|
||||
if (document.HasParseError()) {
|
||||
dbgWarning(D_ORCHESTRATOR) << "JSON file is not valid";
|
||||
return genError("JSON file is not valid.");
|
||||
}
|
||||
const Value &tenants_data = document[tenants_key.c_str()];
|
||||
for (Value::ConstValueIterator itr = tenants_data.Begin(); itr != tenants_data.End(); ++itr) {
|
||||
|
||||
@@ -145,9 +217,21 @@ Downloader::Impl::downloadVirtualFileFromFog(
|
||||
|
||||
if (artifact_data != itr->MemberEnd()) {
|
||||
auto profile_id_obj = itr->FindMember(profile_id_key.c_str());
|
||||
if (profile_id_obj == itr->MemberEnd()) continue;
|
||||
string profile_id;
|
||||
if (profile_id_obj == itr->MemberEnd()) {
|
||||
if (tenant_profile_map.count(tenant_id)) {
|
||||
dbgWarning(D_ORCHESTRATOR)
|
||||
<< "Forcing profile ID to be "
|
||||
<< getProfileFromMap(tenant_id);
|
||||
profile_id = getProfileFromMap(tenant_id);
|
||||
} else {
|
||||
dbgWarning(D_ORCHESTRATOR) << "Couldn't force profile ID";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
string profile_id = profile_id_obj->value.GetString();
|
||||
if (profile_id.empty()) profile_id = profile_id_obj->value.GetString();
|
||||
dbgTrace(D_ORCHESTRATOR) << "Found a profile ID " << profile_id;
|
||||
|
||||
string file_path =
|
||||
dir_path + "/" + resourse_file.getFileName() + "_" +
|
||||
@@ -161,6 +245,9 @@ Downloader::Impl::downloadVirtualFileFromFog(
|
||||
if (orchestration_tools->writeFile(buffer.GetString(), file_path)) {
|
||||
res.insert({{tenant_id, profile_id}, file_path});
|
||||
}
|
||||
|
||||
orchestration_tools->fillKeyInJson(file_path, "profileID", profile_id);
|
||||
orchestration_tools->fillKeyInJson(file_path, "tenantID", tenant_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -387,4 +474,5 @@ Downloader::preload()
|
||||
registerExpectedConfiguration<string>("orchestration", "Default file download path");
|
||||
registerExpectedConfiguration<string>("orchestration", "Self signed certificates acceptable");
|
||||
registerExpectedConfiguration<bool>("orchestration", "Add tenant suffix");
|
||||
registerConfigLoadCb([this]() { pimpl->createTenantProfileMap(); });
|
||||
}
|
||||
|
@@ -345,6 +345,8 @@ TEST_F(DownloaderTest, download_virtual_policy)
|
||||
EXPECT_CALL(mock_orchestration_tools, writeFile(tenant_0000_file, "/tmp/virtualPolicy_0000_profile_1234.download"))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
EXPECT_CALL(mock_orchestration_tools, fillKeyInJson(_, _, _)).WillRepeatedly(Return());
|
||||
|
||||
EXPECT_CALL(mock_orchestration_tools, writeFile(tenant_1111_file, "/tmp/virtualPolicy_1111_profile_1235.download"))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
@@ -429,6 +431,8 @@ TEST_F(DownloaderTest, download_virtual_settings)
|
||||
)
|
||||
).WillOnce(Return(true));
|
||||
|
||||
EXPECT_CALL(mock_orchestration_tools, fillKeyInJson(_, _, _)).WillRepeatedly(Return());
|
||||
|
||||
stringstream file_path;
|
||||
file_path << "/tmp/virtualSettings_4c721b40-85df-4364-be3d-303a10ee9789"
|
||||
"_profile_4c721b40-85df-4364-be3d-303a10ee9780.download";
|
||||
|
@@ -40,6 +40,12 @@ public:
|
||||
downloadFileFromURL,
|
||||
Maybe<std::string>(const std::string &, const std::string &, Package::ChecksumTypes, const std::string &)
|
||||
);
|
||||
|
||||
MOCK_CONST_METHOD1(
|
||||
getProfileFromMap,
|
||||
std::string(const std::string &)
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
#endif // __MOCK_DOWNLOADER_H__
|
||||
|
@@ -31,13 +31,6 @@ operator<<(std::ostream &os, const std::map<T, S> &)
|
||||
return os;
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
std::ostream &
|
||||
operator<<(std::ostream &os, const Maybe<std::map<T, S>> &)
|
||||
{
|
||||
return os;
|
||||
}
|
||||
|
||||
class MockOrchestrationTools
|
||||
:
|
||||
public Singleton::Provide<I_OrchestrationTools>::From<MockProvider<I_OrchestrationTools>>
|
||||
@@ -56,6 +49,7 @@ public:
|
||||
Maybe<std::map<std::string, std::string>>(const std::string &, const std::string &, const std::string &)
|
||||
);
|
||||
MOCK_CONST_METHOD1(doesFileExist, bool(const std::string &));
|
||||
MOCK_CONST_METHOD3(fillKeyInJson, void(const std::string &, const std::string &, const std::string &));
|
||||
MOCK_CONST_METHOD1(createDirectory, bool(const std::string &));
|
||||
MOCK_CONST_METHOD1(doesDirectoryExist, bool(const std::string &));
|
||||
MOCK_CONST_METHOD1(executeCmd, bool(const std::string &));
|
||||
|
@@ -1113,17 +1113,26 @@ private:
|
||||
// Download virtual policy
|
||||
bool is_empty = true;
|
||||
GetResourceFile resource_v_policy_file(GetResourceFile::ResourceFileType::VIRTUAL_POLICY);
|
||||
I_Downloader *downloader = Singleton::Consume<I_Downloader>::by<OrchestrationComp>();
|
||||
for (const auto &tenant: *updated_policy_tenants) {
|
||||
if (!tenant.getVersion().empty()) {
|
||||
is_empty = false;
|
||||
|
||||
string profile_to_use = tenant.getProfileID().empty() ?
|
||||
downloader->getProfileFromMap(tenant.getTenantID()) :
|
||||
tenant.getProfileID();
|
||||
|
||||
dbgTrace(D_ORCHESTRATOR)
|
||||
<< "Adding a tenant to the multi-tenant list. Tenant: "
|
||||
<< tenant.getTenantID();
|
||||
<< tenant.getTenantID()
|
||||
<< " Profile: "
|
||||
<< profile_to_use;
|
||||
auto tenant_manager = Singleton::Consume<I_TenantManager>::by<OrchestrationComp>();
|
||||
tenant_manager->addActiveTenantAndProfile(tenant.getTenantID(), tenant.getProfileID());
|
||||
|
||||
tenant_manager->addActiveTenantAndProfile(tenant.getTenantID(), profile_to_use);
|
||||
resource_v_policy_file.addTenant(
|
||||
tenant.getTenantID(),
|
||||
tenant.getProfileID(),
|
||||
profile_to_use,
|
||||
tenant.getVersion(),
|
||||
tenant.getChecksum()
|
||||
);
|
||||
@@ -1132,7 +1141,7 @@ private:
|
||||
|
||||
if (!is_empty) {
|
||||
auto new_virtual_policy_files =
|
||||
Singleton::Consume<I_Downloader>::by<OrchestrationComp>()->downloadVirtualFileFromFog(
|
||||
downloader->downloadVirtualFileFromFog(
|
||||
resource_v_policy_file,
|
||||
I_OrchestrationTools::SELECTED_CHECKSUM_TYPE
|
||||
);
|
||||
@@ -1151,9 +1160,24 @@ private:
|
||||
for (const auto &tenant: *updated_settings_tenants) {
|
||||
if (!tenant.getVersion().empty()) {
|
||||
is_empty = false;
|
||||
|
||||
string profile_to_use = tenant.getProfileID().empty() ?
|
||||
downloader->getProfileFromMap(tenant.getTenantID()) :
|
||||
tenant.getProfileID();
|
||||
|
||||
dbgTrace(D_ORCHESTRATOR)
|
||||
<< "Handling virtual settings: Tenant ID: "
|
||||
<< tenant.getTenantID()
|
||||
<< ", Profile ID: "
|
||||
<< profile_to_use
|
||||
<< ", version: "
|
||||
<< tenant.getVersion()
|
||||
<< ", checksum: "
|
||||
<< tenant.getChecksum();
|
||||
|
||||
resource_v_settings_file.addTenant(
|
||||
tenant.getTenantID(),
|
||||
tenant.getProfileID(),
|
||||
profile_to_use,
|
||||
tenant.getVersion(),
|
||||
tenant.getChecksum()
|
||||
);
|
||||
@@ -1169,6 +1193,11 @@ private:
|
||||
if (new_virtual_settings_files.ok()) {
|
||||
for (const auto &tenant_file: *new_virtual_settings_files) {
|
||||
auto tenant_profile = TenantProfilePair(tenant_file.first.first, tenant_file.first.second);
|
||||
dbgTrace(D_ORCHESTRATOR)
|
||||
<< "Downloaded a file from the FOG: Tenant ID: "
|
||||
<< tenant_profile.getTenantId()
|
||||
<< ", Profile ID: "
|
||||
<< tenant_profile.getProfileId();
|
||||
sorted_files[tenant_profile].push_back(tenant_file.second);
|
||||
}
|
||||
}
|
||||
|
@@ -45,6 +45,7 @@ public:
|
||||
bool removeFile(const string &path) const override;
|
||||
bool copyFile(const string &src_path, const string &dst_path) const override;
|
||||
bool doesFileExist(const string &file_path) const override;
|
||||
void fillKeyInJson(const string &filename, const string &_key, const string &_val) const override;
|
||||
bool createDirectory(const string &directory_path) const override;
|
||||
bool doesDirectoryExist(const string &dir_path) const override;
|
||||
bool executeCmd(const string &cmd) const override;
|
||||
@@ -78,6 +79,41 @@ checkExistence(const string &path, bool is_dir)
|
||||
}
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START Reason: NSaaS upgrade WA
|
||||
void
|
||||
OrchestrationTools::Impl::fillKeyInJson(const string &filename, const string &_key, const string &_val) const
|
||||
{
|
||||
// Load the JSON file into a string
|
||||
std::ifstream ifs(filename);
|
||||
std::string jsonStr((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
||||
|
||||
dbgTrace(D_ORCHESTRATOR) << "Trying to parse " << filename;
|
||||
// Parse the JSON string
|
||||
Document doc;
|
||||
doc.Parse(jsonStr.c_str());
|
||||
|
||||
// Check if the key exists
|
||||
if (doc.HasMember(_key.c_str())) {
|
||||
dbgTrace(D_ORCHESTRATOR) << _key << " already exists.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Add the key with value
|
||||
Value key(_key.c_str(), doc.GetAllocator());
|
||||
Value val(_val.c_str(), doc.GetAllocator());
|
||||
doc.AddMember(key, val, doc.GetAllocator());
|
||||
|
||||
// Write the modified JSON to a new file
|
||||
StringBuffer buffer;
|
||||
Writer<StringBuffer> writer(buffer);
|
||||
doc.Accept(writer);
|
||||
std::ofstream ofs(filename);
|
||||
ofs << buffer.GetString() << std::endl;
|
||||
|
||||
dbgTrace(D_ORCHESTRATOR) << _key << " added with val " << _val;
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
bool
|
||||
OrchestrationTools::Impl::doesFileExist(const string &file_path) const
|
||||
{
|
||||
|
@@ -265,14 +265,14 @@ TEST_F(OrchestrationMultitenancyTest, handle_virtual_resource)
|
||||
EXPECT_CALL(mock_service_controller, getPolicyVersion())
|
||||
.Times(2).WillRepeatedly(ReturnRef(first_policy_version));
|
||||
|
||||
vector<string> active_tenants = { "1236", "1235" };
|
||||
set<string> active_tenants = { "1236", "1235" };
|
||||
EXPECT_CALL(tenant_manager, fetchActiveTenants()).WillOnce(Return(active_tenants));
|
||||
|
||||
EXPECT_CALL(tenant_manager, addActiveTenantAndProfile("1235", "2311"));
|
||||
EXPECT_CALL(tenant_manager, addActiveTenantAndProfile("1236", "2611"));
|
||||
|
||||
vector<string> first_tenant_profiles = { "2611" };
|
||||
vector<string> second_tenant_profiles = { "2311"};
|
||||
set<string> first_tenant_profiles = { "2611" };
|
||||
set<string> second_tenant_profiles = { "2311"};
|
||||
EXPECT_CALL(
|
||||
tenant_manager,
|
||||
fetchProfileIds("1236")).WillRepeatedly(Return(first_tenant_profiles)
|
||||
|
@@ -1466,8 +1466,8 @@ TEST_F(ServiceControllerTest, testMultitenantConfFiles)
|
||||
make_pair("/etc/cp/conf/tenant2_profile_1235_policy.json", "")}
|
||||
};
|
||||
|
||||
vector<string> ids = {"family1_id2"};
|
||||
vector<string> empty_ids;
|
||||
set<string> ids = {"family1_id2"};
|
||||
set<string> empty_ids;
|
||||
|
||||
EXPECT_CALL(tenant_manager, getInstances("tenant1", "1234")).WillOnce(Return(ids));
|
||||
EXPECT_CALL(tenant_manager, getInstances("tenant2", "1235")).WillOnce(Return(empty_ids));
|
||||
@@ -1592,7 +1592,7 @@ TEST_F(ServiceControllerTest, cleanup_virtual_files)
|
||||
"222222\n"
|
||||
"333333\n";
|
||||
|
||||
vector<string> active_tenants = {
|
||||
set<string> active_tenants = {
|
||||
"222222"
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user