Compare commits

...

25 Commits

Author SHA1 Message Date
Ned Wright
2dda6231f6 sync code 2024-11-28 10:53:40 +00:00
Ned Wright
1c1f0b7e29 sync code 2024-11-28 10:41:59 +00:00
orianelou
6255e1f30d Rename docker-compose.yaml to docker-compose.yaml 2024-11-06 14:57:50 +02:00
orianelou
454aacf622 Rename .env to .env 2024-11-06 14:57:31 +02:00
orianelou
c91ccba5a8 Create .env 2024-11-06 14:01:40 +02:00
orianelou
b1f897191c Create docker-compose.yaml 2024-11-06 14:01:20 +02:00
Daniel-Eisenberg
027ddfea21 Merge pull request #200 from openappsec/Oct_14_2024-Dev
Oct 14 2024 dev
2024-11-05 12:12:10 +02:00
orianelou
d1a2906b29 Create default.conf 2024-11-03 14:23:34 +02:00
Ned Wright
b1ade9bba0 code sync 2024-10-15 06:57:25 +00:00
Ned Wright
36d302b77e code sync 2024-10-14 16:43:58 +00:00
Ned Wright
1d7d38b0a6 code sync 2024-10-14 16:39:35 +00:00
Ned Wright
1b7eafaa23 code sync 2024-10-14 16:32:23 +00:00
Ned Wright
c2ea2cda6d sync code 2024-10-14 14:51:28 +00:00
orianelou
b58f7781e6 Update local_policy.yaml 2024-10-01 13:05:23 +03:00
orianelou
7153d222c0 Update local_policy.yaml 2024-10-01 13:03:59 +03:00
orianelou
f1ec8959b7 Update apisix-standalone.yaml 2024-10-01 12:49:25 +03:00
Daniel-Eisenberg
4a7336b276 Merge pull request #190 from openappsec/Sep_17_2024-Dev
sync code
2024-09-30 14:53:51 +03:00
orianelou
4d0042e933 Create apisix-standalone.yaml 2024-09-30 14:10:35 +03:00
orianelou
015915497a Create docker-compose.yaml 2024-09-30 14:09:43 +03:00
Ned Wright
586150fe4f sync code 2024-09-17 10:53:09 +00:00
orianelou
3fe0b42fcd Merge pull request #189 from openappsec/Sep_15_2024-Dev
sync code
2024-09-15 17:25:26 +03:00
orianelou
84e10c7129 Merge pull request #186 from chkp-omriat2/main
Updating crowdsec auxiliary
2024-09-15 17:25:13 +03:00
Ned Wright
eddd250409 sync code 2024-09-15 02:49:26 +00:00
chkp-omriat2
294cb600f8 Updating crowdsec auxiliary 2024-09-10 06:09:54 +00:00
Ned Wright
f4bad4c4d9 Remove non-active files 2024-09-02 14:16:01 +03:00
273 changed files with 34435 additions and 18594 deletions

View File

@@ -73,27 +73,27 @@ TEST_F(HttpAttachmentUtilTest, GetValidAttachmentConfiguration)
valid_configuration_file.close();
EXPECT_EQ(initAttachmentConfig(attachment_configuration_file_name.c_str()), 1);
EXPECT_EQ(getDbgLevel(), 2);
EXPECT_EQ(getDbgLevel(), 2u);
EXPECT_EQ(getStaticResourcesPath(), static_resources_path);
EXPECT_EQ(isFailOpenMode(), 0);
EXPECT_EQ(getFailOpenTimeout(), 1234);
EXPECT_EQ(getFailOpenTimeout(), 1234u);
EXPECT_EQ(isFailOpenHoldMode(), 1);
EXPECT_EQ(getFailOpenHoldTimeout(), 4321);
EXPECT_EQ(getFailOpenHoldTimeout(), 4321u);
EXPECT_EQ(isFailOpenOnSessionLimit(), 1);
EXPECT_EQ(getMaxSessionsPerMinute(), 0);
EXPECT_EQ(getNumOfNginxIpcElements(), 200);
EXPECT_EQ(getKeepAliveIntervalMsec(), 10000);
EXPECT_EQ(getResProccessingTimeout(), 420);
EXPECT_EQ(getReqProccessingTimeout(), 42);
EXPECT_EQ(getRegistrationThreadTimeout(), 101);
EXPECT_EQ(getReqHeaderThreadTimeout(), 10);
EXPECT_EQ(getReqBodyThreadTimeout(), 155);
EXPECT_EQ(getResHeaderThreadTimeout(), 1);
EXPECT_EQ(getResBodyThreadTimeout(), 0);
EXPECT_EQ(getMinRetriesForVerdict(), 1);
EXPECT_EQ(getMaxRetriesForVerdict(), 3);
EXPECT_EQ(getReqBodySizeTrigger(), 777);
EXPECT_EQ(getWaitingForVerdictThreadTimeout(), 75);
EXPECT_EQ(getMaxSessionsPerMinute(), 0u);
EXPECT_EQ(getNumOfNginxIpcElements(), 200u);
EXPECT_EQ(getKeepAliveIntervalMsec(), 10000u);
EXPECT_EQ(getResProccessingTimeout(), 420u);
EXPECT_EQ(getReqProccessingTimeout(), 42u);
EXPECT_EQ(getRegistrationThreadTimeout(), 101u);
EXPECT_EQ(getReqHeaderThreadTimeout(), 10u);
EXPECT_EQ(getReqBodyThreadTimeout(), 155u);
EXPECT_EQ(getResHeaderThreadTimeout(), 1u);
EXPECT_EQ(getResBodyThreadTimeout(), 0u);
EXPECT_EQ(getMinRetriesForVerdict(), 1u);
EXPECT_EQ(getMaxRetriesForVerdict(), 3u);
EXPECT_EQ(getReqBodySizeTrigger(), 777u);
EXPECT_EQ(getWaitingForVerdictThreadTimeout(), 75u);
EXPECT_EQ(getInspectionMode(), ngx_http_inspection_mode::BLOCKING_THREAD);
EXPECT_EQ(isDebugContext("1.2.3.4", "5.6.7.8", 80, "GET", "test", "/abc"), 1);

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,3 @@
add_subdirectory(report_messaging)
add_subdirectory(http_manager)
add_subdirectory(signal_handler)
add_subdirectory(gradual_deployment)

View File

@@ -39,6 +39,8 @@ USE_DEBUG_FLAG(D_ATTACHMENT_REGISTRATION);
using namespace std;
static const AlertInfo alert(AlertTeam::CORE, "attachment registrator");
class AttachmentRegistrator::Impl
{
public:
@@ -163,7 +165,7 @@ private:
break;
}
default:
dbgAssert(false) << "Unsupported Attachment " << static_cast<int>(type);
dbgAssert(false) << alert << "Unsupported Attachment " << static_cast<int>(type);
}
if (!family_id.empty()) handler_path << family_id << "_";
@@ -175,7 +177,9 @@ private:
string
genRegCommand(const string &family_id, const uint num_of_members, const AttachmentType type) const
{
dbgAssert(num_of_members > 0) << "Failed to generate a registration command for an empty group of attachments";
dbgAssert(num_of_members > 0)
<< alert
<< "Failed to generate a registration command for an empty group of attachments";
static const string registration_format = "/etc/cp/watchdog/cp-nano-watchdog --register ";
stringstream registration_command;
@@ -187,7 +191,7 @@ private:
break;
}
default:
dbgAssert(false) << "Unsupported Attachment " << static_cast<int>(type);
dbgAssert(false) << alert << "Unsupported Attachment " << static_cast<int>(type);
}
if (!family_id.empty()) registration_command << " --family " << family_id;
@@ -265,7 +269,7 @@ private:
return -1;
}
dbgAssert(new_socket.unpack() > 0) << "Generated socket is OK yet negative";
dbgAssert(new_socket.unpack() > 0) << alert << "Generated socket is OK yet negative";
return new_socket.unpack();
}
@@ -281,7 +285,7 @@ private:
}
I_Socket::socketFd client_socket = accepted_socket.unpack();
dbgAssert(client_socket > 0) << "Generated client socket is OK yet negative";
dbgAssert(client_socket > 0) << alert << "Generated client socket is OK yet negative";
auto close_socket_on_exit = make_scope_exit([&]() { i_socket->closeSocket(client_socket); });
Maybe<uint8_t> attachment_id = readNumericParam(client_socket);
@@ -375,7 +379,7 @@ private:
}
I_Socket::socketFd client_socket = accepted_socket.unpack();
dbgAssert(client_socket > 0) << "Generated client socket is OK yet negative";
dbgAssert(client_socket > 0) << alert << "Generated client socket is OK yet negative";
auto close_socket_on_exit = make_scope_exit([&]() { i_socket->closeSocket(client_socket); });
Maybe<AttachmentType> attachment_type = readAttachmentType(client_socket);

View File

@@ -76,6 +76,7 @@ using namespace std;
using ChunkType = ngx_http_chunk_type_e;
static const uint32_t corrupted_session_id = CORRUPTED_SESSION_ID;
static const AlertInfo alert(AlertTeam::CORE, "nginx attachment");
class FailopenModeListener : public Listener<FailopenModeEvent>
{
@@ -410,7 +411,10 @@ private:
bool
registerAttachmentProcess(uint32_t nginx_user_id, uint32_t nginx_group_id, I_Socket::socketFd new_socket)
{
dbgAssert(server_sock > 0) << "Registration attempt occurred while registration socket is uninitialized";
dbgAssert(server_sock > 0)
<< alert
<< "Registration attempt occurred while registration socket is uninitialized";
#ifdef FAILURE_TEST
bool did_fail_on_purpose = false;
#endif
@@ -802,10 +806,10 @@ private:
case ChunkType::HOLD_DATA:
return "HOLD_DATA";
case ChunkType::COUNT:
dbgAssert(false) << "Invalid 'COUNT' ChunkType";
dbgAssert(false) << alert << "Invalid 'COUNT' ChunkType";
return "";
}
dbgAssert(false) << "ChunkType was not handled by the switch case";
dbgAssert(false) << alert << "ChunkType was not handled by the switch case";
return "";
}
@@ -1131,7 +1135,11 @@ private:
"webUserResponse"
);
bool remove_event_id_param =
getProfileAgentSettingWithDefault<string>("false", "nginxAttachment.removeRedirectEventId") == "true";
string uuid;
string redirectUrl;
if (i_transaction_table->hasState<NginxAttachmentOpaque>()) {
NginxAttachmentOpaque &opaque = i_transaction_table->getState<NginxAttachmentOpaque>();
uuid = opaque.getSessionUUID();
@@ -1141,7 +1149,12 @@ private:
if (web_trigger_conf.getDetailsLevel() == "Redirect") {
web_response_data.response_data.redirect_data.redirect_location_size =
web_trigger_conf.getRedirectURL().size();
web_response_data.response_data.redirect_data.add_event_id = web_trigger_conf.getAddEventId() ? 1 : 0;
bool add_event = web_trigger_conf.getAddEventId();
if (add_event && !remove_event_id_param) {
web_response_data.response_data.redirect_data.redirect_location_size +=
strlen("?event_id=") + uuid.size();
}
web_response_data.response_data.redirect_data.add_event_id = add_event ? 1 : 0;
web_response_data.web_repsonse_type = static_cast<uint8_t>(ngx_web_response_type_e::REDIRECT_WEB_RESPONSE);
} else {
web_response_data.response_data.custom_response_data.title_size =
@@ -1155,8 +1168,13 @@ private:
verdict_data_sizes.push_back(sizeof(ngx_http_cp_web_response_data_t));
if (web_trigger_conf.getDetailsLevel() == "Redirect") {
verdict_data.push_back(reinterpret_cast<const char *>(web_trigger_conf.getRedirectURL().data()));
verdict_data_sizes.push_back(web_trigger_conf.getRedirectURL().size());
redirectUrl = web_trigger_conf.getRedirectURL();
if (!remove_event_id_param && web_trigger_conf.getAddEventId()) {
redirectUrl += "?event-id=" + uuid;
}
verdict_data.push_back(reinterpret_cast<const char *>(redirectUrl.data()));
verdict_data_sizes.push_back(redirectUrl.size());
} else {
verdict_data.push_back(reinterpret_cast<const char *>(web_trigger_conf.getResponseTitle().data()));
verdict_data_sizes.push_back(web_trigger_conf.getResponseTitle().size());
@@ -1582,7 +1600,7 @@ private:
case WAIT:
return "WAIT";
}
dbgAssert(false) << "Invalid EventVerdict enum: " << static_cast<int>(verdict.getVerdict());
dbgAssert(false) << alert << "Invalid EventVerdict enum: " << static_cast<int>(verdict.getVerdict());
return string();
}
@@ -1633,13 +1651,14 @@ private:
return false;
}
dbgAssert(sock.unpack() > 0) << "The generated server socket is OK, yet negative";
dbgAssert(sock.unpack() > 0) << alert << "The generated server socket is OK, yet negative";
server_sock = sock.unpack();
I_MainLoop::Routine accept_attachment_routine =
[this] ()
{
dbgAssert(inst_awareness->getUniqueID().ok())
<< alert
<< "NGINX attachment Initialized without Instance Awareness";
bool did_fail_on_purpose = false;
@@ -1652,7 +1671,7 @@ private:
<< (did_fail_on_purpose ? "Intentional Failure" : new_sock.getErr());
return;
}
dbgAssert(new_sock.unpack() > 0) << "The generated client socket is OK, yet negative";
dbgAssert(new_sock.unpack() > 0) << alert << "The generated client socket is OK, yet negative";
I_Socket::socketFd new_attachment_socket = new_sock.unpack();
Maybe<string> uid = getUidFromSocket(new_attachment_socket);
@@ -1711,7 +1730,9 @@ private:
Maybe<string>
getUidFromSocket(I_Socket::socketFd new_attachment_socket)
{
dbgAssert(server_sock > 0) << "Registration attempt occurred while registration socket is uninitialized";
dbgAssert(server_sock > 0)
<< alert
<< "Registration attempt occurred while registration socket is uninitialized";
bool did_fail_on_purpose = false;
DELAY_IF_NEEDED(IntentionalFailureHandler::FailureType::ReceiveDataFromSocket);

View File

@@ -282,7 +282,7 @@ isIpTrusted(const string &value, const vector<CIDRSData> &cidr_values)
}
Maybe<string>
UsersAllIdentifiersConfig::parseXForwardedFor(const string &str) const
UsersAllIdentifiersConfig::parseXForwardedFor(const string &str, ExtractType type) const
{
vector<string> header_values = split(str);
@@ -291,12 +291,23 @@ UsersAllIdentifiersConfig::parseXForwardedFor(const string &str) const
vector<string> xff_values = getHeaderValuesFromConfig("x-forwarded-for");
vector<CIDRSData> cidr_values(xff_values.begin(), xff_values.end());
for (const string &value : header_values) {
if (!IPAddr::createIPAddr(value).ok()) {
dbgWarning(D_NGINX_ATTACHMENT_PARSER) << "Invalid IP address found in the xff header IPs list: " << value;
for (auto it = header_values.rbegin(); it != header_values.rend() - 1; ++it) {
if (!IPAddr::createIPAddr(*it).ok()) {
dbgWarning(D_NGINX_ATTACHMENT_PARSER) << "Invalid IP address found in the xff header IPs list: " << *it;
return genError("Invalid IP address");
}
if (!isIpTrusted(value, cidr_values)) return genError("Untrusted Ip found");
if (type == ExtractType::PROXYIP) continue;
if (!isIpTrusted(*it, cidr_values)) {
dbgDebug(D_NGINX_ATTACHMENT_PARSER) << "Found untrusted IP in the xff header IPs list: " << *it;
return *it;
}
}
if (!IPAddr::createIPAddr(header_values[0]).ok()) {
dbgWarning(D_NGINX_ATTACHMENT_PARSER)
<< "Invalid IP address found in the xff header IPs list: "
<< header_values[0];
return genError("Invalid IP address");
}
return header_values[0];
@@ -312,9 +323,7 @@ UsersAllIdentifiersConfig::setXFFValuesToOpaqueCtx(const HttpHeader &header, Ext
return;
}
NginxAttachmentOpaque &opaque = i_transaction_table->getState<NginxAttachmentOpaque>();
opaque.setSavedData(HttpTransactionData::xff_vals_ctx, header.getValue());
dbgTrace(D_NGINX_ATTACHMENT_PARSER) << "xff found, value from header: " << static_cast<string>(header.getValue());
auto value = parseXForwardedFor(header.getValue());
auto value = parseXForwardedFor(header.getValue(), type);
if (!value.ok()) {
dbgTrace(D_NGINX_ATTACHMENT_PARSER) << "Could not extract source identifier from X-Forwarded-For header";
return;
@@ -323,8 +332,13 @@ UsersAllIdentifiersConfig::setXFFValuesToOpaqueCtx(const HttpHeader &header, Ext
if (type == ExtractType::SOURCEIDENTIFIER) {
opaque.setSourceIdentifier(header.getKey(), value.unpack());
dbgDebug(D_NGINX_ATTACHMENT_PARSER)
<< "Added source identifir to XFF "
<< "Added source identifier from XFF header"
<< value.unpack();
opaque.setSavedData(HttpTransactionData::xff_vals_ctx, header.getValue());
opaque.setSavedData(HttpTransactionData::source_identifier, value.unpack());
dbgTrace(D_NGINX_ATTACHMENT_PARSER)
<< "XFF found, set ctx with value from header: "
<< static_cast<string>(header.getValue());
} else {
opaque.setSavedData(HttpTransactionData::proxy_ip_ctx, value.unpack());
}

View File

@@ -128,7 +128,7 @@ private:
break;
}
default:
dbgAssert(false) << "Unsupported IP type";
dbgAssert(false) << AlertInfo(AlertTeam::CORE, "gradual deployment") << "Unsupported IP type";
}
return address;
}

View File

@@ -46,7 +46,10 @@ operator<<(ostream &os, const EventVerdict &event)
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_WAIT: return os << "Wait";
}
dbgAssert(false) << "Illegal Event Verdict value: " << static_cast<uint>(event.getVerdict());
dbgAssert(false)
<< AlertInfo(AlertTeam::CORE, "http manager")
<< "Illegal Event Verdict value: "
<< static_cast<uint>(event.getVerdict());
return os;
}
@@ -321,8 +324,11 @@ private:
state.setApplicationVerdict(respond.first, respond.second.getVerdict());
}
return state.getCurrVerdict();
FilterVerdict aggregated_verdict = state.getCurrVerdict();
if (aggregated_verdict.getVerdict() == ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP) {
SecurityAppsDropEvent(state.getCurrentDropVerdictCausers()).notify();
}
return aggregated_verdict;
}
static void

View File

@@ -69,6 +69,7 @@ HttpManagerOpaque::getCurrVerdict() const
break;
default:
dbgAssert(false)
<< AlertInfo(AlertTeam::CORE, "http manager")
<< "Received unknown verdict "
<< static_cast<int>(app_verdic_pair.second);
}
@@ -77,6 +78,25 @@ HttpManagerOpaque::getCurrVerdict() const
return accepted_apps == applications_verdicts.size() ? ngx_http_cp_verdict_e::TRAFFIC_VERDICT_ACCEPT : verdict;
}
std::set<std::string>
HttpManagerOpaque::getCurrentDropVerdictCausers() const
{
std::set<std::string> causers;
if (manager_verdict == ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP) {
causers.insert(HTTP_MANAGER_NAME);
}
for (const auto &app_verdic_pair : applications_verdicts) {
bool was_dropped = app_verdic_pair.second == ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP;
dbgTrace(D_HTTP_MANAGER)
<< "The verdict from: " << app_verdic_pair.first
<< (was_dropped ? " is \"drop\"" : " is not \"drop\" ");
if (was_dropped) {
causers.insert(app_verdic_pair.first);
}
}
return causers;
}
void
HttpManagerOpaque::saveCurrentDataToCache(const Buffer &full_data)
{

View File

@@ -20,6 +20,8 @@
#include "table_opaque.h"
#include "nginx_attachment_common.h"
static const std::string HTTP_MANAGER_NAME = "HTTP Manager";
class HttpManagerOpaque : public TableOpaqueSerialize<HttpManagerOpaque>
{
public:
@@ -30,6 +32,7 @@ public:
void setManagerVerdict(ngx_http_cp_verdict_e verdict) { manager_verdict = verdict; }
ngx_http_cp_verdict_e getManagerVerdict() const { return manager_verdict; }
ngx_http_cp_verdict_e getCurrVerdict() const;
std::set<std::string> getCurrentDropVerdictCausers() const;
void saveCurrentDataToCache(const Buffer &full_data);
void setUserDefinedValue(const std::string &value) { user_defined_value = value; }
Maybe<std::string> getUserDefinedValue() const { return user_defined_value; }

View File

@@ -29,12 +29,15 @@ public:
virtual EnvType getEnvType() override;
virtual std::string getToken() override;
virtual std::string getNameSpace() override;
private:
std::string retrieveToken();
std::string retrieveNamespace();
std::string readFileContent(const std::string &file_path);
std::string token;
std::string agent_namespace;
EnvType env_type;
};

View File

@@ -91,7 +91,7 @@ private:
bool matchAttributesString(const std::set<std::string> &values) const;
bool matchAttributesIp(const std::set<std::string> &values) const;
bool isRegEx() const;
bool isIP() const;
void sortAndMergeIpRangesValues();
MatchType type;
Operators operator_type;

View File

@@ -21,6 +21,7 @@
#include "i_shell_cmd.h"
#include "i_orchestration_status.h"
#include "component.h"
#include "i_service_controller.h"
class HealthChecker
:
@@ -29,7 +30,8 @@ class HealthChecker
Singleton::Consume<I_Socket>,
Singleton::Consume<I_Health_Check_Manager>,
Singleton::Consume<I_ShellCmd>,
Singleton::Consume<I_OrchestrationStatus>
Singleton::Consume<I_OrchestrationStatus>,
Singleton::Consume<I_ServiceController>
{
public:
HealthChecker();

View File

@@ -50,9 +50,11 @@ public:
position(mod_position)
{
dbgAssert(mod_type != ModificationType::APPEND || position == injection_pos_irrelevant)
<< AlertInfo(AlertTeam::CORE, "http manager")
<< "Injection position is not applicable to a modification of type \"Append\"";
dbgAssert(mod_type != ModificationType::INJECT || position >= 0)
<< AlertInfo(AlertTeam::CORE, "http manager")
<< "Invalid injection position: must be non-negative. Position: "
<< position;
}
@@ -166,6 +168,7 @@ private:
}
default:
dbgAssert(false)
<< AlertInfo(AlertTeam::CORE, "http manager")
<< "Unknown type of ModificationType: "
<< static_cast<int>(modification_type);
}

View File

@@ -183,4 +183,16 @@ class WaitTransactionEvent : public Event<WaitTransactionEvent, EventVerdict>
{
};
class SecurityAppsDropEvent : public Event<SecurityAppsDropEvent>
{
public:
SecurityAppsDropEvent(
const std::set<std::string> &apps_names)
:
apps_names(apps_names) {}
const std::set<std::string> & getAppsNames() const { return apps_names; }
private:
const std::set<std::string> apps_names;
};
#endif // __HTTP_INSPECTION_EVENTS_H__

View File

@@ -66,6 +66,8 @@ public:
virtual std::map<std::string, std::vector<PortNumber>> getServiceToPortMap() = 0;
virtual bool getServicesPolicyStatus() const = 0;
protected:
virtual ~I_ServiceController() {}
};

View File

@@ -28,8 +28,9 @@
// LCOV_EXCL_START Reason: temporary until we add relevant UT until 07/10
bool operator<(const IpAddress &this_ip_addr, const IpAddress &other_ip_addr);
bool operator==(const IpAddress &this_ip_addr, const IpAddress &other_ip_addr);
bool operator<=(const IpAddress &this_ip_addr, const IpAddress &other_ip_addr);
bool operator<(const IPRange &range1, const IPRange &range2);
// LCOV_EXCL_STOP
Maybe<std::pair<std::string, int>> extractAddressAndMaskSize(const std::string &cidr);

View File

