mirror of
https://github.com/openappsec/openappsec.git
synced 2025-09-30 03:34:26 +03:00
First release of open-appsec source code
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
add_library(update_communication update_communication.cc hybrid_communication.cc fog_communication.cc fog_authenticator.cc local_communication.cc)
|
||||
|
||||
add_subdirectory(update_communication_ut)
|
572
components/security_apps/orchestration/update_communication/fog_authenticator.cc
Executable file
572
components/security_apps/orchestration/update_communication/fog_authenticator.cc
Executable file
@@ -0,0 +1,572 @@
|
||||
// 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 "fog_communication.h"
|
||||
#include "rest.h"
|
||||
#include "config.h"
|
||||
#include "log_generator.h"
|
||||
#include "agent_details.h"
|
||||
#include "version.h"
|
||||
#include "sasal.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
SASAL_START // Orchestration - Communication
|
||||
|
||||
using namespace std;
|
||||
using namespace cereal;
|
||||
using HTTPMethod = I_Messaging::Method;
|
||||
|
||||
USE_DEBUG_FLAG(D_ORCHESTRATOR);
|
||||
|
||||
function<Maybe<FogAuthenticator::AccessToken>()> FogAuthenticator::AccessTokenProvider::getAccessToken = nullptr;
|
||||
|
||||
FogAuthenticator::AccessToken::AccessToken(const string &_token, chrono::seconds _expiration)
|
||||
:
|
||||
token(_token),
|
||||
expiration(_expiration)
|
||||
{
|
||||
received_time = Singleton::Consume<I_TimeGet>::by<FogAuthenticator>()->getMonotonicTime();
|
||||
}
|
||||
|
||||
chrono::seconds
|
||||
FogAuthenticator::AccessToken::getRemainingTime() const
|
||||
{
|
||||
return
|
||||
expiration -
|
||||
chrono::duration_cast<chrono::seconds>(
|
||||
Singleton::Consume<I_TimeGet>::by<FogAuthenticator>()->getMonotonicTime() - received_time
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
FogAuthenticator::AccessTokenProvider::doCall()
|
||||
{
|
||||
if (getAccessToken != nullptr) {
|
||||
auto access_token = getAccessToken();
|
||||
if (access_token.ok()) {
|
||||
auto encryptor = Singleton::Consume<I_Encryptor>::by<FogAuthenticator>();
|
||||
token = encryptor->obfuscateXorBase64(access_token.unpack().getToken());
|
||||
expiration = access_token.unpack().getRemainingTime().count();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FogAuthenticator::RegistrationData::RegistrationData(const string &token)
|
||||
:
|
||||
type(AuthenticationType::Token),
|
||||
data(token)
|
||||
{
|
||||
}
|
||||
|
||||
FogAuthenticator::UserCredentials::UserCredentials(const string &_client_id, const string &_shared_secret)
|
||||
:
|
||||
client_id(_client_id),
|
||||
shared_secret(_shared_secret)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
FogAuthenticator::UserCredentials::serialize(JSONOutputArchive &out_ar) const
|
||||
{
|
||||
out_ar(
|
||||
make_nvp("client_id", client_id),
|
||||
make_nvp("shared_secret", shared_secret)
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
FogAuthenticator::UserCredentials::serialize(JSONInputArchive &in_ar)
|
||||
{
|
||||
in_ar(
|
||||
make_nvp("client_id", client_id),
|
||||
make_nvp("shared_secret", shared_secret)
|
||||
);
|
||||
|
||||
if (client_id.empty() || shared_secret.empty()) {
|
||||
throw cereal::Exception("Agent credentials can't be empty.");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FogAuthenticator::RegistrationData::serialize(JSONInputArchive &in_ar)
|
||||
{
|
||||
string type_as_string;
|
||||
static const map<string, AuthenticationType> StringToAuthenticationType {
|
||||
{ "token", AuthenticationType::Token },
|
||||
{ "presharedsecret", AuthenticationType::PresharedSecret }
|
||||
};
|
||||
|
||||
in_ar(
|
||||
make_nvp("registration type", type_as_string),
|
||||
make_nvp("registration data", data)
|
||||
);
|
||||
|
||||
if (type_as_string.empty()) throw cereal::Exception("registration type can't be empty.");
|
||||
if (data.empty()) throw cereal::Exception("registration data can't be empty.");
|
||||
|
||||
auto auth_type = StringToAuthenticationType.find(type_as_string);
|
||||
if (auth_type == StringToAuthenticationType.end()) throw cereal::Exception("Unsupported registration type.");
|
||||
type = auth_type->second;
|
||||
}
|
||||
|
||||
void
|
||||
FogAuthenticator::RegistrationData::serialize(JSONOutputArchive &out_ar) const
|
||||
{
|
||||
static const EnumArray<AuthenticationType, string> AuthenticationTypeString {
|
||||
"token",
|
||||
"presharedsecret"
|
||||
};
|
||||
|
||||
out_ar(
|
||||
make_nvp("authenticationMethod", AuthenticationTypeString[type]),
|
||||
make_nvp("data", data)
|
||||
);
|
||||
}
|
||||
|
||||
Maybe<FogAuthenticator::UserCredentials>
|
||||
FogAuthenticator::registerAgent(
|
||||
const FogAuthenticator::RegistrationData ®_data,
|
||||
const string &name,
|
||||
const string &type,
|
||||
const string &platform,
|
||||
const string &architecture) const
|
||||
{
|
||||
dbgInfo(D_ORCHESTRATOR) << "Starting agent registration to fog";
|
||||
|
||||
auto details_resolver = Singleton::Consume<I_DetailsResolver>::by<FogAuthenticator>();
|
||||
RegistrationRequest request(
|
||||
reg_data,
|
||||
name,
|
||||
type,
|
||||
platform,
|
||||
architecture,
|
||||
details_resolver->getAgentVersion()
|
||||
);
|
||||
|
||||
request << make_pair("agent_version", details_resolver->getAgentVersion());
|
||||
|
||||
if (required_security_apps.size() > 0) {
|
||||
request << make_pair("require", makeSeparatedStr(required_security_apps, ";"));
|
||||
}
|
||||
|
||||
auto nginx_data = details_resolver->parseNginxMetadata();
|
||||
|
||||
if (nginx_data.ok()) {
|
||||
string nginx_version;
|
||||
string config_opt;
|
||||
string cc_opt;
|
||||
tie(config_opt, cc_opt, nginx_version) = nginx_data.unpack();
|
||||
request << make_pair("nginxVersion", nginx_version);
|
||||
request << make_pair("configureOpt", config_opt);
|
||||
request << make_pair("extraCompilerOpt", cc_opt);
|
||||
} else {
|
||||
dbgDebug(D_ORCHESTRATOR) << nginx_data.getErr();
|
||||
}
|
||||
|
||||
for (const pair<string, string> details : details_resolver->getResolvedDetails()) {
|
||||
request << details;
|
||||
}
|
||||
|
||||
if (details_resolver->isReverseProxy()) {
|
||||
request << make_pair("reverse_proxy", "true");
|
||||
}
|
||||
|
||||
if (details_resolver->isKernelVersion3OrHigher()) {
|
||||
request << make_pair("isKernelVersion3OrHigher", "true");
|
||||
}
|
||||
|
||||
if (details_resolver->isGwNotVsx()) {
|
||||
request << make_pair("isGwNotVsx", "true");
|
||||
}
|
||||
|
||||
if (details_resolver->isVersionEqualOrAboveR8110()) {
|
||||
request << make_pair("isVersionEqualOrAboveR8110", "true");
|
||||
}
|
||||
|
||||
#if defined(gaia) || defined(smb)
|
||||
if (details_resolver->compareCheckpointVersion(8100, std::greater_equal<int>())) {
|
||||
request << make_pair("isCheckpointVersionGER81", "true");
|
||||
}
|
||||
#endif // gaia || smb
|
||||
|
||||
auto fog_messaging = Singleton::Consume<I_Messaging>::by<FogAuthenticator>();
|
||||
if (fog_messaging->sendObject(request, HTTPMethod::POST, fog_address_ex + "/agents")) {
|
||||
dbgDebug(D_ORCHESTRATOR) << "Agent has registered successfully.";
|
||||
auto i_agent_details = Singleton::Consume<I_AgentDetails>::by<FogAuthenticator>();
|
||||
i_agent_details->setAgentId(request.getAgentId());
|
||||
i_agent_details->setProfileId(request.getProfileId());
|
||||
i_agent_details->setTenantId(request.getTenantId());
|
||||
i_agent_details->writeAgentDetails();
|
||||
|
||||
auto orc_status = Singleton::Consume<I_OrchestrationStatus>::by<FogAuthenticator>();
|
||||
orc_status->setAgentDetails(request.getAgentId(), request.getProfileId(), request.getTenantId());
|
||||
return UserCredentials(request.getClientId(), request.getSharedSecret());
|
||||
}
|
||||
|
||||
LogGen log(
|
||||
"We suggest to check that your Agent Profile is defined and enforced",
|
||||
ReportIS::Audience::SECURITY,
|
||||
ReportIS::Severity::INFO,
|
||||
ReportIS::Priority::MEDIUM,
|
||||
LogField("source", "fog_communication"),
|
||||
ReportIS::Tags::ORCHESTRATOR
|
||||
);
|
||||
|
||||
return genError("Failed to register agent with the Fog");
|
||||
}
|
||||
|
||||
Maybe<FogAuthenticator::AccessToken>
|
||||
FogAuthenticator::getAccessToken(const UserCredentials &user_credentials) const
|
||||
{
|
||||
dbgDebug(D_ORCHESTRATOR) << "Requesting token from fog.";
|
||||
static const string grant_type_string = "/oauth/token?grant_type=client_credentials";
|
||||
TokenRequest request = TokenRequest();
|
||||
|
||||
auto fog_messaging = Singleton::Consume<I_Messaging>::by<FogAuthenticator>();
|
||||
auto sending_result = fog_messaging->sendObject(
|
||||
request,
|
||||
HTTPMethod::POST,
|
||||
fog_address_ex + grant_type_string,
|
||||
buildBasicAuthHeader(user_credentials.getClientId(), user_credentials.getSharedSecret())
|
||||
);
|
||||
|
||||
if (sending_result) {
|
||||
auto data_path = getConfigurationWithDefault<string>(
|
||||
filesystem_prefix + "/data/",
|
||||
"encryptor",
|
||||
"Data files directory"
|
||||
);
|
||||
auto orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<FogAuthenticator>();
|
||||
if (!orchestration_tools->writeFile(request.getAccessToken(), data_path + session_token_file_name)) {
|
||||
return genError("Failed to write new access token to file");
|
||||
}
|
||||
|
||||
dbgInfo(D_ORCHESTRATOR) << "New access token was saved";
|
||||
fog_messaging->loadAccessToken();
|
||||
|
||||
return AccessToken(request.getAccessToken(), chrono::seconds(request.getExpirationTime()));
|
||||
}
|
||||
|
||||
return genError("Failed to get access token.");
|
||||
}
|
||||
|
||||
Maybe<FogAuthenticator::RegistrationData>
|
||||
FogAuthenticator::getRegistrationData()
|
||||
{
|
||||
if (!otp.empty()) {
|
||||
reg_data = RegistrationData(otp);
|
||||
return reg_data;
|
||||
}
|
||||
|
||||
const char *env_otp = getenv("NANO_AGENT_TOKEN");
|
||||
if (env_otp) {
|
||||
dbgInfo(D_ORCHESTRATOR) << "Loading registration token from environment";
|
||||
return RegistrationData(env_otp);
|
||||
}
|
||||
if (reg_data.ok()) {
|
||||
dbgInfo(D_ORCHESTRATOR) << "Loading registration token from cache";
|
||||
return reg_data;
|
||||
}
|
||||
|
||||
auto reg_data_path = getConfigurationWithDefault<string>(
|
||||
filesystem_prefix + "/conf/registration-data.json",
|
||||
"orchestration",
|
||||
"Registration data Path"
|
||||
);
|
||||
|
||||
dbgDebug(D_ORCHESTRATOR) << "Loading registration data from " << reg_data_path;
|
||||
auto orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<FogAuthenticator>();
|
||||
auto raw_reg_data = orchestration_tools->readFile(reg_data_path);
|
||||
if (!raw_reg_data.ok()) return genError(raw_reg_data.getErr());
|
||||
|
||||
dbgTrace(D_ORCHESTRATOR) << "Successfully loaded the registration data";
|
||||
auto decoded_reg_data = orchestration_tools->base64Decode(raw_reg_data.unpack());
|
||||
reg_data = orchestration_tools->jsonStringToObject<RegistrationData>(decoded_reg_data);
|
||||
|
||||
if (reg_data.ok()) {
|
||||
dbgTrace(D_ORCHESTRATOR) << "Registration token has been converted to an object";
|
||||
}
|
||||
|
||||
return reg_data;
|
||||
}
|
||||
|
||||
bool
|
||||
FogAuthenticator::saveCredentialsToFile(const UserCredentials &user_credentials) const
|
||||
{
|
||||
auto data_path = getConfigurationWithDefault<string>(
|
||||
filesystem_prefix + "/data/",
|
||||
"encryptor",
|
||||
"Data files directory"
|
||||
);
|
||||
|
||||
auto orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<FogAuthenticator>();
|
||||
auto cred_str = orchestration_tools->objectToJson<UserCredentials>(user_credentials);
|
||||
if (!cred_str.ok()) {
|
||||
dbgWarning(D_ORCHESTRATOR) << "Failed to parse user credentials to JSON. Error: " << cred_str.getErr();
|
||||
return false;
|
||||
}
|
||||
|
||||
return orchestration_tools->writeFile(cred_str.unpack(), data_path + user_cred_file_name);
|
||||
}
|
||||
|
||||
void
|
||||
FogAuthenticator::initRestAPI()
|
||||
{
|
||||
AccessTokenProvider::getAccessToken = [this] () {
|
||||
return access_token;
|
||||
};
|
||||
|
||||
auto rest = Singleton::Consume<I_RestApi>::by<FogAuthenticator>();
|
||||
rest->addRestCall<FogAuthenticator::AccessTokenProvider>(RestAction::SHOW, "access-token");
|
||||
}
|
||||
|
||||
Maybe<FogAuthenticator::UserCredentials>
|
||||
FogAuthenticator::getCredentialsFromFile() const
|
||||
{
|
||||
auto data_path = getConfigurationWithDefault<string>(
|
||||
filesystem_prefix + "/data/",
|
||||
"encryptor",
|
||||
"Data files directory"
|
||||
);
|
||||
|
||||
auto orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<FogAuthenticator>();
|
||||
auto encrypted_cred = orchestration_tools->readFile(data_path + user_cred_file_name);
|
||||
if (!encrypted_cred.ok()) return genError(encrypted_cred.getErr());
|
||||
|
||||
dbgTrace(D_ORCHESTRATOR) << "Read the user credentials from the file";
|
||||
return orchestration_tools->jsonStringToObject<UserCredentials>(encrypted_cred.unpack());
|
||||
}
|
||||
|
||||
Maybe<FogAuthenticator::UserCredentials>
|
||||
FogAuthenticator::getCredentials()
|
||||
{
|
||||
auto maybe_credentials = getCredentialsFromFile();
|
||||
if (maybe_credentials.ok()) {
|
||||
return maybe_credentials;
|
||||
}
|
||||
|
||||
auto reg_data = getRegistrationData();
|
||||
if (!reg_data.ok()) {
|
||||
return genError("Failed to load a valid registration token, Error: " + reg_data.getErr());
|
||||
}
|
||||
|
||||
auto details_resolver = Singleton::Consume<I_DetailsResolver>::by<FogAuthenticator>();
|
||||
Maybe<string> name = details_resolver->getHostname();
|
||||
if (!name.ok()) return name.passErr();
|
||||
|
||||
Maybe<string> platform = details_resolver->getPlatform();
|
||||
if (!platform.ok()) return platform.passErr();
|
||||
|
||||
Maybe<string> arch = details_resolver->getArch();
|
||||
if (!arch.ok()) return arch.passErr();
|
||||
|
||||
string type = getConfigurationWithDefault<string>("Embedded", "orchestration", "Agent type");
|
||||
maybe_credentials = registerAgent(reg_data.unpack(), *name, type, *platform, *arch);
|
||||
|
||||
auto orc_status = Singleton::Consume<I_OrchestrationStatus>::by<FogAuthenticator>();
|
||||
orc_status->setRegistrationDetails(*name, type, *platform, *arch);
|
||||
|
||||
if (!maybe_credentials.ok()) return maybe_credentials;
|
||||
|
||||
auto credentials = maybe_credentials.unpack();
|
||||
auto token_path = getConfigurationWithDefault<string>(
|
||||
filesystem_prefix + "/conf/registration-data.json",
|
||||
"orchestration",
|
||||
"Registration data Path"
|
||||
);
|
||||
|
||||
auto orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<FogAuthenticator>();
|
||||
if (saveCredentialsToFile(credentials)) {
|
||||
if (!orchestration_tools->removeFile(token_path)) {
|
||||
dbgWarning(D_ORCHESTRATOR) << "Failed to remove one time token file";
|
||||
}
|
||||
return credentials;
|
||||
}
|
||||
|
||||
dbgWarning(D_ORCHESTRATOR) << "Failed to save credentials to file";
|
||||
Singleton::Consume<I_MainLoop>::by<FogAuthenticator>()->addOneTimeRoutine(
|
||||
I_MainLoop::RoutineType::Offline,
|
||||
[this, credentials, token_path] ()
|
||||
{
|
||||
auto orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<FogAuthenticator>();
|
||||
static uint retry_counter = 1;
|
||||
while (!saveCredentialsToFile(credentials)) {
|
||||
dbgTrace(D_ORCHESTRATOR) << "Failed to save credentials to file, retry number: " << retry_counter++;
|
||||
Singleton::Consume<I_MainLoop>::by<FogAuthenticator>()->yield(chrono::seconds(60));
|
||||
}
|
||||
|
||||
if (!orchestration_tools->removeFile(token_path)) {
|
||||
dbgWarning(D_ORCHESTRATOR) << "Failed to remove one time token file";
|
||||
}
|
||||
},
|
||||
"Fog credential save to file"
|
||||
);
|
||||
|
||||
return credentials;
|
||||
}
|
||||
|
||||
string
|
||||
FogAuthenticator::buildBasicAuthHeader(const string &username, const string &pass) const
|
||||
{
|
||||
auto orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<FogAuthenticator>();
|
||||
auto auth_encode = orchestration_tools->base64Encode(username + ":" + pass);
|
||||
return "Authorization: Basic " + auth_encode + "\r\n";
|
||||
}
|
||||
|
||||
string
|
||||
FogAuthenticator::buildOAuth2Header(const string &token) const
|
||||
{
|
||||
return "Authorization: Bearer " + token + "\r\n";
|
||||
}
|
||||
|
||||
void
|
||||
FogAuthenticator::setAddressExtenesion(const std::string &extension)
|
||||
{
|
||||
fog_address_ex = extension;
|
||||
}
|
||||
|
||||
|
||||
Maybe<void>
|
||||
FogAuthenticator::authenticateAgent()
|
||||
{
|
||||
const int min_expiration_time = 10;
|
||||
if (!credentials.ok()) {
|
||||
dbgDebug(D_ORCHESTRATOR) << "Getting Agent credentials.";
|
||||
|
||||
auto orc_status = Singleton::Consume<I_OrchestrationStatus>::by<FogAuthenticator>();
|
||||
credentials = getCredentials();
|
||||
if (!credentials.ok()) {
|
||||
orc_status->setFieldStatus(
|
||||
OrchestrationStatusFieldType::REGISTRATION,
|
||||
OrchestrationStatusResult::FAILED,
|
||||
credentials.getErr()
|
||||
);
|
||||
return genError(credentials.getErr());
|
||||
}
|
||||
orc_status->setFieldStatus(
|
||||
OrchestrationStatusFieldType::REGISTRATION,
|
||||
OrchestrationStatusResult::SUCCESS
|
||||
);
|
||||
}
|
||||
|
||||
auto mainloop = Singleton::Consume<I_MainLoop>::by<FogAuthenticator>();
|
||||
if (!mainloop->doesRoutineExist(routine)) {
|
||||
routine = mainloop->addOneTimeRoutine(
|
||||
I_MainLoop::RoutineType::RealTime,
|
||||
[this, min_expiration_time] ()
|
||||
{
|
||||
uint expiration_time;
|
||||
uint pre_expire_time = 0;
|
||||
do {
|
||||
expiration_time = 20;
|
||||
auto orc_status = Singleton::Consume<I_OrchestrationStatus>::by<FogAuthenticator>();
|
||||
access_token = getAccessToken(credentials.unpack());
|
||||
if (access_token.ok()) {
|
||||
pre_expire_time = getConfigurationWithDefault<int>(
|
||||
120,
|
||||
"fog communication",
|
||||
"Time (seconds) to renew token prior its expiration"
|
||||
);
|
||||
expiration_time = access_token.unpack().getExpiration();
|
||||
dbgInfo(D_ORCHESTRATOR) << "New token was received, expiration time: " << expiration_time;
|
||||
orc_status->setFieldStatus(
|
||||
OrchestrationStatusFieldType::REGISTRATION,
|
||||
OrchestrationStatusResult::SUCCESS
|
||||
);
|
||||
} else {
|
||||
dbgWarning(D_ORCHESTRATOR)
|
||||
<< "Failed to receive access token. Error: " << access_token.getErr();
|
||||
orc_status->setFieldStatus(
|
||||
OrchestrationStatusFieldType::REGISTRATION,
|
||||
OrchestrationStatusResult::FAILED,
|
||||
access_token.getErr()
|
||||
);
|
||||
}
|
||||
int next_session_req = max(
|
||||
static_cast<int>(expiration_time - pre_expire_time),
|
||||
min_expiration_time
|
||||
);
|
||||
dbgDebug(D_ORCHESTRATOR)
|
||||
<< "Schedule the next re-activate session token. Seconds: "
|
||||
<< next_session_req;
|
||||
Singleton::Consume<I_MainLoop>::by<FogAuthenticator>()->yield(chrono::seconds(next_session_req));
|
||||
} while (1);
|
||||
},
|
||||
"Fog communication token periodic update",
|
||||
true
|
||||
);
|
||||
// Wait for the access token mainloop
|
||||
mainloop->yield(chrono::seconds(min_expiration_time + 1));
|
||||
}
|
||||
|
||||
if (!access_token.ok()) return genError(access_token.getErr());
|
||||
return Maybe<void>();
|
||||
}
|
||||
|
||||
void
|
||||
FogAuthenticator::preload()
|
||||
{
|
||||
registerExpectedConfiguration<string>("orchestration", "Agent type");
|
||||
registerExpectedConfiguration<string>("orchestration", "OTP Token Path");
|
||||
registerExpectedConfiguration<string>("orchestration", "User Credentials Path");
|
||||
registerExpectedConfiguration<int>("fog communication", "Time (seconds) to renew token prior its expiration");
|
||||
}
|
||||
|
||||
void
|
||||
FogAuthenticator::loadRequiredSecurityApps()
|
||||
{
|
||||
auto required_apps_file_path = getConfigurationWithDefault<string>(
|
||||
filesystem_prefix + "/conf/support-practices.txt",
|
||||
"orchestration",
|
||||
"Supported practices file path"
|
||||
);
|
||||
|
||||
auto orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<FogAuthenticator>();
|
||||
if (orchestration_tools->doesFileExist(required_apps_file_path)) {
|
||||
try {
|
||||
ifstream input_stream(required_apps_file_path);
|
||||
if (!input_stream) {
|
||||
dbgDebug(D_ORCHESTRATOR)
|
||||
<< "Cannot open the file with required security apps"
|
||||
<< "File: " << required_apps_file_path;
|
||||
return;
|
||||
}
|
||||
|
||||
string required_security_app;
|
||||
while (getline(input_stream, required_security_app)) {
|
||||
required_security_apps.push_back(required_security_app);
|
||||
}
|
||||
input_stream.close();
|
||||
|
||||
} catch (const ifstream::failure &exception) {
|
||||
dbgWarning(D_ORCHESTRATOR)
|
||||
<< "Cannot read the file with required security app lists."
|
||||
<< " File: " << required_apps_file_path
|
||||
<< " Error: " << exception.what();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FogAuthenticator::init()
|
||||
{
|
||||
filesystem_prefix = getFilesystemPathConfig();
|
||||
dbgTrace(D_ORCHESTRATOR) << "Initializing Fog communication, file system path prefix: " << filesystem_prefix;
|
||||
loadRequiredSecurityApps();
|
||||
initRestAPI();
|
||||
}
|
||||
|
||||
SASAL_END
|
@@ -0,0 +1,89 @@
|
||||
// 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 "fog_communication.h"
|
||||
#include "rest.h"
|
||||
#include "config.h"
|
||||
#include "log_generator.h"
|
||||
#include "agent_details.h"
|
||||
#include "version.h"
|
||||
#include "sasal.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
SASAL_START // Orchestration - Communication
|
||||
|
||||
using namespace std;
|
||||
using namespace cereal;
|
||||
using HTTPMethod = I_Messaging::Method;
|
||||
|
||||
USE_DEBUG_FLAG(D_ORCHESTRATOR);
|
||||
|
||||
Maybe<void>
|
||||
FogCommunication::getUpdate(CheckUpdateRequest &request)
|
||||
{
|
||||
if (!access_token.ok()) return genError("Acccess Token not available.");
|
||||
|
||||
auto unpacked_access_token = access_token.unpack().getToken();
|
||||
static const string check_update_str = "/api/v2/agents/resources";
|
||||
auto request_status = Singleton::Consume<I_Messaging>::by<FogCommunication>()->sendObject(
|
||||
request,
|
||||
HTTPMethod::POST,
|
||||
fog_address_ex + check_update_str,
|
||||
buildOAuth2Header(unpacked_access_token)
|
||||
);
|
||||
|
||||
if (!request_status) {
|
||||
dbgDebug(D_ORCHESTRATOR) << "Failed to get response after check update request.";
|
||||
return genError("Failed to request updates");
|
||||
}
|
||||
dbgDebug(D_ORCHESTRATOR) << "Got response after check update request.";
|
||||
return Maybe<void>();
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
FogCommunication::downloadAttributeFile(const GetResourceFile &resourse_file)
|
||||
{
|
||||
if (!access_token.ok()) return genError("Acccess Token not available.");
|
||||
|
||||
auto unpacked_access_token = access_token.unpack().getToken();
|
||||
|
||||
static const string file_attribute_str = "/api/v2/agents/resources/";
|
||||
Maybe<string> attribute_file = Singleton::Consume<I_Messaging>::by<FogCommunication>()->downloadFile(
|
||||
resourse_file,
|
||||
resourse_file.getRequestMethod(),
|
||||
fog_address_ex + file_attribute_str + resourse_file.getFileName(),
|
||||
buildOAuth2Header(unpacked_access_token) // Header
|
||||
);
|
||||
|
||||
return attribute_file;
|
||||
}
|
||||
|
||||
Maybe<void>
|
||||
FogCommunication::sendPolicyVersion(const string &policy_version) const
|
||||
{
|
||||
PolicyVersionPatchRequest request(policy_version);
|
||||
auto fog_messaging = Singleton::Consume<I_Messaging>::by<FogCommunication>();
|
||||
if (fog_messaging->sendNoReplyObject(request, HTTPMethod::PATCH, fog_address_ex + "/agents")) {
|
||||
dbgInfo(D_ORCHESTRATOR)
|
||||
<< "Patch request was sent successfully to the fog."
|
||||
<< " Policy version: "
|
||||
<< policy_version;
|
||||
return Maybe<void>();
|
||||
}
|
||||
return genError("Failed to patch policy version");
|
||||
}
|
||||
|
||||
SASAL_END
|
@@ -0,0 +1,128 @@
|
||||
// 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 "hybrid_communication.h"
|
||||
#include "rest.h"
|
||||
#include "config.h"
|
||||
#include "log_generator.h"
|
||||
#include "agent_details.h"
|
||||
#include "version.h"
|
||||
#include "sasal.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
SASAL_START // Orchestration - Communication
|
||||
|
||||
using namespace std;
|
||||
using HTTPMethod = I_Messaging::Method;
|
||||
|
||||
USE_DEBUG_FLAG(D_ORCHESTRATOR);
|
||||
|
||||
void
|
||||
HybridCommunication::init()
|
||||
{
|
||||
FogAuthenticator::init();
|
||||
dbgTrace(D_ORCHESTRATOR) << "Initializing the Hybrid Communication Component";
|
||||
if (getConfigurationFlag("otp") != "") {
|
||||
otp = getConfigurationFlag("otp");
|
||||
} else {
|
||||
otp = "cp-3fb5c718-5e39-47e6-8d5e-99b4bc5660b74b4b7fc8-5312-451d-a763-aaf7872703c0";
|
||||
}
|
||||
}
|
||||
|
||||
string
|
||||
HybridCommunication::getChecksum(const string &policy_version)
|
||||
{
|
||||
dbgFlow(D_ORCHESTRATOR) << "Checking the policy Checksum";
|
||||
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<I_K8S_Policy_Gen>::by<HybridCommunication>()->parsePolicy(clean_plicy_version);
|
||||
|
||||
I_OrchestrationTools *orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<FogAuthenticator>();
|
||||
Maybe<string> file_checksum = orchestration_tools->calculateChecksum(
|
||||
I_OrchestrationTools::SELECTED_CHECKSUM_TYPE,
|
||||
Singleton::Consume<I_K8S_Policy_Gen>::by<HybridCommunication>()->getPolicyPath()
|
||||
);
|
||||
|
||||
if (!file_checksum.ok()) {
|
||||
dbgWarning(D_ORCHESTRATOR) << "Failed the policy checksum calculation";
|
||||
return "";
|
||||
}
|
||||
return file_checksum.unpack();
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
HybridCommunication::getNewVersion()
|
||||
{
|
||||
I_OrchestrationTools *orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<FogAuthenticator>();
|
||||
return orchestration_tools->readFile("/etc/cp/conf/k8s-policy-check.trigger");
|
||||
}
|
||||
|
||||
Maybe<void>
|
||||
HybridCommunication::getUpdate(CheckUpdateRequest &request)
|
||||
{
|
||||
dbgFlow(D_ORCHESTRATOR) << "Getting policy update in an Hybrid Communication";
|
||||
auto maybe_new_version = getNewVersion();
|
||||
if (!maybe_new_version.ok() || maybe_new_version == curr_version) {
|
||||
request = CheckUpdateRequest("", "", "", "", "", "");
|
||||
dbgDebug(D_ORCHESTRATOR) << "No new version is currently available";
|
||||
return Maybe<void>();
|
||||
}
|
||||
|
||||
auto policy_checksum = request.getPolicy();
|
||||
|
||||
auto offline_policy_checksum = getChecksum(maybe_new_version.unpack());
|
||||
|
||||
string policy_response = "";
|
||||
|
||||
if (!policy_checksum.ok() || offline_policy_checksum != policy_checksum.unpack()) {
|
||||
policy_response = offline_policy_checksum;
|
||||
}
|
||||
|
||||
dbgDebug(D_ORCHESTRATOR)
|
||||
<< "Local update response: "
|
||||
<< " policy: "
|
||||
<< (policy_response.empty() ? "has no change," : "has new update," );
|
||||
|
||||
request = CheckUpdateRequest("", policy_response, "", "", "", "");
|
||||
curr_version = *maybe_new_version;
|
||||
|
||||
return Maybe<void>();
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
HybridCommunication::downloadAttributeFile(const GetResourceFile &resourse_file)
|
||||
{
|
||||
auto file_name = resourse_file.getFileName();
|
||||
|
||||
if (file_name.compare("policy") == 0) {
|
||||
return curr_policy;
|
||||
}
|
||||
|
||||
dbgWarning(D_ORCHESTRATOR) << "Failed downloading the attribute files";
|
||||
return string("");
|
||||
}
|
||||
|
||||
Maybe<void>
|
||||
HybridCommunication::sendPolicyVersion(const string &policy_version) const
|
||||
{
|
||||
dbgFlow(D_ORCHESTRATOR);
|
||||
policy_version.empty();
|
||||
return Maybe<void>();
|
||||
}
|
||||
|
||||
SASAL_END
|
@@ -0,0 +1,187 @@
|
||||
// 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 "local_communication.h"
|
||||
#include "config.h"
|
||||
#include "sasal.h"
|
||||
|
||||
SASAL_START // Orchestration - Communication
|
||||
|
||||
using namespace std;
|
||||
|
||||
USE_DEBUG_FLAG(D_ORCHESTRATOR);
|
||||
|
||||
void
|
||||
LocalCommunication::init()
|
||||
{
|
||||
filesystem_prefix = getFilesystemPathConfig();
|
||||
dbgTrace(D_ORCHESTRATOR) << "Initializing Local communication, file system path prefix: " << filesystem_prefix;
|
||||
}
|
||||
|
||||
void
|
||||
LocalCommunication::preload()
|
||||
{
|
||||
registerExpectedConfiguration<string>("orchestration", "Offline manifest file path");
|
||||
registerExpectedConfiguration<string>("orchestration", "Offline settings file path");
|
||||
registerExpectedConfiguration<string>("orchestration", "Offline policy file path");
|
||||
registerExpectedConfiguration<string>("orchestration", "Offline Data file path");
|
||||
}
|
||||
|
||||
Maybe<void>
|
||||
LocalCommunication::authenticateAgent()
|
||||
{
|
||||
return Maybe<void>();
|
||||
}
|
||||
|
||||
string
|
||||
LocalCommunication::getChecksum(const string &file_path)
|
||||
{
|
||||
I_OrchestrationTools *orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<LocalCommunication>();
|
||||
Maybe<string> file_checksum = orchestration_tools->calculateChecksum(
|
||||
I_OrchestrationTools::SELECTED_CHECKSUM_TYPE,
|
||||
file_path
|
||||
);
|
||||
|
||||
if (!file_checksum.ok()) return "";
|
||||
return file_checksum.unpack();
|
||||
}
|
||||
|
||||
Maybe<void>
|
||||
LocalCommunication::getUpdate(CheckUpdateRequest &request)
|
||||
{
|
||||
auto manifest_checksum = request.getManifest();
|
||||
auto policy_checksum = request.getPolicy();
|
||||
auto settings_checksum =request.getSettings();
|
||||
auto data_checksum = request.getData();
|
||||
|
||||
auto offline_manifest_checksum = getChecksum(
|
||||
getConfigurationWithDefault<string>(
|
||||
filesystem_prefix + "/conf/offline_manifest.json",
|
||||
"orchestration",
|
||||
"Offline Manifest file path"
|
||||
)
|
||||
);
|
||||
auto offline_policy_checksum = getChecksum(
|
||||
getConfigurationWithDefault<string>(
|
||||
filesystem_prefix + "/conf/offline_policy.json",
|
||||
"orchestration",
|
||||
"Offline Policy file path"
|
||||
)
|
||||
);
|
||||
auto offline_settings_checksum = getChecksum(
|
||||
getConfigurationWithDefault<string>(
|
||||
filesystem_prefix + "/conf/offline_settings.json",
|
||||
"orchestration",
|
||||
"Offline Settings file path"
|
||||
)
|
||||
);
|
||||
auto offline_data_checksum = getChecksum(
|
||||
getConfigurationWithDefault<string>(
|
||||
filesystem_prefix + "/conf/data/offline_data.json",
|
||||
"orchestration",
|
||||
"Offline Data file path"
|
||||
)
|
||||
);
|
||||
|
||||
string manifest_response = "";
|
||||
string policy_response = "";
|
||||
string settings_response = "";
|
||||
string data_response = "";
|
||||
|
||||
if (!manifest_checksum.ok() || offline_manifest_checksum != manifest_checksum.unpack()) {
|
||||
manifest_response = offline_manifest_checksum;
|
||||
}
|
||||
|
||||
if (!policy_checksum.ok() || offline_policy_checksum != policy_checksum.unpack()) {
|
||||
policy_response = offline_policy_checksum;
|
||||
}
|
||||
|
||||
if (!settings_checksum.ok() || offline_settings_checksum != settings_checksum.unpack()) {
|
||||
settings_response = offline_settings_checksum;
|
||||
}
|
||||
|
||||
if (!data_checksum.ok() || offline_data_checksum != data_checksum.unpack()) {
|
||||
data_response = offline_data_checksum;
|
||||
}
|
||||
|
||||
dbgDebug(D_ORCHESTRATOR) << "Local update response, "
|
||||
<< " manifest: " << (manifest_response.empty() ? "has no change," : "has new update,")
|
||||
<< " policy: " << (policy_response.empty() ? "has no change," : "has new update," )
|
||||
<< " settings: " << (settings_response.empty() ? "has no change" : "has new update")
|
||||
<< " data: " << (data_response.empty() ? "has no change" : "has new update");
|
||||
|
||||
request = CheckUpdateRequest(manifest_response, policy_response, settings_response, data_response, "", "");
|
||||
return Maybe<void>();
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
LocalCommunication::downloadAttributeFile(const GetResourceFile &resourse_file)
|
||||
{
|
||||
auto file_name = resourse_file.getFileName();
|
||||
|
||||
I_OrchestrationTools *orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<LocalCommunication>();
|
||||
if (file_name.compare("policy") == 0) {
|
||||
return orchestration_tools->readFile(getConfigurationWithDefault<string>(
|
||||
filesystem_prefix + "/conf/offline_policy.json",
|
||||
"orchestration",
|
||||
"Offline Policy file path"
|
||||
));
|
||||
}
|
||||
if (file_name.compare("manifest") == 0) {
|
||||
return orchestration_tools->readFile(getConfigurationWithDefault<string>(
|
||||
filesystem_prefix + "/conf/offline_manifest.json",
|
||||
"orchestration",
|
||||
"Offline Manifest file path"
|
||||
));
|
||||
}
|
||||
if (file_name.compare("settings") == 0) {
|
||||
return orchestration_tools->readFile(getConfigurationWithDefault<string>(
|
||||
filesystem_prefix + "/conf/offline_settings.json",
|
||||
"orchestration",
|
||||
"Offline Settings file path"
|
||||
));
|
||||
}
|
||||
if (file_name.compare("virtualSettings") == 0) {
|
||||
return orchestration_tools->readFile(getConfigurationWithDefault<string>(
|
||||
filesystem_prefix + "/conf/offline_virtual_manifest.json",
|
||||
"orchestration",
|
||||
"Offline virtual Manifest file path"
|
||||
));
|
||||
}
|
||||
if (file_name.compare("virtualPolicy") == 0) {
|
||||
return orchestration_tools->readFile(getConfigurationWithDefault<string>(
|
||||
filesystem_prefix + "/conf/offline_virtual_settings.json",
|
||||
"orchestration",
|
||||
"Offline virtual Settings file path"
|
||||
));
|
||||
}
|
||||
|
||||
dbgError(D_ORCHESTRATOR) << "Unknown resourse file name " << file_name;
|
||||
return genError("Failed to detect resourse file name " + file_name);
|
||||
}
|
||||
|
||||
void
|
||||
LocalCommunication::setAddressExtenesion(const string &)
|
||||
{
|
||||
dbgTrace(D_ORCHESTRATOR) << "Agent in offline mode, no need for address setting";
|
||||
return;
|
||||
}
|
||||
|
||||
Maybe<void>
|
||||
LocalCommunication::sendPolicyVersion(const string &) const
|
||||
{
|
||||
dbgTrace(D_ORCHESTRATOR) << "Agent in offline mode, no need to send policy version";
|
||||
return Maybe<void>();
|
||||
}
|
||||
|
||||
SASAL_END
|
@@ -0,0 +1,148 @@
|
||||
// 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 "update_communication.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "rest.h"
|
||||
#include "config.h"
|
||||
#include "log_generator.h"
|
||||
#include "agent_details.h"
|
||||
#include "version.h"
|
||||
#include "sasal.h"
|
||||
#include "i_encryptor.h"
|
||||
#include "fog_authenticator.h"
|
||||
#include "fog_communication.h"
|
||||
#include "local_communication.h"
|
||||
#include "hybrid_communication.h"
|
||||
|
||||
SASAL_START // Orchestration - Communication
|
||||
|
||||
using namespace std;
|
||||
|
||||
USE_DEBUG_FLAG(D_ORCHESTRATOR);
|
||||
class UpdateCommunication::Impl
|
||||
:
|
||||
public ServerRest,
|
||||
Singleton::Provide<I_UpdateCommunication>::From<UpdateCommunication>
|
||||
{
|
||||
public:
|
||||
void
|
||||
doCall() override
|
||||
{
|
||||
Singleton::Consume<I_MainLoop>::by<UpdateCommunication>()->stopAll();
|
||||
status = "Operation mode had changed successfully";
|
||||
}
|
||||
|
||||
void
|
||||
preload()
|
||||
{
|
||||
FogAuthenticator::preload();
|
||||
LocalCommunication::preload();
|
||||
}
|
||||
|
||||
void
|
||||
init()
|
||||
{
|
||||
auto rest = Singleton::Consume<I_RestApi>::by<UpdateCommunication>();
|
||||
rest->addRestCall<UpdateCommunication::Impl>(RestAction::SET, "orchestration-mode");
|
||||
setMode();
|
||||
}
|
||||
|
||||
Maybe<void>
|
||||
authenticateAgent()
|
||||
{
|
||||
return i_update_comm_impl->authenticateAgent();
|
||||
}
|
||||
|
||||
Maybe<void>
|
||||
getUpdate(CheckUpdateRequest &request) override
|
||||
{
|
||||
return i_update_comm_impl->getUpdate(request);
|
||||
}
|
||||
|
||||
Maybe<void>
|
||||
sendPolicyVersion(const string &policy_version) const override
|
||||
{
|
||||
return i_update_comm_impl->sendPolicyVersion(policy_version);
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
downloadAttributeFile(const GetResourceFile &resourse_file) override
|
||||
{
|
||||
return i_update_comm_impl->downloadAttributeFile(resourse_file);
|
||||
}
|
||||
|
||||
void
|
||||
setAddressExtenesion(const string &extension) override
|
||||
{
|
||||
i_update_comm_impl->setAddressExtenesion(extension);
|
||||
}
|
||||
|
||||
void
|
||||
fini()
|
||||
{
|
||||
i_update_comm_impl = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
setMode()
|
||||
{
|
||||
if (getConfigurationFlag("orchestration-mode") == "offline_mode") {
|
||||
i_update_comm_impl = make_unique<LocalCommunication>();
|
||||
LocalCommunication *local_comm = static_cast<LocalCommunication*>(i_update_comm_impl.get());
|
||||
local_comm->init();
|
||||
return;
|
||||
} else if (getConfigurationFlag("orchestration-mode") == "hybrid_mode") {
|
||||
i_update_comm_impl = make_unique<HybridCommunication>();
|
||||
HybridCommunication *local_comm = static_cast<HybridCommunication*>(i_update_comm_impl.get());
|
||||
local_comm->init();
|
||||
return;
|
||||
}
|
||||
|
||||
i_update_comm_impl = make_unique<FogCommunication>();
|
||||
FogCommunication *fog_comm = static_cast<FogCommunication*>(i_update_comm_impl.get());
|
||||
fog_comm->init();
|
||||
}
|
||||
|
||||
std::unique_ptr<I_UpdateCommunication> i_update_comm_impl = nullptr;
|
||||
S2C_LABEL_PARAM(string, status, "status");
|
||||
};
|
||||
|
||||
UpdateCommunication::UpdateCommunication() : Component("UpdateCommunication"), pimpl(make_unique<Impl>()) {}
|
||||
|
||||
UpdateCommunication::~UpdateCommunication() {}
|
||||
|
||||
void
|
||||
UpdateCommunication::preload()
|
||||
{
|
||||
pimpl->preload();
|
||||
}
|
||||
|
||||
void
|
||||
UpdateCommunication::init()
|
||||
{
|
||||
pimpl->init();
|
||||
}
|
||||
|
||||
void
|
||||
UpdateCommunication::fini()
|
||||
{
|
||||
pimpl->fini();
|
||||
}
|
||||
|
||||
SASAL_END
|
@@ -0,0 +1,7 @@
|
||||
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;"
|
||||
)
|
@@ -0,0 +1,233 @@
|
||||
#include <string>
|
||||
|
||||
#include "local_communication.h"
|
||||
#include "cptest.h"
|
||||
#include "mock/mock_orchestration_tools.h"
|
||||
#include "config.h"
|
||||
#include "config_component.h"
|
||||
#include "orchestration_status.h"
|
||||
#include "mock/mock_mainloop.h"
|
||||
#include "mock/mock_time_get.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace testing;
|
||||
|
||||
ostream &
|
||||
operator<<(ostream &os, const tuple<OrchManifest, OrchPolicy, OrchSettings> &)
|
||||
{
|
||||
return os;
|
||||
}
|
||||
|
||||
class LocalCommunicationTest: public Test
|
||||
{
|
||||
public:
|
||||
LocalCommunicationTest()
|
||||
{
|
||||
local_communication.init();
|
||||
}
|
||||
|
||||
void
|
||||
preload()
|
||||
{
|
||||
local_communication.preload();
|
||||
}
|
||||
|
||||
Maybe<void>
|
||||
authenticateAgent()
|
||||
{
|
||||
return local_communication.authenticateAgent();
|
||||
}
|
||||
|
||||
Maybe<void>
|
||||
sendPolicyVersion(const string &version)
|
||||
{
|
||||
return local_communication.sendPolicyVersion(version);
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
downloadAttributeFile(const GetResourceFile &resourse_file)
|
||||
{
|
||||
return local_communication.downloadAttributeFile(resourse_file);
|
||||
}
|
||||
|
||||
void
|
||||
setAddressExtenesion(const string &ext)
|
||||
{
|
||||
local_communication.setAddressExtenesion(ext);
|
||||
}
|
||||
|
||||
Maybe<void>
|
||||
checkUpdate(CheckUpdateRequest &request)
|
||||
{
|
||||
return local_communication.getUpdate(request);
|
||||
}
|
||||
|
||||
NiceMock<MockMainLoop> mock_mainloop;
|
||||
NiceMock<MockTimeGet> mock_timer;
|
||||
::Environment env;
|
||||
ConfigComponent config_comp;
|
||||
StrictMock<MockOrchestrationTools> mock_orc_tools;
|
||||
OrchestrationStatus orc_status;
|
||||
|
||||
private:
|
||||
LocalCommunication local_communication;
|
||||
};
|
||||
|
||||
TEST_F(LocalCommunicationTest, doNothing)
|
||||
{
|
||||
}
|
||||
|
||||
TEST_F(LocalCommunicationTest, registerConfig)
|
||||
{
|
||||
env.preload();
|
||||
env.init();
|
||||
|
||||
preload();
|
||||
string config_json =
|
||||
"{\n"
|
||||
" \"orchestration\": {\n"
|
||||
" \"Offline manifest file path\": [\n"
|
||||
" {\n"
|
||||
" \"context\": \"All()\",\n"
|
||||
" \"value\": \"ABC\"\n"
|
||||
" }\n"
|
||||
" ],\n"
|
||||
" \"Offline policy file path\": [\n"
|
||||
" {\n"
|
||||
" \"context\": \"All()\",\n"
|
||||
" \"value\": \"qwe\"\n"
|
||||
" }\n"
|
||||
" ],\n"
|
||||
" \"Offline settings file path\": [\n"
|
||||
" {\n"
|
||||
" \"context\": \"All()\",\n"
|
||||
" \"value\": \"CCCC\"\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
"}";
|
||||
istringstream ss(config_json);
|
||||
Singleton::Consume<Config::I_Config>::from(config_comp)->loadConfiguration(ss);
|
||||
|
||||
EXPECT_THAT(getConfiguration<string>("orchestration", "Offline manifest file path"), IsValue("ABC"));
|
||||
EXPECT_THAT(getConfiguration<string>("orchestration", "Offline policy file path"), IsValue("qwe"));
|
||||
EXPECT_THAT(getConfiguration<string>("orchestration", "Offline settings file path"), IsValue("CCCC"));
|
||||
|
||||
env.fini();
|
||||
}
|
||||
|
||||
TEST_F(LocalCommunicationTest, authenticateAgent)
|
||||
{
|
||||
auto authenticat_res = authenticateAgent();
|
||||
EXPECT_TRUE(authenticat_res.ok());
|
||||
}
|
||||
|
||||
TEST_F(LocalCommunicationTest, downloadManifest)
|
||||
{
|
||||
string new_manifest_string = "new manifest";
|
||||
EXPECT_CALL(mock_orc_tools, readFile("/etc/cp/conf/offline_manifest.json")).WillOnce(Return(new_manifest_string));
|
||||
GetResourceFile resourse_file(GetResourceFile::ResourceFileType::MANIFEST);
|
||||
auto downloaded_string = downloadAttributeFile(resourse_file);
|
||||
EXPECT_TRUE(downloaded_string.ok());
|
||||
EXPECT_EQ(downloaded_string.unpack(), new_manifest_string);
|
||||
}
|
||||
|
||||
TEST_F(LocalCommunicationTest, checkUpdateWithNoUpdate)
|
||||
{
|
||||
Maybe<string> manifest_checksum(string("1"));
|
||||
Maybe<string> policy_checksum(string("2"));
|
||||
Maybe<string> settings_checksum(string("3"));
|
||||
Maybe<string> data_checksum(string("4"));
|
||||
EXPECT_CALL(mock_orc_tools, calculateChecksum(
|
||||
Package::ChecksumTypes::SHA256, "/etc/cp/conf/offline_manifest.json")).WillOnce(Return(manifest_checksum));
|
||||
EXPECT_CALL(mock_orc_tools, calculateChecksum(
|
||||
Package::ChecksumTypes::SHA256, "/etc/cp/conf/offline_policy.json")).WillOnce(Return(policy_checksum));
|
||||
EXPECT_CALL(mock_orc_tools, calculateChecksum(
|
||||
Package::ChecksumTypes::SHA256, "/etc/cp/conf/offline_settings.json")).WillOnce(Return(settings_checksum));
|
||||
EXPECT_CALL(mock_orc_tools, calculateChecksum(
|
||||
Package::ChecksumTypes::SHA256, "/etc/cp/conf/data/offline_data.json")).WillOnce(Return(data_checksum));
|
||||
|
||||
CheckUpdateRequest request(
|
||||
*manifest_checksum,
|
||||
*policy_checksum,
|
||||
*settings_checksum,
|
||||
*data_checksum,
|
||||
I_OrchestrationTools::SELECTED_CHECKSUM_TYPE_STR,
|
||||
"123"
|
||||
);
|
||||
|
||||
auto update_response = checkUpdate(request);
|
||||
EXPECT_TRUE(update_response.ok());
|
||||
|
||||
Maybe<string> manifest = request.getManifest();
|
||||
EXPECT_FALSE(manifest.ok());
|
||||
|
||||
Maybe<string> policy = request.getPolicy();
|
||||
EXPECT_FALSE(policy.ok());
|
||||
|
||||
Maybe<string> settings = request.getSettings();
|
||||
EXPECT_FALSE(settings.ok());
|
||||
|
||||
Maybe<string> data = request.getData();
|
||||
EXPECT_FALSE(data.ok());
|
||||
}
|
||||
|
||||
TEST_F(LocalCommunicationTest, checkUpdateWithPolicyUpdate)
|
||||
{
|
||||
Maybe<string> manifest_checksum(string("1"));
|
||||
Maybe<string> policy_checksum(string("2"));
|
||||
Maybe<string> new_policy_checksum(string("22"));
|
||||
Maybe<string> settings_checksum(string("3"));
|
||||
Maybe<string> data_checksum(string("4"));
|
||||
|
||||
EXPECT_CALL(
|
||||
mock_orc_tools,
|
||||
calculateChecksum(Package::ChecksumTypes::SHA256, "/etc/cp/conf/offline_manifest.json")
|
||||
).WillOnce(Return(manifest_checksum));
|
||||
EXPECT_CALL(
|
||||
mock_orc_tools,
|
||||
calculateChecksum(Package::ChecksumTypes::SHA256, "/etc/cp/conf/offline_policy.json")
|
||||
).WillOnce(Return(new_policy_checksum));
|
||||
EXPECT_CALL(
|
||||
mock_orc_tools,
|
||||
calculateChecksum(Package::ChecksumTypes::SHA256, "/etc/cp/conf/offline_settings.json")
|
||||
).WillOnce(Return(settings_checksum));
|
||||
EXPECT_CALL(
|
||||
mock_orc_tools,
|
||||
calculateChecksum(Package::ChecksumTypes::SHA256, "/etc/cp/conf/data/offline_data.json")
|
||||
).WillOnce(Return(data_checksum));
|
||||
|
||||
CheckUpdateRequest request(
|
||||
*manifest_checksum,
|
||||
*policy_checksum,
|
||||
*settings_checksum,
|
||||
*data_checksum,
|
||||
I_OrchestrationTools::SELECTED_CHECKSUM_TYPE_STR,
|
||||
"123"
|
||||
);
|
||||
|
||||
auto update_response = checkUpdate(request);
|
||||
EXPECT_TRUE(update_response.ok());
|
||||
|
||||
Maybe<string> manifest = request.getManifest();
|
||||
EXPECT_FALSE(manifest.ok());
|
||||
|
||||
EXPECT_THAT(request.getPolicy(), IsValue("22"));
|
||||
|
||||
Maybe<string> settings = request.getSettings();
|
||||
EXPECT_FALSE(settings.ok());
|
||||
|
||||
Maybe<string> data = request.getData();
|
||||
EXPECT_FALSE(data.ok());
|
||||
}
|
||||
|
||||
TEST_F(LocalCommunicationTest, setAddressExtenesion)
|
||||
{
|
||||
setAddressExtenesion("Test");
|
||||
}
|
||||
|
||||
TEST_F(LocalCommunicationTest, sendPolicyVersion)
|
||||
{
|
||||
auto res = sendPolicyVersion("12");
|
||||
EXPECT_TRUE(res.ok());
|
||||
}
|
Reference in New Issue
Block a user