diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index c48e065..ee7bf7d 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -4,7 +4,6 @@ add_subdirectory(signal_handler) add_subdirectory(gradual_deployment) add_subdirectory(packet) add_subdirectory(pending_key) -add_subdirectory(health_check_manager) add_subdirectory(utils) add_subdirectory(attachment-intakers) diff --git a/components/include/report_messaging.h b/components/include/report_messaging.h index 43f2f09..db618ce 100755 --- a/components/include/report_messaging.h +++ b/components/include/report_messaging.h @@ -36,7 +36,6 @@ public: title, audience_team, obj, - false, MessageCategory::GENERIC, std::forward(args)... ) @@ -48,26 +47,6 @@ public: const std::string &title, const ReportIS::AudienceTeam &audience_team, const T &obj, - bool is_async_message, - Args ...args) - : - ReportMessaging( - title, - audience_team, - obj, - is_async_message, - MessageCategory::GENERIC, - std::forward(args)... - ) - { - } - - template - ReportMessaging( - const std::string &title, - const ReportIS::AudienceTeam &audience_team, - const T &obj, - bool is_async_message, const MessageCategory &message_type, Args ...args) : @@ -77,7 +56,6 @@ public: ReportIS::Severity::INFO, ReportIS::Priority::LOW, obj, - is_async_message, message_type, std::forward(args)... ) @@ -99,7 +77,6 @@ public: severity, priority, obj, - false, MessageCategory::GENERIC, std::forward(args)... ) @@ -114,7 +91,6 @@ public: const ReportIS::Severity &severity, const ReportIS::Priority &priority, const T &obj, - bool _is_async_message, const MessageCategory &message_type, Args ...args) : @@ -131,7 +107,6 @@ public: std::chrono::seconds(0), std::forward(args)... ), - is_async_message(_is_async_message), message_type_tag(message_type) { report << LogField("eventObject", obj); @@ -141,11 +116,13 @@ public: ReportMessaging & operator<<(const LogField &field); + Maybe sendReportSynchronously(); + void setForceBuffering(bool _force_buffering); private: Report report; - bool is_async_message; + bool is_async_message = true; bool force_buffering = false; MessageCategory message_type_tag; }; diff --git a/components/report_messaging/report_messaging.cc b/components/report_messaging/report_messaging.cc index 290a1c2..077d3e7 100755 --- a/components/report_messaging/report_messaging.cc +++ b/components/report_messaging/report_messaging.cc @@ -24,6 +24,7 @@ static const string url = "/api/v1/agents/events"; ReportMessaging::~ReportMessaging() { if (!Singleton::exists()) return; + if (!is_async_message) return; LogRest log_rest(report); @@ -47,6 +48,25 @@ ReportMessaging::operator<<(const LogField &field) return *this; } +class LogRestWithReply : public LogRest +{ +public: + LogRestWithReply(const Report &report) : LogRest(report) {} + + bool loadJson(const string &) const { return true; } +}; + +Maybe +ReportMessaging::sendReportSynchronously() +{ + is_async_message = false; + + LogRestWithReply log_rest(report); + + auto messaging = Singleton::Consume::by(); + return messaging->sendSyncMessage(HTTPMethod::POST, url, log_rest, message_type_tag); +} + void ReportMessaging::setForceBuffering(bool _force_buffering) { diff --git a/components/report_messaging/report_messaging_ut/report_messaging_ut.cc b/components/report_messaging/report_messaging_ut/report_messaging_ut.cc index 85a2743..0ecb549 100644 --- a/components/report_messaging/report_messaging_ut/report_messaging_ut.cc +++ b/components/report_messaging/report_messaging_ut/report_messaging_ut.cc @@ -103,7 +103,48 @@ TEST_F(ReportMessagingTest, title_only) _ ) ).Times(1); - ReportMessaging("test", ReportIS::AudienceTeam::AGENT_CORE, 1, true, ReportIS::Tags::ACCESS_CONTROL); + ReportMessaging("test", ReportIS::AudienceTeam::AGENT_CORE, 1, ReportIS::Tags::ACCESS_CONTROL); +} + +TEST_F(ReportMessagingTest, sync_sending) +{ + EXPECT_CALL( + mock_messaging, + sendSyncMessage( + _, + _, + "{\n" + " \"log\": {\n" + " \"eventTime\": \"Best Time ever\",\n" + " \"eventName\": \"test\",\n" + " \"eventSeverity\": \"Info\",\n" + " \"eventPriority\": \"Low\",\n" + " \"eventType\": \"Event Driven\",\n" + " \"eventLevel\": \"Log\",\n" + " \"eventLogLevel\": \"info\",\n" + " \"eventAudience\": \"Internal\",\n" + " \"eventAudienceTeam\": \"Agent Core\",\n" + " \"eventFrequency\": 0,\n" + " \"eventTags\": [\n" + " \"Access Control\"\n" + " ],\n" + " \"eventSource\": {\n" + " \"eventTraceId\": \"\",\n" + " \"eventSpanId\": \"\",\n" + " \"issuingEngineVersion\": \"\",\n" + " \"serviceName\": \"Unnamed Nano Service\"\n" + " },\n" + " \"eventData\": {\n" + " \"eventObject\": 1\n" + " }\n" + " }\n" + "}", + _, + _ + ) + ).WillOnce(Return(HTTPResponse(HTTPStatusCode::HTTP_OK, "response!!"))); + ReportMessaging report("test", ReportIS::AudienceTeam::AGENT_CORE, 1, ReportIS::Tags::ACCESS_CONTROL); + EXPECT_TRUE(report.sendReportSynchronously().ok()); } TEST_F(ReportMessagingTest, with_buffering) @@ -144,7 +185,7 @@ TEST_F(ReportMessagingTest, with_buffering) true ) ).Times(1); - ReportMessaging report("test", ReportIS::AudienceTeam::AGENT_CORE, 1, true, ReportIS::Tags::ACCESS_CONTROL); + ReportMessaging report("test", ReportIS::AudienceTeam::AGENT_CORE, 1, ReportIS::Tags::ACCESS_CONTROL); report.setForceBuffering(true); } diff --git a/components/security_apps/orchestration/CMakeLists.txt b/components/security_apps/orchestration/CMakeLists.txt index 4c500e8..d0c0a2f 100755 --- a/components/security_apps/orchestration/CMakeLists.txt +++ b/components/security_apps/orchestration/CMakeLists.txt @@ -12,6 +12,8 @@ add_subdirectory(manifest_controller) add_subdirectory(update_communication) add_subdirectory(details_resolver) add_subdirectory(health_check) +add_subdirectory(health_check_manager) add_subdirectory(env_details) +add_subdirectory(updates_process_reporter) #add_subdirectory(orchestration_ut) diff --git a/components/security_apps/orchestration/health_check/health_check_ut/CMakeLists.txt b/components/security_apps/orchestration/health_check/health_check_ut/CMakeLists.txt index 8553708..e7ef859 100755 --- a/components/security_apps/orchestration/health_check/health_check_ut/CMakeLists.txt +++ b/components/security_apps/orchestration/health_check/health_check_ut/CMakeLists.txt @@ -3,5 +3,5 @@ link_directories(${BOOST_ROOT}/lib) add_unit_test( health_check_ut "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" ) diff --git a/components/health_check_manager/CMakeLists.txt b/components/security_apps/orchestration/health_check_manager/CMakeLists.txt similarity index 100% rename from components/health_check_manager/CMakeLists.txt rename to components/security_apps/orchestration/health_check_manager/CMakeLists.txt diff --git a/components/health_check_manager/health_check_manager.cc b/components/security_apps/orchestration/health_check_manager/health_check_manager.cc old mode 100755 new mode 100644 similarity index 54% rename from components/health_check_manager/health_check_manager.cc rename to components/security_apps/orchestration/health_check_manager/health_check_manager.cc index ea73d5d..7439acd --- a/components/health_check_manager/health_check_manager.cc +++ b/components/security_apps/orchestration/health_check_manager/health_check_manager.cc @@ -21,6 +21,7 @@ #include "config.h" #include "cereal/archives/json.hpp" #include "customized_cereal_map.h" +#include "updates_process_event.h" using namespace std; @@ -79,19 +80,22 @@ class HealthCheckValue public: HealthCheckValue() = default; - HealthCheckValue(HealthCheckStatus raw_status, const map &descriptions) + HealthCheckValue(HealthCheckStatus raw_status, const HealthCheckStatusReply &description) : status(raw_status) { - for (const auto &single_stat : descriptions) { - if (single_stat.second.getStatus() == HealthCheckStatus::HEALTHY) { - dbgTrace(D_HEALTH_CHECK_MANAGER) << "Ignoring healthy status reply. Comp name: " << single_stat.first; - continue; - } + if (description.getStatus() == HealthCheckStatus::HEALTHY) { + dbgTrace(D_HEALTH_CHECK_MANAGER) + << "Ignoring healthy status reply. Comp name: " + << description.getCompName(); + return; + } - for (const auto &status : single_stat.second.getExtendedStatus()) { - errors.push_back(HealthCheckError(single_stat.first + " " + status.first, status.second)); - } + for (const auto &extended_status : description.getExtendedStatus()) { + errors.push_back( + HealthCheckError(description.getCompName() + " " + extended_status.first, + extended_status.second + )); } } @@ -113,9 +117,9 @@ private: class HealthCheckPatch : public ClientRest { public: - HealthCheckPatch(HealthCheckStatus raw_status, const map &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"); @@ -123,7 +127,8 @@ public: class HealthCheckManager::Impl : - Singleton::Provide::From + Singleton::Provide::From, + public Listener { public: void @@ -132,6 +137,7 @@ public: auto rest = Singleton::Consume::by(); rest->addRestCall(RestAction::SHOW, "health-check-on-demand"); + registerListener(); int interval_in_seconds = getProfileAgentSettingWithDefault(30, "agent.healthCheck.intervalInSeconds"); @@ -157,9 +163,62 @@ public: void printRepliesHealthStatus(ofstream &oputput_file) { - getRegisteredComponentsHealthStatus(); 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: @@ -168,9 +227,10 @@ private: { dbgFlow(D_HEALTH_CHECK_MANAGER) << "Sending a health check patch"; - HealthCheckPatch patch_to_send(general_health_aggregated_status, all_comps_health_status); - auto messaging = Singleton::Consume::by(); - return messaging->sendSyncMessageWithoutResponse( + HealthCheckPatch patch_to_send(general_health_aggregated_status, health_check_reply); + extended_status.clear(); + field_types_status.clear(); + return Singleton::Consume::by()->sendSyncMessageWithoutResponse( HTTPMethod::PATCH, "/agents", patch_to_send, @@ -178,59 +238,11 @@ private: ); } - void - getRegisteredComponentsHealthStatus() - { - vector 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 executeHealthCheck() { dbgFlow(D_HEALTH_CHECK_MANAGER) << "Collecting health status from all registered components."; - getRegisteredComponentsHealthStatus(); - calcGeneralHealthAggregatedStatus(); - dbgTrace(D_HEALTH_CHECK_MANAGER) << "Aggregated status: " << HealthCheckStatusReply::convertHealthCheckStatusToStr(general_health_aggregated_status); @@ -244,9 +256,43 @@ private: }; } - HealthCheckStatus general_health_aggregated_status; - map all_comps_health_status; + string + 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) << "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) << "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; + map extended_status; + map field_types_status; }; HealthCheckManager::HealthCheckManager() : Component("HealthCheckManager"), pimpl(make_unique()) {} diff --git a/components/health_check_manager/health_check_manager_ut/CMakeLists.txt b/components/security_apps/orchestration/health_check_manager/health_check_manager_ut/CMakeLists.txt similarity index 61% rename from components/health_check_manager/health_check_manager_ut/CMakeLists.txt rename to components/security_apps/orchestration/health_check_manager/health_check_manager_ut/CMakeLists.txt index 99d8148..0c49fe2 100755 --- a/components/health_check_manager/health_check_manager_ut/CMakeLists.txt +++ b/components/security_apps/orchestration/health_check_manager/health_check_manager_ut/CMakeLists.txt @@ -4,5 +4,5 @@ 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" + "singleton;updates_process_reporter;messaging;mainloop;health_check_manager;event_is;metric;-lboost_regex" ) diff --git a/components/health_check_manager/health_check_manager_ut/health_check_manager_ut.cc b/components/security_apps/orchestration/health_check_manager/health_check_manager_ut/health_check_manager_ut.cc old mode 100755 new mode 100644 similarity index 74% rename from components/health_check_manager/health_check_manager_ut/health_check_manager_ut.cc rename to components/security_apps/orchestration/health_check_manager/health_check_manager_ut/health_check_manager_ut.cc index 8a69986..a4e59c3 --- a/components/health_check_manager/health_check_manager_ut/health_check_manager_ut.cc +++ b/components/security_apps/orchestration/health_check_manager/health_check_manager_ut/health_check_manager_ut.cc @@ -13,42 +13,13 @@ #include "mock/mock_mainloop.h" #include "mock/mock_messaging.h" #include "mock/mock_rest_api.h" +#include "updates_process_event.h" using namespace std; using namespace testing; USE_DEBUG_FLAG(D_HEALTH_CHECK); -class TestHealthCheckStatusListener : public Listener -{ -public: - void upon(const HealthCheckStatusEvent &) override {} - - HealthCheckStatusReply - respond(const HealthCheckStatusEvent &) override - { - map 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 HealthCheckManagerTest : public Test @@ -56,8 +27,7 @@ class HealthCheckManagerTest : public Test public: HealthCheckManagerTest() { - Debug::setNewDefaultStdout(&debug_output); - Debug::setUnitTestFlag(D_HEALTH_CHECK, Debug::DebugLevel::INFO); + Debug::setUnitTestFlag(D_HEALTH_CHECK, Debug::DebugLevel::NOISE); EXPECT_CALL(mock_ml, addRecurringRoutine(_, _, _, _, _)).WillRepeatedly( DoAll(SaveArg<2>(&health_check_periodic_routine), Return(1)) @@ -70,7 +40,6 @@ public: ); env.preload(); - event_listener.registerListener(); env.init(); @@ -98,14 +67,12 @@ public: StrictMock mock_ml; StrictMock mock_rest; StrictMock mock_message; - stringstream debug_output; ConfigComponent config; Config::I_Config *i_config = nullptr; ::Environment env; HealthCheckManager health_check_manager; I_Health_Check_Manager *i_health_check_manager; unique_ptr health_check_server; - TestHealthCheckStatusListener event_listener; }; TEST_F(HealthCheckManagerTest, runPeriodicHealthCheckTest) @@ -142,7 +109,20 @@ TEST_F(HealthCheckManagerTest, runPeriodicHealthCheckTest) EXPECT_EQ(actual_body, expected_healthy_body); 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 { health_check_periodic_routine(); } catch (const TestEnd &t) {} @@ -156,16 +136,16 @@ TEST_F(HealthCheckManagerTest, runPeriodicHealthCheckTest) " \"status\": \"Degraded\",\n" " \"errors\": [\n" " {\n" - " \"code\": \"Test city\",\n" + " \"code\": \"Orchestration Last Update\",\n" " \"message\": [\n" - " \"Tel-Aviv\"\n" + " \"Failed to download the file setting.json. Error: File not found\"\n" " ],\n" " \"internal\": true\n" " },\n" " {\n" - " \"code\": \"Test team\",\n" + " \"code\": \"Orchestration Manifest\",\n" " \"message\": [\n" - " \"Hapoel\"\n" + " \"Failed to download the file manifest.json. Error: File not found\"\n" " ],\n" " \"internal\": true\n" " }\n" @@ -196,19 +176,24 @@ TEST_F(HealthCheckManagerTest, runOnDemandHealthCheckTest) config.preload(); Singleton::Consume::from(config)->loadConfiguration(ss); + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::MANIFEST, + UpdatesFailureReason::DOWNLOAD_FILE, + "manifest.json", + "File not found" + ).notify(); + stringstream is; is << "{}"; health_check_server->performRestCall(is); string expected_status = "{\n" - " \"allComponentsHealthCheckReplies\": {\n" - " \"Test\": {\n" - " \"status\": \"Healthy\",\n" - " \"extendedStatus\": {\n" - " \"city\": \"Tel-Aviv\",\n" - " \"team\": \"Hapoel\"\n" - " }\n" + " \"Orchestration\": {\n" + " \"status\": \"Unhealthy\",\n" + " \"extendedStatus\": {\n" + " \"Manifest\": \"Failed to download the file manifest.json. Error: File not found\"\n" " }\n" " }\n" "}"; diff --git a/components/security_apps/orchestration/include/updates_process_event.h b/components/security_apps/orchestration/include/updates_process_event.h new file mode 100644 index 0000000..12eab13 --- /dev/null +++ b/components/security_apps/orchestration/include/updates_process_event.h @@ -0,0 +1,130 @@ +// 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, + 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::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 +{ +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; + +private: + UpdatesProcessResult result; + UpdatesConfigType type; + UpdatesFailureReason reason; + std::string detail; + std::string description; + +}; + +#endif // __UPDATES_PROCESS_EVENT_H__ diff --git a/components/security_apps/orchestration/include/updates_process_report.h b/components/security_apps/orchestration/include/updates_process_report.h new file mode 100644 index 0000000..f7d2f0f --- /dev/null +++ b/components/security_apps/orchestration/include/updates_process_report.h @@ -0,0 +1,61 @@ +// 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 +#include + +#include "singleton.h" +#include "i_time_get.h" +#include "updates_process_event.h" + +class UpdatesProcessReport : Singleton::Consume +{ +public: + UpdatesProcessReport( + UpdatesProcessResult result, + UpdatesConfigType type, + UpdatesFailureReason reason, + const std::string &description) + : + result(result), type(type), reason(reason), description(description) + { + time_stamp = Singleton::Consume::by()->getWalltimeStr(); + } + + std::string + toString() const + { + std::stringstream report; + report + << "[" + << time_stamp << "] - " + << convertUpdateProcessResultToStr(result) << " | " + << convertUpdatesConfigTypeToStr(type) << " | " + << convertUpdatesFailureReasonToStr(reason) << " | " + << description; + + return report.str(); + } + +private: + UpdatesProcessResult result; + UpdatesConfigType type; + UpdatesFailureReason reason; + std::string description; + std::string time_stamp; +}; + +#endif // __UPDATES_PROCESS_EVENT_H__ diff --git a/components/security_apps/orchestration/include/updates_process_reporter.h b/components/security_apps/orchestration/include/updates_process_reporter.h new file mode 100644 index 0000000..75567e4 --- /dev/null +++ b/components/security_apps/orchestration/include/updates_process_reporter.h @@ -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 __UPDATES_PROCESS_REPORTER_H__ +#define __UPDATES_PROCESS_REPORTER_H__ + +#include + +#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 "updates_process_event.h" +#include "updates_process_report.h" + +class UpdatesProcessReporter : public Listener +{ +public: + void upon(const UpdatesProcessEvent &event) override; + +private: + void sendReoprt(); + + static std::vector reports; +}; + +#endif // __UPDATES_PROCESS_REPORTER_H__ diff --git a/components/security_apps/orchestration/manifest_controller/manifest_controller.cc b/components/security_apps/orchestration/manifest_controller/manifest_controller.cc index a0662c8..dfc7870 100755 --- a/components/security_apps/orchestration/manifest_controller/manifest_controller.cc +++ b/components/security_apps/orchestration/manifest_controller/manifest_controller.cc @@ -21,6 +21,7 @@ #include "version.h" #include "log_generator.h" #include "orchestration_comp.h" +#include "updates_process_event.h" using namespace std; using namespace ReportIS; @@ -219,6 +220,13 @@ ManifestController::Impl::updateManifest(const string &new_manifest_file) if (isIgnoreFile(new_manifest_file)) { if (!orchestration_tools->copyFile(new_manifest_file, manifest_file_path)) { 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 true; @@ -237,6 +245,13 @@ ManifestController::Impl::updateManifest(const string &new_manifest_file) if (!orchestration_tools->copyFile(new_manifest_file, manifest_file_path)) { 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 true; @@ -245,6 +260,13 @@ ManifestController::Impl::updateManifest(const string &new_manifest_file) Maybe> parsed_manifest = orchestration_tools->loadPackagesFromJson(new_manifest_file); if (!parsed_manifest.ok()) { 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; } @@ -332,6 +354,13 @@ ManifestController::Impl::updateManifest(const string &new_manifest_file) dbgWarning(D_ORCHESTRATOR) << "Failed building installation queue. Error: " << installation_queue_res.getErr(); + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::MANIFEST, + UpdatesFailureReason::INSTALLATION_QUEUE, + "", + installation_queue_res.getErr() + ).notify(); return false; } const vector &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"; if (!orchestration_tools->copyFile(new_manifest_file, manifest_file_path)) { 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; } if (!orchestration_tools->isNonEmptyFile(manifest_file_path)) { 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; } diff --git a/components/security_apps/orchestration/manifest_controller/manifest_controller_ut/manifest_controller_ut.cc b/components/security_apps/orchestration/manifest_controller/manifest_controller_ut/manifest_controller_ut.cc index 1cb2f88..9441867 100755 --- a/components/security_apps/orchestration/manifest_controller/manifest_controller_ut/manifest_controller_ut.cc +++ b/components/security_apps/orchestration/manifest_controller/manifest_controller_ut/manifest_controller_ut.cc @@ -281,13 +281,7 @@ TEST_F(ManifestControllerTest, badChecksum) EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/packages/my/my")).WillOnce(Return(false)); string hostname = "hostname"; - string empty_err; - EXPECT_CALL(mock_status, getManifestError()).WillOnce(ReturnRef(empty_err)); EXPECT_CALL(mock_details_resolver, getHostname()).WillOnce(Return( Maybe(hostname))); - EXPECT_CALL( - mock_status, - setFieldStatus(OrchestrationStatusFieldType::MANIFEST, OrchestrationStatusResult::FAILED, _) - ); EXPECT_FALSE(i_manifest_controller->updateManifest(file_name)); } @@ -710,10 +704,6 @@ TEST_F(ManifestControllerTest, selfUpdateWithOldCopyWithError) string hostname = "hostname"; string empty_err; EXPECT_CALL(mock_status, getManifestError()).WillOnce(ReturnRef(empty_err)); - EXPECT_CALL( - mock_status, - setFieldStatus(OrchestrationStatusFieldType::MANIFEST, OrchestrationStatusResult::FAILED, _) - ); load(manifest, new_services); EXPECT_CALL(mock_orchestration_tools, @@ -932,10 +922,6 @@ TEST_F(ManifestControllerTest, badInstall) string empty_err; EXPECT_CALL(mock_status, getManifestError()).WillOnce(ReturnRef(empty_err)); EXPECT_CALL(mock_details_resolver, getHostname()).WillOnce(Return( Maybe(hostname))); - EXPECT_CALL( - mock_status, - setFieldStatus(OrchestrationStatusFieldType::MANIFEST, OrchestrationStatusResult::FAILED, _) - ); string corrupted_packages_manifest = "{" @@ -1008,12 +994,6 @@ TEST_F(ManifestControllerTest, failToDownloadWithselfUpdate) doesFileExist("/etc/cp/packages/orchestration/orchestration") ).WillOnce(Return(false)); 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)); } @@ -1404,12 +1384,6 @@ TEST_F(ManifestControllerTest, failureOnDownloadSharedObject) ).WillOnce(Return(false)); 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_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)); } @@ -2538,12 +2512,6 @@ TEST_F(ManifestDownloadTest, download_relative_path) doesFileExist("/etc/cp/packages/orchestration/orchestration") ).WillOnce(Return(false)); 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)); } @@ -2589,8 +2557,6 @@ TEST_F(ManifestDownloadTest, download_relative_path_no_fog_domain) mock_orchestration_tools, doesFileExist("/etc/cp/packages/orchestration/orchestration") ).WillOnce(Return(false)); - string not_error; - EXPECT_CALL(mock_status, getManifestError()).WillOnce(ReturnRef(not_error)); checkIfFileExistsCall(new_packages.at("orchestration")); @@ -2604,10 +2570,6 @@ TEST_F(ManifestDownloadTest, download_relative_path_no_fog_domain) ) ).WillOnce(Return(downloaded_package)); 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)); } diff --git a/components/security_apps/orchestration/manifest_controller/manifest_handler.cc b/components/security_apps/orchestration/manifest_controller/manifest_handler.cc index c2cbd7e..e196637 100755 --- a/components/security_apps/orchestration/manifest_controller/manifest_handler.cc +++ b/components/security_apps/orchestration/manifest_controller/manifest_handler.cc @@ -19,6 +19,7 @@ #include "config.h" #include "agent_details.h" #include "orchestration_comp.h" +#include "updates_process_event.h" using namespace std; @@ -174,14 +175,13 @@ ManifestHandler::downloadPackages(const map &new_packages_to_do " software update failed. Agent is running previous software. Contact Check Point support."; } - auto orchestration_status = Singleton::Consume::by(); - if (orchestration_status->getManifestError().find("Gateway was not fully deployed") == string::npos) { - orchestration_status->setFieldStatus( - OrchestrationStatusFieldType::MANIFEST, - OrchestrationStatusResult::FAILED, - install_error - ); - } + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::MANIFEST, + UpdatesFailureReason::DOWNLOAD_FILE, + package.getName(), + install_error + ).notify(); return genError( "Failed to download installation package. Package: " + package.getName() + @@ -219,11 +219,13 @@ ManifestHandler::installPackage( err_hostname + " software update failed. Agent is running previous software. Contact Check Point support."; if (orchestration_status->getManifestError().find("Gateway was not fully deployed") == string::npos) { - orchestration_status->setFieldStatus( - OrchestrationStatusFieldType::MANIFEST, - OrchestrationStatusResult::FAILED, + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::MANIFEST, + UpdatesFailureReason::INSTALL_PACKAGE, + package_name, install_error - ); + ).notify(); } } return self_update_status; @@ -289,11 +291,13 @@ ManifestHandler::installPackage( auto orchestration_status = Singleton::Consume::by(); if (orchestration_status->getManifestError().find("Gateway was not fully deployed") == string::npos) { - orchestration_status->setFieldStatus( - OrchestrationStatusFieldType::MANIFEST, - OrchestrationStatusResult::FAILED, + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::MANIFEST, + UpdatesFailureReason::INSTALL_PACKAGE, + package_name, install_error - ); + ).notify(); } return false; } diff --git a/components/security_apps/orchestration/modules/modules_ut/orchestration_status_ut.cc b/components/security_apps/orchestration/modules/modules_ut/orchestration_status_ut.cc index 6c902ed..08b870c 100755 --- a/components/security_apps/orchestration/modules/modules_ut/orchestration_status_ut.cc +++ b/components/security_apps/orchestration/modules/modules_ut/orchestration_status_ut.cc @@ -13,6 +13,7 @@ #include "mock/mock_agent_details.h" #include "mock/mock_mainloop.h" #include "mock/mock_rest_api.h" +#include "updates_process_event.h" using namespace testing; using namespace std; @@ -200,6 +201,19 @@ TEST_F(OrchestrationStatusTest, checkUpdateStatus) auto result = orchestrationStatusFileToString(); 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) { @@ -482,3 +496,69 @@ TEST_F(OrchestrationStatusTest, setAllFields) EXPECT_EQ(i_orchestration_status->getServiceSettings(), service_map_a); 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(true, true, true) + ); + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::GENERAL, + UpdatesFailureReason::NONE, + "", + last_update_error + ).notify(); + i_orchestration_status->setIsConfigurationUpdated( + EnumArray(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. Error: " + registar_error, + "Failed. Reason: " + manifest_error + ), + result + ); +} diff --git a/components/security_apps/orchestration/modules/orchestration_status.cc b/components/security_apps/orchestration/modules/orchestration_status.cc index 112f868..331a10b 100755 --- a/components/security_apps/orchestration/modules/orchestration_status.cc +++ b/components/security_apps/orchestration/modules/orchestration_status.cc @@ -19,6 +19,8 @@ #include "debug.h" #include "config.h" +#include "updates_process_event.h" +#include "health_check_status/health_check_status.h" using namespace cereal; using namespace std; @@ -383,7 +385,10 @@ private: map service_settings; }; -class OrchestrationStatus::Impl : Singleton::Provide::From +class OrchestrationStatus::Impl + : + Singleton::Provide::From, + public Listener { public: void @@ -462,6 +467,13 @@ public: }, "Write Orchestration status file" ); + registerListener(); + } + + void + upon(const UpdatesProcessEvent &event) override + { + setFieldStatus(event.getStatusFieldType(), event.getOrchestrationStatusResult(), event.parseDescription()); } private: diff --git a/components/security_apps/orchestration/orchestration_comp.cc b/components/security_apps/orchestration/orchestration_comp.cc index eb9f357..6349638 100755 --- a/components/security_apps/orchestration/orchestration_comp.cc +++ b/components/security_apps/orchestration/orchestration_comp.cc @@ -42,6 +42,8 @@ #include "hybrid_communication.h" #include "agent_core_utilities.h" #include "fog_communication.h" +#include "updates_process_event.h" +#include "updates_process_reporter.h" using namespace std; using namespace chrono; @@ -53,85 +55,6 @@ USE_DEBUG_FLAG(D_ORCHESTRATOR); static string fw_last_update_time = ""; #endif // gaia || smb -class HealthCheckStatusListener : public Listener -{ -public: - void upon(const HealthCheckStatusEvent &) override {} - - HealthCheckStatusReply - respond(const HealthCheckStatusEvent &) override - { - return HealthCheckStatusReply(comp_name, status, extended_status); - } - - string getListenerName() const override { return "HealthCheckStatusListener"; } - - void - setStatus( - HealthCheckStatus _status, - OrchestrationStatusFieldType _status_field_type, - const string &_status_description = "Success") - { - string status_field_type_str = convertOrchestrationStatusFieldTypeToStr(_status_field_type); - extended_status[status_field_type_str] = _status_description; - field_types_status[status_field_type_str] = _status; - - switch(_status) { - case HealthCheckStatus::UNHEALTHY: { - status = HealthCheckStatus::UNHEALTHY; - return; - } - case HealthCheckStatus::DEGRADED: { - for (const auto &type_status : field_types_status) { - if ((type_status.first != status_field_type_str) - && (type_status.second == HealthCheckStatus::UNHEALTHY)) - { - return; - } - } - status = HealthCheckStatus::DEGRADED; - return; - } - 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) - ) - { - return; - } - status = HealthCheckStatus::HEALTHY; - } - return; - } - case HealthCheckStatus::IGNORED: { - return; - } - } - } - -private: - string - 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"; - } - - dbgError(D_ORCHESTRATOR) << "Trying to convert unknown orchestration status field to string."; - return ""; - } - - string comp_name = "Orchestration"; - HealthCheckStatus status = HealthCheckStatus::IGNORED; - map extended_status; - map field_types_status; -}; - class SetAgentUninstall : public ServerRest, @@ -257,6 +180,13 @@ private: << "Failed to load Orchestration Policy. Error: " << maybe_policy.getErr() << "Trying to load from backup."; + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::POLICY, + UpdatesFailureReason::POLICY_CONFIGURATION, + orchestration_policy_file, + maybe_policy.getErr() + ).notify(); return loadOrchestrationPolicyFromBackup(); } @@ -280,6 +210,13 @@ private: return maybe_policy; } + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::POLICY, + UpdatesFailureReason::POLICY_CONFIGURATION, + orchestration_policy_file + backup_ext, + maybe_policy.getErr() + ).notify(); return genError("Failed to load Orchestration policy from backup."); } @@ -337,17 +274,13 @@ private: << new_manifest_file.getErr() << " Presenting the next message to the user: " << install_error; - i_orchestration_status->setFieldStatus( - OrchestrationStatusFieldType::MANIFEST, - OrchestrationStatusResult::FAILED, - install_error - ); - - health_check_status_listener.setStatus( - HealthCheckStatus::UNHEALTHY, - OrchestrationStatusFieldType::MANIFEST, - install_error - ); + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::MANIFEST, + UpdatesFailureReason::DOWNLOAD_FILE, + resource_file.getFileName(), + new_manifest_file.getErr() + ).notify(); return genError(install_error); } @@ -372,23 +305,12 @@ private: << "Manifest failed to be updated. Presenting the next message to the user: " << install_error; - health_check_status_listener.setStatus( - HealthCheckStatus::UNHEALTHY, - OrchestrationStatusFieldType::MANIFEST, - install_error - ); - return genError(install_error); } - - i_orchestration_status->setFieldStatus( - OrchestrationStatusFieldType::MANIFEST, - OrchestrationStatusResult::SUCCESS - ); - health_check_status_listener.setStatus( - HealthCheckStatus::HEALTHY, - OrchestrationStatusFieldType::MANIFEST - ); + UpdatesProcessEvent( + UpdatesProcessResult::SUCCESS, + UpdatesConfigType::MANIFEST + ).notify(); ifstream restart_watchdog_orch(filesystem_prefix + "/orchestration/restart_watchdog"); if (restart_watchdog_orch.good()) { @@ -473,6 +395,13 @@ private: if (!updateFogAddress(policy.getFogAddress())) { dbgWarning(D_ORCHESTRATOR) << "Failed to restore the old Fog address."; } + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::POLICY, + UpdatesFailureReason::POLICY_FOG_CONFIGURATION, + orchestration_policy.getFogAddress(), + "Failed to update the new Fog address." + ).notify(); return ""; } @@ -499,13 +428,19 @@ private: // Handling policy update. dbgInfo(D_ORCHESTRATOR) << "There is a new policy file."; GetResourceFile resource_file(GetResourceFile::ResourceFileType::POLICY); - Maybe new_policy_file = - Singleton::Consume::by()->downloadFile( + Maybe new_policy_file = Singleton::Consume::by()->downloadFile( new_policy.unpack(), I_OrchestrationTools::SELECTED_CHECKSUM_TYPE, resource_file ); if (!new_policy_file.ok()) { + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::POLICY, + UpdatesFailureReason::DOWNLOAD_FILE, + resource_file.getFileName(), + new_policy_file.getErr() + ).notify(); return genError("Failed to download the new policy file. Error: " + new_policy_file.getErr()); } @@ -564,6 +499,13 @@ private: << LogField("policyVersion", updated_policy_version) << LogField("previousPolicyVersion", old_policy_version); + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::POLICY, + UpdatesFailureReason::POLICY_CONFIGURATION, + updated_policy_version, + res.getErr() + ).notify(); return genError(error_str); } i_service_controller->moveChangedPolicies(); @@ -648,6 +590,11 @@ private: "Send policy update report" ); + UpdatesProcessEvent( + UpdatesProcessResult::SUCCESS, + UpdatesConfigType::POLICY + ).notify(); + dbgInfo(D_ORCHESTRATOR) << "Policy update report was successfully sent to fog"; return Maybe(); @@ -683,10 +630,24 @@ private: ); if (!new_data_files.ok()) { + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::DATA, + UpdatesFailureReason::DOWNLOAD_FILE, + resource_file.getFileName(), + new_data_files.getErr() + ).notify(); return genError("Failed to download new data file, Error: " + new_data_files.getErr()); } auto new_data_file_input = i_orchestration_tools->readFile(new_data_files.unpack()); if (!new_data_file_input.ok()) { + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::DATA, + UpdatesFailureReason::HANDLE_FILE, + resource_file.getFileName(), + "Failed to read new data file, Error: " + new_data_file_input.getErr() + ).notify(); return genError("Failed to read new data file, Error: " + new_data_file_input.getErr()); } @@ -702,21 +663,35 @@ private: << e.what() << ". Content: " << new_data_files.unpack(); + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::DATA, + UpdatesFailureReason::HANDLE_FILE, + new_data_files.unpack(), + string("Failed to load data from JSON file, Error: ") + e.what() + ).notify(); return genError(e.what()); } for (const auto &data_file : parsed_data) { const string data_file_save_path = getPolicyConfigPath(data_file.first, Config::ConfigFileType::Data); Maybe new_data_file = - Singleton::Consume::by()->downloadFileFromURL( - data_file.second.getDownloadPath(), - data_file.second.getChecksum(), - I_OrchestrationTools::SELECTED_CHECKSUM_TYPE, - "data_" + data_file.first - ); + Singleton::Consume::by()->downloadFileFromURL( + data_file.second.getDownloadPath(), + data_file.second.getChecksum(), + I_OrchestrationTools::SELECTED_CHECKSUM_TYPE, + "data_" + data_file.first + ); if (!new_data_file.ok()) { dbgWarning(D_ORCHESTRATOR) << "Failed to download the " << data_file.first << " data file."; + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::DATA, + UpdatesFailureReason::DOWNLOAD_FILE, + data_file.first, + new_data_file.getErr() + ).notify(); return new_data_file.passErr(); } auto data_new_checksum = getChecksum(new_data_file.unpack()); @@ -729,6 +704,16 @@ private: << data_new_checksum; dbgWarning(D_ORCHESTRATOR) << current_error.str(); + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::DATA, + UpdatesFailureReason::CHECKSUM_UNMATCHED, + data_file.first, + " Expected checksum: " + + data_file.second.getChecksum() + + ". Downloaded checksum: " + + data_new_checksum + ).notify(); return genError(current_error.str()); } if (!i_orchestration_tools->copyFile(new_data_file.unpack(), data_file_save_path)) { @@ -741,6 +726,10 @@ private: dbgWarning(D_ORCHESTRATOR) << "Failed to copy a new agents' data file to " << data_file_path; } + UpdatesProcessEvent( + UpdatesProcessResult::SUCCESS, + UpdatesConfigType::DATA + ).notify(); return Maybe(); } @@ -751,8 +740,7 @@ private: dbgInfo(D_ORCHESTRATOR) << "There is a new settings file."; GetResourceFile resource_file(GetResourceFile::ResourceFileType::SETTINGS); - Maybe new_settings_file = - Singleton::Consume::by()->downloadFile( + Maybe new_settings_file = Singleton::Consume::by()->downloadFile( orch_settings.unpack(), I_OrchestrationTools::SELECTED_CHECKSUM_TYPE, resource_file @@ -762,6 +750,13 @@ private: dbgWarning(D_ORCHESTRATOR) << "Failed to download the new settings file. Error: " << new_settings_file.getErr(); + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::SETTINGS, + UpdatesFailureReason::DOWNLOAD_FILE, + resource_file.getFileName(), + new_settings_file.getErr() + ).notify(); return genError("Failed to download the new settings file. Error: " + new_settings_file.getErr()); } @@ -769,6 +764,10 @@ private: if (res.ok()) { settings_file_path = *res; reloadConfiguration(); + UpdatesProcessEvent( + UpdatesProcessResult::SUCCESS, + UpdatesConfigType::SETTINGS + ).notify(); return Maybe(); } @@ -877,11 +876,13 @@ private: if (!response.ok()) { dbgWarning(D_ORCHESTRATOR) << "Failed to get the update. Error: " << response.getErr(); - i_orchestration_status->setFieldStatus( - OrchestrationStatusFieldType::LAST_UPDATE, - OrchestrationStatusResult::FAILED, + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::GENERAL, + UpdatesFailureReason::GET_UPDATE_REQUEST, + "", "Warning: Agent/Gateway failed during the update process. Contact Check Point support." - ); + ).notify(); return genError(response.getErr()); } @@ -924,10 +925,10 @@ private: OrchSettings orch_settings = response.getSettings(); OrchData orch_data = response.getData(); - i_orchestration_status->setFieldStatus( - OrchestrationStatusFieldType::LAST_UPDATE, - OrchestrationStatusResult::SUCCESS - ); + UpdatesProcessEvent( + UpdatesProcessResult::SUCCESS, + UpdatesConfigType::GENERAL + ).notify(); i_orchestration_status->setIsConfigurationUpdated( EnumArray( orch_manifest.ok(), orch_policy.ok(), orch_settings.ok(), orch_data.ok() @@ -1017,6 +1018,10 @@ private: } if (maybe_errors != "") return genError(maybe_errors); + UpdatesProcessEvent( + UpdatesProcessResult::SUCCESS, + UpdatesConfigType::GENERAL + ).notify(); return Maybe(); } @@ -1196,6 +1201,13 @@ private: dbgTrace(D_ORCHESTRATOR) << "The settings directory is " << settings_file_path; if (!i_orchestration_tools->copyFile(new_settings_file, settings_file_path)) { dbgWarning(D_ORCHESTRATOR) << "Failed to update the settings."; + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::SETTINGS, + UpdatesFailureReason::HANDLE_FILE, + settings_file_path, + "Failed to update the settings" + ).notify(); return genError("Failed to update the settings"); } @@ -1443,20 +1455,24 @@ private: << check_update_result.getErr() << ", new check will be every: " << sleep_interval << " seconds"; - - health_check_status_listener.setStatus( - HealthCheckStatus::UNHEALTHY, - OrchestrationStatusFieldType::LAST_UPDATE, + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::GENERAL, + UpdatesFailureReason::CHECK_UPDATE, + "", "Failed during check update. Error: " + check_update_result.getErr() - ); + ).notify(); return; } failure_count = 0; dbgDebug(D_ORCHESTRATOR) << "Check update process completed successfully"; - health_check_status_listener.setStatus( - HealthCheckStatus::HEALTHY, - OrchestrationStatusFieldType::LAST_UPDATE - ); + UpdatesProcessEvent( + UpdatesProcessResult::SUCCESS, + UpdatesConfigType::GENERAL, + UpdatesFailureReason::CHECK_UPDATE, + "", + "Check update procces succeeded!" + ).notify(); sleep_interval = policy.getSleepInterval(); if (!is_new_success) { dbgInfo(D_ORCHESTRATOR) @@ -1491,11 +1507,13 @@ private: sleep_interval = policy.getErrorSleepInterval(); Maybe registration_status(genError("Not running yet.")); while (!(registration_status = registerToTheFog()).ok()) { - health_check_status_listener.setStatus( - HealthCheckStatus::UNHEALTHY, - OrchestrationStatusFieldType::REGISTRATION, + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::GENERAL, + UpdatesFailureReason::REGISTRATION, + "", registration_status.getErr() - ); + ).notify(); sleep_interval = getConfigurationWithDefault( 30, "orchestration", @@ -1515,10 +1533,11 @@ private: Singleton::Consume::by()->yield(chrono::seconds(1)); - health_check_status_listener.setStatus( - HealthCheckStatus::HEALTHY, - OrchestrationStatusFieldType::REGISTRATION - ); + UpdatesProcessEvent( + UpdatesProcessResult::SUCCESS, + UpdatesConfigType::GENERAL, + UpdatesFailureReason::REGISTRATION + ).notify(); LogGen( "Check Point Orchestration nano service successfully started", @@ -1552,16 +1571,18 @@ private: if (!Singleton::Consume::by()->loadAfterSelfUpdate()) { // Should restore from backup dbgWarning(D_ORCHESTRATOR) << "Failed to load Orchestration after self-update"; - health_check_status_listener.setStatus( - HealthCheckStatus::UNHEALTHY, - OrchestrationStatusFieldType::LAST_UPDATE, + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::GENERAL, + UpdatesFailureReason::ORCHESTRATION_SELF_UPDATE, + "", "Failed to load Orchestration after self-update" - ); + ).notify(); } else { - health_check_status_listener.setStatus( - HealthCheckStatus::HEALTHY, - OrchestrationStatusFieldType::MANIFEST - ); + UpdatesProcessEvent( + UpdatesProcessResult::SUCCESS, + UpdatesConfigType::MANIFEST + ).notify(); } setUpgradeTime(); @@ -1911,7 +1932,7 @@ private: ReportIS::Audience::INTERNAL ); hybrid_mode_metric.registerListener(); - health_check_status_listener.registerListener(); + updates_process_reporter_listener.registerListener(); } void @@ -2024,7 +2045,7 @@ private: unsigned int sleep_interval = 0; bool is_new_success = false; OrchestrationPolicy policy; - HealthCheckStatusListener health_check_status_listener; + UpdatesProcessReporter updates_process_reporter_listener; HybridModeMetric hybrid_mode_metric; EnvDetails env_details; chrono::minutes upgrade_delay_time; diff --git a/components/security_apps/orchestration/orchestration_tools/orchestration_tools.cc b/components/security_apps/orchestration/orchestration_tools/orchestration_tools.cc index 929abfe..4c88c5c 100755 --- a/components/security_apps/orchestration/orchestration_tools/orchestration_tools.cc +++ b/components/security_apps/orchestration/orchestration_tools/orchestration_tools.cc @@ -20,6 +20,7 @@ #include "cereal/types/set.hpp" #include "agent_core_utilities.h" #include "namespace_data.h" +#include "updates_process_event.h" #include #include @@ -469,6 +470,13 @@ OrchestrationTools::Impl::packagesToJsonFile(const map &pa archive_out(cereal::make_nvp("packages", packges_vector)); } catch (cereal::Exception &e) { dbgDebug(D_ORCHESTRATOR) << "Failed to write vector of packages to JSON file " << path << ", " << e.what(); + UpdatesProcessEvent( + UpdatesProcessResult::FAILED, + UpdatesConfigType::MANIFEST, + UpdatesFailureReason::HANDLE_FILE, + path, + string("Failed to write vector of packages to JSON file. Error: ") + e.what() + ).notify(); return false; } return true; diff --git a/components/security_apps/orchestration/orchestration_ut/orchestration_ut.cc b/components/security_apps/orchestration/orchestration_ut/orchestration_ut.cc index edc9c3e..1775f68 100755 --- a/components/security_apps/orchestration/orchestration_ut/orchestration_ut.cc +++ b/components/security_apps/orchestration/orchestration_ut/orchestration_ut.cc @@ -22,6 +22,7 @@ #include "agent_details.h" #include "customized_cereal_map.h" #include "health_check_status/health_check_status.h" +#include "updates_process_event.h" #include "declarative_policy_utils.h" using namespace testing; @@ -358,6 +359,7 @@ private: TEST_F(OrchestrationTest, hybridModeRegisterLocalAgentRoutine) { EXPECT_CALL(rest, mockRestCall(_, _, _)).WillRepeatedly(Return(true)); + Singleton::Consume::from(config_comp)->loadConfiguration( vector{"--orchestration-mode=hybrid_mode"} ); @@ -376,7 +378,6 @@ TEST_F(OrchestrationTest, hybridModeRegisterLocalAgentRoutine) expectDetailsResolver(); EXPECT_CALL(mock_update_communication, getUpdate(_)); EXPECT_CALL(mock_status, setLastUpdateAttempt()); - EXPECT_CALL(mock_status, setFieldStatus(_, _, _)); EXPECT_CALL(mock_status, setIsConfigurationUpdated(_)); EXPECT_CALL(mock_ml, yield(A())) @@ -584,7 +585,6 @@ TEST_F(OrchestrationTest, check_sending_registration_data) expectDetailsResolver(); EXPECT_CALL(mock_update_communication, getUpdate(_)); EXPECT_CALL(mock_status, setLastUpdateAttempt()); - EXPECT_CALL(mock_status, setFieldStatus(_, _, _)); EXPECT_CALL(mock_status, setIsConfigurationUpdated(_)); EXPECT_CALL(mock_ml, yield(A())) @@ -761,10 +761,6 @@ TEST_F(OrchestrationTest, orchestrationPolicyUpdatRollback) ).WillOnce(Return(true)); EXPECT_CALL(mock_update_communication, setAddressExtenesion("/test")); EXPECT_CALL(mock_status, setLastUpdateAttempt()); - EXPECT_CALL( - mock_status, - setFieldStatus(OrchestrationStatusFieldType::LAST_UPDATE, OrchestrationStatusResult::SUCCESS, "") - ); EXPECT_CALL(mock_status, setIsConfigurationUpdated(A>()) ).WillOnce( Invoke( @@ -940,10 +936,6 @@ TEST_F(OrchestrationTest, orchestrationPolicyUpdate) ).WillOnce(Return(true)); EXPECT_CALL(mock_update_communication, setAddressExtenesion("/test")); EXPECT_CALL(mock_status, setLastUpdateAttempt()); - EXPECT_CALL( - mock_status, - setFieldStatus(OrchestrationStatusFieldType::LAST_UPDATE, OrchestrationStatusResult::SUCCESS, "") - ); EXPECT_CALL(mock_status, setIsConfigurationUpdated(A>()) ).WillOnce( Invoke( @@ -1108,14 +1100,6 @@ TEST_F(OrchestrationTest, manifestUpdate) ); EXPECT_CALL(mock_status, setLastUpdateAttempt()); - EXPECT_CALL( - mock_status, - setFieldStatus(OrchestrationStatusFieldType::LAST_UPDATE, OrchestrationStatusResult::SUCCESS, "") - ); - EXPECT_CALL( - mock_status, - setFieldStatus(OrchestrationStatusFieldType::MANIFEST, OrchestrationStatusResult::SUCCESS, "") - ); EXPECT_CALL(mock_status, setIsConfigurationUpdated(A>()) ).WillOnce( Invoke( @@ -1237,10 +1221,6 @@ TEST_F(OrchestrationTest, getBadPolicyUpdate) .WillOnce(ReturnRef(second_val) ); EXPECT_CALL(mock_status, setLastUpdateAttempt()); - EXPECT_CALL( - mock_status, - setFieldStatus(OrchestrationStatusFieldType::LAST_UPDATE, OrchestrationStatusResult::SUCCESS, "") - ); EXPECT_CALL(mock_status, setIsConfigurationUpdated(A>()) ).WillOnce( Invoke( @@ -1271,7 +1251,7 @@ TEST_F(OrchestrationTest, getBadPolicyUpdate) EXPECT_CALL( mock_service_controller, updateServiceConfiguration(string("policy path"), "", expected_data_types, "", "", _) - ).WillOnce(Return(Maybe(genError(string(""))))); + ).WillOnce(Return(Maybe(genError(string("Fail to load policy"))))); EXPECT_CALL(mock_ml, yield(A())) .WillOnce( @@ -1328,6 +1308,7 @@ TEST_F(OrchestrationTest, failedDownloadSettings) EXPECT_CALL(mock_update_communication, authenticateAgent()).WillOnce(Return(Maybe())); expectDetailsResolver(); + EXPECT_CALL(mock_manifest_controller, loadAfterSelfUpdate()).WillOnce(Return(false)); EXPECT_CALL(mock_orchestration_tools, calculateChecksum(Package::ChecksumTypes::SHA256, manifest_file_path)) .WillOnce(Return(manifest_checksum)); @@ -1359,22 +1340,10 @@ TEST_F(OrchestrationTest, failedDownloadSettings) ); EXPECT_CALL(mock_status, setLastUpdateAttempt()); - EXPECT_CALL( - mock_status, - setFieldStatus(OrchestrationStatusFieldType::LAST_UPDATE, OrchestrationStatusResult::SUCCESS, "") - ).Times(1); string manifest_err = "Critical Error: Agent/Gateway was not fully deployed on host 'hostname' " "and is not enforcing a security policy. Retry installation or contact Check Point support."; - EXPECT_CALL( - mock_status, - setFieldStatus( - OrchestrationStatusFieldType::MANIFEST, - OrchestrationStatusResult::FAILED, - manifest_err - ) - ).Times(1); EXPECT_CALL(mock_status, getManifestError()).WillOnce(ReturnRef(manifest_err)); EXPECT_CALL(mock_status, setIsConfigurationUpdated(A>()) @@ -1475,10 +1444,6 @@ TEST_P(OrchestrationTest, orchestrationFirstRun) .WillOnce(Return(data_checksum)); EXPECT_CALL(mock_status, setLastUpdateAttempt()); - EXPECT_CALL( - mock_status, - setFieldStatus(OrchestrationStatusFieldType::LAST_UPDATE, OrchestrationStatusResult::SUCCESS, "") - ); EXPECT_CALL(mock_status, setIsConfigurationUpdated(A>()) ).WillOnce( Invoke( @@ -1537,23 +1502,6 @@ TEST_P(OrchestrationTest, orchestrationFirstRun) } catch (const invalid_argument& e) {} EXPECT_CALL(mock_status, writeStatusToFile()); - vector reply; - bool is_named_query = GetParam(); - if (is_named_query) { - auto all_comps_status_reply = HealthCheckStatusEvent().performNamedQuery(); - for (auto &elem : all_comps_status_reply) { - reply.push_back(elem.second); - } - } else { - reply = HealthCheckStatusEvent().query(); - } - - ASSERT_EQ(reply.size(), 1); - EXPECT_EQ(reply[0].getCompName(), "Orchestration"); - EXPECT_EQ(reply[0].getStatus(), HealthCheckStatus::HEALTHY); - - HealthCheckStatusEvent().notify(); - orchestration_comp.fini(); } @@ -1721,10 +1669,6 @@ TEST_F(OrchestrationTest, dataUpdate) ); EXPECT_CALL(mock_status, setLastUpdateAttempt()); - EXPECT_CALL( - mock_status, - setFieldStatus(OrchestrationStatusFieldType::LAST_UPDATE, OrchestrationStatusResult::SUCCESS, "") - ); EXPECT_CALL(mock_status, setIsConfigurationUpdated(A>()) ).WillOnce( Invoke( diff --git a/components/security_apps/orchestration/update_communication/update_communication.cc b/components/security_apps/orchestration/update_communication/update_communication.cc index 95a3390..cebea89 100755 --- a/components/security_apps/orchestration/update_communication/update_communication.cc +++ b/components/security_apps/orchestration/update_communication/update_communication.cc @@ -32,6 +32,7 @@ using namespace std; USE_DEBUG_FLAG(D_ORCHESTRATOR); + class UpdateCommunication::Impl : public ServerRest, diff --git a/components/security_apps/orchestration/updates_process_reporter/CMakeLists.txt b/components/security_apps/orchestration/updates_process_reporter/CMakeLists.txt new file mode 100644 index 0000000..94357a8 --- /dev/null +++ b/components/security_apps/orchestration/updates_process_reporter/CMakeLists.txt @@ -0,0 +1 @@ +add_library(updates_process_reporter updates_process_event.cc updates_process_reporter.cc) diff --git a/components/security_apps/orchestration/updates_process_reporter/updates_process_event.cc b/components/security_apps/orchestration/updates_process_reporter/updates_process_event.cc new file mode 100644 index 0000000..b6afa5b --- /dev/null +++ b/components/security_apps/orchestration/updates_process_reporter/updates_process_event.cc @@ -0,0 +1,124 @@ +// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved. + +// Licensed under the Apache License, Version 2.0 (the "License"); +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "updates_process_event.h" + +#include +#include + +#include "debug.h" + +using namespace std; + +USE_DEBUG_FLAG(D_UPDATES_PROCESS_REPORTER); + +UpdatesProcessEvent::UpdatesProcessEvent( + UpdatesProcessResult _result, + UpdatesConfigType _type, + UpdatesFailureReason _reason, + const std::string &_detail, + const std::string &_description) + : + result(_result), + type(_type), + reason(_reason), + detail(_detail), + description(_description) +{ + string report = + "Result: " + convertUpdateProcessResultToStr(result) + + ", Reason: " + convertUpdatesFailureReasonToStr(reason) + + ", Type: " + convertUpdatesConfigTypeToStr(type) + + ", Detail: " + detail + + ", Description: " + description; + dbgTrace(D_UPDATES_PROCESS_REPORTER) << "Updates process event: " << report; +} + +OrchestrationStatusFieldType +UpdatesProcessEvent::getStatusFieldType() const +{ + if (reason == UpdatesFailureReason::REGISTRATION) { + return OrchestrationStatusFieldType::REGISTRATION; + } + if (type == UpdatesConfigType::MANIFEST) { + return OrchestrationStatusFieldType::MANIFEST; + } + return OrchestrationStatusFieldType::LAST_UPDATE; +} + +OrchestrationStatusResult +UpdatesProcessEvent::getOrchestrationStatusResult() const +{ + return result == UpdatesProcessResult::SUCCESS ? + OrchestrationStatusResult::SUCCESS : + OrchestrationStatusResult::FAILED; +} + +string +UpdatesProcessEvent::parseDescription() const +{ + stringstream err; + if (description.empty() || result == UpdatesProcessResult::SUCCESS) return ""; + + switch (reason) { + case UpdatesFailureReason::CHECK_UPDATE: { + err << description; + break; + } + case UpdatesFailureReason::REGISTRATION: { + err << "Registration failed. Error: " << description; + break; + } + case UpdatesFailureReason::GET_UPDATE_REQUEST: { + err << "Failed to get update request. Error: " << description; + break; + } + case UpdatesFailureReason::DOWNLOAD_FILE : { + err << "Failed to download the file " << detail << ". Error: " << description; + break; + } + case UpdatesFailureReason::HANDLE_FILE : { + err << "Failed to handle the file " << detail << ". " << description; + break; + } + case UpdatesFailureReason::INSTALLATION_QUEUE : { + err << "Installation queue creation failed. Error: " << description; + break; + } + case UpdatesFailureReason::INSTALL_PACKAGE : { + err << "Failed to install the package " << detail << ". Error: " << description; + break; + } + case UpdatesFailureReason::CHECKSUM_UNMATCHED : { + err << "Checksums do not match for the file: " << detail << ". " << description; + break; + } + case UpdatesFailureReason::POLICY_CONFIGURATION : { + err << "Failed to configure policy version: " << detail << ". Error: " << description; + break; + } + case UpdatesFailureReason::POLICY_FOG_CONFIGURATION : { + err << "Failed to configure the fog address: " << detail << ". Error: " << description; + break; + } + case UpdatesFailureReason::ORCHESTRATION_SELF_UPDATE : { + err << description; + break; + } + case UpdatesFailureReason::NONE : { + err << description; + break; + } + } + return err.str(); +} diff --git a/components/security_apps/orchestration/updates_process_reporter/updates_process_reporter.cc b/components/security_apps/orchestration/updates_process_reporter/updates_process_reporter.cc new file mode 100644 index 0000000..c9269a0 --- /dev/null +++ b/components/security_apps/orchestration/updates_process_reporter/updates_process_reporter.cc @@ -0,0 +1,71 @@ +// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved. + +// Licensed under the Apache License, Version 2.0 (the "License"); +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "updates_process_reporter.h" + +#include +#include + +#include "debug.h" +#include "log_generator.h" + +using namespace std; + +USE_DEBUG_FLAG(D_UPDATES_PROCESS_REPORTER); + +vector UpdatesProcessReporter::reports; + +void +UpdatesProcessReporter::upon(const UpdatesProcessEvent &event) +{ + if (event.getReason() == UpdatesFailureReason::CHECK_UPDATE) { + if (event.getResult() == UpdatesProcessResult::SUCCESS && reports.empty()) { + dbgTrace(D_UPDATES_PROCESS_REPORTER) << "Update proccess finished successfully"; + return; + } + dbgTrace(D_UPDATES_PROCESS_REPORTER) << "Update proccess finished with errors"; + reports.emplace_back( + UpdatesProcessReport( + event.getResult(), + event.getType(), + event.getReason(), + event.parseDescription() + ) + ); + sendReoprt(); + return; + } + if (event.getResult() == UpdatesProcessResult::SUCCESS || event.getResult() == UpdatesProcessResult::UNSET) return; + reports.emplace_back( + UpdatesProcessReport(event.getResult(), event.getType(), event.getReason(), event.parseDescription()) + ); +} + +void +UpdatesProcessReporter::sendReoprt() +{ + stringstream all_reports; + all_reports << "Updates process reports:" << endl; + for (const auto &report : reports) { + all_reports << report.toString() << endl; + } + reports.clear(); + dbgTrace(D_UPDATES_PROCESS_REPORTER) << "Sending updates process report: " << endl << all_reports.str(); + LogGen( + "Updates process report", + ReportIS::Audience::INTERNAL, + ReportIS::Severity::HIGH, + ReportIS::Priority::HIGH, + ReportIS::Tags::ORCHESTRATOR + ) << LogField("eventMessage", all_reports.str()); +} diff --git a/components/security_apps/waap/waap_clib/DeepParser.cc b/components/security_apps/waap/waap_clib/DeepParser.cc index 0dcf014..3735778 100755 --- a/components/security_apps/waap/waap_clib/DeepParser.cc +++ b/components/security_apps/waap/waap_clib/DeepParser.cc @@ -273,55 +273,58 @@ DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int f // Detect and decode potential base64 chunks in the value before further processing bool base64ParamFound = false; - dbgTrace(D_WAAP_DEEP_PARSER) << " ===Processing potential base64==="; - std::string decoded_val, decoded_key; Waap::Util::BinaryFileType base64BinaryFileType = Waap::Util::BinaryFileType::FILE_TYPE_NONE; - base64_variants base64_status = Waap::Util::b64Test(cur_val, decoded_key, decoded_val, base64BinaryFileType); + if (m_depth == 1 && flags == BUFFERED_RECEIVER_F_MIDDLE && m_key.depth() == 1 && m_key.first() != "#base64"){ + dbgTrace(D_WAAP_DEEP_PARSER) << " === will not check base64 since prev data block was not b64-encoded ==="; + } else { + dbgTrace(D_WAAP_DEEP_PARSER) << " ===Processing potential base64==="; + std::string decoded_val, decoded_key; + base64_variants base64_status = Waap::Util::b64Test(cur_val, decoded_key, decoded_val, base64BinaryFileType); - dbgTrace(D_WAAP_DEEP_PARSER) - << " status = " - << base64_status - << " key = " - << decoded_key - << " value = " - << decoded_val; + dbgTrace(D_WAAP_DEEP_PARSER) + << " status = " + << base64_status + << " key = " + << decoded_key + << " value = " + << decoded_val; - switch (base64_status) { - case SINGLE_B64_CHUNK_CONVERT: - cur_val = decoded_val; - base64ParamFound = true; - break; - case KEY_VALUE_B64_PAIR: - // going deep with new pair in case value is not empty - if (decoded_val.size() > 0) { + switch (base64_status) { + case SINGLE_B64_CHUNK_CONVERT: cur_val = decoded_val; base64ParamFound = true; - rc = onKv( - decoded_key.c_str(), - decoded_key.size(), - cur_val.data(), - cur_val.size(), - flags, - parser_depth + break; + case KEY_VALUE_B64_PAIR: + // going deep with new pair in case value is not empty + if (decoded_val.size() > 0) { + cur_val = decoded_val; + base64ParamFound = true; + rc = onKv( + decoded_key.c_str(), + decoded_key.size(), + cur_val.data(), + cur_val.size(), + flags, + parser_depth ); - dbgTrace(D_WAAP_DEEP_PARSER) << " rc = " << rc; - if (rc != CONTINUE_PARSING) { - return rc; + dbgTrace(D_WAAP_DEEP_PARSER) << " rc = " << rc; + if (rc != CONTINUE_PARSING) { + return rc; + } } - } - break; - case CONTINUE_AS_IS: - break; - default: - break; - } + break; + case CONTINUE_AS_IS: + break; + default: + break; + } - if (base64ParamFound) { - dbgTrace(D_WAAP_DEEP_PARSER) << "DeepParser::onKv(): pushing #base64 prefix to the key."; - m_key.push("#base64", 7, false); + if (base64ParamFound) { + dbgTrace(D_WAAP_DEEP_PARSER) << "DeepParser::onKv(): pushing #base64 prefix to the key."; + m_key.push("#base64", 7, false); + } } - // cur_val is later passed through some filters (such as urldecode) before JSON, XML or HTML is detected/decoded std::string orig_val = cur_val; @@ -472,19 +475,19 @@ DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int f if (rc != CONTINUE_PARSING) { return rc; } - - if (Waap::Util::detectJSONasParameter(cur_val, decoded_key, decoded_val)) { + std::string json_decoded_val, json_decoded_key; + if (Waap::Util::detectJSONasParameter(cur_val, json_decoded_key, json_decoded_val)) { dbgTrace(D_WAAP_DEEP_PARSER) << " detectJSONasParameter was true: key = " - << decoded_key + << json_decoded_key << " value = " - << decoded_val; + << json_decoded_val; rc = onKv( - decoded_key.c_str(), - decoded_key.size(), - decoded_val.data(), - decoded_val.size(), + json_decoded_key.c_str(), + json_decoded_key.size(), + json_decoded_val.data(), + json_decoded_val.size(), flags, parser_depth ); diff --git a/components/security_apps/waap/waap_clib/ParserBase.h b/components/security_apps/waap/waap_clib/ParserBase.h index 4d7d9e3..0e3265e 100755 --- a/components/security_apps/waap/waap_clib/ParserBase.h +++ b/components/security_apps/waap/waap_clib/ParserBase.h @@ -22,6 +22,7 @@ #define BUFFERED_RECEIVER_F_LAST 0x02 #define BUFFERED_RECEIVER_F_BOTH (BUFFERED_RECEIVER_F_FIRST | BUFFERED_RECEIVER_F_LAST) #define BUFFERED_RECEIVER_F_UNNAMED 0x04 +#define BUFFERED_RECEIVER_F_MIDDLE 0x00 #if (DISTRO_centos6) // pre c++11 compiler doesn' support the "final" keyword diff --git a/components/security_apps/waap/waap_clib/Serializator.cc b/components/security_apps/waap/waap_clib/Serializator.cc index b80e5f3..5b982b9 100755 --- a/components/security_apps/waap/waap_clib/Serializator.cc +++ b/components/security_apps/waap/waap_clib/Serializator.cc @@ -727,7 +727,6 @@ void SerializeToLocalAndRemoteSyncBase::syncWorker() "sync notification for '" + m_assetId + "'", ReportIS::AudienceTeam::WAAP, syncNotification, - false, MessageCategory::GENERIC, ReportIS::Tags::WAF, ReportIS::Notification::SYNC_LEARNING diff --git a/components/security_apps/waap/waap_clib/WaapOverride.h b/components/security_apps/waap/waap_clib/WaapOverride.h index 2d315ff..2d5d3bd 100755 --- a/components/security_apps/waap/waap_clib/WaapOverride.h +++ b/components/security_apps/waap/waap_clib/WaapOverride.h @@ -39,12 +39,19 @@ public: m_op = to_lower_copy(m_op); m_isCidr = false; m_value = ""; + m_isValid = true; if (m_op == "basic") { // If op == "BASIC" - read numeric value ar(cereal::make_nvp("tag", m_tag)); m_tag = to_lower_copy(m_tag); + if (m_tag != "sourceip" && m_tag != "sourceidentifier" && m_tag != "url" && m_tag != "hostname" && + m_tag != "keyword" && m_tag != "paramname" && m_tag != "paramvalue" && m_tag != "paramlocation" && + m_tag != "responsebody" && m_tag != "headername" && m_tag != "headervalue" ) { + m_isValid = false; + dbgDebug(D_WAAP_OVERRIDE) << "Invalid override tag: " << m_tag; + } // The name "value" here is misleading. The real meaning is "regex pattern string" ar(cereal::make_nvp("value", m_value)); @@ -73,12 +80,14 @@ public: m_operand2 = std::make_shared(); ar(cereal::make_nvp("operand2", *m_operand2)); m_isOverrideResponse = m_operand1->m_isOverrideResponse || m_operand2->m_isOverrideResponse; + m_isValid = m_operand1->m_isValid && m_operand2->m_isValid; } else if (m_op == "not") { // If op is "NOT" get one operand m_operand1 = std::make_shared(); ar(cereal::make_nvp("operand1", *m_operand1)); m_isOverrideResponse = m_operand1->m_isOverrideResponse; + m_isValid = m_operand1->m_isValid; } } } @@ -120,6 +129,10 @@ public: return m_isOverrideResponse; } + bool isValidMatch() const{ + return m_isValid; + } + private: std::string m_op; std::shared_ptr m_operand1; @@ -130,6 +143,7 @@ private: Waap::Util::CIDRData m_cidr; bool m_isCidr; bool m_isOverrideResponse; + bool m_isValid; }; class Behavior @@ -189,6 +203,9 @@ private: class Rule { public: + + Rule(): m_match(), m_isChangingRequestData(false), isValid(true){} + bool operator==(const Rule &other) const; template @@ -202,6 +219,11 @@ public: m_id.clear(); } ar(cereal::make_nvp("parsedMatch", m_match)); + if (!m_match.isValidMatch()) { + dbgDebug(D_WAAP_OVERRIDE) << "An override rule was not load"; + isValid = false; + } + ar(cereal::make_nvp("parsedBehavior", m_behaviors)); m_isChangingRequestData = false; @@ -242,6 +264,7 @@ public: dbgTrace(D_WAAP_OVERRIDE) << "Rule not matched"; } + bool isChangingRequestData() const { return m_isChangingRequestData; } @@ -253,11 +276,16 @@ public: return m_id; } + bool isValidRule() const { + return isValid; + } + private: Match m_match; bool m_isChangingRequestData; std::vector m_behaviors; std::string m_id; + bool isValid; }; class Policy { @@ -270,6 +298,10 @@ public: for (std::vector::const_iterator it = rules.begin(); it != rules.end(); ++it) { const Waap::Override::Rule& rule = *it; + if (!rule.isValidRule()) { + dbgWarning(D_WAAP_OVERRIDE) << "rule is not valid"; + continue; + } if (rule.isChangingRequestData()) { m_RequestOverrides.push_back(rule); diff --git a/core/agent_core_utilities/agent_core_utilities.cc b/core/agent_core_utilities/agent_core_utilities.cc index 2483f8a..4cd74ee 100644 --- a/core/agent_core_utilities/agent_core_utilities.cc +++ b/core/agent_core_utilities/agent_core_utilities.cc @@ -175,7 +175,7 @@ copyFile(const string &src, const string &dest, bool overide_if_exists, mode_t p struct stat stat_buf; int source_fd = open(src.c_str(), O_RDONLY); fstat(source_fd, &stat_buf); - int dest_fd = open(dest.c_str(), O_WRONLY | O_CREAT, permission); + int dest_fd = open(dest.c_str(), O_WRONLY | O_CREAT | O_TRUNC, permission); int bytes_copied = 1; while (bytes_copied > 0) { static const int buf_size = 4096*1000; diff --git a/core/agent_core_utilities/agent_core_utilities_ut/agent_core_utilities_ut.cc b/core/agent_core_utilities/agent_core_utilities_ut/agent_core_utilities_ut.cc index bbf86ac..979f457 100644 --- a/core/agent_core_utilities/agent_core_utilities_ut/agent_core_utilities_ut.cc +++ b/core/agent_core_utilities/agent_core_utilities_ut/agent_core_utilities_ut.cc @@ -37,8 +37,11 @@ TEST_F(AgentCoreUtilUT, filesTest) EXPECT_FALSE(NGEN::Filesystem::exists("/i/am/not/a/real/path")); const vector lines{"i am a line in the text file", "i am iron man"}; + const vector lines_b{"i am a line 2 in the text file", "i am iron man 2", "hello again"}; CPTestTempfile test_file(lines); + CPTestTempfile test_file_b(lines_b); ASSERT_TRUE(NGEN::Filesystem::exists(test_file.fname)); + ASSERT_TRUE(NGEN::Filesystem::exists(test_file_b.fname)); string output_orig = test_file.readFile(); string new_path = test_file.fname + ".new"; @@ -46,6 +49,7 @@ TEST_F(AgentCoreUtilUT, filesTest) ASSERT_TRUE(NGEN::Filesystem::exists(new_path)); ASSERT_FALSE(NGEN::Filesystem::copyFile(test_file.fname, new_path, false)); ASSERT_TRUE(NGEN::Filesystem::copyFile(test_file.fname, new_path, true)); + ASSERT_TRUE(NGEN::Filesystem::copyFile(test_file.fname, test_file_b.fname, true)); string output_new; { ifstream new_file_stream(new_path); @@ -55,11 +59,20 @@ TEST_F(AgentCoreUtilUT, filesTest) output_new = buffer.str(); } + string output_test_b; + ifstream new_file_stream(test_file_b.fname); + ASSERT_TRUE(new_file_stream.good()); + stringstream buffer; + buffer << new_file_stream.rdbuf(); + output_test_b = buffer.str(); + EXPECT_EQ(output_orig, output_new); + EXPECT_EQ(output_orig, output_test_b); EXPECT_THAT(output_new, HasSubstr("i am a line in the text file")); EXPECT_THAT(output_new, HasSubstr("i am iron man")); EXPECT_TRUE(NGEN::Filesystem::deleteFile(test_file.fname)); EXPECT_TRUE(NGEN::Filesystem::deleteFile(new_path)); + EXPECT_TRUE(NGEN::Filesystem::deleteFile(test_file_b.fname)); EXPECT_FALSE(NGEN::Filesystem::exists(test_file.fname)); EXPECT_FALSE(NGEN::Filesystem::exists(new_path)); } diff --git a/core/include/internal/messaging.h b/core/include/internal/messaging.h index 3051aaf..6de8566 100644 --- a/core/include/internal/messaging.h +++ b/core/include/internal/messaging.h @@ -26,6 +26,7 @@ #include "i_time_get.h" #include "i_encryptor.h" #include "i_shell_cmd.h" +#include "i_rest_api.h" #include "i_instance_awareness.h" #include "config.h" @@ -41,6 +42,7 @@ class Messaging Singleton::Consume, Singleton::Consume, Singleton::Consume, + Singleton::Consume, Singleton::Consume { public: diff --git a/core/include/services_sdk/resources/debug_flags.h b/core/include/services_sdk/resources/debug_flags.h index e11287c..cc992c8 100644 --- a/core/include/services_sdk/resources/debug_flags.h +++ b/core/include/services_sdk/resources/debug_flags.h @@ -142,6 +142,7 @@ DEFINE_FLAG(D_COMPONENT, D_ALL) DEFINE_FLAG(D_LOCAL_POLICY, D_ORCHESTRATOR) DEFINE_FLAG(D_NGINX_POLICY, D_ORCHESTRATOR) DEFINE_FLAG(D_SERVICE_CONTROLLER, D_ORCHESTRATOR) + DEFINE_FLAG(D_UPDATES_PROCESS_REPORTER, D_ORCHESTRATOR) DEFINE_FLAG(D_GRADUAL_DEPLOYMENT, D_COMPONENT) DEFINE_FLAG(D_SDWAN, D_COMPONENT) diff --git a/core/include/services_sdk/resources/health_check_status/health_check_status.h b/core/include/services_sdk/resources/health_check_status/health_check_status.h index 7111e0b..9048a7a 100644 --- a/core/include/services_sdk/resources/health_check_status/health_check_status.h +++ b/core/include/services_sdk/resources/health_check_status/health_check_status.h @@ -89,11 +89,4 @@ private: std::map extended_status = {}; }; -class HealthCheckStatusEvent : public Event -{ -public: - HealthCheckStatusEvent() {} - ~HealthCheckStatusEvent() {} -}; - #endif // __HEALTH_CHECK_STATUS_H__ diff --git a/core/messaging/messaging_comp/messaging_comp.cc b/core/messaging/messaging_comp/messaging_comp.cc index 4aaf040..e48a8c7 100644 --- a/core/messaging/messaging_comp/messaging_comp.cc +++ b/core/messaging/messaging_comp/messaging_comp.cc @@ -18,6 +18,7 @@ #include "agent_core_utilities.h" #include "connection_comp.h" +#include "rest.h" #include "debug.h" #include "messaging_buffer.h" @@ -25,6 +26,40 @@ using namespace std; USE_DEBUG_FLAG(D_MESSAGING); +class FogConnectionChecker : public ServerRest +{ +public: + void + doCall() override + { + dbgTrace(D_MESSAGING) << "Checking connection to the FOG"; + auto response = Singleton::Consume::from()->sendSyncMessage( + HTTPMethod::GET, + "/access-manager/health/live", + string("") + ); + if (!response.ok()) { + dbgTrace(D_MESSAGING) << "Failed to check connection to the FOG"; + connected_to_fog = false; + error = response.getErr().toString(); + return; + } + if (response.unpack().getHTTPStatusCode() == HTTPStatusCode::HTTP_OK) { + dbgTrace(D_MESSAGING) << "Connected to the FOG"; + connected_to_fog = true; + error = ""; + } else { + dbgTrace(D_MESSAGING) << "No connection to the FOG"; + connected_to_fog = false; + error = response.unpack().toString(); + } + } + +private: + S2C_PARAM(bool, connected_to_fog); + S2C_PARAM(string, error); +}; + void MessagingComp::init() { @@ -42,6 +77,13 @@ MessagingComp::init() "message", "Buffer Failed Requests" ); + + if (Singleton::exists()) { + Singleton::Consume::by()->addRestCall( + RestAction::SHOW, + "check-fog-connection" + ); + } } static bool diff --git a/core/messaging/messaging_comp/messaging_comp_ut/messaging_comp_ut.cc b/core/messaging/messaging_comp/messaging_comp_ut/messaging_comp_ut.cc index 84c8ea2..ed2cc94 100644 --- a/core/messaging/messaging_comp/messaging_comp_ut/messaging_comp_ut.cc +++ b/core/messaging/messaging_comp/messaging_comp_ut/messaging_comp_ut.cc @@ -15,6 +15,8 @@ #include "mocks/mock_messaging_connection.h" #include "rest.h" #include "rest_server.h" +#include "mock/mock_messaging.h" +#include "mock/mock_rest_api.h" #include "dummy_socket.h" using namespace std; @@ -26,12 +28,6 @@ operator<<(ostream &os, const Maybe &) return os; } -static std::ostream & -operator<<(std::ostream &os, const HTTPResponse &) -{ - return os; -} - static std::ostream & operator<<(std::ostream &os, const HTTPStatusCode &) { @@ -51,6 +47,9 @@ public: { Debug::setUnitTestFlag(D_MESSAGING, Debug::DebugLevel::TRACE); EXPECT_CALL(mock_time_get, getMonotonicTime()).WillRepeatedly(Return(chrono::microseconds(0))); + EXPECT_CALL(mock_rest, mockRestCall(RestAction::SHOW, "check-fog-connection", _)) + .WillOnce(WithArg<2>(Invoke(this, &TestMessagingComp::showFogConnection)) + ); ON_CALL(mock_agent_details, getFogDomain()).WillByDefault(Return(Maybe(fog_addr))); ON_CALL(mock_agent_details, getFogPort()).WillByDefault(Return(Maybe(fog_port))); @@ -73,6 +72,13 @@ public: EXPECT_CALL(mock_proxy_conf, getProxyAuthentication(_)).WillRepeatedly(Return(string("cred"))); } + bool + showFogConnection(const unique_ptr &p) + { + show_fog_connection = p->getRest(); + return true; + } + const string fog_addr = "127.0.0.1"; int fog_port = 8080; CPTestTempfile agent_details_file; @@ -85,16 +91,37 @@ public: NiceMock mock_time_get; NiceMock mock_agent_details; NiceMock mock_proxy_conf; + NiceMock mock_rest; + NiceMock mock_message; + unique_ptr show_fog_connection; DummySocket dummy_socket; }; -TEST_F(TestMessagingComp, testInitComp) +TEST_F(TestMessagingComp, testCheckFogConnectivity) { - EXPECT_CALL( - mock_mainloop, addRecurringRoutine(I_MainLoop::RoutineType::Timer, _, _, "Delete expired cache entries", _) - ) - .WillOnce(Return(0)); - messaging_comp.init(); + setAgentDetails(); + HTTPResponse res( + HTTPStatusCode::HTTP_OK, + string( + "{" + " \"up\": true," + " \"timestamp\":\"\"" + "}" + ) + ); + + EXPECT_CALL(mock_message, sendSyncMessage(HTTPMethod::GET, "/access-manager/health/live", "", _, _)) + .WillOnce(Return(res)); + + stringstream ss("{}"); + Maybe maybe_res = show_fog_connection->performRestCall(ss); + EXPECT_TRUE(maybe_res.ok()); + EXPECT_EQ(maybe_res.unpack(), + "{\n" + " \"connected_to_fog\": true,\n" + " \"error\": \"\"\n" + "}" + ); } TEST_F(TestMessagingComp, testSendSyncMessage) diff --git a/nodes/orchestration/CMakeLists.txt b/nodes/orchestration/CMakeLists.txt index a6af870..b85a8dd 100755 --- a/nodes/orchestration/CMakeLists.txt +++ b/nodes/orchestration/CMakeLists.txt @@ -28,6 +28,7 @@ target_link_libraries( orchestration_tools env_details local_policy_mgmt_gen + updates_process_reporter curl -Wl,--end-group diff --git a/nodes/orchestration/package/local-default-policy.yaml b/nodes/orchestration/package/local-default-policy.yaml index e963ebf..efc0223 100644 --- a/nodes/orchestration/package/local-default-policy.yaml +++ b/nodes/orchestration/package/local-default-policy.yaml @@ -52,7 +52,7 @@ log-triggers: url-path: false url-query: false log-destination: - cloud: true + cloud: false stdout: format: json diff --git a/nodes/orchestration/package/orchestration_package.sh b/nodes/orchestration/package/orchestration_package.sh index abecd7f..7b690d7 100755 --- a/nodes/orchestration/package/orchestration_package.sh +++ b/nodes/orchestration/package/orchestration_package.sh @@ -418,9 +418,9 @@ cp_print() printf "%b\n" "$1" fi if [ "$is_smb" != "1" ]; then - printf "%b\n" "$1" >> ${LOG_FILE_PATH}/${LOG_PATH}/${INSTALLATION_LOG_FILE} + printf "[%s] %b\n" "$(date +%Y-%m-%dT%H:%M:%S)" "$1" >> ${LOG_FILE_PATH}/${LOG_PATH}/${INSTALLATION_LOG_FILE} else - printf "%b\n" "$1" >> ${SMB_LOG_FILE_PATH}/${LOG_PATH}/${INSTALLATION_LOG_FILE} + printf "[%s] %b\n" "$(date +%Y-%m-%dT%H:%M:%S)" "$1" >> ${SMB_LOG_FILE_PATH}/${LOG_PATH}/${INSTALLATION_LOG_FILE} fi }