mirror of
https://github.com/openappsec/openappsec.git
synced 2025-12-31 13:49:08 +03:00
sync code
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
add_subdirectory(report_messaging)
|
||||
add_subdirectory(http_manager)
|
||||
add_subdirectory(signal_handler)
|
||||
add_subdirectory(gradual_deployment)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 "";
|
||||
}
|
||||
|
||||
@@ -1582,7 +1586,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 +1637,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 +1657,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 +1716,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);
|
||||
|
||||
@@ -312,8 +312,6 @@ 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());
|
||||
if (!value.ok()) {
|
||||
dbgTrace(D_NGINX_ATTACHMENT_PARSER) << "Could not extract source identifier from X-Forwarded-For header";
|
||||
@@ -325,6 +323,10 @@ UsersAllIdentifiersConfig::setXFFValuesToOpaqueCtx(const HttpHeader &header, Ext
|
||||
dbgDebug(D_NGINX_ATTACHMENT_PARSER)
|
||||
<< "Added source identifir to XFF "
|
||||
<< value.unpack();
|
||||
opaque.setSavedData(HttpTransactionData::xff_vals_ctx, header.getValue());
|
||||
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());
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ private:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
dbgAssert(false) << "Unsupported IP type";
|
||||
dbgAssert(false) << AlertInfo(AlertTeam::CORE, "gradual deployment") << "Unsupported IP type";
|
||||
}
|
||||
return address;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -66,6 +66,8 @@ public:
|
||||
|
||||
virtual std::map<std::string, std::vector<PortNumber>> getServiceToPortMap() = 0;
|
||||
|
||||
virtual bool getServicesPolicyStatus() const = 0;
|
||||
|
||||
protected:
|
||||
virtual ~I_ServiceController() {}
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
// 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 __REPORT_MESSAGING_H__
|
||||
#define __REPORT_MESSAGING_H__
|
||||
|
||||
#include "singleton.h"
|
||||
#include "i_time_get.h"
|
||||
#include "i_messaging.h"
|
||||
#include "report/report.h"
|
||||
|
||||
class ReportMessaging
|
||||
:
|
||||
Singleton::Consume<I_Messaging>,
|
||||
Singleton::Consume<I_TimeGet>
|
||||
{
|
||||
public:
|
||||
template <typename ...Args, typename T>
|
||||
ReportMessaging(
|
||||
const std::string &title,
|
||||
const ReportIS::AudienceTeam &audience_team,
|
||||
const T &obj,
|
||||
Args ...args)
|
||||
:
|
||||
ReportMessaging(
|
||||
title,
|
||||
audience_team,
|
||||
obj,
|
||||
MessageCategory::GENERIC,
|
||||
std::forward<Args>(args)...
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename ...Args, typename T>
|
||||
ReportMessaging(
|
||||
const std::string &title,
|
||||
const ReportIS::AudienceTeam &audience_team,
|
||||
const T &obj,
|
||||
const MessageCategory &message_type,
|
||||
Args ...args)
|
||||
:
|
||||
ReportMessaging(
|
||||
title,
|
||||
audience_team,
|
||||
ReportIS::Severity::INFO,
|
||||
ReportIS::Priority::LOW,
|
||||
obj,
|
||||
message_type,
|
||||
std::forward<Args>(args)...
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename ...Args, typename T>
|
||||
ReportMessaging(
|
||||
const std::string &title,
|
||||
const ReportIS::AudienceTeam &audience_team,
|
||||
const ReportIS::Severity &severity,
|
||||
const ReportIS::Priority &priority,
|
||||
const T &obj,
|
||||
Args ...args)
|
||||
:
|
||||
ReportMessaging(
|
||||
title,
|
||||
audience_team,
|
||||
severity,
|
||||
priority,
|
||||
obj,
|
||||
MessageCategory::GENERIC,
|
||||
std::forward<Args>(args)...
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template <typename ...Args, typename T>
|
||||
ReportMessaging(
|
||||
const std::string &title,
|
||||
const ReportIS::AudienceTeam &audience_team,
|
||||
const ReportIS::Severity &severity,
|
||||
const ReportIS::Priority &priority,
|
||||
const T &obj,
|
||||
const MessageCategory &message_type,
|
||||
Args ...args)
|
||||
:
|
||||
report(
|
||||
title,
|
||||
Singleton::Consume<I_TimeGet>::by<ReportMessaging>()->getWalltime(),
|
||||
ReportIS::Type::EVENT,
|
||||
ReportIS::Level::LOG,
|
||||
ReportIS::LogLevel::INFO,
|
||||
ReportIS::Audience::INTERNAL,
|
||||
audience_team,
|
||||
severity,
|
||||
priority,
|
||||
std::chrono::seconds(0),
|
||||
std::forward<Args>(args)...
|
||||
),
|
||||
message_type_tag(message_type)
|
||||
{
|
||||
report << LogField("eventObject", obj);
|
||||
}
|
||||
|
||||
~ReportMessaging();
|
||||
|
||||
ReportMessaging & operator<<(const LogField &field);
|
||||
|
||||
Maybe<void, HTTPResponse> sendReportSynchronously();
|
||||
|
||||
void setForceBuffering(bool _force_buffering);
|
||||
|
||||
private:
|
||||
Report report;
|
||||
bool is_async_message = true;
|
||||
bool force_buffering = false;
|
||||
MessageCategory message_type_tag;
|
||||
};
|
||||
|
||||
#endif // __REPORT_MESSAGING_H__
|
||||
@@ -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/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 =
|
||||
|
||||
39
components/include/service_health_status.h
Normal file
39
components/include/service_health_status.h
Normal 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__
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
add_library(report_messaging report_messaging.cc)
|
||||
|
||||
add_subdirectory(report_messaging_ut)
|
||||
@@ -1,74 +0,0 @@
|
||||
// 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 "report_messaging.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "report/log_rest.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const string url = "/api/v1/agents/events";
|
||||
|
||||
ReportMessaging::~ReportMessaging()
|
||||
{
|
||||
if (!Singleton::exists<I_Messaging>()) return;
|
||||
if (!is_async_message) return;
|
||||
|
||||
LogRest log_rest(report);
|
||||
|
||||
auto messaging = Singleton::Consume<I_Messaging>::by<ReportMessaging>();
|
||||
try {
|
||||
messaging->sendAsyncMessage(
|
||||
HTTPMethod::POST,
|
||||
url,
|
||||
log_rest,
|
||||
message_type_tag,
|
||||
MessageMetadata(),
|
||||
force_buffering
|
||||
);
|
||||
} catch (...) {}
|
||||
}
|
||||
|
||||
ReportMessaging &
|
||||
ReportMessaging::operator<<(const LogField &field)
|
||||
{
|
||||
report << field;
|
||||
return *this;
|
||||
}
|
||||
|
||||
class LogRestWithReply : public LogRest
|
||||
{
|
||||
public:
|
||||
LogRestWithReply(const Report &report) : LogRest(report) {}
|
||||
|
||||
bool loadJson(const string &) const { return true; }
|
||||
};
|
||||
|
||||
Maybe<void, HTTPResponse>
|
||||
ReportMessaging::sendReportSynchronously()
|
||||
{
|
||||
is_async_message = false;
|
||||
|
||||
LogRestWithReply log_rest(report);
|
||||
|
||||
auto messaging = Singleton::Consume<I_Messaging>::by<ReportMessaging>();
|
||||
return messaging->sendSyncMessage(HTTPMethod::POST, url, log_rest, message_type_tag);
|
||||
}
|
||||
|
||||
void
|
||||
ReportMessaging::setForceBuffering(bool _force_buffering)
|
||||
{
|
||||
force_buffering = _force_buffering;
|
||||
}
|
||||
@@ -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")
|
||||
@@ -1,412 +0,0 @@
|
||||
#include "report_messaging.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "config.h"
|
||||
#include "config_component.h"
|
||||
#include "cptest.h"
|
||||
#include "mock/mock_messaging.h"
|
||||
#include "mock/mock_time_get.h"
|
||||
#include "mock/mock_environment.h"
|
||||
#include "cereal/archives/json.hpp"
|
||||
#include "cereal/types/string.hpp"
|
||||
#include "cereal/types/common.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace testing;
|
||||
|
||||
class ReportObject
|
||||
{
|
||||
public:
|
||||
ReportObject(int _integer_val, string _string_val, vector<int> _vec_val)
|
||||
:
|
||||
integer_val(_integer_val),
|
||||
string_val(_string_val),
|
||||
vec_val(_vec_val)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
serialize(cereal::JSONOutputArchive &ar) const
|
||||
{
|
||||
ar(cereal::make_nvp("integerVal", integer_val));
|
||||
ar(cereal::make_nvp("stringVal", string_val));
|
||||
ar(cereal::make_nvp("vecVal", vec_val));
|
||||
}
|
||||
|
||||
friend ostream &
|
||||
operator<<(ostream &os, const ReportObject &)
|
||||
{
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
int integer_val;
|
||||
string string_val;
|
||||
vector<int> vec_val;
|
||||
};
|
||||
|
||||
class ReportMessagingTest : public Test
|
||||
{
|
||||
public:
|
||||
ReportMessagingTest()
|
||||
{
|
||||
EXPECT_CALL(mock_time_get, getWalltime()).WillRepeatedly(Return(chrono::microseconds(0)));
|
||||
EXPECT_CALL(mock_time_get, getWalltimeStr(_)).WillRepeatedly(Return("Best Time ever"));
|
||||
}
|
||||
|
||||
StrictMock<MockMessaging> mock_messaging;
|
||||
StrictMock<MockTimeGet> mock_time_get;
|
||||
|
||||
private:
|
||||
ConfigComponent config;
|
||||
};
|
||||
|
||||
TEST_F(ReportMessagingTest, title_only)
|
||||
{
|
||||
EXPECT_CALL(
|
||||
mock_messaging,
|
||||
sendAsyncMessage(
|
||||
_,
|
||||
_,
|
||||
"{\n"
|
||||
" \"log\": {\n"
|
||||
" \"eventTime\": \"Best Time ever\",\n"
|
||||
" \"eventName\": \"test\",\n"
|
||||
" \"eventSeverity\": \"Info\",\n"
|
||||
" \"eventPriority\": \"Low\",\n"
|
||||
" \"eventType\": \"Event Driven\",\n"
|
||||
" \"eventLevel\": \"Log\",\n"
|
||||
" \"eventLogLevel\": \"info\",\n"
|
||||
" \"eventAudience\": \"Internal\",\n"
|
||||
" \"eventAudienceTeam\": \"Agent Core\",\n"
|
||||
" \"eventFrequency\": 0,\n"
|
||||
" \"eventTags\": [\n"
|
||||
" \"Access Control\"\n"
|
||||
" ],\n"
|
||||
" \"eventSource\": {\n"
|
||||
" \"eventTraceId\": \"\",\n"
|
||||
" \"eventSpanId\": \"\",\n"
|
||||
" \"issuingEngineVersion\": \"\",\n"
|
||||
" \"serviceName\": \"Unnamed Nano Service\"\n"
|
||||
" },\n"
|
||||
" \"eventData\": {\n"
|
||||
" \"eventObject\": 1\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}",
|
||||
_,
|
||||
_,
|
||||
_
|
||||
)
|
||||
).Times(1);
|
||||
ReportMessaging("test", ReportIS::AudienceTeam::AGENT_CORE, 1, ReportIS::Tags::ACCESS_CONTROL);
|
||||
}
|
||||
|
||||
TEST_F(ReportMessagingTest, sync_sending)
|
||||
{
|
||||
EXPECT_CALL(
|
||||
mock_messaging,
|
||||
sendSyncMessage(
|
||||
_,
|
||||
_,
|
||||
"{\n"
|
||||
" \"log\": {\n"
|
||||
" \"eventTime\": \"Best Time ever\",\n"
|
||||
" \"eventName\": \"test\",\n"
|
||||
" \"eventSeverity\": \"Info\",\n"
|
||||
" \"eventPriority\": \"Low\",\n"
|
||||
" \"eventType\": \"Event Driven\",\n"
|
||||
" \"eventLevel\": \"Log\",\n"
|
||||
" \"eventLogLevel\": \"info\",\n"
|
||||
" \"eventAudience\": \"Internal\",\n"
|
||||
" \"eventAudienceTeam\": \"Agent Core\",\n"
|
||||
" \"eventFrequency\": 0,\n"
|
||||
" \"eventTags\": [\n"
|
||||
" \"Access Control\"\n"
|
||||
" ],\n"
|
||||
" \"eventSource\": {\n"
|
||||
" \"eventTraceId\": \"\",\n"
|
||||
" \"eventSpanId\": \"\",\n"
|
||||
" \"issuingEngineVersion\": \"\",\n"
|
||||
" \"serviceName\": \"Unnamed Nano Service\"\n"
|
||||
" },\n"
|
||||
" \"eventData\": {\n"
|
||||
" \"eventObject\": 1\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}",
|
||||
_,
|
||||
_
|
||||
)
|
||||
).WillOnce(Return(HTTPResponse(HTTPStatusCode::HTTP_OK, "response!!")));
|
||||
ReportMessaging report("test", ReportIS::AudienceTeam::AGENT_CORE, 1, ReportIS::Tags::ACCESS_CONTROL);
|
||||
EXPECT_TRUE(report.sendReportSynchronously().ok());
|
||||
}
|
||||
|
||||
TEST_F(ReportMessagingTest, with_buffering)
|
||||
{
|
||||
EXPECT_CALL(
|
||||
mock_messaging,
|
||||
sendAsyncMessage(
|
||||
_,
|
||||
_,
|
||||
"{\n"
|
||||
" \"log\": {\n"
|
||||
" \"eventTime\": \"Best Time ever\",\n"
|
||||
" \"eventName\": \"test\",\n"
|
||||
" \"eventSeverity\": \"Info\",\n"
|
||||
" \"eventPriority\": \"Low\",\n"
|
||||
" \"eventType\": \"Event Driven\",\n"
|
||||
" \"eventLevel\": \"Log\",\n"
|
||||
" \"eventLogLevel\": \"info\",\n"
|
||||
" \"eventAudience\": \"Internal\",\n"
|
||||
" \"eventAudienceTeam\": \"Agent Core\",\n"
|
||||
" \"eventFrequency\": 0,\n"
|
||||
" \"eventTags\": [\n"
|
||||
" \"Access Control\"\n"
|
||||
" ],\n"
|
||||
" \"eventSource\": {\n"
|
||||
" \"eventTraceId\": \"\",\n"
|
||||
" \"eventSpanId\": \"\",\n"
|
||||
" \"issuingEngineVersion\": \"\",\n"
|
||||
" \"serviceName\": \"Unnamed Nano Service\"\n"
|
||||
" },\n"
|
||||
" \"eventData\": {\n"
|
||||
" \"eventObject\": 1\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}",
|
||||
_,
|
||||
_,
|
||||
true
|
||||
)
|
||||
).Times(1);
|
||||
ReportMessaging report("test", ReportIS::AudienceTeam::AGENT_CORE, 1, ReportIS::Tags::ACCESS_CONTROL);
|
||||
report.setForceBuffering(true);
|
||||
}
|
||||
|
||||
TEST_F(ReportMessagingTest, with_dynamic_fields)
|
||||
{
|
||||
EXPECT_CALL(
|
||||
mock_messaging,
|
||||
sendAsyncMessage(
|
||||
_,
|
||||
_,
|
||||
"{\n"
|
||||
" \"log\": {\n"
|
||||
" \"eventTime\": \"Best Time ever\",\n"
|
||||
" \"eventName\": \"test\",\n"
|
||||
" \"eventSeverity\": \"Info\",\n"
|
||||
" \"eventPriority\": \"Low\",\n"
|
||||
" \"eventType\": \"Event Driven\",\n"
|
||||
" \"eventLevel\": \"Log\",\n"
|
||||
" \"eventLogLevel\": \"info\",\n"
|
||||
" \"eventAudience\": \"Internal\",\n"
|
||||
" \"eventAudienceTeam\": \"Agent Core\",\n"
|
||||
" \"eventFrequency\": 0,\n"
|
||||
" \"eventTags\": [\n"
|
||||
" \"Access Control\"\n"
|
||||
" ],\n"
|
||||
" \"eventSource\": {\n"
|
||||
" \"eventTraceId\": \"\",\n"
|
||||
" \"eventSpanId\": \"\",\n"
|
||||
" \"issuingEngineVersion\": \"\",\n"
|
||||
" \"serviceName\": \"Unnamed Nano Service\"\n"
|
||||
" },\n"
|
||||
" \"eventData\": {\n"
|
||||
" \"eventObject\": 1,\n"
|
||||
" \"ASD\": \"QWE\"\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}",
|
||||
_,
|
||||
_,
|
||||
_
|
||||
)
|
||||
).Times(1);
|
||||
ReportMessaging("test", ReportIS::AudienceTeam::AGENT_CORE, 1, ReportIS::Tags::ACCESS_CONTROL)
|
||||
<< LogField("ASD", "QWE");
|
||||
}
|
||||
|
||||
TEST_F(ReportMessagingTest, custom_event_object)
|
||||
{
|
||||
EXPECT_CALL(
|
||||
mock_messaging,
|
||||
sendAsyncMessage(
|
||||
_,
|
||||
_,
|
||||
"{\n"
|
||||
" \"log\": {\n"
|
||||
" \"eventTime\": \"Best Time ever\",\n"
|
||||
" \"eventName\": \"test\",\n"
|
||||
" \"eventSeverity\": \"Info\",\n"
|
||||
" \"eventPriority\": \"Low\",\n"
|
||||
" \"eventType\": \"Event Driven\",\n"
|
||||
" \"eventLevel\": \"Log\",\n"
|
||||
" \"eventLogLevel\": \"info\",\n"
|
||||
" \"eventAudience\": \"Internal\",\n"
|
||||
" \"eventAudienceTeam\": \"Agent Core\",\n"
|
||||
" \"eventFrequency\": 0,\n"
|
||||
" \"eventTags\": [\n"
|
||||
" \"Access Control\"\n"
|
||||
" ],\n"
|
||||
" \"eventSource\": {\n"
|
||||
" \"eventTraceId\": \"\",\n"
|
||||
" \"eventSpanId\": \"\",\n"
|
||||
" \"issuingEngineVersion\": \"\",\n"
|
||||
" \"serviceName\": \"Unnamed Nano Service\"\n"
|
||||
" },\n"
|
||||
" \"eventData\": {\n"
|
||||
" \"eventObject\": {\n"
|
||||
" \"integerVal\": 1,\n"
|
||||
" \"stringVal\": \"2\",\n"
|
||||
" \"vecVal\": [\n"
|
||||
" 1,\n"
|
||||
" 2,\n"
|
||||
" 3\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}",
|
||||
_,
|
||||
_,
|
||||
_
|
||||
)
|
||||
).Times(1);
|
||||
|
||||
ReportMessaging(
|
||||
"test",
|
||||
ReportIS::AudienceTeam::AGENT_CORE,
|
||||
ReportObject(1, "2", { 1, 2, 3}),
|
||||
ReportIS::Tags::ACCESS_CONTROL
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(ReportMessagingTest, custom_priority)
|
||||
{
|
||||
EXPECT_CALL(
|
||||
mock_messaging,
|
||||
sendAsyncMessage(
|
||||
_,
|
||||
_,
|
||||
"{\n"
|
||||
" \"log\": {\n"
|
||||
" \"eventTime\": \"Best Time ever\",\n"
|
||||
" \"eventName\": \"test\",\n"
|
||||
" \"eventSeverity\": \"High\",\n"
|
||||
" \"eventPriority\": \"Medium\",\n"
|
||||
" \"eventType\": \"Event Driven\",\n"
|
||||
" \"eventLevel\": \"Log\",\n"
|
||||
" \"eventLogLevel\": \"info\",\n"
|
||||
" \"eventAudience\": \"Internal\",\n"
|
||||
" \"eventAudienceTeam\": \"Agent Core\",\n"
|
||||
" \"eventFrequency\": 0,\n"
|
||||
" \"eventTags\": [\n"
|
||||
" \"Access Control\"\n"
|
||||
" ],\n"
|
||||
" \"eventSource\": {\n"
|
||||
" \"eventTraceId\": \"\",\n"
|
||||
" \"eventSpanId\": \"\",\n"
|
||||
" \"issuingEngineVersion\": \"\",\n"
|
||||
" \"serviceName\": \"Unnamed Nano Service\"\n"
|
||||
" },\n"
|
||||
" \"eventData\": {\n"
|
||||
" \"eventObject\": {\n"
|
||||
" \"integerVal\": 1,\n"
|
||||
" \"stringVal\": \"2\",\n"
|
||||
" \"vecVal\": [\n"
|
||||
" 1,\n"
|
||||
" 2,\n"
|
||||
" 3\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}",
|
||||
_,
|
||||
_,
|
||||
_
|
||||
)
|
||||
).Times(1);
|
||||
|
||||
ReportMessaging(
|
||||
"test",
|
||||
ReportIS::AudienceTeam::AGENT_CORE,
|
||||
ReportIS::Severity::HIGH,
|
||||
ReportIS::Priority::MEDIUM,
|
||||
ReportObject(1, "2", {1, 2, 3}),
|
||||
ReportIS::Tags::ACCESS_CONTROL
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(ReportMessagingTest, with_env_details)
|
||||
{
|
||||
StrictMock<MockEnvironment> mock_env;
|
||||
|
||||
Context context;
|
||||
context.registerValue<string>("Service Name", "Access Control App");
|
||||
context.registerValue<string>("Service Version", "1.2.3.0.0");
|
||||
I_Environment::ActiveContexts active_context({&context}, true);
|
||||
EXPECT_CALL(mock_env, getActiveContexts()).WillRepeatedly(ReturnRef(active_context));
|
||||
EXPECT_CALL(mock_env, getCurrentTrace()).WillOnce(Return(string("best trace")));
|
||||
EXPECT_CALL(mock_env, getCurrentSpan()).WillOnce(Return(string("best span")));
|
||||
|
||||
EXPECT_CALL(
|
||||
mock_messaging,
|
||||
sendAsyncMessage(
|
||||
_,
|
||||
_,
|
||||
"{\n"
|
||||
" \"log\": {\n"
|
||||
" \"eventTime\": \"Best Time ever\",\n"
|
||||
" \"eventName\": \"test\",\n"
|
||||
" \"eventSeverity\": \"High\",\n"
|
||||
" \"eventPriority\": \"Medium\",\n"
|
||||
" \"eventType\": \"Event Driven\",\n"
|
||||
" \"eventLevel\": \"Log\",\n"
|
||||
" \"eventLogLevel\": \"info\",\n"
|
||||
" \"eventAudience\": \"Internal\",\n"
|
||||
" \"eventAudienceTeam\": \"Agent Core\",\n"
|
||||
" \"eventFrequency\": 0,\n"
|
||||
" \"eventTags\": [\n"
|
||||
" \"Access Control\"\n"
|
||||
" ],\n"
|
||||
" \"eventSource\": {\n"
|
||||
" \"eventTraceId\": \"best trace\",\n"
|
||||
" \"eventSpanId\": \"best span\",\n"
|
||||
" \"issuingEngineVersion\": \"1.2.3.0.0\",\n"
|
||||
" \"serviceName\": \"Access Control App\"\n"
|
||||
" },\n"
|
||||
" \"eventData\": {\n"
|
||||
" \"eventObject\": {\n"
|
||||
" \"integerVal\": 1,\n"
|
||||
" \"stringVal\": \"2\",\n"
|
||||
" \"vecVal\": [\n"
|
||||
" 1,\n"
|
||||
" 2,\n"
|
||||
" 3\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}",
|
||||
_,
|
||||
_,
|
||||
_
|
||||
)
|
||||
).Times(1);
|
||||
|
||||
ReportMessaging(
|
||||
"test",
|
||||
ReportIS::AudienceTeam::AGENT_CORE,
|
||||
ReportIS::Severity::HIGH,
|
||||
ReportIS::Priority::MEDIUM,
|
||||
ReportObject(1, "2", {1, 2, 3}),
|
||||
ReportIS::Tags::ACCESS_CONTROL
|
||||
);
|
||||
}
|
||||
@@ -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(); });
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -428,7 +434,6 @@ 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"),
|
||||
@@ -438,6 +443,9 @@ WebAppSection::WebAppSection(
|
||||
trusted_sources({ parsed_trusted_sources })
|
||||
{
|
||||
web_attack_mitigation = web_attack_mitigation_mode != "Disabled";
|
||||
web_attack_mitigation_severity =
|
||||
web_attack_mitigation_mode != "Prevent" ? "Transparent" :
|
||||
parsed_appsec_spec.getWebAttacks().getMinimumConfidence();
|
||||
web_attack_mitigation_action =
|
||||
web_attack_mitigation_mode != "Prevent" ? "Transparent" :
|
||||
web_attack_mitigation_severity == "critical" ? "low" :
|
||||
@@ -470,6 +478,7 @@ WebAppSection::WebAppSection(
|
||||
const string &_context,
|
||||
const string &_web_attack_mitigation_severity,
|
||||
const string &_web_attack_mitigation_mode,
|
||||
const string &_bot_protection,
|
||||
const PracticeAdvancedConfig &_practice_advanced_config,
|
||||
const AppsecPracticeAntiBotSection &_anti_bots,
|
||||
const LogTriggerSection &parsed_log_trigger,
|
||||
@@ -486,6 +495,7 @@ WebAppSection::WebAppSection(
|
||||
context(_context),
|
||||
web_attack_mitigation_severity(_web_attack_mitigation_severity),
|
||||
web_attack_mitigation_mode(_web_attack_mitigation_mode),
|
||||
bot_protection(_bot_protection),
|
||||
practice_advanced_config(_practice_advanced_config),
|
||||
anti_bots(_anti_bots),
|
||||
trusted_sources({ parsed_trusted_sources })
|
||||
@@ -514,7 +524,6 @@ 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),
|
||||
@@ -542,7 +551,7 @@ WebAppSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
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("botProtection_v2", bot_protection != "" ? bot_protection : string("Detect"))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -290,6 +290,7 @@ 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 PracticeAdvancedConfig &_practice_advanced_config,
|
||||
const AppsecPracticeAntiBotSection &_anti_bots,
|
||||
const LogTriggerSection &parsed_log_trigger,
|
||||
@@ -315,6 +316,7 @@ private:
|
||||
std::string csrf_protection_mode;
|
||||
std::string open_redirect_mode;
|
||||
std::string error_disclosure_mode;
|
||||
std::string bot_protection;
|
||||
bool web_attack_mitigation;
|
||||
std::vector<TriggersInWaapSection> triggers;
|
||||
PracticeAdvancedConfig practice_advanced_config;
|
||||
|
||||
@@ -508,30 +508,20 @@ private:
|
||||
bool is_temporary;
|
||||
};
|
||||
|
||||
class NewAppSecWebBotsURI
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const std::string & getURI() const;
|
||||
|
||||
private:
|
||||
std::string uri;
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -50,6 +50,13 @@ static const std::unordered_map<std::string, std::string> key_to_mode_val = {
|
||||
{ "detect", "Detect"},
|
||||
{ "inactive", "Inactive"}
|
||||
};
|
||||
static const std::unordered_map<std::string, std::string> anti_bot_key_to_mode_val = {
|
||||
{ "prevent-learn", "Prevent"},
|
||||
{ "detect-learn", "Detect"},
|
||||
{ "prevent", "Prevent"},
|
||||
{ "detect", "Detect"},
|
||||
{ "inactive", "Disabled"}
|
||||
};
|
||||
static const std::unordered_map<std::string, uint64_t> unit_to_int = {
|
||||
{ "bytes", 1},
|
||||
{ "KB", 1024},
|
||||
@@ -81,57 +88,44 @@ getModeWithDefault(
|
||||
return key_to_val.at(mode);
|
||||
}
|
||||
|
||||
void
|
||||
NewAppSecWebBotsURI::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec Web Bots URI";
|
||||
parseAppsecJSONKey<string>("uri", uri, archive_in);
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppSecWebBotsURI::getURI() const
|
||||
{
|
||||
return uri;
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
const std::vector<std::string> &
|
||||
NewAppSecPracticeAntiBot::getIjectedUris() const
|
||||
{
|
||||
vector<string> injected;
|
||||
for (const NewAppSecWebBotsURI &uri : injected_uris) injected.push_back(uri.getURI());
|
||||
return injected;
|
||||
return injected_uris;
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
const std::vector<std::string> &
|
||||
NewAppSecPracticeAntiBot::getValidatedUris() const
|
||||
{
|
||||
vector<string> validated;
|
||||
for (const NewAppSecWebBotsURI &uri : validated_uris) validated.push_back(uri.getURI());
|
||||
return validated;
|
||||
return validated_uris;
|
||||
}
|
||||
|
||||
const std::string &
|
||||
NewAppSecPracticeAntiBot::getMode() const
|
||||
{
|
||||
return override_mode;
|
||||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
string mode;
|
||||
parseAppsecJSONKey<vector<string>>("injectedUris", injected_uris, archive_in);
|
||||
parseAppsecJSONKey<vector<string>>("validatedUris", validated_uris, archive_in);
|
||||
parseMandatoryAppsecJSONKey<string>("overrideMode", mode, archive_in, "inactive");
|
||||
if (valid_modes.count(mode) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec Web Bots override mode invalid: " << mode;
|
||||
}
|
||||
override_mode = anti_bot_key_to_mode_val.at(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)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -555,7 +555,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();
|
||||
@@ -582,7 +582,7 @@ extractLogTriggerData(const string &trigger_annotation_name, const T &trigger_sp
|
||||
logToAgent,
|
||||
logToCef,
|
||||
logToCloud,
|
||||
logToContainerService,
|
||||
logTolocalTuning,
|
||||
logToSyslog,
|
||||
responseBody,
|
||||
tpDetect,
|
||||
@@ -1236,6 +1236,7 @@ PolicyMakerUtils::createWebAppSection(
|
||||
rule_config.getContext(),
|
||||
apssec_practice.getWebAttacks().getMinimumConfidence(practice_mode),
|
||||
apssec_practice.getWebAttacks().getMode(practice_mode),
|
||||
apssec_practice.getAntiBot().getMode(),
|
||||
practice_advance_config,
|
||||
apssec_practice.getAntiBot(),
|
||||
log_triggers[rule_annotations[AnnotationTypes::TRIGGER]],
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -60,20 +60,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>
|
||||
@@ -191,26 +187,44 @@ getMgmtObjAttr(shared_ptr<istream> file_stream, const string &attr)
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getMgmtObjUid(shared_ptr<istream> file_stream)
|
||||
getMgmtObjUid(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, "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>
|
||||
|
||||
@@ -42,13 +42,29 @@ 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("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 || echo ''",
|
||||
getQUID)
|
||||
@@ -102,8 +118,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 +139,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",
|
||||
@@ -219,6 +240,7 @@ SHELL_CMD_HANDLER(
|
||||
|
||||
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 +249,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 +261,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
|
||||
|
||||
@@ -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>()) {}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ public:
|
||||
|
||||
MOCK_CONST_METHOD0(getPolicyVersions, const std::string &());
|
||||
|
||||
MOCK_CONST_METHOD0(getServicesPolicyStatus, bool());
|
||||
|
||||
MOCK_METHOD6(
|
||||
updateServiceConfiguration,
|
||||
Maybe<void>(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1631,6 +1631,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 +1653,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 +1697,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 +1718,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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
UpdatesConfigType::GENERAL,
|
||||
UpdatesFailureReason::SERVISE_CONFIGURATION,
|
||||
string(service_name.get() + ", ID: " + to_string(id.get())),
|
||||
(error_message.isActive() ? " Error: " + error_message.get() : "")
|
||||
(error_message.isActive() ? " " + error_message.get() : "")
|
||||
).notify();
|
||||
dbgError(D_SERVICE_CONTROLLER)
|
||||
<< "Request for service reconfiguration failed to complete. ID: "
|
||||
@@ -327,6 +327,8 @@ public:
|
||||
|
||||
set<string> && moveChangedPolicies() override;
|
||||
|
||||
bool getServicesPolicyStatus() const override;
|
||||
|
||||
private:
|
||||
void cleanUpVirtualFiles();
|
||||
|
||||
@@ -365,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;
|
||||
|
||||
@@ -459,6 +462,12 @@ ServiceController::Impl::moveChangedPolicies()
|
||||
return move(changed_policy_files);
|
||||
}
|
||||
|
||||
bool
|
||||
ServiceController::Impl::getServicesPolicyStatus() const
|
||||
{
|
||||
return total_services_status;
|
||||
}
|
||||
|
||||
void
|
||||
ServiceController::Impl::init()
|
||||
{
|
||||
@@ -960,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()) {
|
||||
@@ -1002,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: {
|
||||
|
||||
@@ -790,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)
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "debug.h"
|
||||
#include "log_generator.h"
|
||||
#include "service_health_update_event.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -34,6 +35,7 @@ UpdatesProcessReporter::upon(const UpdatesProcessEvent &event)
|
||||
if (event.getResult() == UpdatesProcessResult::SUCCESS && reports.empty()) {
|
||||
dbgTrace(D_UPDATES_PROCESS_REPORTER) << "Update proccess finished successfully";
|
||||
report_failure_count_map.erase(version);
|
||||
ServiceHealthUpdateEvent().notify();
|
||||
return;
|
||||
}
|
||||
if (report_failure_count_map.find(version) == report_failure_count_map.end()) {
|
||||
@@ -62,6 +64,7 @@ UpdatesProcessReporter::upon(const UpdatesProcessEvent &event)
|
||||
reports.emplace_back(
|
||||
UpdatesProcessReport(event.getResult(), event.getType(), event.getReason(), event.parseDescription())
|
||||
);
|
||||
ServiceHealthUpdateEvent(convertUpdatesConfigTypeToStr(event.getType()), event.parseDescription()).notify();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -390,6 +390,38 @@ 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,
|
||||
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
|
||||
@@ -1183,6 +1215,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;
|
||||
@@ -1279,7 +1312,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()
|
||||
@@ -1305,7 +1338,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()
|
||||
|
||||
@@ -103,6 +103,9 @@ ParserUrlEncode::push(const char *buf, size_t len)
|
||||
}
|
||||
case s_key_start: {
|
||||
dbgTrace(D_WAAP_PARSER_URLENCODE) << "ParserUrlEncode::push(): s_key_start";
|
||||
if (isspace(c)){
|
||||
break;
|
||||
}
|
||||
mark = i;
|
||||
m_state = s_key;
|
||||
|
||||
@@ -112,12 +115,6 @@ ParserUrlEncode::push(const char *buf, size_t len)
|
||||
case s_key: {
|
||||
dbgTrace(D_WAAP_PARSER_URLENCODE) << "ParserUrlEncode::push(): s_key";
|
||||
|
||||
// skip leading spaces in the key
|
||||
if (isspace(c)) {
|
||||
m_state = s_key_start; // skip the space character without including it in the output
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == '%' && should_decode_percent) {
|
||||
if (i - mark > 0) {
|
||||
if (m_receiver.onKey(buf + mark, i - mark) != 0) {
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
|
||||
if (m_tag != "sourceip" && m_tag != "sourceidentifier" && m_tag != "url" && m_tag != "hostname" &&
|
||||
m_tag != "keyword" && m_tag != "paramname" && m_tag != "paramvalue" && m_tag != "paramlocation" &&
|
||||
m_tag != "responsebody" && m_tag != "headername" && m_tag != "headervalue" ) {
|
||||
m_tag != "responsebody" && m_tag != "headername" && m_tag != "headervalue" && m_tag != "method") {
|
||||
m_isValid = false;
|
||||
dbgDebug(D_WAAP_OVERRIDE) << "Invalid override tag: " << m_tag;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,10 @@ bool WaapOverrideFunctor::operator()(const std::string& tag, const boost::regex&
|
||||
std::string tagLower = tag;
|
||||
std::transform(tagLower.begin(), tagLower.end(), tagLower.begin(), ::tolower);
|
||||
try {
|
||||
if (tagLower == "url") {
|
||||
if (tagLower == "method") {
|
||||
return NGEN::Regex::regexMatch(__FILE__, __LINE__, waf2Transaction.getMethod().c_str(), what, rx);
|
||||
}
|
||||
else if (tagLower == "url") {
|
||||
return NGEN::Regex::regexMatch(__FILE__, __LINE__, waf2Transaction.getUriStr().c_str(), what, rx);
|
||||
}
|
||||
else if (tagLower == "hostname") {
|
||||
|
||||
@@ -95,7 +95,9 @@ ValueStatsAnalyzer::ValueStatsAnalyzer(const std::string &cur_val)
|
||||
canSplitPipe(true),
|
||||
hasSpace(false),
|
||||
isUrlEncoded(false),
|
||||
hasCharLess(false)
|
||||
hasCharLess(false),
|
||||
hasDoubleQuote(false),
|
||||
hasPercent(false)
|
||||
{
|
||||
unsigned int zerosSeq[2] = {0};
|
||||
bool lastNul = false; // whether last processed character was ASCII NUL
|
||||
@@ -146,6 +148,9 @@ ValueStatsAnalyzer::ValueStatsAnalyzer(const std::string &cur_val)
|
||||
case '\"':
|
||||
hasDoubleQuote = true;
|
||||
break;
|
||||
case '%':
|
||||
hasPercent = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (isspace(ch)) {
|
||||
@@ -270,4 +275,6 @@ ValueStatsAnalyzer::ValueStatsAnalyzer(const std::string &cur_val)
|
||||
textual +=(hasCharLess ? "true" : "false");
|
||||
textual.append("\nhasDoubleQuote = ");
|
||||
textual +=(hasDoubleQuote ? "true" : "false");
|
||||
textual.append("\nhasPercent = ");
|
||||
textual +=(hasPercent ? "true" : "false");
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ struct ValueStatsAnalyzer
|
||||
bool isUrlEncoded;
|
||||
bool hasCharLess;
|
||||
bool hasDoubleQuote;
|
||||
bool hasPercent;
|
||||
std::string textual;
|
||||
};
|
||||
|
||||
|
||||
@@ -867,7 +867,7 @@ void Waf2Transaction::parseCookie(const char* value, int value_len)
|
||||
if (value_len > 0) {
|
||||
dbgTrace(D_WAAP_HEADERS) << "[transaction:" << this << "] scanning the cookie value";
|
||||
m_deepParser.m_key.push("cookie", 6);
|
||||
ParserUrlEncode cookieValueParser(m_deepParserReceiver, 0, ';');
|
||||
ParserUrlEncode cookieValueParser(m_deepParserReceiver, 0, ';', false);
|
||||
cookieValueParser.push(value, value_len);
|
||||
cookieValueParser.finish();
|
||||
m_deepParser.m_key.pop("cookie");
|
||||
@@ -1077,6 +1077,9 @@ void Waf2Transaction::add_request_hdr(const char* name, int name_len, const char
|
||||
std::string header_name(name, name_len);
|
||||
boost::algorithm::to_lower(header_name);
|
||||
hdrs_map[header_name] = std::string(value, value_len);
|
||||
if (header_name == "host") {
|
||||
m_hostStr = hdrs_map[header_name];
|
||||
}
|
||||
}
|
||||
|
||||
void Waf2Transaction::end_request_hdrs() {
|
||||
|
||||
@@ -117,7 +117,7 @@ WaapComponent::Impl::fini()
|
||||
std::string
|
||||
WaapComponent::Impl::getListenerName() const
|
||||
{
|
||||
return "waap application";
|
||||
return WAAP_APPLICATION_NAME;
|
||||
}
|
||||
|
||||
// Start request (called before headers arrive). However, the method and URL path is known at this stage.
|
||||
|
||||
@@ -4,3 +4,4 @@ add_subdirectory(http_transaction_data)
|
||||
add_subdirectory(ip_utilities)
|
||||
add_subdirectory(keywords)
|
||||
add_subdirectory(pm)
|
||||
add_subdirectory(service_health_status)
|
||||
|
||||
@@ -173,7 +173,7 @@ LogTriggerConf::load(cereal::JSONInputArchive& archive_in)
|
||||
setTriggersFlag("webUrlQuery", archive_in, WebLogFields::webUrlQuery, log_web_fields);
|
||||
setTriggersFlag("logToAgent", archive_in, ReportIS::StreamType::JSON_LOG_FILE, active_streams);
|
||||
setTriggersFlag("logToCloud", archive_in, ReportIS::StreamType::JSON_FOG, active_streams);
|
||||
setTriggersFlag("logToContainerService", archive_in, ReportIS::StreamType::JSON_CONTAINER_SVC, active_streams);
|
||||
setTriggersFlag("logTolocalTuning", archive_in, ReportIS::StreamType::JSON_CONTAINER_SVC, active_streams);
|
||||
setTriggersFlag("logToSyslog", archive_in, ReportIS::StreamType::SYSLOG, active_streams);
|
||||
setTriggersFlag("logToCef", archive_in, ReportIS::StreamType::CEF, active_streams);
|
||||
setTriggersFlag("acAllow", archive_in, SecurityType::AccessControl, should_log_on_detect);
|
||||
|
||||
@@ -301,7 +301,7 @@ ConvertToIpAddress(const IPAddr &addr) {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
dbgAssert(false) << "Unsupported IP type";
|
||||
dbgAssert(false) << AlertInfo(AlertTeam::CORE, "ip utilities") << "Unsupported IP type";
|
||||
}
|
||||
return address;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,9 @@ private:
|
||||
uint
|
||||
moveOnNoMatch(uint offset_from_end, unsigned char first_unmatched_byte) const
|
||||
{
|
||||
dbgAssert(shift.size() > offset_from_end) << "Shift table of the 'data' keyword is shorter than the offset";
|
||||
dbgAssert(shift.size() > offset_from_end)
|
||||
<< AlertInfo(AlertTeam::CORE, "keywords")
|
||||
<< "Shift table of the 'data' keyword is shorter than the offset";
|
||||
|
||||
uint skip_size;
|
||||
if (skip[first_unmatched_byte]>offset_from_end) {
|
||||
@@ -350,7 +352,9 @@ DataKeyword::bytesMatched(const Buffer &buf, uint offset) const
|
||||
MatchStatus
|
||||
DataKeyword::isMatch(const I_KeywordRuntimeState *prev) const
|
||||
{
|
||||
dbgAssert(pattern.size()>0) << "Trying to run on an uninitialized keyword data";
|
||||
dbgAssert(pattern.size()>0)
|
||||
<< AlertInfo(AlertTeam::CORE, "keywords")
|
||||
<< "Trying to run on an uninitialized keyword data";
|
||||
|
||||
dbgDebug(D_KEYWORD) << "Searching for " << dumpHex(pattern);
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ jumpKeyword::getStartOffset(uint buf_size, const I_KeywordRuntimeState *prev) co
|
||||
return prev->getOffset(ctx);
|
||||
}
|
||||
}
|
||||
dbgAssert(false) << "Invalid jumping 'from' parameter";
|
||||
dbgAssert(false) << AlertInfo(AlertTeam::CORE, "keywords") << "Invalid jumping 'from' parameter";
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ SentinelRuntimeState::getOffset(const std::string &) const
|
||||
uint
|
||||
SentinelRuntimeState::getVariable(uint var_id) const
|
||||
{
|
||||
dbgAssert(false) << "Could not find the variable ID: " << var_id;
|
||||
dbgAssert(false) << AlertInfo(AlertTeam::CORE, "keywords") << "Could not find the variable ID: " << var_id;
|
||||
return 0;
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
@@ -297,7 +297,9 @@ PCREKeyword::getStartOffsetAndLength(uint buf_size, const I_KeywordRuntimeState
|
||||
MatchStatus
|
||||
PCREKeyword::isMatch(const I_KeywordRuntimeState *prev) const
|
||||
{
|
||||
dbgAssert(pcre_machine!=nullptr) << "Trying to run on an uninitialized keyword 'pcre'";
|
||||
dbgAssert(pcre_machine!=nullptr)
|
||||
<< AlertInfo(AlertTeam::CORE, "keywords")
|
||||
<< "Trying to run on an uninitialized keyword 'pcre'";
|
||||
|
||||
auto part = Singleton::Consume<I_Environment>::by<KeywordComp>()->get<Buffer>(static_cast<string>(ctx));
|
||||
|
||||
|
||||
@@ -250,7 +250,9 @@ ComparisonAttr::operator()(int first_val, int second_val) const
|
||||
return first_val >= second_val;
|
||||
}
|
||||
}
|
||||
dbgAssert(false) << "ComparisonAttr::operator found an invalid comparison operator";
|
||||
dbgAssert(false)
|
||||
<< AlertInfo(AlertTeam::CORE, "keywords")
|
||||
<< "ComparisonAttr::operator found an invalid comparison operator";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ StateopKeyword::isMatch(const I_KeywordRuntimeState *prev) const
|
||||
if (table->hasState<KeywordStateop>()) table->getState<KeywordStateop>().removeVariable(var_name);
|
||||
return runNext(prev);
|
||||
} else {
|
||||
dbgAssert(false) << "Impossible 'stateop' keyword without operation";
|
||||
dbgAssert(false) << AlertInfo(AlertTeam::CORE, "keywords") << "Impossible 'stateop' keyword without operation";
|
||||
}
|
||||
|
||||
// If there was no matches and the keyword is effected by other keywords, then we know that the rule won't match
|
||||
|
||||
@@ -80,7 +80,7 @@ kiss_pmglob_string_s::kiss_pmglob_string_s(const char *buffer, size_t size, int
|
||||
|
||||
kiss_pmglob_string_s::kiss_pmglob_string_s(const u_char *buffer, size_t size, int _pattern_id, u_int _flags)
|
||||
{
|
||||
dbgAssert(buffer && size > 0) << "Illegal arguments";
|
||||
dbgAssert(buffer && size > 0) << AlertInfo(AlertTeam::CORE, "pattern matcher") << "Illegal arguments";
|
||||
buf.resize(size);
|
||||
memcpy(buf.data(), buffer, size);
|
||||
pattern_id = _pattern_id;
|
||||
|
||||
@@ -430,7 +430,9 @@ kiss_thin_nfa_exec(KissThinNFA *nfa_h, const Buffer& buf, std::vector<std::pair<
|
||||
{
|
||||
struct kiss_bnfa_runtime_s bnfa_runtime;
|
||||
|
||||
dbgAssert(nfa_h != nullptr) << "kiss_thin_nfa_exec() was called with null handle";
|
||||
dbgAssert(nfa_h != nullptr)
|
||||
<< AlertInfo(AlertTeam::CORE, "pattern matcher")
|
||||
<< "kiss_thin_nfa_exec() was called with null handle";
|
||||
|
||||
if (buf.size() == 0) {
|
||||
return;
|
||||
|
||||
@@ -105,7 +105,7 @@ PMHook::prepare(const set<PMPattern> &inputs)
|
||||
set<PMPattern>
|
||||
PMHook::scanBuf(const Buffer &buf) const
|
||||
{
|
||||
dbgAssert(handle != nullptr) << "Unusable Pattern Matcher";
|
||||
dbgAssert(handle != nullptr) << AlertInfo(AlertTeam::CORE, "pattern matcher") << "Unusable Pattern Matcher";
|
||||
vector<pair<uint, uint>> pm_matches;
|
||||
kiss_thin_nfa_exec(handle.get(), buf, pm_matches);
|
||||
dbgTrace(D_PM) << pm_matches.size() << " raw matches found";
|
||||
@@ -121,7 +121,7 @@ PMHook::scanBuf(const Buffer &buf) const
|
||||
set<pair<uint, uint>>
|
||||
PMHook::scanBufWithOffset(const Buffer &buf) const
|
||||
{
|
||||
dbgAssert(handle != nullptr) << "Unusable Pattern Matcher";
|
||||
dbgAssert(handle != nullptr) << AlertInfo(AlertTeam::CORE, "pattern matcher") << "Unusable Pattern Matcher";
|
||||
|
||||
vector<pair<uint, uint>> pm_matches;
|
||||
kiss_thin_nfa_exec(handle.get(), buf, pm_matches);
|
||||
@@ -135,7 +135,7 @@ PMHook::scanBufWithOffset(const Buffer &buf) const
|
||||
void
|
||||
PMHook::scanBufWithOffsetLambda(const Buffer &buf, I_PMScan::CBFunction cb) const
|
||||
{
|
||||
dbgAssert(handle != nullptr) << "Unusable Pattern Matcher";
|
||||
dbgAssert(handle != nullptr) << AlertInfo(AlertTeam::CORE, "pattern matcher") << "Unusable Pattern Matcher";
|
||||
|
||||
unordered_map<uint, uint> match_counts;
|
||||
vector<pair<uint, uint>> pm_matches;
|
||||
|
||||
2
components/utils/service_health_status/CMakeLists.txt
Executable file
2
components/utils/service_health_status/CMakeLists.txt
Executable file
@@ -0,0 +1,2 @@
|
||||
add_library(service_health_status service_health_status.cc)
|
||||
add_subdirectory(service_health_status_ut)
|
||||
104
components/utils/service_health_status/service_health_status.cc
Normal file
104
components/utils/service_health_status/service_health_status.cc
Normal file
@@ -0,0 +1,104 @@
|
||||
// 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 "service_health_status.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include "debug.h"
|
||||
#include "rest.h"
|
||||
#include "customized_cereal_map.h"
|
||||
#include "service_health_update_event.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
USE_DEBUG_FLAG(D_SERVICE_HEALTH_STATUS);
|
||||
|
||||
class I_ServiceHealthStatusImpl
|
||||
{
|
||||
public:
|
||||
virtual const map<string, string> & getErrors() const = 0;
|
||||
|
||||
protected:
|
||||
virtual ~I_ServiceHealthStatusImpl() {}
|
||||
};
|
||||
|
||||
class ServiceHealthStatus::Impl
|
||||
:
|
||||
public Singleton::Provide<I_ServiceHealthStatusImpl>::SelfInterface,
|
||||
public Listener<ServiceHealthUpdateEvent>
|
||||
{
|
||||
public:
|
||||
void init();
|
||||
const map<string, string> & getErrors() const override { return errors_map; }
|
||||
void upon(const ServiceHealthUpdateEvent &event) override;
|
||||
|
||||
private:
|
||||
map<string, string> errors_map;
|
||||
};
|
||||
|
||||
class ServiceHealthStatusRest
|
||||
:
|
||||
public ServerRest,
|
||||
Singleton::Consume<I_ServiceHealthStatusImpl>
|
||||
{
|
||||
using ErrorsMap = map<string, string>;
|
||||
|
||||
public:
|
||||
void
|
||||
doCall()
|
||||
{
|
||||
errors = Singleton::Consume<I_ServiceHealthStatusImpl>::by<ServiceHealthStatusRest>()->getErrors();
|
||||
healthy = errors.get().empty();
|
||||
dbgTrace(D_SERVICE_HEALTH_STATUS)
|
||||
<< "Heath status requested. "
|
||||
<< (healthy ? "Service is healthy." : "Service is not healthy.");
|
||||
}
|
||||
|
||||
private:
|
||||
S2C_PARAM(bool, healthy);
|
||||
S2C_PARAM(ErrorsMap, errors);
|
||||
};
|
||||
|
||||
void
|
||||
ServiceHealthStatus::Impl::init()
|
||||
{
|
||||
if (!Singleton::exists<I_RestApi>()) return;
|
||||
Singleton::Consume<I_RestApi>::by<ServiceHealthStatus>()->addRestCall<ServiceHealthStatusRest>(
|
||||
RestAction::SHOW,
|
||||
"health"
|
||||
);
|
||||
registerListener();
|
||||
}
|
||||
|
||||
void
|
||||
ServiceHealthStatus::Impl::upon(const ServiceHealthUpdateEvent &event)
|
||||
{
|
||||
dbgTrace(D_SERVICE_HEALTH_STATUS)
|
||||
<< "Service health update event. Error: "
|
||||
<< event.getComponent()
|
||||
<< " - "
|
||||
<< event.getError();
|
||||
|
||||
if (event.isHealthyUpdate()) {
|
||||
errors_map.clear();
|
||||
} else {
|
||||
errors_map[event.getComponent()] = event.getError();
|
||||
}
|
||||
}
|
||||
|
||||
ServiceHealthStatus::ServiceHealthStatus() : Component("ServiceHealthStatus"), pimpl(make_unique<Impl>()) {}
|
||||
ServiceHealthStatus::~ServiceHealthStatus() {}
|
||||
|
||||
void ServiceHealthStatus::init() { pimpl->init(); }
|
||||
@@ -0,0 +1,8 @@
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
link_directories(${BOOST_ROOT}/lib)
|
||||
|
||||
add_unit_test(
|
||||
service_health_status_ut
|
||||
"service_health_status_ut.cc"
|
||||
"service_health_status;rest;event_is;connkey;mainloop;encryptor;messaging;-lz;metric;-lboost_regex;-lboost_context;-lcrypto;"
|
||||
)
|
||||
@@ -0,0 +1,73 @@
|
||||
#include "service_health_status.h"
|
||||
|
||||
#include "cptest.h"
|
||||
#include "environment.h"
|
||||
#include "config.h"
|
||||
#include "config_component.h"
|
||||
#include "debug.h"
|
||||
#include "connkey.h"
|
||||
#include "rest.h"
|
||||
#include "rest_server.h"
|
||||
#include "mock/mock_rest_api.h"
|
||||
#include "service_health_update_event.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace testing;
|
||||
|
||||
USE_DEBUG_FLAG(D_GEO_DB);
|
||||
|
||||
class HealthCheckStatusTest : public Test
|
||||
{
|
||||
public:
|
||||
HealthCheckStatusTest()
|
||||
{
|
||||
EXPECT_CALL(mock_rest, mockRestCall(RestAction::SHOW, "health", _))
|
||||
.WillOnce(WithArg<2>(Invoke(this, &HealthCheckStatusTest::showHealthCheckStatus)));
|
||||
health_check_status.init();
|
||||
}
|
||||
|
||||
bool
|
||||
showHealthCheckStatus(const unique_ptr<RestInit> &p)
|
||||
{
|
||||
show_health_check_status = p->getRest();
|
||||
return true;
|
||||
}
|
||||
|
||||
::Environment env;
|
||||
ConfigComponent config;
|
||||
ServiceHealthStatus health_check_status;
|
||||
NiceMock<MockRestApi> mock_rest;
|
||||
unique_ptr<ServerRest> show_health_check_status;
|
||||
};
|
||||
|
||||
TEST_F(HealthCheckStatusTest, testHealthCheckStatus)
|
||||
{
|
||||
ServiceHealthUpdateEvent().notify();
|
||||
|
||||
stringstream ss("{}");
|
||||
Maybe<string> maybe_res = show_health_check_status->performRestCall(ss);
|
||||
EXPECT_TRUE(maybe_res.ok());
|
||||
EXPECT_EQ(maybe_res.unpack(),
|
||||
"{\n"
|
||||
" \"healthy\": true,\n"
|
||||
" \"errors\": {}\n"
|
||||
"}"
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(HealthCheckStatusTest, testNotHealthyService)
|
||||
{
|
||||
ServiceHealthUpdateEvent("test", "test description").notify();
|
||||
|
||||
stringstream ss("{}");
|
||||
Maybe<string> maybe_res = show_health_check_status->performRestCall(ss);
|
||||
EXPECT_TRUE(maybe_res.ok());
|
||||
EXPECT_EQ(maybe_res.unpack(),
|
||||
"{\n"
|
||||
" \"healthy\": false,\n"
|
||||
" \"errors\": {\n"
|
||||
" \"test\": \"test description\"\n"
|
||||
" }\n"
|
||||
"}"
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user