diff --git a/components/security_apps/orchestration/include/declarative_policy_utils.h b/components/security_apps/orchestration/include/declarative_policy_utils.h new file mode 100644 index 0000000..0f38c4a --- /dev/null +++ b/components/security_apps/orchestration/include/declarative_policy_utils.h @@ -0,0 +1,83 @@ +#ifndef __DECLARATIVE_POLICY_UTILS_H__ +#define __DECLARATIVE_POLICY_UTILS_H__ + +#include +#include +#include +#include +#include "cereal/archives/json.hpp" + +#include "singleton.h" +#include "i_update_communication.h" +#include "fog_authenticator.h" +#include "i_local_policy_mgmt_gen.h" +#include "i_orchestration_tools.h" +#include "i_agent_details.h" +#include "i_orchestration_status.h" +#include "i_messaging.h" +#include "i_mainloop.h" +#include "i_encryptor.h" +#include "i_details_resolver.h" +#include "i_rest_api.h" +#include "i_time_get.h" +#include "i_shell_cmd.h" +#include "i_encryptor.h" +#include "maybe_res.h" +#include "event.h" + +class ApplyPolicyEvent : public Event +{ +public: + ApplyPolicyEvent() {} +}; + +class DeclarativePolicyUtils + : + public Singleton::Consume, + Singleton::Consume, + Singleton::Consume, + Singleton::Consume, + Singleton::Consume, + public Listener +{ +public: + class ApplyPolicyRest : public ServerRest + { + public: + // LCOV_EXCL_START Reason: no test exist + void + doCall() override + { + ApplyPolicyEvent().notify(); + } + // LCOV_EXCL_STOP + }; + + void init(); + Maybe getLocalPolicyChecksum(); + std::string getPolicyChecksum(); + void updateCurrentPolicy(const std::string &policy_checksum); + void sendUpdatesToFog( + const std::string &access_token, + const std::string &tenant_id, + const std::string &profile_id, + const std::string &fog_address + ); + std::string getUpdate(CheckUpdateRequest &request); + bool shouldApplyPolicy(); + void turnOffApplyPolicyFlag(); + + std::string getCurrVersion() { return curr_version; } + std::string getCurrPolicy() { return curr_policy; } + + void upon(const ApplyPolicyEvent &event) override; + +private: + std::string getCleanChecksum(const std::string &unclean_checksum); + + std::string curr_version; + std::string curr_policy; + bool should_apply_policy; +}; + +#endif // __DECLARATIVE_POLICY_UTILS_H__ diff --git a/components/security_apps/orchestration/include/fog_communication.h b/components/security_apps/orchestration/include/fog_communication.h index b93dac2..d41768b 100755 --- a/components/security_apps/orchestration/include/fog_communication.h +++ b/components/security_apps/orchestration/include/fog_communication.h @@ -33,13 +33,18 @@ #include "i_time_get.h" #include "i_encryptor.h" #include "maybe_res.h" +#include "declarative_policy_utils.h" class FogCommunication : public FogAuthenticator { public: + void init() override; Maybe getUpdate(CheckUpdateRequest &request) override; Maybe downloadAttributeFile(const GetResourceFile &resourse_file) override; Maybe sendPolicyVersion(const std::string &policy_version) const override; + +private: + DeclarativePolicyUtils declarative_policy_utils; }; #endif // __FOG_COMMUNICATION_H__ diff --git a/components/security_apps/orchestration/include/hybrid_communication.h b/components/security_apps/orchestration/include/hybrid_communication.h index a582cc1..e452354 100755 --- a/components/security_apps/orchestration/include/hybrid_communication.h +++ b/components/security_apps/orchestration/include/hybrid_communication.h @@ -35,6 +35,7 @@ #include "i_time_get.h" #include "i_encryptor.h" #include "maybe_res.h" +#include "declarative_policy_utils.h" class HybridCommunication : @@ -42,17 +43,15 @@ class HybridCommunication Singleton::Consume { public: - virtual void init() override; + void init() override; Maybe getUpdate(CheckUpdateRequest &request) override; Maybe downloadAttributeFile(const GetResourceFile &resourse_file) override; Maybe sendPolicyVersion(const std::string &policy_version) const override; - std::string getChecksum(const std::string &policy_version); private: Maybe getNewVersion(); - std::string curr_version; - std::string curr_policy; + DeclarativePolicyUtils declarative_policy_utils; }; #endif // __HYBRID_COMMUNICATION_H__ diff --git a/components/security_apps/orchestration/include/update_policy_notification.h b/components/security_apps/orchestration/include/update_policy_notification.h new file mode 100755 index 0000000..ccd4492 --- /dev/null +++ b/components/security_apps/orchestration/include/update_policy_notification.h @@ -0,0 +1,30 @@ +// 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 __UPDATE_POLICY_NOTIFICATION__H__ +#define __UPDATE_POLICY_NOTIFICATION__H__ + +#include +#include +#include "rest.h" + +class UpdatePolicyCrdObject : public ClientRest +{ +public: + UpdatePolicyCrdObject(const std::string &_policy_version) : policy_version(_policy_version) {} + +private: + C2S_LABEL_PARAM(std::string, policy_version, "policyVersion"); +}; + +#endif //__UPDATE_POLICY_NOTIFICATION__H__ diff --git a/components/security_apps/orchestration/local_policy_mgmt_gen/include/appsec_practice_section.h b/components/security_apps/orchestration/local_policy_mgmt_gen/include/appsec_practice_section.h index 8aa7d58..c9020f1 100644 --- a/components/security_apps/orchestration/local_policy_mgmt_gen/include/appsec_practice_section.h +++ b/components/security_apps/orchestration/local_policy_mgmt_gen/include/appsec_practice_section.h @@ -31,7 +31,7 @@ #include "trusted_sources_section.h" USE_DEBUG_FLAG(D_K8S_POLICY); - +// LCOV_EXCL_START Reason: no test exist class AppSecWebBotsURI { public: @@ -700,9 +700,9 @@ public: const std::string & getMode() const { return mode; } - void setHost(const std::string &_host) { host = _host; }; + void setHost(const std::string &_host) { host = _host; } - void setMode(const std::string &_mode) { mode = _mode; }; + void setMode(const std::string &_mode) { mode = _mode; } const std::string & getCustomResponse() const { return custom_response; } @@ -827,5 +827,5 @@ operator<<(std::ostream &os, const AppsecPolicySpec &obj) << std::endl << "]"; return os; } - +// LCOV_EXCL_STOP #endif // __APPSEC_PRACTICE_SECTION_H__ diff --git a/components/security_apps/orchestration/local_policy_mgmt_gen/include/exceptions_section.h b/components/security_apps/orchestration/local_policy_mgmt_gen/include/exceptions_section.h index 8359aba..69b3196 100644 --- a/components/security_apps/orchestration/local_policy_mgmt_gen/include/exceptions_section.h +++ b/components/security_apps/orchestration/local_policy_mgmt_gen/include/exceptions_section.h @@ -26,7 +26,7 @@ #include "k8s_policy_common.h" USE_DEBUG_FLAG(D_K8S_POLICY); - +// LCOV_EXCL_START Reason: no test exist class AppsecExceptionSpec { public: @@ -309,5 +309,5 @@ public: private: Exception exception_rulebase; }; - +// LCOV_EXCL_STOP #endif // __EXCEPTPIONS_SECTION_H__ diff --git a/components/security_apps/orchestration/local_policy_mgmt_gen/include/ingress_data.h b/components/security_apps/orchestration/local_policy_mgmt_gen/include/ingress_data.h index ece21a6..1dcece2 100644 --- a/components/security_apps/orchestration/local_policy_mgmt_gen/include/ingress_data.h +++ b/components/security_apps/orchestration/local_policy_mgmt_gen/include/ingress_data.h @@ -23,7 +23,7 @@ #include "cereal/archives/json.hpp" USE_DEBUG_FLAG(D_K8S_POLICY); - +// LCOV_EXCL_START Reason: no test exist class IngressMetadata { public: @@ -220,5 +220,5 @@ private: std::string apiVersion; std::vector items; }; - +// LCOV_EXCL_STOP #endif // __INGRESS_DATA_H__ diff --git a/components/security_apps/orchestration/local_policy_mgmt_gen/include/k8s_policy_common.h b/components/security_apps/orchestration/local_policy_mgmt_gen/include/k8s_policy_common.h index 040be25..9e19b0e 100644 --- a/components/security_apps/orchestration/local_policy_mgmt_gen/include/k8s_policy_common.h +++ b/components/security_apps/orchestration/local_policy_mgmt_gen/include/k8s_policy_common.h @@ -24,7 +24,7 @@ #include "rest.h" USE_DEBUG_FLAG(D_K8S_POLICY); - +// LCOV_EXCL_START Reason: no test exist enum class PracticeType { WebApplication, WebAPI }; enum class TriggerType { Log, WebUserResponse }; enum class MatchType { Condition, Operator }; @@ -102,5 +102,5 @@ public: private: T spec; }; - +// LCOV_EXCL_STOP #endif // __K8S_POLICY_COMMON_H__ diff --git a/components/security_apps/orchestration/local_policy_mgmt_gen/include/rules_config_section.h b/components/security_apps/orchestration/local_policy_mgmt_gen/include/rules_config_section.h index 6044b13..39a2e85 100644 --- a/components/security_apps/orchestration/local_policy_mgmt_gen/include/rules_config_section.h +++ b/components/security_apps/orchestration/local_policy_mgmt_gen/include/rules_config_section.h @@ -26,7 +26,7 @@ #include "k8s_policy_common.h" USE_DEBUG_FLAG(D_K8S_POLICY); - +// LCOV_EXCL_START Reason: no test exist class AssetUrlParser { public: @@ -227,7 +227,7 @@ public: triggers(_triggers) { try { - id = to_string(boost::uuids::random_generator()()); + id = _url+_uri; bool any = _name == "Any" && _url == "Any" && _uri == "Any"; if (_uri != "/") { context = any ? "All()" : "Any(" @@ -387,5 +387,5 @@ public: private: RulesConfig rules_config_rulebase; }; - +// LCOV_EXCL_STOP #endif // __RULES_CONFIG_SECTION_H__ diff --git a/components/security_apps/orchestration/local_policy_mgmt_gen/include/settings_section.h b/components/security_apps/orchestration/local_policy_mgmt_gen/include/settings_section.h index 23b09a8..ce403b7 100644 --- a/components/security_apps/orchestration/local_policy_mgmt_gen/include/settings_section.h +++ b/components/security_apps/orchestration/local_policy_mgmt_gen/include/settings_section.h @@ -24,7 +24,7 @@ #include "k8s_policy_common.h" USE_DEBUG_FLAG(D_K8S_POLICY); - +// LCOV_EXCL_START Reason: no test exist class AgentSettingsSection { public: @@ -117,5 +117,5 @@ private: std::string name = "Kubernetes Agents"; SettingsRulebase agent; }; - +// LCOV_EXCL_STOP #endif // __SETTINGS_SECTION_H__ diff --git a/components/security_apps/orchestration/local_policy_mgmt_gen/include/snort_section.h b/components/security_apps/orchestration/local_policy_mgmt_gen/include/snort_section.h index d5b7167..073b644 100644 --- a/components/security_apps/orchestration/local_policy_mgmt_gen/include/snort_section.h +++ b/components/security_apps/orchestration/local_policy_mgmt_gen/include/snort_section.h @@ -23,7 +23,7 @@ #include "debug.h" USE_DEBUG_FLAG(D_K8S_POLICY); - +// LCOV_EXCL_START Reason: no test exist class AgentSettingsSection { public: @@ -75,5 +75,5 @@ public: private: std::vector agentSettings; }; - +// LCOV_EXCL_STOP #endif // __SNORT_SECTION_H__ diff --git a/components/security_apps/orchestration/local_policy_mgmt_gen/include/triggers_section.h b/components/security_apps/orchestration/local_policy_mgmt_gen/include/triggers_section.h index c704937..9b91c3a 100644 --- a/components/security_apps/orchestration/local_policy_mgmt_gen/include/triggers_section.h +++ b/components/security_apps/orchestration/local_policy_mgmt_gen/include/triggers_section.h @@ -24,7 +24,7 @@ #include "k8s_policy_common.h" USE_DEBUG_FLAG(D_K8S_POLICY); - +// LCOV_EXCL_START Reason: no test exist class LogTriggerSection { public: @@ -633,5 +633,5 @@ public: private: TriggersRulebase triggers_rulebase; }; - +// LCOV_EXCL_STOP #endif // __TRIGGERS_SECTION_H__ diff --git a/components/security_apps/orchestration/local_policy_mgmt_gen/include/trusted_sources_section.h b/components/security_apps/orchestration/local_policy_mgmt_gen/include/trusted_sources_section.h index a152bf6..4d6c020 100755 --- a/components/security_apps/orchestration/local_policy_mgmt_gen/include/trusted_sources_section.h +++ b/components/security_apps/orchestration/local_policy_mgmt_gen/include/trusted_sources_section.h @@ -25,7 +25,7 @@ #include "k8s_policy_common.h" USE_DEBUG_FLAG(D_K8S_POLICY); - +// LCOV_EXCL_START Reason: no test exist class TrustedSourcesSpec { public: @@ -218,5 +218,5 @@ private: int num_of_sources; std::vector sources_identifiers; }; - +// LCOV_EXCL_STOP #endif // __TRUSTED_SOURCES_SECTION_H__ diff --git a/components/security_apps/orchestration/local_policy_mgmt_gen/local_policy_mgmt_gen.cc b/components/security_apps/orchestration/local_policy_mgmt_gen/local_policy_mgmt_gen.cc index 3925e30..0156a98 100644 --- a/components/security_apps/orchestration/local_policy_mgmt_gen/local_policy_mgmt_gen.cc +++ b/components/security_apps/orchestration/local_policy_mgmt_gen/local_policy_mgmt_gen.cc @@ -56,7 +56,7 @@ const static string policy_key = "policy"; const static string syslog_key = "syslog"; const static string mode_key = "mode"; const static string local_mgmt_policy_path = "/conf/local_policy.yaml"; - +// LCOV_EXCL_START Reason: no test exist class SecurityAppsWrapper { public: @@ -719,8 +719,16 @@ public: default_rule.getTrustedSources() : parsed_rule.getTrustedSources(); - string url = asset_name.substr(0, asset_name.find("/")); - string uri = asset_name.substr(asset_name.find("/")); + auto pos = asset_name.find("/"); + string url; + string uri; + if (pos != string::npos) { + url = asset_name.substr(0, asset_name.find("/")); + uri = asset_name.substr(asset_name.find("/")); + } else { + url = asset_name; + uri = ""; + } if (specific_assets_from_ingress.find({url, uri}) != specific_assets_from_ingress.end()) { // Erasing the current asset from the specific assets, because it won't have default policy specific_assets_from_ingress.erase({url, uri}); @@ -1247,7 +1255,8 @@ private: uid, EnvKeyAttr::LogSection::SOURCE ); - Singleton::Consume::by()->setClusterId(playground_uid + uid); + auto i_agent_details = Singleton::Consume::by(); + i_agent_details->setClusterId(playground_uid + uid); return true; } } @@ -1688,4 +1697,4 @@ LocalPolicyMgmtGenerator::init() void LocalPolicyMgmtGenerator::preload() {} - +// LCOV_EXCL_STOP diff --git a/components/security_apps/orchestration/update_communication/CMakeLists.txt b/components/security_apps/orchestration/update_communication/CMakeLists.txt index e88e689..1b7273c 100755 --- a/components/security_apps/orchestration/update_communication/CMakeLists.txt +++ b/components/security_apps/orchestration/update_communication/CMakeLists.txt @@ -1,3 +1,2 @@ -add_library(update_communication update_communication.cc hybrid_communication.cc fog_communication.cc fog_authenticator.cc local_communication.cc) - +add_library(update_communication update_communication.cc hybrid_communication.cc fog_communication.cc fog_authenticator.cc local_communication.cc declarative_policy_utils.cc) add_subdirectory(update_communication_ut) diff --git a/components/security_apps/orchestration/update_communication/declarative_policy_utils.cc b/components/security_apps/orchestration/update_communication/declarative_policy_utils.cc new file mode 100755 index 0000000..ba300e0 --- /dev/null +++ b/components/security_apps/orchestration/update_communication/declarative_policy_utils.cc @@ -0,0 +1,172 @@ +#include "declarative_policy_utils.h" +#include "rest.h" +#include "config.h" +#include "log_generator.h" +#include "agent_details.h" +#include "version.h" + +#include +#include +#include + +using namespace std; + +USE_DEBUG_FLAG(D_ORCHESTRATOR); + +void +DeclarativePolicyUtils::init() +{ + should_apply_policy = true; + Singleton::Consume::by()->addRestCall( + RestAction::SET, "apply-policy" + ); + registerListener(); +} + +// LCOV_EXCL_START Reason: no test exist +void +DeclarativePolicyUtils::upon(const ApplyPolicyEvent &) +{ + dbgTrace(D_ORCHESTRATOR) << "Apply policy event"; + should_apply_policy = true; +} +// LCOV_EXCL_STOP + +bool +DeclarativePolicyUtils::shouldApplyPolicy() +{ + auto env_type = Singleton::Consume::by()->getEnvType(); + return env_type == I_LocalPolicyMgmtGen::LocalPolicyEnv::K8S ? true : should_apply_policy; +} + +void +DeclarativePolicyUtils::turnOffApplyPolicyFlag() +{ + should_apply_policy = false; +} + +Maybe +DeclarativePolicyUtils::getLocalPolicyChecksum() +{ + I_OrchestrationTools *orchestration_tools = Singleton::Consume::by(); + auto env_type = Singleton::Consume::by()->getEnvType(); + if (env_type == I_LocalPolicyMgmtGen::LocalPolicyEnv::K8S) { + return orchestration_tools->readFile("/etc/cp/conf/k8s-policy-check.trigger"); + } + + string policy_path = getConfigurationFlagWithDefault( + getFilesystemPathConfig() + "/conf/local_policy.yaml", + "local_mgmt_policy" + ); + + Maybe file_checksum = orchestration_tools->calculateChecksum( + I_OrchestrationTools::SELECTED_CHECKSUM_TYPE, + policy_path + ); + + if (!file_checksum.ok()) { + dbgWarning(D_ORCHESTRATOR) << "Policy checksum was not calculated: " << file_checksum.getErr(); + return genError(file_checksum.getErr()); + } + + return file_checksum.unpack(); +} + +string +DeclarativePolicyUtils::getCleanChecksum(const string &unclean_checksum) +{ + string clean_checksum = unclean_checksum; + if (!clean_checksum.empty() && clean_checksum[clean_checksum.size() - 1] == '\n') { + clean_checksum.erase(clean_checksum.size() - 1); + } + return clean_checksum; +} + +void +DeclarativePolicyUtils::updateCurrentPolicy(const string &policy_checksum) +{ + string clean_policy_checksum = getCleanChecksum(policy_checksum); + curr_policy = Singleton::Consume::by()->parsePolicy( + clean_policy_checksum + ); +} + +string +DeclarativePolicyUtils::getPolicyChecksum() +{ + I_OrchestrationTools *orchestration_tools = Singleton::Consume::by(); + Maybe file_checksum = orchestration_tools->calculateChecksum( + I_OrchestrationTools::SELECTED_CHECKSUM_TYPE, + Singleton::Consume::by()->getPolicyPath() + ); + + if (!file_checksum.ok()) { + dbgWarning(D_ORCHESTRATOR) << "Failed policy checksum calculation"; + return ""; + } + return file_checksum.unpack(); +} + +void +DeclarativePolicyUtils::sendUpdatesToFog( + const string &access_token, + const string &tenant_id, + const string &profile_id, + const string &fog_address) +{ + auto shell_cmd = Singleton::Consume::by(); + string exec_command = + getFilesystemPathConfig() + + "/scripts/open-appsec-cloud-mgmt --upload_policy_only" + + " --access_token " + access_token + + " --tenant_id " + tenant_id + + " --profile_id " + profile_id; + auto env = Singleton::Consume::by()->getEnvType(); + if (env == I_LocalPolicyMgmtGen::LocalPolicyEnv::K8S) { + exec_command = + getFilesystemPathConfig() + + "/scripts/open-appsec-cloud-mgmt-k8s" + + " --access_token " + access_token; + } + if (fog_address != "") exec_command = exec_command + " --fog https://" + fog_address; + + auto maybe_cmd_output = shell_cmd->getExecOutput( + exec_command, + 300000, + false + ); + if (maybe_cmd_output.ok()) { + dbgTrace(D_ORCHESTRATOR) << "Successfully send policy updates to the fog"; + } else { + dbgError(D_ORCHESTRATOR) << "Failed to send policy updates to the fog. Error: " << maybe_cmd_output.getErr(); + } +} + +string +DeclarativePolicyUtils::getUpdate(CheckUpdateRequest &request) +{ + dbgTrace(D_ORCHESTRATOR) << "Getting policy update in declarative policy"; + + string policy_response = ""; + auto policy_checksum = request.getPolicy(); + + auto maybe_new_version = getLocalPolicyChecksum(); + if (!maybe_new_version.ok() || maybe_new_version == curr_version) { + dbgDebug(D_ORCHESTRATOR) << "No new version is currently available"; + return ""; + } + + updateCurrentPolicy(maybe_new_version.unpack()); + string offline_policy_checksum = getPolicyChecksum(); + if (!policy_checksum.ok() || offline_policy_checksum != policy_checksum.unpack()) { + dbgTrace(D_ORCHESTRATOR) << "Update policy checksum"; + policy_response = offline_policy_checksum; + } + + dbgDebug(D_ORCHESTRATOR) + << "Local update response, " + << "policy: " + << (policy_response.empty() ? "has no change," : "has new update," ); + curr_version = maybe_new_version.unpack(); + return policy_response; +} diff --git a/components/security_apps/orchestration/update_communication/fog_communication.cc b/components/security_apps/orchestration/update_communication/fog_communication.cc index 65cf396..95f673b 100755 --- a/components/security_apps/orchestration/update_communication/fog_communication.cc +++ b/components/security_apps/orchestration/update_communication/fog_communication.cc @@ -31,9 +31,17 @@ using HTTPMethod = I_Messaging::Method; USE_DEBUG_FLAG(D_ORCHESTRATOR); +void +FogCommunication::init() +{ + FogAuthenticator::init(); + declarative_policy_utils.init(); +} + Maybe FogCommunication::getUpdate(CheckUpdateRequest &request) { + dbgTrace(D_ORCHESTRATOR) << "Getting updates - fog Communication"; if (!access_token.ok()) return genError("Acccess Token not available."); auto unpacked_access_token = access_token.unpack().getToken(); @@ -49,6 +57,41 @@ FogCommunication::getUpdate(CheckUpdateRequest &request) dbgDebug(D_ORCHESTRATOR) << "Failed to get response after check update request."; return genError("Failed to request updates"); } + + string policy_mgmt_mode = getSettingWithDefault("management", "profileManagedMode"); + dbgTrace(D_ORCHESTRATOR) << "Profile managed mode: " << policy_mgmt_mode; + if (policy_mgmt_mode == "declarative") { + Maybe maybe_new_manifest = request.getManifest(); + string manifest_checksum = maybe_new_manifest.ok() ? maybe_new_manifest.unpack() : ""; + + Maybe maybe_new_settings = request.getSettings(); + string settings_checksum = maybe_new_settings.ok() ? maybe_new_settings.unpack() : ""; + + Maybe maybe_new_data = request.getData(); + string data_checksum = maybe_new_data.ok() ? maybe_new_data.unpack() : ""; + + if (declarative_policy_utils.shouldApplyPolicy()) { + string policy_response = declarative_policy_utils.getUpdate(request); + if (!policy_response.empty()) { + dbgTrace(D_ORCHESTRATOR) << "Apply policy - declarative mode"; + auto agent_details = Singleton::Consume::by(); + auto maybe_fog_address = agent_details->getFogDomain(); + string fog_address = maybe_fog_address.ok() ? maybe_fog_address.unpack() : ""; + + declarative_policy_utils.sendUpdatesToFog( + unpacked_access_token, + agent_details->getTenantId(), + agent_details->getProfileId(), + fog_address + ); + } + request = CheckUpdateRequest(manifest_checksum, policy_response, settings_checksum, data_checksum, "", ""); + declarative_policy_utils.turnOffApplyPolicyFlag(); + } else { + request = CheckUpdateRequest(manifest_checksum, "", settings_checksum, data_checksum, "", ""); + } + } + dbgDebug(D_ORCHESTRATOR) << "Got response after check update request."; return Maybe(); } @@ -60,6 +103,11 @@ FogCommunication::downloadAttributeFile(const GetResourceFile &resourse_file) auto unpacked_access_token = access_token.unpack().getToken(); + string policy_mgmt_mode = getSettingWithDefault("management", "profileManagedMode"); + if (policy_mgmt_mode == "declarative" && resourse_file.getFileName() =="policy") { + dbgDebug(D_ORCHESTRATOR) << "Download policy on declarative mode - returnig the local policy"; + return declarative_policy_utils.getCurrPolicy(); + } static const string file_attribute_str = "/api/v2/agents/resources/"; Maybe attribute_file = Singleton::Consume::by()->downloadFile( resourse_file, diff --git a/components/security_apps/orchestration/update_communication/hybrid_communication.cc b/components/security_apps/orchestration/update_communication/hybrid_communication.cc index 18f4e93..27598de 100755 --- a/components/security_apps/orchestration/update_communication/hybrid_communication.cc +++ b/components/security_apps/orchestration/update_communication/hybrid_communication.cc @@ -12,6 +12,7 @@ // limitations under the License. #include "hybrid_communication.h" +#include "update_policy_notification.h" #include "rest.h" #include "config.h" #include "log_generator.h" @@ -30,10 +31,14 @@ using HTTPMethod = I_Messaging::Method; USE_DEBUG_FLAG(D_ORCHESTRATOR); +#define TUNING_HOST_ENV_NAME "TUNING_HOST" +static const string defaultTuningHost = "appsec-tuning-svc"; + void HybridCommunication::init() { FogAuthenticator::init(); + declarative_policy_utils.init(); dbgTrace(D_ORCHESTRATOR) << "Initializing the Hybrid Communication Component"; if (getConfigurationFlag("otp") != "") { otp = getConfigurationFlag("otp"); @@ -42,56 +47,6 @@ HybridCommunication::init() } } -string -HybridCommunication::getChecksum(const string &policy_version) -{ - string clean_plicy_version = policy_version; - if (!clean_plicy_version.empty() && clean_plicy_version[clean_plicy_version.size() - 1] == '\n') { - clean_plicy_version.erase(clean_plicy_version.size() - 1); - } - - curr_policy = Singleton::Consume::by()->parsePolicy(clean_plicy_version); - - I_OrchestrationTools *orchestration_tools = Singleton::Consume::by(); - Maybe file_checksum = orchestration_tools->calculateChecksum( - I_OrchestrationTools::SELECTED_CHECKSUM_TYPE, - Singleton::Consume::by()->getPolicyPath() - ); - - if (!file_checksum.ok()) { - dbgWarning(D_ORCHESTRATOR) << "Failed the policy checksum calculation"; - return ""; - } - return file_checksum.unpack(); -} - -Maybe -HybridCommunication::getNewVersion() -{ - I_OrchestrationTools *orchestration_tools = Singleton::Consume::by(); - auto env = Singleton::Consume::by()->getEnvType(); - if (env == I_LocalPolicyMgmtGen::LocalPolicyEnv::K8S) { - return orchestration_tools->readFile("/etc/cp/conf/k8s-policy-check.trigger"); - } - - string policy_path = getConfigurationFlagWithDefault( - getFilesystemPathConfig() + "/conf/local_policy.yaml", - "local_mgmt_policy" - ); - - Maybe file_checksum = orchestration_tools->calculateChecksum( - I_OrchestrationTools::SELECTED_CHECKSUM_TYPE, - policy_path - ); - - if (!file_checksum.ok()) { - dbgWarning(D_ORCHESTRATOR) << "Policy checksum was not calculated: " << file_checksum.getErr(); - return genError(file_checksum.getErr()); - } - - return file_checksum.unpack(); -} - Maybe HybridCommunication::getUpdate(CheckUpdateRequest &request) { @@ -117,32 +72,61 @@ HybridCommunication::getUpdate(CheckUpdateRequest &request) dbgWarning(D_ORCHESTRATOR) << "Acccess Token not available."; } - dbgTrace(D_ORCHESTRATOR) << "Getting policy update in Hybrid Communication"; - - auto maybe_new_version = getNewVersion(); - if (!maybe_new_version.ok() || maybe_new_version == curr_version) { + if (!declarative_policy_utils.shouldApplyPolicy()) { request = CheckUpdateRequest(manifest_checksum, "", "", "", "", ""); - dbgDebug(D_ORCHESTRATOR) << "No new version is currently available"; return Maybe(); } - auto policy_checksum = request.getPolicy(); + dbgTrace(D_ORCHESTRATOR) << "Getting policy update in Hybrid Communication"; - auto offline_policy_checksum = getChecksum(maybe_new_version.unpack()); + string policy_response = declarative_policy_utils.getUpdate(request); - string policy_response = ""; + auto env = Singleton::Consume::by()->getEnvType(); + if (env == I_LocalPolicyMgmtGen::LocalPolicyEnv::K8S && !policy_response.empty()) { + dbgDebug(D_ORCHESTRATOR) << "Policy has changes, sending notification to tuning host"; + I_AgentDetails *agentDetails = Singleton::Consume::by(); + I_Messaging *messaging = Singleton::Consume::by(); - if (!policy_checksum.ok() || offline_policy_checksum != policy_checksum.unpack()) { - policy_response = offline_policy_checksum; + UpdatePolicyCrdObject policy_change_object(policy_response); + + Flags conn_flags; + conn_flags.setFlag(MessageConnConfig::EXTERNAL); + + string tenant_header = "X-Tenant-Id: " + agentDetails->getTenantId(); + + auto get_tuning_host = []() + { + static string tuning_host; + if (tuning_host != "") return tuning_host; + + char* tuning_host_env = getenv(TUNING_HOST_ENV_NAME); + if (tuning_host_env != NULL) { + tuning_host = string(tuning_host_env); + return tuning_host; + } + dbgWarning(D_ORCHESTRATOR) << "tuning host is not set. using default"; + tuning_host = defaultTuningHost; + + return tuning_host; + }; + + bool ok = messaging->sendNoReplyObject( + policy_change_object, + I_Messaging::Method::POST, + get_tuning_host(), + 80, + conn_flags, + "/api/update-policy-crd", + tenant_header + ); + dbgDebug(D_ORCHESTRATOR) << "sent tuning policy update notification ok: " << ok; + if (!ok) { + dbgWarning(D_ORCHESTRATOR) << "failed to send tuning notification"; + } } - dbgDebug(D_ORCHESTRATOR) - << "Local update response: " - << " policy: " - << (policy_response.empty() ? "has no change," : "has new update," ); - request = CheckUpdateRequest(manifest_checksum, policy_response, "", "", "", ""); - curr_version = *maybe_new_version; + declarative_policy_utils.turnOffApplyPolicyFlag(); return Maybe(); } @@ -155,10 +139,9 @@ HybridCommunication::downloadAttributeFile(const GetResourceFile &resourse_file) << resourse_file.getFileName(); if (resourse_file.getFileName() == "policy") { - return curr_policy; + return declarative_policy_utils.getCurrPolicy(); } - if (resourse_file.getFileName() == "manifest") { if (!access_token.ok()) return genError("Acccess Token not available."); diff --git a/components/security_apps/orchestration/update_communication/update_communication.cc b/components/security_apps/orchestration/update_communication/update_communication.cc index a5ac217..9ef4248 100755 --- a/components/security_apps/orchestration/update_communication/update_communication.cc +++ b/components/security_apps/orchestration/update_communication/update_communication.cc @@ -50,6 +50,7 @@ public: void preload() { + registerExpectedSetting("profileManagedMode"); FogAuthenticator::preload(); LocalCommunication::preload(); } diff --git a/components/security_apps/orchestration/update_communication/update_communication_ut/CMakeLists.txt b/components/security_apps/orchestration/update_communication/update_communication_ut/CMakeLists.txt index 997e434..ebeaffd 100755 --- a/components/security_apps/orchestration/update_communication/update_communication_ut/CMakeLists.txt +++ b/components/security_apps/orchestration/update_communication/update_communication_ut/CMakeLists.txt @@ -3,5 +3,5 @@ link_directories(${BOOST_ROOT}/lib) add_unit_test( update_communication_ut "local_communication_ut.cc" - "rest;version;orchestration_modules;update_communication;singleton;config;metric;event_is;logging;agent_details;-lboost_regex;" + "rest;version;orchestration_modules;update_communication;singleton;config;metric;event_is;logging;agent_details;-lboost_regex;local_policy_mgmt_gen;connkey;" ) diff --git a/core/encryptor/cpnano_base64/CMakeLists.txt b/core/encryptor/cpnano_base64/CMakeLists.txt index c54eba8..1d4a0e6 100755 --- a/core/encryptor/cpnano_base64/CMakeLists.txt +++ b/core/encryptor/cpnano_base64/CMakeLists.txt @@ -2,5 +2,12 @@ add_executable(cpnano_base64 cpnano_base64.cc base64.cc) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COMPILE_FLAGS}") SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_LINK_FLAGS}") +add_custom_command(TARGET cpnano_base64 + POST_BUILD + COMMAND strip $ -o $.strip + COMMAND ${CMAKE_COMMAND} -E copy $.strip ${CMAKE_INSTALL_PREFIX}/bin/$.strip + COMMAND ${CMAKE_COMMAND} -E copy $.strip ${CMAKE_INSTALL_PREFIX}/orchestration/$ + COMMAND ${CMAKE_COMMAND} -E copy $.strip ${CMAKE_INSTALL_PREFIX}/wlp_standalone/$ +) + install(TARGETS cpnano_base64 DESTINATION bin/) -install(TARGETS cpnano_base64 DESTINATION orchestration/) diff --git a/core/encryptor/cpnano_base64/cpnano_base64.strip b/core/encryptor/cpnano_base64/cpnano_base64.strip new file mode 100755 index 0000000..ea38835 Binary files /dev/null and b/core/encryptor/cpnano_base64/cpnano_base64.strip differ diff --git a/core/shell_cmd/shell_cmd.cc b/core/shell_cmd/shell_cmd.cc index a31f61c..b3c6828 100755 --- a/core/shell_cmd/shell_cmd.cc +++ b/core/shell_cmd/shell_cmd.cc @@ -68,7 +68,7 @@ public: return genError("Cannot execute an empty command"); } - uint max_ms_tmout = getConfigurationWithDefault(10000u, "Infra", "Shell Command Timeout"); + uint max_ms_tmout = getConfigurationWithDefault(400000u, "Infra", "Shell Command Timeout"); if (ms_tmout > max_ms_tmout) { return genError("Provided timeout is too long, max timeout is " + to_string(max_ms_tmout)); } diff --git a/nodes/orchestration/package/open-appsec-cloud-mgmt b/nodes/orchestration/package/open-appsec-cloud-mgmt new file mode 100755 index 0000000..6a0cb71 --- /dev/null +++ b/nodes/orchestration/package/open-appsec-cloud-mgmt @@ -0,0 +1,287 @@ +#!/bin/bash + +POLICY_TEMP_PATH="/tmp/policy_temp.json" +DECLARATIVE_CONFIG_PATH="/etc/cp/conf/declarative_config.cfg" +CHANGE_AGENT_MODE=true +ra_token= +tenant_id= +agent_id= +profile_id= + +load_agent_details() +{ + tenant_id=$(cat /etc/cp/conf/agent_details.json | sed "s|Tenant ID|TenantID|g" | /etc/cp/bin/yq -P '.TenantID') + profile_id=$(cat /etc/cp/conf/agent_details.json | sed "s|Profile ID|ProfileID|g" | /etc/cp/bin/yq -P '.ProfileID') +} + +generate_policy() +{ + cp -f /etc/cp/conf/local_policy.yaml /tmp/tmp_local_policy.yaml + sed -i "s|\"\*\"|\"Any\"|g" /tmp/tmp_local_policy.yaml + POLICY=$(/etc/cp/bin/yq /tmp/tmp_local_policy.yaml -o json) + echo $POLICY > $POLICY_TEMP_PATH + rm -f /tmp/tmp_local_policy.yaml +} + +upload_the_policy_to_s3() +{ + echo "Uploading local policy configuration to cloud..." + + upload_res="$(curl -s -w "%{http_code}\n" --progress-bar --request PUT -T "${POLICY_TEMP_PATH}" \ + -H "user-agent: Infinity Next (a7030abf93a4c13)" -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${ra_token}" \ + "$var_fog/agents-core/storage/$tenant_id/$profile_id/$((AGENT_POLICY+1))/policy-$agent_id.json")" + + if test "$upload_res" != "200"; then + echo "Failed uploading policy to cloud: Failed Error code ${upload_res}" + return 1 + fi + + file_exists="$(curl -s -w "%{http_code}\n" --request GET \ + -H "user-agent: Infinity Next (a7030abf93a4c13)" -H "Authorization: Bearer ${ra_token}" \ + "$var_fog/agents-core/storage/$tenant_id/$profile_id/$((AGENT_POLICY+1))/policy-$agent_id.json")" + + check_file_exists="$(echo "$file_exists" | grep 200)" + if [ -z "$check_file_exists" ]; then + echo "Failed uploading policy to cloud: Failed on checking the file. Error code ${check_file_exists}" + return 1 + fi +} + +send_notification_to_the_fog() +{ + correlation_id=$(cat /proc/sys/kernel/random/uuid) + DATE=$(date "+%FT%T.000") + upload_res=$(curl -s -w "%{http_code}\n" --request POST \ + "$var_fog/api/v1/agents/events/bulk" -H "X-Trace-Id:${correlation_id}" \ + --header "Authorization: Bearer ${ra_token}" --header "user-agent: Infinity Next (a7030abf93a4c13)" \ + --header "Content-Type: application/json" \ + --data "{\"logs\": [{\"log\": {\"eventTime\": \ + \"$DATE\",\"eventName\": \"Agent started onboarding process to cloud management\",\"eventSeverity\": \ + \"Info\",\"eventPriority\": \"Urgent\",\"eventLogLevel\": \"info\",\"eventType\": \"Event Driven\", + \"eventLevel\": \"Log\",\"eventAudience\": \"Internal\",\"eventAudienceTeam\": \"Agent Core\", + \"eventFrequency\": 0,\"eventSource\": {\"serviceName\": \"Orchestration\",\"agentId\": \"$agent_id\", + \"tenantId\": \"$tenant_id\",\"serviceId\": \"1\",\"issuingEngineVersion\": \"1.2229.123456\", + \"issuingEngine\": \"onboardingInfoProvider\"},\"eventData\": {\"eventObject\": {\"onboardingInfo\": + {\"policyVersion\": $((AGENT_POLICY+1)),\"profileId\": \"$profile_id\"}}}, + \"eventTags\": [\"Orchestration\"]}, \"tenantId\": \"$tenant_id\", \"id\": 1}]}") + + if test "$upload_res" != "200"; then + sleep 5 + upload_res=$(curl -s -o /dev/null -s -w "%{http_code}\n" \ + --request POST "$var_fog/api/v1/agents/events/bulk" -H "X-Trace-Id:${correlation_id}" \ + --header "Authorization: Bearer ${ra_token}" --header "user-agent: Infinity Next (a7030abf93a4c13)" \ + --header "Content-Type: application/json" --data "{\"logs\": \ + [{\"log\": {\"eventTime\": \"$DATE\",\"eventName\": \"Agent started onboarding process to cloud management\", + \"eventSeverity\": \"Info\",\"eventPriority\": \"Urgent\",\"eventLogLevel\": \"info\",\"eventType\": \"Event Driven\", + \"eventLevel\": \"Log\",\"eventAudience\": \"Internal\",\"eventAudienceTeam\": \"Agent Core\",\"eventFrequency\": 0, + \"eventSource\": {\"serviceName\": \"Orchestration\",\"agentId\": \"$agent_id\",\"tenantId\": + \"$tenant_id\",\"serviceId\": \"1\",\"issuingEngineVersion\": \"1.2229.123456\",\"issuingEngine\": + \"onboardingInfoProvider\"},\"eventData\": {\"eventObject\": {\"onboardingInfo\": {\"policyVersion\": + $((AGENT_POLICY+1)),\"profileId\": \"$profile_id\"}}}, + \"eventTags\": [\"Orchestration\"]}, \"tenantId\": \"$tenant_id\", \"id\": 1}]}") + if test "$upload_res" != "200"; then + echo "Failed to notify the FOG on the new policy: Failed Error code ${upload_res}" + return 1 + fi + fi + +} + +get_jwt() +{ + response="$(curl -s -w --noproxy "*" --header "User-Agent: Infinity Next (a7030abf93a4c13)" \ + --header "Content-Type: application/json" --request POST --data \ + "{\"authenticationData\": [{\"authenticationMethod\": \"token\", \"data\": \"$var_token\"}], \ + \"metaData\": {\"agentName\": \"K8S\", \"agentType\": \"Embedded\", \"platform\": \"linux\", \ + \"architecture\": \"x86\", \"additionalMetaData\": {\"agentVendor\": \"python\"}}}" $var_fog/agents)" + + if [ ! -z "$( echo $response | grep referenceId)" ]; then + echo "Couldn't register to the FOG" + return 1 + fi + agent_id=$(echo $response | grep -o '"agentId":"[^"]*' | grep -o '[^"]*$') + echo "agent_id=${agent_id}" > $DECLARATIVE_CONFIG_PATH + clientId=$(echo $response | grep -o '"clientId":"[^"]*' | grep -o '[^"]*$') + clientSecret=$(echo $response | grep -o '"clientSecret":"[^"]*' | grep -o '[^"]*$') + tenant_id=$(echo $response | grep -o '"tenantId":"[^"]*' | grep -o '[^"]*$') + profile_id=$(echo $response | grep -o '"profileId":"[^"]*' | grep -o '[^"]*$') + + response="$(curl -s -w --noproxy "*" --header "User-Agent: Infinity Next (a7030abf93a4c13)" \ + --header "Content-Type: application/json" -d "{\"login\":\"$clientId\", \"password\":\"$clientSecret\"}" \ + --user "$clientId:$clientSecret" --request POST --data "{}" $var_fog/oauth/token?grant_type=client_credentials)" + if [ ! -z "$( echo $response | grep referenceId)" ]; then + echo "Couldn't receive JWT" + return 1 + fi + + ra_token=$(echo $response | grep -o '"access_token":"[^"]*' | grep -o '[^"]*$') + + profile_data="$(curl -s -w "%{http_code}" --request POST $var_fog/api/v2/agents/resources/ \ + -H "X-Trace-Id:2ade3b96-2451-4720-8a58-2bc83fd73292" --header "Authorization: Bearer $ra_token" \ + --header "user-agent: Infinity Next (a7030abf93a4c13)" --header "Content-Type: application/json" \ + --data "{\"manifest\": \"\",\"policy\": \"\",\"settings\": \"\",\"data\": \"\"}")" + if [ ! -z "$( echo $profile_data | grep referenceId)" ]; then + echo "Couldn't receive profile data" + return 1 + fi + policy_md5=$(echo $profile_data | grep -o '"policy":"[^"]*' | grep -o '[^"]*$') + if [ ! -z "$( echo $policy_md5 | grep referenceId)" ]; then + echo "Couldn't receive profile md5" + return 1 + fi + policy_data="$(curl -s -w '%{http_code}\n' --request GET $var_fog/api/v2/agents/resources/policy \ + -H 'X-Trace-Id:2ade3b96-2451-4720-8a58-2bc83fd73292' --header "Authorization: Bearer $ra_token" \ + --header 'user-agent: Infinity Next (a7030abf93a4c13)' --header 'Content-Type: application/json' \ + --data '{"policy": "$policy_md5"}')" + if [ ! -z "$( echo $policy_md5 | grep referenceId)" ]; then + echo "Couldn't receive policy data" + return 1 + fi + + AGENT_POLICY="$(echo $policy_data | grep -o '"version":"[^"]*' | grep -o '[^"]*$')" + echo "AGENT_POLICY=${AGENT_POLICY}" >> $DECLARATIVE_CONFIG_PATH + return 0 +} + +poll_for_status_file() +{ + correlation_id=$(cat /proc/sys/kernel/random/uuid) + attempt_counter=0 + max_attempts=18 + + until [ ${attempt_counter} -eq ${max_attempts} ]; do + if [ ${attempt_counter} -eq ${max_attempts} ];then + echo "Max attempts reached" + exit 1 + fi + file_exists="$(curl -s -w "%{http_code}\n" --request GET -H \ + "user-agent: Infinity Next (a7030abf93a4c13)" -H \ + "Authorization: Bearer ${ra_token}" \ + "$var_fog/agents-core/storage/$tenant_id/$profile_id/$((AGENT_POLICY+1))/status-$agent_id.json")" + + check_file_exists=$(echo $file_exists | grep 200) + if [ ! -z "$check_file_exists" ]; then + FAILURE=$(echo $file_exists | grep "false") + if [ ! -z "$FAILURE" ]; then + echo "Failed creating the Assets: $(echo $file_exists | cut -c27- | cut -d '"' -f 1)" + exit 1 + else + echo "." + return 0 + fi + else + echo -n '.' + attempt_counter=$(($attempt_counter+1)) + sleep 10 + fi + done + echo "Error: Status file was not generated" + exit 1 +} + +upload_policy_to_the_cloud() +{ + load_agent_details + generate_policy + STATUS="FAILURE" + if [ $CHANGE_AGENT_MODE = true ]; then + get_jwt + if [ "$?" = "1" ]; then + echo "Failed registering to the FOG" + exit 1 + fi + fi + + upload_the_policy_to_s3 + if [ "$?" = "1" ]; then + echo "Failed uploading the policy to S3" + exit 1 + fi + + send_notification_to_the_fog + if [ "$?" = "1" ]; then + echo "Failed Notifying to FOG" + exit 1 + fi + + poll_for_status_file + if [ "$?" = "0" ]; then + if [ $CHANGE_AGENT_MODE = true ]; then + open-appsec-ctl --set-mode --online_mode --token $var_token --fog $var_fog + else + sed -i "s|AGENT_POLICY=.*|AGENT_POLICY=$((AGENT_POLICY+1))|g" $DECLARATIVE_CONFIG_PATH + fi + STATUS="SUCCESS" + exit 0 + fi + if [ "$STATUS" = "FAILURE" ]; then + echo "Failed to upload policy to the cloud" + exit 1 + fi +} + +usage() +{ + echo "Usage: $0 --token [options...] ]" + echo " --token : Registration token" + echo "Options:" + echo " --namespace : Namespace with the relevant Helm Chart" + echo " --fog : Namespace with the relevant Helm Chart" + echo " --upload_policy_only : Upload policy to the fog, withput changing agent mode" + exit 255 +} + +validate_arg_value_exists() +{ + if test "$2" = "1"; then + echo "Error: The script is missing value for '$1'" + usage + exit 1 + fi +} + +while true; do + if [ "$1" = "--token" ]; then + validate_arg_value_exists "$1" "$#" + shift + var_token="$1" + elif [ "$1" = "--namespace" ]; then + validate_arg_value_exists "$1" "$#" + shift + var_namespace="$1" + elif [ "$1" = "--fog" ]; then + validate_arg_value_exists "$1" "$#" + shift + var_fog="$1" + elif [ "$1" = "--upload_policy_only" ]; then + CHANGE_AGENT_MODE=false + source $DECLARATIVE_CONFIG_PATH + elif [ "$1" = "--access_token" ] || [ "$1" = "-at" ]; then + validate_arg_value_exists "$1" "$#" + shift + ra_token="$1" + elif [ "$1" = "--tenant_id" ] || [ "$1" = "-tid" ]; then + validate_arg_value_exists "$1" "$#" + shift + tenant_id="$1" + elif [ "$1" = "--profile_id" ] || [ "$1" = "-pid" ]; then + validate_arg_value_exists "$1" "$#" + shift + profile_id="$1" + elif [ -z "$1" ]; then + break + fi + shift +done + +if [ -z "$var_fog" ]; then + var_fog="https://inext-agents.cloud.ngen.checkpoint.com" +fi + +upload_policy_to_the_cloud +if [ "$?" = "0" ]; then + echo "SUCCESS" +fi + +exit 0 diff --git a/nodes/orchestration/package/open-appsec-cloud-mgmt-k8s b/nodes/orchestration/package/open-appsec-cloud-mgmt-k8s new file mode 100755 index 0000000..5f4d254 --- /dev/null +++ b/nodes/orchestration/package/open-appsec-cloud-mgmt-k8s @@ -0,0 +1,285 @@ +#!/bin/bash + +POLICY_CRDS_PATH="/tmp/policy_crds.json" +APISERVER=https://kubernetes.default.svc +SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount +TOKEN=$(cat ${SERVICEACCOUNT}/token) +NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace) +CACERT=${SERVICEACCOUNT}/ca.crt +ra_token= +tenant_id= +agent_id= +profile_id= +cluster_id= +latest_policy_version=1 + +load_agent_details() +{ + tenant_id=$(cat /etc/cp/conf/agent_details.json | sed "s|Tenant ID|TenantID|g" | /etc/cp/bin/yq -P '.TenantID') + agent_id=$(cat /etc/cp/conf/agent_details.json | sed "s|Agent ID|AgentID|g" | /etc/cp/bin/yq -P '.AgentID') + profile_id=$(cat /etc/cp/conf/agent_details.json | sed "s|Profile ID|ProfileID|g" | /etc/cp/bin/yq -P '.ProfileID') + cluster_id=$(echo $(curl -s --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api/v1/namespaces/ ) \ + | /etc/cp/bin/yq .items | /etc/cp/bin/yq '.[] | select(.metadata.name | contains("kube-system"))' | /etc/cp/bin/yq .metadata.uid) +} + +get_latest_policy_version() +{ + bucket_list=$(curl -s -w "%{http_code}\n" --request GET \ + -H "user-agent: Infinity Next (a7030abf93a4c13)" -H "Authorization: Bearer ${ra_token}" \ + "$var_fog/agents-core/storage/?list-type=2&prefix=${tenant_id}/${profile_id}") + paths_list=$(echo $bucket_list | /etc/cp/bin/yq -p xml | grep "/policy") + + prefix="${tenant_id}/${profile_id}" + paths=$(echo $paths_list | tr " " "\n" | grep / ) + for path in $paths; do + new_path=$(echo ${path%/*}) + version=$(echo ${new_path##*/}) + if [[ $version =~ ^-?[0-9]+$ ]] && [ $latest_policy_version -lt $version ]; then + latest_policy_version=$version + fi + done + latest_policy_version=$((latest_policy_version+1)) + echo "Policy version: $latest_policy_version" +} + +concat_to_policy() +{ + crd_to_concat="$1" + is_first=$2 + if [ ! -z $is_first ]; then + POLICY="$POLICY \"$1\": " + else + POLICY="$POLICY, \"$1\": " + fi + CRD=$(curl -s --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" \ + -X GET ${APISERVER}/apis/openappsec.io/v1beta1/$crd_to_concat) + CRD=$(echo $CRD|tr -d '\n') + if [ -z "$CRD" ]; then + CRD="{}" + fi + POLICY="$POLICY $CRD" +} + +generate_policy() +{ + POLICY="{ \"Policy\": {" + concat_to_policy policies true + concat_to_policy practices + concat_to_policy logtriggers + concat_to_policy customresponses + concat_to_policy exceptions + concat_to_policy sourcesidentifiers + concat_to_policy trustedsources + + POLICY="$POLICY, \"assets\": { \"items\":[ " + + FIRST="1" + all_ingresses=$(curl -s --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" \ + -X GET ${APISERVER}/apis/networking.k8s.io/v1/ingresses) + namespaces=$(echo $all_ingresses | /etc/cp/bin/yq -P '.items[].metadata.namespace') + + for ns in ${namespaces}; do + ingress_in_ns=$(curl -s --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" \ + -X GET ${APISERVER}/apis/networking.k8s.io/v1/namespaces/${ns}/ingresses) + ingress_list=$(echo $ingress_in_ns | /etc/cp/bin/yq -P '.items[].metadata.name') + for ingress_name in ${ingress_list}; do + ingress_crd=$(curl -s --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" \ + -X GET ${APISERVER}/apis/networking.k8s.io/v1/namespaces/${ns}/ingresses/${ingress_name}) + + if echo $ingress_crd | grep -n "openappsec" 1>/dev/null; then + ingress_crd=$(echo $ingress_crd | tr -d '\n') + fi + if [ "$FIRST" = "0" ]; then + POLICY="$POLICY ," + fi + POLICY="$POLICY $ingress_crd" + FIRST="0" + done + done + + POLICY="$POLICY ] } } }" + echo $POLICY > $POLICY_CRDS_PATH +} + +upload_the_crds_to_s3() +{ + echo "Uploading local configuration to cloud..." + upload_res="$(curl -o /dev/null -s -w "%{http_code}\n" --progress-bar --request PUT -T "${POLICY_CRDS_PATH}" \ + -H "user-agent: Infinity Next (a7030abf93a4c13)" -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${ra_token}" \ + "$var_fog/agents-core/storage/$tenant_id/$profile_id/$latest_policy_version/policy-$cluster_id.json")" + + if test "$upload_res" != "200"; then + echo "Failed uploading CRDs to cloud: Failed Error code ${upload_res}" + return 1 + fi + + check_file_exists="$(curl -o /dev/null -s -w "%{http_code}\n" --request GET -H "user-agent: Infinity Next (a7030abf93a4c13)" \ + -H "Authorization: Bearer ${ra_token}" \ + "$var_fog/agents-core/storage/$tenant_id/$profile_id/$latest_policy_version/policy-$cluster_id.json")" + if test "$check_file_exists" != "200"; then + echo "Failed uploading CRD to cloud: Failed on checking the file. Error code ${check_file_exists}" + return 1 + fi +} + +send_notification_to_the_fog() +{ + correlation_id=$(cat /proc/sys/kernel/random/uuid) + DATE=$(date "+%FT%T.000") + upload_res=$(curl -o /dev/null -s -w "%{http_code}\n" --request POST "$var_fog/api/v1/agents/events/bulk" \ + -H "X-Trace-Id:${correlation_id}" --header "Authorization: Bearer ${ra_token}" \ + --header "user-agent: Infinity Next (a7030abf93a4c13)" --header "Content-Type: application/json" \ + --data "{\"logs\": [{\"log\": {\"eventTime\": \"$DATE\",\"eventName\": \ + \"Agent started onboarding process to cloud management\",\"eventSeverity\": \"Info\",\"eventPriority\": \ + \"Urgent\",\"eventLogLevel\": \"info\",\"eventType\": \"Event Driven\",\"eventLevel\": \"Log\",\"eventAudience\": \ + \"Internal\",\"eventAudienceTeam\": \"Agent Core\",\"eventFrequency\": 0,\"eventSource\": {\"serviceName\": \ + \"Orchestration\",\"agentId\": \"$agent_id\",\"tenantId\": \"$tenant_id\",\"serviceId\": \"1\",\"issuingEngineVersion\": \ + \"1.2229.123456\",\"issuingEngine\": \"onboardingInfoProvider\"},\"eventData\": {\"eventObject\": {\"onboardingInfo\": \ + {\"policyVersion\": $latest_policy_version,\"clusterId\": \"$cluster_id\",\"profileId\": \"$profile_id\"}}},\ + \"eventTags\": [\"Orchestration\"]}, \"tenantId\": \"$tenant_id\", \"id\": 1}]}") + + if test "$upload_res" != "200"; then + sleep 5 + upload_res=$(curl -o /dev/null -s -w "%{http_code}\n" --request POST "$var_fog/api/v1/agents/events/bulk" \ + -H "X-Trace-Id:${correlation_id}" --header "Authorization: Bearer ${ra_token}" \ + --header "user-agent: Infinity Next (a7030abf93a4c13)" --header "Content-Type: application/json" \ + --data "{\"logs\": [{\"log\": {\"eventTime\": \"$DATE\",\"eventName\": \ + \"Agent started onboarding process to cloud management\",\"eventSeverity\": \"Info\",\"eventPriority\": \ + \"Urgent\",\"eventLogLevel\": \"info\",\"eventType\": \"Event Driven\",\"eventLevel\": \"Log\",\ + \"eventAudience\": \"Internal\",\"eventAudienceTeam\": \"Agent Core\",\"eventFrequency\": 0,\"eventSource\": \ + {\"serviceName\": \"Orchestration\",\"agentId\": \"$agent_id\",\"tenantId\": \"$tenant_id\",\ + \"serviceId\": \"1\",\"issuingEngineVersion\": \"1.2229.123456\",\"issuingEngine\": \"onboardingInfoProvider\"},\ + \"eventData\": {\"eventObject\": {\"onboardingInfo\": {\"policyVersion\": $latest_policy_version,\ + \"clusterId\": \"$cluster_id\",\"profileId\": \"$profile_id\"}}},\"eventTags\": [\"Orchestration\"]}, \ + \"tenantId\": \"$tenant_id\", \"id\": 1}]}") + if test "$upload_res" != "200"; then + echo "Failed to notify the FOG on the new CRDs: Failed Error code ${upload_res}" + return 1 + fi + fi +} + +poll_for_status_file() +{ + correlation_id=$(cat /proc/sys/kernel/random/uuid) + + attempt_counter=0 + max_attempts=18 + + until [ ${attempt_counter} -eq ${max_attempts} ]; do + if [ ${attempt_counter} -eq ${max_attempts} ];then + echo "Max attempts reached" + exit 1 + fi + file_exists="$(curl -s -w "%{http_code}\n" --request GET -H "user-agent: Infinity Next (a7030abf93a4c13)" \ + -H "Authorization: Bearer ${ra_token}" \ + "$var_fog/agents-core/storage/$tenant_id/$profile_id/$latest_policy_version/status-$cluster_id.json")" + + check_file_exists=$(echo $file_exists | grep 200) + if [ ! -z "$check_file_exists" ]; then + FAILURE=$(echo $file_exists | grep "false") + if [ ! -z "$FAILURE" ]; then + echo "Failed creating the Assets: $(echo $file_exists | cut -c27- | cut -d '"' -f 1)" + exit 1 + else + echo "." + return 0 + fi + else + echo -n '.' + attempt_counter=$(($attempt_counter+1)) + sleep 10 + fi + done + echo "Error: Status file was not generated" + exit 1 +} + +upload_crds_to_the_cloud() +{ + STATUS="FAILURE" + load_agent_details + get_latest_policy_version + generate_policy + + upload_the_crds_to_s3 + if [ "$?" = "1" ]; then + echo "Failed uploading the CRDs to S3" + exit 1 + fi + + send_notification_to_the_fog + if [ "$?" = "1" ]; then + echo "Failed Notifying to FOG" + exit 1 + fi + + poll_for_status_file + if [ "$?" = "0" ]; then + STATUS="SUCCESS" + fi + + if [ "$STATUS" = "FAILURE" ]; then + echo "Failed to upload CRDs to the cloud" + exit 1 + fi +} + +usage() +{ + echo "Usage: $0 --token [options...] ]" + echo " --token : Registration token" + echo "Options:" + echo " --fog : Namespace with the relevant Helm Chart" + echo " --upload_policy_only : Upload policy to the fog, withput changing agent mode" + exit 255 +} + +validate_flags() +{ + if [ -z $var_token ]; then + usage + exit 1 + fi +} + +validate_arg_value_exists() +{ + if test "$2" = "1"; then + echo "Error: The script is missing value for '$1'" + usage + exit 1 + fi +} + +while true; do + if [ "$1" = "--token" ]; then + validate_arg_value_exists "$1" "$#" + shift + var_token="$1" + elif [ "$1" = "--fog" ]; then + validate_arg_value_exists "$1" "$#" + shift + var_fog="$1" + elif [ "$1" = "--access_token" ] || [ "$1" = "-at" ]; then + validate_arg_value_exists "$1" "$#" + shift + ra_token="$1" + elif [ -z "$1" ]; then + break + fi + shift +done + +if [ -z "$var_fog" ]; then + var_fog=$(cat /etc/cp/conf/agent_details.json | sed "s|Fog domain|Fogdomain|g" | /etc/cp/bin/yq -P '.Fogdomain') + var_fog="https://$var_fog" +fi + +upload_crds_to_the_cloud +if [ "$?" = "0" ]; then + echo "SUCCESS" +fi + +exit 0 diff --git a/nodes/orchestration/package/orchestration_package.sh b/nodes/orchestration/package/orchestration_package.sh index 7bde5bf..cac5578 100755 --- a/nodes/orchestration/package/orchestration_package.sh +++ b/nodes/orchestration/package/orchestration_package.sh @@ -655,6 +655,9 @@ copy_orchestration_executable() cp_print "Copying cp-nano-agent binary file to folder: ${FILESYSTEM_PATH}/${SERVICE_PATH}/${ORCHESTRATION_FILE_NAME}" $FORCE_STDOUT cp_copy "$ORCHESTRATION_EXE_SOURCE_PATH" ${FILESYSTEM_PATH}/${SERVICE_PATH}/${ORCHESTRATION_FILE_NAME} cp_exec "chmod 700 ${FILESYSTEM_PATH}/${SERVICE_PATH}/${ORCHESTRATION_FILE_NAME}" + cp_copy open-appsec-cloud-mgmt ${FILESYSTEM_PATH}/${SCRIPTS_PATH}/open-appsec-cloud-mgmt + cp_copy open-appsec-cloud-mgmt-k8s ${FILESYSTEM_PATH}/${SCRIPTS_PATH}/open-appsec-cloud-mgmt-k8s + cp_copy open-appsec-ctl.sh ${FILESYSTEM_PATH}/${SCRIPTS_PATH}/open-appsec-ctl.sh if [ $var_hybrid_mode = true ]; then cp_copy local-default-policy.yaml ${FILESYSTEM_PATH}/${CONF_PATH}/local_policy.yaml fi