Compare commits

...

48 Commits

Author SHA1 Message Date
Ned Wright
2dda6231f6 sync code 2024-11-28 10:53:40 +00:00
Ned Wright
1c1f0b7e29 sync code 2024-11-28 10:41:59 +00:00
orianelou
6255e1f30d Rename docker-compose.yaml to docker-compose.yaml 2024-11-06 14:57:50 +02:00
orianelou
454aacf622 Rename .env to .env 2024-11-06 14:57:31 +02:00
orianelou
c91ccba5a8 Create .env 2024-11-06 14:01:40 +02:00
orianelou
b1f897191c Create docker-compose.yaml 2024-11-06 14:01:20 +02:00
Daniel-Eisenberg
027ddfea21 Merge pull request #200 from openappsec/Oct_14_2024-Dev
Oct 14 2024 dev
2024-11-05 12:12:10 +02:00
orianelou
d1a2906b29 Create default.conf 2024-11-03 14:23:34 +02:00
Ned Wright
b1ade9bba0 code sync 2024-10-15 06:57:25 +00:00
Ned Wright
36d302b77e code sync 2024-10-14 16:43:58 +00:00
Ned Wright
1d7d38b0a6 code sync 2024-10-14 16:39:35 +00:00
Ned Wright
1b7eafaa23 code sync 2024-10-14 16:32:23 +00:00
Ned Wright
c2ea2cda6d sync code 2024-10-14 14:51:28 +00:00
orianelou
b58f7781e6 Update local_policy.yaml 2024-10-01 13:05:23 +03:00
orianelou
7153d222c0 Update local_policy.yaml 2024-10-01 13:03:59 +03:00
orianelou
f1ec8959b7 Update apisix-standalone.yaml 2024-10-01 12:49:25 +03:00
Daniel-Eisenberg
4a7336b276 Merge pull request #190 from openappsec/Sep_17_2024-Dev
sync code
2024-09-30 14:53:51 +03:00
orianelou
4d0042e933 Create apisix-standalone.yaml 2024-09-30 14:10:35 +03:00
orianelou
015915497a Create docker-compose.yaml 2024-09-30 14:09:43 +03:00
Ned Wright
586150fe4f sync code 2024-09-17 10:53:09 +00:00
orianelou
3fe0b42fcd Merge pull request #189 from openappsec/Sep_15_2024-Dev
sync code
2024-09-15 17:25:26 +03:00
orianelou
84e10c7129 Merge pull request #186 from chkp-omriat2/main
Updating crowdsec auxiliary
2024-09-15 17:25:13 +03:00
Ned Wright
eddd250409 sync code 2024-09-15 02:49:26 +00:00
chkp-omriat2
294cb600f8 Updating crowdsec auxiliary 2024-09-10 06:09:54 +00:00
Ned Wright
f4bad4c4d9 Remove non-active files 2024-09-02 14:16:01 +03:00
WrightNed
6e916599d9 Merge pull request #179 from openappsec/Aug_20_2024-Dev
Aug 20th update
2024-08-27 12:33:46 +03:00
orianelou
24d53aed53 Update docker-compose.yaml 2024-08-27 10:50:25 +03:00
WrightNed
93fb3da2f8 Merge pull request #177 from wiaam96/patch-1
Update entry.sh
2024-08-22 15:17:49 +03:00
wiaam96
e7378c9a5f Update entry.sh 2024-08-22 15:15:24 +03:00
Ned Wright
110f0c8bd2 Aug 20th update 2024-08-21 08:42:14 +00:00
WrightNed
ca31aac08a Merge pull request #174 from openappsec/orianelou-patch-6
Update docker-compose.yaml
2024-08-20 15:17:02 +03:00
orianelou
161b6dd180 Update docker-compose.yaml 2024-08-20 14:50:01 +03:00
WrightNed
84327e0b19 Merge pull request #170 from openappsec/orianelou-patch-4
Create docker-compose.yaml
2024-08-05 13:12:40 +03:00
orianelou
b9723ba6ce Create docker-compose.yaml
added compose for docker SWAG
2024-08-05 12:06:37 +03:00
WrightNed
00e183b8c6 Merge pull request #169 from openappsec/Jul_31_2024-Dev
Jul 31st update
2024-08-01 18:10:44 +03:00
WrightNed
e859c167ed Merge pull request #167 from openappsec/orianelou-crds
Orianelou crds
2024-08-01 18:10:11 +03:00
Ned Wright
384b59cc87 Jul 31st update 2024-07-31 17:15:35 +00:00
orianelou
805e958cb9 Create open-appsec-crd-latest.yaml 2024-07-25 12:06:59 +03:00
orianelou
5bcd7cfcf1 Create open-appsec-crd-v1beta2.yaml 2024-07-25 12:05:57 +03:00
orianelou
ae6f2faeec Create open-appsec-crd-v1beta1.yaml 2024-07-25 12:04:22 +03:00
WrightNed
705a5e6061 Merge pull request #166 from openappsec/Jul_23_2024-Dev
Jul 23rd update
2024-07-24 16:01:45 +03:00
WrightNed
c33b74a970 Merge pull request #164 from chkp-omris/main
update intelligence
2024-07-24 15:54:58 +03:00
chkp-omris
2da9fbc385 update intelligence 2024-07-23 13:15:33 +00:00
Ned Wright
f58e9a6128 Jul 23rd update 2024-07-23 11:08:24 +00:00
WrightNed
57ea5c72c5 Merge pull request #156 from openappsec/Jul_04_2024-Dev
Jul 4th update
2024-07-07 08:47:38 +03:00
Ned Wright
962bd31d46 Jul 4th update 2024-07-04 14:10:34 +00:00
WrightNed
01770475ec Merge pull request #153 from openappsec/Jun_26_2024-Dev
June 27th update
2024-07-01 11:42:11 +03:00
Ned Wright
78b114a274 June 27th update 2024-06-27 12:05:38 +00:00
339 changed files with 141419 additions and 120090 deletions

View File

@@ -155,6 +155,24 @@ getWaitingForVerdictThreadTimeout()
return conf_data.getNumericalValue("waiting_for_verdict_thread_timeout_msec"); return conf_data.getNumericalValue("waiting_for_verdict_thread_timeout_msec");
} }
unsigned int
getMinRetriesForVerdict()
{
return conf_data.getNumericalValue("min_retries_for_verdict");
}
unsigned int
getMaxRetriesForVerdict()
{
return conf_data.getNumericalValue("max_retries_for_verdict");
}
unsigned int
getReqBodySizeTrigger()
{
return conf_data.getNumericalValue("body_size_trigger");
}
int int
isIPAddress(c_str ip_str) isIPAddress(c_str ip_str)
{ {

View File

@@ -63,31 +63,37 @@ TEST_F(HttpAttachmentUtilTest, GetValidAttachmentConfiguration)
"\"waiting_for_verdict_thread_timeout_msec\": 75,\n" "\"waiting_for_verdict_thread_timeout_msec\": 75,\n"
"\"req_header_thread_timeout_msec\": 10,\n" "\"req_header_thread_timeout_msec\": 10,\n"
"\"ip_ranges\": " + createIPRangesString(ip_ranges) + ",\n" "\"ip_ranges\": " + createIPRangesString(ip_ranges) + ",\n"
"\"static_resources_path\": \"" + static_resources_path + "\"" "\"static_resources_path\": \"" + static_resources_path + "\",\n"
"\"min_retries_for_verdict\": 1,\n"
"\"max_retries_for_verdict\": 3,\n"
"\"body_size_trigger\": 777\n"
"}\n"; "}\n";
ofstream valid_configuration_file(attachment_configuration_file_name); ofstream valid_configuration_file(attachment_configuration_file_name);
valid_configuration_file << valid_configuration; valid_configuration_file << valid_configuration;
valid_configuration_file.close(); valid_configuration_file.close();
EXPECT_EQ(initAttachmentConfig(attachment_configuration_file_name.c_str()), 1); EXPECT_EQ(initAttachmentConfig(attachment_configuration_file_name.c_str()), 1);
EXPECT_EQ(getDbgLevel(), 2); EXPECT_EQ(getDbgLevel(), 2u);
EXPECT_EQ(getStaticResourcesPath(), static_resources_path); EXPECT_EQ(getStaticResourcesPath(), static_resources_path);
EXPECT_EQ(isFailOpenMode(), 0); EXPECT_EQ(isFailOpenMode(), 0);
EXPECT_EQ(getFailOpenTimeout(), 1234); EXPECT_EQ(getFailOpenTimeout(), 1234u);
EXPECT_EQ(isFailOpenHoldMode(), 1); EXPECT_EQ(isFailOpenHoldMode(), 1);
EXPECT_EQ(getFailOpenHoldTimeout(), 4321); EXPECT_EQ(getFailOpenHoldTimeout(), 4321u);
EXPECT_EQ(isFailOpenOnSessionLimit(), 1); EXPECT_EQ(isFailOpenOnSessionLimit(), 1);
EXPECT_EQ(getMaxSessionsPerMinute(), 0); EXPECT_EQ(getMaxSessionsPerMinute(), 0u);
EXPECT_EQ(getNumOfNginxIpcElements(), 200); EXPECT_EQ(getNumOfNginxIpcElements(), 200u);
EXPECT_EQ(getKeepAliveIntervalMsec(), 10000); EXPECT_EQ(getKeepAliveIntervalMsec(), 10000u);
EXPECT_EQ(getResProccessingTimeout(), 420); EXPECT_EQ(getResProccessingTimeout(), 420u);
EXPECT_EQ(getReqProccessingTimeout(), 42); EXPECT_EQ(getReqProccessingTimeout(), 42u);
EXPECT_EQ(getRegistrationThreadTimeout(), 101); EXPECT_EQ(getRegistrationThreadTimeout(), 101u);
EXPECT_EQ(getReqHeaderThreadTimeout(), 10); EXPECT_EQ(getReqHeaderThreadTimeout(), 10u);
EXPECT_EQ(getReqBodyThreadTimeout(), 155); EXPECT_EQ(getReqBodyThreadTimeout(), 155u);
EXPECT_EQ(getResHeaderThreadTimeout(), 1); EXPECT_EQ(getResHeaderThreadTimeout(), 1u);
EXPECT_EQ(getResBodyThreadTimeout(), 0); EXPECT_EQ(getResBodyThreadTimeout(), 0u);
EXPECT_EQ(getWaitingForVerdictThreadTimeout(), 75); EXPECT_EQ(getMinRetriesForVerdict(), 1u);
EXPECT_EQ(getMaxRetriesForVerdict(), 3u);
EXPECT_EQ(getReqBodySizeTrigger(), 777u);
EXPECT_EQ(getWaitingForVerdictThreadTimeout(), 75u);
EXPECT_EQ(getInspectionMode(), ngx_http_inspection_mode::BLOCKING_THREAD); EXPECT_EQ(getInspectionMode(), ngx_http_inspection_mode::BLOCKING_THREAD);
EXPECT_EQ(isDebugContext("1.2.3.4", "5.6.7.8", 80, "GET", "test", "/abc"), 1); EXPECT_EQ(isDebugContext("1.2.3.4", "5.6.7.8", 80, "GET", "test", "/abc"), 1);

View File

@@ -44,8 +44,11 @@ while true; do
done done
if [ -z $var_token ] && [ $var_mode != "--hybrid_mode" ]; then if [ -z $var_token ] && [ $var_mode != "--hybrid_mode" ]; then
echo "Error: Token was not provided as input argument." var_token=$(env | grep 'AGENT_TOKEN=' | cut -d'=' -f2-)
exit 1 if [ -z $var_token ]; then
echo "Error: Token was not provided as input argument."
exit 1
fi
fi fi
orchestration_service_installation_flags="--container_mode --skip_registration" orchestration_service_installation_flags="--container_mode --skip_registration"

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,10 +1,8 @@
add_subdirectory(report_messaging)
add_subdirectory(http_manager) add_subdirectory(http_manager)
add_subdirectory(signal_handler) add_subdirectory(signal_handler)
add_subdirectory(gradual_deployment) add_subdirectory(gradual_deployment)
add_subdirectory(packet) add_subdirectory(packet)
add_subdirectory(pending_key) add_subdirectory(pending_key)
add_subdirectory(health_check_manager)
add_subdirectory(utils) add_subdirectory(utils)
add_subdirectory(attachment-intakers) add_subdirectory(attachment-intakers)

View File

@@ -39,6 +39,8 @@ USE_DEBUG_FLAG(D_ATTACHMENT_REGISTRATION);
using namespace std; using namespace std;
static const AlertInfo alert(AlertTeam::CORE, "attachment registrator");
class AttachmentRegistrator::Impl class AttachmentRegistrator::Impl
{ {
public: public:
@@ -163,7 +165,7 @@ private:
break; break;
} }
default: 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 << "_"; if (!family_id.empty()) handler_path << family_id << "_";
@@ -175,7 +177,9 @@ private:
string string
genRegCommand(const string &family_id, const uint num_of_members, const AttachmentType type) const 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 "; static const string registration_format = "/etc/cp/watchdog/cp-nano-watchdog --register ";
stringstream registration_command; stringstream registration_command;
@@ -187,7 +191,7 @@ private:
break; break;
} }
default: 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; if (!family_id.empty()) registration_command << " --family " << family_id;
@@ -265,7 +269,7 @@ private:
return -1; 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(); return new_socket.unpack();
} }
@@ -281,7 +285,7 @@ private:
} }
I_Socket::socketFd client_socket = accepted_socket.unpack(); 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); }); auto close_socket_on_exit = make_scope_exit([&]() { i_socket->closeSocket(client_socket); });
Maybe<uint8_t> attachment_id = readNumericParam(client_socket); Maybe<uint8_t> attachment_id = readNumericParam(client_socket);
@@ -375,7 +379,7 @@ private:
} }
I_Socket::socketFd client_socket = accepted_socket.unpack(); 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); }); auto close_socket_on_exit = make_scope_exit([&]() { i_socket->closeSocket(client_socket); });
Maybe<AttachmentType> attachment_type = readAttachmentType(client_socket); Maybe<AttachmentType> attachment_type = readAttachmentType(client_socket);

View File

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

View File

@@ -42,6 +42,7 @@ HttpAttachmentConfig::init()
setNumOfNginxIpcElements(); setNumOfNginxIpcElements();
setDebugByContextValues(); setDebugByContextValues();
setKeepAliveIntervalMsec(); setKeepAliveIntervalMsec();
setRetriesForVerdict();
} }
bool bool
@@ -215,6 +216,31 @@ HttpAttachmentConfig::setFailOpenTimeout()
conf_data.setNumericalValue("nginx_inspection_mode", inspection_mode); conf_data.setNumericalValue("nginx_inspection_mode", inspection_mode);
} }
void
HttpAttachmentConfig::setRetriesForVerdict()
{
conf_data.setNumericalValue("min_retries_for_verdict", getAttachmentConf<uint>(
3,
"agent.minRetriesForVerdict.nginxModule",
"HTTP manager",
"Min retries for verdict"
));
conf_data.setNumericalValue("max_retries_for_verdict", getAttachmentConf<uint>(
15,
"agent.maxRetriesForVerdict.nginxModule",
"HTTP manager",
"Max retries for verdict"
));
conf_data.setNumericalValue("body_size_trigger", getAttachmentConf<uint>(
200000,
"agent.reqBodySizeTrigger.nginxModule",
"HTTP manager",
"Request body size trigger"
));
}
void void
HttpAttachmentConfig::setFailOpenWaitMode() HttpAttachmentConfig::setFailOpenWaitMode()
{ {

View File

@@ -70,6 +70,8 @@ private:
void setDebugByContextValues(); void setDebugByContextValues();
void setRetriesForVerdict();
WebTriggerConf web_trigger_conf; WebTriggerConf web_trigger_conf;
HttpAttachmentConfiguration conf_data; HttpAttachmentConfiguration conf_data;
}; };

View File

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

View File

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

View File

@@ -1,8 +0,0 @@
include_directories(${CMAKE_SOURCE_DIR}/components/include)
link_directories(${BOOST_ROOT}/lib)
add_unit_test(
health_check_manager_ut
"health_check_manager_ut.cc"
"singleton;messaging;mainloop;health_check_manager;event_is;metric;-lboost_regex"
)

View File

@@ -46,7 +46,10 @@ operator<<(ostream &os, const EventVerdict &event)
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_WAIT: return os << "Wait"; 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; return os;
} }
@@ -321,8 +324,11 @@ private:
state.setApplicationVerdict(respond.first, respond.second.getVerdict()); state.setApplicationVerdict(respond.first, respond.second.getVerdict());
} }
FilterVerdict aggregated_verdict = state.getCurrVerdict();
return state.getCurrVerdict(); if (aggregated_verdict.getVerdict() == ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP) {
SecurityAppsDropEvent(state.getCurrentDropVerdictCausers()).notify();
}
return aggregated_verdict;
} }
static void static void