@@ -115,7 +115,7 @@ public:
case ResourceFileType::VIRTUAL_SETTINGS: return "virtualSettings";
case ResourceFileType::VIRTUAL_POLICY: return "virtualPolicy";
default:
dbgAssert(false) << "Unknown file type";
dbgAssert(false) << AlertInfo(AlertTeam::CORE, "update process") << "Unknown file type";
}
return std::string();
}

View File

@@ -56,7 +56,7 @@ private:
if (mapped_type.second == type) return mapped_type.first;
}
dbgAssert(false) << "Unsupported type " << static_cast<int>(type);
dbgAssert(false) << AlertInfo(AlertTeam::CORE, "packaging") << "Unsupported type " << static_cast<int>(type);
// Just satisfying the compiler, this return never reached
return std::string();
}

View File

@@ -7,24 +7,28 @@ static const std::string product_name = getenv("DOCKER_RPM_ENABLED") ? "CloudGua
static const std::string default_cp_cert_file = "/etc/cp/cpCert.pem";
static const std::string default_cp_key_file = "/etc/cp/cpKey.key";
static const std::string default_rpm_conf_path = "/etc/cp/conf/rpmanager/";
static const std::string default_certificate_path = "/etc/cp/rpmanager/certs";
static const std::string default_manual_certs_path = "/etc/cp/rpmanager/manualCerts/";
static const std::string default_config_path = "/etc/cp/conf/rpmanager/servers";
static const std::string default_rpm_prepare_path = "/etc/cp/conf/rpmanager/prepare/servers";
static const std::string default_nginx_log_files_path = "/var/log/nginx/";
static const std::string default_additional_files_path = "/etc/cp/conf/rpmanager/include";
static const std::string default_server_config = "additional_server_config.conf";
static const std::string default_location_config = "additional_location_config.conf";
static const std::string default_trusted_ca_suffix = "_user_ca_bundle.crt";
static const std::string default_nginx_log_files_path = "/var/log/nginx/";
static const std::string default_log_files_host_path = "/var/log/nano_agent/rpmanager/nginx_log/";
static const std::string default_config_path = "/etc/cp/conf/rpmanager/servers";
static const std::string default_template_path = "/etc/cp/conf/rpmanager/nginx-template-clear";
static const std::string default_manual_certs_path = "/etc/cp/rpmanager/manualCerts/";
static const std::string default_server_certificate_path = "/etc/cp/rpmanager/certs/sslCertificate_";
static const std::string default_server_certificate_key_path = "/etc/cp/rpmanager/certs/sslPrivateKey_";
static const std::string default_container_name = "cp_nginx_gaia";
static const std::string default_docker_image = "cp_nginx_gaia";
static const std::string default_nginx_config_file = "/etc/cp/conf/rpmanager/nginx.conf";
static const std::string default_prepare_nginx_config_file = "/etc/cp/conf/rpmanager/nginx_prepare.conf";
static const std::string default_global_conf_template = "/etc/cp/conf/rpmanager/nginx-conf-template";
static const std::string default_nginx_config_include_file =
"/etc/cp/conf/rpmanager/servers/nginx_conf_include";
"/etc/cp/conf/rpmanager/servers/00_nginx_conf_include.conf";
static const std::string default_global_conf_include_template =
"/etc/cp/conf/rpmanager/nginx-conf-include-template";
static const std::string default_global_conf_include_template_no_responses =

View File

@@ -0,0 +1,39 @@
// 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 __SERVICE_HEALTH_STATUS_H__
#define __SERVICE_HEALTH_STATUS_H__
#include "singleton.h"
#include "i_rest_api.h"
#include "i_environment.h"
#include "component.h"
class ServiceHealthStatus
:
public Component,
Singleton::Consume<I_RestApi>,
Singleton::Consume<I_Environment>
{
public:
ServiceHealthStatus();
~ServiceHealthStatus();
void init() override;
private:
class Impl;
std::unique_ptr<Impl> pimpl;
};
#endif // __SERVICE_HEALTH_STATUS_H__

View File

@@ -58,7 +58,7 @@ private:
const std::string::const_iterator &end,
const std::string &key) const;
Buffer extractKeyValueFromCookie(const std::string &cookie_value, const std::string &key) const;
Maybe<std::string> parseXForwardedFor(const std::string &str) const;
Maybe<std::string> parseXForwardedFor(const std::string &str, ExtractType type) const;
std::vector<UsersIdentifiersConfig> user_identifiers;
};

View File

@@ -34,6 +34,8 @@ class I_Messaging;
class I_AgentDetails;
class I_Encryptor;
const std::string WAAP_APPLICATION_NAME = "waap application";
class WaapComponent
:
public Component,

View File

@@ -563,7 +563,10 @@ Packet::parsePacket(PktType type, IPType proto)
return parseFromL3v6();
}
default: {
dbgAssert(false) << "Unknown (neither IPv4, nor IPv6), or uninitialized packet type: " << proto;
dbgAssert(false)
<< AlertInfo(AlertTeam::CORE, "packet")
<< "Unknown (neither IPv4, nor IPv6), or uninitialized packet type: "
<< proto;
}
}

View File

@@ -43,7 +43,9 @@ PendingKey::print(ostream &os) const
size_t
PendingKey::hash() const
{
dbgAssert(src.type != IPType::UNINITIALIZED) << "PendingKey::hash was called on an uninitialized object";
dbgAssert(src.type != IPType::UNINITIALIZED)
<< AlertInfo(AlertTeam::CORE, "pending key")
<< "PendingKey::hash was called on an uninitialized object";
size_t seed = 0;
hashCombine(seed, static_cast<u_char>(src.type));
hashCombine(seed, src.proto);

View File

@@ -1,3 +0,0 @@
link_directories(${BOOST_ROOT}/lib)
add_unit_test(report_messaging_ut "report_messaging_ut.cc" "report_messaging;report;messaging;singleton;-lboost_regex")

View File

@@ -67,18 +67,18 @@ public:
dbgTrace(D_GEO_FILTER) << getListenerName() << " new transaction event";
if (!event.isLastHeader()) return EventVerdict(ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT);
std::set<std::string> xff_set;
std::set<std::string> ip_set;
auto env = Singleton::Consume<I_Environment>::by<HttpGeoFilter>();
auto maybe_xff = env->get<std::string>(HttpTransactionData::xff_vals_ctx);
if (!maybe_xff.ok()) {
dbgTrace(D_GEO_FILTER) << "failed to get xff vals from env";
} else {
xff_set = split(maybe_xff.unpack(), ',');
ip_set = split(maybe_xff.unpack(), ',');
}
dbgDebug(D_GEO_FILTER) << getListenerName() << " last header, start lookup";
if (xff_set.size() > 0) {
removeTrustedIpsFromXff(xff_set);
if (ip_set.size() > 0) {
removeTrustedIpsFromXff(ip_set);
} else {
dbgDebug(D_GEO_FILTER) << "xff not found in headers";
}
@@ -90,14 +90,14 @@ public:
}
auto source_ip = convertIpAddrToString(maybe_source_ip.unpack());
xff_set.insert(source_ip);
ip_set.insert(source_ip);
ngx_http_cp_verdict_e exception_verdict = getExceptionVerdict(xff_set);
ngx_http_cp_verdict_e exception_verdict = getExceptionVerdict(ip_set);
if (exception_verdict != ngx_http_cp_verdict_e::TRAFFIC_VERDICT_IRRELEVANT) {
return EventVerdict(exception_verdict);
}
ngx_http_cp_verdict_e geo_lookup_verdict = getGeoLookupVerdict(xff_set);
ngx_http_cp_verdict_e geo_lookup_verdict = getGeoLookupVerdict(ip_set);
if (geo_lookup_verdict != ngx_http_cp_verdict_e::TRAFFIC_VERDICT_IRRELEVANT) {
return EventVerdict(geo_lookup_verdict);
}
@@ -469,5 +469,6 @@ void
HttpGeoFilter::preload()
{
registerExpectedConfiguration<GeoConfig>("rulebase", "httpGeoFilter");
registerExpectedConfiguration<UsersAllIdentifiersConfig>("rulebase", "usersIdentifiers");
registerConfigLoadCb([this]() { pimpl->loadDefaultAction(); });
}

View File

@@ -43,7 +43,10 @@ CompoundProtection::Impl::getMatch(const set<PMPattern> &matched) const
case Operation::ORDERED_AND: return getMatchOrderedAnd(matched);
}
dbgAssert(false) << "Unknown compound operation: " << static_cast<uint>(operation);
dbgAssert(false)
<< AlertInfo(AlertTeam::CORE, "ips")
<< "Unknown compound operation: "
<< static_cast<uint>(operation);
return MatchType::NO_MATCH;
}

View File

@@ -8,7 +8,9 @@ IPSConfiguration::Context::Context(ContextType _type, uint history) : type(_type
uint
IPSConfiguration::Context::getHistorySize() const
{
dbgAssert(type == ContextType::HISTORY) << "Try to access history size for non-history context";
dbgAssert(type == ContextType::HISTORY)
<< AlertInfo(AlertTeam::CORE, "ips")
<< "Try to access history size for non-history context";
return history_size;
}
@@ -69,6 +71,8 @@ uint
IPSConfiguration::getHistorySize(const string &name) const
{
auto context = context_config.find(name);
dbgAssert(context != context_config.end()) << "Try to access history size for non-exiting context";
dbgAssert(context != context_config.end())
<< AlertInfo(AlertTeam::CORE, "ips")
<< "Try to access history size for non-exiting context";
return context->second.getHistorySize();
}

View File

@@ -26,6 +26,8 @@ static const map<string, IPSConfiguration::Context> default_conf_mapping = {
};
static const IPSConfiguration default_conf(default_conf_mapping);
static const IPSSignatures default_ips_sigs;
static const SnortSignatures default_snort_sigs;
IPSEntry::IPSEntry() : TableOpaqueSerialize<IPSEntry>(this) {}
@@ -51,9 +53,9 @@ IPSEntry::respond(const ParsedContext &parsed)
ctx.registerValue(name, buf);
ctx.activate();
auto &signatures = getConfigurationWithDefault(IPSSignatures(), "IPS", "IpsProtections");
auto &signatures = getConfigurationWithDefault(default_ips_sigs, "IPS", "IpsProtections");
bool should_drop = signatures.isMatchedPrevent(parsed.getName(), buf);
auto &snort_signatures = getConfigurationWithDefault(SnortSignatures(), "IPSSnortSigs", "SnortProtections");
auto &snort_signatures = getConfigurationWithDefault(default_snort_sigs, "IPSSnortSigs", "SnortProtections");
should_drop |= snort_signatures.isMatchedPrevent(parsed.getName(), buf);
ctx.deactivate();

View File

@@ -84,7 +84,7 @@ IPSSignatureMetaData::getSeverityString() const
return "Critical";
}
dbgAssert(false) << "Illegal severity value: " << static_cast<uint>(severity);
dbgAssert(false) << AlertInfo(AlertTeam::CORE, "ips") << "Illegal severity value: " << static_cast<uint>(severity);
return "Critical";
}
@@ -116,7 +116,10 @@ IPSSignatureMetaData::getPerformanceString() const
return "Critical";
}
dbgAssert(false) << "Illegal performance value: " << static_cast<uint>(performance);
dbgAssert(false)
<< AlertInfo(AlertTeam::CORE, "ips")
<< "Illegal performance value: "
<< static_cast<uint>(performance);
return "Critical";
}

View File

@@ -7,7 +7,7 @@ TEST(configuration, basic_context)
IPSConfiguration::Context ctx1(IPSConfiguration::ContextType::HISTORY, 254);
EXPECT_EQ(ctx1.getType(), IPSConfiguration::ContextType::HISTORY);
EXPECT_EQ(ctx1.getHistorySize(), 254);
EXPECT_EQ(ctx1.getHistorySize(), 254u);
IPSConfiguration::Context ctx2(IPSConfiguration::ContextType::NORMAL, 0);
EXPECT_EQ(ctx2.getType(), IPSConfiguration::ContextType::NORMAL);
@@ -42,7 +42,7 @@ TEST(configuration, read_configuration)
auto body = conf.getContext("HTTP_REQUEST_BODY");
EXPECT_EQ(body.getType(), IPSConfiguration::ContextType::HISTORY);
EXPECT_EQ(conf.getHistorySize("HTTP_REQUEST_BODY"), 100);
EXPECT_EQ(conf.getHistorySize("HTTP_REQUEST_BODY"), 100u);
auto header = conf.getContext("HTTP_REQUEST_HEADER");
EXPECT_EQ(header.getType(), IPSConfiguration::ContextType::KEEP);

View File

@@ -137,8 +137,8 @@ private:
TEST_F(EntryTest, basic_inherited_functions)
{
EXPECT_EQ(IPSEntry::name(), "IPS");
EXPECT_EQ(IPSEntry::currVer(), 0);
EXPECT_EQ(IPSEntry::minVer(), 0);
EXPECT_EQ(IPSEntry::currVer(), 0u);
EXPECT_EQ(IPSEntry::minVer(), 0u);
EXPECT_NE(IPSEntry::prototype(), nullptr);
EXPECT_EQ(entry.getListenerName(), IPSEntry::name());

View File

@@ -71,7 +71,7 @@ TEST(resources, basic_resource)
Singleton::Consume<Config::I_Config>::from(conf)->loadConfiguration(resource);
auto loaded_resources = getSettingWithDefault(IPSSignaturesResource(), "IPS", "protections");
EXPECT_EQ(loaded_resources.getSignatures().size(), 2);
EXPECT_EQ(loaded_resources.getSignatures().size(), 2u);
auto version = getSettingWithDefault<string>("", "IPS", "VersionId");
EXPECT_EQ(version, "1234567");
}

View File

@@ -247,7 +247,9 @@ Layer7AccessControlTest::verifyReport(
string log = reportToStr(report);
dbgTrace(D_L7_ACCESS_CONTROL) << "Report: " << log;
if (!source_identifier.empty()) EXPECT_THAT(log, HasSubstr("\"httpSourceId\": \"" + source_identifier + "\""));
if (!source_identifier.empty()) {
EXPECT_THAT(log, HasSubstr("\"httpSourceId\": \"" + source_identifier + "\""));
}
EXPECT_THAT(log, HasSubstr("\"securityAction\": \"" + security_action + "\""));
EXPECT_THAT(log, HasSubstr("\"eventName\": \"Access Control External Vendor Reputation\""));
EXPECT_THAT(log, HasSubstr("\"httpHostName\": \"juice-shop.checkpoint.com\""));

View File

@@ -228,7 +228,11 @@ AccessControlPracticeSpec::load(cereal::JSONInputArchive &archive_in)
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec practice spec";
parseAppsecJSONKey<string>("name", practice_name, archive_in);
parseAppsecJSONKey<string>("practiceMode", mode, archive_in);
parseAppsecJSONKey<string>("practiceMode", mode, archive_in, "inherited");
if (valid_modes.count(mode) == 0) {
dbgWarning(D_LOCAL_POLICY) << "AppSec Access control practice mode invalid: " << mode;
throw PolicyGenException("AppSec Access control practice mode invalid: " + mode);
}
parseAppsecJSONKey<string>("appsecClassName", appsec_class_name, archive_in);
parseMandatoryAppsecJSONKey<AccessControlRateLimit>("rateLimit", rate_limit, archive_in);
}

View File

