mirror of
https://github.com/openappsec/openappsec.git
synced 2025-09-30 03:34:26 +03:00
Aug_23_2023-Dev
This commit is contained in:
@@ -17,6 +17,8 @@
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
@@ -36,6 +38,46 @@ void
|
||||
AgentDetails::init()
|
||||
{
|
||||
registerMachineType();
|
||||
loadAccessToken();
|
||||
Singleton::Consume<I_MainLoop>::by<AgentDetails>()->addRecurringRoutine(
|
||||
I_MainLoop::RoutineType::System,
|
||||
chrono::seconds(60),
|
||||
[this] () { loadAccessToken(); },
|
||||
"Load access token"
|
||||
);
|
||||
proxies = {
|
||||
{ProxyProtocol::HTTP, ProxyData()},
|
||||
{ProxyProtocol::HTTPS, ProxyData()}
|
||||
};
|
||||
|
||||
auto proxy_config = getProfileAgentSetting<string>("agent.config.message.proxy");
|
||||
if (proxy_config.ok()) {
|
||||
setProxy(*proxy_config);
|
||||
writeAgentDetails();
|
||||
}
|
||||
|
||||
registerConfigLoadCb(
|
||||
[&]()
|
||||
{
|
||||
auto proxy_config = getProfileAgentSetting<string>("agent.config.message.proxy");
|
||||
if (proxy_config.ok()) {
|
||||
is_proxy_configured_via_settings = true;
|
||||
setProxy(*proxy_config);
|
||||
writeAgentDetails();
|
||||
} else if (is_proxy_configured_via_settings) {
|
||||
is_proxy_configured_via_settings = false;
|
||||
setProxy(string(""));
|
||||
writeAgentDetails();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
auto load_env_proxy = loadProxy();
|
||||
if (!load_env_proxy.ok()) {
|
||||
dbgDebug(D_ORCHESTRATOR)
|
||||
<< "Could not initialize load proxy from environment, Error: "
|
||||
<< load_env_proxy.getErr();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -260,6 +302,36 @@ AgentDetails::getOrchestrationMode() const
|
||||
return orchestration_mode;
|
||||
}
|
||||
|
||||
string
|
||||
AgentDetails::getAccessToken() const
|
||||
{
|
||||
return access_token;
|
||||
}
|
||||
|
||||
void
|
||||
AgentDetails::loadAccessToken()
|
||||
{
|
||||
readAgentDetails();
|
||||
auto data_path = getConfigurationWithDefault<string>(
|
||||
getFilesystemPathConfig() + "/data/",
|
||||
"encryptor",
|
||||
"Data files directory"
|
||||
);
|
||||
ifstream token_file(data_path + session_token_file_name);
|
||||
if (!token_file.is_open()) {
|
||||
dbgWarning(D_ORCHESTRATOR) << "Failed to open session token file: " << data_path + session_token_file_name;
|
||||
return;
|
||||
}
|
||||
stringstream token_steam;
|
||||
token_steam << token_file.rdbuf();
|
||||
|
||||
auto new_token = token_steam.str();
|
||||
if (access_token != new_token) {
|
||||
access_token = new_token;
|
||||
dbgTrace(D_ORCHESTRATOR) << "Loaded the new token";
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<I_AgentDetails::MachineType>
|
||||
AgentDetails::getMachineTypeFromDmiTable()
|
||||
{
|
||||
@@ -300,3 +372,235 @@ AgentDetails::registerMachineType()
|
||||
);
|
||||
dbgInfo(D_ORCHESTRATOR) << "Setting machine type " << static_cast<int>(machine_type.unpack());
|
||||
}
|
||||
|
||||
string
|
||||
AgentDetails::convertProxyProtocolToString(ProxyProtocol proto) const
|
||||
{
|
||||
switch(proto) {
|
||||
case ProxyProtocol::HTTP: return "http";
|
||||
case ProxyProtocol::HTTPS: return "https";
|
||||
}
|
||||
dbgAssert(false) << "Unsupported Proxy Protocol " << static_cast<int>(proto);
|
||||
return "";
|
||||
}
|
||||
|
||||
Maybe<void>
|
||||
AgentDetails::verifyProxySyntax(
|
||||
const string &protocol,
|
||||
const string &auth,
|
||||
const string &domain,
|
||||
const string &port,
|
||||
const string &env_proxy)
|
||||
{
|
||||
stringstream verify_string;
|
||||
verify_string
|
||||
<< protocol
|
||||
<< "://"
|
||||
<< (!auth.empty() ? auth + string("@") : "")
|
||||
<< domain
|
||||
<< ":"
|
||||
<< port
|
||||
<< (env_proxy.back() == '/' ? "/" : "");
|
||||
|
||||
if (env_proxy.compare(verify_string.str()) != 0) {
|
||||
return genError(string("Provided proxy has the wrong syntax:" ) + env_proxy);
|
||||
}
|
||||
return Maybe<void>();
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
AgentDetails::loadProxyType(const string &proxy_type)
|
||||
{
|
||||
readAgentDetails();
|
||||
auto proxy_config = getProxy();
|
||||
if (proxy_config.ok()) {
|
||||
if (proxy_config.unpack() == "none") {
|
||||
return Maybe<string>(string());
|
||||
}
|
||||
return proxy_config;
|
||||
}
|
||||
|
||||
#ifdef gaia
|
||||
I_ShellCmd *shell_cmd = Singleton::Consume<I_ShellCmd>::by<AgentDetails>();
|
||||
auto proxy_ip = shell_cmd->getExecOutput("dbget proxy:ip-address| tr -d '\n'");
|
||||
if (!proxy_ip.ok()) return proxy_ip;
|
||||
auto proxy_port = shell_cmd->getExecOutput("dbget proxy:port| tr -d '\n'");
|
||||
if (!proxy_port.ok()) return proxy_port;
|
||||
if (*proxy_port != "" && *proxy_ip != "") return ("http://" + *proxy_ip + ":" + *proxy_port);
|
||||
|
||||
const string umis_file_path(string(getenv("CPDIR")) + "/tmp/umis_objects.C");
|
||||
|
||||
{
|
||||
ifstream umis_file(umis_file_path.c_str());
|
||||
if (!umis_file.good()) return Maybe<string>(string());
|
||||
}
|
||||
|
||||
const string read_umis_cmd = "cat " + umis_file_path + " | grep -w \"";
|
||||
const string parse_value_command = "\" | awk -F \"[ \\t]+\" '{printf $NF}' | tr -d \"()\"";
|
||||
|
||||
auto use_proxy = shell_cmd->getExecOutput(read_umis_cmd + "use_proxy" + parse_value_command);
|
||||
if (!use_proxy.ok())
|
||||
return genError("Failed to read use_proxy from " + umis_file_path + ": " + use_proxy.getErr());
|
||||
|
||||
if (use_proxy.unpack() == "true") {
|
||||
auto umis_proxy_add = shell_cmd->getExecOutput(read_umis_cmd + "proxy_address" + parse_value_command);
|
||||
if (!umis_proxy_add.ok() || *umis_proxy_add == "") return umis_proxy_add;
|
||||
auto umis_proxy_port = shell_cmd->getExecOutput(read_umis_cmd + "proxy_port" + parse_value_command);
|
||||
if (!umis_proxy_port.ok() || *umis_proxy_port == "") return umis_proxy_port;
|
||||
|
||||
return ("http://" + *umis_proxy_add + ":" + *umis_proxy_port);
|
||||
} else {
|
||||
dbgTrace(D_ORCHESTRATOR) << "Smart Console Proxy is turned off";
|
||||
}
|
||||
return Maybe<string>(string());
|
||||
#else // not gaia
|
||||
char *proxy = getenv(proxy_type.c_str());
|
||||
if (proxy) return string(proxy);
|
||||
|
||||
proxy = getenv(boost::algorithm::to_upper_copy(proxy_type).c_str());
|
||||
if (proxy) return string(proxy);
|
||||
return Maybe<string>(string());
|
||||
#endif // gaia
|
||||
}
|
||||
|
||||
Maybe<void>
|
||||
AgentDetails::loadProxyType(ProxyProtocol protocol)
|
||||
{
|
||||
dbgAssert(protocol == ProxyProtocol::HTTP || protocol == ProxyProtocol::HTTPS)
|
||||
<< "Unsupported Proxy Protocol " << static_cast<int>(protocol);
|
||||
|
||||
static const map<ProxyProtocol, string> env_var_name = {
|
||||
{ProxyProtocol::HTTPS, "https_proxy"},
|
||||
{ProxyProtocol::HTTP, "http_proxy"}
|
||||
};
|
||||
auto env_proxy = loadProxyType(env_var_name.at(protocol));
|
||||
if (!env_proxy.ok()) return genError(env_proxy.getErr());
|
||||
if (env_proxy.unpack().empty()) {
|
||||
return Maybe<void>();
|
||||
}
|
||||
|
||||
string protocol_regex = "(http|https)://";
|
||||
const static boost::regex no_auth_proxy_regex(protocol_regex + "(.)*:[0-9]{0,5}(/|)");
|
||||
const static boost::regex auth_proxy_regex(protocol_regex + "(.)*:(.)*@(.)*:[0-9]{0,5}(/|)");
|
||||
|
||||
ProxyData env_proxy_data;
|
||||
env_proxy_data.is_exists = true;
|
||||
string proxy_copy;
|
||||
if (!NGEN::Regex::regexMatch(__FILE__, __LINE__, env_proxy.unpack(), boost::regex(protocol_regex + "(.)*"))) {
|
||||
env_proxy = "http://" + env_proxy.unpack();
|
||||
}
|
||||
proxy_copy.assign(env_proxy.unpack());
|
||||
env_proxy_data.protocol = env_proxy.unpack().substr(0, proxy_copy.find(":"));
|
||||
proxy_copy.erase(0, proxy_copy.find(":") + 3); //remove "http://" or "https://"
|
||||
|
||||
if (NGEN::Regex::regexMatch(__FILE__, __LINE__, env_proxy.unpack(), auth_proxy_regex)) {
|
||||
env_proxy_data.auth = string(&proxy_copy[0], &proxy_copy[proxy_copy.find("@")]);
|
||||
proxy_copy.erase(0, proxy_copy.find("@") + 1); // remove "user:pass@"
|
||||
} else if (!NGEN::Regex::regexMatch(__FILE__, __LINE__, env_proxy.unpack(), no_auth_proxy_regex)) {
|
||||
return genError(string("Provided proxy has wrong syntax: ") + env_proxy.unpack());
|
||||
}
|
||||
env_proxy_data.domain = proxy_copy.substr(0, proxy_copy.find(":"));
|
||||
proxy_copy.erase(0, proxy_copy.find(":") + 1); // remove "host:"
|
||||
env_proxy_data.port = static_cast<uint16_t>(stoi(proxy_copy));
|
||||
|
||||
auto proxy_syntax = verifyProxySyntax(
|
||||
env_proxy_data.protocol,
|
||||
env_proxy_data.auth,
|
||||
env_proxy_data.domain,
|
||||
to_string(env_proxy_data.port),
|
||||
env_proxy.unpack()
|
||||
);
|
||||
if (!proxy_syntax.ok()) return proxy_syntax;
|
||||
if (env_proxy_data == proxies.at(protocol)) {
|
||||
return Maybe<void>();
|
||||
}
|
||||
|
||||
proxies.at(protocol) = env_proxy_data;
|
||||
dbgInfo(D_ORCHESTRATOR)
|
||||
<< convertProxyProtocolToString(protocol)
|
||||
<< " proxy was successfully loaded, "
|
||||
<< getProxyAddress(protocol).unpack();
|
||||
|
||||
return Maybe<void>();
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
AgentDetails::getProxyDomain(ProxyProtocol protocol) const
|
||||
{
|
||||
if (proxies.find(protocol) == proxies.end()) {
|
||||
return genError("Proxy type is not loaded in map, type: " + convertProxyProtocolToString(protocol));
|
||||
}
|
||||
if (proxies.at(protocol).domain.empty()) return genError(
|
||||
convertProxyProtocolToString(protocol) + string(" proxy domain is unset")
|
||||
);
|
||||
return proxies.at(protocol).domain;
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
AgentDetails::getProxyCredentials(ProxyProtocol protocol) const
|
||||
{
|
||||
if (proxies.find(protocol) == proxies.end()) {
|
||||
return genError("Proxy type is not loaded in map, type: " + convertProxyProtocolToString(protocol));
|
||||
}
|
||||
if (proxies.at(protocol).auth.empty()) return genError(
|
||||
convertProxyProtocolToString(protocol) + string(" proxy auth is unset")
|
||||
);
|
||||
return proxies.at(protocol).auth;
|
||||
}
|
||||
|
||||
Maybe<uint16_t>
|
||||
AgentDetails::getProxyPort(ProxyProtocol protocol) const
|
||||
{
|
||||
if (proxies.find(protocol) == proxies.end()) {
|
||||
return genError("Proxy type is not loaded in map, type: " + convertProxyProtocolToString(protocol));
|
||||
}
|
||||
if (proxies.at(protocol).port == 0) return genError(
|
||||
convertProxyProtocolToString(protocol) + string(" proxy port is unset")
|
||||
);
|
||||
return proxies.at(protocol).port;
|
||||
}
|
||||
|
||||
bool
|
||||
AgentDetails::getProxyExists(ProxyProtocol protocol) const
|
||||
{
|
||||
if (proxies.find(protocol) == proxies.end()) {
|
||||
dbgInfo(D_ORCHESTRATOR)
|
||||
<< "Proxy type is not loaded in map, type: "
|
||||
<< convertProxyProtocolToString(protocol);
|
||||
return false;
|
||||
}
|
||||
return proxies.at(protocol).is_exists;
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
AgentDetails::getProxyAddress(ProxyProtocol protocol) const
|
||||
{
|
||||
if (proxies.find(protocol) == proxies.end()) {
|
||||
return genError("Proxy type is not loaded in map, type: " + convertProxyProtocolToString(protocol));
|
||||
}
|
||||
if (proxies.at(protocol).protocol.empty() ||
|
||||
proxies.at(protocol).domain.empty() ||
|
||||
proxies.at(protocol).port == 0) {
|
||||
return genError(
|
||||
string("Can't construct ") +
|
||||
convertProxyProtocolToString(protocol) +
|
||||
string(" proxy address")
|
||||
);
|
||||
}
|
||||
return proxies.at(protocol).protocol +
|
||||
"://" +
|
||||
proxies.at(protocol).domain +
|
||||
":" +
|
||||
to_string(proxies.at(protocol).port);
|
||||
}
|
||||
|
||||
Maybe<void>
|
||||
AgentDetails::loadProxy()
|
||||
{
|
||||
if (getConfigurationFlag("orchestration-mode") == "offline_mode") return Maybe<void>();
|
||||
for (const auto &proxy_type : proxies) {
|
||||
auto loaded_proxy = loadProxyType(proxy_type.first);
|
||||
if (!loaded_proxy.ok()) return loaded_proxy;
|
||||
}
|
||||
return Maybe<void>();
|
||||
}
|
||||
|
@@ -1,7 +1,11 @@
|
||||
#include "agent_details.h"
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "mock/mock_encryptor.h"
|
||||
#include "mock/mock_shell_cmd.h"
|
||||
#include "mock/mock_mainloop.h"
|
||||
#include "cptest.h"
|
||||
#include "config.h"
|
||||
#include "config_component.h"
|
||||
@@ -24,133 +28,6 @@ public:
|
||||
StrictMock<MockEncryptor> mock_encryptor;
|
||||
StrictMock<MockShellCmd> mock_shell_cmd;
|
||||
Config::I_Config *config = nullptr;
|
||||
StrictMock<MockMainLoop> mock_ml;
|
||||
};
|
||||
|
||||
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