View File

@@ -69,6 +69,7 @@ HttpManagerOpaque::getCurrVerdict() const
break; break;
default: default:
dbgAssert(false) dbgAssert(false)
<< AlertInfo(AlertTeam::CORE, "http manager")
<< "Received unknown verdict " << "Received unknown verdict "
<< static_cast<int>(app_verdic_pair.second); << 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; 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 void
HttpManagerOpaque::saveCurrentDataToCache(const Buffer &full_data) HttpManagerOpaque::saveCurrentDataToCache(const Buffer &full_data)
{ {

View File

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

View File

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

View File

@@ -24,7 +24,8 @@ class ExternalSdkServer
: :
public Component, public Component,
Singleton::Provide<I_ExternalSdkServer>, Singleton::Provide<I_ExternalSdkServer>,
Singleton::Consume<I_RestApi> Singleton::Consume<I_RestApi>,
Singleton::Consume<I_Messaging>
{ {
public: public:
ExternalSdkServer(); ExternalSdkServer();

View File

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

View File

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

View File

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

View File

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

View File

@@ -31,7 +31,7 @@ public:
virtual bool isReverseProxy() = 0; virtual bool isReverseProxy() = 0;
virtual bool isCloudStorageEnabled() = 0; virtual bool isCloudStorageEnabled() = 0;
virtual Maybe<std::tuple<std::string, std::string, std::string>> parseNginxMetadata() = 0; virtual Maybe<std::tuple<std::string, std::string, std::string>> parseNginxMetadata() = 0;
virtual Maybe<std::tuple<std::string, std::string, std::string>> readCloudMetadata() = 0; virtual Maybe<std::tuple<std::string, std::string, std::string, std::string, std::string>> readCloudMetadata() = 0;
virtual std::map<std::string, std::string> getResolvedDetails() = 0; virtual std::map<std::string, std::string> getResolvedDetails() = 0;
#if defined(gaia) || defined(smb) #if defined(gaia) || defined(smb)
virtual bool compareCheckpointVersion(int cp_version, std::function<bool(int, int)> compare_operator) const = 0; virtual bool compareCheckpointVersion(int cp_version, std::function<bool(int, int)> compare_operator) const = 0;

View File

@@ -64,7 +64,9 @@ public:
const std::string &service_id const std::string &service_id
) = 0; ) = 0;
virtual std::map<std::string, PortNumber> getServiceToPortMap() = 0; virtual std::map<std::string, std::vector<PortNumber>> getServiceToPortMap() = 0;
virtual bool getServicesPolicyStatus() const = 0;
protected: protected:
virtual ~I_ServiceController() {} virtual ~I_ServiceController() {}

View File

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

View File

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

View File

@@ -56,7 +56,7 @@ private:
if (mapped_type.second == type) return mapped_type.first; 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 // Just satisfying the compiler, this return never reached
return std::string(); return std::string();
} }

View File

@@ -7,24 +7,28 @@ static const std::string product_name = getenv("DOCKER_RPM_ENABLED") ? "CloudGua
static const std::string default_cp_cert_file = "/etc/cp/cpCert.pem"; static const std::string default_cp_cert_file = "/etc/cp/cpCert.pem";
static const std::string default_cp_key_file = "/etc/cp/cpKey.key"; 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_rpm_conf_path = "/etc/cp/conf/rpmanager/";
static const std::string default_certificate_path = "/etc/cp/rpmanager/certs"; 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_additional_files_path = "/etc/cp/conf/rpmanager/include";
static const std::string default_server_config = "additional_server_config.conf"; 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_location_config = "additional_location_config.conf";
static const std::string default_trusted_ca_suffix = "_user_ca_bundle.crt"; 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_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_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_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_server_certificate_key_path = "/etc/cp/rpmanager/certs/sslPrivateKey_";
static const std::string default_container_name = "cp_nginx_gaia"; 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_docker_image = "cp_nginx_gaia";
static const std::string default_nginx_config_file = "/etc/cp/conf/rpmanager/nginx.conf"; 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_global_conf_template = "/etc/cp/conf/rpmanager/nginx-conf-template";
static const std::string default_nginx_config_include_file = static const std::string default_nginx_config_include_file =
"/etc/cp/conf/rpmanager/servers/nginx_conf_include"; "/etc/cp/conf/rpmanager/servers/00_nginx_conf_include.conf";
static const std::string default_global_conf_include_template = static const std::string default_global_conf_include_template =
"/etc/cp/conf/rpmanager/nginx-conf-include-template"; "/etc/cp/conf/rpmanager/nginx-conf-include-template";
static const std::string default_global_conf_include_template_no_responses = static const std::string default_global_conf_include_template_no_responses =

View File

@@ -0,0 +1,39 @@
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __SERVICE_HEALTH_STATUS_H__
#define __SERVICE_HEALTH_STATUS_H__
#include "singleton.h"
#include "i_rest_api.h"
#include "i_environment.h"
#include "component.h"
class ServiceHealthStatus
:
public Component,
Singleton::Consume<I_RestApi>,
Singleton::Consume<I_Environment>
{
public:
ServiceHealthStatus();
~ServiceHealthStatus();
void init() override;
private:
class Impl;
std::unique_ptr<Impl> pimpl;
};
#endif // __SERVICE_HEALTH_STATUS_H__

View File

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

View File

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

View File

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

View File

@@ -43,7 +43,9 @@ PendingKey::print(ostream &os) const
size_t size_t
PendingKey::hash() const 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; size_t seed = 0;
hashCombine(seed, static_cast<u_char>(src.type)); hashCombine(seed, static_cast<u_char>(src.type));
hashCombine(seed, src.proto); hashCombine(seed, src.proto);

View File

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

View File

@@ -67,18 +67,18 @@ public:
dbgTrace(D_GEO_FILTER) << getListenerName() << " new transaction event"; dbgTrace(D_GEO_FILTER) << getListenerName() << " new transaction event";
if (!event.isLastHeader()) return EventVerdict(ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT); 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 env = Singleton::Consume<I_Environment>::by<HttpGeoFilter>();
auto maybe_xff = env->get<std::string>(HttpTransactionData::xff_vals_ctx); auto maybe_xff = env->get<std::string>(HttpTransactionData::xff_vals_ctx);
if (!maybe_xff.ok()) { if (!maybe_xff.ok()) {
dbgTrace(D_GEO_FILTER) << "failed to get xff vals from env"; dbgTrace(D_GEO_FILTER) << "failed to get xff vals from env";
} else { } else {
xff_set = split(maybe_xff.unpack(), ','); ip_set = split(maybe_xff.unpack(), ',');
} }
dbgDebug(D_GEO_FILTER) << getListenerName() << " last header, start lookup"; dbgDebug(D_GEO_FILTER) << getListenerName() << " last header, start lookup";
if (xff_set.size() > 0) { if (ip_set.size() > 0) {
removeTrustedIpsFromXff(xff_set); removeTrustedIpsFromXff(ip_set);
} else { } else {
dbgDebug(D_GEO_FILTER) << "xff not found in headers"; dbgDebug(D_GEO_FILTER) << "xff not found in headers";
} }
@@ -90,14 +90,14 @@ public:
} }
auto source_ip = convertIpAddrToString(maybe_source_ip.unpack()); 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) { if (exception_verdict != ngx_http_cp_verdict_e::TRAFFIC_VERDICT_IRRELEVANT) {
return EventVerdict(exception_verdict); 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) { if (geo_lookup_verdict != ngx_http_cp_verdict_e::TRAFFIC_VERDICT_IRRELEVANT) {
return EventVerdict(geo_lookup_verdict); return EventVerdict(geo_lookup_verdict);
} }
@@ -361,19 +361,10 @@ private:
<< ", source ip address: " << ", source ip address: "
<< source; << source;
unordered_map<string, set<string>> exception_value_source_ip = {{"sourceIP", {source}}};
auto matched_behavior_maybe = getBehaviorsVerdict(exception_value_source_ip, geo_location_data);
if (matched_behavior_maybe.ok()) {
curr_matched_behavior = matched_behavior_maybe.unpack();
verdict = curr_matched_behavior.first;
dbgDebug(D_GEO_FILTER) << "found sourceIP exception, return verdict";
break;
}
unordered_map<string, set<string>> exception_value_country_code = { unordered_map<string, set<string>> exception_value_country_code = {
{"countryCode", {country_code}} {"countryCode", {country_code}}
}; };
matched_behavior_maybe = getBehaviorsVerdict(exception_value_country_code, geo_location_data); auto matched_behavior_maybe = getBehaviorsVerdict(exception_value_country_code, geo_location_data);
if (matched_behavior_maybe.ok()) { if (matched_behavior_maybe.ok()) {
curr_matched_behavior = matched_behavior_maybe.unpack(); curr_matched_behavior = matched_behavior_maybe.unpack();
verdict = curr_matched_behavior.first; verdict = curr_matched_behavior.first;
@@ -430,8 +421,11 @@ private:
ReportIS::Tags::HTTP_GEO_FILTER ReportIS::Tags::HTTP_GEO_FILTER
); );
auto env = Singleton::Consume<I_Environment>::by<HttpGeoFilter>(); auto env = Singleton::Consume<I_Environment>::by<HttpGeoFilter>();
auto source_ip = env->get<string>(HttpTransactionData::client_ip_ctx); auto source_ip = env->get<IPAddr>(HttpTransactionData::client_ip_ctx);
if (source_ip.ok()) log << LogField("sourceIP", source_ip.unpack()); if (source_ip.ok()) log << LogField("sourceIP", convertIpAddrToString(source_ip.unpack()));
auto source_identifier = env->get<string>(HttpTransactionData::source_identifier);
if (source_identifier.ok()) log << LogField("httpSourceId", source_identifier.unpack());
auto source_port = env->get<string>(HttpTransactionData::client_port_ctx); auto source_port = env->get<string>(HttpTransactionData::client_port_ctx);
if (source_port.ok()) log << LogField("sourcePort", source_port.unpack()); if (source_port.ok()) log << LogField("sourcePort", source_port.unpack());
@@ -445,7 +439,7 @@ private:
log << LogField("securityAction", is_prevent ? "Prevent" : "Detect"); log << LogField("securityAction", is_prevent ? "Prevent" : "Detect");
if (is_default_action) log << LogField("isDefaultSecurityAction", true); if (is_default_action) log << LogField("isDefaultSecurityAction", true);
auto xff = env->get<std::string>(HttpTransactionData::xff_vals_ctx); auto xff = env->get<string>(HttpTransactionData::xff_vals_ctx);
if (xff.ok()) log << LogField("proxyIP", xff.unpack()); if (xff.ok()) log << LogField("proxyIP", xff.unpack());
log log
@@ -475,5 +469,6 @@ void
HttpGeoFilter::preload() HttpGeoFilter::preload()
{ {
registerExpectedConfiguration<GeoConfig>("rulebase", "httpGeoFilter"); registerExpectedConfiguration<GeoConfig>("rulebase", "httpGeoFilter");
registerExpectedConfiguration<UsersAllIdentifiersConfig>("rulebase", "usersIdentifiers");
registerConfigLoadCb([this]() { pimpl->loadDefaultAction(); }); registerConfigLoadCb([this]() { pimpl->loadDefaultAction(); });
} }

View File

@@ -43,7 +43,10 @@ CompoundProtection::Impl::getMatch(const set<PMPattern> &matched) const
case Operation::ORDERED_AND: return getMatchOrderedAnd(matched); 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; return MatchType::NO_MATCH;
} }

View File

@@ -8,7 +8,9 @@ IPSConfiguration::Context::Context(ContextType _type, uint history) : type(_type
uint uint
IPSConfiguration::Context::getHistorySize() const 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; return history_size;
} }
@@ -69,6 +71,8 @@ uint
IPSConfiguration::getHistorySize(const string &name) const IPSConfiguration::getHistorySize(const string &name) const
{ {
auto context = context_config.find(name); 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(); return context->second.getHistorySize();
} }

View File

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

View File

@@ -84,7 +84,7 @@ IPSSignatureMetaData::getSeverityString() const
return "Critical"; 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"; return "Critical";
} }
@@ -116,7 +116,10 @@ IPSSignatureMetaData::getPerformanceString() const
return "Critical"; 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"; return "Critical";
} }

View File

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

View File

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

View File

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

View File

@@ -385,8 +385,29 @@ Layer7AccessControl::Impl::init()
i_intelligence = Singleton::Consume<I_Intelligence_IS_V2>::by<Layer7AccessControl>(); i_intelligence = Singleton::Consume<I_Intelligence_IS_V2>::by<Layer7AccessControl>();
i_mainloop = Singleton::Consume<I_MainLoop>::by<Layer7AccessControl>(); i_mainloop = Singleton::Consume<I_MainLoop>::by<Layer7AccessControl>();
chrono::minutes expiration( int cache_expiration_in_seconds = 30;
getProfileAgentSettingWithDefault<uint>(60u, "layer7AccessControl.crowdsec.cacheExpiration") string cache_expiration_env = getenv("CROWDSEC_CACHE_EXPIRATION") ? getenv("CROWDSEC_CACHE_EXPIRATION") : "";
if (!cache_expiration_env.empty()) {
if (
all_of(cache_expiration_env.begin(), cache_expiration_env.end(), ::isdigit)
&& stoi(cache_expiration_env) > 0
) {
cache_expiration_in_seconds = stoi(cache_expiration_env);
dbgInfo(D_L7_ACCESS_CONTROL)
<< "Successfully read cache expiration value from env: "
<< cache_expiration_env;
} else {
dbgWarning(D_L7_ACCESS_CONTROL)
<< "An invalid cache expiration value was provided in env: "
<< cache_expiration_env;
}
}
chrono::seconds expiration(
getProfileAgentSettingWithDefault<uint>(
cache_expiration_in_seconds,
"layer7AccessControl.crowdsec.cacheExpiration"
)
); );
ip_reputation_cache.startExpiration( ip_reputation_cache.startExpiration(

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -79,6 +79,7 @@ class DefaultBackend
{ {
public: public:
void load(cereal::JSONInputArchive &); void load(cereal::JSONInputArchive &);
bool doesExist() const;
private: private:
bool is_exists = false; bool is_exists = false;
@@ -90,6 +91,7 @@ public:
void load(cereal::JSONInputArchive &archive_in); void load(cereal::JSONInputArchive &archive_in);
const std::vector<IngressDefinedRule> & getRules() const; const std::vector<IngressDefinedRule> & getRules() const;
bool doesDefaultBackendExist() const;
private: private:
std::string ingress_class_name; std::string ingress_class_name;

View File

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

View File

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

View File

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

View File

@@ -129,7 +129,7 @@ public:
bool shouldBeautifyLogs() const; bool shouldBeautifyLogs() const;
bool getCloud() const; bool getCloud() const;
bool isK8SNeeded() const; bool isContainerNeeded() const;
bool isCefNeeded() const; bool isCefNeeded() const;
bool isSyslogNeeded() const; bool isSyslogNeeded() const;
const std::string & getSyslogServerIpv4Address() const; const std::string & getSyslogServerIpv4Address() const;
@@ -140,7 +140,7 @@ private:
const NewLoggingService & getCefServiceData() const; const NewLoggingService & getCefServiceData() const;
bool cloud = false; bool cloud = false;
bool k8s_service = false; bool container_service = false;
bool agent_local = true; bool agent_local = true;
bool beautify_logs = true; bool beautify_logs = true;
NewLoggingService syslog_service; NewLoggingService syslog_service;

View File

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

View File

@@ -111,7 +111,7 @@ private:
SecurityAppsWrapper security_apps; SecurityAppsWrapper security_apps;
}; };
class PolicyMakerUtils class PolicyMakerUtils : Singleton::Consume<I_EnvDetails>
{ {
public: public:
std::string proccesSingleAppsecPolicy( std::string proccesSingleAppsecPolicy(

View File

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

View File

@@ -39,7 +39,7 @@ public:
bool _logToAgent, bool _logToAgent,
bool _logToCef, bool _logToCef,
bool _logToCloud, bool _logToCloud,
bool _logToK8sService, bool _logTolocalTuning,
bool _logToSyslog, bool _logToSyslog,
bool _responseBody, bool _responseBody,
bool _tpDetect, bool _tpDetect,
@@ -73,7 +73,7 @@ private:
bool logToAgent; bool logToAgent;
bool logToCef; bool logToCef;
bool logToCloud; bool logToCloud;
bool logToK8sService; bool logTolocalTuning;
bool logToSyslog; bool logToSyslog;
bool responseBody; bool responseBody;
bool tpDetect; bool tpDetect;
@@ -258,7 +258,7 @@ public:
bool shouldBeautifyLogs() const; bool shouldBeautifyLogs() const;
bool getCloud() const; bool getCloud() const;
bool isK8SNeeded() const; bool isContainerNeeded() const;
bool isCefNeeded() const; bool isCefNeeded() const;
bool isSyslogNeeded() const; bool isSyslogNeeded() const;
const std::string & getSyslogServerIpv4Address() const; const std::string & getSyslogServerIpv4Address() const;
@@ -269,7 +269,7 @@ private:
const LoggingService & getCefServiceData() const; const LoggingService & getCefServiceData() const;
bool cloud = false; bool cloud = false;
bool k8s_service = false; bool container_service = false;
bool agent_local = true; bool agent_local = true;
bool beautify_logs = true; bool beautify_logs = true;
LoggingService syslog_service; LoggingService syslog_service;

View File

@@ -86,6 +86,12 @@ DefaultBackend::load(cereal::JSONInputArchive &)
is_exists = true; is_exists = true;
} }
bool
DefaultBackend::doesExist() const
{
return is_exists;
}
void void
IngressSpec::load(cereal::JSONInputArchive &archive_in) IngressSpec::load(cereal::JSONInputArchive &archive_in)
{ {
@@ -101,6 +107,12 @@ IngressSpec::getRules() const
return rules; return rules;
} }
bool
IngressSpec::doesDefaultBackendExist() const
{
return default_backend.doesExist();
}
void void
SingleIngressData::load(cereal::JSONInputArchive &archive_in) SingleIngressData::load(cereal::JSONInputArchive &archive_in)
{ {

View File

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

View File

@@ -126,6 +126,7 @@ NewAppsecPolicySpec::load(cereal::JSONInputArchive &archive_in)
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec policy spec"; dbgTrace(D_LOCAL_POLICY) << "Loading AppSec policy spec";
parseAppsecJSONKey<string>("appsecClassName", appsec_class_name, archive_in); parseAppsecJSONKey<string>("appsecClassName", appsec_class_name, archive_in);
parseAppsecJSONKey<NewParsedRule>("default", default_rule, archive_in); parseAppsecJSONKey<NewParsedRule>("default", default_rule, archive_in);
default_rule.setHost("*");
parseAppsecJSONKey<vector<NewParsedRule>>("specificRules", specific_rules, archive_in); parseAppsecJSONKey<vector<NewParsedRule>>("specificRules", specific_rules, archive_in);
} }

View File

@@ -180,10 +180,16 @@ NewAppsecTriggerLogDestination::load(cereal::JSONInputArchive &archive_in)
} else { } else {
cloud = false; cloud = false;
} }
auto mode = Singleton::Consume<I_AgentDetails>::by<NewAppsecTriggerLogDestination>()->getOrchestrationMode(); bool local_tuning_default = false;
auto env_type = Singleton::Consume<I_EnvDetails>::by<NewAppsecTriggerLogDestination>()->getEnvType(); // check ENV VAR LOCAL_TUNING_ENABLED
bool k8s_service_default = (mode == OrchestrationMode::HYBRID && env_type == EnvType::K8S); char * tuning_enabled = getenv("LOCAL_TUNING_ENABLED");
parseAppsecJSONKey<bool>("k8s-service", k8s_service, archive_in, k8s_service_default); 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; NewStdoutLogging stdout_log;
parseAppsecJSONKey<NewStdoutLogging>("stdout", stdout_log, archive_in); parseAppsecJSONKey<NewStdoutLogging>("stdout", stdout_log, archive_in);
@@ -224,9 +230,9 @@ NewAppsecTriggerLogDestination::getCloud() const
} }
bool bool
NewAppsecTriggerLogDestination::isK8SNeeded() const NewAppsecTriggerLogDestination::isContainerNeeded() const
{ {
return k8s_service; return container_service;
} }
bool bool

