First release of open-appsec source code

This commit is contained in:
roybarda
2022-10-26 19:33:19 +03:00
parent 3883109caf
commit a883352f79
1353 changed files with 276290 additions and 1 deletions

View File

@@ -0,0 +1,10 @@
add_library(
orchestration_modules
orchestration_policy.cc
url_parser.cc
package.cc
orchestration_status.cc
data.cc
)
add_subdirectory(modules_ut)

View File

@@ -0,0 +1,52 @@
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "orchestrator/data.h"
#include <map>
#include "sasal.h"
SASAL_START // Orchestration - Modules
using namespace std;
using namespace cereal;
USE_DEBUG_FLAG(D_ORCHESTRATOR);
static const map<string, Data::ChecksumTypes> checksum_map = {
{ "sha1sum", Data::ChecksumTypes::SHA1 },
{ "sha256sum", Data::ChecksumTypes::SHA256 },
{ "sha512sum", Data::ChecksumTypes::SHA512 },
{ "md5sum", Data::ChecksumTypes::MD5 }
};
void
Data::serialize(JSONInputArchive &in_archive)
{
string checksum_type_as_string;
in_archive(make_nvp("checksumType", checksum_type_as_string));
if (checksum_map.find(checksum_type_as_string) != checksum_map.end()) {
checksum_type = checksum_map.at(checksum_type_as_string);
} else {
dbgWarning(D_ORCHESTRATOR) << "Unsupported checksum type: " << checksum_type_as_string;
return;
}
in_archive(
make_nvp("downloadPath", download_path),
make_nvp("checksum", checksum_value),
make_nvp("version", version)
);
}
SASAL_END

View File

@@ -0,0 +1,7 @@
link_directories(${BOOST_ROOT}/lib)
add_unit_test(
orchestration_modules_ut
"orchestration_policy_ut.cc;url_parser_ut.cc;package_ut.cc;orchestration_status_ut.cc;data_ut.cc;"
"orchestration_modules;config;environment;metric;event_is;time_proxy;-lboost_regex"
)

View File

@@ -0,0 +1,85 @@
#include "orchestrator/data.h"
#include "cereal/types/string.hpp"
#include "cereal/archives/json.hpp"
#include <string>
#include <memory>
#include <fstream>
#include "cptest.h"
#include "customized_cereal_map.h"
using namespace testing;
using namespace std;
class DataTest : public Test
{
public:
bool
load(stringstream &string_stream, Data &data)
{
try {
cereal::JSONInputArchive archive_in(string_stream);
data.serialize(archive_in);
} catch (const cereal::Exception &) {
return false;
}
return true;
}
};
TEST_F(DataTest, doNothing)
{
}
TEST_F(DataTest, serializationFromString)
{
stringstream string_stream;
string_stream << "{"
" \"version\": \"c\","
" \"downloadPath\": \"https://a/data.json\",\n"
" \"checksumType\": \"sha1sum\","
" \"checksum\": \"8d4a5709673a05b380ba7d6567e28910019118f5\""
"}";
bool res = false;
Data data;
try {
cereal::JSONInputArchive archive_in(string_stream);
data.serialize(archive_in);
res = true;
} catch (const cereal::Exception &) {
}
EXPECT_EQ(true, res);
EXPECT_EQ(Data::ChecksumTypes::SHA1, data.getChecksumType());
EXPECT_EQ("8d4a5709673a05b380ba7d6567e28910019118f5", data.getChecksum());
EXPECT_EQ("c", data.getVersion());
EXPECT_EQ("https://a/data.json", data.getDownloadPath());
}
TEST_F(DataTest, serializationFromStringAsMap)
{
stringstream string_stream;
string_stream << "{\n"
" \"ips\": {\n"
" \"version\": \"c\","
" \"downloadPath\": \"https://a/data.json\",\n"
" \"checksumType\": \"sha1sum\","
" \"checksum\": \"8d4a5709673a05b380ba7d6567e28910019118f5\""
" }\n"
"}\n";
map<string, Data> data;
bool res = false;
try {
cereal::JSONInputArchive archive_in(string_stream);
cereal::load(archive_in, data);
res = true;
} catch (const cereal::Exception &e) {
}
EXPECT_EQ(true, res);
EXPECT_EQ(Data::ChecksumTypes::SHA1, data["ips"].getChecksumType());
EXPECT_EQ("8d4a5709673a05b380ba7d6567e28910019118f5", data["ips"].getChecksum());
EXPECT_EQ("c", data["ips"].getVersion());
EXPECT_EQ("https://a/data.json", data["ips"].getDownloadPath());
}

View File

@@ -0,0 +1,158 @@
#include "orchestration_policy.h"
#include <string>
#include <memory>
#include "cptest.h"
#include "cereal/types/string.hpp"
using namespace testing;
using namespace std;
class PolicyTest : public Test
{
public:
PolicyTest() {}
void
orchestrationPolicyToString(stringstream &string_stream)
{
cereal::JSONInputArchive archive_in(string_stream);
orchestration_policy.serialize(archive_in);
}
OrchestrationPolicy orchestration_policy;
};
TEST_F(PolicyTest, doNothing)
{
}
TEST_F(PolicyTest, serialization)
{
stringstream string_stream;
string_stream << "{"
" \"fog-address\": \"http://10.0.0.18:81/control/\","
" \"agent-type\": \"13324sadsd2\","
" \"pulling-interval\": 20,"
" \"error-pulling-interval\": 15"
"}";
try {
orchestrationPolicyToString(string_stream);
} catch (cereal::Exception &e) {
ASSERT_TRUE(false) << "Cereal threw an exception: " << e.what();
}
EXPECT_EQ(15u, orchestration_policy.getErrorSleepInterval());
EXPECT_EQ(20u, orchestration_policy.getSleepInterval());
EXPECT_EQ("http://10.0.0.18:81/control/", orchestration_policy.getFogAddress());
}
TEST_F(PolicyTest, noAgentType)
{
stringstream string_stream;
string_stream << "{"
" \"fog-address\": \"http://10.0.0.18:81/control/\","
" \"agent-type\": \"\","
" \"pulling-interval\": 20,"
" \"error-pulling-interval\": 15"
"}";
try {
orchestrationPolicyToString(string_stream);
} catch (cereal::Exception &e) {
ASSERT_TRUE(false) << "Cereal threw an exception: " << e.what();
}
EXPECT_EQ(15u, orchestration_policy.getErrorSleepInterval());
EXPECT_EQ(20u, orchestration_policy.getSleepInterval());
EXPECT_EQ("http://10.0.0.18:81/control/", orchestration_policy.getFogAddress());
}
TEST_F(PolicyTest, zeroSleepIntervels)
{
stringstream string_stream;
string_stream << "{"
" \"fog-address\": \"http://10.0.0.18:81/control/\","
" \"agent-type\": \"13324sadsd2\","
" \"pulling-interval\": 0,"
" \"error-pulling-interval\": 0"
"}";
try {
orchestrationPolicyToString(string_stream);
} catch (cereal::Exception &e) {
ASSERT_TRUE(false) << "Cereal threw an exception: " << e.what();
}
EXPECT_EQ(0u, orchestration_policy.getErrorSleepInterval());
EXPECT_EQ(0u, orchestration_policy.getSleepInterval());
EXPECT_EQ("http://10.0.0.18:81/control/", orchestration_policy.getFogAddress());
}
TEST_F(PolicyTest, operatorEqual)
{
stringstream string_stream;
string_stream << "{"
" \"fog-address\": \"http://10.0.0.18:81/control/\","
" \"pulling-interval\": 20,"
" \"error-pulling-interval\": 15"
"}";
try {
orchestrationPolicyToString(string_stream);
} catch (cereal::Exception &e) {
ASSERT_TRUE(false) << "Cereal threw an exception: " << e.what();
}
OrchestrationPolicy orchestration_copy_policy;
stringstream string_stream_copy;
string_stream_copy << "{"
" \"fog-address\": \"http://10.0.0.18:81/control/\","
" \"pulling-interval\": 20,"
" \"error-pulling-interval\": 15"
"}";
try{
cereal::JSONInputArchive archive_in(string_stream_copy);
orchestration_copy_policy.serialize(archive_in);
} catch (cereal::Exception &e) {
ASSERT_TRUE(false) << "Cereal threw an exception: " << e.what();
}
EXPECT_TRUE(orchestration_copy_policy == orchestration_policy);
EXPECT_FALSE(orchestration_copy_policy != orchestration_policy);
OrchestrationPolicy orchestration_new_policy;
stringstream string_stream_new;
string_stream_new << "{"
" \"fog-address\": \"http://10.0.0.18:801/control/\","
" \"pulling-interval\": 20,"
" \"error-pulling-interval\": 15"
"}";
try{
cereal::JSONInputArchive archive_in(string_stream_new);
orchestration_new_policy.serialize(archive_in);
} catch (cereal::Exception &e) {
ASSERT_TRUE(false) << "Cereal threw an exception: " << e.what();
}
EXPECT_FALSE(orchestration_new_policy == orchestration_policy);
EXPECT_TRUE(orchestration_new_policy != orchestration_policy);
}
TEST_F(PolicyTest, newOptionalFields)
{
stringstream string_stream;
string_stream << "{"
" \"fog-address\": \"https://fog-api-gw-agents.cloud.ngen.checkpoint.com\","
" \"pulling-interval\": 30,"
" \"error-pulling-interval\": 10,"
" \"agent-type\": \"arrow\""
"}";
try {
orchestrationPolicyToString(string_stream);
} catch (cereal::Exception &e) {
ASSERT_TRUE(false) << "Cereal threw an exception: " << e.what();
}
EXPECT_EQ(10u, orchestration_policy.getErrorSleepInterval());
EXPECT_EQ(30u, orchestration_policy.getSleepInterval());
EXPECT_EQ("https://fog-api-gw-agents.cloud.ngen.checkpoint.com", orchestration_policy.getFogAddress());
}

