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,3 @@
include_directories(details_resolver_handlers)
add_library(details_resolver details_resolver.cc details_resolving_handler.cc)

View File

@@ -0,0 +1,288 @@
// 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 "details_resolver.h"
#include <sstream>
#include <string>
#include <vector>
#include "details_resolving_handler.h"
#include "i_orchestration_tools.h"
#include "maybe_res.h"
#include "version.h"
#include "config.h"
using namespace std;
USE_DEBUG_FLAG(D_ORCHESTRATOR);
class DetailsResolver::Impl
:
Singleton::Provide<I_DetailsResolver>::From<DetailsResolver>
{
public:
Maybe<string> getHostname() override;
Maybe<string> getPlatform() override;
Maybe<string> getArch() override;
map<string, string> getResolvedDetails() override;
string getAgentVersion() override;
bool isKernelVersion3OrHigher() override;
bool isGwNotVsx() override;
bool isVersionEqualOrAboveR8110() override;
bool isReverseProxy() override;
Maybe<tuple<string, string, string>> parseNginxMetadata() override;
#if defined(gaia) || defined(smb)
bool compareCheckpointVersion(int cp_version, std::function<bool(int, int)> compare_operator) const override;
#endif // gaia || smb
private:
#if defined(gaia) || defined(smb)
int getCheckpointVersion() const;
#endif // gaia || smb
DetailsResolvingHanlder handler;
};
map<string, string>
DetailsResolver::Impl::getResolvedDetails()
{
return handler.getResolvedDetails();
}
Maybe<string>
DetailsResolver::Impl::getHostname()
{
#if defined(arm32_musl) || defined(openwrt)
auto host_name = DetailsResolvingHanlder::getCommandOutput("uname -a | awk '{print $(2)}'");
#else // not arm32_musl || openwrt
auto host_name = DetailsResolvingHanlder::getCommandOutput("hostname");
#endif // defined(arm32_musl) || defined(openwrt)
if (!host_name.ok()) return genError("Failed to load host name, Error: " + host_name.getErr());
return host_name;
}
Maybe<string>
DetailsResolver::Impl::getPlatform()
{
#if defined(gaia)
return string("gaia");
#elif defined(arm32_rpi)
return string("glibc");
#elif defined(arm32_musl)
return string("musl");
#elif defined(smb_mrv_v1)
return string("smb_mrv_v1");
#elif defined(smb_sve_v2)
return string("smb_sve_v2");
#elif defined(smb_thx_v3)
return string("smb_thx_v3");
#elif defined(openwrt)
return string("uclibc");
#elif defined(arm64_linaro)
return string("arm64_linaro");
#elif defined(alpine)
return string("alpine");
#elif defined(arm64_trustbox)
return string("arm64_trustbox");
#elif defined(linux)
return string("linux");
#else
return genError("Failed to load platform details");
#endif
}
Maybe<string>
DetailsResolver::Impl::getArch()
{
#if defined(arm32_rpi) || defined(arm32_musl) || defined(openwrt)
auto architecture = DetailsResolvingHanlder::getCommandOutput("uname -a | awk '{print $(NF -1) }'");
#else // not arm32_rpi || arm32_musl || openwrt
auto architecture = DetailsResolvingHanlder::getCommandOutput("arch");
#endif // defined(arm32_rpi) || defined(arm32_musl) || defined(openwrt)
if (!architecture.ok()) return genError("Failed to load platform architecture, Error: " + architecture.getErr());
return architecture;
}
string
DetailsResolver::Impl::getAgentVersion()
{
return Version::getFullVersion();
}
bool
DetailsResolver::Impl::isReverseProxy()
{
#if defined(gaia) || defined(smb)
auto is_reverse_proxy = DetailsResolvingHanlder::getCommandOutput("cpprod_util CPPROD_IsConfigured CPwaap");
if (is_reverse_proxy.ok()) {
return is_reverse_proxy.unpack().front() == '1';
}
#endif
return false;
}
bool
DetailsResolver::Impl::isKernelVersion3OrHigher()
{
static const string cmd =
"clish -c 'show version os kernel' | awk '{print $4}' "
"| cut -d '.' -f 1 | awk -F: '{ if ( $1 >= 3 ) {print 1} else {print 0}}'";
auto is_gogo = DetailsResolvingHanlder::getCommandOutput(cmd);
if (is_gogo.ok()) {
return is_gogo.unpack().front() == '1';
}
return false;
}
bool
DetailsResolver::Impl::isGwNotVsx()
{
static const string is_gw_cmd = "cpprod_util FwIsFirewallModule";
static const string is_vsx_cmd = "cpprod_util FWisVSX";
auto is_gw = DetailsResolvingHanlder::getCommandOutput(is_gw_cmd);
auto is_vsx = DetailsResolvingHanlder::getCommandOutput(is_vsx_cmd);
if (is_gw.ok() && is_vsx.ok()) {
return is_gw.unpack().front() == '1' && is_vsx.unpack().front() == '0';
}
return false;
}
#if defined(gaia) || defined(smb)
bool
DetailsResolver::Impl::compareCheckpointVersion(int cp_version, std::function<bool(int, int)> compare_operator) const
{
int curr_version = getCheckpointVersion();
return compare_operator(curr_version, cp_version);
}
int
DetailsResolver::Impl::getCheckpointVersion() const
{
#ifdef gaia
static const string cmd =
"echo $CPDIR | awk -F'-' '{print $NF}' | cut -c 2- |"
" awk -F'.' '{ if( NF == 1 ) {print $1\"00\"} else {print $1$2} }'";
#else // smb
static const string cmd = "sqlcmd 'select major,minor from cpver' |"
"awk '{if ($1 == \"major\") v += (substr($3,2) * 100);"
" if ($1 == \"minor\") v += $3; } END { print v}'";
#endif // gaia
auto version_out = DetailsResolvingHanlder::getCommandOutput(cmd);
int cp_version = 0;
if (version_out.ok()) {
stringstream version_stream(version_out.unpack());
version_stream >> cp_version;
}
return cp_version;
}
#endif // gaia || smb
bool
DetailsResolver::Impl::isVersionEqualOrAboveR8110()
{
#if defined(gaia) || defined(smb)
return compareCheckpointVersion(8110, std::greater_equal<int>());
#endif
return false;
}
Maybe<tuple<string, string, string>>
DetailsResolver::Impl::parseNginxMetadata()
{
auto output_path = getConfigurationWithDefault<string>(
"/tmp/nginx_meta_data.txt",
"orchestration",
"Nginx metadata temp file"
);
const string srcipt_exe_cmd =
getFilesystemPathConfig() +
"/scripts/cp-nano-makefile-generator.sh -f -o " +
output_path;
dbgTrace(D_ORCHESTRATOR) << "Details resolver, srcipt exe cmd: " << srcipt_exe_cmd;
auto is_nginx_exist = DetailsResolvingHanlder::getCommandOutput("which nginx");
if (!is_nginx_exist.ok() || is_nginx_exist.unpack().size() == 0) {
return genError("Nginx isn't installed");
}
auto script_output = DetailsResolvingHanlder::getCommandOutput(srcipt_exe_cmd);
if (!script_output.ok()) {
return genError("Failed to generate nginx metadata, Error: " + script_output.getErr());
}
I_OrchestrationTools *orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<DetailsResolver>();
if (!orchestration_tools->doesFileExist(output_path)) {
return genError("Failed to access nginx metadata file.");
}
vector<string> lines;
try {
ifstream input_stream(output_path);
if (!input_stream) {
return genError("Cannot open the file with nginx metadata, File: " + output_path);
}
string line;
while (getline(input_stream, line)) {
lines.push_back(line);
}
input_stream.close();
orchestration_tools->removeFile(output_path);
} catch (const ifstream::failure &exception) {
dbgWarning(D_ORCHESTRATOR)
<< "Cannot read the file with required nginx metadata."
<< " File: " << output_path
<< " Error: " << exception.what();
}
if (lines.size() == 0) return genError("Failed to read nginx metadata file");
string nginx_version;
string config_opt;
string cc_opt;
for(string &line : lines) {
if (line.size() == 0) continue;
if (line.find("RELEASE_VERSION") != string::npos) continue;
if (line.find("--with-cc=") != string::npos) continue;
if (line.find("NGINX_VERSION") != string::npos) {
auto eq_index = line.find("=");
nginx_version = "nginx-" + line.substr(eq_index + 1);
continue;
}
if (line.find("EXTRA_CC_OPT") != string::npos) {
auto eq_index = line.find("=");
cc_opt = line.substr(eq_index + 1);
continue;
}
if (line.find("CONFIGURE_OPT") != string::npos) continue;
if (line.back() == '\\') line.pop_back();
config_opt += line;
}
return make_tuple(config_opt, cc_opt, nginx_version);
}
DetailsResolver::DetailsResolver() : Component("DetailsResolver"), pimpl(make_unique<Impl>()) {}
DetailsResolver::~DetailsResolver() {}
void
DetailsResolver::preload()
{
registerExpectedConfiguration<uint32_t>("orchestration", "Details resolver time out");
}