View File

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

View File

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

View File

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

View File

@@ -30,7 +30,7 @@ LogTriggerSection::LogTriggerSection(
bool _logToAgent, bool _logToAgent,
bool _logToCef, bool _logToCef,
bool _logToCloud, bool _logToCloud,
bool _logToK8sService, bool _logTolocalTuning,
bool _logToSyslog, bool _logToSyslog,
bool _responseBody, bool _responseBody,
bool _tpDetect, bool _tpDetect,
@@ -55,7 +55,7 @@ LogTriggerSection::LogTriggerSection(
logToAgent(_logToAgent), logToAgent(_logToAgent),
logToCef(_logToCef), logToCef(_logToCef),
logToCloud(_logToCloud), logToCloud(_logToCloud),
logToK8sService(_logToK8sService), logTolocalTuning(_logTolocalTuning),
logToSyslog(_logToSyslog), logToSyslog(_logToSyslog),
responseBody(_responseBody), responseBody(_responseBody),
tpDetect(_tpDetect), tpDetect(_tpDetect),
@@ -96,12 +96,12 @@ LogTriggerSection::save(cereal::JSONOutputArchive &out_ar) const
cereal::make_nvp("acDrop", acDrop), cereal::make_nvp("acDrop", acDrop),
cereal::make_nvp("complianceViolations", false), cereal::make_nvp("complianceViolations", false),
cereal::make_nvp("complianceWarnings", false), cereal::make_nvp("complianceWarnings", false),
cereal::make_nvp("extendloggingMinSeverity", extendloggingMinSeverity), cereal::make_nvp("extendLoggingMinSeverity", extendloggingMinSeverity),
cereal::make_nvp("extendlogging", extendlogging), cereal::make_nvp("extendLogging", extendlogging),
cereal::make_nvp("logToAgent", logToAgent), cereal::make_nvp("logToAgent", logToAgent),
cereal::make_nvp("logToCef", logToCef), cereal::make_nvp("logToCef", logToCef),
cereal::make_nvp("logToCloud", logToCloud), cereal::make_nvp("logToCloud", logToCloud),
cereal::make_nvp("logToK8sService", logToK8sService), cereal::make_nvp("logTolocalTuning", logTolocalTuning),
cereal::make_nvp("logToSyslog", logToSyslog), cereal::make_nvp("logToSyslog", logToSyslog),
cereal::make_nvp("responseBody", responseBody), cereal::make_nvp("responseBody", responseBody),
cereal::make_nvp("responseCode", false), cereal::make_nvp("responseCode", false),
@@ -393,10 +393,16 @@ AppsecTriggerLogDestination::load(cereal::JSONInputArchive &archive_in)
} else { } else {
cloud = false; cloud = false;
} }
auto mode = Singleton::Consume<I_AgentDetails>::by<AppsecTriggerLogDestination>()->getOrchestrationMode(); // check ENV VAR LOCAL_TUNING_ENABLED
auto env_type = Singleton::Consume<I_EnvDetails>::by<AppsecTriggerLogDestination>()->getEnvType(); char * tuning_enabled = getenv("LOCAL_TUNING_ENABLED");
bool k8s_service_default = (mode == OrchestrationMode::HYBRID && env_type == EnvType::K8S); if (tuning_enabled != NULL) {
parseAppsecJSONKey<bool>("k8s-service", k8s_service, archive_in, k8s_service_default); 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; StdoutLogging stdout_log;
parseAppsecJSONKey<StdoutLogging>("stdout", stdout_log, archive_in); parseAppsecJSONKey<StdoutLogging>("stdout", stdout_log, archive_in);
@@ -437,9 +443,9 @@ AppsecTriggerLogDestination::getCloud() const
} }
bool bool
AppsecTriggerLogDestination::isK8SNeeded() const AppsecTriggerLogDestination::isContainerNeeded() const
{ {
return k8s_service; return container_service;
} }
bool bool

View File

@@ -12,6 +12,9 @@ add_subdirectory(manifest_controller)
add_subdirectory(update_communication) add_subdirectory(update_communication)
add_subdirectory(details_resolver) add_subdirectory(details_resolver)
add_subdirectory(health_check) add_subdirectory(health_check)
add_subdirectory(health_check_manager)
add_subdirectory(updates_process_reporter)
add_subdirectory(env_details) add_subdirectory(env_details)
add_subdirectory(external_sdk_server)
#add_subdirectory(orchestration_ut) #add_subdirectory(orchestration_ut)

View File

@@ -45,7 +45,7 @@ public:
bool isVersionAboveR8110() override; bool isVersionAboveR8110() override;
bool isReverseProxy() override; bool isReverseProxy() override;
bool isCloudStorageEnabled() override; bool isCloudStorageEnabled() override;
Maybe<tuple<string, string, string>> readCloudMetadata() override; Maybe<tuple<string, string, string, string, string>> readCloudMetadata() override;
Maybe<tuple<string, string, string>> parseNginxMetadata() override; Maybe<tuple<string, string, string>> parseNginxMetadata() override;
#if defined(gaia) || defined(smb) #if defined(gaia) || defined(smb)
bool compareCheckpointVersion(int cp_version, std::function<bool(int, int)> compare_operator) const override; bool compareCheckpointVersion(int cp_version, std::function<bool(int, int)> compare_operator) const override;
@@ -142,7 +142,7 @@ DetailsResolver::Impl::isCloudStorageEnabled()
{ {
auto cloud_storage_mode_override = getProfileAgentSetting<bool>("agent.cloudStorage.enabled"); auto cloud_storage_mode_override = getProfileAgentSetting<bool>("agent.cloudStorage.enabled");
if (cloud_storage_mode_override.ok()) { if (cloud_storage_mode_override.ok()) {
dbgInfo(D_ORCHESTRATOR) << "Received cloud-storage mode override: " << *cloud_storage_mode_override; dbgDebug(D_ORCHESTRATOR) << "Received cloud-storage mode override: " << *cloud_storage_mode_override;
return *cloud_storage_mode_override; return *cloud_storage_mode_override;
} }
@@ -152,6 +152,7 @@ DetailsResolver::Impl::isCloudStorageEnabled()
bool bool
DetailsResolver::Impl::isKernelVersion3OrHigher() DetailsResolver::Impl::isKernelVersion3OrHigher()
{ {
#if defined(gaia) || defined(smb)
static const string cmd = static const string cmd =
"clish -c 'show version os kernel' | awk '{print $4}' " "clish -c 'show version os kernel' | awk '{print $4}' "
"| cut -d '.' -f 1 | awk -F: '{ if ( $1 >= 3 ) {print 1} else {print 0}}'"; "| cut -d '.' -f 1 | awk -F: '{ if ( $1 >= 3 ) {print 1} else {print 0}}'";
@@ -160,12 +161,14 @@ DetailsResolver::Impl::isKernelVersion3OrHigher()
if (is_gogo.ok() && !is_gogo.unpack().empty()) { if (is_gogo.ok() && !is_gogo.unpack().empty()) {
return is_gogo.unpack().front() == '1'; return is_gogo.unpack().front() == '1';
} }
#endif
return false; return false;
} }
bool bool
DetailsResolver::Impl::isGwNotVsx() DetailsResolver::Impl::isGwNotVsx()
{ {
#if defined(gaia) || defined(smb)
static const string is_gw_cmd = "cpprod_util FwIsFirewallModule"; static const string is_gw_cmd = "cpprod_util FwIsFirewallModule";
static const string is_vsx_cmd = "cpprod_util FWisVSX"; static const string is_vsx_cmd = "cpprod_util FWisVSX";
auto is_gw = DetailsResolvingHanlder::getCommandOutput(is_gw_cmd); auto is_gw = DetailsResolvingHanlder::getCommandOutput(is_gw_cmd);
@@ -173,6 +176,7 @@ DetailsResolver::Impl::isGwNotVsx()
if (is_gw.ok() && is_vsx.ok() && !is_gw.unpack().empty() && !is_vsx.unpack().empty()) { if (is_gw.ok() && is_vsx.ok() && !is_gw.unpack().empty() && !is_vsx.unpack().empty()) {
return is_gw.unpack().front() == '1' && is_vsx.unpack().front() == '0'; return is_gw.unpack().front() == '1' && is_vsx.unpack().front() == '0';
} }
#endif
return false; return false;
} }
@@ -300,19 +304,26 @@ DetailsResolver::Impl::parseNginxMetadata()
return make_tuple(config_opt, cc_opt, nginx_version); return make_tuple(config_opt, cc_opt, nginx_version);
} }
Maybe<tuple<string, string, string>> Maybe<tuple<string, string, string, string, string>>
DetailsResolver::Impl::readCloudMetadata() DetailsResolver::Impl::readCloudMetadata()
{ {
auto env_read_cloud_metadata = []() -> Maybe<tuple<string, string, string>> { auto env_read_cloud_metadata = []() -> Maybe<tuple<string, string, string, string, string>> {
string account_id = getenv("CLOUD_ACCOUNT_ID") ? getenv("CLOUD_ACCOUNT_ID") : ""; string account_id = getenv("CLOUD_ACCOUNT_ID") ? getenv("CLOUD_ACCOUNT_ID") : "";
string vpc_id = getenv("CLOUD_VPC_ID") ? getenv("CLOUD_VPC_ID") : ""; string vpc_id = getenv("CLOUD_VPC_ID") ? getenv("CLOUD_VPC_ID") : "";
string instance_id = getenv("CLOUD_INSTANCE_ID") ? getenv("CLOUD_INSTANCE_ID") : ""; string instance_id = getenv("CLOUD_INSTANCE_ID") ? getenv("CLOUD_INSTANCE_ID") : "";
string instance_local_ip = getenv("CLOUD_INSTANCE_LOCAL_IP") ? getenv("CLOUD_INSTANCE_LOCAL_IP") : "";
string region = getenv("CLOUD_REGION") ? getenv("CLOUD_REGION") : "";
if (account_id.empty() || vpc_id.empty() || instance_id.empty()) { if (
account_id.empty() ||
vpc_id.empty() ||
instance_id.empty() ||
instance_local_ip.empty() ||
region.empty()) {
return genError("Could not read cloud metadata"); return genError("Could not read cloud metadata");
} }
return make_tuple(account_id, vpc_id, instance_id); return make_tuple(account_id, vpc_id, instance_id, instance_local_ip, region);
}; };
auto cloud_metadata = env_read_cloud_metadata(); auto cloud_metadata = env_read_cloud_metadata();
@@ -339,7 +350,7 @@ DetailsResolver::Impl::readCloudMetadata()
} }
if (!cloud_metadata.ok()) { if (!cloud_metadata.ok()) {
dbgWarning(D_ORCHESTRATOR) << cloud_metadata.getErr(); dbgDebug(D_ORCHESTRATOR) << cloud_metadata.getErr();
return genError("Failed to fetch cloud metadata"); return genError("Failed to fetch cloud metadata");
} }
@@ -347,9 +358,11 @@ DetailsResolver::Impl::readCloudMetadata()
<< "Successfully fetched cloud metadata: " << "Successfully fetched cloud metadata: "
<< ::get<0>(cloud_metadata.unpack()) << ", " << ::get<0>(cloud_metadata.unpack()) << ", "
<< ::get<1>(cloud_metadata.unpack()) << ", " << ::get<1>(cloud_metadata.unpack()) << ", "
<< ::get<2>(cloud_metadata.unpack()); << ::get<2>(cloud_metadata.unpack()) << ", "
<< ::get<3>(cloud_metadata.unpack()) << ", "
<< ::get<4>(cloud_metadata.unpack());
return cloud_metadata.unpack(); return cloud_metadata;
} }
DetailsResolver::DetailsResolver() : Component("DetailsResolver"), pimpl(make_unique<Impl>()) {} DetailsResolver::DetailsResolver() : Component("DetailsResolver"), pimpl(make_unique<Impl>()) {}

View File