View File

@@ -0,0 +1,484 @@
#include "orchestration_status.h"
#include <string>
#include <chrono>
#include <fstream>
#include <map>
#include "cptest.h"
#include "config.h"
#include "config_component.h"
#include "mock/mock_time_get.h"
#include "mock/mock_orchestration_tools.h"
#include "mock/mock_agent_details.h"
#include "mock/mock_mainloop.h"
#include "mock/mock_rest_api.h"
using namespace testing;
using namespace std;
using namespace chrono;
class OrchestrationStatusTest : public Test
{
public:
~OrchestrationStatusTest() { Debug::setNewDefaultStdout(&cout); }
void
init()
{
Debug::setUnitTestFlag(D_ORCHESTRATOR, Debug::DebugLevel::TRACE);
Debug::setNewDefaultStdout(&capture_debug);
CPTestTempfile status_file;
file_path = status_file.fname;
setConfiguration(file_path, "orchestration", "Orchestration status path");
// Write orchestration status to file routine
EXPECT_CALL(
mock_mainloop,
addRecurringRoutine(I_MainLoop::RoutineType::Timer, chrono::microseconds(5000000), _, _, false))
.WillOnce(DoAll(SaveArg<2>(&routine), Return(1))
);
EXPECT_CALL(mock_tools, readFile(file_path)).WillOnce(Return(start_file_content));
orchestration_status.init();
}
string
orchestrationStatusFileToString()
{
routine();
ifstream status_file(file_path);
stringstream string_stream;
if (status_file.is_open()) {
string line;
bool is_first_line = true;
while (getline(status_file, line)) {
if (is_first_line) {
is_first_line = false;
} else {
string_stream << endl;
}
string_stream << line;
}
status_file.close();
}
return string_stream.str();
}
string
buildOrchestrationStatusJSON(
const string &last_update_attempt = "None",
const string &last_update_status = "None",
const string &last_update = "None",
const string &last_manifest_update = "None",
const string &policy_version = "",
const string &last_policy_update = "None",
const string &last_settings_update = "None",
const string &upgrade_mode = "None",
const string &fog_address = "None",
const string &registration_status = "None",
const string &manifest_status = "None",
const string &registration_details_name = "",
const string &registration_details_type = "",
const string &registration_details_platform = "",
const string &registration_details_architecture = "",
const string &agent_id = "None",
const string &profile_id = "None",
const string &tenant_id = "None"
)
{
return "{\n"
" \"Last update attempt\": \"" + last_update_attempt + "\",\n"
" \"Last update status\": \"" + last_update_status + "\",\n"
" \"Last update\": \"" + last_update + "\",\n"
" \"Last manifest update\": \"" + last_manifest_update + "\",\n"
" \"Policy version\": \"" + policy_version + "\",\n"
" \"Last policy update\": \"" + last_policy_update + "\",\n"
" \"Last settings update\": \"" + last_settings_update + "\",\n"
" \"Upgrade mode\": \"" + upgrade_mode + "\",\n"
" \"Fog address\": \"" + fog_address + "\",\n"
" \"Registration status\": \"" + registration_status + "\",\n"
" \"Registration details\": {\n"
" \"Name\": \"" + registration_details_name + "\",\n"
" \"Type\": \"" + registration_details_type + "\",\n"
" \"Platform\": \"" + registration_details_platform + "\",\n"
" \"Architecture\": \"" + registration_details_architecture + "\"\n"
" },\n"
" \"Agent ID\": \"" + agent_id + "\",\n"
" \"Profile ID\": \"" + profile_id + "\",\n"
" \"Tenant ID\": \"" + tenant_id + "\",\n"
" \"Manifest status\": \"" + manifest_status + "\",\n"
" \"Service policy\": {},\n"
" \"Service settings\": {}\n"
"}";
}
::Environment env;
ConfigComponent config;
StrictMock<MockTimeGet> time;
StrictMock<MockMainLoop> mock_mainloop;
ostringstream capture_debug;
StrictMock<MockOrchestrationTools> mock_tools;
StrictMock<MockAgentDetails> mock_agent_details;
OrchestrationStatus orchestration_status;
I_OrchestrationStatus * i_orchestration_status =
Singleton::Consume<I_OrchestrationStatus>::from(orchestration_status);
string file_path;
Maybe<string> start_file_content = genError("No file");
I_MainLoop::Routine routine;
};
TEST_F(OrchestrationStatusTest, doNothing)
{
}
TEST_F(OrchestrationStatusTest, noFieldsValues)
{
init();
auto result = orchestrationStatusFileToString();
EXPECT_EQ(buildOrchestrationStatusJSON(), result);
}
TEST_F(OrchestrationStatusTest, recoverFields)
{
init();
auto result = orchestrationStatusFileToString();
i_orchestration_status->recoverFields();
EXPECT_EQ(orchestrationStatusFileToString(), result);
}
TEST_F(OrchestrationStatusTest, loadFromFile)
{
Maybe<string> status = genError("No file");;
CPTestTempfile status_file;
file_path = status_file.fname;
setConfiguration(file_path, "orchestration", "Orchestration status path");
// Write to file routine
EXPECT_CALL(
mock_mainloop,
addRecurringRoutine(I_MainLoop::RoutineType::Timer, chrono::microseconds(5000000), _, _, false)
).Times(3).WillRepeatedly(DoAll(SaveArg<2>(&routine), Return(1)));
EXPECT_CALL(mock_tools, readFile(file_path)).Times(3).WillRepeatedly(Return(status));
orchestration_status.init();
status = orchestrationStatusFileToString();
orchestration_status.init();
EXPECT_EQ(orchestrationStatusFileToString(), status.unpack());
EXPECT_CALL(time, getLocalTimeStr())
.WillOnce(Return(string("attempt time")))
.WillOnce(Return(string("current time")));
i_orchestration_status->setLastUpdateAttempt();
i_orchestration_status->setFieldStatus(
OrchestrationStatusFieldType::LAST_UPDATE,
OrchestrationStatusResult::SUCCESS
);
status = orchestrationStatusFileToString();
EXPECT_EQ(buildOrchestrationStatusJSON("attempt time", "Succeeded ", "current time"), status.unpack());
// Write status to file
routine();
// Reload status from file and validate status
orchestration_status.init();
EXPECT_EQ(buildOrchestrationStatusJSON("attempt time", "Succeeded ", "current time"), status.unpack());
}
TEST_F(OrchestrationStatusTest, checkUpdateStatus)
{
init();
EXPECT_CALL(time, getLocalTimeStr())
.WillOnce(Return(string("attempt time")))
.WillOnce(Return(string("current time")));
i_orchestration_status->setLastUpdateAttempt();
i_orchestration_status->setFieldStatus(
OrchestrationStatusFieldType::LAST_UPDATE,
OrchestrationStatusResult::SUCCESS
);
auto result = orchestrationStatusFileToString();
EXPECT_EQ(buildOrchestrationStatusJSON("attempt time", "Succeeded ", "current time"), result);
}
TEST_F(OrchestrationStatusTest, recoveryFields)
{
init();
CPTestTempfile status({""});
setConfiguration(status.fname, "orchestration", "Orchestration status path");
i_orchestration_status->setFieldStatus(
OrchestrationStatusFieldType::REGISTRATION,
OrchestrationStatusResult::SUCCESS
);
const string agent_id = "AgentId";
const string profile_id = "ProfileId";
const string tenant_id = "TenantId";
auto fog_addr = Maybe<string>(string("FogDomain"));
EXPECT_CALL(mock_agent_details, getAgentId()).WillOnce(Return(agent_id));
EXPECT_CALL(mock_agent_details, getProfileId()).WillOnce(Return(profile_id));
EXPECT_CALL(mock_agent_details, getTenantId()).WillOnce(Return(tenant_id));
EXPECT_CALL(mock_agent_details, getFogDomain()).WillOnce(Return(fog_addr));
i_orchestration_status->writeStatusToFile();
EXPECT_THAT(capture_debug.str(), HasSubstr("Repairing status fields"));
EXPECT_EQ(i_orchestration_status->getAgentId(), agent_id);
EXPECT_EQ(i_orchestration_status->getProfileId(), profile_id);
EXPECT_EQ(i_orchestration_status->getTenantId(), tenant_id);
EXPECT_EQ(i_orchestration_status->getFogAddress(), fog_addr.unpack());
}
TEST_F(OrchestrationStatusTest, updateAllLastUpdatesTypes)
{
init();
EXPECT_CALL(time, getLocalTimeStr())
.WillOnce(Return(string("attempt time")))
.WillOnce(Return(string("current time")))
.WillOnce(Return(string("current time001")));
i_orchestration_status->setLastUpdateAttempt();
i_orchestration_status->setFieldStatus(
OrchestrationStatusFieldType::LAST_UPDATE,
OrchestrationStatusResult::SUCCESS
);
i_orchestration_status->setIsConfigurationUpdated(
EnumArray<OrchestrationStatusConfigType, bool>(true, false, false)
);
auto result = orchestrationStatusFileToString();
EXPECT_EQ(buildOrchestrationStatusJSON("attempt time", "Succeeded ", "current time", "current time001"), result);
EXPECT_CALL(time, getLocalTimeStr())
.Times(2)
.WillRepeatedly(Return(string("current time002")));
i_orchestration_status->setFieldStatus(
OrchestrationStatusFieldType::LAST_UPDATE,
OrchestrationStatusResult::SUCCESS
);
i_orchestration_status->setIsConfigurationUpdated(
EnumArray<OrchestrationStatusConfigType, bool>(true, true, false)
);
result = orchestrationStatusFileToString();
EXPECT_EQ(
buildOrchestrationStatusJSON(
"attempt time",
"Succeeded ",
"current time002",
"current time002",
"",
"current time002"
),
result
);
EXPECT_CALL(time, getLocalTimeStr())
.Times(2)
.WillRepeatedly(Return(string("current time003")));
i_orchestration_status->setFieldStatus(
OrchestrationStatusFieldType::LAST_UPDATE,
OrchestrationStatusResult::SUCCESS
);
i_orchestration_status->setIsConfigurationUpdated(
EnumArray<OrchestrationStatusConfigType, bool>(true, true, true)
);
result = orchestrationStatusFileToString();
EXPECT_EQ(
buildOrchestrationStatusJSON(
"attempt time",
"Succeeded ",
"current time003",
"current time003",
"",
"current time003",
"current time003"
),
result
);
}
TEST_F(OrchestrationStatusTest, errorInRegistrationAndMainfest)
{
init();
string fog_address = "http://fog.address";
string registar_error = "Fail to registar";
string manifest_error = "Fail to achieve manifest";
string last_update_error = "Fail to update";
EXPECT_CALL(time, getLocalTimeStr()).Times(3).WillRepeatedly(Return(string("Time")));
i_orchestration_status->setFieldStatus(
OrchestrationStatusFieldType::LAST_UPDATE,
OrchestrationStatusResult::SUCCESS
);
i_orchestration_status->setIsConfigurationUpdated(
EnumArray<OrchestrationStatusConfigType, bool>(true, true, true)
);
i_orchestration_status->setFieldStatus(
OrchestrationStatusFieldType::LAST_UPDATE,
OrchestrationStatusResult::FAILED,
last_update_error
);
i_orchestration_status->setIsConfigurationUpdated(
EnumArray<OrchestrationStatusConfigType, bool>(false, false, false)
);
i_orchestration_status->setUpgradeMode("Online upgrades");
i_orchestration_status->setFogAddress(fog_address);
i_orchestration_status->setUpgradeMode("Online upgrades");
i_orchestration_status->setFogAddress(fog_address);
i_orchestration_status->setFieldStatus(
OrchestrationStatusFieldType::REGISTRATION,
OrchestrationStatusResult::FAILED,
registar_error
);
i_orchestration_status->setFieldStatus(
OrchestrationStatusFieldType::MANIFEST,
OrchestrationStatusResult::FAILED,
manifest_error
);
EXPECT_EQ(i_orchestration_status->getManifestError(), manifest_error);
auto result = orchestrationStatusFileToString();
EXPECT_EQ(
buildOrchestrationStatusJSON(
"None",
"Failed. Reason: " + last_update_error,
"Time",
"Time",
"",
"Time",
"Time",
"Online upgrades",
fog_address,
"Failed. Reason: " + registar_error,
"Failed. Reason: " + manifest_error
),
result
);
}
TEST_F(OrchestrationStatusTest, setAllFields)
{
init();
string fog_address = "http://fog.address";
EXPECT_CALL(time, getLocalTimeStr())
.Times(3)
.WillRepeatedly(Return(string("current time")));
i_orchestration_status->setFieldStatus(
OrchestrationStatusFieldType::LAST_UPDATE,
OrchestrationStatusResult::SUCCESS
);
i_orchestration_status->setIsConfigurationUpdated(
EnumArray<OrchestrationStatusConfigType, bool>(true, true, true)
);
i_orchestration_status->setRegistrationDetails("name", "type", "platform", "arch");
i_orchestration_status->setAgentDetails("id", "profile", "tenant");
i_orchestration_status->setFogAddress("http://fog.address");
i_orchestration_status->setPolicyVersion("12");
i_orchestration_status->setAgentType("test_type");
i_orchestration_status->setUpgradeMode("Test Mode");
i_orchestration_status->setRegistrationStatus("Succeeded");
i_orchestration_status->setFieldStatus(
OrchestrationStatusFieldType::REGISTRATION,
OrchestrationStatusResult::SUCCESS
);
i_orchestration_status->setFieldStatus(
OrchestrationStatusFieldType::MANIFEST,
OrchestrationStatusResult::SUCCESS
);
string non_empty_conf = "{x:y}";
string curr_mock_path = "path";
EXPECT_CALL(mock_tools, readFile(curr_mock_path)).WillRepeatedly(Return(non_empty_conf));
EXPECT_CALL(mock_tools, readFile(string("new_path"))).WillOnce(Return(string("{}")));
i_orchestration_status->setServiceConfiguration(
"service_a", "path", OrchestrationStatusConfigType::SETTINGS
);
i_orchestration_status->setServiceConfiguration(
"service_b", "path", OrchestrationStatusConfigType::POLICY
);
i_orchestration_status->setServiceConfiguration(
"service_c", "path", OrchestrationStatusConfigType::POLICY
);
i_orchestration_status->setServiceConfiguration(
"service_c", "new_path", OrchestrationStatusConfigType::POLICY
);
i_orchestration_status->setLastUpdateAttempt();
auto result = orchestrationStatusFileToString();
string expected = "{\n"
" \"Last update attempt\": \"current time\",\n"
" \"Last update status\": \"Succeeded \",\n"
" \"Last update\": \"current time\",\n"
" \"Last manifest update\": \"current time\",\n"
" \"Policy version\": \"12\",\n"
" \"Last policy update\": \"current time\",\n"
" \"Last settings update\": \"current time\",\n"
" \"Upgrade mode\": \"Test Mode\",\n"
" \"Fog address\": \"http://fog.address\",\n"
" \"Registration status\": \"Succeeded \",\n"
" \"Registration details\": {\n"
" \"Name\": \"name\",\n"
" \"Type\": \"test_type\",\n"
" \"Platform\": \"platform\",\n"
" \"Architecture\": \"arch\"\n"
" },\n"
" \"Agent ID\": \"id\",\n"
" \"Profile ID\": \"profile\",\n"
" \"Tenant ID\": \"tenant\",\n"
" \"Manifest status\": \"Succeeded \",\n"
" \"Service policy\": {\n"
" \"service_b\": \"path\"\n"
" },\n"
" \"Service settings\": {\n"
" \"service_a\": \"path\"\n"
" }\n"
"}";
EXPECT_EQ(expected, result);
// Now lets check load from file
routine();
EXPECT_EQ(expected, orchestrationStatusFileToString());
EXPECT_CALL(
mock_mainloop,
addRecurringRoutine(I_MainLoop::RoutineType::Timer, chrono::microseconds(5000000), _, _, false))
.WillOnce(DoAll(SaveArg<2>(&routine), Return(1)));
EXPECT_CALL(mock_tools, readFile(file_path)).Times(1).WillOnce(Return(expected));
orchestration_status.init();
EXPECT_EQ(expected, orchestrationStatusFileToString());
map<string, string> service_map_a = {{"service_a", "path"}};
map<string, string> service_map_b = {{"service_b", "path"}};
string agent_details =
"\n Name: name"
"\n Type: test_type"
"\n Platform: platform"
"\n Architecture: arch";
EXPECT_EQ(i_orchestration_status->getLastUpdateAttempt(), "current time");
EXPECT_EQ(i_orchestration_status->getUpdateStatus(), "Succeeded ");;
EXPECT_EQ(i_orchestration_status->getUpdateTime(), "current time");
EXPECT_EQ(i_orchestration_status->getLastManifestUpdate(), "current time");
EXPECT_EQ(i_orchestration_status->getPolicyVersion(), "12");
EXPECT_EQ(i_orchestration_status->getLastPolicyUpdate(), "current time");
EXPECT_EQ(i_orchestration_status->getLastSettingsUpdate(), "current time");
EXPECT_EQ(i_orchestration_status->getUpgradeMode(), "Test Mode");
EXPECT_EQ(i_orchestration_status->getFogAddress(), "http://fog.address");
EXPECT_EQ(i_orchestration_status->getRegistrationStatus(), "Succeeded ");
EXPECT_EQ(i_orchestration_status->getAgentId(), "id");
EXPECT_EQ(i_orchestration_status->getProfileId(), "profile");
EXPECT_EQ(i_orchestration_status->getTenantId(), "tenant");
EXPECT_EQ(i_orchestration_status->getManifestStatus(), "Succeeded ");
EXPECT_EQ(i_orchestration_status->getServicePolicies(), service_map_b);
EXPECT_EQ(i_orchestration_status->getServiceSettings(), service_map_a);
EXPECT_EQ(i_orchestration_status->getRegistrationDetails(), agent_details);
}