View File

@@ -0,0 +1,183 @@
// 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.
#ifndef __CHECKPOINT_PRODUCT_HANDLERS_H__
#define __CHECKPOINT_PRODUCT_HANDLERS_H__
#include <algorithm>
#include <boost/regex.hpp>
#if defined(gaia) || defined(smb)
Maybe<string>
checkHasSDWan(const string &command_output)
{
if (command_output.front() == '1') return string("true");
return genError("Current host does not have SDWAN capability");
}
Maybe<string>
getMgmtObjType(const string &command_output)
{
if (!command_output.empty()) {
if (command_output[0] == '1') return string("management");
if (command_output[0] == '0') return string("gateway");
}
return genError("Object type was not found");
}
Maybe<string>
chopHeadAndTail(const string &str, const string &prefix, const string &suffix)
{
if (str.size() < prefix.size() + suffix.size()) return genError("String too short");
if (str.compare(0, prefix.size(), prefix)) return genError("Prefix mismatch");
if (str.compare(str.size() - suffix.size(), suffix.size(), suffix)) return genError("Suffix mismatch");
return str.substr(prefix.size(), str.size() - prefix.size() - suffix.size());
}
Maybe<string>
getMgmtObjAttr(shared_ptr<istream> file_stream, const string &attr)
{
string line;
while (getline(*file_stream, line)) {
size_t attr_pos = line.find(attr);
if (attr_pos == string::npos) continue;
line = line.substr(attr_pos + attr.size());
return chopHeadAndTail(line, "(", ")");
}
return genError("Object attribute was not found. Attr: " + attr);
}
Maybe<string>
getMgmtObjUid(shared_ptr<istream> file_stream)
{
return getMgmtObjAttr(file_stream, "uuid ");
}
Maybe<string>
getMgmtObjName(shared_ptr<istream> file_stream)
{
return getMgmtObjAttr(file_stream, "name ");
}
Maybe<string>
getMgmtParentObjAttr(shared_ptr<istream> file_stream, const string &parent_obj, const string &attr)
{
string line;
bool found_parent_obj = false;
while (getline(*file_stream, line)) {
size_t parent_obj_pos = line.find(parent_obj);
if (parent_obj_pos != string::npos) found_parent_obj = true;
if (!found_parent_obj) continue;
size_t attr_pos = line.find(attr);
if (attr_pos == string::npos) continue;
line = line.substr(attr_pos + attr.size());
return line;
}
return genError("Parent object attribute was not found. Attr: " + attr);
}
Maybe<string>
getMgmtParentObjUid(shared_ptr<istream> file_stream)
{
auto maybe_unparsed_uid = getMgmtParentObjAttr(file_stream, "cluster_object", "Uid ");
if (!maybe_unparsed_uid.ok()) {
return maybe_unparsed_uid;
}
const string &unparsed_uid = maybe_unparsed_uid.unpack();
auto maybe_uid = chopHeadAndTail(unparsed_uid, "(\"{", "}\")");
if (!maybe_uid.ok()) {
return maybe_uid;
}
string uid = maybe_uid.unpack();
transform(uid.begin(), uid.end(), uid.begin(), ::tolower);
return uid;
}
Maybe<string>
getMgmtParentObjName(shared_ptr<istream> file_stream)
{
auto maybe_unparsed_name = getMgmtParentObjAttr(file_stream, "cluster_object", "Name ");
if (!maybe_unparsed_name.ok()) {
return maybe_unparsed_name;
}
const string &unparsed_name = maybe_unparsed_name.unpack();
return chopHeadAndTail(unparsed_name, "(", ")");
}
#endif // gaia || smb
Maybe<string>
getOsRelease(shared_ptr<istream> file_stream)
{
string line;
while (getline(*file_stream, line)) {
if (line.find("Check Point") != string::npos) return line;
static const string prety_name_attr = "PRETTY_NAME=";
size_t pretty_name_idx = line.find(prety_name_attr);
if (pretty_name_idx == string::npos) continue;
line = line.substr(pretty_name_idx + prety_name_attr.size());
if (line.front() == '"') line.erase(0, 1);
if (line.back() == '"') line.pop_back();
return line;
}
return genError("Os release was not found");
}
#if defined(alpine)
string &
ltrim(string &s)
{
auto it = find_if(
s.begin(),
s.end(),
[](char c) { return !isspace<char>(c, locale::classic()); }
);
s.erase(s.begin(), it);
return s;
}
string &
rtrim(string &s)
{
auto it = find_if(
s.rbegin(),
s.rend(),
[](char c) { return !isspace<char>(c, locale::classic()); }
);
s.erase(it.base(), s.end());
return s;
}
string &
trim(string &s)
{
return ltrim(rtrim(s));
}
Maybe<string>
getCPAlpineTag(shared_ptr<istream> file_stream)
{
string line;
while (getline(*file_stream, line)) {
if (trim(line) != "") return line;
}
return genError("Alpine tag was not found");
}
#endif // alpine
#endif // __CHECKPOINT_PRODUCT_HANDLERS_H__