@@ -18,20 +18,24 @@
#include <regex> #include <regex>
#include <boost/regex.hpp> #include <boost/regex.hpp>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <cereal/external/rapidjson/document.h>
#include <cereal/external/rapidjson/filereadstream.h>
#if defined(gaia) #if defined(gaia)
Maybe<string> Maybe<string>
checkSAMLSupportedBlade(const string &command_output) checkSAMLSupportedBlade(const string &command_output)
{ {
string supportedBlades[3] = {"identityServer", "vpn", "cvpn"}; // uncomment when vpn will support SAML authentication
// string supportedBlades[3] = {"identityServer", "vpn", "cvpn"};
string supportedBlades[1] = {"identityServer"};
for(const string &blade : supportedBlades) { for(const string &blade : supportedBlades) {
if (command_output.find(blade) != string::npos) { if (command_output.find(blade) != string::npos) {
return string("true"); return string("true");
} }
} }
return genError("Current host does not have SAML capability"); return string("false");
} }
Maybe<string> Maybe<string>
@@ -42,7 +46,7 @@ checkIDABlade(const string &command_output)
return string("true"); return string("true");
} }
return genError("Current host does not have IDA installed"); return string("false");
} }
Maybe<string> Maybe<string>
@@ -52,33 +56,22 @@ checkSAMLPortal(const string &command_output)
return string("true"); return string("true");
} }
return genError("Current host does not have SAML Portal configured"); return string("false");
} }
Maybe<string> Maybe<string>
checkPepIdaIdnStatus(const string &command_output) checkPepIdaIdnStatus(const string &command_output)
{ {
if (command_output.find("ida_idn_nano_service_enabled=1") != string::npos) { if (command_output.find("nac_pep_identity_next_enabled = 1") != string::npos) {
return string("true"); return string("true");
} }
return string("false");
return genError("Current host does not have PEP control IDA IDN enabled");
} }
Maybe<string> Maybe<string>
checkAgentIntelligence(const string &command_output) getRequiredNanoServices(const string &command_output)
{ {
if (command_output.find("is registered") != string::npos) { return command_output;
return string("true");
}
return genError("Current host does not have agent intelligence installed");
}
Maybe<string>
getIDAGaiaPackages(const string &command_output)
{
return string("idaSaml_gaia;idaIdn_gaia;idaIdnBg_gaia;");
} }
Maybe<string> Maybe<string>
@@ -94,7 +87,7 @@ checkIDP(shared_ptr<istream> file_stream)
} }
} }
return genError("Identity Provider was not found"); return string("false");
} }
#endif // gaia #endif // gaia
@@ -109,6 +102,14 @@ checkIsInstallHorizonTelemetrySucceeded(const string &command_output)
return command_output; return command_output;
} }
Maybe<string>
getOtlpAgentGaiaOsRole(const string &command_output)
{
if (command_output == "" ) return string("-1");
return command_output;
}
Maybe<string> Maybe<string>
getQUID(const string &command_output) getQUID(const string &command_output)
{ {
@@ -120,6 +121,13 @@ getQUID(const string &command_output)
return command_output; return command_output;
} }
Maybe<string>
getIsAiopsRunning(const string &command_output)
{
if (command_output == "" ) return string("false");
return command_output;
}
Maybe<string> Maybe<string>
checkHasSDWan(const string &command_output) checkHasSDWan(const string &command_output)
@@ -196,26 +204,67 @@ getMgmtObjAttr(shared_ptr<istream> file_stream, const string &attr)
} }
Maybe<string> Maybe<string>
getMgmtObjUid(shared_ptr<istream> file_stream) getAttrFromCpsdwanGetDataJson(const string &attr)
{ {
static const std::string get_data_json_path = "/tmp/cpsdwan_getdata_orch.json";
std::ifstream ifs(get_data_json_path);
if (ifs.is_open()) {
rapidjson::IStreamWrapper isw(ifs);
rapidjson::Document document;
document.ParseStream(isw);
if (!document.HasParseError() && document.HasMember(attr.c_str()) && document[attr.c_str()].IsString()) {
return string(document[attr.c_str()].GetString());
}
}
return genError("Attribute " + attr + " was not found in " + get_data_json_path);
}
Maybe<string>
getMgmtObjUid(const string &command_output)
{
if (!command_output.empty()) {
return command_output;
}
Maybe<string> obj_uuid = getAttrFromCpsdwanGetDataJson("uuid");
if (obj_uuid.ok()) {
return obj_uuid.unpack();
}
static const string obj_path = (getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myown.C";
auto file_stream = std::make_shared<std::ifstream>(obj_path);
if (!file_stream->is_open()) {
return genError("Failed to open the object file");
}
return getMgmtObjAttr(file_stream, "uuid "); return getMgmtObjAttr(file_stream, "uuid ");
} }
Maybe<string> 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 "); return getMgmtObjAttr(file_stream, "name ");
} }
Maybe<string> Maybe<string>
getGWHardware(const string &command_output) getHardware(const string &command_output)
{ {
if (!command_output.empty()) { if (!command_output.empty()) {
if (command_output == "software") return string("Open server"); if (command_output == "software") return string("Open server");
if (command_output == "Maestro Gateway") return string("Maestro"); if (command_output == "Maestro Gateway") return string("Maestro");
return string(command_output); return string(command_output);
} }
return genError("GW Hardware was not found"); return genError("Hardware was not found");
} }
Maybe<string> Maybe<string>
@@ -301,7 +350,12 @@ getSmbObjectName(const string &command_output)
if (command_output.empty() || command_output[0] != centrally_managed_comd_output) { if (command_output.empty() || command_output[0] != centrally_managed_comd_output) {
return genError("Object name was not found"); return genError("Object name was not found");
} }
Maybe<string> obj_name = getAttrFromCpsdwanGetDataJson("name");
if (obj_name.ok()) {
return obj_name.unpack();
}
static const string obj_path = (getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myown.C"; static const string obj_path = (getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myown.C";
auto ifs = std::make_shared<std::ifstream>(obj_path); auto ifs = std::make_shared<std::ifstream>(obj_path);
if (!ifs->is_open()) { if (!ifs->is_open()) {

View File

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

View File

@@ -99,6 +99,7 @@ map<string, string>
DetailsResolvingHanlder::Impl::getResolvedDetails() const DetailsResolvingHanlder::Impl::getResolvedDetails() const
{ {
I_ShellCmd *shell = Singleton::Consume<I_ShellCmd>::by<DetailsResolvingHanlder>(); I_ShellCmd *shell = Singleton::Consume<I_ShellCmd>::by<DetailsResolvingHanlder>();
I_AgentDetailsReporter *reporter = Singleton::Consume<I_AgentDetailsReporter>::by<DetailsResolvingHanlder>();
uint32_t timeout = getConfigurationWithDefault<uint32_t>(5000, "orchestration", "Details resolver time out"); uint32_t timeout = getConfigurationWithDefault<uint32_t>(5000, "orchestration", "Details resolver time out");
for (auto &shell_pre_command : shell_pre_commands) { for (auto &shell_pre_command : shell_pre_commands) {
@@ -122,7 +123,15 @@ DetailsResolvingHanlder::Impl::getResolvedDetails() const
Maybe<string> shell_command_output = getCommandOutput(command); Maybe<string> shell_command_output = getCommandOutput(command);
if (!shell_command_output.ok()) continue; if (!shell_command_output.ok()) continue;
Maybe<string> handler_ret = handler(*shell_command_output); Maybe<string> handler_ret = handler(*shell_command_output);
if (handler_ret.ok()) resolved_details[attr] = *handler_ret;
if (handler_ret.ok()) {
resolved_details[attr] = *handler_ret;
} else {
if (reporter->isPersistantAttr(attr)) {
dbgTrace(D_AGENT_DETAILS)<< "Persistent attribute changed, removing old value";
reporter->deleteAttr(attr);
}
}
} }
for (auto file_handler : file_content_handlers) { for (auto file_handler : file_content_handlers) {
@@ -133,7 +142,7 @@ DetailsResolvingHanlder::Impl::getResolvedDetails() const
shared_ptr<ifstream> in_file = shared_ptr<ifstream> in_file =
Singleton::Consume<I_OrchestrationTools>::by<DetailsResolvingHanlder>()->fileStreamWrapper(path); Singleton::Consume<I_OrchestrationTools>::by<DetailsResolvingHanlder>()->fileStreamWrapper(path);
if (!in_file->is_open()) { if (!in_file->is_open()) {
dbgWarning(D_AGENT_DETAILS) << "Could not open file for processing. Path: " << path; dbgDebug(D_AGENT_DETAILS) << "Could not open file for processing. Path: " << path;
continue; continue;
} }
@@ -157,7 +166,6 @@ DetailsResolvingHanlder::Impl::getResolvedDetails() const
} }
} }
I_AgentDetailsReporter *reporter = Singleton::Consume<I_AgentDetailsReporter>::by<DetailsResolvingHanlder>();
reporter->addAttr(resolved_details, true); reporter->addAttr(resolved_details, true);
return resolved_details; return resolved_details;

View File

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

View File

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

View File

@@ -0,0 +1,4 @@
include_directories(${PROJECT_SOURCE_DIR}/core/external_sdk/)
add_library(external_sdk_server external_sdk_server.cc)
add_subdirectory(external_sdk_server_ut)

View File

@@ -0,0 +1,348 @@
#include "external_sdk_server.h"
#include "external_agent_sdk.h"
#include "log_generator.h"
#include "rest_server.h"
#include "generic_metric.h"
#include "customized_cereal_map.h"
#include "report/log_rest.h"
using namespace std;
USE_DEBUG_FLAG(D_EXTERNAL_SDK_USER);
USE_DEBUG_FLAG(D_EXTERNAL_SDK_SERVER);
class ExternalSdkRest : public ServerRest
{
public:
void
doCall() override
{
dbgFlow(D_EXTERNAL_SDK_SERVER);
Maybe<SdkApiType> sdk_event_type = convertToEnum<SdkApiType>(event_type.get());
if (!sdk_event_type.ok()) {
dbgWarning(D_EXTERNAL_SDK_SERVER) << "Received illegal event type. Type : " << event_type.get();
throw JsonError("Illegal event type provided");
}
dbgDebug(D_EXTERNAL_SDK_SERVER)
<< "Handling a new external sdk api call event. Type : "
<< convertApiTypeToString(sdk_event_type.unpack());
I_ExternalSdkServer *sdk_server = Singleton::Consume<I_ExternalSdkServer>::from<ExternalSdkServer>();
switch(sdk_event_type.unpack()) {
case SdkApiType::SendCodeEvent: {
if (!file.isActive()) {
throw JsonError("File was not provided for code event");
}
if (!func.isActive()) {
throw JsonError("Function was not provided for code event");
}
if (!line.isActive()) {
throw JsonError("Line path was not provided for code event");
}
if (!trace_id.isActive()) {
throw JsonError("Trace ID was not provided for code event");
}
if (!span_id.isActive()) {
throw JsonError("Span ID was not provided for code event");
}
if (!message.isActive()) {
throw JsonError("Message was not provided for code event");
}
sdk_server->sendDebug(
file.get(),
func.get(),
line.get(),
getDebugLevel(),
trace_id.get(),
span_id.get(),
message.get(),
additional_fields.isActive() ? additional_fields.get() : map<string, string>()
);
return;
}
case SdkApiType::SendEventDrivenEvent: {
if (!event_name.isActive()) {
throw JsonError("Event name was not provided for event");
}
sdk_server->sendLog(
event_name.get(),
getAudience(),
getSeverity(),
getPriority(),
tag.get(),
additional_fields.isActive() ? additional_fields.get() : map<string, string>()
);
return;
}
case SdkApiType::SendGetConfigRequest: {
if (!config_path.isActive()) {
throw JsonError("Config path was not provided for get configuration event");
}
Maybe<string> config_val = sdk_server->getConfigValue(config_path.get());
config_value = config_val.ok() ? config_val.unpack() : "";
return;
}
case SdkApiType::SendPeriodicEvent: {
if (!event_name.isActive()) {
throw JsonError("Event name was not provided for periodic event");
}
if (!service_name.isActive()) {
throw JsonError("Service name was not provided for periodic event");
}
sdk_server->sendMetric(
event_name,
service_name,
getAudienceTeam(),
ReportIS::IssuingEngine::AGENT_CORE,
additional_fields.isActive() ? additional_fields.get() : map<string, string>()
);
return;
}
default: {
dbgError(D_EXTERNAL_SDK_SERVER) << "Received illegal event type. Type : " << event_type.get();
}
}
}
private:
static string
convertApiTypeToString(SdkApiType type)
{
static const EnumArray<SdkApiType, string> api_type_string {
"Code Event",
"Periodic Event",
"Event Driven",
"Get Configuration",
};
return api_type_string[type];
}
Debug::DebugLevel
getDebugLevel()
{
static const map<int, Debug::DebugLevel> debug_levels = {
{0, Debug::DebugLevel::TRACE},
{1, Debug::DebugLevel::DEBUG},
{2, Debug::DebugLevel::INFO},
{3, Debug::DebugLevel::WARNING},
{4, Debug::DebugLevel::ERROR}
};
if (!debug_level.isActive()) {
throw JsonError("Debug level was not provided for code event");
}
auto level = debug_levels.find(debug_level.get());
if(level == debug_levels.end()) {
throw JsonError("Illegal debug level provided");
}
return level->second;
}
ReportIS::Severity
getSeverity()
{
if (!severity.isActive()) {
throw JsonError("Event severity was not provided for periodic event");
}
switch (severity.get()) {
case EventSeverity::SeverityCritical: return ReportIS::Severity::CRITICAL;
case EventSeverity::SeverityHigh: return ReportIS::Severity::HIGH;
case EventSeverity::SeverityMedium: return ReportIS::Severity::MEDIUM;
case EventSeverity::SeverityLow: return ReportIS::Severity::LOW;
case EventSeverity::SeverityInfo: return ReportIS::Severity::INFO;
default:
throw JsonError("Illegal event severity provided");
}
}
ReportIS::Priority
getPriority()
{
if (!priority.isActive()) {
throw JsonError("Event priority was not provided");
}
switch (priority.get()) {
case EventPriority::PriorityUrgent: return ReportIS::Priority::URGENT;
case EventPriority::PriorityHigh: return ReportIS::Priority::HIGH;
case EventPriority::PriorityMedium: return ReportIS::Priority::MEDIUM;
case EventPriority::PriorityLow: return ReportIS::Priority::LOW;
default:
throw JsonError("Illegal event priority provided");
}
}
ReportIS::Audience
getAudience()
{
if (!audience.isActive()) {
throw JsonError("Event audience was not provided");
}
switch (audience.get()) {
case EventAudience::AudienceSecurity: return ReportIS::Audience::SECURITY;
case EventAudience::AudienceInternal: return ReportIS::Audience::INTERNAL;
default:
throw JsonError("Illegal event audience provided");
}
}
ReportIS::AudienceTeam
getAudienceTeam()
{
if (!team.isActive()) {
throw JsonError("Event audience team was not provided");
}
switch (team.get()) {
case EventAudienceTeam::AudienceTeamAgentCore: return ReportIS::AudienceTeam::AGENT_CORE;
case EventAudienceTeam::AudienceTeamIot: return ReportIS::AudienceTeam::IOT_NEXT;
case EventAudienceTeam::AudienceTeamWaap: return ReportIS::AudienceTeam::WAAP;
case EventAudienceTeam::AudienceTeamAgentIntelligence: return ReportIS::AudienceTeam::AGENT_INTELLIGENCE;
default:
throw JsonError("Illegal event audience team provided");
}
}
using additional_fields_map = map<string, string>;
C2S_LABEL_PARAM(int, event_type, "eventType");
C2S_LABEL_OPTIONAL_PARAM(additional_fields_map, additional_fields, "additionalFields");
C2S_LABEL_OPTIONAL_PARAM(string, event_name, "eventName");
C2S_LABEL_OPTIONAL_PARAM(string, service_name, "serviceName");
C2S_OPTIONAL_PARAM(int, team);
C2S_OPTIONAL_PARAM(int, audience);
C2S_OPTIONAL_PARAM(int, severity);
C2S_OPTIONAL_PARAM(int, priority);
C2S_OPTIONAL_PARAM(string, tag);
C2S_OPTIONAL_PARAM(string, file);
C2S_OPTIONAL_PARAM(string, func);
C2S_OPTIONAL_PARAM(int, line);
C2S_LABEL_OPTIONAL_PARAM(int, debug_level, "debugLevel");
C2S_LABEL_OPTIONAL_PARAM(string, trace_id, "traceId");
C2S_LABEL_OPTIONAL_PARAM(string, span_id, "spanId");
C2S_OPTIONAL_PARAM(string, message);
C2S_LABEL_OPTIONAL_PARAM(string, config_path, "configPath");
S2C_LABEL_OPTIONAL_PARAM(string, config_value, "configValue");
};
class ExternalSdkServer::Impl
:
public Singleton::Provide<I_ExternalSdkServer>::From<ExternalSdkServer>
{
public:
void
init()
{
auto rest = Singleton::Consume<I_RestApi>::by<ExternalSdkServer>();
rest->addRestCall<ExternalSdkRest>(RestAction::ADD, "sdk-call");
}
void
sendLog(
const string &event_name,
ReportIS::Audience audience,
ReportIS::Severity severity,
ReportIS::Priority priority,
const string &tag_string,
const map<string, string> &additional_fields)
{
Maybe<ReportIS::Tags> tag = TagAndEnumManagement::convertStringToTag(tag_string);
set<ReportIS::Tags> tags;
if (tag.ok()) tags.insert(tag.unpack());
LogGen log(event_name, audience, severity, priority, tags);
for (const auto &field : additional_fields) {
log << LogField(field.first, field.second);
}
}
void
sendDebug(
const string &file_name,
const string &function_name,
unsigned int line_number,
Debug::DebugLevel debug_level,
const string &trace_id,
const string &span_id,
const string &message,
const map<string, string> &additional_fields)
{
(void)trace_id;
(void)span_id;
Debug debug(file_name, function_name, line_number, debug_level, D_EXTERNAL_SDK_USER);
debug.getStreamAggr() << message;
bool is_first_key = true;
for (const auto &field : additional_fields) {
if (is_first_key) {
is_first_key = false;
debug.getStreamAggr() << ". ";
} else {
debug.getStreamAggr() << ", ";
}
debug.getStreamAggr() << "\"" << field.first << "\": \"" << field.second << "\"";
}
}
void
sendMetric(
const string &event_title,
const string &service_name,
ReportIS::AudienceTeam team,
ReportIS::IssuingEngine issuing_engine,
const map<string, string> &additional_fields)
{
ScopedContext ctx;
ctx.registerValue("Service Name", service_name);
set<ReportIS::Tags> tags;
Report metric_to_fog(
event_title,
Singleton::Consume<I_TimeGet>::by<GenericMetric>()->getWalltime(),
ReportIS::Type::PERIODIC,
ReportIS::Level::LOG,
ReportIS::LogLevel::INFO,
ReportIS::Audience::INTERNAL,
team,
ReportIS::Severity::INFO,
ReportIS::Priority::LOW,
chrono::seconds(0),
LogField("agentId", Singleton::Consume<I_AgentDetails>::by<GenericMetric>()->getAgentId()),
tags,
ReportIS::Tags::INFORMATIONAL,
issuing_engine
);
for (const auto &field : additional_fields) {
metric_to_fog << LogField(field.first, field.second);
}
LogRest metric_client_rest(metric_to_fog);
string fog_metric_uri = getConfigurationWithDefault<string>("/api/v1/agents/events", "metric", "fogMetricUri");
Singleton::Consume<I_Messaging>::by<ExternalSdkServer>()->sendAsyncMessage(
HTTPMethod::POST,
fog_metric_uri,
metric_client_rest,
MessageCategory::METRIC,
MessageMetadata(),
false
);
}
Maybe<string>
getConfigValue(const string &config_path)
{
auto config_val = getProfileAgentSetting<string>(config_path);
if (!config_val.ok()) {
stringstream error;
error << "Failed to get configuration. Config path: " << config_path << ", Error: " << config_val.getErr();
return genError(error.str());
}
return config_val.unpack();
}
};
ExternalSdkServer::ExternalSdkServer() : Component("ExternalSdkServer"), pimpl(make_unique<Impl>()) {}
ExternalSdkServer::~ExternalSdkServer() {}
void ExternalSdkServer::init() { pimpl->init(); }
void ExternalSdkServer::fini() {}
void ExternalSdkServer::preload() {}

View File

@@ -0,0 +1,7 @@
link_directories(${BOOST_ROOT}/lib)
add_unit_test(
external_sdk_server_ut
"external_sdk_server_ut.cc"
"external_sdk_server;mainloop;singleton;rest;environment;time_proxy;logging;event_is;metric;-lboost_context;agent_details;-lboost_regex;messaging;"
)

View File

@@ -0,0 +1,349 @@
#include <stdio.h>
#include <stdarg.h>
#include "external_sdk_server.h"
#include "cptest.h"
#include "mock/mock_rest_api.h"
#include "mock/mock_messaging.h"
#include "mock/mock_logging.h"
#include "mock/mock_time_get.h"
#include "config.h"
#include "config_component.h"
#include "agent_details.h"
using namespace std;
using namespace testing;
class ExternalSdkServerTest : public Test
{
public:
ExternalSdkServerTest()
{
EXPECT_CALL(rest_mocker, mockRestCall(RestAction::ADD, "sdk-call", _)).WillOnce(
WithArg<2>(
Invoke(
[this](const unique_ptr<RestInit> &rest_ptr)
{
mock_sdk_rest = rest_ptr->getRest();
return true;
}
)
)
);
sdk_server.preload();
sdk_server.init();
i_sdk = Singleton::Consume<I_ExternalSdkServer>::from(sdk_server);
}
~ExternalSdkServerTest()
{
sdk_server.fini();
}
ExternalSdkServer sdk_server;
NiceMock<MockTimeGet> mock_timer;
StrictMock<MockMessaging> messaging_mocker;
StrictMock<MockRestApi> rest_mocker;
StrictMock<MockLogging> log_mocker;
unique_ptr<ServerRest> mock_sdk_rest;
I_ExternalSdkServer *i_sdk;
ConfigComponent conf;
AgentDetails agent_details;
::Environment env;
};
TEST_F(ExternalSdkServerTest, initTest)
{
}
TEST_F(ExternalSdkServerTest, configCall)
{
Maybe<string> no_conf = i_sdk->getConfigValue("key1");
EXPECT_FALSE(no_conf.ok());
string config_json =
"{\n"
"\"agentSettings\": [\n"
"{\n"
"\"id\": \"id1\",\n"
"\"key\": \"key1\",\n"
"\"value\": \"value1\"\n"
"},\n"
"{\n"
"\"id\": \"id1\",\n"
"\"key\": \"key2\",\n"
"\"value\": \"value2\"\n"
"}\n"
"]\n"
"}\n";
conf.preload();
istringstream conf_stream(config_json);
ASSERT_TRUE(Singleton::Consume<Config::I_Config>::from(conf)->loadConfiguration(conf_stream));
Maybe<string> conf_found = i_sdk->getConfigValue("key1");
ASSERT_TRUE(conf_found.ok());
EXPECT_EQ(conf_found.unpack(), "value1");
conf_found = i_sdk->getConfigValue("key2");
ASSERT_TRUE(conf_found.ok());
EXPECT_EQ(conf_found.unpack(), "value2");
stringstream config_call_body;
config_call_body << "{ \"eventType\": 3, \"configPath\": \"key1\" }";
Maybe<string> sdk_conf = mock_sdk_rest->performRestCall(config_call_body);
ASSERT_TRUE(sdk_conf.ok());
EXPECT_EQ(
sdk_conf.unpack(),
"{\n"
" \"configValue\": \"value1\"\n"
"}"
);
}
template <typename T>
string
toJson(const T &obj)
{
stringstream ss;
{
cereal::JSONOutputArchive ar(ss);
obj.serialize(ar);
}
return ss.str();
}
TEST_F(ExternalSdkServerTest, eventDrivenCall)
{
string generated_log;
EXPECT_CALL(log_mocker, getCurrentLogId()).Times(2).WillRepeatedly(Return(0));
EXPECT_CALL(log_mocker, sendLog(_)).Times(2).WillRepeatedly(
WithArg<0>(
Invoke(
[&] (const Report &msg)
{
generated_log = toJson(msg);
}
)
)
);
i_sdk->sendLog(
"my log",
ReportIS::Audience::INTERNAL,
ReportIS::Severity::LOW,
ReportIS::Priority::HIGH,
"IPS",
{{"key1", "value1"}, {"key2", "value2"}}
);
static const string expected_log =
"{\n"
" \"eventTime\": \"\",\n"
" \"eventName\": \"my log\",\n"
" \"eventSeverity\": \"Low\",\n"
" \"eventPriority\": \"High\",\n"
" \"eventType\": \"Event Driven\",\n"
" \"eventLevel\": \"Log\",\n"
" \"eventLogLevel\": \"info\",\n"
" \"eventAudience\": \"Internal\",\n"
" \"eventAudienceTeam\": \"\",\n"
" \"eventFrequency\": 0,\n"
" \"eventTags\": [\n"
" \"IPS\"\n"
" ],\n"
" \"eventSource\": {\n"
" \"agentId\": \"Unknown\",\n"
" \"eventTraceId\": \"\",\n"
" \"eventSpanId\": \"\",\n"
" \"issuingEngineVersion\": \"\",\n"
" \"serviceName\": \"Unnamed Nano Service\"\n"
" },\n"
" \"eventData\": {\n"
" \"logIndex\": 0,\n"
" \"key1\": \"value1\",\n"
" \"key2\": \"value2\"\n"
" }\n"
"}";
EXPECT_EQ(generated_log, expected_log);
string event_call_body =
"{\n"
" \"eventType\": 2,\n"
" \"eventName\": \"my log\",\n"
" \"audience\": 1,\n"
" \"severity\": 3,\n"
" \"priority\": 1,\n"
" \"tag\": \"IPS\",\n"
" \"team\": 3,\n"
" \"additionalFields\": {\n"
" \"key1\": \"value1\",\n"
" \"key2\": \"value2\"\n"
" }\n"
"}";
generated_log = "";
stringstream event_call_stream;
event_call_stream << event_call_body;
EXPECT_TRUE(mock_sdk_rest->performRestCall(event_call_stream).ok());
EXPECT_EQ(generated_log, expected_log);
}
TEST_F(ExternalSdkServerTest, periodicEventCall)
{
string message_body;
EXPECT_CALL(
messaging_mocker,
sendAsyncMessage(
HTTPMethod::POST,
"/api/v1/agents/events",
_,
MessageCategory::METRIC,
_,
false
)
).Times(2).WillRepeatedly(SaveArg<2>(&message_body));
i_sdk->sendMetric(
"my metric",
"matrix",
ReportIS::AudienceTeam::AGENT_INTELLIGENCE,
ReportIS::IssuingEngine::AGENT_CORE,
{{"key", "value"}}
);
static const string expected_message =
"{\n"
" \"log\": {\n"
" \"eventTime\": \"\",\n"
" \"eventName\": \"my metric\",\n"
" \"eventSeverity\": \"Info\",\n"
" \"eventPriority\": \"Low\",\n"
" \"eventType\": \"Periodic\",\n"
" \"eventLevel\": \"Log\",\n"
" \"eventLogLevel\": \"info\",\n"
" \"eventAudience\": \"Internal\",\n"
" \"eventAudienceTeam\": \"Agent Intelligence\",\n"
" \"eventFrequency\": 0,\n"
" \"eventTags\": [\n"
" \"Informational\"\n"
" ],\n"
" \"eventSource\": {\n"
" \"agentId\": \"Unknown\",\n"
" \"issuingEngine\": \"Agent Core\",\n"
" \"eventTraceId\": \"\",\n"
" \"eventSpanId\": \"\",\n"
" \"issuingEngineVersion\": \"\",\n"
" \"serviceName\": \"matrix\"\n"
" },\n"
" \"eventData\": {\n"
" \"key\": \"value\"\n"
" }\n"
" }\n"
"}";
EXPECT_EQ(message_body, expected_message);
string event_call_body =
"{\n"
" \"eventType\": 1,\n"
" \"eventName\": \"my metric\",\n"
" \"serviceName\": \"matrix\",\n"
" \"team\": 3,\n"
" \"additionalFields\": {\n"
" \"key\": \"value\"\n"
" }\n"
"}";
stringstream event_call_stream;
event_call_stream << event_call_body;
message_body = "";
EXPECT_TRUE(mock_sdk_rest->performRestCall(event_call_stream).ok());
EXPECT_EQ(message_body, expected_message);
}
USE_DEBUG_FLAG(D_EXTERNAL_SDK_USER);
USE_DEBUG_FLAG(D_EXTERNAL_SDK_SERVER);
TEST_F(ExternalSdkServerTest, codeEventCall)
{
ostringstream capture_debug;
Debug::setUnitTestFlag(D_EXTERNAL_SDK_SERVER, Debug::DebugLevel::TRACE);
Debug::setUnitTestFlag(D_EXTERNAL_SDK_USER, Debug::DebugLevel::TRACE);
Debug::setNewDefaultStdout(&capture_debug);
i_sdk->sendDebug(
"file.cc",
"myFunc2",
42,
Debug::DebugLevel::TRACE,
"123",
"abc",
"h#l1ow w0r!d",
{{"hi", "universe"}}
);
EXPECT_THAT(
capture_debug.str(),
HasSubstr(
"[myFunc2@file.cc:42 | >>>] "
"h#l1ow w0r!d. \"hi\": \"universe\"\n"
)
);
string debug_event =
"{\n"
" \"eventType\": 0,\n"
" \"file\": \"my file\",\n"
" \"func\": \"function_name\",\n"
" \"line\": 42,\n"
" \"debugLevel\": 0,\n"
" \"traceId\": \"\",\n"
" \"spanId\": \"span2323\",\n"
" \"message\": \"some short debug\",\n"
" \"team\": 1,\n"
" \"additionalFields\": {\n"
" \"name\": \"moshe\",\n"
" \"food\": \"bamba\"\n"
" }\n"
"}";
stringstream event_call_stream;
event_call_stream << debug_event;
EXPECT_TRUE(mock_sdk_rest->performRestCall(event_call_stream).ok());
EXPECT_THAT(
capture_debug.str(),
HasSubstr(
"[function_name@my file:42 | >>>] "
"some short debug. \"food\": \"bamba\", \"name\": \"moshe\"\n"
)
);
Debug::setNewDefaultStdout(&cout);
}
TEST_F(ExternalSdkServerTest, ilegalEventCall)
{
string event_call_body =
"{\n"
" \"eventType\": 7,\n"
" \"eventName\": \"my metric\",\n"
" \"serviceName\": \"matrix\",\n"
" \"team\": 3,\n"
" \"additionalFields\": {\n"
" \"key\": \"value\"\n"
" }\n"
"}";
stringstream event_call_stream;
event_call_stream << event_call_body;
Maybe<string> failed_respond = mock_sdk_rest->performRestCall(event_call_stream);
EXPECT_FALSE(failed_respond.ok());
EXPECT_EQ(failed_respond.getErr(), "Illegal event type provided");
}

View File

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

View File

@@ -3,5 +3,5 @@ link_directories(${BOOST_ROOT}/lib)
add_unit_test( add_unit_test(
health_check_ut health_check_ut
"health_check_ut.cc" "health_check_ut.cc"
"health_check;messaging;mainloop;singleton;agent_details;config;logging;metric;event_is;health_check_manager;-lboost_regex;-lboost_system" "health_check;updates_process_reporter;messaging;mainloop;singleton;agent_details;config;logging;metric;event_is;health_check_manager;-lboost_regex;-lboost_system"
) )

View File

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

View File

@@ -1,3 +1 @@
add_library(health_check_manager health_check_manager.cc) add_library(health_check_manager health_check_manager.cc)
add_subdirectory(health_check_manager_ut)

View File

@@ -21,6 +21,7 @@
#include "config.h" #include "config.h"
#include "cereal/archives/json.hpp" #include "cereal/archives/json.hpp"
#include "customized_cereal_map.h" #include "customized_cereal_map.h"
#include "updates_process_event.h"
using namespace std; using namespace std;
@@ -79,19 +80,22 @@ class HealthCheckValue
public: public:
HealthCheckValue() = default; HealthCheckValue() = default;
HealthCheckValue(HealthCheckStatus raw_status, const map<string, HealthCheckStatusReply> &descriptions) HealthCheckValue(HealthCheckStatus raw_status, const HealthCheckStatusReply &description)
: :
status(raw_status) status(raw_status)
{ {
for (const auto &single_stat : descriptions) { if (description.getStatus() == HealthCheckStatus::HEALTHY) {
if (single_stat.second.getStatus() == HealthCheckStatus::HEALTHY) { dbgTrace(D_HEALTH_CHECK_MANAGER)
dbgTrace(D_HEALTH_CHECK_MANAGER) << "Ignoring healthy status reply. Comp name: " << single_stat.first; << "Ignoring healthy status reply. Comp name: "
continue; << description.getCompName();
} return;
}
for (const auto &status : single_stat.second.getExtendedStatus()) { for (const auto &extended_status : description.getExtendedStatus()) {
errors.push_back(HealthCheckError(single_stat.first + " " + status.first, status.second)); errors.push_back(
} HealthCheckError(description.getCompName() + " " + extended_status.first,
extended_status.second
));
} }
} }
@@ -113,9 +117,9 @@ private:
class HealthCheckPatch : public ClientRest class HealthCheckPatch : public ClientRest
{ {
public: public:
HealthCheckPatch(HealthCheckStatus raw_status, const map<string, HealthCheckStatusReply> &descriptions) HealthCheckPatch(HealthCheckStatus raw_status, const HealthCheckStatusReply &description)
{ {
health_check = HealthCheckValue(raw_status, descriptions); health_check = HealthCheckValue(raw_status, description);
} }
C2S_LABEL_PARAM(HealthCheckValue, health_check, "healthCheck"); C2S_LABEL_PARAM(HealthCheckValue, health_check, "healthCheck");
@@ -123,7 +127,8 @@ public:
class HealthCheckManager::Impl class HealthCheckManager::Impl
: :
Singleton::Provide<I_Health_Check_Manager>::From<HealthCheckManager> Singleton::Provide<I_Health_Check_Manager>::From<HealthCheckManager>,
public Listener<UpdatesProcessEvent>
{ {
public: public:
void void
@@ -132,6 +137,7 @@ public:
auto rest = Singleton::Consume<I_RestApi>::by<HealthCheckManager>(); auto rest = Singleton::Consume<I_RestApi>::by<HealthCheckManager>();
rest->addRestCall<HealthCheckOnDemand>(RestAction::SHOW, "health-check-on-demand"); rest->addRestCall<HealthCheckOnDemand>(RestAction::SHOW, "health-check-on-demand");
registerListener();
int interval_in_seconds = int interval_in_seconds =
getProfileAgentSettingWithDefault<int>(30, "agent.healthCheck.intervalInSeconds"); getProfileAgentSettingWithDefault<int>(30, "agent.healthCheck.intervalInSeconds");
@@ -157,9 +163,62 @@ public:
void void
printRepliesHealthStatus(ofstream &oputput_file) printRepliesHealthStatus(ofstream &oputput_file)
{ {
getRegisteredComponentsHealthStatus();
cereal::JSONOutputArchive ar(oputput_file); cereal::JSONOutputArchive ar(oputput_file);
ar(cereal::make_nvp("allComponentsHealthCheckReplies", all_comps_health_status)); ar(cereal::make_nvp(health_check_reply.getCompName(), health_check_reply));
}
void
upon(const UpdatesProcessEvent &event)
{
OrchestrationStatusFieldType status_field_type = event.getStatusFieldType();
HealthCheckStatus _status = convertResultToHealthCheckStatus(event.getResult());
string status_field_type_str = convertOrchestrationStatusFieldTypeToStr(status_field_type);
extended_status[status_field_type_str] =
_status == HealthCheckStatus::HEALTHY ?
"Success" :
event.parseDescription();
field_types_status[status_field_type_str] = _status;
switch(_status) {
case HealthCheckStatus::UNHEALTHY: {
general_health_aggregated_status = HealthCheckStatus::UNHEALTHY;
break;
}
case HealthCheckStatus::DEGRADED: {
for (const auto &type_status : field_types_status) {
if ((type_status.first != status_field_type_str)
&& (type_status.second == HealthCheckStatus::UNHEALTHY))
{
break;
}
}
general_health_aggregated_status = HealthCheckStatus::DEGRADED;
break;
}
case HealthCheckStatus::HEALTHY: {
for (const auto &type_status : field_types_status) {
if ((type_status.first != status_field_type_str)
&& (type_status.second == HealthCheckStatus::UNHEALTHY
|| type_status.second == HealthCheckStatus::DEGRADED)
)
{
break;
}
general_health_aggregated_status = HealthCheckStatus::HEALTHY;
}
break;
}
case HealthCheckStatus::IGNORED: {
break;
}
}
health_check_reply = HealthCheckStatusReply(
"Orchestration",
general_health_aggregated_status,
extended_status
);
} }
private: private:
@@ -168,9 +227,10 @@ private:
{ {
dbgFlow(D_HEALTH_CHECK_MANAGER) << "Sending a health check patch"; dbgFlow(D_HEALTH_CHECK_MANAGER) << "Sending a health check patch";
HealthCheckPatch patch_to_send(general_health_aggregated_status, all_comps_health_status); HealthCheckPatch patch_to_send(general_health_aggregated_status, health_check_reply);
auto messaging = Singleton::Consume<I_Messaging>::by<HealthCheckManager>(); extended_status.clear();
return messaging->sendSyncMessageWithoutResponse( field_types_status.clear();
return Singleton::Consume<I_Messaging>::by<HealthCheckManager>()->sendSyncMessageWithoutResponse(
HTTPMethod::PATCH, HTTPMethod::PATCH,
"/agents", "/agents",
patch_to_send, patch_to_send,
@@ -178,59 +238,11 @@ private:
); );
} }
void
getRegisteredComponentsHealthStatus()
{
vector<HealthCheckStatusReply> health_check_event_reply = HealthCheckStatusEvent().query();
all_comps_health_status.clear();
for (const auto &reply : health_check_event_reply) {
if (reply.getStatus() != HealthCheckStatus::IGNORED) {
all_comps_health_status.emplace(reply.getCompName(), reply);
}
}
}
void
calcGeneralHealthAggregatedStatus()
{
general_health_aggregated_status = HealthCheckStatus::HEALTHY;
for (const auto &reply : all_comps_health_status) {
HealthCheckStatus status = reply.second.getStatus();
dbgTrace(D_HEALTH_CHECK_MANAGER)
<< "Current aggregated status is: "
<< HealthCheckStatusReply::convertHealthCheckStatusToStr(
general_health_aggregated_status
)
<< ". Got health status: "
<< HealthCheckStatusReply::convertHealthCheckStatusToStr(status)
<< "for component: "
<< reply.first;
switch (status) {
case HealthCheckStatus::UNHEALTHY : {
general_health_aggregated_status = HealthCheckStatus::UNHEALTHY;
return;
}
case HealthCheckStatus::DEGRADED : {
general_health_aggregated_status = HealthCheckStatus::DEGRADED;
break;
}
case HealthCheckStatus::IGNORED : break;
case HealthCheckStatus::HEALTHY : break;
}
}
}
void void
executeHealthCheck() executeHealthCheck()
{ {
dbgFlow(D_HEALTH_CHECK_MANAGER) << "Collecting health status from all registered components."; dbgFlow(D_HEALTH_CHECK_MANAGER) << "Collecting health status from all registered components.";
getRegisteredComponentsHealthStatus();
calcGeneralHealthAggregatedStatus();
dbgTrace(D_HEALTH_CHECK_MANAGER) dbgTrace(D_HEALTH_CHECK_MANAGER)
<< "Aggregated status: " << "Aggregated status: "
<< HealthCheckStatusReply::convertHealthCheckStatusToStr(general_health_aggregated_status); << HealthCheckStatusReply::convertHealthCheckStatusToStr(general_health_aggregated_status);
@@ -244,9 +256,47 @@ private:
}; };
} }
HealthCheckStatus general_health_aggregated_status; string
map<string, HealthCheckStatusReply> all_comps_health_status; convertOrchestrationStatusFieldTypeToStr(OrchestrationStatusFieldType type)
{
switch (type) {
case OrchestrationStatusFieldType::REGISTRATION : return "Registration";
case OrchestrationStatusFieldType::MANIFEST : return "Manifest";
case OrchestrationStatusFieldType::LAST_UPDATE : return "Last Update";
case OrchestrationStatusFieldType::COUNT : return "Count";
}
dbgAssert(false)
<< AlertInfo(AlertTeam::CORE, "orchestration health")
<< "Trying to convert unknown orchestration status field to string.";
return "";
}
HealthCheckStatus
convertResultToHealthCheckStatus(UpdatesProcessResult result)
{
switch (result) {
case UpdatesProcessResult::SUCCESS : return HealthCheckStatus::HEALTHY;
case UpdatesProcessResult::UNSET : return HealthCheckStatus::IGNORED;
case UpdatesProcessResult::FAILED : return HealthCheckStatus::UNHEALTHY;
case UpdatesProcessResult::DEGRADED : return HealthCheckStatus::DEGRADED;
}
dbgAssert(false)
<< AlertInfo(AlertTeam::CORE, "orchestration health")
<< "Trying to convert unknown update process result field to health check status.";
return HealthCheckStatus::IGNORED;
}
HealthCheckStatus general_health_aggregated_status = HealthCheckStatus::HEALTHY;
HealthCheckStatusReply health_check_reply = HealthCheckStatusReply(
"Orchestration",
HealthCheckStatus::HEALTHY,
{}
);
bool should_patch_report; bool should_patch_report;
map<string, string> extended_status;
map<string, HealthCheckStatus> field_types_status;
}; };
HealthCheckManager::HealthCheckManager() : Component("HealthCheckManager"), pimpl(make_unique<Impl>()) {} HealthCheckManager::HealthCheckManager() : Component("HealthCheckManager"), pimpl(make_unique<Impl>()) {}

View File

@@ -13,42 +13,13 @@
#include "mock/mock_mainloop.h" #include "mock/mock_mainloop.h"
#include "mock/mock_messaging.h" #include "mock/mock_messaging.h"
#include "mock/mock_rest_api.h" #include "mock/mock_rest_api.h"
#include "updates_process_event.h"
using namespace std; using namespace std;
using namespace testing; using namespace testing;
USE_DEBUG_FLAG(D_HEALTH_CHECK); USE_DEBUG_FLAG(D_HEALTH_CHECK);
class TestHealthCheckStatusListener : public Listener<HealthCheckStatusEvent>
{
public:
void upon(const HealthCheckStatusEvent &) override {}
HealthCheckStatusReply
respond(const HealthCheckStatusEvent &) override
{
map<string, string> extended_status;
extended_status["team"] = team;
extended_status["city"] = city;
HealthCheckStatusReply reply(comp_name, status, extended_status);
return reply;
}
void setStatus(HealthCheckStatus new_status) { status = new_status; }
string getListenerName() const { return "TestHealthCheckStatusListener"; }
private:
static const string comp_name;
HealthCheckStatus status = HealthCheckStatus::HEALTHY;
static const string team;
static const string city;
};
const string TestHealthCheckStatusListener::comp_name = "Test";
const string TestHealthCheckStatusListener::team = "Hapoel";
const string TestHealthCheckStatusListener::city = "Tel-Aviv";
class TestEnd {}; class TestEnd {};
class HealthCheckManagerTest : public Test class HealthCheckManagerTest : public Test
@@ -56,8 +27,7 @@ class HealthCheckManagerTest : public Test
public: public:
HealthCheckManagerTest() HealthCheckManagerTest()
{ {
Debug::setNewDefaultStdout(&debug_output); Debug::setUnitTestFlag(D_HEALTH_CHECK, Debug::DebugLevel::NOISE);
Debug::setUnitTestFlag(D_HEALTH_CHECK, Debug::DebugLevel::INFO);
EXPECT_CALL(mock_ml, addRecurringRoutine(_, _, _, _, _)).WillRepeatedly( EXPECT_CALL(mock_ml, addRecurringRoutine(_, _, _, _, _)).WillRepeatedly(
DoAll(SaveArg<2>(&health_check_periodic_routine), Return(1)) DoAll(SaveArg<2>(&health_check_periodic_routine), Return(1))
@@ -70,7 +40,6 @@ public:
); );
env.preload(); env.preload();
event_listener.registerListener();
env.init(); env.init();
@@ -98,14 +67,12 @@ public:
StrictMock<MockMainLoop> mock_ml; StrictMock<MockMainLoop> mock_ml;
StrictMock<MockRestApi> mock_rest; StrictMock<MockRestApi> mock_rest;
StrictMock<MockMessaging> mock_message; StrictMock<MockMessaging> mock_message;
stringstream debug_output;
ConfigComponent config; ConfigComponent config;
Config::I_Config *i_config = nullptr; Config::I_Config *i_config = nullptr;
::Environment env; ::Environment env;
HealthCheckManager health_check_manager; HealthCheckManager health_check_manager;
I_Health_Check_Manager *i_health_check_manager; I_Health_Check_Manager *i_health_check_manager;
unique_ptr<ServerRest> health_check_server; unique_ptr<ServerRest> health_check_server;
TestHealthCheckStatusListener event_listener;
}; };
TEST_F(HealthCheckManagerTest, runPeriodicHealthCheckTest) TEST_F(HealthCheckManagerTest, runPeriodicHealthCheckTest)
@@ -142,7 +109,20 @@ TEST_F(HealthCheckManagerTest, runPeriodicHealthCheckTest)
EXPECT_EQ(actual_body, expected_healthy_body); EXPECT_EQ(actual_body, expected_healthy_body);
EXPECT_EQ("Healthy", aggregated_status_str); EXPECT_EQ("Healthy", aggregated_status_str);
event_listener.setStatus(HealthCheckStatus::DEGRADED); UpdatesProcessEvent(
UpdatesProcessResult::DEGRADED,
UpdatesConfigType::SETTINGS,
UpdatesFailureReason::DOWNLOAD_FILE,
"setting.json",
"File not found"
).notify();
UpdatesProcessEvent(
UpdatesProcessResult::DEGRADED,
UpdatesConfigType::MANIFEST,
UpdatesFailureReason::DOWNLOAD_FILE,
"manifest.json",
"File not found"
).notify();
try { try {
health_check_periodic_routine(); health_check_periodic_routine();
} catch (const TestEnd &t) {} } catch (const TestEnd &t) {}
@@ -156,16 +136,16 @@ TEST_F(HealthCheckManagerTest, runPeriodicHealthCheckTest)
" \"status\": \"Degraded\",\n" " \"status\": \"Degraded\",\n"
" \"errors\": [\n" " \"errors\": [\n"
" {\n" " {\n"
" \"code\": \"Test city\",\n" " \"code\": \"Orchestration Last Update\",\n"
" \"message\": [\n" " \"message\": [\n"
" \"Tel-Aviv\"\n" " \"Failed to download the file setting.json. Error: File not found\"\n"
" ],\n" " ],\n"
" \"internal\": true\n" " \"internal\": true\n"
" },\n" " },\n"
" {\n" " {\n"
" \"code\": \"Test team\",\n" " \"code\": \"Orchestration Manifest\",\n"
" \"message\": [\n" " \"message\": [\n"
" \"Hapoel\"\n" " \"Failed to download the file manifest.json. Error: File not found\"\n"
" ],\n" " ],\n"
" \"internal\": true\n" " \"internal\": true\n"
" }\n" " }\n"
@@ -196,19 +176,24 @@ TEST_F(HealthCheckManagerTest, runOnDemandHealthCheckTest)
config.preload(); config.preload();
Singleton::Consume<Config::I_Config>::from(config)->loadConfiguration(ss); Singleton::Consume<Config::I_Config>::from(config)->loadConfiguration(ss);
UpdatesProcessEvent(
UpdatesProcessResult::FAILED,
UpdatesConfigType::MANIFEST,
UpdatesFailureReason::DOWNLOAD_FILE,
"manifest.json",
"File not found"
).notify();
stringstream is; stringstream is;
is << "{}"; is << "{}";
health_check_server->performRestCall(is); health_check_server->performRestCall(is);
string expected_status = string expected_status =
"{\n" "{\n"
" \"allComponentsHealthCheckReplies\": {\n" " \"Orchestration\": {\n"
" \"Test\": {\n" " \"status\": \"Unhealthy\",\n"
" \"status\": \"Healthy\",\n" " \"extendedStatus\": {\n"
" \"extendedStatus\": {\n" " \"Manifest\": \"Failed to download the file manifest.json. Error: File not found\"\n"
" \"city\": \"Tel-Aviv\",\n"
" \"team\": \"Hapoel\"\n"
" }\n"
" }\n" " }\n"
" }\n" " }\n"
"}"; "}";

View File

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

View File

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

View File

@@ -51,6 +51,7 @@ public:
private: private:
I_DeclarativePolicy *i_declarative_policy = nullptr; I_DeclarativePolicy *i_declarative_policy = nullptr;
std::string profile_mode;
}; };
#endif // __FOG_COMMUNICATION_H__ #endif // __FOG_COMMUNICATION_H__

View File

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

View File

@@ -26,6 +26,13 @@ operator<<(std::ostream &os, const Maybe<std::tuple<std::string, std::string, st
return os; return os;
} }
std::ostream &
operator<<(
std::ostream &os, const Maybe<std::tuple<std::string, std::string, std::string, std::string, std::string>> &)
{
return os;
}
class MockDetailsResolver class MockDetailsResolver
: :
public Singleton::Provide<I_DetailsResolver>::From<MockProvider<I_DetailsResolver>> public Singleton::Provide<I_DetailsResolver>::From<MockProvider<I_DetailsResolver>>
@@ -42,7 +49,8 @@ public:
MOCK_METHOD0(getResolvedDetails, std::map<std::string, std::string>()); MOCK_METHOD0(getResolvedDetails, std::map<std::string, std::string>());
MOCK_METHOD0(isVersionAboveR8110, bool()); MOCK_METHOD0(isVersionAboveR8110, bool());
MOCK_METHOD0(parseNginxMetadata, Maybe<std::tuple<std::string, std::string, std::string>>()); MOCK_METHOD0(parseNginxMetadata, Maybe<std::tuple<std::string, std::string, std::string>>());
MOCK_METHOD0(readCloudMetadata, Maybe<std::tuple<std::string, std::string, std::string>>()); MOCK_METHOD0(
readCloudMetadata, Maybe<std::tuple<std::string, std::string, std::string, std::string, std::string>>());
}; };
#endif // __MOCK_DETAILS_RESOLVER_H__ #endif // __MOCK_DETAILS_RESOLVER_H__