View File

@@ -0,0 +1,236 @@
#include "package.h"
#include "cptest.h"
#include "cereal/types/string.hpp"
#include "cereal/archives/json.hpp"
#include <string>
#include <memory>
#include <fstream>
using namespace testing;
using namespace std;
class PackageTest : public Test
{
public:
PackageTest() {}
bool
load(stringstream &string_stream, Package &package)
{
try {
cereal::JSONInputArchive archive_in(string_stream);
package.serialize(archive_in);
} catch (const cereal::Exception &) {
return false;
}
return true;
}
void
write(const string &path, Package &package)
{
std::ofstream os(path);
cereal::JSONOutputArchive archive_out(os);
package.serialize(archive_out);
}
string
readFile(const string &path)
{
ifstream text_file(path);
stringstream buffer;
buffer << text_file.rdbuf();
return buffer.str();
}
};
TEST_F(PackageTest, doNothing)
{
}
TEST_F(PackageTest, serializationFromString)
{
stringstream string_stream;
string_stream << "{"
" \"version\": \"c\","
" \"download-path\": \"https://a/install_orchestration.sh\",\n"
" \"relative-path\": \"/install_orchestration.sh\",\n"
" \"name\": \"orchestration\","
" \"checksum-type\": \"sha1sum\","
" \"checksum\": \"8d4a5709673a05b380ba7d6567e28910019118f5\","
" \"package-type\": \"service\","
" \"require\": []"
"}";
Package package;
EXPECT_EQ(true, load(string_stream, package));
vector<string> links = { "https://10.0.0.18/install_orchestration.sh", "ftp://172.23.92.135/policy.txt" };
EXPECT_EQ("orchestration", package.getName());
EXPECT_EQ(Package::ChecksumTypes::SHA1, package.getChecksumType());
EXPECT_EQ("8d4a5709673a05b380ba7d6567e28910019118f5", package.getChecksum());
EXPECT_EQ("orchestration", package.getName());
EXPECT_EQ("c", package.getVersion());
EXPECT_EQ(Package::PackageType::Service, package.getType());
EXPECT_TRUE(package.isInstallable().ok());
}
TEST_F(PackageTest, writeAsJson)
{
stringstream string_stream;
string_stream << "{\n"
" \"download-path\": \"https://a/install_orchestration.sh\",\n"
" \"relative-path\": \"/install_orchestration.sh\",\n"
" \"version\": \"c\",\n"
" \"name\": \"orchestration\",\n"
" \"checksum-type\": \"sha1sum\",\n"
" \"checksum\": \"8d4a5709673a05b380ba7d6567e28910019118f5\",\n"
" \"package-type\": \"service\"\n"
"}";
Package package;
EXPECT_EQ(true, load(string_stream, package));
vector<string> links = { "https://10.0.0.18/install_orchestration.sh", "ftp://172.23.92.135/policy.txt" };
EXPECT_EQ("orchestration", package.getName());
EXPECT_EQ(Package::ChecksumTypes::SHA1, package.getChecksumType());
EXPECT_EQ("8d4a5709673a05b380ba7d6567e28910019118f5", package.getChecksum());
EXPECT_EQ("orchestration", package.getName());
EXPECT_EQ("c", package.getVersion());
EXPECT_EQ(Package::PackageType::Service, package.getType());
EXPECT_TRUE(package.isInstallable().ok());
write("service.json", package);
string data = readFile("service.json");
EXPECT_EQ(string_stream.str(), data);
}
TEST_F(PackageTest, eqService)
{
stringstream string_stream;
string_stream << "{\n"
" \"download-path\": \"https://a/install_orchestration.sh\",\n"
" \"relative-path\": \"/install_orchestration.sh\",\n"
" \"version\": \"c\",\n"
" \"name\": \"orchestration\",\n"
" \"checksum-type\": \"sha1sum\",\n"
" \"checksum\": \"8d4a5709673a05b380ba7d6567e28910019118f5\",\n"
" \"package-type\": \"service\"\n"
"}";
Package package;
Package package2;
EXPECT_TRUE(load(string_stream, package));
string_stream.clear();
string_stream << "{\n"
" \"download-path\": \"https://a/install_orchestration.sh\",\n"
" \"relative-path\": \"/install_orchestration.sh\",\n"
" \"version\": \"c\",\n"
" \"name\": \"orchestration\",\n"
" \"checksum-type\": \"sha1sum\",\n"
" \"checksum\": \"8d4a5709673a05b380ba7d6567e28910000000000\",\n"
" \"package-type\": \"service\"\n"
"}";
EXPECT_TRUE(load(string_stream, package));
EXPECT_TRUE(package != package2);
}
TEST_F(PackageTest, changeDir)
{
stringstream string_stream;
string_stream << "{\n"
" \"download-path\": \"https://a/install_orchestration.sh\",\n"
" \"relative-path\": \"/install_orchestration.sh\",\n"
" \"version\": \"c\",\n"
" \"name\": \"../..\",\n"
" \"checksum-type\": \"sha1sum\",\n"
" \"checksum\": \"8d4a5709673a05b380ba7d6567e28910019118f5\",\n"
" \"package-type\": \"service\"\n"
"}";
Package package;
EXPECT_FALSE(load(string_stream, package));
}
TEST_F(PackageTest, mkdirCommand)
{
stringstream string_stream;
string_stream << "{\n"
" \"download-path\": \"https://a/install_orchestration.sh\",\n"
" \"relative-path\": \"/install_orchestration.sh\",\n"
" \"version\": \"c\",\n"
" \"name\": \"mkdir ../../something\",\n"
" \"checksum-type\": \"sha1sum\",\n"
" \"checksum\": \"8d4a5709673a05b380ba7d6567e28910019118f5\",\n"
" \"package-type\": \"service\"\n"
"}";
Package package;
EXPECT_FALSE(load(string_stream, package));
}
TEST_F(PackageTest, badPackageName)
{
stringstream string_stream;
string_stream << "{\n"
" \"download-path\": \"https://a/install_orchestration.sh\",\n"
" \"relative-path\": \"/install_orchestration.sh\",\n"
" \"version\": \"c\",\n"
" \"name\": \"- - - - - -\",\n"
" \"checksum-type\": \"sha1sum\",\n"
" \"checksum\": \"8d4a5709673a05b380ba7d6567e28910019118f5\",\n"
" \"package-type\": \"service\"\n"
"}";
Package package;
EXPECT_FALSE(load(string_stream, package));
}
TEST_F(PackageTest, anyOrder)
{
stringstream string_stream;
string_stream << "{\n"
" \"name\": \"asdQwe\",\n"
" \"relative-path\": \"/install_orchestration.sh\",\n"
" \"version\": \"c\",\n"
" \"download-path\": \"https://a/install_orchestration.sh\",\n"
" \"checksum\": \"8d4a5709673a05b380ba7d6567e28910019118f5\",\n"
" \"package-type\": \"service\",\n"
" \"checksum-type\": \"sha1sum\"\n"
"}";
Package package;
EXPECT_TRUE(load(string_stream, package));
}
TEST_F(PackageTest, anyOrderWithRequire)
{
stringstream string_stream;
string_stream << "{\n"
" \"require\": [],\n"
" \"name\": \"asdQwe\",\n"
" \"version\": \"c\",\n"
" \"relative-path\": \"/install_orchestration.sh\",\n"
" \"download-path\": \"https://a/install_orchestration.sh\",\n"
" \"checksum\": \"8d4a5709673a05b380ba7d6567e28910019118f5\",\n"
" \"package-type\": \"service\",\n"
" \"checksum-type\": \"sha1sum\"\n"
"}";
Package package;
EXPECT_TRUE(load(string_stream, package));
}
TEST_F(PackageTest, uninstallablePackage)
{
stringstream string_stream;
string_stream << "{\n"
" \"name\": \"waap\",\n"
" \"version\": \"\",\n"
" \"download-path\": \"\",\n"
" \"relative-path\": \"\",\n"
" \"checksum\": \"\",\n"
" \"package-type\": \"service\",\n"
" \"checksum-type\": \"sha1sum\",\n"
" \"status\": false,\n"
" \"message\": \"This security app isn't valid for this agent\"\n"
"}";
Package package;
EXPECT_TRUE(load(string_stream, package));
EXPECT_THAT(package.isInstallable(), IsError("This security app isn't valid for this agent"));
}