View File

@@ -0,0 +1,72 @@
// 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.
#ifndef __DETAILS_RESOLVER_HANDLER_CC__
#error details_resolver_handlers/details_resolver_impl.h should not be included directly.
#endif // __DETAILS_RESOLVER_HANDLER_CC__
// use SHELL_CMD_HANDLER(key as string, shell command as string, ptr to Maybe<string> handler(const string&))
// to return a string value for an attribute key based on a logic executed in a handler that receives
// shell command execution output as its input
#ifdef SHELL_CMD_HANDLER
#if defined(gaia) || defined(smb)
SHELL_CMD_HANDLER("cpProductIntegrationMgmtObjectType", "cpprod_util CPPROD_IsMgmtMachine", getMgmtObjType)
SHELL_CMD_HANDLER("hasSDWan", "[ -f $FWDIR/bin/sdwan_steering ] && echo '1' || echo '0'", checkHasSDWan)
#endif //gaia
#endif // SHELL_CMD_HANDLER
// use SHELL_CMD_OUTPUT(key as string, shell command as string) to return a shell command output as the value
// for a given key
#ifdef SHELL_CMD_OUTPUT
SHELL_CMD_OUTPUT("kernel_version", "uname -r")
SHELL_CMD_OUTPUT("helloWorld", "cat /tmp/agentHelloWorld 2>/dev/null")
#endif // SHELL_CMD_OUTPUT
// use FILE_CONTENT_HANDLER(key as string, path to file as string, ptr to Maybe<string> handler(ifstream&))
// to return a string value for an attribute key based on a logic executed in a handler that receives file as input
#ifdef FILE_CONTENT_HANDLER
#if defined(alpine)
FILE_CONTENT_HANDLER("alpine_tag", "/usr/share/build/cp-alpine-tag", getCPAlpineTag)
#endif // alpine
#if defined(gaia) || defined(smb)
FILE_CONTENT_HANDLER("os_release", "/etc/cp-release", getOsRelease)
FILE_CONTENT_HANDLER(
"cpProductIntegrationMgmtObjectUid",
(getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myown.C",
getMgmtObjUid
)
FILE_CONTENT_HANDLER(
"cpProductIntegrationMgmtObjectName",
(getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myown.C",
getMgmtObjName
)
FILE_CONTENT_HANDLER(
"cpProductIntegrationMgmtParentObjectUid",
(getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myself_objects.C",
getMgmtParentObjUid
)
FILE_CONTENT_HANDLER(
"cpProductIntegrationMgmtParentObjectName",
(getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myself_objects.C",
getMgmtParentObjName
)
#else // !(gaia || smb)
FILE_CONTENT_HANDLER("os_release", "/etc/os-release", getOsRelease)
#endif // gaia || smb
#endif // FILE_CONTENT_HANDLER

View File

@@ -0,0 +1,128 @@
// 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 "details_resolving_handler.h"
#include <string>
#include <functional>
#include <map>
#include <fstream>
#include <iostream>
#include "maybe_res.h"
#include "enum_array.h"
#include "i_shell_cmd.h"
#include "config.h"
using namespace std;
USE_DEBUG_FLAG(D_AGENT_DETAILS);
using ShellCommandHandler = function<Maybe<string>(const string &raw_otput)>;
using FileContentHandler = function<Maybe<string>(shared_ptr<istream> file_otput)>;
#define __DETAILS_RESOLVER_HANDLER_CC__
#include "checkpoint_product_handlers.h"
class DetailsResolvingHanlder::Impl
{
public:
map<string, string> getResolvedDetails() const;
static Maybe<string> getCommandOutput(const string &cmd);
private:
#define SHELL_CMD_OUTPUT(ATTRIBUTE, COMMAND) SHELL_CMD_HANDLER(ATTRIBUTE, COMMAND, [](const string &s) { return s; })
#define SHELL_CMD_HANDLER(ATTRIBUTE, COMMAND, HANDLER) {ATTRIBUTE, {COMMAND, ShellCommandHandler(HANDLER)}},
map<string, pair<string, ShellCommandHandler>> shell_command_handlers = {
#include "details_resolver_impl.h"
};
#undef SHELL_CMD_OUTPUT
#undef SHELL_CMD_HANDLER
#define FILE_CONTENT_HANDLER(ATTRIBUTE, FILE, HANDLER) {ATTRIBUTE, {FILE, FileContentHandler(HANDLER)}},
map<string, pair<string, FileContentHandler>> file_content_handlers = {
#include "details_resolver_impl.h"
};
#undef FILE_CONTENT_HANDLER
};
map<string, string>
DetailsResolvingHanlder::Impl::getResolvedDetails() const
{
map<string, string> resolved_details;
for (auto shell_handler : shell_command_handlers) {
const string &attr = shell_handler.first;
const string &command = shell_handler.second.first;
ShellCommandHandler handler = shell_handler.second.second;
Maybe<string> shell_command_output = getCommandOutput(command);
if (!shell_command_output.ok()) continue;
Maybe<string> handler_ret = handler(*shell_command_output);
if (handler_ret.ok()) resolved_details[attr] = *handler_ret;
}
for (auto file_handler : file_content_handlers) {
const string &attr = file_handler.first;
const string &path = file_handler.second.first;
FileContentHandler handler = file_handler.second.second;
shared_ptr<ifstream> in_file = make_shared<ifstream>(path);
if (!in_file->is_open()) {
dbgWarning(D_AGENT_DETAILS) << "Could not open file for processing. Path: " << path;
continue;
}
dbgDebug(D_AGENT_DETAILS) << "Successfully opened file for processing. Path: " << path;
if (in_file->peek() != ifstream::traits_type::eof()) {
Maybe<string> handler_ret = handler(in_file);
if (handler_ret.ok()) resolved_details[attr] = *handler_ret;
}
in_file->close();
}
I_AgentDetailsReporter *reporter = Singleton::Consume<I_AgentDetailsReporter>::by<DetailsResolvingHanlder>();
reporter->addAttr(resolved_details);
return resolved_details;
}
Maybe<string>
DetailsResolvingHanlder::Impl::getCommandOutput(const string &cmd)
{
I_ShellCmd *shell = Singleton::Consume<I_ShellCmd>::by<DetailsResolvingHanlder>();
uint32_t timeout = getConfigurationWithDefault<uint32_t>(5000, "orchestration", "Details resolver time out");
auto result = shell->getExecOutput(cmd, timeout);
if (!result.ok()) return result;
auto unpacked_result = result.unpack();
if (unpacked_result.back() == '\n') unpacked_result.pop_back();
return unpacked_result;
}
DetailsResolvingHanlder::DetailsResolvingHanlder() : pimpl(make_unique<Impl>()) {}
DetailsResolvingHanlder::~DetailsResolvingHanlder() {}
map<string, string>
DetailsResolvingHanlder::getResolvedDetails() const
{
return pimpl->getResolvedDetails();
}
Maybe<string>
DetailsResolvingHanlder::getCommandOutput(const string &cmd)
{
return DetailsResolvingHanlder::Impl::getCommandOutput(cmd);
}

View File

@@ -0,0 +1,41 @@
// 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.
#ifndef __DETAILS_RESOLVING_HANDLER_H__
#define __DETAILS_RESOLVING_HANDLER_H__
#include <string>
#include <map>
#include "i_shell_cmd.h"
#include "i_agent_details_reporter.h"
class DetailsResolvingHanlder
:
Singleton::Consume<I_ShellCmd>,
Singleton::Consume<I_AgentDetailsReporter>
{
public:
DetailsResolvingHanlder();
~DetailsResolvingHanlder();
std::map<std::string, std::string> getResolvedDetails() const;
static Maybe<std::string> getCommandOutput(const std::string &cmd);
private:
class Impl;
std::unique_ptr<Impl> pimpl;
};
#endif // __DETAILS_RESOLVING_HANDLER_H__