View File

@@ -40,6 +40,8 @@ public:
MOCK_CONST_METHOD0(getPolicyVersions, const std::string &()); MOCK_CONST_METHOD0(getPolicyVersions, const std::string &());
MOCK_CONST_METHOD0(getServicesPolicyStatus, bool());
MOCK_METHOD6( MOCK_METHOD6(
updateServiceConfiguration, updateServiceConfiguration,
Maybe<void>( Maybe<void>(
@@ -64,7 +66,7 @@ public:
) )
); );
typedef std::map<std::string, PortNumber> ServicePortMap; typedef std::map<std::string, std::vector<PortNumber>> ServicePortMap;
MOCK_METHOD0(getServiceToPortMap, ServicePortMap()); MOCK_METHOD0(getServiceToPortMap, ServicePortMap());
MOCK_METHOD3(updateReconfStatus, void(int id, const std::string &service_name, ReconfStatus status)); MOCK_METHOD3(updateReconfStatus, void(int id, const std::string &service_name, ReconfStatus status));
MOCK_METHOD4( MOCK_METHOD4(

View File

@@ -0,0 +1,135 @@
// 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 __UPDATES_PROCESS_EVENT_H__
#define __UPDATES_PROCESS_EVENT_H__
#include "event.h"
#include "singleton.h"
#include "config.h"
#include "debug.h"
#include "i_orchestration_status.h"
#include "health_check_status/health_check_status.h"
#include "customized_cereal_map.h"
USE_DEBUG_FLAG(D_UPDATES_PROCESS_REPORTER);
enum class UpdatesFailureReason {
CHECK_UPDATE,
REGISTRATION,
ORCHESTRATION_SELF_UPDATE,
GET_UPDATE_REQUEST,
DOWNLOAD_FILE,
HANDLE_FILE,
INSTALLATION_QUEUE,
INSTALL_PACKAGE,
CHECKSUM_UNMATCHED,
POLICY_CONFIGURATION,
SERVISE_CONFIGURATION,
SERVISE_CONFIGURATION_TIMEOUT,
POLICY_FOG_CONFIGURATION,
NONE
};
enum class UpdatesConfigType { MANIFEST, POLICY, SETTINGS, DATA, GENERAL };
enum class UpdatesProcessResult { UNSET, SUCCESS, FAILED, DEGRADED };
static inline std::string
convertUpdatesFailureReasonToStr(UpdatesFailureReason reason)
{
switch (reason) {
case UpdatesFailureReason::CHECK_UPDATE : return "CHECK_UPDATE";
case UpdatesFailureReason::REGISTRATION : return "REGISTRATION";
case UpdatesFailureReason::ORCHESTRATION_SELF_UPDATE : return "ORCHESTRATION_SELF_UPDATE";
case UpdatesFailureReason::GET_UPDATE_REQUEST : return "GET_UPDATE_REQUEST";
case UpdatesFailureReason::DOWNLOAD_FILE : return "DOWNLOAD_FILE";
case UpdatesFailureReason::HANDLE_FILE : return "HANDLE_FILE";
case UpdatesFailureReason::INSTALLATION_QUEUE : return "INSTALLATION_QUEUE";
case UpdatesFailureReason::INSTALL_PACKAGE : return "INSTALL_PACKAGE";
case UpdatesFailureReason::CHECKSUM_UNMATCHED : return "CHECKSUM_UNMATCHED";
case UpdatesFailureReason::POLICY_CONFIGURATION : return "POLICY_CONFIGURATION";
case UpdatesFailureReason::SERVISE_CONFIGURATION : return "SERVISE_CONFIGURATION";
case UpdatesFailureReason::SERVISE_CONFIGURATION_TIMEOUT : return "SERVISE_CONFIGURATION_TIMEOUT";
case UpdatesFailureReason::POLICY_FOG_CONFIGURATION : return "POLICY_FOG_CONFIGURATION";
case UpdatesFailureReason::NONE : return "NONE";
}
dbgWarning(D_UPDATES_PROCESS_REPORTER) << "Trying to convert unknown updates failure reason to string.";
return "";
}
static inline std::string
convertUpdatesConfigTypeToStr(UpdatesConfigType type)
{
switch (type) {
case UpdatesConfigType::MANIFEST : return "MANIFEST";
case UpdatesConfigType::POLICY : return "POLICY";
case UpdatesConfigType::SETTINGS : return "SETTINGS";
case UpdatesConfigType::DATA : return "DATA";
case UpdatesConfigType::GENERAL : return "GENERAL";
}
dbgWarning(D_UPDATES_PROCESS_REPORTER) << "Trying to convert unknown updates failure reason to string.";
return "";
}
static inline std::string
convertUpdateProcessResultToStr(UpdatesProcessResult result)
{
switch (result) {
case UpdatesProcessResult::SUCCESS : return "SUCCESS";
case UpdatesProcessResult::UNSET : return "UNSET";
case UpdatesProcessResult::FAILED : return "FAILURE";
case UpdatesProcessResult::DEGRADED : return "DEGRADED";
}
dbgWarning(D_UPDATES_PROCESS_REPORTER) << "Trying to convert unknown updates failure reason to string.";
return "";
}
class UpdatesProcessEvent : public Event<UpdatesProcessEvent>
{
public:
UpdatesProcessEvent() {}
UpdatesProcessEvent(
UpdatesProcessResult _result,
UpdatesConfigType _type,
UpdatesFailureReason _reason = UpdatesFailureReason::NONE,
const std::string &_detail = "",
const std::string &_description = "");
~UpdatesProcessEvent() {}
UpdatesProcessResult getResult() const { return result; }
UpdatesConfigType getType() const { return type; }
UpdatesFailureReason getReason() const { return reason; }
std::string getDetail() const { return detail; }
std::string getDescription() const { return description; }
OrchestrationStatusFieldType getStatusFieldType() const;
OrchestrationStatusResult getOrchestrationStatusResult() const;
std::string parseDescription() const;
std::string getDescriptionWithoutErrors() const;
private:
UpdatesProcessResult result;
UpdatesConfigType type;
UpdatesFailureReason reason;
std::string detail;
std::string description;
};
#endif // __UPDATES_PROCESS_EVENT_H__

View File

@@ -0,0 +1,63 @@
// 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 __UPDATES_PROCESS_REPORT_H__
#define __UPDATES_PROCESS_REPORT_H__
#include <sstream>
#include <string>
#include "singleton.h"
#include "i_time_get.h"
#include "updates_process_event.h"
class UpdatesProcessReport : Singleton::Consume<I_TimeGet>
{
public:
UpdatesProcessReport(
UpdatesProcessResult result,
UpdatesConfigType type,
UpdatesFailureReason reason,
const std::string &description)
:
result(result), type(type), reason(reason), description(description)
{
time_stamp = Singleton::Consume<I_TimeGet>::by<UpdatesProcessReport>()->getWalltimeStr();
}
std::string
toString() const
{
std::stringstream report;
report
<< "["
<< time_stamp << "] - "
<< convertUpdateProcessResultToStr(result) << " | "
<< convertUpdatesConfigTypeToStr(type) << " | "
<< convertUpdatesFailureReasonToStr(reason) << " | "
<< description;
return report.str();
}
UpdatesFailureReason getReason() const { return reason; }
private:
UpdatesProcessResult result;
UpdatesConfigType type;
UpdatesFailureReason reason;
std::string description;
std::string time_stamp;
};
#endif // __UPDATES_PROCESS_EVENT_H__

View File

@@ -0,0 +1,44 @@
// 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 __UPDATES_PROCESS_REPORTER_H__
#define __UPDATES_PROCESS_REPORTER_H__
#include <string>
#include "event.h"
#include "singleton.h"
#include "config.h"
#include "debug.h"
#include "i_orchestration_status.h"
#include "i_service_controller.h"
#include "health_check_status/health_check_status.h"
#include "updates_process_event.h"
#include "updates_process_report.h"
class UpdatesProcessReporter
:
public Listener<UpdatesProcessEvent>,
Singleton::Consume<I_ServiceController>
{
public:
void upon(const UpdatesProcessEvent &event) override;
private:
void sendReoprt(const std::string &version);
static std::vector<UpdatesProcessReport> reports;
std::map<std::string, uint> report_failure_count_map;
};
#endif // __UPDATES_PROCESS_REPORTER_H__

View File

@@ -21,6 +21,7 @@
#include "version.h" #include "version.h"
#include "log_generator.h" #include "log_generator.h"
#include "orchestration_comp.h" #include "orchestration_comp.h"
#include "updates_process_event.h"
using namespace std; using namespace std;
using namespace ReportIS; using namespace ReportIS;
@@ -219,6 +220,13 @@ ManifestController::Impl::updateManifest(const string &new_manifest_file)
if (isIgnoreFile(new_manifest_file)) { if (isIgnoreFile(new_manifest_file)) {
if (!orchestration_tools->copyFile(new_manifest_file, manifest_file_path)) { if (!orchestration_tools->copyFile(new_manifest_file, manifest_file_path)) {
dbgWarning(D_ORCHESTRATOR) << "Failed to copy a new manifest file"; dbgWarning(D_ORCHESTRATOR) << "Failed to copy a new manifest file";
UpdatesProcessEvent(
UpdatesProcessResult::FAILED,
UpdatesConfigType::MANIFEST,
UpdatesFailureReason::HANDLE_FILE,
new_manifest_file,
"Failed to copy a new manifest file"
).notify();
return false; return false;
} }
return true; return true;
@@ -237,6 +245,13 @@ ManifestController::Impl::updateManifest(const string &new_manifest_file)
if (!orchestration_tools->copyFile(new_manifest_file, manifest_file_path)) { if (!orchestration_tools->copyFile(new_manifest_file, manifest_file_path)) {
dbgWarning(D_ORCHESTRATOR) << "Failed to copy a new manifest file"; dbgWarning(D_ORCHESTRATOR) << "Failed to copy a new manifest file";
UpdatesProcessEvent(
UpdatesProcessResult::FAILED,
UpdatesConfigType::MANIFEST,
UpdatesFailureReason::HANDLE_FILE,
new_manifest_file,
"Failed to copy a new manifest file"
).notify();
return false; return false;
} }
return true; return true;
@@ -245,6 +260,13 @@ ManifestController::Impl::updateManifest(const string &new_manifest_file)
Maybe<map<string, Package>> parsed_manifest = orchestration_tools->loadPackagesFromJson(new_manifest_file); Maybe<map<string, Package>> parsed_manifest = orchestration_tools->loadPackagesFromJson(new_manifest_file);
if (!parsed_manifest.ok()) { if (!parsed_manifest.ok()) {
dbgWarning(D_ORCHESTRATOR) << "Failed to parse the new manifest file. File: " << new_manifest_file; dbgWarning(D_ORCHESTRATOR) << "Failed to parse the new manifest file. File: " << new_manifest_file;
UpdatesProcessEvent(
UpdatesProcessResult::FAILED,
UpdatesConfigType::MANIFEST,
UpdatesFailureReason::HANDLE_FILE,
new_manifest_file,
"Failed to parse the new manifest file"
).notify();
return false; return false;
} }
@@ -332,6 +354,13 @@ ManifestController::Impl::updateManifest(const string &new_manifest_file)
dbgWarning(D_ORCHESTRATOR) dbgWarning(D_ORCHESTRATOR)
<< "Failed building installation queue. Error: " << "Failed building installation queue. Error: "
<< installation_queue_res.getErr(); << installation_queue_res.getErr();
UpdatesProcessEvent(
UpdatesProcessResult::FAILED,
UpdatesConfigType::MANIFEST,
UpdatesFailureReason::INSTALLATION_QUEUE,
"",
installation_queue_res.getErr()
).notify();
return false; return false;
} }
const vector<Package> &installation_queue = installation_queue_res.unpack(); const vector<Package> &installation_queue = installation_queue_res.unpack();
@@ -447,11 +476,25 @@ ManifestController::Impl::changeManifestFile(const string &new_manifest_file)
dbgDebug(D_ORCHESTRATOR) << "Writing new manifest to file"; dbgDebug(D_ORCHESTRATOR) << "Writing new manifest to file";
if (!orchestration_tools->copyFile(new_manifest_file, manifest_file_path)) { if (!orchestration_tools->copyFile(new_manifest_file, manifest_file_path)) {
dbgWarning(D_ORCHESTRATOR) << "Failed write new manifest to file"; dbgWarning(D_ORCHESTRATOR) << "Failed write new manifest to file";
UpdatesProcessEvent(
UpdatesProcessResult::FAILED,
UpdatesConfigType::MANIFEST,
UpdatesFailureReason::HANDLE_FILE,
new_manifest_file,
"Failed write new manifest to file"
).notify();
return false; return false;
} }
if (!orchestration_tools->isNonEmptyFile(manifest_file_path)) { if (!orchestration_tools->isNonEmptyFile(manifest_file_path)) {
dbgWarning(D_ORCHESTRATOR) << "Failed to get manifest file data"; dbgWarning(D_ORCHESTRATOR) << "Failed to get manifest file data";
UpdatesProcessEvent(
UpdatesProcessResult::FAILED,
UpdatesConfigType::MANIFEST,
UpdatesFailureReason::HANDLE_FILE,
manifest_file_path,
"Failed to get manifest file data"
).notify();
return false; return false;
} }

View File

@@ -1,3 +1,7 @@
#include <sstream>
class Package;
static std::ostream & operator<<(std::ostream &os, const Package &) { return os; }
#include "manifest_controller.h" #include "manifest_controller.h"
#include <vector> #include <vector>
@@ -281,13 +285,7 @@ TEST_F(ManifestControllerTest, badChecksum)
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/packages/my/my")).WillOnce(Return(false)); EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/packages/my/my")).WillOnce(Return(false));
string hostname = "hostname"; string hostname = "hostname";
string empty_err;
EXPECT_CALL(mock_status, getManifestError()).WillOnce(ReturnRef(empty_err));
EXPECT_CALL(mock_details_resolver, getHostname()).WillOnce(Return( Maybe<string>(hostname))); EXPECT_CALL(mock_details_resolver, getHostname()).WillOnce(Return( Maybe<string>(hostname)));
EXPECT_CALL(
mock_status,
setFieldStatus(OrchestrationStatusFieldType::MANIFEST, OrchestrationStatusResult::FAILED, _)
);
EXPECT_FALSE(i_manifest_controller->updateManifest(file_name)); EXPECT_FALSE(i_manifest_controller->updateManifest(file_name));
} }
@@ -710,10 +708,6 @@ TEST_F(ManifestControllerTest, selfUpdateWithOldCopyWithError)
string hostname = "hostname"; string hostname = "hostname";
string empty_err; string empty_err;
EXPECT_CALL(mock_status, getManifestError()).WillOnce(ReturnRef(empty_err)); EXPECT_CALL(mock_status, getManifestError()).WillOnce(ReturnRef(empty_err));
EXPECT_CALL(
mock_status,
setFieldStatus(OrchestrationStatusFieldType::MANIFEST, OrchestrationStatusResult::FAILED, _)
);
load(manifest, new_services); load(manifest, new_services);
EXPECT_CALL(mock_orchestration_tools, EXPECT_CALL(mock_orchestration_tools,
@@ -932,10 +926,6 @@ TEST_F(ManifestControllerTest, badInstall)
string empty_err; string empty_err;
EXPECT_CALL(mock_status, getManifestError()).WillOnce(ReturnRef(empty_err)); EXPECT_CALL(mock_status, getManifestError()).WillOnce(ReturnRef(empty_err));
EXPECT_CALL(mock_details_resolver, getHostname()).WillOnce(Return( Maybe<string>(hostname))); EXPECT_CALL(mock_details_resolver, getHostname()).WillOnce(Return( Maybe<string>(hostname)));
EXPECT_CALL(
mock_status,
setFieldStatus(OrchestrationStatusFieldType::MANIFEST, OrchestrationStatusResult::FAILED, _)
);
string corrupted_packages_manifest = string corrupted_packages_manifest =
"{" "{"
@@ -1008,12 +998,6 @@ TEST_F(ManifestControllerTest, failToDownloadWithselfUpdate)
doesFileExist("/etc/cp/packages/orchestration/orchestration") doesFileExist("/etc/cp/packages/orchestration/orchestration")
).WillOnce(Return(false)); ).WillOnce(Return(false));
EXPECT_CALL(mock_details_resolver, getHostname()).WillOnce(Return(string("hostname"))); EXPECT_CALL(mock_details_resolver, getHostname()).WillOnce(Return(string("hostname")));
EXPECT_CALL(
mock_status,
setFieldStatus(OrchestrationStatusFieldType::MANIFEST, OrchestrationStatusResult::FAILED, _)
);
string not_error;
EXPECT_CALL(mock_status, getManifestError()).WillOnce(ReturnRef(not_error));
EXPECT_FALSE(i_manifest_controller->updateManifest(file_name)); EXPECT_FALSE(i_manifest_controller->updateManifest(file_name));
} }
@@ -1404,12 +1388,6 @@ TEST_F(ManifestControllerTest, failureOnDownloadSharedObject)
).WillOnce(Return(false)); ).WillOnce(Return(false));
EXPECT_CALL(mock_details_resolver, getHostname()).WillOnce(Return(string("hostname"))); EXPECT_CALL(mock_details_resolver, getHostname()).WillOnce(Return(string("hostname")));
EXPECT_CALL(mock_orchestration_tools, removeFile("/tmp/temp_file1")).WillOnce(Return(true)); EXPECT_CALL(mock_orchestration_tools, removeFile("/tmp/temp_file1")).WillOnce(Return(true));
EXPECT_CALL(
mock_status,
setFieldStatus(OrchestrationStatusFieldType::MANIFEST, OrchestrationStatusResult::FAILED, _)
);
string not_error;
EXPECT_CALL(mock_status, getManifestError()).WillOnce(ReturnRef(not_error));
EXPECT_FALSE(i_manifest_controller->updateManifest(file_name)); EXPECT_FALSE(i_manifest_controller->updateManifest(file_name));
} }
@@ -2538,12 +2516,6 @@ TEST_F(ManifestDownloadTest, download_relative_path)
doesFileExist("/etc/cp/packages/orchestration/orchestration") doesFileExist("/etc/cp/packages/orchestration/orchestration")
).WillOnce(Return(false)); ).WillOnce(Return(false));
EXPECT_CALL(mock_details_resolver, getHostname()).WillOnce(Return(string("hostname"))); EXPECT_CALL(mock_details_resolver, getHostname()).WillOnce(Return(string("hostname")));
EXPECT_CALL(
mock_status,
setFieldStatus(OrchestrationStatusFieldType::MANIFEST, OrchestrationStatusResult::FAILED, _)
);
string not_error;
EXPECT_CALL(mock_status, getManifestError()).WillOnce(ReturnRef(not_error));
EXPECT_FALSE(i_manifest_controller->updateManifest(manifest_file.fname)); EXPECT_FALSE(i_manifest_controller->updateManifest(manifest_file.fname));
} }
@@ -2589,8 +2561,6 @@ TEST_F(ManifestDownloadTest, download_relative_path_no_fog_domain)
mock_orchestration_tools, mock_orchestration_tools,
doesFileExist("/etc/cp/packages/orchestration/orchestration") doesFileExist("/etc/cp/packages/orchestration/orchestration")
).WillOnce(Return(false)); ).WillOnce(Return(false));
string not_error;
EXPECT_CALL(mock_status, getManifestError()).WillOnce(ReturnRef(not_error));
checkIfFileExistsCall(new_packages.at("orchestration")); checkIfFileExistsCall(new_packages.at("orchestration"));
@@ -2604,10 +2574,6 @@ TEST_F(ManifestDownloadTest, download_relative_path_no_fog_domain)
) )
).WillOnce(Return(downloaded_package)); ).WillOnce(Return(downloaded_package));
EXPECT_CALL(mock_details_resolver, getHostname()).WillOnce(Return(string("hostname"))); EXPECT_CALL(mock_details_resolver, getHostname()).WillOnce(Return(string("hostname")));
EXPECT_CALL(
mock_status,
setFieldStatus(OrchestrationStatusFieldType::MANIFEST, OrchestrationStatusResult::FAILED, _)
);
EXPECT_FALSE(i_manifest_controller->updateManifest(manifest_file.fname)); EXPECT_FALSE(i_manifest_controller->updateManifest(manifest_file.fname));
} }