@@ -19,7 +19,14 @@ using namespace std;
USE_DEBUG_FLAG(D_LOCAL_POLICY);
// LCOV_EXCL_START Reason: no test exist
static const set<string> valid_modes = {"prevent-learn", "detect-learn", "prevent", "detect", "inactive"};
static const set<string> valid_modes = {
"prevent-learn",
"detect-learn",
"prevent",
"detect",
"inactive",
"as-top-level"
};
static const set<string> valid_confidences = {"medium", "high", "critical"};
void
@@ -138,15 +145,11 @@ AppSecPracticeWebAttacks::load(cereal::JSONInputArchive &archive_in)
dbgWarning(D_LOCAL_POLICY) << "AppSec practice override mode invalid: " << mode;
}
if (getMode() == "Prevent") {
parseAppsecJSONKey<string>("minimum-confidence", minimum_confidence, archive_in, "critical");
if (valid_confidences.count(minimum_confidence) == 0) {
dbgWarning(D_LOCAL_POLICY)
<< "AppSec practice override minimum confidence invalid: "
<< minimum_confidence;
}
} else {
minimum_confidence = "Transparent";
parseAppsecJSONKey<string>("minimum-confidence", minimum_confidence, archive_in, "critical");
if (valid_confidences.count(minimum_confidence) == 0) {
dbgWarning(D_LOCAL_POLICY)
<< "AppSec practice override minimum confidence invalid: "
<< minimum_confidence;
}
parseAppsecJSONKey<int>("max-body-size-kb", max_body_size_kb, archive_in, 1000000);
parseAppsecJSONKey<int>("max-header-size-bytes", max_header_size_bytes, archive_in, 102400);
@@ -189,7 +192,10 @@ AppSecPracticeWebAttacks::getMode(const string &default_mode) const
{
if (isModeInherited(mode) || (key_to_practices_val2.find(mode) == key_to_practices_val2.end())) {
dbgError(D_LOCAL_POLICY) << "Couldn't find a value for key: " << mode << ". Returning " << default_mode;
return default_mode;
if(key_to_practices_val2.find(default_mode) == key_to_practices_val2.end()) {
return default_mode;
}
return key_to_practices_val2.at(default_mode);
}
return key_to_practices_val2.at(mode);
}
@@ -404,6 +410,7 @@ AppsecPracticeAntiBotSection::save(cereal::JSONOutputArchive &out_ar) const
}
// LCOV_EXCL_START Reason: no test exist
// Used for V1Beta1
WebAppSection::WebAppSection(
const string &_application_urls,
const string &_asset_id,
@@ -417,7 +424,7 @@ WebAppSection::WebAppSection(
const LogTriggerSection &parsed_log_trigger,
const string &default_mode,
const AppSecTrustedSources &parsed_trusted_sources,
const vector<InnerException> &parsed_exceptions)
const std::map<std::string, std::vector<InnerException>> &exceptions)
:
application_urls(_application_urls),
asset_id(_asset_id),
@@ -427,21 +434,34 @@ WebAppSection::WebAppSection(
practice_id(_practice_id),
practice_name(_practice_name),
context(_context),
web_attack_mitigation_severity(parsed_appsec_spec.getWebAttacks().getMinimumConfidence()),
web_attack_mitigation_mode(parsed_appsec_spec.getWebAttacks().getMode(default_mode)),
csrf_protection_mode("Disabled"),
open_redirect_mode("Disabled"),
error_disclosure_mode("Disabled"),
schema_validation_mode("Disabled"),
schema_validation_enforce_level("fullSchema"),
practice_advanced_config(parsed_appsec_spec),
anti_bots(parsed_appsec_spec.getAntiBot()),
trusted_sources({ parsed_trusted_sources })
{
auto mitigation_sevirity = parsed_appsec_spec.getWebAttacks().getMinimumConfidence();
if (key_to_mitigation_severity.find(mitigation_sevirity) == key_to_mitigation_severity.end()) {
dbgWarning(D_LOCAL_POLICY)
<< "web attack mitigation severity invalid: "
<< mitigation_sevirity;
throw PolicyGenException("web attack mitigation severity invalid: " + mitigation_sevirity);
} else {
web_attack_mitigation_severity = key_to_mitigation_severity.at(mitigation_sevirity);
}
web_attack_mitigation = web_attack_mitigation_mode != "Disabled";
web_attack_mitigation_severity =
web_attack_mitigation_mode != "Prevent" ? "Transparent" :
web_attack_mitigation_severity;
web_attack_mitigation_action =
web_attack_mitigation_mode != "Prevent" ? "Transparent" :
web_attack_mitigation_severity == "critical" ? "low" :
web_attack_mitigation_severity == "high" ? "balanced" :
web_attack_mitigation_severity == "medium" ? "high" :
web_attack_mitigation_severity == "Critical" ? "Low" :
web_attack_mitigation_severity == "High" ? "Balanced" :
web_attack_mitigation_severity == "Medium" ? "High" :
"Error";
triggers.push_back(TriggersInWaapSection(parsed_log_trigger));
@@ -449,8 +469,11 @@ WebAppSection::WebAppSection(
overrides.push_back(AppSecOverride(source_ident));
}
for (const InnerException &exception : parsed_exceptions) {
overrides.push_back(AppSecOverride(exception));
for (const auto &exception : exceptions) {
for (const auto &inner_exception : exception.second) {
overrides.push_back(AppSecOverride(inner_exception));
}
}
}
@@ -466,6 +489,10 @@ WebAppSection::WebAppSection(
const string &_context,
const string &_web_attack_mitigation_severity,
const string &_web_attack_mitigation_mode,
const string &_bot_protection,
const string &_schema_validation_mode,
const string &_schema_validation_enforce_level,
const vector<string> &_schema_validation_oas,
const PracticeAdvancedConfig &_practice_advanced_config,
const AppsecPracticeAntiBotSection &_anti_bots,
const LogTriggerSection &parsed_log_trigger,
@@ -480,18 +507,29 @@ WebAppSection::WebAppSection(
practice_id(_practice_id),
practice_name(_practice_name),
context(_context),
web_attack_mitigation_severity(_web_attack_mitigation_severity),
web_attack_mitigation_mode(_web_attack_mitigation_mode),
bot_protection(_bot_protection),
schema_validation_mode(_schema_validation_mode),
schema_validation_enforce_level(_schema_validation_enforce_level),
schema_validation_oas(_schema_validation_oas),
practice_advanced_config(_practice_advanced_config),
anti_bots(_anti_bots),
trusted_sources({ parsed_trusted_sources })
{
if (key_to_mitigation_severity.find(_web_attack_mitigation_severity) == key_to_mitigation_severity.end()) {
dbgWarning(D_LOCAL_POLICY)
<< "web attack mitigation severity invalid: "
<< _web_attack_mitigation_severity;
throw PolicyGenException("web attack mitigation severity invalid: " + _web_attack_mitigation_severity);
} else {
web_attack_mitigation_severity = key_to_mitigation_severity.at(_web_attack_mitigation_severity);
}
web_attack_mitigation = web_attack_mitigation_mode != "Disabled";
web_attack_mitigation_action =
web_attack_mitigation_mode != "Prevent" ? "Transparent" :
web_attack_mitigation_severity == "critical" ? "low" :
web_attack_mitigation_severity == "high" ? "balanced" :
web_attack_mitigation_severity == "medium" ? "high" :
web_attack_mitigation_severity == "Critical" ? "Low" :
web_attack_mitigation_severity == "High" ? "Balanced" :
web_attack_mitigation_severity == "Medium" ? "High" :
"Error";
csrf_protection_mode = protections.getCsrfProtectionMode(_web_attack_mitigation_mode);
@@ -502,6 +540,7 @@ WebAppSection::WebAppSection(
for (const SourcesIdentifiers &source_ident : parsed_trusted_sources.getSourcesIdentifiers()) {
overrides.push_back(AppSecOverride(source_ident));
}
}
// LCOV_EXCL_STOP
@@ -509,36 +548,35 @@ WebAppSection::WebAppSection(
void
WebAppSection::save(cereal::JSONOutputArchive &out_ar) const
{
string disabled_str = "Disabled";
string detect_str = "Detect";
vector<string> empty_list;
out_ar(
cereal::make_nvp("context", context),
cereal::make_nvp("webAttackMitigation", web_attack_mitigation),
cereal::make_nvp("webAttackMitigationSeverity", web_attack_mitigation_severity),
cereal::make_nvp("webAttackMitigationAction", web_attack_mitigation_action),
cereal::make_nvp("webAttackMitigationMode", web_attack_mitigation_mode),
cereal::make_nvp("practiceAdvancedConfig", practice_advanced_config),
cereal::make_nvp("csrfProtection", csrf_protection_mode),
cereal::make_nvp("openRedirect", open_redirect_mode),
cereal::make_nvp("errorDisclosure", error_disclosure_mode),
cereal::make_nvp("practiceId", practice_id),
cereal::make_nvp("practiceName", practice_name),
cereal::make_nvp("assetId", asset_id),
cereal::make_nvp("assetName", asset_name),
cereal::make_nvp("ruleId", rule_id),
cereal::make_nvp("ruleName", rule_name),
cereal::make_nvp("schemaValidation", false),
cereal::make_nvp("schemaValidation_v2", disabled_str),
cereal::make_nvp("oas", empty_list),
cereal::make_nvp("triggers", triggers),
cereal::make_nvp("applicationUrls", application_urls),
cereal::make_nvp("overrides", overrides),
cereal::make_nvp("trustedSources", trusted_sources),
cereal::make_nvp("waapParameters", empty_list),
cereal::make_nvp("botProtection", false),
cereal::make_nvp("antiBot", anti_bots),
cereal::make_nvp("botProtection_v2", detect_str)
cereal::make_nvp("context", context),
cereal::make_nvp("webAttackMitigation", web_attack_mitigation),
cereal::make_nvp("webAttackMitigationSeverity", web_attack_mitigation_severity),
cereal::make_nvp("webAttackMitigationAction", web_attack_mitigation_action),
cereal::make_nvp("webAttackMitigationMode", web_attack_mitigation_mode),
cereal::make_nvp("practiceAdvancedConfig", practice_advanced_config),
cereal::make_nvp("csrfProtection", csrf_protection_mode),
cereal::make_nvp("openRedirect", open_redirect_mode),
cereal::make_nvp("errorDisclosure", error_disclosure_mode),
cereal::make_nvp("practiceId", practice_id),
cereal::make_nvp("practiceName", practice_name),
cereal::make_nvp("assetId", asset_id),
cereal::make_nvp("assetName", asset_name),
cereal::make_nvp("ruleId", rule_id),
cereal::make_nvp("ruleName", rule_name),
cereal::make_nvp("schemaValidation", schema_validation_mode == "Prevent"),
cereal::make_nvp("schemaValidation_v2", schema_validation_mode),
cereal::make_nvp("oas", schema_validation_oas),
cereal::make_nvp("schemaValidationEnforceLevel", schema_validation_enforce_level),
cereal::make_nvp("triggers", triggers),
cereal::make_nvp("applicationUrls", application_urls),
cereal::make_nvp("overrides", overrides),
cereal::make_nvp("trustedSources", trusted_sources),
cereal::make_nvp("waapParameters", empty_list),
cereal::make_nvp("botProtection", false),
cereal::make_nvp("antiBot", anti_bots),
cereal::make_nvp("botProtection_v2", bot_protection != "" ? bot_protection : string("Detect"))
);
}

View File

@@ -146,7 +146,9 @@ AppsecException::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec exception";
parseAppsecJSONKey<string>("name", name, archive_in);
archive_in(CEREAL_NVP(exception_spec));
AppsecExceptionSpec single_exception_spec;
single_exception_spec.load(archive_in);
exception_spec.push_back(single_exception_spec);
}
void
@@ -174,7 +176,7 @@ ExceptionMatch::ExceptionMatch(const AppsecExceptionSpec &parsed_exception)
{
bool single_condition = parsed_exception.isOneCondition();
for (auto &attrib : attributes) {
auto &attrib_name = attrib.first;
auto attrib_name = (attrib.first == "sourceIp" ? "sourceIP" : attrib.first);
auto &attrib_getter = attrib.second;
auto exceptions_value = attrib_getter(parsed_exception);
if (exceptions_value.empty()) continue;

View File

@@ -275,7 +275,7 @@ public:
const LogTriggerSection &parsed_log_trigger,
const std::string &default_mode,
const AppSecTrustedSources &parsed_trusted_sources,
const std::vector<InnerException> &parsed_exceptions
const std::map<std::string, std::vector<InnerException>> &exceptions
);
// used for V1beta2
@@ -290,6 +290,10 @@ public:
const std::string &_context,
const std::string &_web_attack_mitigation_severity,
const std::string &_web_attack_mitigation_mode,
const std::string &_bot_protection,
const std::string &schema_validation_mode,
const std::string &schema_validation_enforce_level,
const std::vector<std::string> &schema_validation_oas,
const PracticeAdvancedConfig &_practice_advanced_config,
const AppsecPracticeAntiBotSection &_anti_bots,
const LogTriggerSection &parsed_log_trigger,
@@ -301,26 +305,30 @@ public:
bool operator< (const WebAppSection &other) const;
private:
std::string application_urls;
std::string asset_id;
std::string asset_name;
std::string rule_id;
std::string rule_name;
std::string practice_id;
std::string practice_name;
std::string context;
std::string web_attack_mitigation_action;
std::string web_attack_mitigation_severity;
std::string web_attack_mitigation_mode;
std::string csrf_protection_mode;
std::string open_redirect_mode;
std::string error_disclosure_mode;
bool web_attack_mitigation;
std::vector<TriggersInWaapSection> triggers;
PracticeAdvancedConfig practice_advanced_config;
AppsecPracticeAntiBotSection anti_bots;
std::vector<AppSecTrustedSources> trusted_sources;
std::vector<AppSecOverride> overrides;
bool web_attack_mitigation;
std::string application_urls;
std::string asset_id;
std::string asset_name;
std::string rule_id;
std::string rule_name;
std::string practice_id;
std::string practice_name;
std::string context;
std::string web_attack_mitigation_action;
std::string web_attack_mitigation_severity;
std::string web_attack_mitigation_mode;
std::string csrf_protection_mode;
std::string open_redirect_mode;
std::string error_disclosure_mode;
std::string bot_protection;
std::string schema_validation_mode;
std::string schema_validation_enforce_level;
std::vector<std::string> schema_validation_oas;
PracticeAdvancedConfig practice_advanced_config;
AppsecPracticeAntiBotSection anti_bots;
std::vector<AppSecOverride> overrides;
std::vector<AppSecTrustedSources> trusted_sources;
std::vector<TriggersInWaapSection> triggers;
};
class WebAPISection
@@ -408,7 +416,7 @@ class ParsedRule
{
public:
ParsedRule() {}
ParsedRule(const std::string &_host) : host(_host) {}
ParsedRule(const std::string &_host, const std::string &_mode) : host(_host), mode(_mode) {}
void load(cereal::JSONInputArchive &archive_in);
const std::vector<std::string> & getExceptions() const;

View File

@@ -44,7 +44,7 @@ public:
bool isOneCondition() const;
private:
int conditions_number;
int conditions_number = 0;
std::string action;
std::vector<std::string> country_code;
std::vector<std::string> country_name;

View File

@@ -24,6 +24,7 @@
#include "maybe_res.h"
#include "i_orchestration_tools.h"
#include "i_shell_cmd.h"
#include "i_encryptor.h"
#include "i_messaging.h"
#include "i_env_details.h"
#include "i_agent_details.h"
@@ -40,6 +41,7 @@ class K8sPolicyUtils
Singleton::Consume<I_Messaging>,
Singleton::Consume<I_ShellCmd>,
Singleton::Consume<I_EnvDetails>,
Singleton::Consume<I_Encryptor>,
Singleton::Consume<I_AgentDetails>
{
public:
@@ -80,6 +82,8 @@ private:
void createSnortFile(std::vector<NewAppSecPracticeSpec> &practices) const;
void createSchemaValidationOas(std::vector<NewAppSecPracticeSpec> &practices) const;
template<class T>
std::vector<T> extractV1Beta2ElementsFromCluster(
const std::string &crd_plural,
@@ -112,6 +116,7 @@ private:
I_Messaging* messaging = nullptr;
EnvType env_type;
std::string token;
std::string agent_ns;
};
#endif // __K8S_POLICY_UTILS_H__

View File

@@ -49,6 +49,13 @@ static const std::unordered_map<std::string, TriggerType> string_to_trigger_type
{ "WebUserResponse", TriggerType::WebUserResponse }
};
static const std::unordered_map<std::string, std::string> key_to_mitigation_severity = {
{ "high", "High"},
{ "medium", "Medium"},
{ "critical", "Critical"},
{ "Transparent", "Transparent"}
};
static const std::unordered_map<std::string, std::string> key_to_practices_val = {
{ "prevent-learn", "Prevent"},
{ "detect-learn", "Learn"},
@@ -57,6 +64,14 @@ static const std::unordered_map<std::string, std::string> key_to_practices_val =
{ "inactive", "Inactive"}
};
static const std::unordered_map<std::string, std::string> key_to_practices_mode_val = {
{ "prevent-learn", "Prevent"},
{ "detect-learn", "Detect"},
{ "prevent", "Prevent"},
{ "detect", "Detect"},
{ "inactive", "Disabled"}
};
static const std::unordered_map<std::string, std::string> key_to_practices_val2 = {
{ "prevent-learn", "Prevent"},
{ "detect-learn", "Learn"},
@@ -66,6 +81,8 @@ static const std::unordered_map<std::string, std::string> key_to_practices_val2
};
static const std::string default_appsec_url = "http://*:*";
static const std::string default_appsec_name = "Any";
class PolicyGenException : public std::exception
{

View File

@@ -31,7 +31,7 @@ class NewParsedRule
{
public:
NewParsedRule() {}
NewParsedRule(const std::string &_host) : host(_host) {}
NewParsedRule(const std::string &_host, const std::string &_mode) : host(_host), mode(_mode) {}
void load(cereal::JSONInputArchive &archive_in);

View File

@@ -23,6 +23,8 @@
#include "config.h"
#include "debug.h"
#include "local_policy_common.h"
#include "i_orchestration_tools.h"
#include "i_encryptor.h"
bool isModeInherited(const std::string &mode);
@@ -88,6 +90,8 @@ public:
void save(cereal::JSONOutputArchive &out_ar) const;
bool operator<(const IpsProtectionsSection &other) const;
private:
std::string context;
std::string name;
@@ -105,7 +109,7 @@ public:
// LCOV_EXCL_START Reason: no test exist
IPSSection() {};
IPSSection(const std::vector<IpsProtectionsSection> &_ips) : ips(_ips) {};
IPSSection(const std::vector<IpsProtectionsSection> &_ips);
// LCOV_EXCL_STOP
void save(cereal::JSONOutputArchive &out_ar) const;
@@ -138,6 +142,12 @@ public:
const std::string & getMode(const std::string &default_mode = "inactive") const;
private:
const std::string & getRulesMode(
const std::string &mode,
const std::string &default_mode = "inactive"
) const;
std::string override_mode;
std::string max_performance_impact;
std::string min_severity_level;
@@ -487,15 +497,16 @@ private:
SnortSection snort;
};
class NewSnortSignaturesAndOpenSchemaAPI
class NewSnortSignatures
{
public:
NewSnortSignaturesAndOpenSchemaAPI() : is_temporary(false) {};
NewSnortSignatures() : is_temporary(false) {};
void load(cereal::JSONInputArchive &archive_in);
void addFile(const std::string &file_name);
const std::string & getOverrideMode(const std::string &default_mode = "inactive") const;
const std::string & getEnforceLevel() const;
const std::vector<std::string> & getConfigMap() const;
const std::vector<std::string> & getFiles() const;
bool isTemporary() const;
@@ -503,35 +514,48 @@ public:
private:
std::string override_mode;
std::string enforcement_level;
std::vector<std::string> config_map;
std::vector<std::string> files;
bool is_temporary;
};
class NewAppSecWebBotsURI
class NewOpenApiSchema : Singleton::Consume<I_OrchestrationTools>, Singleton::Consume<I_Encryptor>
{
public:
NewOpenApiSchema() {};
void load(cereal::JSONInputArchive &archive_in);
const std::string & getURI() const;
void addOas(const std::string &file);
const std::string & getOverrideMode(const std::string &default_mode = "inactive") const;
const std::string & getEnforceLevel() const;
const std::vector<std::string> & getConfigMap() const;
const std::vector<std::string> & getFiles() const;
const std::vector<std::string> & getOas() const;
private:
std::string uri;
std::string override_mode;
std::string enforcement_level;
std::vector<std::string> config_map;
std::vector<std::string> files;
std::vector<std::string> oas;
};
class NewAppSecPracticeAntiBot
{
public:
std::vector<std::string> getIjectedUris() const;
std::vector<std::string> getValidatedUris() const;
const std::vector<std::string> & getIjectedUris() const;
const std::vector<std::string> & getValidatedUris() const;
const std::string & getMode(const std::string &default_mode = "inactive") const;
void load(cereal::JSONInputArchive &archive_in);
void save(cereal::JSONOutputArchive &out_ar) const;
private:
std::string override_mode;
std::vector<NewAppSecWebBotsURI> injected_uris;
std::vector<NewAppSecWebBotsURI> validated_uris;
std::vector<std::string> injected_uris;
std::vector<std::string> validated_uris;
};
class NewAppSecWebAttackProtections
@@ -579,8 +603,8 @@ class NewAppSecPracticeSpec
public:
void load(cereal::JSONInputArchive &archive_in);
NewSnortSignaturesAndOpenSchemaAPI & getSnortSignatures();
const NewSnortSignaturesAndOpenSchemaAPI & getOpenSchemaValidation() const;
NewSnortSignatures & getSnortSignatures();
NewOpenApiSchema & getOpenSchemaValidation();
const NewAppSecPracticeWebAttacks & getWebAttacks() const;
const NewAppSecPracticeAntiBot & getAntiBot() const;
const NewIntrusionPrevention & getIntrusionPrevention() const;
@@ -593,8 +617,8 @@ public:
private:
NewFileSecurity file_security;
NewIntrusionPrevention intrusion_prevention;
NewSnortSignaturesAndOpenSchemaAPI openapi_schema_validation;
NewSnortSignaturesAndOpenSchemaAPI snort_signatures;
NewOpenApiSchema openapi_schema_validation;
NewSnortSignatures snort_signatures;
NewAppSecPracticeWebAttacks web_attacks;
NewAppSecPracticeAntiBot anti_bot;
std::string appsec_class_name;

View File

@@ -123,6 +123,7 @@ public:
);
const std::string & getIdentifier() const;
const std::string & getIdentifierValue() const;
void save(cereal::JSONOutputArchive &out_ar) const;
@@ -145,6 +146,7 @@ public:
);
const std::string & getIdentifier() const;
const std::string & getIdentifierValue() const;
void save(cereal::JSONOutputArchive &out_ar) const;

View File

@@ -39,7 +39,7 @@ public:
bool _logToAgent,
bool _logToCef,
bool _logToCloud,
bool _logToContainerService,
bool _logTolocalTuning,
bool _logToSyslog,
bool _responseBody,
bool _tpDetect,
@@ -73,7 +73,7 @@ private:
bool logToAgent;
bool logToCef;
bool logToCloud;
bool logToContainerService;
bool logTolocalTuning;
bool logToSyslog;
bool responseBody;
bool tpDetect;

View File

@@ -35,6 +35,14 @@ convertAnnotationKeysTostring(const AnnotationKeys &key)
}
}
string
getAppSecScopeType()
{
auto env_res = getenv("CRDS_SCOPE");
if (env_res != nullptr) return env_res;
return "cluster";
}
void
K8sPolicyUtils::init()
{
@@ -42,6 +50,7 @@ K8sPolicyUtils::init()
env_type = env_details->getEnvType();
if (env_type == EnvType::K8S) {
token = env_details->getToken();
agent_ns = getAppSecScopeType() == "namespaced" ? env_details->getNameSpace() + "/" : "";
messaging = Singleton::Consume<I_Messaging>::by<K8sPolicyUtils>();
}
}
@@ -140,10 +149,12 @@ extractElementsFromNewRule(
const NewParsedRule &rule,
map<AnnotationTypes, unordered_set<string>> &policy_elements_names)
{
policy_elements_names[AnnotationTypes::EXCEPTION].insert(
rule.getExceptions().begin(),
rule.getExceptions().end()
);
if (rule.getExceptions().size() > 0) {
policy_elements_names[AnnotationTypes::EXCEPTION].insert(
rule.getExceptions().begin(),
rule.getExceptions().end()
);
}
policy_elements_names[AnnotationTypes::THREAT_PREVENTION_PRACTICE].insert(
rule.getPractices().begin(),
rule.getPractices().end()
@@ -152,14 +163,24 @@ extractElementsFromNewRule(
rule.getAccessControlPractices().begin(),
rule.getAccessControlPractices().end()
);
policy_elements_names[AnnotationTypes::TRIGGER].insert(
rule.getLogTriggers().begin(),
rule.getLogTriggers().end()
);
policy_elements_names[AnnotationTypes::WEB_USER_RES].insert(rule.getCustomResponse());
policy_elements_names[AnnotationTypes::SOURCE_IDENTIFIERS].insert(rule.getSourceIdentifiers());
policy_elements_names[AnnotationTypes::TRUSTED_SOURCES].insert(rule.getTrustedSources());
policy_elements_names[AnnotationTypes::UPGRADE_SETTINGS].insert(rule.getUpgradeSettings());
if (rule.getLogTriggers().size() > 0) {
policy_elements_names[AnnotationTypes::TRIGGER].insert(
rule.getLogTriggers().begin(),
rule.getLogTriggers().end()
);
}
if (rule.getCustomResponse() != "" ) {
policy_elements_names[AnnotationTypes::WEB_USER_RES].insert(rule.getCustomResponse());
}
if (rule.getSourceIdentifiers() != "" ) {
policy_elements_names[AnnotationTypes::SOURCE_IDENTIFIERS].insert(rule.getSourceIdentifiers());
}
if (rule.getTrustedSources() != "" ) {
policy_elements_names[AnnotationTypes::TRUSTED_SOURCES].insert(rule.getTrustedSources());
}
if (rule.getUpgradeSettings() != "" ) {
policy_elements_names[AnnotationTypes::UPGRADE_SETTINGS].insert(rule.getUpgradeSettings());
}
}
map<AnnotationTypes, unordered_set<string>>
@@ -259,9 +280,11 @@ K8sPolicyUtils::extractV1Beta2ElementsFromCluster(
dbgTrace(D_LOCAL_POLICY) << "Retrieve AppSec elements. type: " << crd_plural;
vector<T> elements;
for (const string &element_name : elements_names) {
string ns_suffix = getAppSecScopeType() == "namespaced" ? "ns" : "";
string ns = getAppSecScopeType() == "namespaced" ? "namespaces/" : "";
dbgTrace(D_LOCAL_POLICY) << "AppSec element name: " << element_name;
auto maybe_appsec_element = getObjectFromCluster<AppsecSpecParser<T>>(
"/apis/openappsec.io/v1beta2/" + crd_plural + "/" + element_name
"/apis/openappsec.io/v1beta2/" + ns + agent_ns + crd_plural + ns_suffix + "/" + element_name
);
if (!maybe_appsec_element.ok()) {
@@ -362,8 +385,9 @@ K8sPolicyUtils::createSnortFile(vector<NewAppSecPracticeSpec> &practices) const
practice.getSnortSignatures().setTemporary(true);
for (const string &config_map : practice.getSnortSignatures().getConfigMap())
{
string ns = agent_ns == "" ? "default/" : agent_ns;
auto maybe_configmap = getObjectFromCluster<ConfigMaps>(
"/api/v1/namespaces/default/configmaps/" + config_map
"/api/v1/namespaces/" + ns + "configmaps/" + config_map
);
if (!maybe_configmap.ok()) {
dbgWarning(D_LOCAL_POLICY) << "Failed to get configMaps from the cluster.";
@@ -381,6 +405,28 @@ K8sPolicyUtils::createSnortFile(vector<NewAppSecPracticeSpec> &practices) const
}
}
void
K8sPolicyUtils::createSchemaValidationOas(vector<NewAppSecPracticeSpec> &practices) const
{
for (NewAppSecPracticeSpec &practice : practices) {
vector<string> res;
for (const string &config_map : practice.getOpenSchemaValidation().getConfigMap())
{
string ns = agent_ns == "" ? "default/" : agent_ns;
auto maybe_configmap = getObjectFromCluster<ConfigMaps>(
"/api/v1/namespaces/" + ns + "configmaps/" + config_map
);
if (!maybe_configmap.ok()) {
dbgWarning(D_LOCAL_POLICY) << "Failed to get configMaps from the cluster.";
continue;
}
string file_content = maybe_configmap.unpack().getFileContent();
string res = Singleton::Consume<I_Encryptor>::by<K8sPolicyUtils>()->base64Encode(file_content);
practice.getOpenSchemaValidation().addOas(res);
}
}
}
Maybe<V1beta2AppsecLinuxPolicy>
K8sPolicyUtils::createAppsecPolicyK8sFromV1beta2Crds(
const AppsecSpecParser<NewAppsecPolicySpec> &appsec_policy_spec,
@@ -396,6 +442,7 @@ K8sPolicyUtils::createAppsecPolicyK8sFromV1beta2Crds(
}
if (default_rule.getMode().empty() && !ingress_mode.empty()) {
dbgTrace(D_LOCAL_POLICY) << "setting the policy default rule mode to the ingress mode: " << ingress_mode;
default_rule.setMode(ingress_mode);
}
@@ -411,6 +458,7 @@ K8sPolicyUtils::createAppsecPolicyK8sFromV1beta2Crds(
);
createSnortFile(threat_prevention_practices);
createSchemaValidationOas(threat_prevention_practices);
vector<AccessControlPracticeSpec> access_control_practices =
extractV1Beta2ElementsFromCluster<AccessControlPracticeSpec>(
@@ -493,9 +541,12 @@ K8sPolicyUtils::createAppsecPolicyK8s(const string &policy_name, const string &i
maybe_appsec_policy_spec.ok() ? "There is no v1beta1 policy" : maybe_appsec_policy_spec.getErr();
dbgWarning(D_LOCAL_POLICY
) << "Failed to retrieve Appsec policy with crds version: v1beta1, Trying version: v1beta2";
string ns_suffix = getAppSecScopeType() == "namespaced" ? "ns" : "";
string ns = getAppSecScopeType() == "namespaced" ? "namespaces/" : "";
auto maybe_v1beta2_appsec_policy_spec = getObjectFromCluster<AppsecSpecParser<NewAppsecPolicySpec>>(
"/apis/openappsec.io/v1beta2/policies/" + policy_name
"/apis/openappsec.io/v1beta2/" + ns + agent_ns + "policies" + ns_suffix + "/" + policy_name
);
if (!maybe_v1beta2_appsec_policy_spec.ok()) {
dbgWarning(D_LOCAL_POLICY)
<< "Failed to retrieve AppSec policy. Error: " << maybe_v1beta2_appsec_policy_spec.getErr();
@@ -535,25 +586,29 @@ K8sPolicyUtils::createPolicy(
if (policies.find(annotations_values[AnnotationKeys::PolicyKey]) == policies.end()) {
policies[annotations_values[AnnotationKeys::PolicyKey]] = appsec_policy;
}
auto default_mode = appsec_policy.getAppsecPolicySpec().getDefaultRule().getMode();
if (item.getSpec().doesDefaultBackendExist()) {
dbgTrace(D_LOCAL_POLICY)
<< "Inserting Any host rule to the specific asset set";
K ingress_rule = K("*");
K ingress_rule = K("*", default_mode);
policies[annotations_values[AnnotationKeys::PolicyKey]].addSpecificRule(ingress_rule);
}
for (const IngressDefinedRule &rule : item.getSpec().getRules()) {
string url = rule.getHost();
string host = rule.getHost();
for (const IngressRulePath &uri : rule.getPathsWrapper().getRulePaths()) {
if (!appsec_policy.getAppsecPolicySpec().isAssetHostExist(url + uri.getPath())) {
if (uri.getPath() != "/") {
host = host + uri.getPath();
}
if (!appsec_policy.getAppsecPolicySpec().isAssetHostExist(host)) {
dbgTrace(D_LOCAL_POLICY)
<< "Inserting Host data to the specific asset set:"
<< "URL: '"
<< url
<< rule.getHost()
<< "' uri: '"
<< uri.getPath()
<< "'";
K ingress_rule = K(url + uri.getPath());
K ingress_rule = K(host, default_mode);
policies[annotations_values[AnnotationKeys::PolicyKey]].addSpecificRule(ingress_rule);
}
}

View File

@@ -180,12 +180,16 @@ NewAppsecTriggerLogDestination::load(cereal::JSONInputArchive &archive_in)
} else {
cloud = false;
}
auto mode = Singleton::Consume<I_AgentDetails>::by<NewAppsecTriggerLogDestination>()->getOrchestrationMode();
auto env_type = Singleton::Consume<I_EnvDetails>::by<NewAppsecTriggerLogDestination>()->getEnvType();
bool k8s_service_default = (mode == OrchestrationMode::HYBRID && env_type == EnvType::K8S);
// BC try load previous name. TODO: update CRD
parseAppsecJSONKey<bool>("k8s-service", container_service, archive_in, k8s_service_default);
parseAppsecJSONKey<bool>("container-service", container_service, archive_in, container_service);
bool local_tuning_default = false;
// check ENV VAR LOCAL_TUNING_ENABLED
char * tuning_enabled = getenv("LOCAL_TUNING_ENABLED");
if (tuning_enabled != NULL) {
for (unsigned int i = 0; i < strlen(tuning_enabled); i++) {
tuning_enabled[i] = tolower(tuning_enabled[i]);
}
local_tuning_default = string(tuning_enabled) == "true";
}
parseAppsecJSONKey<bool>("local-tuning", container_service, archive_in, local_tuning_default);
NewStdoutLogging stdout_log;
parseAppsecJSONKey<NewStdoutLogging>("stdout", stdout_log, archive_in);

View File

@@ -22,6 +22,7 @@ static const set<string> performance_impacts = {"low", "medium", "high"};
static const set<string> severity_levels = {"low", "medium", "high", "critical"};
static const set<string> size_unit = {"bytes", "KB", "MB", "GB"};
static const set<string> confidences_actions = {"prevent", "detect", "inactive", "as-top-level", "inherited"};
static const set<string> valied_enforcement_level = {"fullSchema", "endpointOnly"};
static const set<string> valid_modes = {
"prevent",
"detect",
@@ -32,31 +33,38 @@ static const set<string> valid_modes = {
"inherited"
};
static const set<string> valid_confidences = {"medium", "high", "critical"};
static const std::unordered_map<std::string, std::string> key_to_performance_impact_val = {
static const unordered_map<string, string> key_to_performance_impact_val = {
{ "low", "Low or lower"},
{ "medium", "Medium or lower"},
{ "high", "High or lower"}
};
static const std::unordered_map<std::string, std::string> key_to_severity_level_val = {
static const unordered_map<string, string> key_to_severity_level_val = {
{ "low", "Low or above"},
{ "medium", "Medium or above"},
{ "high", "High or above"},
{ "critical", "Critical"}
};
static const std::unordered_map<std::string, std::string> key_to_mode_val = {
static const unordered_map<string, string> key_to_mode_val = {
{ "prevent-learn", "Prevent"},
{ "detect-learn", "Detect"},
{ "prevent", "Prevent"},
{ "detect", "Detect"},
{ "inactive", "Inactive"}
};
static const std::unordered_map<std::string, uint64_t> unit_to_int = {
static const unordered_map<string, string> anti_bot_key_to_mode_val = {
{ "prevent-learn", "Prevent"},
{ "detect-learn", "Detect"},
{ "prevent", "Prevent"},
{ "detect", "Detect"},
{ "inactive", "Disabled"}
};
static const unordered_map<string, uint64_t> unit_to_int = {
{ "bytes", 1},
{ "KB", 1024},
{ "MB", 1048576},
{ "GB", 1073741824}
};
static const std::string TRANSPARENT_MODE = "Transparent";
static const string TRANSPARENT_MODE = "Transparent";
bool
isModeInherited(const string &mode)
@@ -64,11 +72,11 @@ isModeInherited(const string &mode)
return mode == "as-top-level" || mode == "inherited";
}
const std::string &
const string &
getModeWithDefault(
const std::string &mode,
const std::string &default_mode,
const std::unordered_map<std::string, std::string> &key_to_val)
const string &mode,
const string &default_mode,
const unordered_map<string, string> &key_to_val)
{
if (isModeInherited(mode) && (key_to_val.find(default_mode) != key_to_val.end())) {
dbgError(D_LOCAL_POLICY) << "Setting to top-level mode: " << default_mode;
@@ -81,57 +89,43 @@ getModeWithDefault(
return key_to_val.at(mode);
}
void
NewAppSecWebBotsURI::load(cereal::JSONInputArchive &archive_in)
const vector<string> &
NewAppSecPracticeAntiBot::getIjectedUris() const
{
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec Web Bots URI";
parseAppsecJSONKey<string>("uri", uri, archive_in);
return injected_uris;
}
const vector<string> &
NewAppSecPracticeAntiBot::getValidatedUris() const
{
return validated_uris;
}
const string &
NewAppSecWebBotsURI::getURI() const
NewAppSecPracticeAntiBot::getMode(const string &default_mode) const
{
return uri;
}
std::vector<std::string>
NewAppSecPracticeAntiBot::getIjectedUris() const
{
vector<string> injected;
for (const NewAppSecWebBotsURI &uri : injected_uris) injected.push_back(uri.getURI());
return injected;
}
std::vector<std::string>
NewAppSecPracticeAntiBot::getValidatedUris() const
{
vector<string> validated;
for (const NewAppSecWebBotsURI &uri : validated_uris) validated.push_back(uri.getURI());
return validated;
return getModeWithDefault(override_mode, default_mode, anti_bot_key_to_mode_val);
}
void
NewAppSecPracticeAntiBot::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec Web Bots";
parseAppsecJSONKey<vector<NewAppSecWebBotsURI>>("injectedUris", injected_uris, archive_in);
parseAppsecJSONKey<vector<NewAppSecWebBotsURI>>("validatedUris", validated_uris, archive_in);
parseAppsecJSONKey<vector<string>>("injectedUris", injected_uris, archive_in);
parseAppsecJSONKey<vector<string>>("validatedUris", validated_uris, archive_in);
parseMandatoryAppsecJSONKey<string>("overrideMode", override_mode, archive_in, "inactive");
if (valid_modes.count(override_mode) == 0) {
dbgWarning(D_LOCAL_POLICY) << "AppSec Web Bots override mode invalid: " << override_mode;
throw PolicyGenException("AppSec Web Bots override mode invalid: " + override_mode);
}
}
void
NewAppSecPracticeAntiBot::save(cereal::JSONOutputArchive &out_ar) const
{
vector<string> injected;
vector<string> validated;
for (const NewAppSecWebBotsURI &uri : injected_uris) injected.push_back(uri.getURI());
for (const NewAppSecWebBotsURI &uri : validated_uris) validated.push_back(uri.getURI());
out_ar(
cereal::make_nvp("injected", injected),
cereal::make_nvp("validated", validated)
cereal::make_nvp("injected", injected_uris),
cereal::make_nvp("validated", validated_uris)
);
}
@@ -248,14 +242,14 @@ NewAppSecPracticeWebAttacks::getProtections() const
}
SnortProtectionsSection::SnortProtectionsSection(
const std::string &_context,
const std::string &_asset_name,
const std::string &_asset_id,
const std::string &_practice_name,
const std::string &_practice_id,
const std::string &_source_identifier,
const std::string &_mode,
const std::vector<std::string> &_files)
const string &_context,
const string &_asset_name,
const string &_asset_id,
const string &_practice_name,
const string &_practice_id,
const string &_source_identifier,
const string &_mode,
const vector<string> &_files)
:
context(_context),
asset_name(_asset_name),
@@ -284,10 +278,10 @@ SnortProtectionsSection::save(cereal::JSONOutputArchive &out_ar) const
}
DetectionRules::DetectionRules(
const std::string &_type,
const std::string &_SSM,
const std::string &_keywords,
const std::vector<std::string> &_context)
const string &_type,
const string &_SSM,
const string &_keywords,
const vector<string> &_context)
:
type(_type),
SSM(_SSM),
@@ -320,14 +314,14 @@ DetectionRules::save(cereal::JSONOutputArchive &out_ar) const
ProtectionMetadata::ProtectionMetadata(
bool _silent,
const std::string &_protection_name,
const std::string &_severity,
const std::string &_confidence_level,
const std::string &_performance_impact,
const std::string &_last_update,
const std::string &_maintrain_id,
const std::vector<std::string> &_tags,
const std::vector<std::string> &_cve_list)
const string &_protection_name,
const string &_severity,
const string &_confidence_level,
const string &_performance_impact,
const string &_last_update,
const string &_maintrain_id,
const vector<string> &_tags,
const vector<string> &_cve_list)
:
silent(_silent),
protection_name(_protection_name),
@@ -400,9 +394,9 @@ ProtectionsProtectionsSection::save(cereal::JSONOutputArchive &out_ar) const
}
ProtectionsSection::ProtectionsSection(
const std::vector<ProtectionsProtectionsSection> &_protections,
const std::string &_name,
const std::string &_modification_time)
const vector<ProtectionsProtectionsSection> &_protections,
const string &_name,
const string &_modification_time)
:
protections(_protections),
name(_name),
@@ -466,12 +460,16 @@ SnortSectionWrapper::save(cereal::JSONOutputArchive &out_ar) const
}
void
NewSnortSignaturesAndOpenSchemaAPI::load(cereal::JSONInputArchive &archive_in)
NewSnortSignatures::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec Snort Signatures practice";
parseMandatoryAppsecJSONKey<string>("overrideMode", override_mode, archive_in, "inactive");
parseAppsecJSONKey<vector<string>>("configmap", config_map, archive_in);
parseAppsecJSONKey<vector<string>>("files", files, archive_in);
if (valid_modes.count(override_mode) == 0) {
dbgWarning(D_LOCAL_POLICY) << "AppSec Snort Signatures override mode invalid: " << override_mode;
throw PolicyGenException("AppSec Snort Signatures override mode invalid: " + override_mode);
}
is_temporary = false;
if (valid_modes.count(override_mode) == 0) {
dbgWarning(D_LOCAL_POLICY) << "AppSec Snort Signatures override mode invalid: " << override_mode;
@@ -480,42 +478,107 @@ NewSnortSignaturesAndOpenSchemaAPI::load(cereal::JSONInputArchive &archive_in)
}
void
NewSnortSignaturesAndOpenSchemaAPI::addFile(const string &file_name)
NewSnortSignatures::addFile(const string &file_name)
{
files.push_back(file_name);
}
const string &
NewSnortSignaturesAndOpenSchemaAPI::getOverrideMode(const string &default_mode) const
NewSnortSignatures::getOverrideMode(const string &default_mode) const
{
const string &res = getModeWithDefault(override_mode, default_mode, key_to_practices_val);
const string &res = getModeWithDefault(override_mode, default_mode, key_to_practices_mode_val);
return res;
}
const vector<string> &
NewSnortSignaturesAndOpenSchemaAPI::getFiles() const
NewSnortSignatures::getFiles() const
{
return files;
}
const vector<string> &
NewSnortSignaturesAndOpenSchemaAPI::getConfigMap() const
NewSnortSignatures::getConfigMap() const
{
return config_map;
}
bool
NewSnortSignaturesAndOpenSchemaAPI::isTemporary() const
NewSnortSignatures::isTemporary() const
{
return is_temporary;
}
void
NewSnortSignaturesAndOpenSchemaAPI::setTemporary(bool val)
NewSnortSignatures::setTemporary(bool val)
{
is_temporary = val;
}
void
NewOpenApiSchema::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec Schema Validation practice";
parseMandatoryAppsecJSONKey<string>("overrideMode", override_mode, archive_in, "inactive");
parseAppsecJSONKey<vector<string>>("configmap", config_map, archive_in);
parseAppsecJSONKey<vector<string>>("files", files, archive_in);
parseAppsecJSONKey<string>("enforcementLevel", enforcement_level, archive_in, "fullSchema");
if (valied_enforcement_level.count(enforcement_level) == 0) {
dbgWarning(D_LOCAL_POLICY) << "AppSec Schema Validation enforcement level invalid: " << enforcement_level;
throw PolicyGenException("AppSec Schema Validation enforcement level invalid: " + enforcement_level);
}
if (valid_modes.count(override_mode) == 0) {
dbgWarning(D_LOCAL_POLICY) << "AppSec Schema Validation override mode invalid: " << override_mode;
throw PolicyGenException("AppSec Schema Validation override mode invalid: " + override_mode);
}
for (const string &file : files)
{
auto i_orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<NewOpenApiSchema>();
auto file_content = i_orchestration_tools->readFile(file);
if (!file_content.ok()) {
dbgWarning(D_LOCAL_POLICY) << "Couldn't open the schema validation file";
continue;
}
oas.push_back(Singleton::Consume<I_Encryptor>::by<NewOpenApiSchema>()->base64Encode(file_content.unpack()));
}
}
void
NewOpenApiSchema::addOas(const string &file)
{
oas.push_back(file);
}
const string &
NewOpenApiSchema::getOverrideMode(const string &default_mode) const
{
const string &res = getModeWithDefault(override_mode, default_mode, key_to_practices_val2);
return res;
}
const string &
NewOpenApiSchema::getEnforceLevel() const
{
return enforcement_level;
}
const vector<string> &
NewOpenApiSchema::getFiles() const
{
return files;
}
const vector<string> &
NewOpenApiSchema::getConfigMap() const
{
return config_map;
}
const vector<string> &
NewOpenApiSchema::getOas() const
{
return oas;
}
void
IpsProtectionsRulesSection::save(cereal::JSONOutputArchive &out_ar) const
{
@@ -554,7 +617,7 @@ IpsProtectionsSection::IpsProtectionsSection(
{
}
std::string &
string &
IpsProtectionsSection::getMode()
{
return mode;
@@ -576,6 +639,20 @@ IpsProtectionsSection::save(cereal::JSONOutputArchive &out_ar) const
);
}
bool
IpsProtectionsSection::operator<(const IpsProtectionsSection &other) const
{
// for sorting from the most specific to the least specific rule
if (name == default_appsec_name) return false;
if (other.name == default_appsec_name) return true;
return name.size() > other.name.size();
}
IPSSection::IPSSection(const vector<IpsProtectionsSection> &_ips) : ips(_ips)
{
sort(ips.begin(), ips.end());
}
void
IPSSection::save(cereal::JSONOutputArchive &out_ar) const
{
@@ -654,7 +731,7 @@ NewIntrusionPrevention::createIpsRules(const string &default_mode) const
vector<IpsProtectionsRulesSection> ips_rules;
IpsProtectionsRulesSection high_rule(
min_cve_Year,
getModeWithDefault(high_confidence_event_action, default_mode, key_to_practices_val),
getRulesMode(high_confidence_event_action, default_mode),
string("High"),
max_performance_impact,
string(""),
@@ -664,7 +741,7 @@ NewIntrusionPrevention::createIpsRules(const string &default_mode) const
IpsProtectionsRulesSection med_rule(
min_cve_Year,
getModeWithDefault(medium_confidence_event_action, default_mode, key_to_practices_val),
getRulesMode(medium_confidence_event_action, default_mode),
string("Medium"),
max_performance_impact,
string(""),
@@ -674,7 +751,7 @@ NewIntrusionPrevention::createIpsRules(const string &default_mode) const
IpsProtectionsRulesSection low_rule(
min_cve_Year,
getModeWithDefault(low_confidence_event_action, default_mode, key_to_practices_val),
getRulesMode(low_confidence_event_action, default_mode),
string("Low"),
max_performance_impact,
string(""),
@@ -685,33 +762,45 @@ NewIntrusionPrevention::createIpsRules(const string &default_mode) const
return ips_rules;
}
const std::string &
NewIntrusionPrevention::getMode(const std::string &default_mode) const
const string &
NewIntrusionPrevention::getMode(const string &default_mode) const
{
const string &res = getModeWithDefault(override_mode, default_mode, key_to_practices_val);
const string &res = getModeWithDefault(override_mode, default_mode, key_to_practices_mode_val);
return res;
}
const string &
NewIntrusionPrevention::getRulesMode(const string &mode, const string &default_mode) const
{
if (isModeInherited(mode)) return default_mode;
if (key_to_practices_mode_val.find(mode) == key_to_practices_mode_val.end()) {
dbgError(D_LOCAL_POLICY) << "Given mode: " << mode << " or top-level: " << default_mode << " is invalid.";
return key_to_practices_mode_val.at("inactive");
}
return key_to_practices_mode_val.at(mode);
}
FileSecurityProtectionsSection::FileSecurityProtectionsSection(
uint64_t _file_size_limit,
uint64_t _archive_file_size_limit,
bool _allow_files_without_name,
bool _required_file_size_limit,
bool _required_archive_extraction,
const std::string &_context,
const std::string &_name,
const std::string &_asset_id,
const std::string &_practice_name,
const std::string &_practice_id,
const std::string &_action,
const std::string &_files_without_name_action,
const std::string &_high_confidence_action,
const std::string &_medium_confidence_action,
const std::string &_low_confidence_action,
const std::string &_severity_level,
const std::string &_file_size_limit_action,
const std::string &_multi_level_archive_action,
const std::string &_unopened_archive_action)
const string &_context,
const string &_name,
const string &_asset_id,
const string &_practice_name,
const string &_practice_id,
const string &_action,
const string &_files_without_name_action,
const string &_high_confidence_action,
const string &_medium_confidence_action,
const string &_low_confidence_action,
const string &_severity_level,
const string &_file_size_limit_action,
const string &_multi_level_archive_action,
const string &_unopened_archive_action)
:
file_size_limit(_file_size_limit),
archive_file_size_limit(_archive_file_size_limit),
@@ -837,13 +926,13 @@ NewFileSecurityArchiveInspection::getrequiredArchiveExtraction() const
return extract_archive_files;
}
const std::string &
const string &
NewFileSecurityArchiveInspection::getMultiLevelArchiveAction() const
{
return archived_files_within_archived_files;
}
const std::string &
const string &
NewFileSecurityArchiveInspection::getUnopenedArchiveAction() const
{
return archived_files_where_content_extraction_failed;
@@ -892,7 +981,7 @@ NewFileSecurityLargeFileInspection::getFileSizeLimit() const
return (file_size_limit * unit_to_int.at(file_size_limit_unit));
}
const std::string &
const string &
NewFileSecurityLargeFileInspection::getFileSizeLimitAction() const
{
return files_exceeding_size_limit_action;
@@ -1013,7 +1102,7 @@ void
NewAppSecPracticeSpec::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec practice spec";
parseAppsecJSONKey<NewSnortSignaturesAndOpenSchemaAPI>(
parseAppsecJSONKey<NewOpenApiSchema>(
"schemaValidation",
openapi_schema_validation,
archive_in
@@ -1021,11 +1110,15 @@ NewAppSecPracticeSpec::load(cereal::JSONInputArchive &archive_in)
parseAppsecJSONKey<string>("appsecClassName", appsec_class_name, archive_in);
parseMandatoryAppsecJSONKey<NewFileSecurity>("fileSecurity", file_security, archive_in);
parseMandatoryAppsecJSONKey<NewIntrusionPrevention>("intrusionPrevention", intrusion_prevention, archive_in);
parseMandatoryAppsecJSONKey<NewSnortSignaturesAndOpenSchemaAPI>("snortSignatures", snort_signatures, archive_in);
parseMandatoryAppsecJSONKey<NewSnortSignatures>("snortSignatures", snort_signatures, archive_in);
parseMandatoryAppsecJSONKey<NewAppSecPracticeWebAttacks>("webAttacks", web_attacks, archive_in);
parseAppsecJSONKey<NewAppSecPracticeAntiBot>("antiBot", anti_bot, archive_in);
parseAppsecJSONKey<string>("name", practice_name, archive_in);
parseAppsecJSONKey<string>("practiceMode", mode, archive_in, "inherited");
if (valid_modes.count(mode) == 0) {
dbgWarning(D_LOCAL_POLICY) << "AppSec Threat prevention practice mode invalid: " << mode;
throw PolicyGenException("AppSec Threat prevention practice mode invalid: " + mode);
}
}
void
@@ -1034,13 +1127,13 @@ NewAppSecPracticeSpec::setName(const string &_name)
practice_name = _name;
}
const NewSnortSignaturesAndOpenSchemaAPI &
NewAppSecPracticeSpec::getOpenSchemaValidation() const
NewOpenApiSchema &
NewAppSecPracticeSpec::getOpenSchemaValidation()
{
return openapi_schema_validation;
}
NewSnortSignaturesAndOpenSchemaAPI &
NewSnortSignatures &
NewAppSecPracticeSpec::getSnortSignatures()
{
return snort_signatures;

View File

@@ -21,6 +21,15 @@
using namespace std;
USE_DEBUG_FLAG(D_NGINX_POLICY);
USE_DEBUG_FLAG(D_LOCAL_POLICY);
static const std::unordered_map<std::string, std::string> key_to_source_identefier_val = {
{ "sourceip", "Source IP"},
{ "cookie", "Cookie:"},
{ "headerkey", "Header:"},
{ "JWTKey", ""},
{ "x-forwarded-for", "X-Forwarded-For"}
};
void
SecurityAppsWrapper::save(cereal::JSONOutputArchive &out_ar) const
@@ -185,6 +194,33 @@ PolicyMakerUtils::dumpPolicyToFile(
return policy_str;
}
template<class R>
vector<string>
extractExceptionAnnotationNames(
const R &parsed_rule,
const R &default_rule,
const string &policy_name)
{
vector<string> annotation_names;
const R &rule = (!parsed_rule.getExceptions().empty() ? parsed_rule : default_rule);
for (const string &exception_name : rule.getExceptions()) {
if (exception_name.empty()) {
continue;
}
const auto policy_exception = policy_name + "/" + exception_name;
dbgTrace(D_NGINX_POLICY) << "Adding " << policy_exception << " to exception vector";
annotation_names.push_back(policy_exception);
}
dbgTrace(D_NGINX_POLICY) << "Number of exceptions related to rule: " << annotation_names.size();
return annotation_names;
}
template<class R>
map<AnnotationTypes, string>
extractAnnotationsNames(
@@ -217,18 +253,6 @@ extractAnnotationsNames(
rule_annotation[AnnotationTypes::TRIGGER] = policy_name + "/" + trigger_annotation_name;
}
string exception_annotation_name;
// TBD: support multiple exceptions
if (!parsed_rule.getExceptions().empty() && !parsed_rule.getExceptions()[0].empty()) {
exception_annotation_name = parsed_rule.getExceptions()[0];
} else if (!default_rule.getExceptions().empty() && !default_rule.getExceptions()[0].empty()) {
exception_annotation_name = default_rule.getExceptions()[0];
}
if (!exception_annotation_name.empty()) {
rule_annotation[AnnotationTypes::EXCEPTION] = policy_name + "/" + exception_annotation_name;
}
string web_user_res_annotation_name =
parsed_rule.getCustomResponse().empty() ?
default_rule.getCustomResponse() :
@@ -444,6 +468,7 @@ template<class T, class R>
R
getAppsecExceptionSpec(const string &exception_annotation_name, const T &policy)
{
dbgFlow(D_NGINX_POLICY) << "anotation name: " << exception_annotation_name;
auto exceptions_vec = policy.getAppsecExceptions();
auto exception_it = extractElement(exceptions_vec.begin(), exceptions_vec.end(), exception_annotation_name);
@@ -538,7 +563,7 @@ extractLogTriggerData(const string &trigger_annotation_name, const T &trigger_sp
bool webHeaders = trigger_spec.getAppsecTriggerExtendedLogging().isHttpHeaders();
bool webBody = trigger_spec.getAppsecTriggerExtendedLogging().isRequestBody();
bool logToCloud = trigger_spec.getAppsecTriggerLogDestination().getCloud();
bool logToContainerService = trigger_spec.getAppsecTriggerLogDestination().isContainerNeeded();
bool logTolocalTuning = trigger_spec.getAppsecTriggerLogDestination().isContainerNeeded();
bool logToAgent = trigger_spec.getAppsecTriggerLogDestination().isAgentLocal();
bool beautify_logs = trigger_spec.getAppsecTriggerLogDestination().shouldBeautifyLogs();
bool logToCef = trigger_spec.getAppsecTriggerLogDestination().isCefNeeded();
@@ -565,7 +590,7 @@ extractLogTriggerData(const string &trigger_annotation_name, const T &trigger_sp
logToAgent,
logToCef,
logToCloud,
logToContainerService,
logTolocalTuning,
logToSyslog,
responseBody,
tpDetect,
@@ -776,6 +801,7 @@ createExceptionSection(
const string &exception_annotation_name,
const T &policy)
{
dbgFlow(D_NGINX_POLICY) << "exception annotation name" << exception_annotation_name;
AppsecException exception_spec =
getAppsecExceptionSpec<T, AppsecException>(exception_annotation_name, policy);
vector<InnerException> res;
@@ -784,6 +810,7 @@ createExceptionSection(
ExceptionBehavior exception_behavior(exception.getAction());
res.push_back(InnerException(exception_behavior, exception_match));
}
return res;
}
@@ -896,13 +923,16 @@ createMultiRulesSections(
const string &web_user_res_vec_id,
const string &web_user_res_vec_type,
const string &asset_name,
const string &exception_name,
const vector<InnerException> &exceptions)
const std::map<std::string, std::vector<InnerException>> &exceptions)
{
PracticeSection practice = PracticeSection(practice_id, practice_type, practice_name);
vector<ParametersSection> exceptions_result;
for (auto exception : exceptions) {
exceptions_result.push_back(ParametersSection(exception.getBehaviorId(), exception_name));
const auto &exception_name = exception.first;
for (const auto &inner_exception : exception.second) {
exceptions_result.push_back(ParametersSection(inner_exception.getBehaviorId(), exception_name));
}
}
vector<RulesTriggerSection> triggers;
@@ -1016,7 +1046,7 @@ PolicyMakerUtils::createIpsSections(
practice_name,
practice_id,
source_identifier,
override_mode,
"Inactive",
apssec_practice.getIntrusionPrevention().createIpsRules(override_mode)
);
@@ -1026,8 +1056,7 @@ PolicyMakerUtils::createIpsSections(
void
PolicyMakerUtils::createSnortProtecionsSection(const string &file_name, bool is_temporary)
{
auto path = getFilesystemPathConfig() + "/conf/snort/" + file_name;
string in_file = is_temporary ? path + ".rule" : path;
auto path = is_temporary ? getFilesystemPathConfig() + "/conf/snort/" + file_name + ".rule" : file_name;
if (snort_protections.find(path) != snort_protections.end()) {
dbgTrace(D_LOCAL_POLICY) << "Snort protections section for file " << file_name << " already exists";
@@ -1038,7 +1067,9 @@ PolicyMakerUtils::createSnortProtecionsSection(const string &file_name, bool is_
<< (is_temporary ? " temporary" : "") << " file " << path;
auto snort_script_path = getFilesystemPathConfig() + "/scripts/snort_to_ips_local.py";
auto cmd = "python3 " + snort_script_path + " " + in_file + " " + path + ".out " + path + ".err";
auto tmp_out = "/tmp/" + file_name + ".out";
auto tmp_err = "/tmp/" + file_name + ".err";
auto cmd = "python3 " + snort_script_path + " " + path + " " + tmp_out + " " + tmp_err;
auto res = Singleton::Consume<I_ShellCmd>::by<LocalPolicyMgmtGenerator>()->getExecOutput(cmd);
@@ -1047,16 +1078,16 @@ PolicyMakerUtils::createSnortProtecionsSection(const string &file_name, bool is_
return;
}
Maybe<ProtectionsSectionWrapper> maybe_protections = openFileAsJson<ProtectionsSectionWrapper>(path + ".out");
Maybe<ProtectionsSectionWrapper> maybe_protections = openFileAsJson<ProtectionsSectionWrapper>(tmp_out);
if (!maybe_protections.ok()){
dbgWarning(D_LOCAL_POLICY) << maybe_protections.getErr();
return;
}
auto i_orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<LocalPolicyMgmtGenerator>();
if (is_temporary) i_orchestration_tools->removeFile(in_file);
i_orchestration_tools->removeFile(path + ".out");
i_orchestration_tools->removeFile(path + ".err");
if (is_temporary) i_orchestration_tools->removeFile(path);
i_orchestration_tools->removeFile(tmp_out);
i_orchestration_tools->removeFile(tmp_err);
snort_protections[path] = ProtectionsSection(
maybe_protections.unpack().getProtections(),
@@ -1186,7 +1217,8 @@ void
PolicyMakerUtils::createWebAppSection(
const V1beta2AppsecLinuxPolicy &policy,
const RulesConfigRulebase& rule_config,
const string &practice_id, const string &full_url,
const string &practice_id,
const string &full_url,
const string &default_mode,
map<AnnotationTypes, string> &rule_annotations)
{
@@ -1203,6 +1235,7 @@ PolicyMakerUtils::createWebAppSection(
apssec_practice.getWebAttacks().getMaxObjectDepth(),
apssec_practice.getWebAttacks().getMaxUrlSizeBytes()
);
WebAppSection web_app = WebAppSection(
full_url == "Any" ? default_appsec_url : full_url,
rule_config.getAssetId(),
@@ -1214,6 +1247,10 @@ PolicyMakerUtils::createWebAppSection(
rule_config.getContext(),
apssec_practice.getWebAttacks().getMinimumConfidence(practice_mode),
apssec_practice.getWebAttacks().getMode(practice_mode),
apssec_practice.getAntiBot().getMode(practice_mode),
apssec_practice.getOpenSchemaValidation().getOverrideMode(practice_mode),
apssec_practice.getOpenSchemaValidation().getEnforceLevel(),
apssec_practice.getOpenSchemaValidation().getOas(),
practice_advance_config,
apssec_practice.getAntiBot(),
log_triggers[rule_annotations[AnnotationTypes::TRIGGER]],
@@ -1267,7 +1304,7 @@ PolicyMakerUtils::createThreatPreventionPracticeSections(
);
rules_config[rule_config.getAssetName()] = rule_config;
string current_identifier;
string current_identifier, current_identifier_value;
if (!rule_annotations[AnnotationTypes::SOURCE_IDENTIFIERS].empty()) {
UsersIdentifiersRulebase user_identifiers = createUserIdentifiers<V1beta2AppsecLinuxPolicy>(
rule_annotations[AnnotationTypes::SOURCE_IDENTIFIERS],
@@ -1276,6 +1313,15 @@ PolicyMakerUtils::createThreatPreventionPracticeSections(
);
users_identifiers[rule_annotations[AnnotationTypes::SOURCE_IDENTIFIERS]] = user_identifiers;
current_identifier = user_identifiers.getIdentifier();
current_identifier_value = user_identifiers.getIdentifierValue();
}
string ips_identifier, ips_identifier_value;
if(key_to_source_identefier_val.find(current_identifier) != key_to_source_identefier_val.end()) {
ips_identifier = key_to_source_identefier_val.at(current_identifier);
}
if (current_identifier == "cookie" || current_identifier == "headerkey") {
ips_identifier_value = current_identifier_value;
}
createIpsSections(
@@ -1283,7 +1329,7 @@ PolicyMakerUtils::createThreatPreventionPracticeSections(
rule_config.getAssetName(),
practice_id,
rule_annotations[AnnotationTypes::PRACTICE],
current_identifier,
ips_identifier + ips_identifier_value,
rule_config.getContext(),
policy,
rule_annotations,
@@ -1344,6 +1390,7 @@ PolicyMakerUtils::combineElementsToPolicy(const string &policy_version)
convertMapToVector(log_triggers), convertMapToVector(web_user_res_triggers)
)
);
ExceptionsWrapper exceptions_section({
ExceptionsRulebase(convertExceptionsMapToVector(inner_exceptions))
});
@@ -1381,6 +1428,7 @@ PolicyMakerUtils::createPolicyElementsByRule(
const string &policy_name)
{
map<AnnotationTypes, string> rule_annotations = extractAnnotationsNames(rule, default_rule, policy_name);
if (
!rule_annotations[AnnotationTypes::TRIGGER].empty() &&
!log_triggers.count(rule_annotations[AnnotationTypes::TRIGGER])
@@ -1403,15 +1451,27 @@ PolicyMakerUtils::createPolicyElementsByRule(
);
}
if (
!rule_annotations[AnnotationTypes::EXCEPTION].empty() &&
!inner_exceptions.count(rule_annotations[AnnotationTypes::EXCEPTION])
) {
inner_exceptions[rule_annotations[AnnotationTypes::EXCEPTION]] =
createExceptionSection<T>(
rule_annotations[AnnotationTypes::EXCEPTION],
policy
);
const auto exceptions_annotations = extractExceptionAnnotationNames(rule, default_rule, policy_name);
std::map<std::string, std::vector<InnerException>> rule_inner_exceptions;
if (!exceptions_annotations.empty()) {
for (const auto &exception_name :exceptions_annotations) {
dbgWarning(D_LOCAL_POLICY) << "exceptions name: " << exception_name;
if (rule_inner_exceptions.count(exception_name)) {
dbgWarning(D_LOCAL_POLICY) << "exception name already exists for that rule: " << exception_name;
continue;
}
if (inner_exceptions.count(exception_name)) {
dbgWarning(D_LOCAL_POLICY) << "exception name already exists in inner exceptions: " << exception_name;
rule_inner_exceptions[exception_name] = inner_exceptions[exception_name];
continue;
}
auto exception_section = createExceptionSection<T>(exception_name, policy);
rule_inner_exceptions[exception_name] = exception_section;
inner_exceptions[exception_name] = exception_section;
}
}
if (
@@ -1470,8 +1530,7 @@ PolicyMakerUtils::createPolicyElementsByRule(
web_user_res_triggers[rule_annotations[AnnotationTypes::WEB_USER_RES]].getTriggerId(),
"WebUserResponse",
full_url,
rule_annotations[AnnotationTypes::EXCEPTION],
inner_exceptions[rule_annotations[AnnotationTypes::EXCEPTION]]
rule_inner_exceptions
);
rules_config[rule_config.getAssetName()] = rule_config;
@@ -1498,7 +1557,7 @@ PolicyMakerUtils::createPolicyElementsByRule(
log_triggers[rule_annotations[AnnotationTypes::TRIGGER]],
rule.getMode(),
trusted_sources[rule_annotations[AnnotationTypes::TRUSTED_SOURCES]],
inner_exceptions[rule_annotations[AnnotationTypes::EXCEPTION]]
rule_inner_exceptions
);
web_apps[rule_config.getAssetName()] = web_app;
}

View File

@@ -17,6 +17,8 @@ using namespace std;
USE_DEBUG_FLAG(D_LOCAL_POLICY);
static const string empty_string="";
AssetUrlParser
AssetUrlParser::parse(const string &uri)
{
@@ -242,6 +244,13 @@ UsersIdentifier::getIdentifier() const
{
return source_identifier;
}
const string &
UsersIdentifier::getIdentifierValue() const
{
if (identifier_values.empty()) return empty_string;
return identifier_values[0];
}
// LCOV_EXCL_STOP
void
@@ -272,6 +281,13 @@ UsersIdentifiersRulebase::getIdentifier() const
if (source_identifiers.empty()) return source_identifier;
return source_identifiers[0].getIdentifier();
}
const string &
UsersIdentifiersRulebase::getIdentifierValue() const
{
if (source_identifiers.empty()) return empty_string;
return source_identifiers[0].getIdentifierValue();
}
// LCOV_EXCL_STOP
void

View File

@@ -30,7 +30,7 @@ LogTriggerSection::LogTriggerSection(
bool _logToAgent,
bool _logToCef,
bool _logToCloud,
bool _logToContainerService,
bool _logTolocalTuning,
bool _logToSyslog,
bool _responseBody,
bool _tpDetect,
@@ -55,7 +55,7 @@ LogTriggerSection::LogTriggerSection(
logToAgent(_logToAgent),
logToCef(_logToCef),
logToCloud(_logToCloud),
logToContainerService(_logToContainerService),
logTolocalTuning(_logTolocalTuning),
logToSyslog(_logToSyslog),
responseBody(_responseBody),
tpDetect(_tpDetect),
@@ -101,7 +101,7 @@ LogTriggerSection::save(cereal::JSONOutputArchive &out_ar) const
cereal::make_nvp("logToAgent", logToAgent),
cereal::make_nvp("logToCef", logToCef),
cereal::make_nvp("logToCloud", logToCloud),
cereal::make_nvp("logToContainerService", logToContainerService),
cereal::make_nvp("logTolocalTuning", logTolocalTuning),
cereal::make_nvp("logToSyslog", logToSyslog),
cereal::make_nvp("responseBody", responseBody),
cereal::make_nvp("responseCode", false),
@@ -393,12 +393,16 @@ AppsecTriggerLogDestination::load(cereal::JSONInputArchive &archive_in)
} else {
cloud = false;
}
auto mode = Singleton::Consume<I_AgentDetails>::by<AppsecTriggerLogDestination>()->getOrchestrationMode();
auto env_type = Singleton::Consume<I_EnvDetails>::by<AppsecTriggerLogDestination>()->getEnvType();
bool k8s_service_default = (mode == OrchestrationMode::HYBRID && env_type == EnvType::K8S);
// BC try load previous name. TODO: update CRD
parseAppsecJSONKey<bool>("k8s-service", container_service, archive_in, k8s_service_default);
parseAppsecJSONKey<bool>("container-service", container_service, archive_in, container_service);
// check ENV VAR LOCAL_TUNING_ENABLED
char * tuning_enabled = getenv("LOCAL_TUNING_ENABLED");
if (tuning_enabled != NULL) {
for (unsigned int i = 0; i < strlen(tuning_enabled); i++) {
tuning_enabled[i] = tolower(tuning_enabled[i]);
}
container_service = string(tuning_enabled) == "true";
} else {
container_service = false;
}
StdoutLogging stdout_log;
parseAppsecJSONKey<StdoutLogging>("stdout", stdout_log, archive_in);

View File

@@ -350,7 +350,7 @@ DetailsResolver::Impl::readCloudMetadata()
}
if (!cloud_metadata.ok()) {
dbgWarning(D_ORCHESTRATOR) << cloud_metadata.getErr();
dbgDebug(D_ORCHESTRATOR) << cloud_metadata.getErr();
return genError("Failed to fetch cloud metadata");
}

View File

@@ -18,6 +18,8 @@
#include <regex>
#include <boost/regex.hpp>
#include <boost/algorithm/string.hpp>
#include <cereal/external/rapidjson/document.h>
#include <cereal/external/rapidjson/filereadstream.h>
#if defined(gaia)
@@ -60,20 +62,16 @@ checkSAMLPortal(const string &command_output)
Maybe<string>
checkPepIdaIdnStatus(const string &command_output)
{
if (command_output.find("nac_pep_scaled_sharing_enabled = 1") != string::npos) {
if (command_output.find("nac_pep_identity_next_enabled = 1") != string::npos) {
return string("true");
}
return string("false");
}
Maybe<string>
getIDAGaiaPackages(const string &command_output)
getRequiredNanoServices(const string &command_output)
{
string result = "idaSaml_gaia;idaIdn_gaia;idaIdnBg_gaia;";
if (command_output.find("nac_pep_scaled_sharing_enabled = 1") != string::npos) {
result += "agentIntelligenceService_gaia;";
}
return result;
return command_output;
}
Maybe<string>
@@ -104,6 +102,14 @@ checkIsInstallHorizonTelemetrySucceeded(const string &command_output)
return command_output;
}
Maybe<string>
getOtlpAgentGaiaOsRole(const string &command_output)
{
if (command_output == "" ) return string("-1");
return command_output;
}
Maybe<string>
getQUID(const string &command_output)
{
@@ -115,6 +121,13 @@ getQUID(const string &command_output)
return command_output;
}
Maybe<string>
getIsAiopsRunning(const string &command_output)
{
if (command_output == "" ) return string("false");
return command_output;
}
Maybe<string>
checkHasSDWan(const string &command_output)
@@ -191,26 +204,67 @@ getMgmtObjAttr(shared_ptr<istream> file_stream, const string &attr)
}
Maybe<string>
getMgmtObjUid(shared_ptr<istream> file_stream)
getAttrFromCpsdwanGetDataJson(const string &attr)
{
static const std::string get_data_json_path = "/tmp/cpsdwan_getdata_orch.json";
std::ifstream ifs(get_data_json_path);
if (ifs.is_open()) {
rapidjson::IStreamWrapper isw(ifs);
rapidjson::Document document;
document.ParseStream(isw);
if (!document.HasParseError() && document.HasMember(attr.c_str()) && document[attr.c_str()].IsString()) {
return string(document[attr.c_str()].GetString());
}
}
return genError("Attribute " + attr + " was not found in " + get_data_json_path);
}
Maybe<string>
getMgmtObjUid(const string &command_output)
{
if (!command_output.empty()) {
return command_output;
}
Maybe<string> obj_uuid = getAttrFromCpsdwanGetDataJson("uuid");
if (obj_uuid.ok()) {
return obj_uuid.unpack();
}
static const string obj_path = (getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myown.C";
auto file_stream = std::make_shared<std::ifstream>(obj_path);
if (!file_stream->is_open()) {
return genError("Failed to open the object file");
}
return getMgmtObjAttr(file_stream, "uuid ");
}
Maybe<string>
getMgmtObjName(shared_ptr<istream> file_stream)
getMgmtObjName(const string &command_output)
{
if (!command_output.empty()) {
return command_output;
}
static const string obj_path = (getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myown.C";
auto file_stream = std::make_shared<std::ifstream>(obj_path);
if (!file_stream->is_open()) {
return genError("Failed to open the object file");
}
return getMgmtObjAttr(file_stream, "name ");
}
Maybe<string>
getGWHardware(const string &command_output)
getHardware(const string &command_output)
{
if (!command_output.empty()) {
if (command_output == "software") return string("Open server");
if (command_output == "Maestro Gateway") return string("Maestro");
return string(command_output);
}
return genError("GW Hardware was not found");
return genError("Hardware was not found");
}
Maybe<string>
@@ -296,7 +350,12 @@ getSmbObjectName(const string &command_output)
if (command_output.empty() || command_output[0] != centrally_managed_comd_output) {
return genError("Object name was not found");
}
Maybe<string> obj_name = getAttrFromCpsdwanGetDataJson("name");
if (obj_name.ok()) {
return obj_name.unpack();
}
static const string obj_path = (getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myown.C";
auto ifs = std::make_shared<std::ifstream>(obj_path);
if (!ifs->is_open()) {

View File

@@ -42,16 +42,46 @@ SHELL_PRE_CMD("gunzip local.cfg", "gunzip -c $FWDIR/state/local/FW1/local.cfg.gz
#ifdef SHELL_CMD_HANDLER
#if defined(gaia) || defined(smb)
SHELL_CMD_HANDLER("cpProductIntegrationMgmtObjectType", "cpprod_util CPPROD_IsMgmtMachine", getMgmtObjType)
SHELL_CMD_HANDLER(
"cpProductIntegrationMgmtObjectUid",
"mgmt_cli --format json -r true show-session | jq -r '.[\"connected-server\"].uid'",
getMgmtObjUid
)
SHELL_CMD_HANDLER("prerequisitesForHorizonTelemetry",
"FS_PATH=<FILESYSTEM-PREFIX>; [ -f ${FS_PATH}/cp-nano-horizon-telemetry-prerequisites.log ] "
"&& head -1 ${FS_PATH}/cp-nano-horizon-telemetry-prerequisites.log || echo ''",
checkIsInstallHorizonTelemetrySucceeded)
SHELL_CMD_HANDLER("QUID", "[ -d /opt/CPquid ] "
SHELL_CMD_HANDLER("GLOBAL_QUID", "[ -d /opt/CPquid ] "
"&& python3 /opt/CPquid/Quid_Api.py -i /opt/CPotelcol/quid_api/get_global_id.json | jq -r .message || echo ''",
getQUID)
SHELL_CMD_HANDLER("SMO_QUID", "[ -d /opt/CPquid ] "
"&& python3 /opt/CPquid/Quid_Api.py -i /opt/CPotelcol/quid_api/get_smo_quid.json | jq -r .message || echo ''",
SHELL_CMD_HANDLER("QUID", "FS_PATH=<FILESYSTEM-PREFIX>;"
"VS_ID=$(echo \"${FS_PATH}\" | grep -o -E \"vs[0-9]+\" | grep -o -E \"[0-9]+\");"
"[ -z \"${VS_ID}\" ] && "
"(python3 /opt/CPquid/Quid_Api.py -i /opt/CPotelcol/quid_api/get_global_id.json | jq -r .message || echo '');"
"[ -n \"${VS_ID}\" ] && "
"(sed \"s|###VS_ID###|${VS_ID}|g\" /opt/CPotelcol/quid_api/get_vs_quid.json"
" > /opt/CPotelcol/quid_api/get_vs_quid.json.${VS_ID}); "
"[ -n \"${VS_ID}\" ] && [ -f /opt/CPotelcol/quid_api/get_vs_quid.json.${VS_ID} ] && "
"(python3 /opt/CPquid/Quid_Api.py -i "
"/opt/CPotelcol/quid_api/get_vs_quid.json.${VS_ID} | jq -r .message[0].QUID || echo '');",
getQUID)
SHELL_CMD_HANDLER("SMO_QUID", "[ -d /opt/CPquid ] "
"&& python3 /opt/CPquid/Quid_Api.py -i "
"/opt/CPotelcol/quid_api/get_smo_quid.json | jq -r .message[0].SMO_QUID || echo ''",
getQUID)
SHELL_CMD_HANDLER("MGMT_QUID", "[ -d /opt/CPquid ] "
"&& python3 /opt/CPquid/Quid_Api.py -i "
"/opt/CPotelcol/quid_api/get_mgmt_quid.json | jq -r .message[0].MGMT_QUID || echo ''",
getQUID)
SHELL_CMD_HANDLER("AIOPS_AGENT_ROLE", "[ -d /opt/CPOtlpAgent/custom_scripts ] "
"&& ENV_NO_FORMAT=1 /opt/CPOtlpAgent/custom_scripts/agent_role.sh",
getOtlpAgentGaiaOsRole)
SHELL_CMD_HANDLER(
"IS_AIOPS_RUNNING",
"FS_PATH=<FILESYSTEM-PREFIX>; "
"PID=$(ps auxf | grep -v grep | grep -E ${FS_PATH}.*cp-nano-horizon-telemetry | awk -F' ' '{printf $2}'); "
"[ -z \"{PID}\" ] && echo 'false' || echo 'true'",
getIsAiopsRunning)
SHELL_CMD_HANDLER("hasSDWan", "[ -f $FWDIR/bin/sdwan_steering ] && echo '1' || echo '0'", checkHasSDWan)
SHELL_CMD_HANDLER(
"canUpdateSDWanData",
@@ -102,8 +132,13 @@ SHELL_CMD_HANDLER(
SHELL_CMD_HANDLER("hasSAMLSupportedBlade", "enabled_blades", checkSAMLSupportedBlade)
SHELL_CMD_HANDLER("hasIDABlade", "enabled_blades", checkIDABlade)
SHELL_CMD_HANDLER("hasSAMLPortal", "mpclient status nac", checkSAMLPortal)
SHELL_CMD_HANDLER("hasIdaIdnEnabled", "fw ctl get int nac_pep_scaled_sharing_enabled", checkPepIdaIdnStatus)
SHELL_CMD_HANDLER("requiredNanoServices", "fw ctl get int nac_pep_scaled_sharing_enabled", getIDAGaiaPackages)
SHELL_CMD_HANDLER("hasIdaIdnEnabled", "fw ctl get int nac_pep_identity_next_enabled", checkPepIdaIdnStatus)
SHELL_CMD_HANDLER("requiredNanoServices", "echo 'idaSaml_gaia;idaIdn_gaia;'", getRequiredNanoServices)
SHELL_CMD_HANDLER(
"cpProductIntegrationMgmtObjectName",
"mgmt_cli --format json -r true show-session | jq -r '.[\"connected-server\"].name'",
getMgmtObjName
)
SHELL_CMD_HANDLER(
"cpProductIntegrationMgmtParentObjectName",
"cat $FWDIR/database/myself_objects.C "
@@ -118,8 +153,8 @@ SHELL_CMD_HANDLER(
)
SHELL_CMD_HANDLER(
"Hardware",
"cat $FWDIR/database/myself_objects.C | awk -F '[:()]' '/:appliance_type/ {print $3}' | head -n 1",
getGWHardware
"cat $FWDIR/database/myself_objects.C | awk -F '[:()]' '/:appliance_type/ {print $3}' | head -n 1 | sed 's/\"//g'",
getHardware
)
SHELL_CMD_HANDLER(
"Application Control",
@@ -154,8 +189,7 @@ SHELL_CMD_HANDLER(
)
SHELL_CMD_HANDLER(
"managements",
"sed -n '/:masters (/,$p' $FWDIR/database/myself_objects.C |"
" sed -e ':a' -e 'N' -e '$!ba' -e 's/\\n//g' -e 's/\t//g' -e 's/ //g' | sed 's/))):.*/)))):/'",
"echo 1",
extractManagements
)
#endif //gaia
@@ -211,14 +245,14 @@ SHELL_CMD_HANDLER(
SHELL_CMD_HANDLER(
"managements",
"sed -n '/:masters (/,$p' /tmp/local.cfg |"
" sed -e ':a' -e 'N' -e '$!ba' -e 's/\\n//g' -e 's/\t//g' -e 's/ //g' | sed 's/))):.*/)))):/'",
"echo 1",
extractManagements
)
#endif//smb
SHELL_CMD_OUTPUT("kernel_version", "uname -r")
SHELL_CMD_OUTPUT("helloWorld", "cat /tmp/agentHelloWorld 2>/dev/null")
SHELL_CMD_OUTPUT("report_timestamp", "date -u +\%s")
#endif // SHELL_CMD_OUTPUT
@@ -227,17 +261,11 @@ SHELL_CMD_OUTPUT("helloWorld", "cat /tmp/agentHelloWorld 2>/dev/null")
#ifdef FILE_CONTENT_HANDLER
#if defined(gaia)
FILE_CONTENT_HANDLER(
"hasIdpConfigured",
(getenv("SAMLPORTAL_HOME") ? string(getenv("SAMLPORTAL_HOME")) : "") + "/phpincs/spPortal/idpPolicy.xml",
checkIDP
)
FILE_CONTENT_HANDLER(
"cpProductIntegrationMgmtObjectName",
(getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myown.C",
getMgmtObjName
)
#endif //gaia
#if defined(alpine)
@@ -245,11 +273,6 @@ FILE_CONTENT_HANDLER("alpine_tag", "/usr/share/build/cp-alpine-tag", getCPAlpine
#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
)
#else // !(gaia || smb)
FILE_CONTENT_HANDLER("os_release", "/etc/os-release", getOsRelease)
#endif // gaia || smb

View File

@@ -1,3 +1,7 @@
#include <sstream>
class Package;
static std::ostream & operator<<(std::ostream &os, const Package &) { return os; }
#include "cptest.h"
#include "config.h"
#include "config_component.h"

View File

@@ -28,6 +28,7 @@ EnvDetails::EnvDetails() : env_type(EnvType::LINUX)
auto tools = Singleton::Consume<I_OrchestrationTools>::from<OrchestrationTools>();
if (tools->doesFileExist("/.dockerenv")) env_type = EnvType::DOCKER;
token = retrieveToken();
agent_namespace = retrieveNamespace();
if (!token.empty()) {
auto env_res = getenv("deployment_type");
env_type = env_res != nullptr && env_res == string("non_crd_k8s") ? EnvType::NON_CRD_K8S : EnvType::K8S;
@@ -46,12 +47,24 @@ EnvDetails::getToken()
return token;
}
string
EnvDetails::getNameSpace()
{
return agent_namespace;
}
string
EnvDetails::retrieveToken()
{
return readFileContent(k8s_service_account + "/token");
}
string
EnvDetails::retrieveNamespace()
{
return readFileContent(k8s_service_account + "/namespace");
}
string
EnvDetails::readFileContent(const string &file_path)
{

View File

@@ -40,6 +40,8 @@ public:
i_mainloop = Singleton::Consume<I_MainLoop>::by<HealthChecker>();
i_socket = Singleton::Consume<I_Socket>::by<HealthChecker>();
i_orchestration_status = Singleton::Consume<I_OrchestrationStatus>::by<HealthChecker>();
i_service_controller = Singleton::Consume<I_ServiceController>::by<HealthChecker>();
initConfig();
initServerSocket();
@@ -270,18 +272,17 @@ private:
}
if (NGEN::Filesystem::exists(rpm_full_load_path)) {
dbgTrace(D_HEALTH_CHECK) << rpm_full_load_path << " exists, returning healthy status";
return HealthCheckStatus::HEALTHY;
dbgTrace(D_HEALTH_CHECK) << "RPM is fully loaded";
return i_service_controller->getServicesPolicyStatus()
? HealthCheckStatus::HEALTHY
: HealthCheckStatus::UNHEALTHY;
}
if (NGEN::Filesystem::exists(rpm_partial_load_path)) {
dbgTrace(D_HEALTH_CHECK) << rpm_partial_load_path << " exists, returning degraded status";
return HealthCheckStatus::DEGRADED;
}
if (!NGEN::Filesystem::exists(first_rpm_policy_load_path)) {
dbgTrace(D_HEALTH_CHECK) << "Could not load latest RPM policy, returning degraded status";
return HealthCheckStatus::DEGRADED;
if (NGEN::Filesystem::exists(rpm_partial_load_path) || !NGEN::Filesystem::exists(first_rpm_policy_load_path)) {
dbgTrace(D_HEALTH_CHECK) << "RPM is partially loaded";
return i_service_controller->getServicesPolicyStatus()
? HealthCheckStatus::DEGRADED
: HealthCheckStatus::UNHEALTHY;
}
dbgTrace(D_HEALTH_CHECK) << "RPM is not loaded, returning unhealthy status";
@@ -442,6 +443,7 @@ private:
I_Socket *i_socket = nullptr;
I_Health_Check_Manager *i_health_check_manager = nullptr;
I_OrchestrationStatus *i_orchestration_status = nullptr;
I_ServiceController *i_service_controller = nullptr;
};
HealthChecker::HealthChecker() : Component("HealthChecker"), pimpl(make_unique<Impl>()) {}

View File

@@ -9,6 +9,7 @@
#include "mock/mock_shell_cmd.h"
#include "mock/mock_orchestration_status.h"
#include "health_check_manager.h"
#include "mock/mock_service_controller.h"
#include "config.h"
#include "config_component.h"
@@ -76,6 +77,7 @@ public:
I_MainLoop::Routine handle_probe_routine;
HealthCheckManager health_check_manager;
I_Health_Check_Manager *i_health_check_manager;
StrictMock<MockServiceController> mock_service_controller;
};
TEST_F(HealthCheckerTest, empty)
@@ -342,3 +344,58 @@ TEST_F(HealthCheckerTest, FailedHealthCheck)
connection_handler_routine();
setConfiguration(false, "Health Check", "Probe enabled");
}
TEST_F(HealthCheckerTest, StandaloneHealthCheck)
{
setenv("DOCKER_RPM_ENABLED", "true", 1);
string ip = "1.2.3.4";
setConfiguration(ip, "Health Check", "Probe IP");
uint port = 11600;
setConfiguration(port, "Health Check", "Probe port");
NGEN::Filesystem::touchFile("/tmp/wd.all_running");
NGEN::Filesystem::touchFile("/tmp/rpm_full_load");
auto on_exit = make_scope_exit(
[]() {
NGEN::Filesystem::deleteFile("/tmp/wd.all_running");
NGEN::Filesystem::deleteFile("/tmp/rpm_full_load");
}
);
const string policy_version = "1";
EXPECT_CALL(mock_orchestration_status, getPolicyVersion()).WillRepeatedly(ReturnRef(policy_version));
EXPECT_CALL(mock_service_controller, getServicesPolicyStatus()).WillRepeatedly(Return(true));
EXPECT_CALL(
mock_mainloop,
addOneTimeRoutine(I_MainLoop::RoutineType::System, _, _, false)
).WillOnce(DoAll(SaveArg<1>(&handle_probe_routine), Return(0)));
EXPECT_CALL(
mock_socket,
genSocket(I_Socket::SocketType::TCP, false, true, _)
).WillRepeatedly(Return(1));
EXPECT_CALL(
mock_mainloop,
addFileRoutine(I_MainLoop::RoutineType::System, _, _, _, true)
).WillRepeatedly(DoAll(SaveArg<2>(&connection_handler_routine), Return(0)));
EXPECT_CALL(
mock_mainloop,
addOneTimeRoutine(I_MainLoop::RoutineType::System, _, "Health check probe connection handler", true)
).WillOnce(DoAll(SaveArg<1>(&connection_handler_routine), Return(0)));
int socket = 1;
EXPECT_CALL(mock_socket, acceptSocket(1, false, ip)).WillOnce(Return(socket));
EXPECT_CALL(mock_mainloop, getCurrentRoutineId()).WillRepeatedly(Return(0));
EXPECT_CALL(mock_socket, receiveData(_, 1, false)).WillOnce(Return(vector<char>()));
EXPECT_CALL(mock_socket, writeData(_, response_buffer)).WillOnce(Return(true));
EXPECT_CALL(mock_socket, closeSocket(socket)).Times(2);
health_checker.init();
handle_probe_routine();
connection_handler_routine();
connection_handler_routine();
}

View File

@@ -266,7 +266,9 @@ private:
case OrchestrationStatusFieldType::COUNT : return "Count";
}
dbgAssert(false) << "Trying to convert unknown orchestration status field to string.";
dbgAssert(false)
<< AlertInfo(AlertTeam::CORE, "orchestration health")
<< "Trying to convert unknown orchestration status field to string.";
return "";
}
@@ -280,7 +282,9 @@ private:
case UpdatesProcessResult::DEGRADED : return HealthCheckStatus::DEGRADED;
}
dbgAssert(false) << "Trying to convert unknown update process result field to health check status.";
dbgAssert(false)
<< AlertInfo(AlertTeam::CORE, "orchestration health")
<< "Trying to convert unknown update process result field to health check status.";
return HealthCheckStatus::IGNORED;
}

View File

@@ -34,7 +34,9 @@ HybridModeMetric::upon(const HybridModeMetricEvent &)
{
auto shell_cmd = Singleton::Consume<I_ShellCmd>::by<OrchestrationComp>();
auto maybe_cmd_output = shell_cmd->getExecOutput(
getFilesystemPathConfig() + "/watchdog/cp-nano-watchdog --restart_count"
getFilesystemPathConfig() + "/watchdog/cp-nano-watchdog --restart_count",
1000,
false
);
// get wd process restart count

View File

@@ -79,8 +79,8 @@ public:
) override;
std::string getUpdate(CheckUpdateRequest &request) override;
bool shouldApplyPolicy() override;
void turnOffApplyPolicyFlag() override;
void turnOnApplyPolicyFlag() override;
void turnOffApplyLocalPolicyFlag() override;
void turnOnApplyLocalPolicyFlag() override;
std::string getCurrPolicy() override { return curr_policy; }
@@ -94,7 +94,7 @@ private:
std::string curr_version;
std::string curr_policy;
std::string curr_checksum;
bool should_apply_policy;
bool should_apply_local_policy;
};
#endif // __DECLARATIVE_POLICY_UTILS_H__

View File

@@ -22,8 +22,8 @@ public:
virtual std::string getCurrPolicy() = 0;
virtual void turnOffApplyPolicyFlag() = 0;
virtual void turnOnApplyPolicyFlag() = 0;
virtual void turnOffApplyLocalPolicyFlag() = 0;
virtual void turnOnApplyLocalPolicyFlag() = 0;
protected:
virtual ~I_DeclarativePolicy() {}

View File

@@ -40,6 +40,8 @@ public:
MOCK_CONST_METHOD0(getPolicyVersions, const std::string &());
MOCK_CONST_METHOD0(getServicesPolicyStatus, bool());
MOCK_METHOD6(
updateServiceConfiguration,
Maybe<void>(

View File

@@ -35,6 +35,8 @@ enum class UpdatesFailureReason {
INSTALL_PACKAGE,
CHECKSUM_UNMATCHED,
POLICY_CONFIGURATION,
SERVISE_CONFIGURATION,
SERVISE_CONFIGURATION_TIMEOUT,
POLICY_FOG_CONFIGURATION,
NONE
@@ -57,6 +59,8 @@ convertUpdatesFailureReasonToStr(UpdatesFailureReason reason)
case UpdatesFailureReason::INSTALL_PACKAGE : return "INSTALL_PACKAGE";
case UpdatesFailureReason::CHECKSUM_UNMATCHED : return "CHECKSUM_UNMATCHED";
case UpdatesFailureReason::POLICY_CONFIGURATION : return "POLICY_CONFIGURATION";
case UpdatesFailureReason::SERVISE_CONFIGURATION : return "SERVISE_CONFIGURATION";
case UpdatesFailureReason::SERVISE_CONFIGURATION_TIMEOUT : return "SERVISE_CONFIGURATION_TIMEOUT";
case UpdatesFailureReason::POLICY_FOG_CONFIGURATION : return "POLICY_FOG_CONFIGURATION";
case UpdatesFailureReason::NONE : return "NONE";
}

View File

@@ -21,20 +21,24 @@
#include "config.h"
#include "debug.h"
#include "i_orchestration_status.h"
#include "i_service_controller.h"
#include "health_check_status/health_check_status.h"
#include "updates_process_event.h"
#include "updates_process_report.h"
class UpdatesProcessReporter : public Listener<UpdatesProcessEvent>
class UpdatesProcessReporter
:
public Listener<UpdatesProcessEvent>,
Singleton::Consume<I_ServiceController>
{
public:
void upon(const UpdatesProcessEvent &event) override;
private:
void sendReoprt();
void sendReoprt(const std::string &version);
static std::vector<UpdatesProcessReport> reports;
uint report_failure_count = 0;
std::map<std::string, uint> report_failure_count_map;
};
#endif // __UPDATES_PROCESS_REPORTER_H__

View File

@@ -1,3 +1,7 @@
#include <sstream>
class Package;
static std::ostream & operator<<(std::ostream &os, const Package &) { return os; }
#include "manifest_controller.h"
#include <vector>

View File

@@ -43,8 +43,8 @@ TEST_F(PolicyTest, serialization)
ASSERT_TRUE(false) << "Cereal threw an exception: " << e.what();
}
EXPECT_EQ(15, orchestration_policy.getErrorSleepInterval());
EXPECT_EQ(20, orchestration_policy.getSleepInterval());
EXPECT_EQ(15u, orchestration_policy.getErrorSleepInterval());
EXPECT_EQ(20u, orchestration_policy.getSleepInterval());
EXPECT_EQ("http://10.0.0.18:81/control/", orchestration_policy.getFogAddress());
}
@@ -63,8 +63,8 @@ TEST_F(PolicyTest, noAgentType)
ASSERT_TRUE(false) << "Cereal threw an exception: " << e.what();
}
EXPECT_EQ(15, orchestration_policy.getErrorSleepInterval());
EXPECT_EQ(20, orchestration_policy.getSleepInterval());
EXPECT_EQ(15u, orchestration_policy.getErrorSleepInterval());
EXPECT_EQ(20u, orchestration_policy.getSleepInterval());
EXPECT_EQ("http://10.0.0.18:81/control/", orchestration_policy.getFogAddress());
}
@@ -83,8 +83,8 @@ TEST_F(PolicyTest, zeroSleepIntervels)
ASSERT_TRUE(false) << "Cereal threw an exception: " << e.what();
}
EXPECT_EQ(0, orchestration_policy.getErrorSleepInterval());
EXPECT_EQ(0, orchestration_policy.getSleepInterval());
EXPECT_EQ(0u, orchestration_policy.getErrorSleepInterval());
EXPECT_EQ(0u, orchestration_policy.getSleepInterval());
EXPECT_EQ("http://10.0.0.18:81/control/", orchestration_policy.getFogAddress());
}
@@ -152,7 +152,7 @@ TEST_F(PolicyTest, newOptionalFields)
ASSERT_TRUE(false) << "Cereal threw an exception: " << e.what();
}
EXPECT_EQ(10, orchestration_policy.getErrorSleepInterval());
EXPECT_EQ(30, orchestration_policy.getSleepInterval());
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

@@ -1,3 +1,7 @@
#include <sstream>
class Package;
static std::ostream & operator<<(std::ostream &os, const Package &) { return os; }
#include "orchestration_status.h"
#include <string>

View File

@@ -1,3 +1,7 @@
#include <sstream>
class Package;
static std::ostream & operator<<(std::ostream &os, const Package &) { return os; }
#include "url_parser.h"
#include "cptest.h"

View File

@@ -429,14 +429,16 @@ public:
status.insertServiceSetting(service_name, path);
return;
case OrchestrationStatusConfigType::MANIFEST:
dbgAssert(false) << "Manifest is not a service configuration file type";
dbgAssert(false)
<< AlertInfo(AlertTeam::CORE, "sesrvice configuration")
<< "Manifest is not a service configuration file type";
break;
case OrchestrationStatusConfigType::DATA:
return;
case OrchestrationStatusConfigType::COUNT:
break;
}
dbgAssert(false) << "Unknown configuration file type";
dbgAssert(false) << AlertInfo(AlertTeam::CORE, "sesrvice configuration") << "Unknown configuration file type";
}
void

View File

@@ -43,7 +43,10 @@ operator<<(ostream &os, const URLProtocol &protocol)
return os << "file://";
}
default: {
dbgAssert(false) << "Unsupported protocol " << static_cast<unsigned int>(protocol);
dbgAssert(false)
<< AlertInfo(AlertTeam::CORE, "fog communication")
<< "Unsupported protocol "
<< static_cast<unsigned int>(protocol);
return os;
}
}
@@ -91,7 +94,10 @@ URLParser::parseURL(const string &url)
return;
}
default: {
dbgAssert(false) << "URL protocol is not supported. Protocol: " << static_cast<unsigned int>(protocol);
dbgAssert(false)
<< AlertInfo(AlertTeam::CORE, "fog communication")
<< "URL protocol is not supported. Protocol: "
<< static_cast<unsigned int>(protocol);
return;
}
}

View File

@@ -1485,11 +1485,10 @@ private:
}
void
setUpgradeTime()
setDelayedUpgradeTime()
{
if (getConfigurationFlag("service_startup") != "true") return;
if (i_service_controller->getServiceToPortMap().empty()) return;
if (!i_agent_details->isOpenAppsecAgent() && i_service_controller->getServiceToPortMap().empty()) return;
try {
string upgrade_delay_interval_str = getAttribute("no-setting", "UPGRADE_DELAY_INTERVAL_MIN");
int upgrade_delay_interval = upgrade_delay_interval_str != "" ? stoi(upgrade_delay_interval_str) : 30;
@@ -1506,6 +1505,7 @@ private:
void
run()
{
loadExistingPolicy();
sleep_interval = policy.getErrorSleepInterval();
Maybe<void> registration_status(genError("Not running yet."));
while (!(registration_status = registerToTheFog()).ok()) {
@@ -1530,7 +1530,6 @@ private:
<< " seconds";
Singleton::Consume<I_MainLoop>::by<OrchestrationComp>()->yield(seconds(sleep_interval));
}
loadExistingPolicy();
failure_count = 0;
Singleton::Consume<I_MainLoop>::by<OrchestrationComp>()->yield(chrono::seconds(1));
@@ -1587,7 +1586,7 @@ private:
).notify();
}
setUpgradeTime();
setDelayedUpgradeTime();
while (true) {
Singleton::Consume<I_Environment>::by<OrchestrationComp>()->startNewTrace(false);
if (shouldReportAgentDetailsMetadata()) {
@@ -1631,6 +1630,7 @@ private:
string server_name = getAttribute("registered-server", "registered_server");
auto server = TagAndEnumManagement::convertStringToTag(server_name);
if (server_name == "'SWAG'") server = Tags::WEB_SERVER_SWAG;
if (server.ok()) tags.insert(*server);
if (getAttribute("no-setting", "CROWDSEC_ENABLED") == "true") tags.insert(Tags::CROWDSEC);
@@ -1652,6 +1652,8 @@ private:
tags
);
if (server_name != "") registration_report.addToOrigin(LogField("eventCategory", server_name));
auto email = getAttribute("email-address", "user_email");
if (email != "") registration_report << LogField("userDefinedId", email);
@@ -1694,9 +1696,11 @@ private:
auto temp_ext = getConfigurationWithDefault<string>("_temp", "orchestration", "Temp file extension");
dbgAssert(i_orchestration_tools->doesFileExist(backup_installation_file))
<< AlertInfo(AlertTeam::CORE, "orchestration backup")
<< "There is no backup installation package";
dbgAssert(i_orchestration_tools->copyFile(backup_installation_file, current_installation_file))
<< AlertInfo(AlertTeam::CORE, "orchestration backup")
<< "Failed to copy backup installation package";
// Copy the backup manifest file to the default manifest file path.
@@ -1713,8 +1717,10 @@ private:
auto package_handler = Singleton::Consume<I_PackageHandler>::by<OrchestrationComp>();
// Install the backup orchestration service installation package.
dbgAssert(package_handler->preInstallPackage(service_name, current_installation_file))
<< AlertInfo(AlertTeam::CORE, "orchestration backup")
<< "Failed to restore from backup, pre install test failed";
dbgAssert(package_handler->installPackage(service_name, current_installation_file, true))
<< AlertInfo(AlertTeam::CORE, "orchestration backup")
<< "Failed to restore from backup, installation failed";
}
// LCOV_EXCL_STOP
@@ -2027,7 +2033,7 @@ private:
}
auto policy_mgmt_mode = getSettingWithDefault<string>("management", "profileManagedMode");
if (getOrchestrationMode() == OrchestrationMode::HYBRID || policy_mgmt_mode == "declarative") {
Singleton::Consume<I_DeclarativePolicy>::from<DeclarativePolicyUtils>()->turnOnApplyPolicyFlag();
Singleton::Consume<I_DeclarativePolicy>::from<DeclarativePolicyUtils>()->turnOnApplyLocalPolicyFlag();
}
auto policy_version = i_service_controller->getPolicyVersion();

View File

@@ -386,7 +386,10 @@ OrchestrationTools::Impl::calculateChecksum(Package::ChecksumTypes checksum_type
return genError("Error while reading file " + path + ", " + e.what());
}
dbgAssert(false) << "Checksum type is not supported. Checksum type: " << static_cast<unsigned int>(checksum_type);
dbgAssert(false)
<< AlertInfo(AlertTeam::CORE, "service configuration")
<< "Checksum type is not supported. Checksum type: "
<< static_cast<unsigned int>(checksum_type);
return genError("Unsupported checksum type");
}

View File

@@ -1,3 +1,7 @@
#include <sstream>
class Package;
std::ostream & operator<<(std::ostream &os, const Package &) { return os; }
#include "orchestration_comp.h"
#include "cptest.h"
@@ -471,6 +475,9 @@ TEST_F(OrchestrationMultitenancyTest, handle_virtual_resource)
)
).WillOnce(Return(Maybe<void>()));
string version = "1";
EXPECT_CALL(mock_service_controller, getUpdatePolicyVersion()).WillOnce(ReturnRef(version));
EXPECT_CALL(
mock_service_controller,
updateServiceConfiguration(

View File

@@ -1,3 +1,7 @@
#include <sstream>
class Package;
std::ostream & operator<<(std::ostream &os, const Package &) { return os; }
#include "orchestration_comp.h"
#include "cptest.h"
@@ -380,6 +384,10 @@ TEST_F(OrchestrationTest, hybridModeRegisterLocalAgentRoutine)
EXPECT_CALL(mock_status, setLastUpdateAttempt());
EXPECT_CALL(mock_status, setIsConfigurationUpdated(_));
string version = "1";
EXPECT_CALL(mock_service_controller, getUpdatePolicyVersion()).WillOnce(ReturnRef(version));
EXPECT_CALL(mock_ml, yield(A<chrono::microseconds>()))
.WillOnce(Return())
.WillOnce(Invoke([] (chrono::microseconds) { throw invalid_argument("stop while loop"); }));
@@ -587,6 +595,9 @@ TEST_F(OrchestrationTest, check_sending_registration_data)
EXPECT_CALL(mock_status, setLastUpdateAttempt());
EXPECT_CALL(mock_status, setIsConfigurationUpdated(_));
string version = "1";
EXPECT_CALL(mock_service_controller, getUpdatePolicyVersion()).WillOnce(ReturnRef(version));
EXPECT_CALL(mock_ml, yield(A<chrono::microseconds>()))
.WillOnce(Return())
.WillOnce(Invoke([] (chrono::microseconds) { throw invalid_argument("stop while loop"); }));
@@ -718,6 +729,9 @@ TEST_F(OrchestrationTest, orchestrationPolicyUpdatRollback)
EXPECT_CALL(mock_status, setPolicyVersion(third_val));
EXPECT_CALL(mock_status, setPolicyVersion(second_val));
string version = "1";
EXPECT_CALL(mock_service_controller, getUpdatePolicyVersion()).WillOnce(ReturnRef(version));
string policy_versions;
EXPECT_CALL(mock_service_controller, getPolicyVersions()).WillRepeatedly(ReturnRef(policy_versions));
EXPECT_CALL(mock_update_communication, sendPolicyVersion("13", _)).Times(1).WillOnce(Return(Maybe<void>()));
@@ -895,6 +909,9 @@ TEST_F(OrchestrationTest, orchestrationPolicyUpdate)
);
EXPECT_CALL(mock_status, setPolicyVersion(third_val));
string version = "1";
EXPECT_CALL(mock_service_controller, getUpdatePolicyVersion()).WillOnce(ReturnRef(version));
string policy_versions;
EXPECT_CALL(mock_service_controller, getPolicyVersions()).WillRepeatedly(ReturnRef(policy_versions));
EXPECT_CALL(mock_update_communication, sendPolicyVersion("13", _)).Times(1).WillOnce(Return(Maybe<void>()));
@@ -1112,6 +1129,9 @@ TEST_F(OrchestrationTest, manifestUpdate)
)
);
string version = "1";
EXPECT_CALL(mock_service_controller, getUpdatePolicyVersion()).WillOnce(ReturnRef(version));
GetResourceFile manifest_file(GetResourceFile::ResourceFileType::MANIFEST);
EXPECT_CALL(mock_downloader,
downloadFile(
@@ -1150,6 +1170,8 @@ TEST_F(OrchestrationTest, manifestUpdate)
TEST_F(OrchestrationTest, getBadPolicyUpdate)
{
Debug::setUnitTestFlag(D_UPDATES_PROCESS_REPORTER, Debug::DebugLevel::NOISE);
EXPECT_CALL(
rest,
mockRestCall(RestAction::ADD, "proxy", _)
@@ -1196,6 +1218,13 @@ TEST_F(OrchestrationTest, getBadPolicyUpdate)
EXPECT_CALL(mock_orchestration_tools, calculateChecksum(Package::ChecksumTypes::SHA256, data_file_path))
.WillOnce(Return(data_checksum));
string manifest = "";
string policy = "111111";
string setting = "";
string second_val = "12";
string third_val = "13";
EXPECT_CALL(mock_service_controller, getUpdatePolicyVersion()).WillRepeatedly(ReturnRef(third_val));
Maybe<string> new_policy_checksum(string("111111"));
GetResourceFile policy_file(GetResourceFile::ResourceFileType::POLICY);
@@ -1207,12 +1236,6 @@ TEST_F(OrchestrationTest, getBadPolicyUpdate)
policy_file
)
).WillOnce(Return(Maybe<std::string>(string(new_policy_path))));
string manifest = "";
string policy = "111111";
string setting = "";
string second_val = "12";
string third_val = "13";
EXPECT_CALL(mock_service_controller, getPolicyVersion())
.Times(4)
.WillOnce(ReturnRef(first_policy_version))
@@ -1246,8 +1269,6 @@ TEST_F(OrchestrationTest, getBadPolicyUpdate)
)
);
EXPECT_CALL(mock_service_controller, getUpdatePolicyVersion()).WillRepeatedly(ReturnRef(third_val));
EXPECT_CALL(
mock_service_controller,
updateServiceConfiguration(string("policy path"), "", expected_data_types, "", "", _)
@@ -1341,6 +1362,9 @@ TEST_F(OrchestrationTest, failedDownloadSettings)
EXPECT_CALL(mock_status, setLastUpdateAttempt());
string version = "1";
EXPECT_CALL(mock_service_controller, getUpdatePolicyVersion()).WillOnce(ReturnRef(version));
string manifest_err =
"Critical Error: Agent/Gateway was not fully deployed on host 'hostname' "
"and is not enforcing a security policy. Retry installation or contact Check Point support.";
@@ -1456,6 +1480,10 @@ TEST_P(OrchestrationTest, orchestrationFirstRun)
}
)
);
string version = "1";
EXPECT_CALL(mock_service_controller, getUpdatePolicyVersion()).WillOnce(ReturnRef(version));
EXPECT_CALL(mock_service_controller, getPolicyVersion()).WillRepeatedly(ReturnRef(first_policy_version));
EXPECT_CALL(mock_update_communication, getUpdate(_)).WillOnce(
Invoke(
@@ -1654,6 +1682,10 @@ TEST_F(OrchestrationTest, dataUpdate)
.WillOnce(Return(data_instance_checksum));
EXPECT_CALL(mock_service_controller, getPolicyVersion()).WillRepeatedly(ReturnRef(first_policy_version));
string version = "1";
EXPECT_CALL(mock_service_controller, getUpdatePolicyVersion()).WillOnce(ReturnRef(version));
EXPECT_CALL(mock_update_communication, getUpdate(_)).WillOnce(
Invoke(
[&](CheckUpdateRequest &req)

View File

@@ -141,7 +141,10 @@ packageHandlerActionsToString(PackageHandlerActions action)
}
}
dbgAssert(false) << "Package handler action is not supported. Action: " << static_cast<unsigned int>(action);
dbgAssert(false)
<< AlertInfo(AlertTeam::CORE, "service configuration")
<< "Package handler action is not supported. Action: "
<< static_cast<unsigned int>(action);
return string();
}

View File

@@ -1,3 +1,7 @@
#include <sstream>
class Package;
static std::ostream & operator<<(std::ostream &os, const Package &) { return os; }
#include "package_handler.h"
#include "cptest.h"

View File

@@ -29,6 +29,7 @@
#include "i_orchestration_tools.h"
#include "customized_cereal_map.h"
#include "declarative_policy_utils.h"
#include "updates_process_event.h"
using namespace std;
using namespace ReportIS;
@@ -65,6 +66,13 @@ public:
}
if (error.get()) {
service_controller->updateReconfStatus(id.get(), service_name.get(), ReconfStatus::FAILED);
UpdatesProcessEvent(
UpdatesProcessResult::FAILED,
UpdatesConfigType::GENERAL,
UpdatesFailureReason::SERVISE_CONFIGURATION,
string(service_name.get() + ", ID: " + to_string(id.get())),
(error_message.isActive() ? " " + error_message.get() : "")
).notify();
dbgError(D_SERVICE_CONTROLLER)
<< "Request for service reconfiguration failed to complete. ID: "
<< id.get()
@@ -319,6 +327,8 @@ public:
set<string> && moveChangedPolicies() override;
bool getServicesPolicyStatus() const override;
private:
void cleanUpVirtualFiles();
@@ -357,6 +367,7 @@ private:
map<int, string> services_reconf_ids;
string filesystem_prefix;
bool is_multi_tenant_env = false;
bool total_services_status = false;
set<string> changed_policy_files;
ServiceDetails orchestration_service_details;
@@ -451,6 +462,12 @@ ServiceController::Impl::moveChangedPolicies()
return move(changed_policy_files);
}
bool
ServiceController::Impl::getServicesPolicyStatus() const
{
return total_services_status;
}
void
ServiceController::Impl::init()
{
@@ -776,7 +793,7 @@ ServiceController::Impl::updateServiceConfiguration(
<< "Policy file was not updated. Sending reload command regarding settings and data";
auto signal_services = sendSignalForServices(nano_services_to_update, "");
if (!signal_services.ok()) return signal_services.passErr();
Singleton::Consume<I_DeclarativePolicy>::from<DeclarativePolicyUtils>()->turnOffApplyPolicyFlag();
Singleton::Consume<I_DeclarativePolicy>::from<DeclarativePolicyUtils>()->turnOffApplyLocalPolicyFlag();
return Maybe<void>();
}
@@ -923,7 +940,7 @@ ServiceController::Impl::updateServiceConfiguration(
if (new_policy_path.compare(config_file_path) == 0) {
dbgDebug(D_SERVICE_CONTROLLER) << "Enforcing the default policy file";
policy_version = version_value;
Singleton::Consume<I_DeclarativePolicy>::from<DeclarativePolicyUtils>()->turnOffApplyPolicyFlag();
Singleton::Consume<I_DeclarativePolicy>::from<DeclarativePolicyUtils>()->turnOffApplyLocalPolicyFlag();
return Maybe<void>();
}
@@ -942,7 +959,7 @@ ServiceController::Impl::updateServiceConfiguration(
}
if (!was_policy_updated && !send_signal_for_services_err.empty()) return genError(send_signal_for_services_err);
Singleton::Consume<I_DeclarativePolicy>::from<DeclarativePolicyUtils>()->turnOffApplyPolicyFlag();
Singleton::Consume<I_DeclarativePolicy>::from<DeclarativePolicyUtils>()->turnOffApplyLocalPolicyFlag();
return Maybe<void>();
}
@@ -952,6 +969,8 @@ ServiceController::Impl::sendSignalForServices(
const string &policy_version_to_update)
{
dbgFlow(D_SERVICE_CONTROLLER) << "Policy version to update: " << policy_version_to_update;
total_services_status = false;
for (auto &service_id : nano_services_to_update) {
auto nano_service = registered_services.find(service_id);
if (nano_service == registered_services.end()) {
@@ -994,6 +1013,7 @@ ServiceController::Impl::sendSignalForServices(
<< "The reconfiguration was successfully completed for all the services";
services_reconf_status.clear();
services_reconf_names.clear();
total_services_status = true;
return Maybe<void>();
}
case ReconfStatus::IN_PROGRESS: {
@@ -1028,6 +1048,12 @@ ServiceController::Impl::sendSignalForServices(
}
dbgDebug(D_SERVICE_CONTROLLER) << "The reconfiguration has reached a timeout";
UpdatesProcessEvent(
UpdatesProcessResult::FAILED,
UpdatesConfigType::GENERAL,
UpdatesFailureReason::SERVISE_CONFIGURATION_TIMEOUT,
"The reconfiguration has reached a timeout"
).notify();
services_reconf_status.clear();
services_reconf_names.clear();
return genError("The reconfiguration has reached a timeout");

View File

@@ -1,3 +1,7 @@
#include <sstream>
class Package;
static std::ostream & operator<<(std::ostream &os, const Package &) { return os; }
#include "cptest.h"
#include <string>
#include "orchestration_tools.h"
@@ -786,6 +790,7 @@ TEST_F(ServiceControllerTest, SettingsAndPolicyUpdateCombinations)
EXPECT_TRUE(i_service_controller->updateServiceConfiguration(file_name, general_settings_path).ok());
EXPECT_EQ(i_service_controller->getPolicyVersion(), version_value);
EXPECT_EQ(i_service_controller->getServicesPolicyStatus(), true);
}
TEST_F(ServiceControllerTest, backup)

View File

@@ -1,2 +1 @@
add_library(update_communication update_communication.cc hybrid_communication.cc fog_communication.cc fog_authenticator.cc local_communication.cc declarative_policy_utils.cc fog_helper_open_source.cc)
#add_subdirectory(update_communication_ut)

View File

@@ -17,7 +17,7 @@ void
DeclarativePolicyUtils::init()
{
local_policy_path = getFilesystemPathConfig() + "/conf/local_policy.yaml";
should_apply_policy = true;
should_apply_local_policy = true;
Singleton::Consume<I_RestApi>::by<DeclarativePolicyUtils>()->addRestCall<ApplyPolicyRest>(
RestAction::SET, "apply-policy"
);
@@ -40,7 +40,7 @@ DeclarativePolicyUtils::upon(const ApplyPolicyEvent &event)
{
dbgTrace(D_ORCHESTRATOR) << "Apply policy event";
local_policy_path = event.getPolicyPath();
should_apply_policy = true;
should_apply_local_policy = true;
}
// LCOV_EXCL_STOP
@@ -48,19 +48,24 @@ bool
DeclarativePolicyUtils::shouldApplyPolicy()
{
auto env_type = Singleton::Consume<I_EnvDetails>::by<DeclarativePolicyUtils>()->getEnvType();
return env_type == EnvType::K8S ? true : should_apply_policy;
if (env_type == EnvType::K8S) {
I_OrchestrationTools *orch_tools = Singleton::Consume<I_OrchestrationTools>::by<DeclarativePolicyUtils>();
auto maybe_new_version = orch_tools->readFile("/etc/cp/conf/k8s-policy-check.trigger");
return maybe_new_version != curr_version;
}
return should_apply_local_policy;
}
void
DeclarativePolicyUtils::turnOffApplyPolicyFlag()
DeclarativePolicyUtils::turnOffApplyLocalPolicyFlag()
{
should_apply_policy = false;
should_apply_local_policy = false;
}
void
DeclarativePolicyUtils::turnOnApplyPolicyFlag()
DeclarativePolicyUtils::turnOnApplyLocalPolicyFlag()
{
should_apply_policy = true;
should_apply_local_policy = true;
}
Maybe<string>
@@ -211,6 +216,6 @@ DeclarativePolicyUtils::periodicPolicyLoad()
if (*new_checksum == curr_checksum) return;
should_apply_policy = true;
should_apply_local_policy = true;
curr_checksum = *new_checksum;
}

View File

@@ -467,7 +467,10 @@ getDeplymentType()
case EnvType::COUNT: break;
}
dbgAssert(false) << "Failed to get a legitimate deplyment type: " << static_cast<uint>(deplyment_type);
dbgAssert(false)
<< AlertInfo(AlertTeam::CORE, "fog communication")
<< "Failed to get a legitimate deplyment type: "
<< static_cast<uint>(deplyment_type);
return "Embedded";
}

View File

@@ -74,7 +74,7 @@ FogCommunication::getUpdate(CheckUpdateRequest &request)
<< " to: "
<< policy_mgmt_mode;
profile_mode = policy_mgmt_mode;
i_declarative_policy->turnOnApplyPolicyFlag();
i_declarative_policy->turnOnApplyLocalPolicyFlag();
}
if (i_declarative_policy->shouldApplyPolicy()) {

View File

@@ -120,10 +120,9 @@ HybridCommunication::downloadAttributeFile(const GetResourceFile &resourse_file,
}
Maybe<void>
HybridCommunication::sendPolicyVersion(const string &policy_version, const string &) const
HybridCommunication::sendPolicyVersion(const string &, const string &) const
{
dbgFlow(D_ORCHESTRATOR);
policy_version.empty();
return Maybe<void>();
}

View File

@@ -1,7 +0,0 @@
link_directories(${BOOST_ROOT}/lib)
add_unit_test(
update_communication_ut
"local_communication_ut.cc;fog_communication_ut.cc"
"rest;version;orchestration_modules;update_communication;singleton;config;metric;event_is;logging;agent_details;-lboost_regex;local_policy_mgmt_gen;connkey;"
)

View File

@@ -1,244 +0,0 @@
#include <string>
#include "local_communication.h"
#include "cptest.h"
#include "mock/mock_orchestration_tools.h"
#include "config.h"
#include "config_component.h"
#include "orchestration_status.h"
#include "mock/mock_mainloop.h"
#include "mock/mock_time_get.h"
using namespace std;
using namespace testing;
ostream &
operator<<(ostream &os, const tuple<OrchManifest, OrchPolicy, OrchSettings> &)
{
return os;
}
class LocalCommunicationTest: public Test
{
public:
LocalCommunicationTest()
{
local_communication.init();
}
void
preload()
{
local_communication.preload();
}
Maybe<void>
authenticateAgent()
{
return local_communication.authenticateAgent();
}
void
registerLocalAgentToFog()
{
local_communication.registerLocalAgentToFog();
}
Maybe<void>
sendPolicyVersion(const string &version, const string &policy_versions)
{
return local_communication.sendPolicyVersion(version, policy_versions);
}
Maybe<string>
downloadAttributeFile(const GetResourceFile &resourse_file, const string &file_path)
{
return local_communication.downloadAttributeFile(resourse_file, file_path);
}
void
setAddressExtenesion(const string &ext)
{
local_communication.setAddressExtenesion(ext);
}
Maybe<void>
checkUpdate(CheckUpdateRequest &request)
{
return local_communication.getUpdate(request);
}
NiceMock<MockMainLoop> mock_mainloop;
NiceMock<MockTimeGet> mock_timer;
::Environment env;
ConfigComponent config_comp;
StrictMock<MockOrchestrationTools> mock_orc_tools;
OrchestrationStatus orc_status;
private:
LocalCommunication local_communication;
};
TEST_F(LocalCommunicationTest, doNothing)
{
}
TEST_F(LocalCommunicationTest, registerConfig)
{
env.preload();
env.init();
preload();
string config_json =
"{\n"
" \"orchestration\": {\n"
" \"Offline manifest file path\": [\n"
" {\n"
" \"context\": \"All()\",\n"
" \"value\": \"ABC\"\n"
" }\n"
" ],\n"
" \"Offline policy file path\": [\n"
" {\n"
" \"context\": \"All()\",\n"
" \"value\": \"qwe\"\n"
" }\n"
" ],\n"
" \"Offline settings file path\": [\n"
" {\n"
" \"context\": \"All()\",\n"
" \"value\": \"CCCC\"\n"
" }\n"
" ]\n"
" }\n"
"}";
istringstream ss(config_json);
Singleton::Consume<Config::I_Config>::from(config_comp)->loadConfiguration(ss);
EXPECT_THAT(getConfiguration<string>("orchestration", "Offline manifest file path"), IsValue("ABC"));
EXPECT_THAT(getConfiguration<string>("orchestration", "Offline policy file path"), IsValue("qwe"));
EXPECT_THAT(getConfiguration<string>("orchestration", "Offline settings file path"), IsValue("CCCC"));
env.fini();
}
TEST_F(LocalCommunicationTest, authenticateAgent)
{
auto authenticat_res = authenticateAgent();
EXPECT_TRUE(authenticat_res.ok());
}
TEST_F(LocalCommunicationTest, registerLocalAgentToFog)
{
registerLocalAgentToFog();
}
TEST_F(LocalCommunicationTest, downloadManifest)
{
string new_manifest_string = "new manifest";
EXPECT_CALL(mock_orc_tools, readFile("/etc/cp/conf/offline_manifest.json")).WillOnce(Return(new_manifest_string));
GetResourceFile resourse_file(GetResourceFile::ResourceFileType::MANIFEST);
auto downloaded_string = downloadAttributeFile(resourse_file, "/tmp/orch_files");
EXPECT_TRUE(downloaded_string.ok());
EXPECT_EQ(downloaded_string.unpack(), new_manifest_string);
}
TEST_F(LocalCommunicationTest, checkUpdateWithNoUpdate)
{
Maybe<string> manifest_checksum(string("1"));
Maybe<string> policy_checksum(string("2"));
Maybe<string> settings_checksum(string("3"));
Maybe<string> data_checksum(string("4"));
EXPECT_CALL(mock_orc_tools, calculateChecksum(
Package::ChecksumTypes::SHA256, "/etc/cp/conf/offline_manifest.json")).WillOnce(Return(manifest_checksum));
EXPECT_CALL(mock_orc_tools, calculateChecksum(
Package::ChecksumTypes::SHA256, "/etc/cp/conf/offline_policy.json")).WillOnce(Return(policy_checksum));
EXPECT_CALL(mock_orc_tools, calculateChecksum(
Package::ChecksumTypes::SHA256, "/etc/cp/conf/offline_settings.json")).WillOnce(Return(settings_checksum));
EXPECT_CALL(mock_orc_tools, calculateChecksum(
Package::ChecksumTypes::SHA256, "/etc/cp/conf/data/offline_data.json")).WillOnce(Return(data_checksum));
CheckUpdateRequest request(
*manifest_checksum,
*policy_checksum,
*settings_checksum,
*data_checksum,
I_OrchestrationTools::SELECTED_CHECKSUM_TYPE_STR,
"123"
);
auto update_response = checkUpdate(request);
EXPECT_TRUE(update_response.ok());
Maybe<string> manifest = request.getManifest();
EXPECT_FALSE(manifest.ok());
Maybe<string> policy = request.getPolicy();
EXPECT_FALSE(policy.ok());
Maybe<string> settings = request.getSettings();
EXPECT_FALSE(settings.ok());
Maybe<string> data = request.getData();
EXPECT_FALSE(data.ok());
}
TEST_F(LocalCommunicationTest, checkUpdateWithPolicyUpdate)
{
Maybe<string> manifest_checksum(string("1"));
Maybe<string> policy_checksum(string("2"));
Maybe<string> new_policy_checksum(string("22"));
Maybe<string> settings_checksum(string("3"));
Maybe<string> data_checksum(string("4"));
EXPECT_CALL(
mock_orc_tools,
calculateChecksum(Package::ChecksumTypes::SHA256, "/etc/cp/conf/offline_manifest.json")
).WillOnce(Return(manifest_checksum));
EXPECT_CALL(
mock_orc_tools,
calculateChecksum(Package::ChecksumTypes::SHA256, "/etc/cp/conf/offline_policy.json")
).WillOnce(Return(new_policy_checksum));
EXPECT_CALL(
mock_orc_tools,
calculateChecksum(Package::ChecksumTypes::SHA256, "/etc/cp/conf/offline_settings.json")
).WillOnce(Return(settings_checksum));
EXPECT_CALL(
mock_orc_tools,
calculateChecksum(Package::ChecksumTypes::SHA256, "/etc/cp/conf/data/offline_data.json")
).WillOnce(Return(data_checksum));
CheckUpdateRequest request(
*manifest_checksum,
*policy_checksum,
*settings_checksum,
*data_checksum,
I_OrchestrationTools::SELECTED_CHECKSUM_TYPE_STR,
"123"
);
auto update_response = checkUpdate(request);
EXPECT_TRUE(update_response.ok());
Maybe<string> manifest = request.getManifest();
EXPECT_FALSE(manifest.ok());
EXPECT_THAT(request.getPolicy(), IsValue("22"));
Maybe<string> settings = request.getSettings();
EXPECT_FALSE(settings.ok());
Maybe<string> data = request.getData();
EXPECT_FALSE(data.ok());
}
TEST_F(LocalCommunicationTest, setAddressExtenesion)
{
setAddressExtenesion("Test");
}
TEST_F(LocalCommunicationTest, sendPolicyVersion)
{
auto res = sendPolicyVersion("12", "");
EXPECT_TRUE(res.ok());
}

View File

@@ -111,6 +111,18 @@ UpdatesProcessEvent::parseDescription() const
err << "Failed to configure the fog address: " << detail << ". Error: " << description;
break;
}
case UpdatesFailureReason::SERVISE_CONFIGURATION : {
err
<< "Request for service reconfiguration failed to complete. Service name: "
<< detail
<< ". Error: "
<< description;
break;
}
case UpdatesFailureReason::SERVISE_CONFIGURATION_TIMEOUT : {
err << detail;
break;
}
case UpdatesFailureReason::ORCHESTRATION_SELF_UPDATE : {
err << description;
break;
@@ -170,6 +182,14 @@ UpdatesProcessEvent::getDescriptionWithoutErrors() const
err << "Failed to configure the fog address: " << detail;
break;
}
case UpdatesFailureReason::SERVISE_CONFIGURATION : {
err << "Request for service reconfiguration failed to complete. Service name: " << detail;
break;
}
case UpdatesFailureReason::SERVISE_CONFIGURATION_TIMEOUT : {
err << detail;
break;
}
case UpdatesFailureReason::ORCHESTRATION_SELF_UPDATE : {
err << description;
break;

View File

@@ -18,6 +18,7 @@
#include "debug.h"
#include "log_generator.h"
#include "service_health_update_event.h"
using namespace std;
@@ -29,14 +30,22 @@ void
UpdatesProcessReporter::upon(const UpdatesProcessEvent &event)
{
if (event.getReason() == UpdatesFailureReason::CHECK_UPDATE) {
auto i_controller = Singleton::Consume<I_ServiceController>::by<UpdatesProcessReporter>();
string version = i_controller->getUpdatePolicyVersion();
if (event.getResult() == UpdatesProcessResult::SUCCESS && reports.empty()) {
dbgTrace(D_UPDATES_PROCESS_REPORTER) << "Update proccess finished successfully";
report_failure_count = 0;
report_failure_count_map.erase(version);
ServiceHealthUpdateEvent().notify();
return;
}
dbgTrace(D_UPDATES_PROCESS_REPORTER) << "Update proccess finished with errors";
report_failure_count++;
if (report_failure_count <= 1) {
if (report_failure_count_map.find(version) == report_failure_count_map.end()) {
report_failure_count_map[version] = 0;
}
report_failure_count_map[version]++;
dbgTrace(D_UPDATES_PROCESS_REPORTER)
<< "Update proccess finished with errors. Count: "
<< report_failure_count_map[version];
if (report_failure_count_map[version] <= 1) {
reports.clear();
return;
}
@@ -48,22 +57,24 @@ UpdatesProcessReporter::upon(const UpdatesProcessEvent &event)
event.parseDescription()
)
);
sendReoprt();
sendReoprt(version);
return;
}
if (event.getResult() == UpdatesProcessResult::SUCCESS || event.getResult() == UpdatesProcessResult::UNSET) return;
reports.emplace_back(
UpdatesProcessReport(event.getResult(), event.getType(), event.getReason(), event.parseDescription())
);
ServiceHealthUpdateEvent(convertUpdatesConfigTypeToStr(event.getType()), event.parseDescription()).notify();
}
void
UpdatesProcessReporter::sendReoprt()
UpdatesProcessReporter::sendReoprt(const string &version)
{
stringstream full_reports;
UpdatesFailureReason failure_reason = UpdatesFailureReason::NONE;
full_reports << "Updates process reports:" << endl;
full_reports << "report failure count:" << report_failure_count << endl;
full_reports << "Policy version: " << version << endl;
full_reports << "report failure count:" << report_failure_count_map[version] << endl;
for (const auto &report : reports) {
if (report.getReason() != UpdatesFailureReason::CHECK_UPDATE) {
failure_reason = report.getReason();

View File

@@ -211,6 +211,8 @@ public:
for (const auto &rule : rate_limit_config.getRateLimitRules()) {
string full_rule_uri = application_uri + rule.getRateLimitUri();
transform(full_rule_uri.begin(), full_rule_uri.end(),
full_rule_uri.begin(), [](unsigned char c) { return std::tolower(c); });
int full_rule_uri_length = full_rule_uri.length();
dbgTrace(D_RATE_LIMIT)
@@ -291,8 +293,13 @@ public:
return ACCEPT;
}
burst = rule.getRateLimit();
limit = calcRuleLimit(rule);
auto replicas = getenv("REPLICA_COUNT") ? std::stoi(getenv("REPLICA_COUNT")) : 1;
if (replicas == 0) {
dbgWarning(D_RATE_LIMIT) << "REPLICA_COUNT environment variable is set to 0, setting REPLICA_COUNT to 1";
replicas = 1;
}
burst = static_cast<float>(rule.getRateLimit()) / replicas;
limit = static_cast<float>(calcRuleLimit(rule)) / replicas;
dbgTrace(D_RATE_LIMIT)
<< "found rate limit rule with: "

View File

@@ -70,6 +70,7 @@ public:
virtual const std::string getParam() const = 0;
virtual const std::vector<std::string> getKeywordMatches() const = 0;
virtual const std::vector<std::string> getKeywordsCombinations() const = 0;
virtual const std::vector<std::string> getKeywordsAfterFilter() const = 0;
virtual const std::string getContentTypeStr() const = 0;
virtual Waap::Util::ContentType getContentType() const = 0;
virtual const std::string getKeywordMatchesStr() const = 0;
@@ -84,6 +85,7 @@ public:
virtual const std::string getUriStr() const = 0;
virtual const std::string& getSourceIdentifier() const = 0;
virtual double getScore() const = 0;
virtual double getOtherModelScore() const = 0;
virtual const std::vector<double> getScoreArray() const = 0;
virtual Waap::CSRF::State& getCsrfState() = 0;
virtual ngx_http_cp_verdict_e getUserLimitVerdict() = 0;

View File

@@ -87,7 +87,10 @@ add_library(waap_clib
ParserPairs.cc
Waf2Util2.cc
ParserPDF.cc
ParserKnownBenignSkipper.cc
ParserScreenedJson.cc
ParserBinaryFile.cc
RegexComparator.cc
)
add_definitions("-Wno-unused-function")

View File

@@ -25,6 +25,51 @@
#include "log_generator.h"
#include <stdexcept>
static in_addr applyMaskV4(const in_addr& addr, uint8_t prefixLength) {
in_addr maskedAddr;
if (prefixLength == 0) {
maskedAddr.s_addr = 0;
} else {
uint32_t mask = htonl(~((1 << (32 - prefixLength)) - 1)); // Create mask
maskedAddr.s_addr = addr.s_addr & mask; // Apply mask
}
return maskedAddr;
}
// Function to apply a network mask to an IPv6 address
static in6_addr applyMaskV6(const in6_addr& addr, uint8_t prefixLength) {
in6_addr maskedAddr = addr;
int fullBytes = prefixLength / 8;
int remainingBits = prefixLength % 8;
// Mask full bytes
for (int i = fullBytes; i < 16; ++i) {
maskedAddr.s6_addr[i] = 0;
}
// Mask remaining bits
if (remainingBits > 0) {
uint8_t mask = ~((1 << (8 - remainingBits)) - 1);
maskedAddr.s6_addr[fullBytes] &= mask;
}
return maskedAddr;
}
// Helper function to convert an IPv4 address to string
static std::string ipv4ToString(const in_addr& ipv4) {
char str[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &ipv4, str, INET_ADDRSTRLEN);
return std::string(str);
}
// Helper function to convert an IPv6 address to string
static std::string ipv6ToString(const in6_addr& ipv6) {
char str[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &ipv6, str, INET6_ADDRSTRLEN);
return std::string(str);
}
USE_DEBUG_FLAG(D_WAAP);
namespace Waap {
namespace Util {
@@ -38,6 +83,15 @@ bool CIDRData::operator==(const CIDRData &other) const {
isIPV6 == other.isIPV6;
}
bool CIDRData::operator<(const CIDRData &other) const {
if (isIPV6) {
if (!other.isIPV6) return false;
return memcmp(ipCIDRV6.s6_addr, other.ipCIDRV6.s6_addr, sizeof(ipCIDRV6.s6_addr)) < 0;
}
if (other.isIPV6) return true;
return ntohl(ipCIDRV4.s_addr) < ntohl(other.ipCIDRV4.s_addr);
}
bool cidr4_match(const in_addr &addr, const in_addr &net, uint8_t bits) {
if (bits == 0) {
// C99 6.5.7 (3): u32 << 32 is undefined behaviour
@@ -114,9 +168,11 @@ bool isCIDR(const std::string& strCIDR, CIDRData& cidr)
memset(&cidr.ipCIDRV6, 0, sizeof(struct in6_addr));
if (inet_pton(AF_INET, strPrefix.c_str(), &cidr.ipCIDRV4) == 1 && bits <= 32) {
cidr.ipCIDRV4 = applyMaskV4(cidr.ipCIDRV4, bits);
cidr.isIPV6 = false;
}
else if (inet_pton(AF_INET6, strPrefix.c_str(), &cidr.ipCIDRV6) == 1 && bits <= 128) {
cidr.ipCIDRV6 = applyMaskV6(cidr.ipCIDRV6, bits);
cidr.isIPV6 = true;
}
else
@@ -128,6 +184,7 @@ bool isCIDR(const std::string& strCIDR, CIDRData& cidr)
return true;
}
bool cidrMatch(const std::string& sourceip, const std::string& targetCidr) {
CIDRData cidrData;
@@ -139,6 +196,7 @@ bool cidrMatch(const std::string& sourceip, const std::string& targetCidr) {
return cidrMatch(sourceip, cidrData);
}
bool cidrMatch(const std::string & sourceip, const CIDRData & cidr){
struct in_addr source_inaddr;
struct in6_addr source_inaddr6;
@@ -155,5 +213,43 @@ bool cidrMatch(const std::string & sourceip, const CIDRData & cidr){
dbgDebug(D_WAAP) << "Source IP address does not match any of the CIDR definitions.";
return false;
}
bool doesFirstCidrContainSecond(const CIDRData &first, const CIDRData &second) {
if (first.isIPV6 != second.isIPV6) return false; // IPv4 and IPv6 cannot overlap
if (first.networkBits >= second.networkBits) return false;
if (!first.isIPV6) {
// IPv4 containment check
in_addr smallerNetwork = applyMaskV4(second.ipCIDRV4, first.networkBits);
return (first.ipCIDRV4.s_addr == smallerNetwork.s_addr);
}
// IPv6 containment check
in6_addr smallerNetwork = applyMaskV6(second.ipCIDRV6, first.networkBits);
for (int i = 0; i < 16; ++i) {
if (first.ipCIDRV6.s6_addr[i] != smallerNetwork.s6_addr[i]) {
return false;
}
}
return true;
}
std::string cidrsToString(const std::vector<CIDRData>& cidrs) {
std::stringstream ss;
bool is_first = true;
ss << "[";
for (const auto& cidr : cidrs) {
if (!is_first) ss << ", ";
if (cidr.isIPV6) {
ss << ipv6ToString(cidr.ipCIDRV6) << "/" << static_cast<int>(cidr.networkBits);
} else {
ss << ipv4ToString(cidr.ipCIDRV4) << "/" << static_cast<int>(cidr.networkBits);
}
is_first = false;
}
ss << "]";
return ss.str();
}
}
}

View File

@@ -18,6 +18,7 @@
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <vector>
namespace Waap {
namespace Util {
@@ -29,11 +30,14 @@ struct CIDRData {
uint8_t networkBits;
bool isIPV6;
bool operator==(const CIDRData &other) const;
bool operator<(const CIDRData &other) const;
};
bool isCIDR(const std::string& strCIDR, CIDRData& cidr);
bool cidrMatch(const std::string& sourceip, const CIDRData& cidr);
bool cidrMatch(const std::string &sourceip, const std::string &target);
bool doesFirstCidrContainSecond(const CIDRData &first, const CIDRData &second);
std::string cidrsToString(const std::vector<CIDRData>& cidrs);
}
}

View File

@@ -28,6 +28,8 @@
#include "ParserDelimiter.h"
#include "ParserPDF.h"
#include "ParserBinaryFile.h"
#include "ParserKnownBenignSkipper.h"
#include "ParserScreenedJson.h"
#include "WaapAssetState.h"
#include "Waf2Regex.h"
#include "Waf2Util.h"
@@ -359,6 +361,7 @@ DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int f
isRefererParamPayload,
isUrlPayload,
isUrlParamPayload,
isCookiePayload,
flags,
parser_depth,
base64BinaryFileType
@@ -390,6 +393,39 @@ DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int f
}
}
if (flags & BUFFERED_RECEIVER_F_FIRST && offset < 0 && valueStats.hasPercent &&
m_key.first().size() == 6 && m_key.first() == "cookie") {
dbgTrace(D_WAAP_DEEP_PARSER)
<< "1st pass of createInternalParser() failed. "
<< "Will try to decode percent-encoded data and repeate search for parser";
orig_val.erase(unquote_plus(orig_val.begin(), orig_val.end()), orig_val.end());
cur_val_html_escaped = orig_val;
cur_val_html_escaped.erase(
escape_html(cur_val_html_escaped.begin(), cur_val_html_escaped.end()), cur_val_html_escaped.end()
);
offset = createInternalParser(
k,
k_len,
orig_val,
valueStats,
isBodyPayload,
isRefererPayload,
isRefererParamPayload,
isUrlPayload,
isUrlParamPayload,
isCookiePayload,
flags,
parser_depth,
base64BinaryFileType
);
if (offset >= 0) {
dbgTrace(D_WAAP_DEEP_PARSER) << "2nd pass of createInternalParser succeeded. Update values and proceed";
ValueStatsAnalyzer valueStatsUpdated(cur_val_html_escaped);
cur_val.erase(unquote_plus(cur_val.begin(), cur_val.end()), cur_val.end());
Waap::Util::decodeUtf16Value(valueStatsUpdated, cur_val);
}
}
// If there's a parser in parsers stack, push the value to the top parser
if (!m_parsersDeque.empty()
&& offset >= 0
@@ -429,6 +465,7 @@ DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int f
isRefererParamPayload,
isUrlPayload,
isUrlParamPayload,
isCookiePayload,
flags,
parser_depth,
base64ParamFound,
@@ -803,6 +840,7 @@ DeepParser::parseAfterMisleadingMultipartBoundaryCleaned(
bool isRefererParamPayload,
bool isUrlPayload,
bool isUrlParamPayload,
bool isCookiePayload,
int flags,
size_t parser_depth,
bool base64ParamFound,
@@ -822,6 +860,7 @@ DeepParser::parseAfterMisleadingMultipartBoundaryCleaned(
isRefererParamPayload,
isUrlPayload,
isUrlParamPayload,
isCookiePayload,
flags,
parser_depth,
b64FileType
@@ -886,6 +925,7 @@ bool isRefererPayload,
bool isRefererParamPayload,
bool isUrlPayload,
bool isUrlParamPayload,
bool isCookiePayload,
int flags,
size_t parser_depth
) {
@@ -927,6 +967,7 @@ DeepParser::createInternalParser(
bool isRefererParamPayload,
bool isUrlPayload,
bool isUrlParamPayload,
bool isCookiePayload,
int flags,
size_t parser_depth,
Waap::Util::BinaryFileType b64FileType
@@ -946,7 +987,19 @@ DeepParser::createInternalParser(
<< "\n\tflags: "
<< flags
<< "\n\tparser_depth: "
<< parser_depth;
<< parser_depth
<< "\n\tisBodyPayload: "
<< isBodyPayload
<< "\n\tisRefererPayload: "
<< isRefererPayload
<< "\n\tisRefererParamPayload: "
<< isRefererParamPayload
<< "\n\tisUrlPayload: "
<< isUrlPayload
<< "\n\tisUrlParamPayload: "
<< isUrlParamPayload
<< "\n\tisCookiePayload: "
<< isCookiePayload;
bool isPipesType = false, isSemicolonType = false, isAsteriskType = false, isCommaType = false,
isAmperType = false;
bool isKeyValDelimited = false;
@@ -1013,6 +1066,53 @@ DeepParser::createInternalParser(
}
}
if (Waap::Util::isScreenedJson(cur_val)) {
dbgTrace(D_WAAP_DEEP_PARSER) << "Starting to parse screened JSON";
m_parsersDeque.push_back(std::make_shared<BufferedParser<ParserScreenedJson>>(*this, parser_depth + 1));
offset = 0;
return offset;
}
dbgTrace(D_WAAP_DEEP_PARSER)
<< "Offset = "
<< offset
<< " depth = "
<< m_depth
<< " isBodyPayload = "
<< isBodyPayload;
//Detect sensor_data format in body and just use dedicated filter for it
if (m_depth == 1
&& isBodyPayload
&& Waap::Util::detectKnownSource(cur_val) == Waap::Util::SOURCE_TYPE_SENSOR_DATA) {
m_parsersDeque.push_back(
std::make_shared<BufferedParser<ParserKnownBenignSkipper>>(
*this,
parser_depth + 1,
Waap::Util::SOURCE_TYPE_SENSOR_DATA
)
);
offset = 0;
dbgTrace(D_WAAP_DEEP_PARSER) << "Starting to parse data_sensor data - skipping it";
return offset;
}
// Detect cookie parameter sensorsdata2015jssdkcross
// and causes false positives due to malformed JSON. Make preprocessing to parse it correctly
if (m_depth == 2
&& isCookiePayload) {
offset = Waap::Util::definePrefixedJson(cur_val);
if (offset >= 0) {
m_parsersDeque.push_back(
std::make_shared<BufferedParser<ParserJson>>(
*this,
parser_depth + 1,
m_pTransaction
)
);
dbgTrace(D_WAAP_DEEP_PARSER) << "Starting to parse JSON data";
return offset;
}
}
// Detect wbxml (binary XML) data type
if (m_depth == 1 && isBodyPayload && !valueStats.isUTF16 && m_pWaapAssetState->isWBXMLSampleType(cur_val)) {
m_is_wbxml = true;
@@ -1183,6 +1283,7 @@ DeepParser::createInternalParser(
offset = 0;
}
}
bool isCockiePapameter = m_key.depth() == 2 && m_key.first().size() == 6 && m_key.first() == "cookie";
if (offset < 0) {
if (isPipesType) {
dbgTrace(D_WAAP_DEEP_PARSER) << "Starting to parse pipes, positional: " << isKeyValDelimited;
@@ -1275,11 +1376,11 @@ DeepParser::createInternalParser(
*this,
parser_depth + 1,
'&',
valueStats.isUrlEncoded)
valueStats.isUrlEncoded && !Waap::Util::testUrlBadUtf8Evasion(cur_val))
);
} else if (!Waap::Util::testUrlBareUtf8Evasion(cur_val)) {
dbgTrace(D_WAAP_DEEP_PARSER) << "!Waap::Util::testUrlBareUtf8Evasion(cur_val)";
if (!valueStats.hasSpace
if ((!valueStats.hasSpace || (valueStats.hasSpace && isCockiePapameter))
&& valueStats.hasCharAmpersand
&& valueStats.hasTwoCharsEqual
&& !isBinaryData()
@@ -1290,7 +1391,7 @@ DeepParser::createInternalParser(
*this,
parser_depth + 1,
'&',
valueStats.isUrlEncoded)
valueStats.isUrlEncoded && !Waap::Util::testUrlBadUtf8Evasion(cur_val))
);
offset = 0;
return offset;
@@ -1305,7 +1406,7 @@ DeepParser::createInternalParser(
}
} else if (!Waap::Util::testUrlBareUtf8Evasion(cur_val)) {
dbgTrace(D_WAAP_DEEP_PARSER) << "!Waap::Util::testUrlBareUtf8Evasion(cur_val)";
if (!valueStats.hasSpace
if ((!valueStats.hasSpace || (valueStats.hasSpace && isCockiePapameter))
&& valueStats.hasCharAmpersand
&& valueStats.hasTwoCharsEqual
&& !isBinaryData()
@@ -1341,6 +1442,7 @@ DeepParser::createInternalParser(
isRefererParamPayload,
isUrlPayload,
isUrlParamPayload,
isCookiePayload,
flags,
parser_depth
);
@@ -1512,5 +1614,6 @@ DeepParser::isPDFDetected(const std::string &cur_val) const
static const std::string PDF_header("%PDF-");
if (cur_val.size() < 10)
return false;
return cur_val.substr(0, cur_val.size() > 64 ? 64 : cur_val.size()).find(PDF_header) != std::string::npos;
return cur_val.substr(0, cur_val.size() > MAX_PDF_HEADER_LOOKUP ? MAX_PDF_HEADER_LOOKUP : cur_val.size())
.find(PDF_header) != std::string::npos;
}

View File

@@ -129,6 +129,7 @@ private:
bool isRefererParamPayload,
bool isUrlPayload,
bool isUrlParamPayload,
bool isCookiePayload,
int flags,
size_t parser_depth,
Waap::Util::BinaryFileType b64FileType
@@ -144,6 +145,7 @@ private:
bool isRefererParamPayload,
bool isUrlPayload,
bool isUrlParamPayload,
bool isCookiePayload,
int flags,
size_t parser_depth
);
@@ -160,6 +162,7 @@ private:
bool isRefererParamPayload,
bool isUrlPayload,
bool isUrlParamPayload,
bool isCookiePayload,
int flags,
size_t parser_depth,
bool base64ParamFound,

View File

@@ -150,7 +150,8 @@ ParserBinaryFile::push(const char *buf, size_t len)
}
} else {
dbgTrace(D_WAAP_PARSER_BINARY_FILE) << "parsing binary. Searching for tail: " << tail;
c = strstr(buf + len - tail.size(), tail.c_str());
size_t tail_lookup_offset = (len > MAX_TAIL_LOOKUP) ? len - MAX_TAIL_LOOKUP : 0;
c = strstr(buf + tail_lookup_offset, tail.c_str());
dbgTrace(D_WAAP_PARSER_BINARY_FILE) << "search result: c=" << c;
if (c) {
m_state = s_end;

View File

@@ -20,7 +20,7 @@
#define MIN_HEADER_LOOKUP 16
#define MAX_HEADER_LOOKUP 64
#define MAX_TAIL_LOOKUP 5
#define MAX_TAIL_LOOKUP 20
class ParserBinaryFile : public ParserBase {
public:

View File

@@ -0,0 +1,139 @@
// 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 "ParserKnownBenignSkipper.h"
#include "Waf2Util.h"
#include "debug.h"
#include <string.h>
USE_DEBUG_FLAG(D_WAAP_PARSER_KNOWN_SOURCE_SKIPPER);
USE_DEBUG_FLAG(D_WAAP);
const std::string ParserKnownBenignSkipper::m_parserName = "ParserKnownBenignSkipper";
const char* DATA_SENSOR_TAIL = "\"}";
ParserKnownBenignSkipper::ParserKnownBenignSkipper(
IParserStreamReceiver &receiver,
size_t parser_depth,
Waap::Util::KnownSourceType source_type
) :
m_receiver(receiver),
m_state(s_start),
m_parser_depth(parser_depth),
m_source_type(source_type)
{}
ParserKnownBenignSkipper::~ParserKnownBenignSkipper()
{}
size_t
ParserKnownBenignSkipper::push(const char *buf, size_t len)
{
dbgTrace(D_WAAP_PARSER_KNOWN_SOURCE_SKIPPER)
<< "buf='"
<< std::string(buf, std::min((size_t)200, len))
<< (len > 200 ? "..." : "")
<< "' len="
<< len
<< " depth="
<< depth();
const char *c;
if (m_state == s_error) {
return 0;
}
if (len == 0)
{
dbgTrace(D_WAAP_PARSER_KNOWN_SOURCE_SKIPPER)
<< "ParserKnownBenignSkipper::push(): end of stream. m_state="
<< m_state;
if (m_state == s_end) {
m_receiver.onKvDone();
} else {
m_state = s_error;
}
return 0;
}
size_t tail_lookup_offset = 0;
switch (m_state) {
case s_start:
m_state = s_body;
CP_FALL_THROUGH;
case s_body:
{
if (m_source_type == Waap::Util::SOURCE_TYPE_SENSOR_DATA) {
tail_lookup_offset =
(len > MAX_DATA_SENSOR_TAIL_LOOKUP) ? len - MAX_DATA_SENSOR_TAIL_LOOKUP : 0;
c = strstr(buf + tail_lookup_offset, DATA_SENSOR_TAIL);
if (c) {
dbgTrace(D_WAAP_PARSER_KNOWN_SOURCE_SKIPPER)
<< "ParserKnownBenignSkipper::push(): found end of sensor data";
m_state = s_end;
CP_FALL_THROUGH;
} else {
break;
}
} else {
dbgTrace(D_WAAP_PARSER_KNOWN_SOURCE_SKIPPER)
<< "ParserKnownBenignSkipper::push(): unknown source type";
m_state = s_error;
break;
}
}
case s_end:
dbgTrace(D_WAAP_PARSER_KNOWN_SOURCE_SKIPPER) << "state = end";
if (m_receiver.onKey("SENSOR_DATA", 11) != 0) {
dbgTrace(D_WAAP_PARSER_KNOWN_SOURCE_SKIPPER) << "state moving to error onKey";
m_state = s_error;
return 0;
}
if (m_receiver.onValue("", 0) != 0) {
dbgTrace(D_WAAP_PARSER_KNOWN_SOURCE_SKIPPER) << "state moving to error onValue";
m_state = s_error;
return 0;
}
break;
case s_error:
dbgTrace(D_WAAP_PARSER_KNOWN_SOURCE_SKIPPER) << "state = error";
break;
default:
dbgTrace(D_WAAP_PARSER_KNOWN_SOURCE_SKIPPER)
<< "ParserKnownBenignSkipper::push(): unknown state: "
<< m_state;
m_state = s_error;
return 0;
}
dbgTrace(D_WAAP_PARSER_KNOWN_SOURCE_SKIPPER)
<< "ParserKnownBenignSkipper::push(): final state: "
<< m_state;
return len;
}
void ParserKnownBenignSkipper::finish()
{
push(NULL, 0);
}
const std::string& ParserKnownBenignSkipper::name() const
{
return m_parserName;
}
bool ParserKnownBenignSkipper::error() const
{
return m_state == s_error;
}

Some files were not shown because too many files have changed in this diff Show More