mirror of
https://github.com/openappsec/openappsec.git
synced 2025-09-29 11:16:30 +03:00
First release of open-appsec source code
This commit is contained in:
3
core/agent_details/CMakeLists.txt
Executable file
3
core/agent_details/CMakeLists.txt
Executable file
@@ -0,0 +1,3 @@
|
||||
add_library(agent_details agent_details.cc)
|
||||
|
||||
add_subdirectory(agent_details_ut)
|
307
core/agent_details/agent_details.cc
Executable file
307
core/agent_details/agent_details.cc
Executable file
@@ -0,0 +1,307 @@
|
||||
// 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 "agent_details.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "sasal.h"
|
||||
|
||||
SASAL_START // Orchestration - Communication
|
||||
|
||||
using namespace std;
|
||||
|
||||
USE_DEBUG_FLAG(D_ORCHESTRATOR);
|
||||
|
||||
const map<string, I_AgentDetails::MachineType> AgentDetails::machineTypes({
|
||||
{ "Amazon EC2", I_AgentDetails::MachineType::AWS },
|
||||
{ "Xen", I_AgentDetails::MachineType::AWS },
|
||||
{ "Microsoft Corporation", I_AgentDetails::MachineType::AZURE },
|
||||
{ "VMware, Inc.", I_AgentDetails::MachineType::ON_PREM }
|
||||
});
|
||||
|
||||
void
|
||||
AgentDetails::init()
|
||||
{
|
||||
registerMachineType();
|
||||
}
|
||||
|
||||
bool
|
||||
AgentDetails::readAgentDetails()
|
||||
{
|
||||
auto agent_details_path = getConfigurationWithDefault<string>(
|
||||
getFilesystemPathConfig() + "/conf/agent_details.json",
|
||||
"Agent details",
|
||||
"File path"
|
||||
);
|
||||
ifstream file(agent_details_path);
|
||||
if (!file.is_open()) {
|
||||
dbgWarning(D_ORCHESTRATOR) << "Agent details file does not exist. File: " << agent_details_path;
|
||||
return false;
|
||||
}
|
||||
|
||||
stringstream file_stream;
|
||||
try {
|
||||
file_stream << file.rdbuf();
|
||||
cereal::JSONInputArchive archive_in(file_stream);
|
||||
serialize(archive_in);
|
||||
} catch (exception &e) {
|
||||
dbgWarning(D_ORCHESTRATOR) << "Failed to parse agent details."
|
||||
<< " File: " << agent_details_path
|
||||
<< ", Error: " << e.what();
|
||||
return false;
|
||||
}
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
AgentDetails::writeAgentDetails()
|
||||
{
|
||||
auto agent_details_path = getConfigurationWithDefault<string>(
|
||||
getFilesystemPathConfig() + "/conf/agent_details.json",
|
||||
"Agent details",
|
||||
"File path"
|
||||
);
|
||||
|
||||
try {
|
||||
ofstream ostream(agent_details_path);
|
||||
cereal::JSONOutputArchive archive_out(ostream);
|
||||
serialize(archive_out);
|
||||
} catch (exception &e) {
|
||||
dbgWarning(D_ORCHESTRATOR) << "Failed to write the agent details."
|
||||
<< " File: " << agent_details_path
|
||||
<< ", Error: " << e.what();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
AgentDetails::serialize(cereal::JSONOutputArchive &ar)
|
||||
{
|
||||
ar(cereal::make_nvp("Fog domain", fog_domain));
|
||||
ar(cereal::make_nvp("Agent ID", agent_id));
|
||||
ar(cereal::make_nvp("Fog port", fog_port));
|
||||
ar(cereal::make_nvp("Tenant ID", tenant_id));
|
||||
ar(cereal::make_nvp("Profile ID", profile_id));
|
||||
ar(cereal::make_nvp("Encrypted connection", encrypted_connection));
|
||||
ar(cereal::make_nvp("OpenSSL certificates directory", openssl_dir));
|
||||
|
||||
try {
|
||||
ar(cereal::make_nvp("Proxy", proxy));
|
||||
} catch (...) {
|
||||
ar.setNextName(nullptr);
|
||||
}
|
||||
|
||||
try {
|
||||
ar(cereal::make_nvp("Cluster ID", cluster_id));
|
||||
} catch (...) {
|
||||
ar.setNextName(nullptr);
|
||||
}
|
||||
|
||||
try {
|
||||
static const EnumArray<OrchestrationMode, std::string> orchestraiton_mode_str {
|
||||
"online_mode",
|
||||
"offline_mode",
|
||||
"hybrid_mode"
|
||||
};
|
||||
std::string orchestraiton_mode_string = orchestraiton_mode_str[orchestration_mode];
|
||||
ar(cereal::make_nvp("Orchestration mode", orchestraiton_mode_string));
|
||||
|
||||
bool is_offline_mode = (orchestration_mode == OrchestrationMode::OFFLINE);
|
||||
ar(cereal::make_nvp("Is Offline Mode", is_offline_mode));
|
||||
} catch (...) {
|
||||
ar.setNextName(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AgentDetails::serialize(cereal::JSONInputArchive &ar)
|
||||
{
|
||||
ar(cereal::make_nvp("Fog domain", fog_domain));
|
||||
ar(cereal::make_nvp("Agent ID", agent_id));
|
||||
ar(cereal::make_nvp("Fog port", fog_port));
|
||||
ar(cereal::make_nvp("Tenant ID", tenant_id));
|
||||
ar(cereal::make_nvp("Profile ID", profile_id));
|
||||
ar(cereal::make_nvp("Encrypted connection", encrypted_connection));
|
||||
ar(cereal::make_nvp("OpenSSL certificates directory", openssl_dir));
|
||||
|
||||
try {
|
||||
ar(cereal::make_nvp("Proxy", proxy));
|
||||
} catch (...) {
|
||||
ar.setNextName(nullptr);
|
||||
}
|
||||
|
||||
try {
|
||||
ar(cereal::make_nvp("Cluster ID", cluster_id));
|
||||
if (!cluster_id.empty()) {
|
||||
Singleton::Consume<I_Environment>::by<AgentDetails>()->getConfigurationContext().registerValue<string>(
|
||||
"k8sClusterId",
|
||||
cluster_id,
|
||||
EnvKeyAttr::LogSection::SOURCE
|
||||
);
|
||||
}
|
||||
} catch (...) {
|
||||
ar.setNextName(nullptr);
|
||||
}
|
||||
|
||||
try {
|
||||
static const std::map<std::string, OrchestrationMode> orchestrationModeMap {
|
||||
{ "online_mode", OrchestrationMode::ONLINE },
|
||||
{ "offline_mode", OrchestrationMode::OFFLINE },
|
||||
{ "hybrid_mode", OrchestrationMode::HYBRID }
|
||||
};
|
||||
std::string orchestraiton_mode_string;
|
||||
ar(cereal::make_nvp("Orchestration mode", orchestraiton_mode_string));
|
||||
auto iter = orchestrationModeMap.find(orchestraiton_mode_string);
|
||||
if (iter != orchestrationModeMap.end()) {
|
||||
orchestration_mode = iter->second;
|
||||
}
|
||||
} catch (...) {
|
||||
try {
|
||||
bool is_offline_mode = false;
|
||||
ar(cereal::make_nvp("Is Offline Mode", is_offline_mode));
|
||||
if (is_offline_mode) {
|
||||
orchestration_mode = OrchestrationMode::OFFLINE;
|
||||
} else {
|
||||
orchestration_mode = OrchestrationMode::ONLINE;
|
||||
}
|
||||
} catch (...) {
|
||||
ar.setNextName(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string
|
||||
AgentDetails::getAgentId() const
|
||||
{
|
||||
static string default_agent_id = "Unknown";
|
||||
if (agent_id.empty()) return default_agent_id;
|
||||
return agent_id;
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
AgentDetails::getProxy() const
|
||||
{
|
||||
if (proxy == "") return genError("Proxy not set");
|
||||
return proxy;
|
||||
}
|
||||
|
||||
Maybe<uint16_t>
|
||||
AgentDetails::getFogPort() const
|
||||
{
|
||||
if (fog_port == 0) return genError("Fog port is unset");
|
||||
return fog_port;
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
AgentDetails::getFogDomain() const
|
||||
{
|
||||
if (fog_domain.empty()) return genError("Fog domain is unset");
|
||||
return fog_domain;
|
||||
}
|
||||
|
||||
void
|
||||
AgentDetails::setClusterId(const std::string &_cluster_id)
|
||||
{
|
||||
dbgTrace(D_ORCHESTRATOR) << "Setting Cluster Id in the agent details. Cluster ID: " << _cluster_id;
|
||||
cluster_id = _cluster_id;
|
||||
writeAgentDetails();
|
||||
}
|
||||
|
||||
void
|
||||
AgentDetails::preload()
|
||||
{
|
||||
registerExpectedConfiguration<string>("orchestration", "Agent details path");
|
||||
registerConfigLoadCb([this] () { readAgentDetails(); });
|
||||
}
|
||||
|
||||
string
|
||||
AgentDetails::getTenantId() const
|
||||
{
|
||||
return tenant_id;
|
||||
}
|
||||
|
||||
string
|
||||
AgentDetails::getProfileId() const
|
||||
{
|
||||
return profile_id;
|
||||
}
|
||||
|
||||
string
|
||||
AgentDetails::getClusterId() const
|
||||
{
|
||||
return cluster_id;
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
AgentDetails::getOpenSSLDir() const
|
||||
{
|
||||
if (openssl_dir.empty()) return genError("OpenSSL certificates directory was not set");
|
||||
return openssl_dir;
|
||||
}
|
||||
|
||||
OrchestrationMode
|
||||
AgentDetails::getOrchestrationMode() const
|
||||
{
|
||||
return orchestration_mode;
|
||||
}
|
||||
|
||||
Maybe<I_AgentDetails::MachineType>
|
||||
AgentDetails::getMachineTypeFromDmiTable()
|
||||
{
|
||||
static const string decode_machine_type_cmd = "dmidecode -s system-manufacturer | tr -d '\\n'";
|
||||
|
||||
I_ShellCmd *i_shell_cmd = Singleton::Consume<I_ShellCmd>::by<AgentDetails>();
|
||||
auto machine_type = i_shell_cmd->getExecOutput(decode_machine_type_cmd);
|
||||
if (!machine_type.ok()) {
|
||||
dbgWarning(D_ORCHESTRATOR) << "Error. Could not decode the DMI table. " << machine_type.getErr();
|
||||
return I_AgentDetails::MachineType::UNRECOGNIZED;
|
||||
} else if (machine_type.unpack().empty()) {
|
||||
dbgWarning(D_ORCHESTRATOR) << "Error. Could not decode the DMI table. Table value is empty";
|
||||
return I_AgentDetails::MachineType::UNRECOGNIZED;
|
||||
}
|
||||
|
||||
dbgInfo(D_ORCHESTRATOR) << "Decoded the DMI talble: " << machine_type.unpack();
|
||||
auto resolved_machine_type = machineTypes.find(*machine_type);
|
||||
if (resolved_machine_type == end(machineTypes)) return I_AgentDetails::MachineType::UNRECOGNIZED;
|
||||
|
||||
return resolved_machine_type->second;
|
||||
}
|
||||
|
||||
void
|
||||
AgentDetails::registerMachineType()
|
||||
{
|
||||
Maybe<I_AgentDetails::MachineType> machine_type = getMachineTypeFromDmiTable();
|
||||
if (!machine_type.ok()) {
|
||||
dbgWarning(D_ORCHESTRATOR)
|
||||
<< "Error. Could not get machine type from the DMI table. "
|
||||
<< machine_type.getErr();
|
||||
return;
|
||||
}
|
||||
if (machine_type.unpack() == I_AgentDetails::MachineType::UNRECOGNIZED) {
|
||||
dbgWarning(D_ORCHESTRATOR) << "Error. Machine type is unrecognized";
|
||||
}
|
||||
Singleton::Consume<I_Environment>::by<AgentDetails>()->registerValue<I_AgentDetails::MachineType>(
|
||||
"MachineType", machine_type.unpack()
|
||||
);
|
||||
dbgInfo(D_ORCHESTRATOR) << "Setting machine type " << static_cast<int>(machine_type.unpack());
|
||||
}
|
||||
|
||||
SASAL_END
|
9
core/agent_details/agent_details_ut/CMakeLists.txt
Normal file
9
core/agent_details/agent_details_ut/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
include_directories(${CMAKE_SOURCE_DIR}/components/include)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/cptest/include)
|
||||
link_directories(${BOOST_ROOT}/lib)
|
||||
|
||||
add_unit_test(
|
||||
agent_details_ut
|
||||
"agent_details_ut.cc"
|
||||
"singleton;config;agent_details;environment;metric;event_is;-lboost_regex"
|
||||
)
|
156
core/agent_details/agent_details_ut/agent_details_ut.cc
Normal file
156
core/agent_details/agent_details_ut/agent_details_ut.cc
Normal file
@@ -0,0 +1,156 @@
|
||||
#include "agent_details.h"
|
||||
|
||||
#include "mock/mock_encryptor.h"
|
||||
#include "mock/mock_shell_cmd.h"
|
||||
#include "cptest.h"
|
||||
#include "config.h"
|
||||
#include "config_component.h"
|
||||
#include "buffer.h"
|
||||
#include "cptest.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace testing;
|
||||
|
||||
class AgentDetailsTest : public Test
|
||||
{
|
||||
public:
|
||||
AgentDetailsTest()
|
||||
{
|
||||
config = Singleton::Consume<Config::I_Config>::from(conf);
|
||||
}
|
||||
|
||||
::Environment env;
|
||||
ConfigComponent conf;
|
||||
StrictMock<MockEncryptor> mock_encryptor;
|
||||
StrictMock<MockShellCmd> mock_shell_cmd;
|
||||
Config::I_Config *config = nullptr;
|
||||
};
|
||||
|
||||
TEST_F(AgentDetailsTest, doNothing)
|
||||
{
|
||||
}
|
||||
|
||||
TEST_F(AgentDetailsTest, basicTest)
|
||||
{
|
||||
const vector<string> agent_details_vec {
|
||||
"{",
|
||||
" \"Fog domain\": \"fog.com\",",
|
||||
" \"Agent ID\": \"fdfdf-5454-dfd\",",
|
||||
" \"Fog port\": 443,",
|
||||
" \"Encrypted connection\": false,",
|
||||
" \"Orchestration mode\": \"offline_mode\",",
|
||||
" \"Tenant ID\": \"tenant_id\",",
|
||||
" \"Profile ID\": \"profile\",",
|
||||
" \"Proxy\": \"http://proxy.checkpoint.com/\",",
|
||||
" \"OpenSSL certificates directory\": \"\"",
|
||||
"}"
|
||||
};
|
||||
AgentDetails agent_details;
|
||||
env.preload();
|
||||
agent_details.preload();
|
||||
EXPECT_CALL(
|
||||
mock_shell_cmd,
|
||||
getExecOutput("dmidecode -s system-manufacturer | tr -d '\\n'", _, _)
|
||||
).WillOnce(Return(string("Microsoft Corporation")));
|
||||
env.init();
|
||||
agent_details.init();
|
||||
|
||||
auto i_conf = Singleton::Consume<Config::I_Config>::from(conf);
|
||||
i_conf->reloadConfiguration();
|
||||
|
||||
CPTestTempfile agent_details_file(agent_details_vec);
|
||||
setConfiguration(agent_details_file.fname, "Agent details", "File path");
|
||||
|
||||
EXPECT_TRUE(agent_details.readAgentDetails());
|
||||
EXPECT_EQ(agent_details.getFogDomain().unpack(), "fog.com");
|
||||
EXPECT_EQ(agent_details.getFogPort().unpack(), 443);
|
||||
EXPECT_EQ(agent_details.getAgentId(), "fdfdf-5454-dfd");
|
||||
EXPECT_FALSE(agent_details.getSSLFlag());
|
||||
|
||||
agent_details.setSSLFlag(true);
|
||||
agent_details.setFogPort(80);
|
||||
agent_details.setFogDomain("fog.checkpoint.com");
|
||||
agent_details.setAgentId("dfdfdf-dfd");
|
||||
agent_details.setClusterId("d5bd7949-554e-4fac-86c3-6e4e5d46a034");
|
||||
EXPECT_EQ(agent_details.getFogDomain().unpack(), "fog.checkpoint.com");
|
||||
EXPECT_EQ(agent_details.getFogPort().unpack(), 80);
|
||||
EXPECT_EQ(agent_details.getAgentId(), "dfdfdf-dfd");
|
||||
EXPECT_EQ(agent_details.getTenantId(), "tenant_id");
|
||||
EXPECT_EQ(agent_details.getProfileId(), "profile");
|
||||
EXPECT_EQ(agent_details.getClusterId(), "d5bd7949-554e-4fac-86c3-6e4e5d46a034");
|
||||
|
||||
EXPECT_TRUE(agent_details.writeAgentDetails());
|
||||
|
||||
EXPECT_TRUE(agent_details.readAgentDetails());
|
||||
EXPECT_EQ(agent_details.getFogDomain().unpack(), "fog.checkpoint.com");
|
||||
EXPECT_EQ(agent_details.getFogPort().unpack(), 80);
|
||||
EXPECT_EQ(agent_details.getAgentId(), "dfdfdf-dfd");
|
||||
EXPECT_EQ(agent_details.getClusterId(), "d5bd7949-554e-4fac-86c3-6e4e5d46a034");
|
||||
EXPECT_TRUE(agent_details.getSSLFlag());
|
||||
EXPECT_THAT(agent_details.getProxy(), IsValue("http://proxy.checkpoint.com/"));
|
||||
agent_details.setProxy("none");
|
||||
EXPECT_THAT(agent_details.getProxy(), IsValue("none"));
|
||||
|
||||
EXPECT_TRUE(agent_details.getOrchestrationMode() == OrchestrationMode::OFFLINE);
|
||||
agent_details.setOrchestrationMode(OrchestrationMode::ONLINE);
|
||||
EXPECT_TRUE(agent_details.getOrchestrationMode() == OrchestrationMode::ONLINE);
|
||||
auto machine_type = Singleton::Consume<I_Environment>::from(env)->get<I_AgentDetails::MachineType>("MachineType");
|
||||
EXPECT_EQ(machine_type.unpack(), I_AgentDetails::MachineType::AZURE);
|
||||
}
|
||||
|
||||
TEST_F(AgentDetailsTest, openSSL)
|
||||
{
|
||||
const vector<string> agent_details_vec {
|
||||
"{",
|
||||
" \"Fog domain\": \"fog.com\",",
|
||||
" \"Agent ID\": \"fdfdf-5454-dfd\",",
|
||||
" \"Fog port\": 443,",
|
||||
" \"Encrypted connection\": false,",
|
||||
" \"Tenant ID\": \"tenant_id\",",
|
||||
" \"Profile ID\": \"profile\",",
|
||||
" \"OpenSSL certificates directory\": \"\"",
|
||||
"}"
|
||||
};
|
||||
|
||||
AgentDetails agent_details;
|
||||
agent_details.preload();
|
||||
|
||||
CPTestTempfile agent_details_file(agent_details_vec);
|
||||
setConfiguration(agent_details_file.fname, "Agent details", "File path");
|
||||
|
||||
EXPECT_FALSE(agent_details.getSSLFlag());
|
||||
EXPECT_THAT(agent_details.getOpenSSLDir(), IsError("OpenSSL certificates directory was not set"));
|
||||
|
||||
agent_details.setOpenSSLDir("a/b/c");
|
||||
EXPECT_THAT(agent_details.getOpenSSLDir(), IsValue("a/b/c"));
|
||||
|
||||
agent_details.setFogPort(10);
|
||||
agent_details.setSSLFlag(false);
|
||||
agent_details.setFogDomain("www.fog.checkpoint.com");
|
||||
agent_details.setOpenSSLDir("");
|
||||
|
||||
EXPECT_THAT(agent_details.getFogPort(), IsValue(10));
|
||||
EXPECT_FALSE(agent_details.getSSLFlag());
|
||||
EXPECT_THAT(agent_details.getFogDomain(), IsValue("www.fog.checkpoint.com"));
|
||||
EXPECT_THAT(agent_details.getOpenSSLDir(), IsError("OpenSSL certificates directory was not set"));
|
||||
|
||||
EXPECT_FALSE(agent_details.getOrchestrationMode() == OrchestrationMode::OFFLINE);
|
||||
agent_details.setOrchestrationMode(OrchestrationMode::OFFLINE);
|
||||
EXPECT_TRUE(agent_details.getOrchestrationMode() == OrchestrationMode::OFFLINE);
|
||||
}
|
||||
|
||||
TEST_F(AgentDetailsTest, unrecognizedMachineType)
|
||||
{
|
||||
env.preload();
|
||||
env.init();
|
||||
AgentDetails agent_details;
|
||||
EXPECT_CALL(
|
||||
mock_shell_cmd,
|
||||
getExecOutput("dmidecode -s system-manufacturer | tr -d '\\n'", _, _)
|
||||
).WillOnce(Return(string("Skynet")));
|
||||
agent_details.preload();
|
||||
agent_details.init();
|
||||
|
||||
auto machine_type = Singleton::Consume<I_Environment>::from(env)->get<I_AgentDetails::MachineType>("MachineType");
|
||||
EXPECT_EQ(machine_type.unpack(), I_AgentDetails::MachineType::UNRECOGNIZED);
|
||||
}
|
Reference in New Issue
Block a user