View File

@@ -19,6 +19,7 @@
#include "config.h" #include "config.h"
#include "agent_details.h" #include "agent_details.h"
#include "orchestration_comp.h" #include "orchestration_comp.h"
#include "updates_process_event.h"
using namespace std; using namespace std;
@@ -174,14 +175,13 @@ ManifestHandler::downloadPackages(const map<string, Package> &new_packages_to_do
" software update failed. Agent is running previous software. Contact Check Point support."; " software update failed. Agent is running previous software. Contact Check Point support.";
} }
auto orchestration_status = Singleton::Consume<I_OrchestrationStatus>::by<ManifestHandler>(); UpdatesProcessEvent(
if (orchestration_status->getManifestError().find("Gateway was not fully deployed") == string::npos) { UpdatesProcessResult::FAILED,
orchestration_status->setFieldStatus( UpdatesConfigType::MANIFEST,
OrchestrationStatusFieldType::MANIFEST, UpdatesFailureReason::DOWNLOAD_FILE,
OrchestrationStatusResult::FAILED, package.getName(),
install_error install_error
); ).notify();
}
return genError( return genError(
"Failed to download installation package. Package: " + "Failed to download installation package. Package: " +
package.getName() + package.getName() +
@@ -219,11 +219,13 @@ ManifestHandler::installPackage(
err_hostname + err_hostname +
" software update failed. Agent is running previous software. Contact Check Point support."; " software update failed. Agent is running previous software. Contact Check Point support.";
if (orchestration_status->getManifestError().find("Gateway was not fully deployed") == string::npos) { if (orchestration_status->getManifestError().find("Gateway was not fully deployed") == string::npos) {
orchestration_status->setFieldStatus( UpdatesProcessEvent(
OrchestrationStatusFieldType::MANIFEST, UpdatesProcessResult::FAILED,
OrchestrationStatusResult::FAILED, UpdatesConfigType::MANIFEST,
UpdatesFailureReason::INSTALL_PACKAGE,
package_name,
install_error install_error
); ).notify();
} }
} }
return self_update_status; return self_update_status;
@@ -289,11 +291,13 @@ ManifestHandler::installPackage(
auto orchestration_status = Singleton::Consume<I_OrchestrationStatus>::by<ManifestHandler>(); auto orchestration_status = Singleton::Consume<I_OrchestrationStatus>::by<ManifestHandler>();
if (orchestration_status->getManifestError().find("Gateway was not fully deployed") == string::npos) { if (orchestration_status->getManifestError().find("Gateway was not fully deployed") == string::npos) {
orchestration_status->setFieldStatus( UpdatesProcessEvent(
OrchestrationStatusFieldType::MANIFEST, UpdatesProcessResult::FAILED,
OrchestrationStatusResult::FAILED, UpdatesConfigType::MANIFEST,
UpdatesFailureReason::INSTALL_PACKAGE,
package_name,
install_error install_error
); ).notify();
} }
return false; return false;
} }