View File

@@ -0,0 +1,117 @@
#include "url_parser.h"
#include "cptest.h"
#include "mock/mock_orchestration_tools.h"
#include <string>
#include <memory>
using namespace testing;
using namespace std;
class URLParserTest : public Test
{
public:
URLParserTest() {}
StrictMock<MockOrchestrationTools> mock_orchestration_tools;
};
TEST_F(URLParserTest, doNothing)
{
}
TEST_F(URLParserTest, parseHTTP)
{
URLParser link("http://172.23.92.180:180/something");
EXPECT_FALSE(link.isOverSSL());
EXPECT_EQ("180", link.getPort());
EXPECT_EQ("/something", link.getQuery());
}
TEST_F(URLParserTest, parseHTTPS)
{
URLParser link("https://172.23.92.180:180/something");
EXPECT_TRUE(link.isOverSSL());
EXPECT_EQ("180", link.getPort());
EXPECT_EQ("/something", link.getQuery());
}
TEST_F(URLParserTest, parseAWS)
{
URLParser link("https://a58efa94efdf711e8a6540620a59b447-1878332922.eu-west-1.elb.amazonaws.com/");
EXPECT_TRUE(link.isOverSSL());
EXPECT_EQ("443", link.getPort());
EXPECT_EQ("a58efa94efdf711e8a6540620a59b447-1878332922.eu-west-1.elb.amazonaws.com", link.getBaseURL().unpack());
EXPECT_EQ("", link.getQuery());
}
TEST_F(URLParserTest, parseAWSWithoutSlash)
{
URLParser link("https://a58efa94efdf711e8a6540620a59b447-1878332922.eu-west-1.elb.amazonaws.com");
EXPECT_TRUE(link.isOverSSL());
EXPECT_EQ("443", link.getPort());
EXPECT_EQ("a58efa94efdf711e8a6540620a59b447-1878332922.eu-west-1.elb.amazonaws.com", link.getBaseURL().unpack());
EXPECT_EQ("", link.getQuery());
}
TEST_F(URLParserTest, protocolIsMissing)
{
// HTTPS is set by default when protocol is not present in URL.
URLParser link("a58efa94efdf711e8a6540620a59b447-1878332922.eu-west-1.elb.amazonaws.com");
EXPECT_EQ(link.getBaseURL().unpack(), "a58efa94efdf711e8a6540620a59b447-1878332922.eu-west-1.elb.amazonaws.com");
EXPECT_TRUE(link.isOverSSL());
EXPECT_EQ("443", link.getPort());
EXPECT_EQ("", link.getQuery());
}
TEST_F(URLParserTest, parseBadURL)
{
URLParser link("http://this_is_not_https_site.com/something");
EXPECT_FALSE(link.isOverSSL());
EXPECT_EQ("80", link.getPort());
EXPECT_EQ("this_is_not_https_site.com", link.getBaseURL().unpack());
EXPECT_EQ("/something", link.getQuery());
}
TEST_F(URLParserTest, parseNothing)
{
URLParser link("");
EXPECT_FALSE(link.getBaseURL().ok());
EXPECT_TRUE(link.isOverSSL());
EXPECT_EQ("443", link.getPort());
EXPECT_EQ("", link.getQuery());
}
TEST_F(URLParserTest, copyCtr)
{
URLParser link("");
URLParser copy_link = link;
EXPECT_TRUE(copy_link.isOverSSL());
EXPECT_EQ("443", copy_link.getPort());
EXPECT_EQ("", copy_link.getQuery());
}
TEST_F(URLParserTest, printTest)
{
string url_path = "this_is_test_url";
URLParser link(url_path);
EXPECT_EQ("https://" + url_path + ":443", link.toString());
stringstream ss;
ss << link;
EXPECT_EQ("https://" + url_path + ":443", ss.str());
}
TEST_F(URLParserTest, setQuery)
{
string url_path = "this_is_test_url/test.sh";
URLParser link(url_path);
EXPECT_EQ("https://" + url_path + ":443", link.toString());
link.setQuery("/new-query");
EXPECT_EQ("https://this_is_test_url/new-query:443", link.toString());
}