View File

@@ -43,8 +43,8 @@ TEST_F(PolicyTest, serialization)
ASSERT_TRUE(false) << "Cereal threw an exception: " << e.what(); ASSERT_TRUE(false) << "Cereal threw an exception: " << e.what();
} }
EXPECT_EQ(15, orchestration_policy.getErrorSleepInterval()); EXPECT_EQ(15u, orchestration_policy.getErrorSleepInterval());
EXPECT_EQ(20, orchestration_policy.getSleepInterval()); EXPECT_EQ(20u, orchestration_policy.getSleepInterval());
EXPECT_EQ("http://10.0.0.18:81/control/", orchestration_policy.getFogAddress()); EXPECT_EQ("http://10.0.0.18:81/control/", orchestration_policy.getFogAddress());
} }
@@ -63,8 +63,8 @@ TEST_F(PolicyTest, noAgentType)
ASSERT_TRUE(false) << "Cereal threw an exception: " << e.what(); ASSERT_TRUE(false) << "Cereal threw an exception: " << e.what();
} }
EXPECT_EQ(15, orchestration_policy.getErrorSleepInterval()); EXPECT_EQ(15u, orchestration_policy.getErrorSleepInterval());
EXPECT_EQ(20, orchestration_policy.getSleepInterval()); EXPECT_EQ(20u, orchestration_policy.getSleepInterval());
EXPECT_EQ("http://10.0.0.18:81/control/", orchestration_policy.getFogAddress()); EXPECT_EQ("http://10.0.0.18:81/control/", orchestration_policy.getFogAddress());
} }
@@ -83,8 +83,8 @@ TEST_F(PolicyTest, zeroSleepIntervels)
ASSERT_TRUE(false) << "Cereal threw an exception: " << e.what(); ASSERT_TRUE(false) << "Cereal threw an exception: " << e.what();
} }
EXPECT_EQ(0, orchestration_policy.getErrorSleepInterval()); EXPECT_EQ(0u, orchestration_policy.getErrorSleepInterval());
EXPECT_EQ(0, orchestration_policy.getSleepInterval()); EXPECT_EQ(0u, orchestration_policy.getSleepInterval());
EXPECT_EQ("http://10.0.0.18:81/control/", orchestration_policy.getFogAddress()); EXPECT_EQ("http://10.0.0.18:81/control/", orchestration_policy.getFogAddress());
} }
@@ -152,7 +152,7 @@ TEST_F(PolicyTest, newOptionalFields)
ASSERT_TRUE(false) << "Cereal threw an exception: " << e.what(); ASSERT_TRUE(false) << "Cereal threw an exception: " << e.what();
} }
EXPECT_EQ(10, orchestration_policy.getErrorSleepInterval()); EXPECT_EQ(10u, orchestration_policy.getErrorSleepInterval());
EXPECT_EQ(30, orchestration_policy.getSleepInterval()); EXPECT_EQ(30u, orchestration_policy.getSleepInterval());
EXPECT_EQ("https://fog-api-gw-agents.cloud.ngen.checkpoint.com", orchestration_policy.getFogAddress()); EXPECT_EQ("https://fog-api-gw-agents.cloud.ngen.checkpoint.com", orchestration_policy.getFogAddress());
} }

View File

@@ -1,3 +1,7 @@
#include <sstream>
class Package;
static std::ostream & operator<<(std::ostream &os, const Package &) { return os; }
#include "orchestration_status.h" #include "orchestration_status.h"
#include <string> #include <string>
@@ -13,6 +17,7 @@
#include "mock/mock_agent_details.h" #include "mock/mock_agent_details.h"
#include "mock/mock_mainloop.h" #include "mock/mock_mainloop.h"
#include "mock/mock_rest_api.h" #include "mock/mock_rest_api.h"
#include "updates_process_event.h"
using namespace testing; using namespace testing;
using namespace std; using namespace std;
@@ -200,6 +205,19 @@ TEST_F(OrchestrationStatusTest, checkUpdateStatus)
auto result = orchestrationStatusFileToString(); auto result = orchestrationStatusFileToString();
EXPECT_EQ(buildOrchestrationStatusJSON("attempt time", "Succeeded ", "current time"), result); EXPECT_EQ(buildOrchestrationStatusJSON("attempt time", "Succeeded ", "current time"), result);
} }
TEST_F(OrchestrationStatusTest, checkUpdateStatusByRaiseEvent)
{
init();
EXPECT_CALL(time, getLocalTimeStr())
.WillOnce(Return(string("attempt time")))
.WillOnce(Return(string("current time")));
i_orchestration_status->setLastUpdateAttempt();
UpdatesProcessEvent(UpdatesProcessResult::SUCCESS, UpdatesConfigType::GENERAL).notify();
auto result = orchestrationStatusFileToString();
EXPECT_EQ(buildOrchestrationStatusJSON("attempt time", "Succeeded ", "current time"), result);
}
TEST_F(OrchestrationStatusTest, recoveryFields) TEST_F(OrchestrationStatusTest, recoveryFields)
{ {
@@ -482,3 +500,69 @@ TEST_F(OrchestrationStatusTest, setAllFields)
EXPECT_EQ(i_orchestration_status->getServiceSettings(), service_map_a); EXPECT_EQ(i_orchestration_status->getServiceSettings(), service_map_a);
EXPECT_EQ(i_orchestration_status->getRegistrationDetails(), agent_details); EXPECT_EQ(i_orchestration_status->getRegistrationDetails(), agent_details);
} }
TEST_F(OrchestrationStatusTest, checkErrorByRaiseEvent)
{
init();
string fog_address = "http://fog.address";
string registar_error = "Fail to registar";
string manifest_error = "Fail to achieve manifest";
string last_update_error = "Fail to update";
EXPECT_CALL(time, getLocalTimeStr()).Times(3).WillRepeatedly(Return(string("Time")));
UpdatesProcessEvent(UpdatesProcessResult::SUCCESS, UpdatesConfigType::GENERAL).notify();
i_orchestration_status->setIsConfigurationUpdated(
EnumArray<OrchestrationStatusConfigType, bool>(true, true, true)
);
UpdatesProcessEvent(
UpdatesProcessResult::FAILED,
UpdatesConfigType::GENERAL,
UpdatesFailureReason::NONE,
"",
last_update_error
).notify();
i_orchestration_status->setIsConfigurationUpdated(
EnumArray<OrchestrationStatusConfigType, bool>(false, false, false)
);
i_orchestration_status->setUpgradeMode("Online upgrades");
i_orchestration_status->setFogAddress(fog_address);
i_orchestration_status->setUpgradeMode("Online upgrades");
i_orchestration_status->setFogAddress(fog_address);
UpdatesProcessEvent(
UpdatesProcessResult::FAILED,
UpdatesConfigType::GENERAL,
UpdatesFailureReason::REGISTRATION,
"",
registar_error
).notify();
UpdatesProcessEvent(
UpdatesProcessResult::FAILED,
UpdatesConfigType::MANIFEST,
UpdatesFailureReason::NONE,
"",
manifest_error
).notify();
EXPECT_EQ(i_orchestration_status->getManifestError(), manifest_error);
auto result = orchestrationStatusFileToString();
EXPECT_EQ(
buildOrchestrationStatusJSON(
"None",
"Failed. Reason: " + last_update_error,
"Time",
"Time",
"",
"Time",
"Time",
"Online upgrades",
fog_address,
"Failed. Reason: Registration failed.",
"Failed. Reason: " + manifest_error
),
result
);
}

View File

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

View File

@@ -19,6 +19,8 @@
#include "debug.h" #include "debug.h"
#include "config.h" #include "config.h"
#include "updates_process_event.h"
#include "health_check_status/health_check_status.h"
using namespace cereal; using namespace cereal;
using namespace std; using namespace std;
@@ -383,7 +385,10 @@ private:
map<string, string> service_settings; map<string, string> service_settings;
}; };
class OrchestrationStatus::Impl : Singleton::Provide<I_OrchestrationStatus>::From<OrchestrationStatus> class OrchestrationStatus::Impl
:
Singleton::Provide<I_OrchestrationStatus>::From<OrchestrationStatus>,
public Listener<UpdatesProcessEvent>
{ {
public: public:
void void
@@ -424,14 +429,16 @@ public:
status.insertServiceSetting(service_name, path); status.insertServiceSetting(service_name, path);
return; return;
case OrchestrationStatusConfigType::MANIFEST: 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; break;
case OrchestrationStatusConfigType::DATA: case OrchestrationStatusConfigType::DATA:
return; return;
case OrchestrationStatusConfigType::COUNT: case OrchestrationStatusConfigType::COUNT:
break; break;
} }
dbgAssert(false) << "Unknown configuration file type"; dbgAssert(false) << AlertInfo(AlertTeam::CORE, "sesrvice configuration") << "Unknown configuration file type";
} }
void void
@@ -462,6 +469,17 @@ public:
}, },
"Write Orchestration status file" "Write Orchestration status file"
); );
registerListener();
}
void
upon(const UpdatesProcessEvent &event) override
{
setFieldStatus(
event.getStatusFieldType(),
event.getOrchestrationStatusResult(),
event.getDescriptionWithoutErrors()
);
} }
private: private:

View File

@@ -43,7 +43,10 @@ operator<<(ostream &os, const URLProtocol &protocol)
return os << "file://"; return os << "file://";
} }
default: { 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; return os;
} }
} }
@@ -91,7 +94,10 @@ URLParser::parseURL(const string &url)
return; return;
} }
default: { 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; return;
} }
} }

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