View File

@@ -0,0 +1,64 @@
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "orchestration_policy.h"
#include "sasal.h"
SASAL_START // Orchestration - Modules
using namespace std;
using namespace cereal;
const string &
OrchestrationPolicy::getFogAddress() const
{
return fog_address;
}
const unsigned long &
OrchestrationPolicy::getSleepInterval() const
{
return sleep_interval;
}
const unsigned long &
OrchestrationPolicy::getErrorSleepInterval() const
{
return error_sleep_interval;
}
void
OrchestrationPolicy::serialize(JSONInputArchive &archive)
{
// Split it, so the order doesn't matter.
archive(make_nvp("fog-address", fog_address));
archive(make_nvp("pulling-interval", sleep_interval));
archive(make_nvp("error-pulling-interval", error_sleep_interval));
}
bool
OrchestrationPolicy::operator==(const OrchestrationPolicy &other) const
{
return error_sleep_interval == other.error_sleep_interval &&
sleep_interval == other.sleep_interval &&
fog_address == other.fog_address;
}
bool
OrchestrationPolicy::operator!=(const OrchestrationPolicy &other) const
{
return !((*this) == other);
}
SASAL_END

View File

@@ -0,0 +1,685 @@
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "orchestration_status.h"
#include <string>
#include <chrono>
#include <algorithm>
#include "debug.h"
#include "config.h"
#include "sasal.h"
using namespace cereal;
using namespace std;
using namespace chrono;
USE_DEBUG_FLAG(D_ORCHESTRATOR);
SASAL_START // Orchestration - Modules
class RegistrationDetails
{
public:
RegistrationDetails() = default;
RegistrationDetails(const RegistrationDetails &) = default;
RegistrationDetails(RegistrationDetails &&) = default;
RegistrationDetails(
string name,
string type,
string platform,
string architecture)
:
name(name),
type(type),
platform(platform),
architecture(architecture)
{}
void
serialize(cereal::JSONOutputArchive &archive)
{
if (type == "InfinityNextGateway") {
type = "AppSecGateway";
}
archive(
cereal::make_nvp("Name", name),
cereal::make_nvp("Type", type),
cereal::make_nvp("Platform", platform),
cereal::make_nvp("Architecture", architecture)
);
}
void
serialize(cereal::JSONInputArchive &archive)
{
archive(
cereal::make_nvp("Name", name),
cereal::make_nvp("Type", type),
cereal::make_nvp("Platform", platform),
cereal::make_nvp("Architecture", architecture)
);
if (type == "InfinityNextGateway") {
type = "AppSecGateway";
}
}
RegistrationDetails & operator=(const RegistrationDetails &) = default;
RegistrationDetails & operator=(RegistrationDetails &&) = default;
void setAgentType(const string &_type) { type = _type; }
string
toString() const
{
return
"\n Name: " + name +
"\n Type: " + type +
"\n Platform: " + platform +
"\n Architecture: " + architecture;
}
private:
string name;
string type;
string platform;
string architecture;
};
class Status
{
public:
Status() = default;
Status(const Status &) = default;
Status(Status &&) = default;
Status & operator=(Status &&from) = default;
Status & operator=(const Status &from)
{
last_update_status = from.last_update_status;
last_update_time = from.last_update_time;
last_update_attempt = from.last_update_attempt;
last_manifest_update = from.last_manifest_update;
policy_version = from.policy_version;
last_policy_update = from.last_policy_update;
last_settings_update = from.last_settings_update;
upgrade_mode = from.upgrade_mode;
fog_address = from.fog_address;
registration_status = from.registration_status;
manifest_status = from.manifest_status;
agent_id = from.agent_id;
profile_id = from.profile_id;
tenant_id = from.tenant_id;
registration_details = from.registration_details;
service_policies = from.service_policies;
service_settings = from.service_settings;
return *this;
}
const string & getLastUpdateAttempt() const { return last_update_attempt; }
const string & getUpdateStatus() const { return last_update_status; }
const string & getUpdateTime() const { return last_update_time; }
const string & getLastManifestUpdate() const { return last_manifest_update; }
const string & getPolicyVersion() const { return policy_version; }
const string & getLastPolicyUpdate() const { return last_policy_update; }
const string & getLastSettingsUpdate() const { return last_settings_update; }
const string & getUpgradeMode() const { return upgrade_mode; }
const string & getFogAddress() const { return fog_address; }
const string & getRegistrationStatus() const { return registration_status; }
const string & getAgentId() const { return agent_id; }
const string & getProfileId() const { return profile_id; }
const string & getTenantId() const { return tenant_id; }
const string & getManifestStatus() const { return manifest_status; }
const string & getManifestError() const { return manifest_error; }
const RegistrationDetails & getRegistrationDetails() const { return registration_details; }
const map<string, string> & getServicePolicies() const { return service_policies; }
const map<string, string> & getServiceSettings() const { return service_settings; }
void
insertServicePolicy(const string &key, const string &value)
{
service_policies.insert(make_pair(key, value));
}
void
eraseServicePolicy(const string &key)
{
service_policies.erase(key);
}
void
insertServiceSetting(const string &key, const string &value)
{
service_settings.insert(make_pair(key, value));
}
void
eraseServiceSetting(const string &key)
{
service_settings.erase(key);
}
void
setIsConfigurationUpdated(
EnumArray<OrchestrationStatusConfigType, bool> config_types,
const string &current_time
)
{
if (config_types[OrchestrationStatusConfigType::MANIFEST]) last_manifest_update = current_time;
if (config_types[OrchestrationStatusConfigType::POLICY]) last_policy_update = current_time;
if (config_types[OrchestrationStatusConfigType::SETTINGS]) last_settings_update = current_time;
}
void
setPolicyVersion(const string &_policy_version)
{
policy_version = _policy_version;
}
void
setRegistrationStatus(const string &_reg_status)
{
registration_status = _reg_status;
}
void
setUpgradeMode(const string &_upgrade_mode)
{
upgrade_mode = _upgrade_mode;
}
void
setAgentType(const string &_agent_type)
{
registration_details.setAgentType(_agent_type);
}
void
setAgentDetails(
const string &_agent_id,
const string &_profile_id,
const string &_tenant_id)
{
agent_id = _agent_id;
profile_id = _profile_id;
tenant_id = _tenant_id;
}
void
setLastUpdateAttempt(const string &_last_update_attempt)
{
last_update_attempt = _last_update_attempt;
}
void
setFogAddress(const string &_fog_address)
{
fog_address = _fog_address;
}
void
setRegistrationDetails(
const string &name,
const string &type,
const string &platform,
const string &arch)
{
registration_details = RegistrationDetails(name, type, platform, arch);
}
void
setManifestStatus(const string &_manifest_status)
{
manifest_status = _manifest_status;
}
void
setManifestError(const string &error)
{
manifest_error = error;
}
void
setLastUpdateTime(const string &_last_update_time)
{
last_update_time = _last_update_time;
}
void
setLastUpdateStatus(const string &_last_update_status)
{
last_update_status = _last_update_status;
}
void
initValues()
{
last_update_attempt = "None";
last_update_time = "None";
last_update_status = "None";
last_manifest_update = "None";
last_policy_update = "None";
last_settings_update = "None";
fog_address = "None";
agent_id = "None";
profile_id = "None";
tenant_id = "None";
registration_status = "None";
manifest_status = "None";
upgrade_mode = "None";
}
void
recoverFields()
{
auto success_status = "Succeeded";
if (fog_address == "None" && registration_status.find(success_status) != string::npos) {
auto agent_details = Singleton::Consume<I_AgentDetails>::by<OrchestrationStatus>();
dbgWarning(D_ORCHESTRATOR) << "Repairing status fields";
agent_id = agent_details->getAgentId();
profile_id = agent_details->getProfileId();
tenant_id = agent_details->getTenantId();
auto maybe_fog_domain = agent_details->getFogDomain();
if (maybe_fog_domain.ok()) {
fog_address = maybe_fog_domain.unpack();
} else {
fog_address = "None";
}
}
}
void
serialize(cereal::JSONOutputArchive &archive)
{
recoverFields();
archive(cereal::make_nvp("Last update attempt", last_update_attempt));
archive(cereal::make_nvp("Last update status", last_update_status));
archive(cereal::make_nvp("Last update", last_update_time));
archive(cereal::make_nvp("Last manifest update", last_manifest_update));
archive(cereal::make_nvp("Policy version", policy_version));
archive(cereal::make_nvp("Last policy update", last_policy_update));
archive(cereal::make_nvp("Last settings update", last_settings_update));
archive(cereal::make_nvp("Upgrade mode", upgrade_mode));
archive(cereal::make_nvp("Fog address", fog_address));
archive(cereal::make_nvp("Registration status", registration_status));
archive(cereal::make_nvp("Registration details", registration_details));
archive(cereal::make_nvp("Agent ID", agent_id));
archive(cereal::make_nvp("Profile ID", profile_id));
archive(cereal::make_nvp("Tenant ID", tenant_id));
archive(cereal::make_nvp("Manifest status", manifest_status));
archive(cereal::make_nvp("Service policy", service_policies));
archive(cereal::make_nvp("Service settings", service_settings));
}
void
serialize(cereal::JSONInputArchive &archive)
{
archive(cereal::make_nvp("Last update attempt", last_update_attempt));
archive(cereal::make_nvp("Last update status", last_update_status));
archive(cereal::make_nvp("Last update", last_update_time));
archive(cereal::make_nvp("Last manifest update", last_manifest_update));
try {
archive(cereal::make_nvp("Policy version", policy_version));
} catch (...) {
archive.setNextName(nullptr);
}
archive(cereal::make_nvp("Last policy update", last_policy_update));
archive(cereal::make_nvp("Last settings update", last_settings_update));
// Optional param (upgrade - new parameter)
bool is_upgrade_mode = false;
try {
archive(cereal::make_nvp("Upgrade mode", upgrade_mode));
is_upgrade_mode = true;
} catch (...) {
archive.setNextName(nullptr);
}
if (!is_upgrade_mode) {
try {
archive(cereal::make_nvp("Update mode", upgrade_mode));
} catch (...) {
archive.setNextName(nullptr);
}
}
archive(cereal::make_nvp("Fog address", fog_address));
archive(cereal::make_nvp("Registration status", registration_status));
archive(cereal::make_nvp("Registration details", registration_details));
archive(cereal::make_nvp("Agent ID", agent_id));
archive(cereal::make_nvp("Profile ID", profile_id));
archive(cereal::make_nvp("Tenant ID", tenant_id));
archive(cereal::make_nvp("Manifest status", manifest_status));
archive(cereal::make_nvp("Service policy", service_policies));
archive(cereal::make_nvp("Service settings", service_settings));
}
private:
string last_update_time;
string last_update_status;
string last_update_attempt;
string last_manifest_update;
string policy_version;
string last_policy_update;
string last_settings_update;
string upgrade_mode;
string fog_address;
string registration_status;
string manifest_status;
string manifest_error;
string agent_id;
string profile_id;
string tenant_id;
RegistrationDetails registration_details;
map<string, string> service_policies;
map<string, string> service_settings;
};
class OrchestrationStatus::Impl : Singleton::Provide<I_OrchestrationStatus>::From<OrchestrationStatus>
{
public:
void
writeStatusToFile()
{
auto orchestrations_status_path = getConfigurationWithDefault<string>(
filesystem_prefix + "/conf/orchestrations_status.json",
"orchestration",
"Orchestration status path"
);
auto write_result =
orchestration_tools->objectToJsonFile<Status>(status, orchestrations_status_path);
if (!write_result) {
dbgWarning(D_ORCHESTRATOR) << "Failed to write Orchestration status. File: " << orchestrations_status_path;
}
dbgTrace(D_ORCHESTRATOR) << "Orchestration status file has been updated. File: " << orchestrations_status_path;
}
void
recoverFields() override
{
status.recoverFields();
}
void
setServiceConfiguration(
const string &service_name,
const string &path,
const OrchestrationStatusConfigType &configuration_file_type
)
{
if (shouldPolicyStatusBeIgnored(service_name, path)) return;
switch (configuration_file_type) {
case OrchestrationStatusConfigType::POLICY:
status.insertServicePolicy(service_name, path);
return;
case OrchestrationStatusConfigType::SETTINGS:
status.insertServiceSetting(service_name, path);
return;
case OrchestrationStatusConfigType::MANIFEST:
dbgAssert(false) << "Manifest is not a service configuration file type";
break;
case OrchestrationStatusConfigType::DATA:
return;
case OrchestrationStatusConfigType::COUNT:
break;
}
dbgAssert(false) << "Unknown configuration file type";
}
void
init()
{
time = Singleton::Consume<I_TimeGet>::by<OrchestrationStatus>();
orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<OrchestrationStatus>();
initValues();
loadFromFile();
filesystem_prefix = getFilesystemPathConfig();
dbgTrace(D_ORCHESTRATOR)
<< "Initializing Orchestration status, file system path prefix: "
<< filesystem_prefix;
map<string, string> service_policies_copy = status.getServicePolicies();
for (const pair<string, string> &policy: service_policies_copy) {
setServiceConfiguration(policy.first, policy.second, OrchestrationStatusConfigType::POLICY);
}
auto mainloop = Singleton::Consume<I_MainLoop>::by<OrchestrationStatus>();
mainloop->addRecurringRoutine(
I_MainLoop::RoutineType::Timer,
seconds(5),
[this] ()
{
dbgTrace(D_ORCHESTRATOR) << "Write Orchestration status file <co-routine>";
writeStatusToFile();
},
"Write Orchestration status file"
);
}
private:
void initValues();
bool shouldPolicyStatusBeIgnored(const string &service_name, const string &path);
void
loadFromFile()
{
auto orchestrations_status_path = getConfigurationWithDefault<string>(
filesystem_prefix + "/conf/orchestrations_status.json",
"orchestration",
"Orchestration status path"
);
Maybe<Status> maybe_status_file =
orchestration_tools->jsonFileToObject<Status>(orchestrations_status_path);
if (!maybe_status_file.ok()) {
dbgTrace(D_ORCHESTRATOR)
<< "Failed to load Orchestration status, start with clear status."
<< " Error: " << maybe_status_file.getErr();
return;
}
status = maybe_status_file.unpack();
dbgInfo(D_ORCHESTRATOR) << "Orchestration status loaded from file." << " File: " << orchestrations_status_path;
}
const string & getLastUpdateAttempt() const override { return status.getLastUpdateAttempt(); }
const string & getUpdateStatus() const override { return status.getUpdateStatus(); }
const string & getUpdateTime() const override { return status.getUpdateTime(); }
const string & getLastManifestUpdate() const override { return status.getLastManifestUpdate(); }
const string & getPolicyVersion() const override { return status.getPolicyVersion(); }
const string & getLastPolicyUpdate() const override { return status.getLastPolicyUpdate(); }
const string & getLastSettingsUpdate() const override { return status.getLastSettingsUpdate(); }
const string & getUpgradeMode() const override { return status.getUpgradeMode(); }
const string & getFogAddress() const override { return status.getFogAddress(); }
const string & getRegistrationStatus() const override { return status.getRegistrationStatus(); }
const string & getAgentId() const override { return status.getAgentId(); }
const string & getProfileId() const override { return status.getProfileId(); }
const string & getTenantId() const override { return status.getTenantId(); }
const string & getManifestStatus() const override { return status.getManifestStatus(); }
const string & getManifestError() const override { return status.getManifestError(); }
const string getRegistrationDetails() const override { return status.getRegistrationDetails().toString(); }
const map<string, string> & getServicePolicies() const override { return status.getServicePolicies(); }
const map<string, string> & getServiceSettings() const override { return status.getServiceSettings(); }
void
setIsConfigurationUpdated(EnumArray<OrchestrationStatusConfigType, bool> config_types) override
{
status.setIsConfigurationUpdated(config_types, time->getLocalTimeStr());
}
void
setPolicyVersion(const string &_policy_version) override
{
status.setPolicyVersion(_policy_version);
}
void
setRegistrationStatus(const string &_reg_status) override
{
status.setRegistrationStatus(_reg_status);
}
void
setUpgradeMode(const string &_upgrade_mode) override
{
status.setUpgradeMode(_upgrade_mode);
}
void
setAgentType(const string &_agent_type) override
{
status.setAgentType(_agent_type);
}
void
setAgentDetails(
const string &_agent_id,
const string &_profile_id,
const string &_tenant_id) override
{
status.setAgentDetails(_agent_id, _profile_id, _tenant_id);
}
void
setLastUpdateAttempt() override
{
status.setLastUpdateAttempt(time->getLocalTimeStr());
}
void
setFogAddress(const string &_fog_address) override
{
status.setFogAddress(_fog_address);
}
void
setFieldStatus(
const OrchestrationStatusFieldType &field_type_status,
const OrchestrationStatusResult &status_result,
const string &failure_reason) override
{
string field_value = status_string_map.at(status_result) + " " + failure_reason;
switch (field_type_status) {
case OrchestrationStatusFieldType::REGISTRATION:
status.setRegistrationStatus(field_value);
return;
case OrchestrationStatusFieldType::MANIFEST:
status.setManifestStatus(field_value);
status.setManifestError(failure_reason);
return;
case OrchestrationStatusFieldType::LAST_UPDATE:
if (status_result == OrchestrationStatusResult::SUCCESS) {
status.setLastUpdateTime(time->getLocalTimeStr());
}
if (status.getUpdateStatus() != field_value) {
writeStatusToFile();
}
status.setLastUpdateStatus(field_value);
return;
case OrchestrationStatusFieldType::COUNT:
break;
}
}
void
setRegistrationDetails(
const string &name,
const string &type,
const string &platform,
const string &arch) override
{
status.setRegistrationDetails(name, type, platform, arch);
}
OrchestrationStatus::Impl & operator=(OrchestrationStatus::Impl &&from) = default;
OrchestrationStatus::Impl & operator=(const OrchestrationStatus::Impl &from) = default;
const map<OrchestrationStatusResult, string> status_string_map = {
{ OrchestrationStatusResult::SUCCESS, "Succeeded" },
{ OrchestrationStatusResult::FAILED, "Failed. Reason:" }
};
Status status;
I_TimeGet *time;
I_OrchestrationTools *orchestration_tools;
string filesystem_prefix;
};
void
OrchestrationStatus::Impl::initValues()
{
status.initValues();
}
bool
OrchestrationStatus::Impl::shouldPolicyStatusBeIgnored(
const string &service_name,
const string &path)
{
vector<string> default_status_ingored_policies = {
"rules",
"zones",
"triggers",
"parameters",
"orchestration",
"webUserResponse",
"kubernetescalico",
"activeContextConfig"
};
auto status_ingored_policies = getSettingWithDefault<vector<string>>(
default_status_ingored_policies,
"orchestration",
"Orchestration status ignored policies"
);
auto config_content = orchestration_tools->readFile(path);
if (!config_content.ok() || config_content.unpack().empty()) {
dbgDebug(D_ORCHESTRATOR) << "Can not read the policy for " << service_name;
return true;
}
auto find_exist_iterator = status.getServicePolicies().find(service_name);
auto find_ignored_iterator = find(status_ingored_policies.begin(), status_ingored_policies.end(), service_name);
if (config_content.unpack() == "{}") {
dbgDebug(D_ORCHESTRATOR) << "Skipping status print for an empty policy file. Policy name: " << service_name;
if (find_exist_iterator != status.getServicePolicies().end()) {
status.eraseServicePolicy(service_name);
}
return true;
} else if (find_ignored_iterator != status_ingored_policies.end()) {
dbgDebug(D_ORCHESTRATOR)
<< "Skipping status print for the policy from a list of ignored policies. Policy name: "
<< service_name;
if (find_exist_iterator != status.getServicePolicies().end()) {
status.eraseServicePolicy(service_name);
}
return true;
}
return false;
}
void
OrchestrationStatus::init() { pimpl->init(); }
OrchestrationStatus::OrchestrationStatus() : Component("OrchestrationStatus"), pimpl(make_unique<Impl>()) {}
OrchestrationStatus::~OrchestrationStatus() {}
SASAL_END

View File

@@ -0,0 +1,133 @@
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "package.h"
#include <map>
#include "sasal.h"
SASAL_START // Orchestration - Modules
using namespace std;
using namespace cereal;
const map<string, Package::ChecksumTypes> checksumMap = {
{ "sha1sum", Package::ChecksumTypes::SHA1 },
{ "sha256sum", Package::ChecksumTypes::SHA256 },
{ "sha512sum", Package::ChecksumTypes::SHA512 },
{ "md5sum", Package::ChecksumTypes::MD5 },
};
const map<string, Package::PackageType> packageTypeMap = {
{ "service", Package::PackageType::Service },
{ "shared objects", Package::PackageType::SharedObject },
};
bool
Package::operator==(const Package &other) const
{
return checksum_type == other.getChecksumType() && checksum_value == other.getChecksum();
}
bool
Package::operator!=(const Package &other) const
{
return !((*this) == other);
}
void
Package::serialize(JSONOutputArchive & out_archive) const
{
string type = mapTypeToString<PackageType>(package_type, packageTypeMap);
string checksum_type_as_string = mapTypeToString<ChecksumTypes>(checksum_type, checksumMap);
out_archive(make_nvp("download-path", download_path));
out_archive(make_nvp("relative-path", relative_path));
out_archive(make_nvp("version", version));
out_archive(make_nvp("name", name));
out_archive(make_nvp("checksum-type", checksum_type_as_string));
out_archive(make_nvp("checksum", checksum_value));
out_archive(make_nvp("package-type", type));
if (require_packages.size() > 0) {
out_archive(make_nvp("require", require_packages));
}
if (!installable.ok()) {
out_archive(make_nvp("status", installable.ok()));
out_archive(make_nvp("message", installable.getErr()));
}
}
void
Package::serialize(JSONInputArchive & in_archive)
{
string type;
string checksum_type_as_string;
in_archive(make_nvp("download-path", download_path));
in_archive(make_nvp("version", version));
in_archive(make_nvp("name", name));
in_archive(make_nvp("checksum-type", checksum_type_as_string));
in_archive(make_nvp("checksum", checksum_value));
in_archive(make_nvp("package-type", type));
try {
in_archive(make_nvp("relative-path", relative_path));
} catch (...) {
in_archive.setNextName(nullptr);
}
try {
in_archive(make_nvp("require", require_packages));
} catch (...) {
in_archive.setNextName(nullptr);
}
bool is_installable = true;
try {
in_archive(make_nvp("status", is_installable));
} catch (...) {
in_archive.setNextName(nullptr);
}
if (!is_installable) {
string error_message;
try {
in_archive(make_nvp("message", error_message));
} catch (...) {
in_archive.setNextName(nullptr);
}
installable = genError(error_message);
}
for (auto &character : name) {
// Name Validation: should include only: decimal digit / letter / '.' / '_' / '-'
if (!isalnum(character) && character != '.' && character != '_' && character != '-') {
throw Exception(name + " is invalid package name");
}
}
auto checksum_type_value = checksumMap.find(checksum_type_as_string);
if (checksum_type_value == checksumMap.end()) {
throw Exception(checksum_type_as_string + " isn't a valid checksum type at " + name);
}
checksum_type = checksum_type_value->second;
auto package_type_value = packageTypeMap.find(type);
if (package_type_value == packageTypeMap.end()) {
throw Exception(checksum_type_as_string + " isn't a valid package type at " + name);
}
package_type = package_type_value->second;
}
SASAL_END

View File

@@ -0,0 +1,149 @@
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "url_parser.h"
#include <sstream>
#include "singleton.h"
#include "common.h"
#include "maybe_res.h"
#include "sasal.h"
using namespace std;
SASAL_START // Orchestration - Modules
USE_DEBUG_FLAG(D_ORCHESTRATOR);
ostream &
operator<<(ostream &os, const URLParser &url)
{
return os << url.toString();
}
ostream &
operator<<(ostream &os, const URLProtocol &protocol)
{
switch(protocol) {
case URLProtocol::HTTP: {
return os << "http://";
}
case URLProtocol::HTTPS: {
return os << "https://";
}
case URLProtocol::LOCAL_FILE: {
return os << "file://";
}
default: {
dbgAssert(false) << "Unsupported protocol " << static_cast<unsigned int>(protocol);
return os;
}
}
}
URLParser::URLParser(const string &url)
{
parseURL(url);
}
Maybe<string>
URLParser::getBaseURL() const
{
if (base_url.empty()) return genError("Error: URL not found");
return base_url;
}
void
URLParser::parseURL(const string &url)
{
string url_builder;
protocol = parseProtocol(url);
switch(protocol) {
case URLProtocol::HTTP: {
dbgDebug(D_ORCHESTRATOR) << "Protocol of " << url << " is HTTP";
port = "80";
over_ssl = false;
url_builder = url.substr(7);
break;
}
case URLProtocol::HTTPS: {
dbgDebug(D_ORCHESTRATOR) << "Protocol of " << url << " is HTTPS";
if (url.find("https://") != string::npos) {
url_builder = url.substr(8);
} else {
url_builder = url;
}
port = "443";
over_ssl = true;
break;
}
case URLProtocol::LOCAL_FILE: {
dbgDebug(D_ORCHESTRATOR) << "Protocol of " << url << " is local file.";
base_url = url.substr(7);
return;
}
default: {
dbgAssert(false) << "URL protocol is not supported. Protocol: " << static_cast<unsigned int>(protocol);
return;
}
}
size_t link_extension_position = url_builder.find_first_of("/");
if (link_extension_position != string::npos) {
query = url_builder.substr(link_extension_position);
url_builder = url_builder.substr(0, link_extension_position);
}
size_t port_position = url_builder.find_last_of(":");
string link = url_builder;
if (port_position != string::npos) {
link = url_builder.substr(0, port_position);
port = url_builder.substr(port_position + 1);
}
if (!link.empty()) base_url = link;
if (!query.empty() && query.back() == '/') query.pop_back();
}
URLProtocol
URLParser::parseProtocol(const string &url) const
{
if (url.find("http://") != string::npos) {
return URLProtocol::HTTP;
} else if (url.find("https://") != string::npos) {
return URLProtocol::HTTPS;
} else if (url.find("file://") != string::npos){
return URLProtocol::LOCAL_FILE;
}
dbgWarning(D_ORCHESTRATOR)
<< "No supported protocol in URL, HTTPS default value is used. URL: " << url;
return URLProtocol::HTTPS;
}
void
URLParser::setQuery(const string &new_query)
{
query = new_query;
}
string
URLParser::toString() const
{
stringstream s_build;
s_build << protocol << base_url << query << ":" << port;
return s_build.str();
}
SASAL_END