Feb 15th 2023 update

This commit is contained in:
Ned Wright
2023-02-15 19:09:38 +00:00
parent f7934cd09d
commit 6a9b33ff93
159 changed files with 16474 additions and 2096 deletions

View File

@@ -28,14 +28,15 @@ public:
MOCK_CONST_METHOD0(getUpdatePolicyVersion, const std::string &());
MOCK_METHOD5(
MOCK_METHOD6(
updateServiceConfiguration,
bool(
const std::string &new_policy_path,
const std::string &new_settings_path,
const std::vector<std::string> &new_data_files,
const std::string &tenant_id,
const std::string &profile_id
const std::string &profile_id,
const bool last_iteration
)
);

View File

@@ -1 +1,3 @@
add_library(local_policy_mgmt_gen local_policy_mgmt_gen.cc)
include_directories(include)
add_library(local_policy_mgmt_gen appsec_practice_section.cc exceptions_section.cc ingress_data.cc local_policy_mgmt_gen.cc policy_maker_utils.cc rules_config_section.cc settings_section.cc snort_section.cc triggers_section.cc trusted_sources_section.cc)

View File

@@ -0,0 +1,571 @@
#include "appsec_practice_section.h"
using namespace std;
USE_DEBUG_FLAG(D_K8S_POLICY);
// LCOV_EXCL_START Reason: no test exist
void
AppSecWebBotsURI::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec Web Bots URI";
parseAppsecJSONKey<string>("uri", uri, archive_in);
}
const string &
AppSecWebBotsURI::getURI() const
{
return uri;
}
void
AppSecPracticeAntiBot::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec Web Bots";
parseAppsecJSONKey<vector<AppSecWebBotsURI>>("injected-URIs", injected_uris, archive_in);
parseAppsecJSONKey<vector<AppSecWebBotsURI>>("validated-URIs", validated_uris, archive_in);
parseAppsecJSONKey<string>("override-mode", override_mode, archive_in, "Inactive");
}
void
AppSecPracticeAntiBot::save(cereal::JSONOutputArchive &out_ar) const
{
vector<string> injected;
vector<string> validated;
for (const AppSecWebBotsURI &uri : injected_uris) injected.push_back(uri.getURI());
for (const AppSecWebBotsURI &uri : validated_uris) injected.push_back(uri.getURI());
out_ar(
cereal::make_nvp("injected", injected),
cereal::make_nvp("validated", validated)
);
}
void
AppSecWebAttackProtections::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec Web Attack Protections";
parseAppsecJSONKey<string>("csrf-enabled", csrf_protection, archive_in, "inactive");
parseAppsecJSONKey<string>("error-disclosure-enabled", error_disclosure, archive_in, "inactive");
parseAppsecJSONKey<string>("open-redirect-enabled", open_redirect, archive_in, "inactive");
parseAppsecJSONKey<bool>("non-valid-http-methods", non_valid_http_methods, archive_in, false);
}
const string
AppSecWebAttackProtections::getCsrfProtectionMode() const
{
if (key_to_practices_val.find(csrf_protection) == key_to_practices_val.end()) {
dbgError(D_K8S_POLICY)
<< "Failed to find a value for "
<< csrf_protection
<< ". Setting CSRF protection to Inactive";
return "Inactive";
}
return key_to_practices_val.at(csrf_protection);
}
const string &
AppSecWebAttackProtections::getErrorDisclosureMode() const
{
return error_disclosure;
}
bool
AppSecWebAttackProtections::getNonValidHttpMethods() const
{
return non_valid_http_methods;
}
const string
AppSecWebAttackProtections::getOpenRedirectMode() const
{
if (key_to_practices_val.find(open_redirect) == key_to_practices_val.end()) {
dbgError(D_K8S_POLICY)
<< "Failed to find a value for "
<< open_redirect
<< ". Setting Open Redirect mode to Inactive";
return "Inactive";
}
return key_to_practices_val.at(open_redirect);
}
void
AppSecPracticeWebAttacks::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec practice spec";
parseAppsecJSONKey<AppSecWebAttackProtections>("protections", protections, archive_in);
if (getMode() == "Prevent") {
parseAppsecJSONKey<string>("minimum-confidence", minimum_confidence, archive_in, "critical");
} else {
minimum_confidence = "Transparent";
}
parseAppsecJSONKey<string>("override-mode", mode, archive_in, "Unset");
parseAppsecJSONKey<int>("max-body-size-kb", max_body_size_kb, archive_in, 1000000);
parseAppsecJSONKey<int>("max-header-size-bytes", max_header_size_bytes, archive_in, 102400);
parseAppsecJSONKey<int>("max-object-depth", max_object_depth, archive_in, 40);
parseAppsecJSONKey<int>("max-url-size-bytes", max_url_size_bytes, archive_in, 32768);
}
int
AppSecPracticeWebAttacks::getMaxBodySizeKb() const
{
return max_body_size_kb;
}
int
AppSecPracticeWebAttacks::getMaxHeaderSizeBytes() const
{
return max_header_size_bytes;
}
int
AppSecPracticeWebAttacks::getMaxObjectDepth() const
{
return max_object_depth;
}
int
AppSecPracticeWebAttacks::getMaxUrlSizeBytes() const
{
return max_url_size_bytes;
}
const string &
AppSecPracticeWebAttacks::getMinimumConfidence() const
{
return minimum_confidence;
}
const string &
AppSecPracticeWebAttacks::getMode(const string &default_mode) const
{
if (mode == "Unset" || (key_to_practices_val.find(mode) == key_to_practices_val.end())) {
dbgError(D_K8S_POLICY) << "Couldn't find a value for key: " << mode << ". Returning " << default_mode;
return default_mode;
}
return key_to_practices_val.at(mode);
}
void
AppSecPracticeSnortSignatures::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec Snort Signatures practice";
parseAppsecJSONKey<string>("override-mode", override_mode, archive_in, "Inactive");
parseAppsecJSONKey<vector<string>>("configmap", config_map, archive_in);
}
const string &
AppSecPracticeSnortSignatures::getOverrideMode() const
{
return override_mode;
}
const vector<string> &
AppSecPracticeSnortSignatures::getConfigMap() const
{
return config_map;
}
void
AppSecPracticeOpenSchemaAPI::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSecPracticeOpenSchemaAPI practice";
parseAppsecJSONKey<string>("override-mode", override_mode, archive_in, "Inactive");
parseAppsecJSONKey<vector<string>>("configmap", config_map, archive_in);
}
const string &
AppSecPracticeOpenSchemaAPI::getOverrideMode() const
{
return override_mode;
}
const vector<string> &
AppSecPracticeOpenSchemaAPI::getConfigMap() const
{
return config_map;
}
void
AppSecPracticeSpec::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec practice spec";
parseAppsecJSONKey<AppSecPracticeOpenSchemaAPI>(
"openapi-schema-validation",
openapi_schema_validation,
archive_in
);
parseAppsecJSONKey<AppSecPracticeSnortSignatures>("snort-signatures", snort_signatures, archive_in);
parseAppsecJSONKey<AppSecPracticeWebAttacks>("web-attacks", web_attacks, archive_in);
parseAppsecJSONKey<AppSecPracticeAntiBot>("anti-bot", anti_bot, archive_in);
parseAppsecJSONKey<string>("name", practice_name, archive_in);
}
const AppSecPracticeOpenSchemaAPI &
AppSecPracticeSpec::getOpenSchemaValidation() const
{
return openapi_schema_validation;
}
const AppSecPracticeSnortSignatures &
AppSecPracticeSpec::getSnortSignatures() const
{
return snort_signatures;
}
const AppSecPracticeWebAttacks &
AppSecPracticeSpec::getWebAttacks() const
{
return web_attacks;
}
const AppSecPracticeAntiBot &
AppSecPracticeSpec::getAntiBot() const
{
return anti_bot;
}
const string &
AppSecPracticeSpec::getName() const
{
return practice_name;
}
void
PracticeAdvancedConfig::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("httpHeaderMaxSize", http_header_max_size),
cereal::make_nvp("httpIllegalMethodsAllowed", http_illegal_methods_allowed),
cereal::make_nvp("httpRequestBodyMaxSize", http_request_body_max_size),
cereal::make_nvp("jsonMaxObjectDepth", json_max_object_depth),
cereal::make_nvp("urlMaxSize", url_max_size)
);
}
void
TriggersInWaapSection::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("$triggerType", trigger_type),
cereal::make_nvp("id", id),
cereal::make_nvp("name", name),
cereal::make_nvp("log", log)
);
}
AppSecOverride::AppSecOverride(const SourcesIdentifiers &parsed_trusted_sources)
{
string source_ident = parsed_trusted_sources.getSourceIdent();
map<string, string> behavior = {{"httpSourceId", source_ident}};
parsed_behavior.push_back(behavior);
parsed_match = {{"operator", "BASIC"}, {"tag", "sourceip"}, {"value", "0.0.0.0/0"}};
}
void
AppSecOverride::save(cereal::JSONOutputArchive &out_ar) const
{
string parameter_type = "TrustedSource";
out_ar(
cereal::make_nvp("parsedBehavior", parsed_behavior),
cereal::make_nvp("parsedMatch", parsed_match)
);
}
WebAppSection::WebAppSection(
const string &_application_urls,
const string &_asset_id,
const string &_asset_name,
const string &_rule_id,
const string &_rule_name,
const string &_practice_id,
const string &_practice_name,
const AppSecPracticeSpec &parsed_appsec_spec,
const LogTriggerSection &parsed_log_trigger,
const string &default_mode,
const AppSecTrustedSources &parsed_trusted_sources)
:
application_urls(_application_urls),
asset_id(_asset_id),
asset_name(_asset_name),
rule_id(_rule_id),
rule_name(_rule_name),
practice_id(_practice_id),
practice_name(_practice_name),
context("practiceId(" + practice_id +")"),
web_attack_mitigation_severity(parsed_appsec_spec.getWebAttacks().getMinimumConfidence()),
web_attack_mitigation_mode(parsed_appsec_spec.getWebAttacks().getMode(default_mode)),
practice_advanced_config(parsed_appsec_spec),
anti_bots(parsed_appsec_spec.getAntiBot()),
trusted_sources({parsed_trusted_sources})
{
web_attack_mitigation = true;
web_attack_mitigation_action =
web_attack_mitigation_severity == "critical" ? "low" :
web_attack_mitigation_severity == "high" ? "balanced" :
web_attack_mitigation_severity == "medium" ? "high" :
"Error";
triggers.push_back(TriggersInWaapSection(parsed_log_trigger));
for (const SourcesIdentifiers &source_ident : parsed_trusted_sources.getSourcesIdentifiers()) {
overrides.push_back(AppSecOverride(source_ident));
}
}
void
WebAppSection::save(cereal::JSONOutputArchive &out_ar) const
{
string disabled_str = "Disabled";
string detect_str = "Detect";
vector<string> empty_list;
out_ar(
cereal::make_nvp("context", context),
cereal::make_nvp("webAttackMitigation", web_attack_mitigation),
cereal::make_nvp("webAttackMitigationSeverity", web_attack_mitigation_severity),
cereal::make_nvp("webAttackMitigationAction", web_attack_mitigation_action),
cereal::make_nvp("webAttackMitigationMode", web_attack_mitigation_mode),
cereal::make_nvp("practiceAdvancedConfig", practice_advanced_config),
cereal::make_nvp("csrfProtection", disabled_str),
cereal::make_nvp("openRedirect", disabled_str),
cereal::make_nvp("errorDisclosure", disabled_str),
cereal::make_nvp("practiceId", practice_id),
cereal::make_nvp("practiceName", practice_name),
cereal::make_nvp("assetId", asset_id),
cereal::make_nvp("assetName", asset_name),
cereal::make_nvp("ruleId", rule_id),
cereal::make_nvp("ruleName", rule_name),
cereal::make_nvp("triggers", triggers),
cereal::make_nvp("applicationUrls", application_urls),
cereal::make_nvp("overrides", overrides),
cereal::make_nvp("trustedSources", trusted_sources),
cereal::make_nvp("waapParameters", empty_list),
cereal::make_nvp("botProtection", false),
cereal::make_nvp("antiBot", anti_bots),
cereal::make_nvp("botProtection_v2", detect_str)
);
}
const string &
WebAppSection::getPracticeId() const
{
return practice_id;
}
bool
WebAppSection::operator<(const WebAppSection &other) const
{
return getPracticeId() < other.getPracticeId();
}
void
WebAPISection::save(cereal::JSONOutputArchive &out_ar) const
{
string disabled_str = "Disabled";
vector<string> empty_list;
out_ar(
cereal::make_nvp("application_urls", application_urls),
cereal::make_nvp("asset_id", asset_id),
cereal::make_nvp("asset_name", asset_name),
cereal::make_nvp("context", context),
cereal::make_nvp("practiceAdvancedConfig", practice_advanced_config),
cereal::make_nvp("practice_id", practice_id),
cereal::make_nvp("practice_name", practice_name),
cereal::make_nvp("ruleId", rule_id),
cereal::make_nvp("ruleName", rule_name),
cereal::make_nvp("schemaValidation", false),
cereal::make_nvp("schemaValidation_v2", disabled_str),
cereal::make_nvp("web_attack_mitigation", web_attack_mitigation),
cereal::make_nvp("web_attack_mitigation_action", web_attack_mitigation_action),
cereal::make_nvp("web_attack_mitigation_severity", web_attack_mitigation_severity),
cereal::make_nvp("web_attack_mitigation_mode", web_attack_mitigation_mode),
cereal::make_nvp("oas", empty_list),
cereal::make_nvp("trustedSources", empty_list),
cereal::make_nvp("triggers", empty_list),
cereal::make_nvp("waapParameters", empty_list),
cereal::make_nvp("overrides", empty_list)
);
}
const string &
WebAPISection::getPracticeId() const
{
return practice_id;
}
void
AppSecRulebase::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("WebAPISecurity", webAPIPractices),
cereal::make_nvp("WebApplicationSecurity", webApplicationPractices)
);
}
void
AppSecWrapper::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(cereal::make_nvp("WAAP", app_sec_rulebase));
}
void
ParsedRule::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec ParsedRule";
parseAppsecJSONKey<vector<string>>("exceptions", exceptions, archive_in);
parseAppsecJSONKey<vector<string>>("triggers", log_triggers, archive_in);
parseAppsecJSONKey<vector<string>>("practices", practices, archive_in);
parseAppsecJSONKey<string>("mode", mode, archive_in);
parseAppsecJSONKey<string>("custom-response", custom_response, archive_in);
parseAppsecJSONKey<string>("source-identifiers", source_identifiers, archive_in);
parseAppsecJSONKey<string>("trusted-sources", trusted_sources, archive_in);
try {
archive_in(cereal::make_nvp("host", host));
} catch (const cereal::Exception &e)
{} // The default ParsedRule does not hold a host, so no error handling
}
const vector<string> &
ParsedRule::getExceptions() const
{
return exceptions;
}
const vector<string> &
ParsedRule::getLogTriggers() const
{
return log_triggers;
}
const vector<string> &
ParsedRule::getPractices() const
{
return practices;
}
const string &
ParsedRule::getHost() const
{
return host;
}
const string &
ParsedRule::getMode() const
{
return mode;
}
void
ParsedRule::setHost(const string &_host)
{
host = _host;
}
void
ParsedRule::setMode(const string &_mode)
{
mode = _mode;
}
const string &
ParsedRule::getCustomResponse() const
{
return custom_response;
}
const string &
ParsedRule::getSourceIdentifiers() const
{
return source_identifiers;
}
const string &
ParsedRule::getTrustedSources() const
{
return trusted_sources;
}
void
AppsecPolicySpec::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec policy spec";
parseAppsecJSONKey<ParsedRule>("default", default_rule, archive_in);
auto default_mode_annot =
Singleton::Consume<I_Environment>::by<AppsecPolicySpec>()->get<string>("default mode annotation");
if (default_mode_annot.ok() && !default_mode_annot.unpack().empty() && default_rule.getMode().empty()) {
default_rule.setMode(default_mode_annot.unpack());
}
default_rule.setHost("*");
parseAppsecJSONKey<list<ParsedRule>>("specific-rules", specific_rules, archive_in);
specific_rules.push_front(default_rule);
}
const ParsedRule &
AppsecPolicySpec::getDefaultRule() const
{
return default_rule;
}
const list<ParsedRule> &
AppsecPolicySpec::getSpecificRules() const
{
return specific_rules;
}
void
AppsecLinuxPolicy::serialize(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading Appsec Linux Policy";
parseAppsecJSONKey<AppsecPolicySpec>("policies", policies, archive_in);
parseAppsecJSONKey<vector<AppSecPracticeSpec>>("practices", practices, archive_in);
parseAppsecJSONKey<vector<AppsecTriggerSpec>>("log-triggers", log_triggers, archive_in);
parseAppsecJSONKey<vector<AppSecCustomResponseSpec>>("custom-responses", custom_responses, archive_in);
parseAppsecJSONKey<vector<AppsecExceptionSpec>>("exceptions", exceptions, archive_in);
parseAppsecJSONKey<vector<TrustedSourcesSpec>>("trusted-sources", trusted_sources, archive_in);
parseAppsecJSONKey<vector<SourceIdentifierSpecWrapper>>(
"source-identifier",
sources_identifier,
archive_in
);
}
const AppsecPolicySpec &
AppsecLinuxPolicy::getAppsecPolicySpec() const
{
return policies;
}
const vector<AppSecPracticeSpec> &
AppsecLinuxPolicy::getAppSecPracticeSpecs() const
{
return practices;
}
const vector<AppsecTriggerSpec> &
AppsecLinuxPolicy::getAppsecTriggerSpecs() const
{
return log_triggers;
}
const vector<AppSecCustomResponseSpec> &
AppsecLinuxPolicy::getAppSecCustomResponseSpecs() const
{
return custom_responses;
}
const vector<AppsecExceptionSpec> &
AppsecLinuxPolicy::getAppsecExceptionSpecs() const
{
return exceptions;
}
const vector<TrustedSourcesSpec> &
AppsecLinuxPolicy::getAppsecTrustedSourceSpecs() const
{
return trusted_sources;
}
const vector<SourceIdentifierSpecWrapper> &
AppsecLinuxPolicy::getAppsecSourceIdentifierSpecs() const
{
return sources_identifier;
}
// LCOV_EXCL_STOP

View File

@@ -0,0 +1,242 @@
#include "exceptions_section.h"
using namespace std;
USE_DEBUG_FLAG(D_K8S_POLICY);
// LCOV_EXCL_START Reason: no test exist
void
AppsecExceptionSpec::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec exception spec";
parseAppsecJSONKey<string>("name", name, archive_in);
parseAppsecJSONKey<string>("action", action, archive_in);
parseAppsecJSONKey<vector<string>>("countryCode", country_code, archive_in);
parseAppsecJSONKey<vector<string>>("countryName", country_name, archive_in);
parseAppsecJSONKey<vector<string>>("hostName", host_name, archive_in);
parseAppsecJSONKey<vector<string>>("paramName", param_name, archive_in);
parseAppsecJSONKey<vector<string>>("paramValue", param_value, archive_in);
parseAppsecJSONKey<vector<string>>("protectionName", protection_name, archive_in);
parseAppsecJSONKey<vector<string>>("sourceIdentifier", source_identifier, archive_in);
parseAppsecJSONKey<vector<string>>("sourceIp", source_ip, archive_in);
parseAppsecJSONKey<vector<string>>("url", url, archive_in);
}
const string &
AppsecExceptionSpec::getName() const
{
return name;
}
const string &
AppsecExceptionSpec::getAction() const
{
return action;
}
const vector<string> &
AppsecExceptionSpec::getCountryCode() const
{
return country_code;
}
const vector<string> &
AppsecExceptionSpec::getCountryName() const
{
return country_name;
}
const vector<string> &
AppsecExceptionSpec::getHostName() const
{
return host_name;
}
const vector<string> &
AppsecExceptionSpec::getParamName() const
{
return param_name;
}
const vector<string> &
AppsecExceptionSpec::getParamValue() const
{
return param_value;
}
const vector<string> &
AppsecExceptionSpec::getProtectionName() const
{
return protection_name;
}
const vector<string> &
AppsecExceptionSpec::getSourceIdentifier() const
{
return source_identifier;
}
const vector<string> &
AppsecExceptionSpec::getSourceIp() const
{
return source_ip;
}
const vector<string> &
AppsecExceptionSpec::getUrl() const
{
return url;
}
ExceptionMatch::ExceptionMatch(const AppsecExceptionSpec &parsed_exception)
:
match_type(MatchType::Operator),
op("and")
{
if (!parsed_exception.getCountryCode().empty()) {
items.push_back(ExceptionMatch("countryCode", parsed_exception.getCountryCode()));
}
if (!parsed_exception.getCountryName().empty()) {
items.push_back(ExceptionMatch("countryName", parsed_exception.getCountryName()));
}
if (!parsed_exception.getHostName().empty()) {
items.push_back(ExceptionMatch("hostName", parsed_exception.getHostName()));
}
if (!parsed_exception.getParamName().empty()) {
items.push_back(ExceptionMatch("paramName", parsed_exception.getParamName()));
}
if (!parsed_exception.getParamValue().empty()) {
items.push_back(ExceptionMatch("paramValue", parsed_exception.getParamValue()));
}
if (!parsed_exception.getProtectionName().empty()) {
items.push_back(ExceptionMatch("protectionName", parsed_exception.getProtectionName()));
}
if (!parsed_exception.getSourceIdentifier().empty()) {
items.push_back(ExceptionMatch("sourceIdentifier", parsed_exception.getSourceIdentifier()));
}
if (!parsed_exception.getSourceIp().empty()) {
items.push_back(ExceptionMatch("sourceIp", parsed_exception.getSourceIp()));
}
if (!parsed_exception.getUrl().empty()) {
items.push_back(ExceptionMatch("url", parsed_exception.getUrl()));
}
}
void
ExceptionMatch::save(cereal::JSONOutputArchive &out_ar) const
{
switch (match_type) {
case (MatchType::Condition): {
string type_str = "condition";
out_ar(
cereal::make_nvp("key", key),
cereal::make_nvp("op", op),
cereal::make_nvp("type", type_str),
cereal::make_nvp("value", value)
);
break;
}
case (MatchType::Operator): {
string type_str = "operator";
out_ar(
cereal::make_nvp("op", op),
cereal::make_nvp("type", type_str),
cereal::make_nvp("items", items)
);
break;
}
default: {
dbgError(D_K8S_POLICY) << "No match for exception match type: " << static_cast<int>(match_type);
}
}
}
ExceptionBehavior::ExceptionBehavior(
const string &_key,
const string &_value)
:
key(_key),
value(_value)
{
try {
id = to_string(boost::uuids::random_generator()());
} catch (const boost::uuids::entropy_error &e) {
dbgWarning(D_K8S_POLICY) << "Failed to generate exception behavior UUID. Error: " << e.what();
}
}
void
ExceptionBehavior::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("key", key),
cereal::make_nvp("value", value),
cereal::make_nvp("id", id)
);
}
const string
ExceptionBehavior::getBehaviorId() const
{
return id;
}
void
InnerException::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("behavior", behavior),
cereal::make_nvp("match", match)
);
}
const string
InnerException::getBehaviorId() const
{
return behavior.getBehaviorId();
}
bool
InnerException::operator<(const InnerException &other) const
{
return getBehaviorId() < other.getBehaviorId();
}
ExceptionsRulebase::ExceptionsRulebase(
vector<InnerException> _exceptions)
:
exceptions(_exceptions)
{
string context_id_str = "";
for (const InnerException & exception : exceptions) {
string curr_id = "parameterId(" + exception.getBehaviorId() + "), ";
context_id_str += curr_id;
}
context_id_str = context_id_str.substr(0, context_id_str.size() - 2);
context = "Any(" + context_id_str + ")";
}
void
ExceptionsRulebase::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("context", context),
cereal::make_nvp("exceptions", exceptions)
);
}
void
ExceptionsWrapper::Exception::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(cereal::make_nvp("exception", exception));
}
void
ExceptionsWrapper::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("rulebase", exception_rulebase)
);
}
// LCOV_EXCL_STOP

View File

@@ -14,7 +14,9 @@
#ifndef __APPSEC_PRACTICE_SECTION_H__
#define __APPSEC_PRACTICE_SECTION_H__
#include <list>
#include <cereal/archives/json.hpp>
#include <cereal/types/list.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
@@ -28,67 +30,24 @@
#include "trusted_sources_section.h"
USE_DEBUG_FLAG(D_K8S_POLICY);
// LCOV_EXCL_START Reason: no test exist
class AppSecWebBotsURI
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec Web Bots URI";
parseAppsecJSONKey<std::string>("uri", uri, archive_in);
}
void load(cereal::JSONInputArchive &archive_in);
const std::string & getURI() const { return uri; }
const std::string & getURI() const;
private:
std::string uri;
};
std::ostream &
operator<<(std::ostream &os, const AppSecWebBotsURI &obj)
{
os << obj.getURI();
return os;
}
std::ostream &
operator<<(std::ostream &os, const std::vector<AppSecWebBotsURI> &obj)
{
os << "[" << std::endl;
makeSeparatedStr(obj, ",");
os << std::endl << "]";
return os;
}
class AppSecPracticeAntiBot
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec Web Bots";
parseAppsecJSONKey<std::vector<AppSecWebBotsURI>>("injected-URIs", injected_uris, archive_in);
parseAppsecJSONKey<std::vector<AppSecWebBotsURI>>("validated-URIs", validated_uris, archive_in);
parseAppsecJSONKey<std::string>("override-mode", override_mode, archive_in, "Inactive");
}
void
save(cereal::JSONOutputArchive &out_ar) const
{
std::vector<std::string> injected;
std::vector<std::string> validated;
for (const AppSecWebBotsURI &uri : getInjectedURIs()) injected.push_back(uri.getURI());
for (const AppSecWebBotsURI &uri : getValidatedURIs()) injected.push_back(uri.getURI());
out_ar(
cereal::make_nvp("injected", injected),
cereal::make_nvp("validated", validated)
);
}
const std::vector<AppSecWebBotsURI> & getInjectedURIs() const { return injected_uris; }
const std::vector<AppSecWebBotsURI> & getValidatedURIs() const { return validated_uris; }
const std::string & getOverrideMode() const { return override_mode; }
void load(cereal::JSONInputArchive &archive_in);
void save(cereal::JSONOutputArchive &out_ar) const;
private:
std::string override_mode;
@@ -96,61 +55,15 @@ private:
std::vector<AppSecWebBotsURI> validated_uris;
};
std::ostream &
operator<<(std::ostream &os, const AppSecPracticeAntiBot &obj)
{
os
<< "injected-URIs: "
<< obj.getInjectedURIs()
<< " validated-URIs: "
<< obj.getValidatedURIs()
<< ", override_mode: "
<< obj.getOverrideMode();
return os;
}
class AppSecWebAttackProtections
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec Web Attack Protections";
parseAppsecJSONKey<std::string>("csrf-protection", csrf_protection, archive_in, "Inactive");
parseAppsecJSONKey<std::string>("error-disclosure", error_disclosure, archive_in, "Inactive");
parseAppsecJSONKey<std::string>("open-redirect", open_redirect, archive_in, "Inactive");
parseAppsecJSONKey<bool>("non-valid-http-methods", non_valid_http_methods, archive_in, false);
}
void load(cereal::JSONInputArchive &archive_in);
const std::string
getCsrfProtectionMode() const
{
if (key_to_practices_val.find(csrf_protection) == key_to_practices_val.end()) {
dbgError(D_K8S_POLICY)
<< "Failed to find a value for "
<< csrf_protection
<< ". Setting CSRF protection to Inactive";
return "Inactive";
}
return key_to_practices_val.at(csrf_protection);
}
const std::string & getErrorDisclosureMode() const { return error_disclosure; }
bool getNonValidHttpMethods() const { return non_valid_http_methods; }
const std::string
getOpenRedirectMode() const
{
if (key_to_practices_val.find(open_redirect) == key_to_practices_val.end()) {
dbgError(D_K8S_POLICY)
<< "Failed to find a value for "
<< open_redirect
<< ". Setting Open Redirect mode to Inactive";
return "Inactive";
}
return key_to_practices_val.at(open_redirect);
}
const std::string getCsrfProtectionMode() const;
const std::string & getErrorDisclosureMode() const;
bool getNonValidHttpMethods() const;
const std::string getOpenRedirectMode() const;
private:
std::string csrf_protection;
@@ -159,53 +72,18 @@ private:
bool non_valid_http_methods;
};
std::ostream &
operator<<(std::ostream &os, const AppSecWebAttackProtections &obj)
{
os
<< " csrf-protection: "
<< obj.getCsrfProtectionMode()
<< " error-disclosure: "
<< obj.getErrorDisclosureMode()
<< " non-valid-http-methods: "
<< obj.getNonValidHttpMethods()
<< " open-redirect: "
<< obj.getOpenRedirectMode();
return os;
}
class AppSecPracticeWebAttacks
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec practice spec";
parseAppsecJSONKey<AppSecWebAttackProtections>("protections", protections, archive_in);
parseAppsecJSONKey<std::string>("minimum-confidence", minimum_confidence, archive_in, "critical");
parseAppsecJSONKey<std::string>("override-mode", mode, archive_in, "Unset");
parseAppsecJSONKey<int>("max-body-size-kb", max_body_size_kb, archive_in, 1000000);
parseAppsecJSONKey<int>("max-header-size-bytes", max_header_size_bytes, archive_in, 102400);
parseAppsecJSONKey<int>("max-object-depth", max_object_depth, archive_in, 40);
parseAppsecJSONKey<int>("max-url-size-bytes", max_url_size_bytes, archive_in, 32768);
}
void load(cereal::JSONInputArchive &archive_in);
int getMaxBodySizeKb() const { return max_body_size_kb; }
int getMaxHeaderSizeBytes() const { return max_header_size_bytes; }
int getMaxObjectDepth() const { return max_object_depth; }
int getMaxUrlSizeBytes() const { return max_url_size_bytes; }
const std::string & getMinimumConfidence() const { return minimum_confidence; }
const AppSecWebAttackProtections & getprotections() const { return protections; }
const std::string &
getMode(const std::string &default_mode = "Inactive") const
{
if (mode == "Unset" || (key_to_practices_val.find(mode) == key_to_practices_val.end())) {
dbgError(D_K8S_POLICY) << "Couldn't find a value for key: " << mode << ". Returning " << default_mode;
return default_mode;
}
return key_to_practices_val.at(mode);
}
int getMaxBodySizeKb() const;
int getMaxHeaderSizeBytes() const;
int getMaxObjectDepth() const;
int getMaxUrlSizeBytes() const;
const std::string & getMinimumConfidence() const;
const AppSecWebAttackProtections & getprotections() const;
const std::string & getMode(const std::string &default_mode = "Inactive") const;
private:
int max_body_size_kb;
@@ -217,114 +95,42 @@ private:
AppSecWebAttackProtections protections;
};
std::ostream &
operator<<(std::ostream &os, const AppSecPracticeWebAttacks &obj)
{
os
<< "mode: "
<< obj.getMode()
<< " max-body-size-kb: "
<< obj.getMaxBodySizeKb()
<< " max-header-size-bytes: "
<< obj.getMaxHeaderSizeBytes()
<< " max-object-depth: "
<< obj.getMaxObjectDepth()
<< " max-url-size-bytes: "
<< obj.getMaxUrlSizeBytes()
<< " minimum-confidence: "
<< obj.getMinimumConfidence()
<< " protections: "
<< obj.getprotections();
return os;
}
class AppSecPracticeSnortSignatures
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec Snort Signatures practice";
parseAppsecJSONKey<std::string>("override-mode", override_mode, archive_in, "Inactive");
parseAppsecJSONKey<std::vector<std::string>>("configmap", config_map, archive_in);
}
void load(cereal::JSONInputArchive &archive_in);
const std::string & getOverrideMode() const { return override_mode; }
const std::vector<std::string> & getConfigMap() const { return config_map; }
const std::string & getOverrideMode() const;
const std::vector<std::string> & getConfigMap() const;
private:
std::string override_mode;
std::vector<std::string> config_map;
};
std::ostream &
operator<<(std::ostream &os, const AppSecPracticeSnortSignatures &obj)
{
os
<< "override mode: "
<< obj.getOverrideMode()
<< ". Config map: [" << std::endl
<< makeSeparatedStr(obj.getConfigMap(), ",")
<< std::endl << "]";
return os;
}
class AppSecPracticeOpenSchemaAPI
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSecPracticeOpenSchemaAPI practice";
parseAppsecJSONKey<std::string>("override-mode", override_mode, archive_in, "Inactive");
parseAppsecJSONKey<std::vector<std::string>>("configmap", config_map, archive_in);
}
void load(cereal::JSONInputArchive &archive_in);
const std::string & getOverrideMode() const { return override_mode; }
const std::vector<std::string> & getConfigMap() const { return config_map; }
const std::string & getOverrideMode() const;
const std::vector<std::string> & getConfigMap() const;
private:
std::string override_mode;
std::vector<std::string> config_map;
};
std::ostream &
operator<<(std::ostream &os, const AppSecPracticeOpenSchemaAPI &obj)
{
os
<< "override mode: "
<< obj.getOverrideMode()
<< ". Config map: [" << std::endl
<< makeSeparatedStr(obj.getConfigMap(), ",")
<< std::endl << "]";
return os;
}
class AppSecPracticeSpec
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec practice spec";
parseAppsecJSONKey<AppSecPracticeOpenSchemaAPI>(
"openapi-schema-validation",
openapi_schema_validation,
archive_in
);
parseAppsecJSONKey<AppSecPracticeSnortSignatures>("snort-signatures", snort_signatures, archive_in);
parseAppsecJSONKey<AppSecPracticeWebAttacks>("web-attacks", web_attacks, archive_in);
parseAppsecJSONKey<AppSecPracticeAntiBot>("anti-bot", anti_bot, archive_in);
parseAppsecJSONKey<std::string>("name", practice_name, archive_in);
}
void load(cereal::JSONInputArchive &archive_in);
const AppSecPracticeOpenSchemaAPI & getOpenSchemaValidation() const { return openapi_schema_validation; }
const AppSecPracticeSnortSignatures & getSnortSignatures() const { return snort_signatures; }
const AppSecPracticeWebAttacks & getWebAttacks() const { return web_attacks; }
const AppSecPracticeAntiBot & getAntiBot() const { return anti_bot; }
const std::string & getName() const { return practice_name; }
const AppSecPracticeOpenSchemaAPI & getOpenSchemaValidation() const;
const AppSecPracticeSnortSignatures & getSnortSignatures() const;
const AppSecPracticeWebAttacks & getWebAttacks() const;
const AppSecPracticeAntiBot & getAntiBot() const;
const std::string & getName() const;
private:
AppSecPracticeOpenSchemaAPI openapi_schema_validation;
@@ -334,24 +140,11 @@ private:
std::string practice_name;
};
std::ostream &
operator<<(std::ostream &os, const AppSecPracticeSpec &obj)
{
os
<< "Open Schema API:" << std::endl
<< obj.getOpenSchemaValidation()
<< std::endl << "Snort Signatures:" << std::endl
<< obj.getOpenSchemaValidation()
<< std::endl << "Web Attacks:" << std::endl
<< obj.getWebAttacks()
<< std::endl << "Web Bots:" << std::endl
<< obj.getAntiBot();
return os;
}
class PracticeAdvancedConfig
{
public:
PracticeAdvancedConfig() {}
PracticeAdvancedConfig(const AppSecPracticeSpec &parsed_appsec_spec)
:
http_header_max_size(parsed_appsec_spec.getWebAttacks().getMaxHeaderSizeBytes()),
@@ -361,19 +154,7 @@ public:
url_max_size(parsed_appsec_spec.getWebAttacks().getMaxUrlSizeBytes())
{}
void
save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("httpHeaderMaxSize", http_header_max_size),
cereal::make_nvp("httpIllegalMethodsAllowed", http_illegal_methods_allowed),
cereal::make_nvp("httpRequestBodyMaxSize", http_request_body_max_size),
cereal::make_nvp("jsonMaxObjectDepth", json_max_object_depth),
cereal::make_nvp("urlMaxSize", url_max_size)
);
}
void setIllegalMethodsAllowed(int val) { http_illegal_methods_allowed = val; };
void save(cereal::JSONOutputArchive &out_ar) const;
private:
int http_header_max_size;
@@ -394,16 +175,7 @@ public:
log(log_section)
{}
void
save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("$triggerType", trigger_type),
cereal::make_nvp("id", id),
cereal::make_nvp("name", name),
cereal::make_nvp("log", log)
);
}
void save(cereal::JSONOutputArchive &out_ar) const;
private:
std::string trigger_type;
@@ -415,23 +187,10 @@ private:
class AppSecOverride
{
public:
AppSecOverride(const SourcesIdentifiers &parsed_trusted_sources)
{
std::string source_ident = parsed_trusted_sources.getSourceIdent();
std::map<std::string, std::string> behavior = {{"httpSourceId", source_ident}};
parsed_behavior.push_back(behavior);
parsed_match = {{"operator", "BASIC"}, {"tag", "sourceip"}, {"value", "0.0.0.0/0"}};
}
AppSecOverride(const SourcesIdentifiers &parsed_trusted_sources);
void save(cereal::JSONOutputArchive &out_ar) const;
void
save(cereal::JSONOutputArchive &out_ar) const
{
std::string parameter_type = "TrustedSource";
out_ar(
cereal::make_nvp("parsedBehavior", parsed_behavior),
cereal::make_nvp("parsedMatch", parsed_match)
);
}
private:
std::vector<std::map<std::string, std::string>> parsed_behavior;
std::map<std::string, std::string> parsed_match;
@@ -440,6 +199,8 @@ private:
class WebAppSection
{
public:
WebAppSection() {}
WebAppSection(
const std::string &_application_urls,
const std::string &_asset_id,
@@ -451,75 +212,12 @@ public:
const AppSecPracticeSpec &parsed_appsec_spec,
const LogTriggerSection &parsed_log_trigger,
const std::string &default_mode,
const AppSecTrustedSources &parsed_trusted_sources)
:
application_urls(_application_urls),
asset_id(_asset_id),
asset_name(_asset_name),
rule_id(_rule_id),
rule_name(_rule_name),
practice_id(_practice_id),
practice_name(_practice_name),
context("practiceId(" + practice_id +")"),
web_attack_mitigation_severity(parsed_appsec_spec.getWebAttacks().getMinimumConfidence()),
web_attack_mitigation_mode(parsed_appsec_spec.getWebAttacks().getMode(default_mode)),
practice_advanced_config(parsed_appsec_spec),
anti_bots(parsed_appsec_spec.getAntiBot()),
trusted_sources({parsed_trusted_sources})
{
web_attack_mitigation = true;
web_attack_mitigation_action =
web_attack_mitigation_severity == "critical" ? "low" :
web_attack_mitigation_severity == "high" ? "balanced" :
web_attack_mitigation_severity == "medium" ? "high" :
"Error";
const AppSecTrustedSources &parsed_trusted_sources
);
triggers.push_back(TriggersInWaapSection(parsed_log_trigger));
for (const SourcesIdentifiers &source_ident : parsed_trusted_sources.getSourcesIdentifiers()) {
overrides.push_back(AppSecOverride(source_ident));
}
}
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
std::string disabled_str = "Disabled";
std::string detect_str = "Detect";
std::vector<std::string> empty_list;
out_ar(
cereal::make_nvp("context", context),
cereal::make_nvp("webAttackMitigation", web_attack_mitigation),
cereal::make_nvp("webAttackMitigationSeverity", web_attack_mitigation_severity),
cereal::make_nvp("webAttackMitigationAction", web_attack_mitigation_action),
cereal::make_nvp("webAttackMitigationMode", web_attack_mitigation_mode),
cereal::make_nvp("practiceAdvancedConfig", practice_advanced_config),
cereal::make_nvp("csrfProtection", disabled_str),
cereal::make_nvp("openRedirect", disabled_str),
cereal::make_nvp("errorDisclosure", disabled_str),
cereal::make_nvp("practiceId", practice_id),
cereal::make_nvp("practiceName", practice_name),
cereal::make_nvp("assetId", asset_id),
cereal::make_nvp("assetName", asset_name),
cereal::make_nvp("ruleId", rule_id),
cereal::make_nvp("ruleName", rule_name),
cereal::make_nvp("triggers", triggers),
cereal::make_nvp("applicationUrls", application_urls),
cereal::make_nvp("overrides", overrides),
cereal::make_nvp("trustedSources", trusted_sources),
cereal::make_nvp("waapParameters", empty_list),
cereal::make_nvp("botProtection", false),
cereal::make_nvp("antiBot", anti_bots),
cereal::make_nvp("botProtection_v2", detect_str)
);
}
const std::string & getPracticeId() const { return practice_id; }
bool
operator<(const WebAppSection &other) const
{
return getPracticeId() < other.getPracticeId();
}
void save(cereal::JSONOutputArchive &out_ar) const;
const std::string & getPracticeId() const;
bool operator<(const WebAppSection &other) const;
private:
std::string application_urls;
@@ -573,36 +271,9 @@ public:
practice_advanced_config(parsed_appsec_spec)
{}
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
std::string disabled_str = "Disabled";
std::vector<std::string> empty_list;
out_ar(
cereal::make_nvp("application_urls", application_urls),
cereal::make_nvp("asset_id", asset_id),
cereal::make_nvp("asset_name", asset_name),
cereal::make_nvp("context", context),
cereal::make_nvp("practiceAdvancedConfig", practice_advanced_config),
cereal::make_nvp("practice_id", practice_id),
cereal::make_nvp("practice_name", practice_name),
cereal::make_nvp("ruleId", rule_id),
cereal::make_nvp("ruleName", rule_name),
cereal::make_nvp("schemaValidation", false),
cereal::make_nvp("schemaValidation_v2", disabled_str),
cereal::make_nvp("web_attack_mitigation", web_attack_mitigation),
cereal::make_nvp("web_attack_mitigation_action", web_attack_mitigation_action),
cereal::make_nvp("web_attack_mitigation_severity", web_attack_mitigation_severity),
cereal::make_nvp("web_attack_mitigation_mode", web_attack_mitigation_mode),
cereal::make_nvp("oas", empty_list),
cereal::make_nvp("trustedSources", empty_list),
cereal::make_nvp("triggers", empty_list),
cereal::make_nvp("waapParameters", empty_list),
cereal::make_nvp("overrides", empty_list)
);
}
void save(cereal::JSONOutputArchive &out_ar) const;
const std::string & getPracticeId() const { return practice_id; }
const std::string & getPracticeId() const;
private:
std::string application_urls;
@@ -630,14 +301,7 @@ public:
webApplicationPractices(_webApplicationPractices),
webAPIPractices(_webAPIPractices) {}
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("WebAPISecurity", webAPIPractices),
cereal::make_nvp("WebApplicationSecurity", webApplicationPractices)
);
}
void save(cereal::JSONOutputArchive &out_ar) const;
private:
std::vector<WebAppSection> webApplicationPractices;
@@ -652,54 +316,27 @@ public:
app_sec_rulebase(_app_sec)
{}
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
out_ar(cereal::make_nvp("WAAP", app_sec_rulebase));
}
void save(cereal::JSONOutputArchive &out_ar) const;
private:
AppSecRulebase app_sec_rulebase;
};
class ParsedRule
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec ParsedRule";
parseAppsecJSONKey<std::vector<std::string>>("exceptions", exceptions, archive_in);
parseAppsecJSONKey<std::vector<std::string>>("triggers", log_triggers, archive_in);
parseAppsecJSONKey<std::vector<std::string>>("practices", practices, archive_in);
parseAppsecJSONKey<std::string>("mode", mode, archive_in);
parseAppsecJSONKey<std::string>("custom-response", custom_response, archive_in);
parseAppsecJSONKey<std::string>("source-identifiers", source_identifiers, archive_in);
parseAppsecJSONKey<std::string>("trusted-sources", trusted_sources, archive_in);
try {
archive_in(cereal::make_nvp("host", host));
} catch (const cereal::Exception &e)
{} // The default ParsedRule does not hold a host, so no error handling
}
void load(cereal::JSONInputArchive &archive_in);
const std::vector<std::string> & getExceptions() const { return exceptions; }
const std::vector<std::string> & getLogTriggers() const { return log_triggers; }
const std::vector<std::string> & getPractices() const { return practices; }
const std::string & getHost() const { return host; }
const std::string & getMode() const { return mode; }
void setMode(const std::string &_mode) { mode = _mode; };
const std::string & getCustomResponse() const { return custom_response; }
const std::string & getSourceIdentifiers() const { return source_identifiers; }
const std::string & getTrustedSources() const { return trusted_sources; }
const std::vector<std::string> & getExceptions() const;
const std::vector<std::string> & getLogTriggers() const;
const std::vector<std::string> & getPractices() const;
const std::string & getHost() const;
const std::string & getMode() const;
void setHost(const std::string &_host);
void setMode(const std::string &_mode);
const std::string & getCustomResponse() const;
const std::string & getSourceIdentifiers() const;
const std::string & getTrustedSources() const;
private:
std::vector<std::string> exceptions;
@@ -712,88 +349,32 @@ private:
std::string trusted_sources;
};
std::ostream &
operator<<(std::ostream &os, const ParsedRule &obj)
{
os
<< "host: "
<< obj.getHost()
<< std::endl << "log trigger: "
<< makeSeparatedStr(obj.getLogTriggers(), ",")
<< std::endl << "mode: "
<< obj.getMode()
<< std::endl << "practices: "
<< makeSeparatedStr(obj.getPractices(), ",")
<< std::endl << "web responce: "
<< obj.getCustomResponse()
<< std::endl << " Exceptions: [" << std::endl
<< makeSeparatedStr(obj.getExceptions(), ",")
<< std::endl << "]";
return os;
}
class AppsecPolicySpec : Singleton::Consume<I_Environment>
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec policy spec";
parseAppsecJSONKey<ParsedRule>("default", default_rule, archive_in);
auto default_mode_annot =
Singleton::Consume<I_Environment>::by<AppsecPolicySpec>()->get<std::string>("default mode annotation");
if (default_mode_annot.ok() && !default_mode_annot.unpack().empty() && default_rule.getMode().empty()) {
default_rule.setMode(default_mode_annot.unpack());
}
parseAppsecJSONKey<std::vector<ParsedRule>>("specific-rules", specific_rules, archive_in);
}
void load(cereal::JSONInputArchive &archive_in);
const ParsedRule & getDefaultRule() const { return default_rule; }
const std::vector<ParsedRule> & getSpecificRules() const { return specific_rules; }
const ParsedRule & getDefaultRule() const;
const std::list<ParsedRule> & getSpecificRules() const;
private:
ParsedRule default_rule;
std::vector<ParsedRule> specific_rules;
std::list<ParsedRule> specific_rules;
};
class AppsecLinuxPolicy : Singleton::Consume<I_Environment>
{
public:
void
serialize(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec policy spec";
parseAppsecJSONKey<AppsecPolicySpec>("policies", policies, archive_in);
parseAppsecJSONKey<std::vector<AppSecPracticeSpec>>("practices", practices, archive_in);
parseAppsecJSONKey<std::vector<AppsecTriggerSpec>>("logtriggers", log_triggers, archive_in);
parseAppsecJSONKey<std::vector<AppSecCustomResponseSpec>>("customresponses", custom_responses, archive_in);
parseAppsecJSONKey<std::vector<AppsecExceptionSpec>>("exceptions", exceptions, archive_in);
parseAppsecJSONKey<std::vector<TrustedSourcesSpec>>("trustedsources", trusted_sources, archive_in);
parseAppsecJSONKey<std::vector<SourceIdentifierSpecWrapper>>(
"sourceidentifiers",
sources_identifier,
archive_in
);
}
serialize(cereal::JSONInputArchive &archive_in);
const AppsecPolicySpec & getAppsecPolicySpec() const { return policies; }
const std::vector<AppSecPracticeSpec> & getAppSecPracticeSpecs() const { return practices; }
const std::vector<AppsecTriggerSpec> & getAppsecTriggerSpecs() const { return log_triggers; }
const std::vector<AppSecCustomResponseSpec> & getAppSecCustomResponseSpecs() const { return custom_responses; }
const std::vector<AppsecExceptionSpec> & getAppsecExceptionSpecs() const { return exceptions; }
const std::vector<TrustedSourcesSpec> & getAppsecTrustedSourceSpecs() const { return trusted_sources; }
const std::vector<SourceIdentifierSpecWrapper> &
getAppsecSourceIdentifierSpecs() const
{
return sources_identifier;
}
const AppsecPolicySpec & getAppsecPolicySpec() const;
const std::vector<AppSecPracticeSpec> & getAppSecPracticeSpecs() const;
const std::vector<AppsecTriggerSpec> & getAppsecTriggerSpecs() const;
const std::vector<AppSecCustomResponseSpec> & getAppSecCustomResponseSpecs() const;
const std::vector<AppsecExceptionSpec> & getAppsecExceptionSpecs() const;
const std::vector<TrustedSourcesSpec> & getAppsecTrustedSourceSpecs() const;
const std::vector<SourceIdentifierSpecWrapper> & getAppsecSourceIdentifierSpecs() const;
private:
AppsecPolicySpec policies;
@@ -805,16 +386,5 @@ private:
std::vector<SourceIdentifierSpecWrapper> sources_identifier;
};
std::ostream &
operator<<(std::ostream &os, const AppsecPolicySpec &obj)
{
os
<< "Default Rule: "
<< obj.getDefaultRule()
<< std::endl <<"Specific Rules: [" << std::endl
<< makeSeparatedStr(obj.getSpecificRules(), ",")
<< std::endl << "]";
return os;
}
// LCOV_EXCL_STOP
#endif // __APPSEC_PRACTICE_SECTION_H__

View File

@@ -30,34 +30,22 @@ USE_DEBUG_FLAG(D_K8S_POLICY);
class AppsecExceptionSpec
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec exception spec";
parseAppsecJSONKey<std::string>("action", action, archive_in);
parseAppsecJSONKey<std::vector<std::string>>("countryCode", country_code, archive_in);
parseAppsecJSONKey<std::vector<std::string>>("countryName", country_name, archive_in);
parseAppsecJSONKey<std::vector<std::string>>("hostName", host_name, archive_in);
parseAppsecJSONKey<std::vector<std::string>>("paramName", param_name, archive_in);
parseAppsecJSONKey<std::vector<std::string>>("paramValue", param_value, archive_in);
parseAppsecJSONKey<std::vector<std::string>>("protectionName", protection_name, archive_in);
parseAppsecJSONKey<std::vector<std::string>>("sourceIdentifier", source_identifier, archive_in);
parseAppsecJSONKey<std::vector<std::string>>("sourceIp", source_ip, archive_in);
parseAppsecJSONKey<std::vector<std::string>>("url", url, archive_in);
}
void load(cereal::JSONInputArchive &archive_in);
const std::string & getAction() const { return action; }
const std::vector<std::string> & getCountryCode() const { return country_code; }
const std::vector<std::string> & getCountryName() const { return country_name; }
const std::vector<std::string> & getHostName() const { return host_name; }
const std::vector<std::string> & getParamName() const { return param_name; }
const std::vector<std::string> & getParamValue() const { return param_value; }
const std::vector<std::string> & getProtectionName() const { return protection_name; }
const std::vector<std::string> & getSourceIdentifier() const { return source_identifier; }
const std::vector<std::string> & getSourceIp() const { return source_ip; }
const std::vector<std::string> & getUrl() const { return url; }
const std::string & getName() const;
const std::string & getAction() const;
const std::vector<std::string> & getCountryCode() const;
const std::vector<std::string> & getCountryName() const;
const std::vector<std::string> & getHostName() const;
const std::vector<std::string> & getParamName() const;
const std::vector<std::string> & getParamValue() const;
const std::vector<std::string> & getProtectionName() const;
const std::vector<std::string> & getSourceIdentifier() const;
const std::vector<std::string> & getSourceIp() const;
const std::vector<std::string> & getUrl() const;
private:
std::string name;
std::string action;
std::vector<std::string> country_code;
std::vector<std::string> country_name;
@@ -70,71 +58,11 @@ private:
std::vector<std::string> url;
};
std::ostream &
operator<<(std::ostream &os, const AppsecExceptionSpec &obj)
{
os
<< "action: "
<< makeSeparatedStr(obj.getAction(), ",")
<< "countryCode: "
<< makeSeparatedStr(obj.getCountryCode(), ",")
<< "countryName: "
<< makeSeparatedStr(obj.getCountryName(), ",")
<< "hostName: "
<< makeSeparatedStr(obj.getHostName(), ",")
<< "paramName: "
<< makeSeparatedStr(obj.getParamName(), ",")
<< "paramValue: "
<< makeSeparatedStr(obj.getParamValue(), ",")
<< "protectionName: "
<< makeSeparatedStr(obj.getProtectionName(), ",")
<< "sourceIdentifier: "
<< makeSeparatedStr(obj.getSourceIdentifier(), ",")
<< "sourceIp: "
<< makeSeparatedStr(obj.getSourceIp(), ",")
<< "url: "
<< makeSeparatedStr(obj.getUrl(), ",");
return os;
}
class ExceptionMatch
{
public:
ExceptionMatch(const AppsecExceptionSpec &parsed_exception)
:
match_type(MatchType::Operator),
op("and")
{
if (!parsed_exception.getCountryCode().empty()) {
items.push_back(ExceptionMatch("countryCode", parsed_exception.getCountryCode()));
}
if (!parsed_exception.getCountryName().empty()) {
items.push_back(ExceptionMatch("countryName", parsed_exception.getCountryName()));
}
if (!parsed_exception.getHostName().empty()) {
items.push_back(ExceptionMatch("hostName", parsed_exception.getHostName()));
}
if (!parsed_exception.getParamName().empty()) {
items.push_back(ExceptionMatch("paramName", parsed_exception.getParamName()));
}
if (!parsed_exception.getParamValue().empty()) {
items.push_back(ExceptionMatch("paramValue", parsed_exception.getParamValue()));
}
if (!parsed_exception.getProtectionName().empty()) {
items.push_back(ExceptionMatch("protectionName", parsed_exception.getProtectionName()));
}
if (!parsed_exception.getSourceIdentifier().empty()) {
items.push_back(ExceptionMatch("sourceIdentifier", parsed_exception.getSourceIdentifier()));
}
if (!parsed_exception.getSourceIp().empty()) {
items.push_back(ExceptionMatch("sourceIp", parsed_exception.getSourceIp()));
}
if (!parsed_exception.getUrl().empty()) {
items.push_back(ExceptionMatch("url", parsed_exception.getUrl()));
}
}
ExceptionMatch() {}
ExceptionMatch(const AppsecExceptionSpec &parsed_exception);
ExceptionMatch(const std::string &_key, const std::vector<std::string> &_value)
:
match_type(MatchType::Condition),
@@ -143,34 +71,7 @@ public:
value(_value)
{}
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
switch (match_type) {
case (MatchType::Condition): {
std::string type_str = "condition";
out_ar(
cereal::make_nvp("key", key),
cereal::make_nvp("op", op),
cereal::make_nvp("type", type_str),
cereal::make_nvp("value", value)
);
break;
}
case (MatchType::Operator): {
std::string type_str = "operator";
out_ar(
cereal::make_nvp("op", op),
cereal::make_nvp("type", type_str),
cereal::make_nvp("items", items)
);
break;
}
default: {
dbgError(D_K8S_POLICY) << "No match for exception match type: " << static_cast<int>(match_type);
}
}
}
void save(cereal::JSONOutputArchive &out_ar) const;
private:
MatchType match_type;
@@ -183,31 +84,14 @@ private:
class ExceptionBehavior
{
public:
ExceptionBehavior() {}
ExceptionBehavior(
const std::string &_key,
const std::string &_value)
:
key(_key),
value(_value)
{
try {
id = to_string(boost::uuids::random_generator()());
} catch (const boost::uuids::entropy_error &e) {
dbgWarning(D_K8S_POLICY) << "Failed to generate exception behavior UUID. Error: " << e.what();
}
}
const std::string &_value
);
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("key", key),
cereal::make_nvp("value", value),
cereal::make_nvp("id", id)
);
}
const std::string getBehaviorId() const { return id; }
void save(cereal::JSONOutputArchive &out_ar) const;
const std::string getBehaviorId() const;
private:
std::string key;
@@ -218,6 +102,7 @@ private:
class InnerException
{
public:
InnerException() {}
InnerException(
ExceptionBehavior _behavior,
ExceptionMatch _match)
@@ -225,22 +110,9 @@ public:
behavior(_behavior),
match(_match) {}
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("behavior", behavior),
cereal::make_nvp("match", match)
);
}
const std::string getBehaviorId() const { return behavior.getBehaviorId(); }
bool
operator<(const InnerException &other) const
{
return getBehaviorId() < other.getBehaviorId();
}
void save(cereal::JSONOutputArchive &out_ar) const;
const std::string getBehaviorId() const;
bool operator<(const InnerException &other) const;
private:
ExceptionBehavior behavior;
@@ -250,28 +122,8 @@ private:
class ExceptionsRulebase
{
public:
ExceptionsRulebase(
std::vector<InnerException> _exceptions)
:
exceptions(_exceptions)
{
std::string context_id_str = "";
for (const InnerException exception : exceptions) {
std::string curr_id = "parameterId(" + exception.getBehaviorId() + "), ";
context_id_str += curr_id;
}
context_id_str = context_id_str.substr(0, context_id_str.size() - 2);
context = "Any(" + context_id_str + ")";
}
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("context", context),
cereal::make_nvp("exceptions", exceptions)
);
}
ExceptionsRulebase(std::vector<InnerException> _exceptions);
void save(cereal::JSONOutputArchive &out_ar) const;
private:
std::string context;
@@ -286,11 +138,7 @@ public:
public:
Exception(const std::vector<ExceptionsRulebase> &_exception) : exception(_exception) {}
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
out_ar(cereal::make_nvp("exception", exception));
}
void save(cereal::JSONOutputArchive &out_ar) const;
private:
std::vector<ExceptionsRulebase> exception;
@@ -298,13 +146,7 @@ public:
ExceptionsWrapper(const std::vector<ExceptionsRulebase> &_exception) : exception_rulebase(Exception(_exception))
{}
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("rulebase", exception_rulebase)
);
}
void save(cereal::JSONOutputArchive &out_ar) const;
private:
Exception exception_rulebase;

View File

@@ -21,26 +21,21 @@
#include "debug.h"
#include "rest.h"
#include "cereal/archives/json.hpp"
#include <cereal/types/map.hpp>
#include "k8s_policy_common.h"
USE_DEBUG_FLAG(D_K8S_POLICY);
// LCOV_EXCL_START Reason: no test exist
class IngressMetadata
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "IngressMetadata load";
parseAppsecJSONKey<std::string>("name", name, archive_in);
parseAppsecJSONKey<std::string>("resourceVersion", resourceVersion, archive_in);
parseAppsecJSONKey<std::string>("namespace", namespace_name, archive_in);
parseAppsecJSONKey<std::map<std::string, std::string>>("annotations", annotations, archive_in);
}
void load(cereal::JSONInputArchive &archive_in);
const std::string & getName() const { return name; }
const std::string & getResourceVersion() const { return resourceVersion; }
const std::string & getNamespace() const { return namespace_name; }
const std::map<std::string, std::string> & getAnnotations() const { return annotations; }
const std::string & getName() const;
const std::string & getResourceVersion() const;
const std::string & getNamespace() const;
const std::map<std::string, std::string> & getAnnotations() const;
private:
std::string name;
@@ -53,19 +48,15 @@ class IngressRulePath
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading ingress defined rule path";
parseAppsecJSONKey<std::string>("path", path, archive_in);
}
load(cereal::JSONInputArchive &archive_in);
const std::string & getPath() const { return path; }
const std::string & getPath() const;
private:
std::string path;
};
std::ostream &
inline std::ostream &
operator<<(std::ostream &os, const IngressRulePath &obj)
{
os << obj.getPath();
@@ -75,14 +66,9 @@ operator<<(std::ostream &os, const IngressRulePath &obj)
class IngressRulePathsWrapper
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading ingress defined rule path wrapper";
parseAppsecJSONKey<std::vector<IngressRulePath>>("paths", paths, archive_in);
}
void load(cereal::JSONInputArchive &archive_in);
const std::vector<IngressRulePath> & getRulePaths() const { return paths; }
const std::vector<IngressRulePath> & getRulePaths() const;
private:
std::vector<IngressRulePath> paths;
@@ -91,23 +77,17 @@ private:
class IngressDefinedRule
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading ingress defined rule";
parseAppsecJSONKey<std::string>("host", host, archive_in);
parseAppsecJSONKey<IngressRulePathsWrapper>("http", paths_wrapper, archive_in);
}
void load(cereal::JSONInputArchive &archive_in);
const std::string & getHost() const { return host; }
const IngressRulePathsWrapper & getPathsWrapper() const { return paths_wrapper; }
const std::string & getHost() const;
const IngressRulePathsWrapper & getPathsWrapper() const;
private:
std::string host;
IngressRulePathsWrapper paths_wrapper;
};
std::ostream &
inline std::ostream &
operator<<(std::ostream &os, const IngressDefinedRule &obj)
{
os
@@ -123,13 +103,9 @@ class DefaultBackend
{
public:
void
load(cereal::JSONInputArchive &)
{
dbgTrace(D_K8S_POLICY) << "Loading Default Backend";
is_exists = true;
}
load(cereal::JSONInputArchive &);
bool isExists() const { return is_exists; }
bool isExists() const;
private:
bool is_exists = false;
@@ -139,17 +115,11 @@ class IngressSpec
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading single ingress spec";
parseAppsecJSONKey<std::string>("ingressClassName", ingress_class_name, archive_in);
parseAppsecJSONKey<std::vector<IngressDefinedRule>>("rules", rules, archive_in);
parseAppsecJSONKey<DefaultBackend>("defaultBackend", default_backend, archive_in);
}
load(cereal::JSONInputArchive &archive_in);
const std::string & getIngressClassName() const { return ingress_class_name; }
const std::vector<IngressDefinedRule> & getRules() const { return rules; }
bool isDefaultBackendExists() const { return default_backend.isExists(); }
const std::string & getIngressClassName() const;
const std::vector<IngressDefinedRule> & getRules() const;
bool isDefaultBackendExists() const;
private:
std::string ingress_class_name;
@@ -157,31 +127,14 @@ private:
DefaultBackend default_backend;
};
std::ostream &
operator<<(std::ostream &os, const IngressSpec &obj)
{
os
<< "Ingress Spec - ingressClassName: "
<< obj.getIngressClassName()
<< ", rules: [" << std::endl
<< makeSeparatedStr(obj.getRules(), ",")
<< std::endl << "]";
return os;
}
class SingleIngressData
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading single ingress data";
parseAppsecJSONKey<IngressMetadata>("metadata", metadata, archive_in);
parseAppsecJSONKey<IngressSpec>("spec", spec, archive_in);
}
load(cereal::JSONInputArchive &archive_in);
const IngressMetadata & getMetadata() const { return metadata; }
const IngressSpec & getSpec() const { return spec; }
const IngressMetadata & getMetadata() const;
const IngressSpec & getSpec() const;
private:
IngressMetadata metadata;
@@ -192,29 +145,10 @@ private:
class IngressData : public ClientRest
{
public:
bool
loadJson(const std::string &json)
{
std::string modified_json = json;
modified_json.pop_back();
std::stringstream in;
in.str(modified_json);
dbgTrace(D_K8S_POLICY) << "Loading ingress data";
try {
cereal::JSONInputArchive in_ar(in);
in_ar(
cereal::make_nvp("apiVersion", apiVersion),
cereal::make_nvp("items", items)
);
} catch (cereal::Exception &e) {
dbgError(D_K8S_POLICY) << "Failed to load ingress data JSON. Error: " << e.what();
return false;
}
return true;
}
bool loadJson(const std::string &json);
const std::string & getapiVersion() const { return apiVersion; }
const std::vector<SingleIngressData> & getItems() const { return items; }
const std::string & getapiVersion() const;
const std::vector<SingleIngressData> & getItems() const;
private:
std::string apiVersion;

View File

@@ -0,0 +1,132 @@
// 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 __POLICY_MAKER_UTILS_H__
#define __POLICY_MAKER_UTILS_H__
#include <string>
#include <fstream>
#include <utility>
#include <sys/types.h>
#include <cereal/archives/json.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include "debug.h"
#include "common.h"
#include "maybe_res.h"
#include "appsec_practice_section.h"
#include "ingress_data.h"
#include "settings_section.h"
#include "triggers_section.h"
#include "k8s_policy_common.h"
#include "exceptions_section.h"
#include "rules_config_section.h"
#include "trusted_sources_section.h"
USE_DEBUG_FLAG(D_NGINX_POLICY);
enum class AnnotationTypes {
PRACTICE,
TRIGGER,
EXCEPTION,
WEB_USER_RES,
SOURCE_IDENTIFIERS,
TRUSTED_SOURCES,
COUNT
};
// LCOV_EXCL_START Reason: no test exist
class SecurityAppsWrapper
{
public:
SecurityAppsWrapper(
const AppSecWrapper &_waap,
const TriggersWrapper &_trrigers,
const RulesConfigWrapper &_rules,
const ExceptionsWrapper &_exceptions,
const std::string &_policy_version)
:
waap(_waap),
trrigers(_trrigers),
rules(_rules),
exceptions(_exceptions),
policy_version(_policy_version) {}
void save(cereal::JSONOutputArchive &out_ar) const;
private:
AppSecWrapper waap;
TriggersWrapper trrigers;
RulesConfigWrapper rules;
ExceptionsWrapper exceptions;
std::string policy_version;
};
class PolicyWrapper
{
public:
PolicyWrapper(
const SettingsWrapper &_settings,
const SecurityAppsWrapper &_security_apps)
:
settings(_settings),
security_apps(_security_apps) {}
void save(cereal::JSONOutputArchive &out_ar) const;
private:
SettingsWrapper settings;
SecurityAppsWrapper security_apps;
};
// LCOV_EXCL_STOP
class PolicyMakerUtils
{
public:
void clearElementsMaps();
bool startsWith(const std::string &str, const std::string &prefix);
bool endsWith(const std::string &str, const std::string &suffix);
std::tuple<std::string, std::string, std::string> splitHostName(const std::string &host_name);
std::string dumpPolicyToFile(const PolicyWrapper &policy, const std::string &policy_path) const;
PolicyWrapper combineElementsToPolicy(const std::string &policy_version);
void createPolicyElementsByRule(
const ParsedRule &rule,
const ParsedRule &default_rule,
const AppsecLinuxPolicy &policy,
const std::string &policy_name
);
void createPolicyElements(
const std::vector<ParsedRule> &rules,
const ParsedRule &default_rule,
const AppsecLinuxPolicy &policy,
const std::string &policy_name
);
private:
std::map<std::string, LogTriggerSection> log_triggers;
std::map<std::string, WebUserResponseTriggerSection> web_user_res_triggers;
std::map<std::string, InnerException> inner_exceptions;
std::map<std::string, WebAppSection> web_apps;
std::map<std::string, RulesConfigRulebase> rules_config;
};
#endif // __POLICY_MAKER_UTILS_H__

View File

@@ -30,100 +30,24 @@ USE_DEBUG_FLAG(D_K8S_POLICY);
class AssetUrlParser
{
public:
AssetUrlParser() {}
static AssetUrlParser parse(const std::string &uri);
std::string query_string, asset_uri, protocol, asset_url, port;
AssetUrlParser()
{}
AssetUrlParser(const std::string &asset)
{
parse(asset);
}
private:
static AssetUrlParser
parse(const std::string &uri)
{
AssetUrlParser result;
using iterator_t = std::string::const_iterator;
if (uri.length() == 0) return result;
iterator_t uri_end = uri.end();
// get query start
iterator_t query_start = std::find(uri.begin(), uri_end, '?');
// protocol
iterator_t protocol_start = uri.begin();
iterator_t protocol_end = std::find(protocol_start, uri_end, ':'); //"://");
if (protocol_end != uri_end) {
std::string http_protocol = &*(protocol_end);
if ((http_protocol.length() > 3) && (http_protocol.substr(0, 3) == "://")) {
result.protocol = std::string(protocol_start, protocol_end);
protocol_end += 3; // ://
} else {
protocol_end = uri.begin(); // no protocol
}
} else {
protocol_end = uri.begin(); // no protocol
}
// URL
iterator_t host_start = protocol_end;
iterator_t path_start = std::find(host_start, uri_end, '/');
iterator_t host_end = std::find(protocol_end, (path_start != uri_end) ? path_start : query_start, ':');
result.asset_url = std::string(host_start, host_end);
// port
if ((host_end != uri_end) && ((&*(host_end))[0] == ':')) { // we have a port
host_end++;
iterator_t portEnd = (path_start != uri_end) ? path_start : query_start;
result.port = std::string(host_end, portEnd);
}
// URI
if (path_start != uri_end) result.asset_uri = std::string(path_start, query_start);
// query
if (query_start != uri_end) result.query_string = std::string(query_start, uri.end());
return result;
} // Parse
}; // uri
};
class PracticeSection
{
public:
PracticeSection(const std::string &_id, const std::string &_type, const std::string &_practice_name)
{
auto maybe_type = string_to_practice_type.find(_type);
if (maybe_type == string_to_practice_type.end()) {
dbgError(D_K8S_POLICY) << "Illegal pracrtice type: " << _type;
return;
}
PracticeSection(
const std::string &_id,
const std::string &_type,
const std::string &_practice_name);
type = _type;
name = _practice_name;
id = _id;
}
void save(cereal::JSONOutputArchive &out_ar) const;
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("practiceId", id),
cereal::make_nvp("practiceName", name),
cereal::make_nvp("practiceType", type)
);
}
const std::string & getPracticeId() const { return id; }
const std::string & getPracticeName() const { return name; }
const std::string & getPracticeId() const;
const std::string & getPracticeName() const;
private:
std::string id;
@@ -134,30 +58,10 @@ private:
class ParametersSection
{
public:
ParametersSection(
const std::string &_id,
const std::string &_name)
:
name(_name),
id(_id)
{
if (_id.empty() && _name.empty()) {
dbgError(D_K8S_POLICY) << "Illegal Parameter values. Name and ID are empty";
return;
}
}
ParametersSection(const std::string &_id, const std::string &_name);
const std::string & getId() const { return id; }
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("parameterId", id),
cereal::make_nvp("parameterName", name),
cereal::make_nvp("parameterType", type)
);
}
void save(cereal::JSONOutputArchive &out_ar) const;
const std::string & getId() const;
private:
std::string name;
@@ -171,35 +75,12 @@ public:
RulesTriggerSection(
const std::string &_name,
const std::string &_id,
const std::string &_type)
:
name(_name),
id(_id)
{
if (_name.empty() && _id.empty()) {
dbgError(D_K8S_POLICY) << "Illegal values for trigger. Name and ID are empty";
return;
}
auto maybe_type = string_to_trigger_type.find(_type);
if (maybe_type == string_to_trigger_type.end()) {
dbgError(D_K8S_POLICY) << "Illegal trigger type in rule: " << _type;
return;
}
type = _type;
}
const std::string &_type);
const std::string & getId() const { return id; }
const std::string & getName() const { return id; }
void save(cereal::JSONOutputArchive &out_ar) const;
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("triggerId", id),
cereal::make_nvp("triggerName", name),
cereal::make_nvp("triggerType", type)
);
}
const std::string & getId() const;
const std::string & getName() const;
private:
std::string name;
@@ -219,84 +100,19 @@ public:
const std::string &_uri,
std::vector<PracticeSection> _practices,
std::vector<ParametersSection> _parameters,
std::vector<RulesTriggerSection> _triggers)
:
name(_name),
practices(_practices),
parameters(_parameters),
triggers(_triggers)
{
try {
id = _url+_uri;
bool any = _name == "Any" && _url == "Any" && _uri == "Any";
if (_uri != "/") {
context = any ? "All()" : "Any("
"All("
"Any("
"EqualHost(" + _url + ")"
"),"
"EqualListeningPort(80)" +
std::string(_uri.empty() ? "" : ",BeginWithUri(" + _uri + ")") +
"),"
"All("
"Any("
"EqualHost(" + _url + ")"
"),"
"EqualListeningPort(443)" +
std::string(_uri.empty() ? "" : ",BeginWithUri(" + _uri + ")") +
")"
")";
} else {
context = any ? "All()" : "Any("
"All("
"Any("
"EqualHost(" + _url + ")"
"),"
"EqualListeningPort(80)"
"),"
"All("
"Any("
"EqualHost(" + _url + ")"
"),"
"EqualListeningPort(443)"
")"
")";
}
} catch (const boost::uuids::entropy_error &e) {
dbgWarning(D_K8S_POLICY) << "Failed to generate rule UUID. Error: " << e.what();
}
}
std::vector<RulesTriggerSection> _triggers);
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
std::string empty_str = "";
out_ar(
cereal::make_nvp("assetId", id),
cereal::make_nvp("assetName", name),
cereal::make_nvp("ruleId", id),
cereal::make_nvp("ruleName", name),
cereal::make_nvp("context", context),
cereal::make_nvp("priority", 1),
cereal::make_nvp("isCleanup", false),
cereal::make_nvp("parameters", parameters),
cereal::make_nvp("practices", practices),
cereal::make_nvp("triggers", triggers),
cereal::make_nvp("zoneId", empty_str),
cereal::make_nvp("zoneName", empty_str)
);
}
const std::string & getRuleId() const { return id; }
const std::string & getAssetName() const { return name; }
const std::string & getRuleName() const { return name; }
const std::string & getAsstId() const { return id; }
const std::string & getPracticeId() const { return practices[0].getPracticeId(); }
const std::string & getPracticeName() const { return practices[0].getPracticeName(); }
const std::vector<PracticeSection> & getPractice() const { return practices; }
const std::vector<ParametersSection> & getParameters() const { return parameters; }
const std::vector<RulesTriggerSection> & getTriggers() const { return triggers; }
void save(cereal::JSONOutputArchive &out_ar) const;
const std::string & getRuleId() const;
const std::string & getAssetName() const;
const std::string & getRuleName() const;
const std::string & getAssetId() const;
const std::string & getPracticeId() const;
const std::string & getPracticeName() const;
const std::vector<PracticeSection> & getPractice() const;
const std::vector<ParametersSection> & getParameters() const;
const std::vector<RulesTriggerSection> & getTriggers() const;
private:
std::string context;
@@ -313,60 +129,13 @@ public:
class RulesConfig
{
public:
RulesConfig(const std::vector<RulesConfigRulebase> &_rules_config)
:
rules_config(_rules_config)
{
sort(rules_config.begin(), rules_config.end(), sortBySpecific);
}
RulesConfig(const std::vector<RulesConfigRulebase> &_rules_config);
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("rulesConfig", rules_config)
);
}
void save(cereal::JSONOutputArchive &out_ar) const;
private:
static bool
sortBySpecific(const RulesConfigRulebase &first, const RulesConfigRulebase &second)
{
return sortBySpecificAux(first.getAssetName(), second.getAssetName());
}
static bool
sortBySpecificAux(const std::string &first, const std::string &second)
{
if (first.empty()) return false;
if (second.empty()) return true;
AssetUrlParser first_parsed = AssetUrlParser(first);
AssetUrlParser second_parsed = AssetUrlParser(second);
// sort by URL
if (first_parsed.asset_url == "*" && second_parsed.asset_url != "*") return false;
if (second_parsed.asset_url == "*" && first_parsed.asset_url != "*") return true;
// sort by port
if (first_parsed.port == "*" && second_parsed.port != "*") return false;
if (second_parsed.port == "*" && first_parsed.port != "*") return true;
// sort by URI
if (first_parsed.asset_uri == "*" && second_parsed.asset_uri != "*") return false;
if (second_parsed.asset_uri == "*" && first_parsed.asset_uri != "*") return true;
if (first_parsed.asset_uri.empty()) return false;
if (second_parsed.asset_uri.empty()) return true;
if (second_parsed.asset_uri.find(first_parsed.asset_uri) != std::string::npos) return false;
if (first_parsed.asset_uri.find(second_parsed.asset_uri) != std::string::npos) return true;
if (first_parsed.asset_url.empty()) return false;
if (second_parsed.asset_url.empty()) return false;
return second < first;
}
static bool sortBySpecific(const RulesConfigRulebase &first, const RulesConfigRulebase &second);
static bool sortBySpecificAux(const std::string &first, const std::string &second);
std::vector<RulesConfigRulebase> rules_config;
};
@@ -376,13 +145,7 @@ public:
rules_config_rulebase(RulesConfig(_rules_config))
{}
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("rulebase", rules_config_rulebase)
);
}
void save(cereal::JSONOutputArchive &out_ar) const;
private:
RulesConfig rules_config_rulebase;

View File

@@ -28,31 +28,10 @@ USE_DEBUG_FLAG(D_K8S_POLICY);
class AgentSettingsSection
{
public:
AgentSettingsSection(
const std::string &_key,
const std::string &_value)
:
key(_key),
value(_value)
{
try {
id = to_string(boost::uuids::random_generator()());
} catch (const boost::uuids::entropy_error &e) {
dbgWarning(D_K8S_POLICY) << "Failed to generate agent setting UUID. Error: " << e.what();
}
}
AgentSettingsSection(const std::string &_key, const std::string &_value);
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("id", id),
cereal::make_nvp("key", key),
cereal::make_nvp("value", value)
);
}
const std::string & getSettingId() const { return id; }
void save(cereal::JSONOutputArchive &out_ar) const;
const std::string & getSettingId() const;
private:
std::string id;
@@ -65,20 +44,7 @@ class SettingsRulebase
public:
SettingsRulebase(std::vector<AgentSettingsSection> _agentSettings) : agentSettings(_agentSettings) {}
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
std::string profile_type = "Kubernetes";
std::string upgrade_mode = "automatic";
out_ar(
cereal::make_nvp("agentSettings", agentSettings),
cereal::make_nvp("agentType", profile_type),
cereal::make_nvp("allowOnlyDefinedApplications", false),
cereal::make_nvp("anyFog", true),
cereal::make_nvp("maxNumberOfAgents", 10),
cereal::make_nvp("upgradeMode", upgrade_mode)
);
}
void save(cereal::JSONOutputArchive &out_ar) const;
private:
std::vector<AgentSettingsSection> agentSettings;
@@ -87,27 +53,9 @@ private:
class SettingsWrapper
{
public:
SettingsWrapper(SettingsRulebase _agent) : agent(_agent)
{
try {
id = to_string(boost::uuids::random_generator()());
} catch (const boost::uuids::entropy_error &e) {
dbgWarning(D_K8S_POLICY) << "Failed to generate Settings Wrapper UUID. Error: " << e.what();
}
}
SettingsWrapper(SettingsRulebase _agent);
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("profileType", profileType),
cereal::make_nvp("tokenType", isToken),
cereal::make_nvp("tokenType", tokenType),
cereal::make_nvp("name", name),
cereal::make_nvp("id", id),
cereal::make_nvp("agent", agent)
);
}
void save(cereal::JSONOutputArchive &out_ar) const;
private:
std::string profileType = "agent";

View File

@@ -27,24 +27,9 @@ USE_DEBUG_FLAG(D_K8S_POLICY);
class AgentSettingsSection
{
public:
AgentSettingsSection(std::string _key, std::string _value) : key(_key), value(_value)
{
try {
id = to_string(boost::uuids::random_generator()());
} catch (const boost::uuids::entropy_error &e) {
dbgWarning(D_K8S_POLICY) << "Failed to generate agent setting UUID. Error: " << e.what();
}
}
AgentSettingsSection(std::string _key, std::string _value);
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("id", id),
cereal::make_nvp("key", key),
cereal::make_nvp("value", value)
);
}
void save(cereal::JSONOutputArchive &out_ar) const;
private:
std::string id;
@@ -57,20 +42,7 @@ class IpsSnortSigsRulebase
public:
IpsSnortSigsRulebase(std::vector<AgentSettingsSection> _agentSettings) : agentSettings(_agentSettings) {}
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
std::string profile_type = "KubernetesProfile";
std::string upgrade_mode = "automatic";
out_ar(
cereal::make_nvp("agentSettings", agentSettings),
cereal::make_nvp("agentType", profile_type),
cereal::make_nvp("allowOnlyDefinedApplications", false),
cereal::make_nvp("anyFog", true),
cereal::make_nvp("maxNumberOfAgents", 10),
cereal::make_nvp("upgradeMode", upgrade_mode)
);
}
void save(cereal::JSONOutputArchive &out_ar) const;
private:
std::vector<AgentSettingsSection> agentSettings;

View File

@@ -52,76 +52,14 @@ public:
const std::string &_cefIpAddress,
int _syslogPortNum,
const std::string &_syslogIpAddress,
bool _beautify_logs)
:
name(_name),
verbosity(_verbosity),
extendloggingMinSeverity(_extendloggingMinSeverity),
extendlogging(_extendlogging),
logToAgent(_logToAgent),
logToCef(_logToCef),
logToCloud(_logToCloud),
logToSyslog(_logToSyslog),
responseBody(_responseBody),
tpDetect(_tpDetect),
tpPrevent(_tpPrevent),
webBody(_webBody),
webHeaders(_webHeaders),
webRequests(_webRequests),
webUrlPath(_webUrlPath),
webUrlQuery(_webUrlQuery),
cefPortNum (_cefPortNum),
cefIpAddress (_cefIpAddress),
syslogPortNum (_syslogPortNum),
syslogIpAddress (_syslogIpAddress),
beautify_logs(_beautify_logs)
{
try {
id = to_string(boost::uuids::random_generator()());
context = "triggerId(" + id + ")";
} catch (const boost::uuids::entropy_error &e) {
dbgWarning(D_K8S_POLICY) << "Failed to generate log trigger UUID. Error: " << e.what();
}
}
bool _beautify_logs
);
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
std::string trigger_type = "log";
std::string urlForSyslog = syslogIpAddress + ":" + std::to_string(syslogPortNum);
std::string urlForCef = cefIpAddress + ":" + std::to_string(cefPortNum);
out_ar(
cereal::make_nvp("context", context),
cereal::make_nvp("triggerName", name),
cereal::make_nvp("triggerType", trigger_type),
cereal::make_nvp("verbosity", verbosity),
cereal::make_nvp("acAllow", false),
cereal::make_nvp("acDrop", false),
cereal::make_nvp("complianceViolations", false),
cereal::make_nvp("complianceWarnings", false),
cereal::make_nvp("extendloggingMinSeverity", extendloggingMinSeverity),
cereal::make_nvp("extendlogging", extendlogging),
cereal::make_nvp("logToAgent", logToAgent),
cereal::make_nvp("logToCef", logToCef),
cereal::make_nvp("logToCloud", logToCloud),
cereal::make_nvp("logToSyslog", logToSyslog),
cereal::make_nvp("responseBody", responseBody),
cereal::make_nvp("responseCode", false),
cereal::make_nvp("tpDetect", tpDetect),
cereal::make_nvp("tpPrevent", tpPrevent),
cereal::make_nvp("webBody", webBody),
cereal::make_nvp("webHeaders", webHeaders),
cereal::make_nvp("webRequests", webRequests),
cereal::make_nvp("webUrlPath", webUrlPath),
cereal::make_nvp("webUrlQuery", webUrlQuery),
cereal::make_nvp("urlForSyslog", urlForSyslog),
cereal::make_nvp("urlForCef", urlForCef),
cereal::make_nvp("formatLoggingOutput", beautify_logs)
);
}
void save(cereal::JSONOutputArchive &out_ar) const;
const std::string & getTriggerId() const { return id; }
const std::string & getTriggerName() const { return name; }
const std::string & getTriggerId() const;
const std::string & getTriggerName() const;
bool operator<(const LogTriggerSection &other) const;
private:
std::string id;
@@ -152,43 +90,22 @@ private:
class WebUserResponseTriggerSection
{
public:
WebUserResponseTriggerSection() {}
WebUserResponseTriggerSection(
const std::string &_name,
const std::string &_details_level,
const std::string &_response_body,
int _response_code,
const std::string &_response_title)
:
name(_name),
context(),
details_level(_details_level),
response_body(_response_body),
response_title(_response_title),
response_code(_response_code)
{
try {
id = to_string(boost::uuids::random_generator()());
context = "triggerId(" + id + ")";
} catch (const boost::uuids::entropy_error &e) {
dbgWarning(D_K8S_POLICY) << "Failed to generate webUserResponse trigger UUID. Error: " << e.what();
}
}
const std::string &_response_title
);
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("context", context),
cereal::make_nvp("triggerName", name),
cereal::make_nvp("details level", details_level),
cereal::make_nvp("response body", response_body),
cereal::make_nvp("response code", response_code),
cereal::make_nvp("response title", response_title)
);
}
void save(cereal::JSONOutputArchive &out_ar) const;
const std::string & getTriggerId() const { return id; }
const std::string & getTriggerName() const { return name; }
const std::string & getTriggerId() const;
const std::string & getTriggerName() const;
bool operator<(const WebUserResponseTriggerSection &other) const;
private:
std::string id;
@@ -203,34 +120,13 @@ private:
class AppSecCustomResponseSpec
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec web user response spec";
parseAppsecJSONKey<int>("http-response-code", httpResponseCode, archive_in, 403);
parseAppsecJSONKey<std::string>("mode", mode, archive_in, "block-page");
parseAppsecJSONKey<std::string>("name", name, archive_in);
if (mode == "block-page") {
parseAppsecJSONKey<std::string>(
"message-body",
messageBody,
archive_in,
"Openappsec's <b>Application Security</b> has detected an attack and blocked it."
);
parseAppsecJSONKey<std::string>(
"message-title",
messageTitle,
archive_in,
"Attack blocked by web application protection"
);
}
}
void load(cereal::JSONInputArchive &archive_in);
int getHttpResponseCode() const { return httpResponseCode; }
const std::string & getMessageBody() const { return messageBody; }
const std::string & getMessageTitle() const { return messageTitle; }
const std::string & getMode() const { return mode; }
const std::string & getName() const { return name; }
int getHttpResponseCode() const;
const std::string & getMessageBody() const;
const std::string & getMessageTitle() const;
const std::string & getMode() const;
const std::string & getName() const;
private:
int httpResponseCode;
@@ -240,21 +136,6 @@ private:
std::string name;
};
std::ostream &
operator<<(std::ostream &os, const AppSecCustomResponseSpec &obj)
{
os
<< "mode: "
<< obj.getMode()
<< "," << std::endl << "message-title: "
<< obj.getMessageTitle()
<< "," << std::endl << "message-body: "
<< obj.getMessageBody()
<< "," << std::endl << "http-response-code: "
<< obj.getHttpResponseCode();
return os;
}
class TriggersRulebase
{
public:
@@ -266,14 +147,7 @@ public:
webUserResponseTriggers(_webUserResponseTriggers) {}
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("log", logTriggers),
cereal::make_nvp("webUserResponse", webUserResponseTriggers)
);
}
void save(cereal::JSONOutputArchive &out_ar) const;
private:
std::vector<LogTriggerSection> logTriggers;
@@ -283,49 +157,24 @@ private:
class AppsecTriggerAccessControlLogging
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec Trigger - Access Control Logging";
parseAppsecJSONKey<bool>("allow-events", allow_events, archive_in, false);
parseAppsecJSONKey<bool>("drop-events", drop_events, archive_in, false);
}
void load(cereal::JSONInputArchive &archive_in);
bool isAllowEvents() const { return allow_events; }
bool isDropEvents() const { return drop_events; }
bool isAllowEvents() const;
bool isDropEvents() const;
private:
bool allow_events = false;
bool drop_events = false;
};
std::ostream &
operator<<(std::ostream &os, const AppsecTriggerAccessControlLogging &obj)
{
os
<< "AppSec Trigger - Access Control Logging: "
<< "isAllowEvents: "
<< obj.isAllowEvents()
<< " , isDropEvents: "
<< obj.isDropEvents();
return os;
}
class AppsecTriggerAdditionalSuspiciousEventsLogging : public ClientRest
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec Trigger - Additional Suspicious Events Logging";
parseAppsecJSONKey<bool>("enabled", enabled, archive_in, true);
parseAppsecJSONKey<bool>("response-body", response_body, archive_in, false);
parseAppsecJSONKey<std::string>("minimum-severity", minimum_severity, archive_in, "high");
}
void load(cereal::JSONInputArchive &archive_in);
bool isEnabled() const { return enabled; }
bool isResponseBody() const { return response_body; }
const std::string & getMinimumSeverity() const { return minimum_severity; }
bool isEnabled() const;
bool isResponseBody() const;
const std::string & getMinimumSeverity() const;
private:
bool enabled = true;
@@ -333,37 +182,15 @@ private:
std::string minimum_severity = "high";
};
std::ostream &
operator<<(std::ostream &os, const AppsecTriggerAdditionalSuspiciousEventsLogging &obj)
{
os
<< "AppsecTriggerAdditionalSuspiciousEventsLogging: "
<< "Enabled: "
<< obj.isEnabled()
<< " response_body: "
<< obj.isResponseBody()
<< " minimum_severity: "
<< obj.getMinimumSeverity();
return os;
}
class AppsecTriggerLogging : public ClientRest
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec Trigger Logging";
parseAppsecJSONKey<bool>("all-web-requests", all_web_requests, archive_in, false);
parseAppsecJSONKey<bool>("detect-events", detect_events, archive_in, false);
parseAppsecJSONKey<bool>("prevent-events", prevent_events, archive_in, true);
}
load(cereal::JSONInputArchive &archive_in);
bool isAllWebRequests() const { return all_web_requests; }
bool isDetectEvents() const { return detect_events; }
bool isPreventEvents() const { return prevent_events; }
bool isAllWebRequests() const;
bool isDetectEvents() const;
bool isPreventEvents() const;
private:
bool all_web_requests = false;
@@ -371,37 +198,15 @@ private:
bool prevent_events = true;
};
std::ostream &
operator<<(std::ostream &os, const AppsecTriggerLogging &obj)
{
os
<< "AppsecTriggerLogging: "
<< "all_web_requests: "
<< obj.isAllWebRequests()
<< ", detect_events: "
<< obj.isDetectEvents()
<< ", prevent_events: "
<< obj.isPreventEvents();
return os;
}
class AppsecTriggerExtendedLogging : public ClientRest
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec Trigger Extended Logging";
parseAppsecJSONKey<bool>("http-headers", http_headers, archive_in, false);
parseAppsecJSONKey<bool>("request-body", request_body, archive_in, false);
parseAppsecJSONKey<bool>("url-path", url_path, archive_in, false);
parseAppsecJSONKey<bool>("url-query", url_query, archive_in, false);
}
void load(cereal::JSONInputArchive &archive_in);
bool isHttpHeaders() const { return http_headers; }
bool isRequestBody() const { return request_body; }
bool isUrlPath() const { return url_path; }
bool isUrlQuery() const { return url_query; }
bool isHttpHeaders() const;
bool isRequestBody() const;
bool isUrlPath() const;
bool isUrlQuery() const;
private:
bool http_headers = false;
@@ -410,36 +215,14 @@ private:
bool url_query = false;
};
std::ostream &
operator<<(std::ostream &os, const AppsecTriggerExtendedLogging &obj)
{
os
<< "AppsecTriggerExtendedLogging: "
<< "http_headers: "
<< obj.isHttpHeaders()
<< ", request_body: "
<< obj.isRequestBody()
<< ", url_path: "
<< obj.isUrlPath()
<< ", url_query: "
<< obj.isUrlQuery();
return os;
}
class LoggingService
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
parseAppsecJSONKey<std::string>("address", address, archive_in);
parseAppsecJSONKey<std::string>("proto", proto, archive_in);
parseAppsecJSONKey<int>("port", port, archive_in, 514);
}
void load(cereal::JSONInputArchive &archive_in);
const std::string & getAddress() const { return address; }
const std::string & getProto() const { return proto; }
int getPort() const { return port; }
const std::string & getAddress() const;
const std::string & getProto() const;
int getPort() const;
private:
std::string address;
@@ -452,13 +235,8 @@ class StdoutLogging
public:
StdoutLogging() : format("json") {}
void
load(cereal::JSONInputArchive &archive_in)
{
parseAppsecJSONKey<std::string>("format", format, archive_in, "json");
}
const std::string & getFormat() const { return format; }
void load(cereal::JSONInputArchive &archive_in);
const std::string & getFormat() const;
private:
std::string format;
@@ -467,35 +245,22 @@ private:
class AppsecTriggerLogDestination : public ClientRest
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec Trigger LogDestination";
// TBD: support "file"
parseAppsecJSONKey<bool>("cloud", cloud, archive_in, false);
void load(cereal::JSONInputArchive &archive_in);
StdoutLogging stdout_log;
parseAppsecJSONKey<StdoutLogging>("stdout", stdout_log, archive_in);
agent_local = !(stdout_log.getFormat().empty());
beautify_logs = stdout_log.getFormat() == "json-formatted";
parseAppsecJSONKey<LoggingService>("syslog-service", syslog_service, archive_in);
parseAppsecJSONKey<LoggingService>("cef-service", cef_service, archive_in);
}
int getCefServerUdpPort() const;
int getSyslogServerUdpPort() const;
bool isAgentLocal() const;
bool shouldBeautifyLogs() const;
int getCefServerUdpPort() const { return getCefServiceData().getPort(); }
int getSyslogServerUdpPort() const { return getSyslogServiceData().getPort(); }
bool isAgentLocal() const { return agent_local; }
bool shouldBeautifyLogs() const { return beautify_logs; }
bool getCloud() const { return cloud; }
bool isCefNeeded() const { return !getCefServiceData().getAddress().empty(); }
bool isSyslogNeeded() const { return !getSyslogServiceData().getAddress().empty(); }
const std::string & getSyslogServerIpv4Address() const { return getSyslogServiceData().getAddress(); }
const std::string & getCefServerIpv4Address() const { return getCefServiceData().getAddress(); }
bool getCloud() const;
bool isCefNeeded() const;
bool isSyslogNeeded() const;
const std::string & getSyslogServerIpv4Address() const;
const std::string & getCefServerIpv4Address() const;
private:
const LoggingService & getSyslogServiceData() const { return syslog_service; }
const LoggingService & getCefServiceData() const { return cef_service; }
const LoggingService & getSyslogServiceData() const;
const LoggingService & getCefServiceData() const;
bool cloud = false;
bool agent_local = true;
@@ -504,90 +269,17 @@ private:
LoggingService cef_service;
};
std::ostream &
operator<<(std::ostream &os, const AppsecTriggerLogDestination &obj)
{
os
<< "AppSec Trigger Log Destination:" << std::endl
<< "agent_local: "
<< obj.isAgentLocal()
<< ", beautify_logs: "
<< obj.shouldBeautifyLogs()
<< ", cef_server_udp_port: "
<< obj.getCefServerUdpPort()
<< ", syslog_server_udp_port: "
<< obj.getSyslogServerUdpPort()
<< ", cef_service: "
<< obj.isCefNeeded()
<< ", cloud: "
<< obj.getCloud()
<< ", syslog: "
<< obj.isSyslogNeeded()
<< ", syslog_server_ipv4_address: "
<< obj.getSyslogServerIpv4Address()
<< ", cef_server_ipv4_address: "
<< obj.getCefServerIpv4Address();
return os;
}
class AppsecTriggerSpec
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec trigger spec";
parseAppsecJSONKey<AppsecTriggerAccessControlLogging>(
"access-control-logging",
access_control_logging,
archive_in
);
parseAppsecJSONKey<AppsecTriggerAdditionalSuspiciousEventsLogging>(
"additional-suspicious-events-logging",
additional_suspicious_events_logging,
archive_in
);
parseAppsecJSONKey<AppsecTriggerLogging>("appsec-logging", appsec_logging, archive_in);
parseAppsecJSONKey<AppsecTriggerExtendedLogging>("extended-logging", extended_logging, archive_in);
parseAppsecJSONKey<AppsecTriggerLogDestination>("log-destination", log_destination, archive_in);
parseAppsecJSONKey<std::string>("name", name, archive_in);
}
void load(cereal::JSONInputArchive &archive_in);
const AppsecTriggerAccessControlLogging &
getAppsecTriggerAccessControlLogging() const
{
return access_control_logging;
}
const std::string &
getName() const
{
return name;
}
const AppsecTriggerAdditionalSuspiciousEventsLogging &
getAppsecTriggerAdditionalSuspiciousEventsLogging() const
{
return additional_suspicious_events_logging;
}
const AppsecTriggerLogging &
getAppsecTriggerLogging() const
{
return appsec_logging;
}
const AppsecTriggerExtendedLogging &
getAppsecTriggerExtendedLogging() const
{
return extended_logging;
}
const AppsecTriggerLogDestination &
getAppsecTriggerLogDestination() const
{
return log_destination;
}
const AppsecTriggerAccessControlLogging & getAppsecTriggerAccessControlLogging() const;
const std::string & getName() const;
const AppsecTriggerAdditionalSuspiciousEventsLogging & getAppsecTriggerAdditionalSuspiciousEventsLogging() const;
const AppsecTriggerLogging & getAppsecTriggerLogging() const;
const AppsecTriggerExtendedLogging & getAppsecTriggerExtendedLogging() const;
const AppsecTriggerLogDestination & getAppsecTriggerLogDestination() const;
private:
AppsecTriggerAccessControlLogging access_control_logging;
@@ -598,36 +290,13 @@ private:
std::string name;
};
std::ostream &
operator<<(std::ostream &os, const AppsecTriggerSpec &obj)
{
os
<< "AppSec Access Control Logging:" << std::endl
<< obj.getAppsecTriggerAccessControlLogging()
<< std::endl << "AppSec Additional Suspocious Events Logging:" << std::endl
<< obj.getAppsecTriggerAdditionalSuspiciousEventsLogging()
<< std::endl << "AppSec Trigger Logging:" << std::endl
<< obj.getAppsecTriggerLogging()
<< std::endl << "Appsec Trigger Extended Logging:" << std::endl
<< obj.getAppsecTriggerExtendedLogging()
<< std::endl << "AppSec Trigger Log Destination:" << std::endl
<< obj.getAppsecTriggerLogDestination();
return os;
}
class TriggersWrapper
{
public:
TriggersWrapper(const TriggersRulebase &_triggers) : triggers_rulebase(_triggers)
{}
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("rulebase", triggers_rulebase)
);
}
void save(cereal::JSONOutputArchive &out_ar) const;
private:
TriggersRulebase triggers_rulebase;

View File

@@ -29,51 +29,18 @@ USE_DEBUG_FLAG(D_K8S_POLICY);
class TrustedSourcesSpec
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading trusted sources spec";
parseAppsecJSONKey<int>("minNumOfSources", min_num_of_sources, archive_in, 3);
parseAppsecJSONKey<std::vector<std::string>>("sourcesIdentifiers", sources_identifiers, archive_in);
parseAppsecJSONKey<std::string>("name", name, archive_in);
}
void load(cereal::JSONInputArchive &archive_in);
int
getMinNumOfSources() const
{
return min_num_of_sources;
}
const std::vector<std::string> &
getSourcesIdentifiers() const
{
return sources_identifiers;
}
const std::string &
getName() const
{
return name;
}
int getMinNumOfSources() const;
const std::vector<std::string> & getSourcesIdentifiers() const;
const std::string & getName() const;
private:
int min_num_of_sources;
int min_num_of_sources = 0;
std::string name;
std::vector<std::string> sources_identifiers;
};
std::ostream &
operator<<(std::ostream &os, const TrustedSourcesSpec &obj)
{
os
<< "Min number of sources: "
<< obj.getMinNumOfSources()
<< ", SourceIdentifiers: ["
<< makeSeparatedStr(obj.getSourcesIdentifiers(), ",")
<< "]";
return os;
}
class SourcesIdentifiers
{
public:
@@ -83,20 +50,8 @@ public:
value(_value)
{}
void
save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("sourceIdentifier", source_identifier),
cereal::make_nvp("value", value)
);
}
const std::string &
getSourceIdent() const
{
return source_identifier;
}
void save(cereal::JSONOutputArchive &out_ar) const;
const std::string & getSourceIdent() const;
private:
std::string source_identifier;
@@ -106,25 +61,10 @@ private:
class SourceIdentifierSpec
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading trusted sources spec";
parseAppsecJSONKey<std::string>("sourceIdentifier", source_identifier, archive_in);
parseAppsecJSONKey<std::vector<std::string>>("value", value, archive_in);
}
void load(cereal::JSONInputArchive &archive_in);
const std::string &
getSourceIdentifier() const
{
return source_identifier;
}
const std::vector<std::string> &
getValues() const
{
return value;
}
const std::string & getSourceIdentifier() const;
const std::vector<std::string> & getValues() const;
private:
std::string source_identifier;
@@ -134,43 +74,16 @@ private:
class SourceIdentifierSpecWrapper
{
public:
void
load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading Source Identifier Spec Wrapper";
parseAppsecJSONKey<std::vector<SourceIdentifierSpec>>("identifiers", identifiers, archive_in);
parseAppsecJSONKey<std::string>("name", name, archive_in);
}
void load(cereal::JSONInputArchive &archive_in);
const std::string &
getName() const
{
return name;
}
const std::vector<SourceIdentifierSpec> &
getIdentifiers() const
{
return identifiers;
}
const std::string & getName() const;
const std::vector<SourceIdentifierSpec> & getIdentifiers() const;
private:
std::string name;
std::vector<SourceIdentifierSpec> identifiers;
};
std::ostream &
operator<<(std::ostream &os, const SourceIdentifierSpec &obj)
{
os
<< "sourceIdentifier: "
<< obj.getSourceIdentifier()
<< ", values: ["
<< makeSeparatedStr(obj.getValues(), ",")
<< "]";
return os;
}
class AppSecTrustedSources
{
public:
@@ -180,42 +93,16 @@ public:
AppSecTrustedSources(
const std::string &_name,
int _num_of_sources,
const std::vector<SourcesIdentifiers> &_sources_identifiers)
:
name(_name),
num_of_sources(_num_of_sources),
sources_identifiers(_sources_identifiers)
{
try {
id = to_string(boost::uuids::random_generator()());
} catch (const boost::uuids::entropy_error &e) {
dbgWarning(D_K8S_POLICY) << "Failed to generate Trusted Sources ID. Error: " << e.what();
}
}
const std::vector<SourcesIdentifiers> &_sources_identifiers
);
void
save(cereal::JSONOutputArchive &out_ar) const
{
std::string parameter_type = "TrustedSource";
out_ar(
cereal::make_nvp("id", id),
cereal::make_nvp("name", name),
cereal::make_nvp("numOfSources", num_of_sources),
cereal::make_nvp("sourcesIdentifiers", sources_identifiers),
cereal::make_nvp("parameterType", parameter_type)
);
}
const std::vector<SourcesIdentifiers> &
getSourcesIdentifiers() const
{
return sources_identifiers;
}
void save(cereal::JSONOutputArchive &out_ar) const;
const std::vector<SourcesIdentifiers> & getSourcesIdentifiers() const;
private:
std::string id;
std::string name;
int num_of_sources;
int num_of_sources = 0;
std::vector<SourcesIdentifiers> sources_identifiers;
};
// LCOV_EXCL_STOP

View File

@@ -0,0 +1,178 @@
#include "ingress_data.h"
using namespace std;
USE_DEBUG_FLAG(D_K8S_POLICY);
// LCOV_EXCL_START Reason: no test exist
void
IngressMetadata::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "IngressMetadata load";
parseAppsecJSONKey<string>("name", name, archive_in);
parseAppsecJSONKey<string>("resourceVersion", resourceVersion, archive_in);
parseAppsecJSONKey<string>("namespace", namespace_name, archive_in);
parseAppsecJSONKey<map<string, string>>("annotations", annotations, archive_in);
}
const string &
IngressMetadata::getName() const
{
return name;
}
const string &
IngressMetadata::getResourceVersion() const
{
return resourceVersion;
}
const string &
IngressMetadata::getNamespace() const
{
return namespace_name;
}
const map<string, string> &
IngressMetadata::getAnnotations() const
{
return annotations;
}
void
IngressRulePath::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading ingress defined rule path";
parseAppsecJSONKey<string>("path", path, archive_in);
}
const string &
IngressRulePath::getPath() const
{
return path;
}
void
IngressRulePathsWrapper::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading ingress defined rule path wrapper";
parseAppsecJSONKey<vector<IngressRulePath>>("paths", paths, archive_in);
}
const vector<IngressRulePath> &
IngressRulePathsWrapper::getRulePaths() const
{
return paths;
}
void
IngressDefinedRule::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading ingress defined rule";
parseAppsecJSONKey<string>("host", host, archive_in);
parseAppsecJSONKey<IngressRulePathsWrapper>("http", paths_wrapper, archive_in);
}
const string &
IngressDefinedRule::getHost() const
{
return host;
}
const IngressRulePathsWrapper &
IngressDefinedRule::getPathsWrapper() const
{
return paths_wrapper;
}
void
DefaultBackend::load(cereal::JSONInputArchive &)
{
dbgTrace(D_K8S_POLICY) << "Loading Default Backend";
is_exists = true;
}
bool
DefaultBackend::isExists() const
{
return is_exists;
}
void
IngressSpec::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading single ingress spec";
parseAppsecJSONKey<string>("ingressClassName", ingress_class_name, archive_in);
parseAppsecJSONKey<vector<IngressDefinedRule>>("rules", rules, archive_in);
parseAppsecJSONKey<DefaultBackend>("defaultBackend", default_backend, archive_in);
}
const string &
IngressSpec::getIngressClassName() const
{
return ingress_class_name;
}
const vector<IngressDefinedRule> &
IngressSpec::getRules() const
{
return rules;
}
bool
IngressSpec::isDefaultBackendExists() const
{
return default_backend.isExists();
}
void
SingleIngressData::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading single ingress data";
parseAppsecJSONKey<IngressMetadata>("metadata", metadata, archive_in);
parseAppsecJSONKey<IngressSpec>("spec", spec, archive_in);
}
const IngressMetadata &
SingleIngressData::getMetadata() const
{
return metadata;
}
const IngressSpec &
SingleIngressData::getSpec() const
{
return spec;
}
bool
IngressData::loadJson(const string &json)
{
string modified_json = json;
modified_json.pop_back();
stringstream in;
in.str(modified_json);
dbgTrace(D_K8S_POLICY) << "Loading ingress data";
try {
cereal::JSONInputArchive in_ar(in);
in_ar(
cereal::make_nvp("apiVersion", apiVersion),
cereal::make_nvp("items", items)
);
} catch (cereal::Exception &e) {
dbgError(D_K8S_POLICY) << "Failed to load ingress data JSON. Error: " << e.what();
return false;
}
return true;
}
const string &
IngressData::getapiVersion() const
{
return apiVersion;
}
const vector<SingleIngressData> &
IngressData::getItems() const
{
return items;
}
// LCOV_EXCL_STOP

View File

@@ -44,6 +44,7 @@
#include "include/exceptions_section.h"
#include "include/rules_config_section.h"
#include "include/trusted_sources_section.h"
#include "include/policy_maker_utils.h"
using namespace std;
@@ -56,62 +57,6 @@ 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:
SecurityAppsWrapper(
const AppSecWrapper &_waap,
const TriggersWrapper &_trrigers,
const RulesConfigWrapper &_rules,
const ExceptionsWrapper &_exceptions,
const string &_policy_version)
:
waap(_waap),
trrigers(_trrigers),
rules(_rules),
exceptions(_exceptions),
policy_version(_policy_version) {}
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("waap", waap),
cereal::make_nvp("triggers", trrigers),
cereal::make_nvp("rules", rules),
cereal::make_nvp("exceptions", exceptions),
cereal::make_nvp("version", policy_version)
);
}
private:
AppSecWrapper waap;
TriggersWrapper trrigers;
RulesConfigWrapper rules;
ExceptionsWrapper exceptions;
string policy_version;
};
class K8sPolicyWrapper
{
public:
K8sPolicyWrapper(
const SettingsWrapper &_settings,
const SecurityAppsWrapper &_security_apps)
:
settings(_settings),
security_apps(_security_apps) {}
void
serialize(cereal::JSONOutputArchive &out_ar) const
{
security_apps.serialize(out_ar);
}
private:
SettingsWrapper settings;
SecurityAppsWrapper security_apps;
};
class NamespaceMetadata
{
@@ -120,16 +65,16 @@ public:
load(cereal::JSONInputArchive &archive_in)
{
dbgInfo(D_K8S_POLICY) << "NamespaceMetadata load";
parseAppsecJSONKey<std::string>("name", name, archive_in);
parseAppsecJSONKey<std::string>("uid", uid, archive_in);
parseAppsecJSONKey<string>("name", name, archive_in);
parseAppsecJSONKey<string>("uid", uid, archive_in);
}
const std::string & getName() const { return name; }
const std::string & getUID() const { return uid; }
const string & getName() const { return name; }
const string & getUID() const { return uid; }
private:
std::string name;
std::string uid;
string name;
string uid;
};
class SingleNamespaceData
@@ -151,12 +96,12 @@ class NamespaceData : public ClientRest
{
public:
bool
loadJson(const std::string &json)
loadJson(const string &json)
{
dbgTrace(D_K8S_POLICY) << "Loading namespace data";
std::string modified_json = json;
string modified_json = json;
modified_json.pop_back();
std::stringstream in;
stringstream in;
in.str(modified_json);
try {
cereal::JSONInputArchive in_ar(in);
@@ -170,10 +115,10 @@ public:
return true;
}
const std::vector<SingleNamespaceData> & getItems() const { return items; }
const vector<SingleNamespaceData> & getItems() const { return items; }
private:
std::vector<SingleNamespaceData> items;
vector<SingleNamespaceData> items;
};
class LocalPolicyMgmtGenerator::Impl
@@ -289,7 +234,7 @@ public:
return appsec_policy;
});
vector<ParsedRule> specific_rules = appsec_policy.getAppsecPolicySpec().getSpecificRules();
list<ParsedRule> specific_rules = appsec_policy.getAppsecPolicySpec().getSpecificRules();
ParsedRule default_rule = appsec_policy.getAppsecPolicySpec().getDefaultRule();
string asset;
@@ -461,7 +406,7 @@ public:
);
string port = "80";
string full_url = asset_name == "Any" ? "" : url + uri + ":" + port;
string asset_id = rules_config.getAsstId();
string asset_id = rules_config.getAssetId();
string practice_id = rules_config.getPracticeId();
if (!generated_apps.count(full_url)) {
@@ -483,7 +428,7 @@ public:
parsed_rules.push_back(rules_config);
generated_apps.insert(full_url);
}
}
} //end specific rules
string exception_name;
if (!default_rule.getExceptions().empty()) {
@@ -563,9 +508,9 @@ public:
);
SettingsWrapper profiles_section = createProfilesSection();
K8sPolicyWrapper k8s_policy = K8sPolicyWrapper(profiles_section, security_app_section);
PolicyWrapper policy_wrapper = PolicyWrapper(profiles_section, security_app_section);
return dumpPolicyToFile(k8s_policy);
return dumpPolicyToFile(policy_wrapper);
}
LocalPolicyEnv getEnvType() const { return env_type;}
@@ -608,14 +553,6 @@ public:
dbgTrace(D_K8S_POLICY) << "Ingress items ammount: " << ingress.getItems().size();
// TBD: break to methods : INXT-31445
for (const SingleIngressData &item : ingress.getItems()) {
dbgTrace(D_K8S_POLICY)
<< "Metadata name is: "
<< item.getMetadata().getName()
<< ", Namespace is: "
<< item.getMetadata().getNamespace()
<< ", Spec: "
<< item.getSpec();
set<pair<string, string>> specific_assets_from_ingress;
for (const IngressDefinedRule &rule : item.getSpec().getRules()) {
string url = rule.getHost();
@@ -670,9 +607,8 @@ public:
}
AppsecSpecParser<AppsecPolicySpec> appsec_policy = maybe_appsec_policy.unpack();
dbgTrace(D_K8S_POLICY) << "Succeessfully retrieved AppSec policy: " << appsec_policy.getSpec();
vector<ParsedRule> specific_rules = appsec_policy.getSpec().getSpecificRules();
list<ParsedRule> specific_rules = appsec_policy.getSpec().getSpecificRules();
ParsedRule default_rule = appsec_policy.getSpec().getDefaultRule();
for (const ParsedRule &parsed_rule : specific_rules) {
@@ -799,10 +735,6 @@ public:
AppsecSpecParser<AppSecPracticeSpec> appsec_practice = maybe_appsec_practice.unpack();
practice_map.emplace(practice_annotation_name, appsec_practice.getSpec());
dbgTrace(D_K8S_POLICY)
<< "Successfully retrieved AppSec practice"
<< practice_annotation_name
<< appsec_practice.getSpec();
}
string log_trigger_id;
@@ -830,7 +762,7 @@ public:
);
string port = "80";
string full_url = asset_name == "Any" ? "" : url + "/" + uri + ":" + port;
string asset_id = rules_config.getAsstId();
string asset_id = rules_config.getAssetId();
string practice_id = rules_config.getPracticeId();
if (!generated_apps.count(full_url)) {
@@ -917,10 +849,6 @@ public:
AppsecSpecParser<AppSecPracticeSpec> appsec_practice = maybe_appsec_practice.unpack();
practice_map.emplace(practice_name, appsec_practice.getSpec());
dbgTrace(D_K8S_POLICY)
<< "Successfully retrieved AppSec practice"
<< practice_name
<< appsec_practice.getSpec();
}
if (item.getSpec().isDefaultBackendExists()) {
@@ -978,7 +906,7 @@ public:
parsed_rules.push_back(default_rule_config);
}
string asset_id = default_rule_config.getAsstId();
string asset_id = default_rule_config.getAssetId();
string practice_id = default_rule_config.getPracticeId();
if (!generated_apps.count(asset.first + asset.second)) {
@@ -1035,7 +963,7 @@ public:
);
SettingsWrapper profiles_section = createProfilesSection();
K8sPolicyWrapper k8s_policy = K8sPolicyWrapper(profiles_section, security_app_section);
PolicyWrapper k8s_policy = PolicyWrapper(profiles_section, security_app_section);
return dumpPolicyToFile(k8s_policy);
}
@@ -1238,7 +1166,7 @@ private:
env_value.begin(),
env_value.end(),
env_value.begin(),
[](unsigned char c) { return std::tolower(c); }
[](unsigned char c) { return tolower(c); }
);
return env_value == "true";
}
@@ -1283,12 +1211,12 @@ private:
}
const string
dumpPolicyToFile(const K8sPolicyWrapper &k8s_policy) const
dumpPolicyToFile(const PolicyWrapper &policy) const
{
stringstream ss;
{
cereal::JSONOutputArchive ar(ss);
k8s_policy.serialize(ar);
policy.save(ar);
}
string policy_str = ss.str();
ofstream policy_file(local_appsec_policy_path);
@@ -1300,12 +1228,18 @@ private:
string
readFileContent(const string&file_path)
{
ifstream file(file_path);
stringstream buffer;
buffer << file.rdbuf();
return buffer.str();
try {
ifstream file(file_path);
stringstream buffer;
buffer << file.rdbuf();
return buffer.str();
} catch (ifstream::failure &f) {
dbgWarning(D_ORCHESTRATOR)
<< "Cannot read the file"
<< " File: " << file_path
<< " Error: " << f.what();
return "";
}
}
string
@@ -1436,12 +1370,6 @@ private:
return false;
}
dbgTrace(D_K8S_POLICY)
<< "Successfuly retrieved AppSec exceptions for "
<< trigger_annotation_name
<< ":\n"
<< *maybe_appsec_trigger_spec;
LogTriggerSection log_triggers_section =
createLogTriggersSection(trigger_annotation_name, false, "", *maybe_appsec_trigger_spec);
log_triggers_map.emplace(trigger_annotation_name, log_triggers_section);
@@ -1688,12 +1616,6 @@ private:
)
);
}
dbgTrace(D_K8S_POLICY)
<< "Successfuly retrieved AppSec web user response for: "
<< web_user_res_annotation_name
<< ":\n"
<< appsec_web_user_res_spec;
}
return true;
}

View File

@@ -0,0 +1,579 @@
#include "policy_maker_utils.h"
using namespace std;
USE_DEBUG_FLAG(D_NGINX_POLICY);
// LCOV_EXCL_START Reason: no test exist
void
SecurityAppsWrapper::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("waap", waap),
cereal::make_nvp("triggers", trrigers),
cereal::make_nvp("rules", rules),
cereal::make_nvp("exceptions", exceptions),
cereal::make_nvp("version", policy_version)
);
}
void
PolicyWrapper::save(cereal::JSONOutputArchive &out_ar) const
{
security_apps.save(out_ar);
}
void
PolicyMakerUtils::clearElementsMaps()
{
log_triggers.clear();
web_user_res_triggers.clear();
inner_exceptions.clear();
web_apps.clear();
rules_config.clear();
}
bool
PolicyMakerUtils::startsWith(const string &str, const string &prefix)
{
return str.rfind(prefix, 0) == 0;
}
bool
PolicyMakerUtils::endsWith(const string &str, const string &suffix)
{
return str.size() >= suffix.size() &&
str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
}
tuple<string, string, string>
PolicyMakerUtils::splitHostName(const string &host_name)
{
string url = host_name;
string uri;
string port;
if (startsWith(url, "http://")) {
url = url.substr(7, url.length() - 1);
port = "80";
} else if (startsWith(url, "https://")) {
url = url.substr(8, url.length() - 1);
port = "443";
}
if (url.find("/") != string::npos) {
uri = url.substr(url.find("/"));
url = url.substr(0, url.find("/"));
} else {
uri = "";
}
if (url.find(":") != string::npos) {
port = url.substr(url.find(":") + 1, url.length() - 1);
url = url.substr(0, url.find(":"));
}
if (host_name == "*") {
url = "Any";
uri = "Any";
}
return make_tuple(url, port, uri);
}
string
PolicyMakerUtils::dumpPolicyToFile(const PolicyWrapper &policy, const string &policy_path) const
{
stringstream ss;
{
cereal::JSONOutputArchive ar(ss);
policy.save(ar);
}
string policy_str = ss.str();
dbgTrace(D_NGINX_POLICY) << "policy: " << policy_str;
try {
ofstream policy_file(policy_path);
policy_file << policy_str;
policy_file.close();
} catch (const ofstream::failure &e) {
dbgDebug(D_NGINX_POLICY) << "Error while writing new policy to " << policy_path << ", Error: " << e.what();
return "";
}
return policy_str;
}
map<AnnotationTypes, string>
extractAnnotationsNames(
const ParsedRule &parsed_rule,
const ParsedRule &default_rule,
const string &policy_name)
{
map<AnnotationTypes, string> rule_annotation;
string practice_annotation_name;
// TBD: support multiple practices
if (!parsed_rule.getPractices().empty() && !parsed_rule.getPractices()[0].empty()) {
practice_annotation_name = parsed_rule.getPractices()[0];
} else if (!default_rule.getPractices().empty() && !default_rule.getPractices()[0].empty()) {
practice_annotation_name = default_rule.getPractices()[0];
}
if (!practice_annotation_name.empty()) {
rule_annotation[AnnotationTypes::PRACTICE] = policy_name + "/" + practice_annotation_name;
}
string trigger_annotation_name;
// TBD: support multiple triggers
if (!parsed_rule.getLogTriggers().empty() && !parsed_rule.getLogTriggers()[0].empty()) {
trigger_annotation_name = parsed_rule.getLogTriggers()[0];
} else if (!default_rule.getLogTriggers().empty() && !default_rule.getLogTriggers()[0].empty()) {
trigger_annotation_name = default_rule.getLogTriggers()[0];
}
if (!trigger_annotation_name.empty()) {
rule_annotation[AnnotationTypes::TRIGGER] = policy_name + "/" + trigger_annotation_name;
}
string exception_annotation_name;
// TBD: support multiple exceptions
if (!parsed_rule.getExceptions().empty() && !parsed_rule.getExceptions()[0].empty()) {
exception_annotation_name = parsed_rule.getExceptions()[0];
} else if (!default_rule.getExceptions().empty() && !default_rule.getExceptions()[0].empty()) {
exception_annotation_name = default_rule.getExceptions()[0];
}
if (!exception_annotation_name.empty()) {
rule_annotation[AnnotationTypes::EXCEPTION] = policy_name + "/" + exception_annotation_name;
}
string web_user_res_annotation_name =
parsed_rule.getCustomResponse().empty() ?
default_rule.getCustomResponse() :
parsed_rule.getCustomResponse();
if (!web_user_res_annotation_name.empty()) {
rule_annotation[AnnotationTypes::WEB_USER_RES] = policy_name + "/" + web_user_res_annotation_name;
}
string source_identifiers_annotation_name =
parsed_rule.getSourceIdentifiers().empty() ?
default_rule.getSourceIdentifiers() :
parsed_rule.getSourceIdentifiers();
if (!source_identifiers_annotation_name.empty()) {
rule_annotation[AnnotationTypes::SOURCE_IDENTIFIERS] = policy_name + "/" + source_identifiers_annotation_name;
}
string trusted_sources_annotation_name =
parsed_rule.getTrustedSources ().empty() ?
default_rule.getTrustedSources() :
parsed_rule.getTrustedSources();
if (!trusted_sources_annotation_name.empty()) {
rule_annotation[AnnotationTypes::TRUSTED_SOURCES] = policy_name + "/" + trusted_sources_annotation_name;
}
return rule_annotation;
}
template<class container_it>
container_it
extractElement(container_it begin, container_it end, const string &element_name)
{
dbgTrace(D_NGINX_POLICY) << "Tryting to find element: " << element_name;
string clean_element_name = element_name.substr(element_name.find("/") + 1);
for (container_it it = begin; it < end; it++) {
if (clean_element_name == it->getName()) {
dbgTrace(D_NGINX_POLICY) << "Element with name " << clean_element_name << " was found";
return it;
}
}
dbgTrace(D_NGINX_POLICY) << "Element with name " << clean_element_name << " was not found";
return end;
}
template<typename K, typename V>
vector<V>
convertMapToVector(map<K, V> map)
{
vector<V> vec;
vec.reserve(map.size());
if (map.empty()) {
return vec;
}
for (const auto &m : map) {
if (!m.first.empty()) vec.push_back(m.second);
}
return vec;
}
AppSecPracticeSpec
getAppsecPracticeSpec(const string &practice_annotation_name, const AppsecLinuxPolicy &policy)
{
auto practices_vec = policy.getAppSecPracticeSpecs();
auto practice_it = extractElement(practices_vec.begin(), practices_vec.end(), practice_annotation_name);
if (practice_it == practices_vec.end()) {
dbgTrace(D_NGINX_POLICY) << "Failed to retrieve AppSec practice";
return AppSecPracticeSpec();
}
return *practice_it;
}
AppsecTriggerSpec
getAppsecTriggerSpec(const string &trigger_annotation_name, const AppsecLinuxPolicy &policy)
{
auto triggers_vec = policy.getAppsecTriggerSpecs();
auto trigger_it = extractElement(triggers_vec.begin(), triggers_vec.end(), trigger_annotation_name);
if (trigger_it == triggers_vec.end()) {
dbgTrace(D_NGINX_POLICY) << "Failed to retrieve AppSec trigger";
return AppsecTriggerSpec();
}
return *trigger_it;
}
AppsecExceptionSpec
getAppsecExceptionSpec(const string &exception_annotation_name, const AppsecLinuxPolicy &policy)
{
auto exceptions_vec = policy.getAppsecExceptionSpecs();
auto exception_it = extractElement(exceptions_vec.begin(), exceptions_vec.end(), exception_annotation_name);
if (exception_it == exceptions_vec.end()) {
dbgTrace(D_NGINX_POLICY) << "Failed to retrieve AppSec exception";
return AppsecExceptionSpec();
}
return *exception_it;
}
AppSecCustomResponseSpec
getAppsecCustomResponseSpec(const string &custom_response_annotation_name, const AppsecLinuxPolicy &policy)
{
auto custom_response_vec = policy.getAppSecCustomResponseSpecs();
auto custom_response_it = extractElement(
custom_response_vec.begin(),
custom_response_vec.end(),
custom_response_annotation_name);
if (custom_response_it == custom_response_vec.end()) {
dbgTrace(D_NGINX_POLICY) << "Failed to retrieve AppSec custom response";
return AppSecCustomResponseSpec();
}
return *custom_response_it;
}
SourceIdentifierSpecWrapper
getAppsecSourceIdentifierSpecs(const string &source_identifiers_annotation_name, const AppsecLinuxPolicy &policy)
{
auto source_identifiers_vec = policy.getAppsecSourceIdentifierSpecs();
auto source_identifier_it = extractElement(
source_identifiers_vec.begin(),
source_identifiers_vec.end(),
source_identifiers_annotation_name);
if (source_identifier_it == source_identifiers_vec.end()) {
dbgTrace(D_NGINX_POLICY) << "Failed to retrieve AppSec source identifier";
return SourceIdentifierSpecWrapper();
}
return *source_identifier_it;
}
TrustedSourcesSpec
getAppsecTrustedSourceSpecs(const string &trusted_sources_annotation_name, const AppsecLinuxPolicy &policy)
{
auto trusted_sources_vec = policy.getAppsecTrustedSourceSpecs();
auto trusted_sources_it = extractElement(
trusted_sources_vec.begin(),
trusted_sources_vec.end(),
trusted_sources_annotation_name);
if (trusted_sources_it == trusted_sources_vec.end()) {
dbgTrace(D_NGINX_POLICY) << "Failed to retrieve AppSec trusted source";
return TrustedSourcesSpec();
}
return *trusted_sources_it;
}
LogTriggerSection
createLogTriggerSection(
const string &trigger_annotation_name,
const AppsecLinuxPolicy &policy)
{
AppsecTriggerSpec trigger_spec = getAppsecTriggerSpec(trigger_annotation_name, policy);
string verbosity = "Standard";
string extendLoggingMinSeverity =
trigger_spec.getAppsecTriggerAdditionalSuspiciousEventsLogging().getMinimumSeverity();
bool tpDetect = trigger_spec.getAppsecTriggerLogging().isDetectEvents();
bool tpPrevent = trigger_spec.getAppsecTriggerLogging().isPreventEvents();
bool webRequests = trigger_spec.getAppsecTriggerLogging().isAllWebRequests();
bool webUrlPath = trigger_spec.getAppsecTriggerExtendedLogging().isUrlPath();
bool webUrlQuery = trigger_spec.getAppsecTriggerExtendedLogging().isUrlQuery();
bool webHeaders = trigger_spec.getAppsecTriggerExtendedLogging().isHttpHeaders();
bool webBody = trigger_spec.getAppsecTriggerExtendedLogging().isRequestBody();
bool logToCloud = trigger_spec.getAppsecTriggerLogDestination().getCloud();
bool logToAgent = trigger_spec.getAppsecTriggerLogDestination().isAgentLocal();
bool beautify_logs = trigger_spec.getAppsecTriggerLogDestination().shouldBeautifyLogs();
bool logToCef = trigger_spec.getAppsecTriggerLogDestination().isCefNeeded();
bool logToSyslog = trigger_spec.getAppsecTriggerLogDestination().isSyslogNeeded();
bool responseBody = trigger_spec.getAppsecTriggerAdditionalSuspiciousEventsLogging().isResponseBody();
bool extendLogging = trigger_spec.getAppsecTriggerAdditionalSuspiciousEventsLogging().isEnabled();
int cefPortNum = logToCef ? trigger_spec.getAppsecTriggerLogDestination().getCefServerUdpPort() : 0;
string cefIpAddress =
logToCef ? trigger_spec.getAppsecTriggerLogDestination().getCefServerIpv4Address() : "";
int syslogPortNum =
logToSyslog ?
trigger_spec.getAppsecTriggerLogDestination().getSyslogServerUdpPort() :
514;
string syslogIpAddress =
logToSyslog ?
trigger_spec.getAppsecTriggerLogDestination().getSyslogServerIpv4Address() :
"";
LogTriggerSection log(
trigger_annotation_name,
verbosity,
extendLoggingMinSeverity,
extendLogging,
logToAgent,
logToCef,
logToCloud,
logToSyslog,
responseBody,
tpDetect,
tpPrevent,
webBody,
webHeaders,
webRequests,
webUrlPath,
webUrlQuery,
cefPortNum,
cefIpAddress,
syslogPortNum,
syslogIpAddress,
beautify_logs
);
return log;
}
WebUserResponseTriggerSection
createWebUserResponseTriggerSection(
const string &web_user_res_annotation_name,
const AppsecLinuxPolicy &policy)
{
AppSecCustomResponseSpec web_user_res_spec = getAppsecCustomResponseSpec(web_user_res_annotation_name, policy);
string mode = web_user_res_spec.getMode();
string response_body = web_user_res_spec.getMessageBody();
string response_title = web_user_res_spec.getMessageTitle();
int response_code = web_user_res_spec.getHttpResponseCode();
WebUserResponseTriggerSection web_user_res(
web_user_res_annotation_name,
mode,
response_body,
response_code,
response_title
);
return web_user_res;
}
InnerException
createExceptionSection(
const string &exception_annotation_name,
const AppsecLinuxPolicy &policy)
{
AppsecExceptionSpec exception_spec = getAppsecExceptionSpec(exception_annotation_name, policy);
ExceptionMatch exception_match(exception_spec);
string behavior =
exception_spec.getAction() == "skip" ?
"ignore" :
exception_spec.getAction();
ExceptionBehavior exception_behavior("action", behavior);
InnerException inner_exception(exception_behavior, exception_match);
return inner_exception;
}
RulesConfigRulebase
createMultiRulesSections(
const string &url,
const string &uri,
const string &practice_id,
const string &practice_name,
const string &practice_type,
const string &log_trigger_name,
const string &log_trigger_id,
const string &log_trigger_type,
const string &web_user_res_vec_name,
const string &web_user_res_vec_id,
const string &web_user_res_vec_type,
const string &asset_name,
const string &exception_name,
const string &exception_id)
{
PracticeSection practice = PracticeSection(practice_id, practice_type, practice_name);
ParametersSection exception_param = ParametersSection(exception_id, exception_name);
vector<RulesTriggerSection> triggers;
if (!log_trigger_id.empty()) {
triggers.push_back(RulesTriggerSection(log_trigger_name, log_trigger_id, log_trigger_type));
}
if (!web_user_res_vec_id.empty()) {
triggers.push_back(RulesTriggerSection(
web_user_res_vec_name,
web_user_res_vec_id,
web_user_res_vec_type)
);
}
RulesConfigRulebase rules_config = RulesConfigRulebase(
asset_name,
url,
uri,
{practice},
{exception_param},
triggers
);
return rules_config;
}
SettingsWrapper
createProfilesSection()
{
string agent_settings_key = "agent.test.policy";
string agent_settings_value = "local policy";
AgentSettingsSection agent_setting_1 = AgentSettingsSection(agent_settings_key, agent_settings_value);
SettingsRulebase settings_rulebase_1 = SettingsRulebase({agent_setting_1});
return SettingsWrapper(settings_rulebase_1);
}
PolicyWrapper
PolicyMakerUtils::combineElementsToPolicy(const string &policy_version)
{
TriggersWrapper triggers_section(
TriggersRulebase(
convertMapToVector(log_triggers), convertMapToVector(web_user_res_triggers)
)
);
ExceptionsWrapper exceptions_section({
ExceptionsRulebase(convertMapToVector(inner_exceptions))
});
AppSecWrapper appses_section(AppSecRulebase(convertMapToVector(web_apps), {}));
RulesConfigWrapper rules_config_section(convertMapToVector(rules_config));
SecurityAppsWrapper security_app_section = SecurityAppsWrapper(
appses_section,
triggers_section,
rules_config_section,
exceptions_section,
policy_version
);
SettingsWrapper profiles_section = createProfilesSection();
PolicyWrapper policy_wrapper = PolicyWrapper(profiles_section, security_app_section);
return policy_wrapper;
}
void
PolicyMakerUtils::createPolicyElementsByRule(
const ParsedRule &rule,
const ParsedRule &default_rule,
const AppsecLinuxPolicy &policy,
const string &policy_name)
{
map<AnnotationTypes, string> rule_annotations = extractAnnotationsNames(rule, default_rule, policy_name);
if (
!rule_annotations[AnnotationTypes::TRIGGER].empty() &&
!log_triggers.count(rule_annotations[AnnotationTypes::TRIGGER])
) {
log_triggers[rule_annotations[AnnotationTypes::TRIGGER]] =
createLogTriggerSection(
rule_annotations[AnnotationTypes::TRIGGER],
policy
);
}
if (
!rule_annotations[AnnotationTypes::WEB_USER_RES].empty() &&
!web_user_res_triggers.count(rule_annotations[AnnotationTypes::WEB_USER_RES])
) {
web_user_res_triggers[rule_annotations[AnnotationTypes::WEB_USER_RES]] =
createWebUserResponseTriggerSection(
rule_annotations[AnnotationTypes::WEB_USER_RES],
policy
);
}
if (
!rule_annotations[AnnotationTypes::EXCEPTION].empty() &&
!inner_exceptions.count(rule_annotations[AnnotationTypes::EXCEPTION])
) {
inner_exceptions[rule_annotations[AnnotationTypes::EXCEPTION]] =
createExceptionSection(
rule_annotations[AnnotationTypes::EXCEPTION],
policy
);
}
if (
!rule_annotations[AnnotationTypes::PRACTICE].empty() &&
!web_apps.count(rule_annotations[AnnotationTypes::PRACTICE])
) {
string practice_id = "";
try {
practice_id = to_string(boost::uuids::random_generator()());
} catch (const boost::uuids::entropy_error &e) {
//TBD: return Maybe as part of future error handling
}
tuple<string, string, string> splited_host_name = splitHostName(rule.getHost());
string full_url = rule.getHost() == "*"
? "Any"
: rule.getHost();
RulesConfigRulebase rule_config = createMultiRulesSections(
std::get<0>(splited_host_name),
std::get<2>(splited_host_name),
practice_id,
rule_annotations[AnnotationTypes::PRACTICE],
"WebApplication",
rule_annotations[AnnotationTypes::TRIGGER],
log_triggers[rule_annotations[AnnotationTypes::TRIGGER]].getTriggerId(),
"log",
rule_annotations[AnnotationTypes::WEB_USER_RES],
web_user_res_triggers[rule_annotations[AnnotationTypes::WEB_USER_RES]].getTriggerId(),
"WebUserResponse",
full_url,
rule_annotations[AnnotationTypes::EXCEPTION],
inner_exceptions[rule_annotations[AnnotationTypes::EXCEPTION]].getBehaviorId()
);
rules_config[rule_config.getAssetName()] = rule_config;
WebAppSection web_app = WebAppSection(
full_url == "Any" ? "" : full_url,
rule_config.getAssetId(),
rule_config.getAssetName(),
rule_config.getAssetId(),
rule_config.getAssetName(),
practice_id,
rule_annotations[AnnotationTypes::PRACTICE],
getAppsecPracticeSpec(rule_annotations[AnnotationTypes::PRACTICE], policy),
log_triggers[rule_annotations[AnnotationTypes::TRIGGER]],
rule.getMode(),
AppSecTrustedSources()
);
web_apps[rule_annotations[AnnotationTypes::PRACTICE]] = web_app;
}
}
void
PolicyMakerUtils::createPolicyElements(
const vector<ParsedRule> &rules,
const ParsedRule &default_rule,
const AppsecLinuxPolicy &policy,
const string &policy_name)
{
for (const ParsedRule &rule : rules) {
createPolicyElementsByRule(rule, default_rule, policy, policy_name);
}
}
// LCOV_EXCL_STOP

View File

@@ -0,0 +1,365 @@
#include "rules_config_section.h"
using namespace std;
USE_DEBUG_FLAG(D_K8S_POLICY);
// LCOV_EXCL_START Reason: no test exist
AssetUrlParser
AssetUrlParser::parse(const string &uri)
{
AssetUrlParser result;
using iterator_t = string::const_iterator;
if (uri.length() == 0) return result;
iterator_t uri_end = uri.end();
// get query start
iterator_t query_start = find(uri.begin(), uri_end, '?');
// protocol
iterator_t protocol_start = uri.begin();
iterator_t protocol_end = find(protocol_start, uri_end, ':'); //"://");
if (protocol_end != uri_end) {
string http_protocol = &*(protocol_end);
if ((http_protocol.length() > 3) && (http_protocol.substr(0, 3) == "://")) {
result.protocol = string(protocol_start, protocol_end);
protocol_end += 3; // ://
} else {
protocol_end = uri.begin(); // no protocol
}
} else {
protocol_end = uri.begin(); // no protocol
}
// URL
iterator_t host_start = protocol_end;
iterator_t path_start = find(host_start, uri_end, '/');
iterator_t host_end = find(protocol_end, (path_start != uri_end) ? path_start : query_start, ':');
result.asset_url = string(host_start, host_end);
// port
if ((host_end != uri_end) && ((&*(host_end))[0] == ':')) { // we have a port
host_end++;
iterator_t portEnd = (path_start != uri_end) ? path_start : query_start;
result.port = string(host_end, portEnd);
}
// URI
if (path_start != uri_end) result.asset_uri = string(path_start, query_start);
// query
if (query_start != uri_end) result.query_string = string(query_start, uri.end());
return result;
} // Parse
PracticeSection::PracticeSection(
const string &_id,
const string &_type,
const string &_practice_name
)
{
auto maybe_type = string_to_practice_type.find(_type);
if (maybe_type == string_to_practice_type.end()) {
dbgError(D_K8S_POLICY) << "Illegal pracrtice type: " << _type;
return;
}
type = _type;
name = _practice_name;
id = _id;
}
void
PracticeSection::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("practiceId", id),
cereal::make_nvp("practiceName", name),
cereal::make_nvp("practiceType", type)
);
}
const string &
PracticeSection::getPracticeId() const
{
return id;
}
const string &
PracticeSection::getPracticeName() const
{
return name;
}
ParametersSection::ParametersSection(
const string &_id,
const string &_name)
:
name(_name),
id(_id)
{
if (_id.empty() && _name.empty()) {
dbgError(D_K8S_POLICY) << "Illegal Parameter values. Name and ID are empty";
return;
}
}
void
ParametersSection::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("parameterId", id),
cereal::make_nvp("parameterName", name),
cereal::make_nvp("parameterType", type)
);
}
const string &
ParametersSection::getId() const
{
return id;
}
RulesTriggerSection::RulesTriggerSection(
const string &_name,
const string &_id,
const string &_type)
:
name(_name),
id(_id)
{
if (_name.empty() && _id.empty()) {
dbgError(D_K8S_POLICY) << "Illegal values for trigger. Name and ID are empty";
return;
}
auto maybe_type = string_to_trigger_type.find(_type);
if (maybe_type == string_to_trigger_type.end()) {
dbgError(D_K8S_POLICY) << "Illegal trigger type in rule: " << _type;
return;
}
type = _type;
}
void
RulesTriggerSection::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("triggerId", id),
cereal::make_nvp("triggerName", name),
cereal::make_nvp("triggerType", type)
);
}
const string &
RulesTriggerSection::getId() const
{
return id;
}
const string &
RulesTriggerSection::getName() const
{
return id;
}
RulesConfigRulebase::RulesConfigRulebase(
const string &_name,
const string &_url,
const string &_uri,
vector<PracticeSection> _practices,
vector<ParametersSection> _parameters,
vector<RulesTriggerSection> _triggers)
:
name(_name),
practices(_practices),
parameters(_parameters),
triggers(_triggers)
{
try {
bool any = _name == "Any" && _url == "Any" && _uri == "Any";
id = any ? "Any" : _url+_uri;
if (_uri != "/") {
context = any ? "All()" : "Any("
"All("
"Any("
"EqualHost(" + _url + ")"
"),"
"EqualListeningPort(80)" +
string(_uri.empty() ? "" : ",BeginWithUri(" + _uri + ")") +
"),"
"All("
"Any("
"EqualHost(" + _url + ")"
"),"
"EqualListeningPort(443)" +
string(_uri.empty() ? "" : ",BeginWithUri(" + _uri + ")") +
")"
")";
} else {
context = any ? "All()" : "Any("
"All("
"Any("
"EqualHost(" + _url + ")"
"),"
"EqualListeningPort(80)"
"),"
"All("
"Any("
"EqualHost(" + _url + ")"
"),"
"EqualListeningPort(443)"
")"
")";
}
} catch (const boost::uuids::entropy_error &e) {
dbgWarning(D_K8S_POLICY) << "Failed to generate rule UUID. Error: " << e.what();
}
}
void
RulesConfigRulebase::save(cereal::JSONOutputArchive &out_ar) const
{
string empty_str = "";
out_ar(
cereal::make_nvp("assetId", id),
cereal::make_nvp("assetName", name),
cereal::make_nvp("ruleId", id),
cereal::make_nvp("ruleName", name),
cereal::make_nvp("context", context),
cereal::make_nvp("priority", 1),
cereal::make_nvp("isCleanup", false),
cereal::make_nvp("parameters", parameters),
cereal::make_nvp("practices", practices),
cereal::make_nvp("triggers", triggers),
cereal::make_nvp("zoneId", empty_str),
cereal::make_nvp("zoneName", empty_str)
);
}
const string &
RulesConfigRulebase::getRuleId() const
{
return id;
}
const string &
RulesConfigRulebase::getAssetName() const
{
return name;
}
const string &
RulesConfigRulebase::getRuleName() const
{
return name;
}
const string &
RulesConfigRulebase::getAssetId() const
{
return id;
}
const string &
RulesConfigRulebase::getPracticeId() const
{
return practices[0].getPracticeId();
}
const string &
RulesConfigRulebase::getPracticeName() const
{
return practices[0].getPracticeName();
}
const vector<PracticeSection> &
RulesConfigRulebase::getPractice() const
{
return practices;
}
const vector<ParametersSection> &
RulesConfigRulebase::getParameters() const
{
return parameters;
}
const vector<RulesTriggerSection> &
RulesConfigRulebase::getTriggers() const
{
return triggers;
}
RulesConfigWrapper::RulesConfig::RulesConfig(const vector<RulesConfigRulebase> &_rules_config)
:
rules_config(_rules_config)
{
sort(rules_config.begin(), rules_config.end(), sortBySpecific);
}
void
RulesConfigWrapper::RulesConfig::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("rulesConfig", rules_config)
);
}
bool
RulesConfigWrapper::RulesConfig::sortBySpecific(
const RulesConfigRulebase &first,
const RulesConfigRulebase &second
)
{
return sortBySpecificAux(first.getAssetName(), second.getAssetName());
}
bool
RulesConfigWrapper::RulesConfig::sortBySpecificAux(const string &first, const string &second)
{
if (first.empty()) return false;
if (second.empty()) return true;
AssetUrlParser first_parsed = AssetUrlParser::parse(first);
AssetUrlParser second_parsed = AssetUrlParser::parse(second);
// sort by URL
if (first_parsed.asset_url == "Any" && second_parsed.asset_url != "Any") return false;
if (second_parsed.asset_url == "Any" && first_parsed.asset_url != "Any") return true;
// sort by port
if (first_parsed.port == "*" && second_parsed.port != "*") return false;
if (second_parsed.port == "*" && first_parsed.port != "*") return true;
// sort by URI
if (first_parsed.asset_uri == "*" && second_parsed.asset_uri != "*") return false;
if (second_parsed.asset_uri == "*" && first_parsed.asset_uri != "*") return true;
if (first_parsed.asset_uri.empty()) return false;
if (second_parsed.asset_uri.empty()) return true;
if (second_parsed.asset_uri.find(first_parsed.asset_uri) != string::npos) return false;
if (first_parsed.asset_uri.find(second_parsed.asset_uri) != string::npos) return true;
if (first_parsed.asset_url.empty()) return false;
if (second_parsed.asset_url.empty()) return false;
return second < first;
}
void
RulesConfigWrapper::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("rulebase", rules_config_rulebase)
);
}
// LCOV_EXCL_STOP

View File

@@ -0,0 +1,74 @@
#include "settings_section.h"
using namespace std;
USE_DEBUG_FLAG(D_K8S_POLICY);
// LCOV_EXCL_START Reason: no test exist
AgentSettingsSection::AgentSettingsSection(
const string &_key,
const string &_value)
:
key(_key),
value(_value)
{
try {
id = to_string(boost::uuids::random_generator()());
} catch (const boost::uuids::entropy_error &e) {
dbgWarning(D_K8S_POLICY) << "Failed to generate agent setting UUID. Error: " << e.what();
}
}
void
AgentSettingsSection::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("id", id),
cereal::make_nvp("key", key),
cereal::make_nvp("value", value)
);
}
const string &
AgentSettingsSection::getSettingId() const
{
return id;
}
void
SettingsRulebase::save(cereal::JSONOutputArchive &out_ar) const
{
string profile_type = "Kubernetes";
string upgrade_mode = "automatic";
out_ar(
cereal::make_nvp("agentSettings", agentSettings),
cereal::make_nvp("agentType", profile_type),
cereal::make_nvp("allowOnlyDefinedApplications", false),
cereal::make_nvp("anyFog", true),
cereal::make_nvp("maxNumberOfAgents", 10),
cereal::make_nvp("upgradeMode", upgrade_mode)
);
}
SettingsWrapper::SettingsWrapper(SettingsRulebase _agent) : agent(_agent)
{
try {
id = to_string(boost::uuids::random_generator()());
} catch (const boost::uuids::entropy_error &e) {
dbgWarning(D_K8S_POLICY) << "Failed to generate Settings Wrapper UUID. Error: " << e.what();
}
}
void
SettingsWrapper::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("profileType", profileType),
cereal::make_nvp("tokenType", isToken),
cereal::make_nvp("tokenType", tokenType),
cereal::make_nvp("name", name),
cereal::make_nvp("id", id),
cereal::make_nvp("agent", agent)
);
}
// LCOV_EXCL_STOP

View File

@@ -0,0 +1,41 @@
#include "snort_section.h"
using namespace std;
USE_DEBUG_FLAG(D_K8S_POLICY);
// LCOV_EXCL_START Reason: no test exist
AgentSettingsSection::AgentSettingsSection(string _key, string _value) : key(_key), value(_value)
{
try {
id = to_string(boost::uuids::random_generator()());
} catch (const boost::uuids::entropy_error &e) {
dbgWarning(D_K8S_POLICY) << "Failed to generate agent setting UUID. Error: " << e.what();
}
}
void
AgentSettingsSection::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("id", id),
cereal::make_nvp("key", key),
cereal::make_nvp("value", value)
);
}
void
IpsSnortSigsRulebase::save(cereal::JSONOutputArchive &out_ar) const
{
string profile_type = "KubernetesProfile";
string upgrade_mode = "automatic";
out_ar(
cereal::make_nvp("agentSettings", agentSettings),
cereal::make_nvp("agentType", profile_type),
cereal::make_nvp("allowOnlyDefinedApplications", false),
cereal::make_nvp("anyFog", true),
cereal::make_nvp("maxNumberOfAgents", 10),
cereal::make_nvp("upgradeMode", upgrade_mode)
);
}
// LCOV_EXCL_STOP

View File

@@ -0,0 +1,522 @@
#include "triggers_section.h"
using namespace std;
USE_DEBUG_FLAG(D_K8S_POLICY);
// LCOV_EXCL_START Reason: no test exist
LogTriggerSection::LogTriggerSection(
const string &_name,
const string &_verbosity,
const string &_extendloggingMinSeverity,
bool _extendlogging,
bool _logToAgent,
bool _logToCef,
bool _logToCloud,
bool _logToSyslog,
bool _responseBody,
bool _tpDetect,
bool _tpPrevent,
bool _webBody,
bool _webHeaders,
bool _webRequests,
bool _webUrlPath,
bool _webUrlQuery,
int _cefPortNum,
const string &_cefIpAddress,
int _syslogPortNum,
const string &_syslogIpAddress,
bool _beautify_logs)
:
name(_name),
verbosity(_verbosity),
extendloggingMinSeverity(_extendloggingMinSeverity),
extendlogging(_extendlogging),
logToAgent(_logToAgent),
logToCef(_logToCef),
logToCloud(_logToCloud),
logToSyslog(_logToSyslog),
responseBody(_responseBody),
tpDetect(_tpDetect),
tpPrevent(_tpPrevent),
webBody(_webBody),
webHeaders(_webHeaders),
webRequests(_webRequests),
webUrlPath(_webUrlPath),
webUrlQuery(_webUrlQuery),
cefPortNum (_cefPortNum),
cefIpAddress (_cefIpAddress),
syslogPortNum (_syslogPortNum),
syslogIpAddress (_syslogIpAddress),
beautify_logs(_beautify_logs)
{
try {
id = to_string(boost::uuids::random_generator()());
context = "triggerId(" + id + ")";
} catch (const boost::uuids::entropy_error &e) {
dbgWarning(D_K8S_POLICY) << "Failed to generate log trigger UUID. Error: " << e.what();
}
}
void
LogTriggerSection::save(cereal::JSONOutputArchive &out_ar) const
{
string trigger_type = "log";
string urlForSyslog = syslogIpAddress + ":" + to_string(syslogPortNum);
string urlForCef = cefIpAddress + ":" + to_string(cefPortNum);
out_ar(
cereal::make_nvp("context", context),
cereal::make_nvp("triggerName", name),
cereal::make_nvp("triggerType", trigger_type),
cereal::make_nvp("verbosity", verbosity),
cereal::make_nvp("acAllow", false),
cereal::make_nvp("acDrop", false),
cereal::make_nvp("complianceViolations", false),
cereal::make_nvp("complianceWarnings", false),
cereal::make_nvp("extendloggingMinSeverity", extendloggingMinSeverity),
cereal::make_nvp("extendlogging", extendlogging),
cereal::make_nvp("logToAgent", logToAgent),
cereal::make_nvp("logToCef", logToCef),
cereal::make_nvp("logToCloud", logToCloud),
cereal::make_nvp("logToSyslog", logToSyslog),
cereal::make_nvp("responseBody", responseBody),
cereal::make_nvp("responseCode", false),
cereal::make_nvp("tpDetect", tpDetect),
cereal::make_nvp("tpPrevent", tpPrevent),
cereal::make_nvp("webBody", webBody),
cereal::make_nvp("webHeaders", webHeaders),
cereal::make_nvp("webRequests", webRequests),
cereal::make_nvp("webUrlPath", webUrlPath),
cereal::make_nvp("webUrlQuery", webUrlQuery),
cereal::make_nvp("urlForSyslog", urlForSyslog),
cereal::make_nvp("urlForCef", urlForCef),
cereal::make_nvp("formatLoggingOutput", beautify_logs)
);
}
const string &
LogTriggerSection::getTriggerId() const
{
return id;
}
const string &
LogTriggerSection::getTriggerName() const
{
return name;
}
bool
LogTriggerSection::operator<(const LogTriggerSection &other) const
{
return getTriggerName() < other.getTriggerName();
}
WebUserResponseTriggerSection::WebUserResponseTriggerSection(
const string &_name,
const string &_details_level,
const string &_response_body,
int _response_code,
const string &_response_title)
:
name(_name),
context(),
details_level(_details_level),
response_body(_response_body),
response_title(_response_title),
response_code(_response_code)
{
try {
id = to_string(boost::uuids::random_generator()());
context = "triggerId(" + id + ")";
} catch (const boost::uuids::entropy_error &e) {
dbgWarning(D_K8S_POLICY) << "Failed to generate webUserResponse trigger UUID. Error: " << e.what();
}
}
void
WebUserResponseTriggerSection::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("context", context),
cereal::make_nvp("triggerName", name),
cereal::make_nvp("details level", details_level),
cereal::make_nvp("response body", response_body),
cereal::make_nvp("response code", response_code),
cereal::make_nvp("response title", response_title)
);
}
const string &
WebUserResponseTriggerSection::getTriggerId() const
{
return id;
}
const string &
WebUserResponseTriggerSection::getTriggerName() const
{
return name;
}
bool
WebUserResponseTriggerSection::operator<(const WebUserResponseTriggerSection &other) const
{
return getTriggerName() < other.getTriggerName();
}
void
AppSecCustomResponseSpec::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec web user response spec";
parseAppsecJSONKey<int>("http-response-code", httpResponseCode, archive_in, 403);
parseAppsecJSONKey<string>("mode", mode, archive_in, "block-page");
parseAppsecJSONKey<string>("name", name, archive_in);
if (mode == "block-page") {
parseAppsecJSONKey<string>(
"message-body",
messageBody,
archive_in,
"Openappsec's <b>Application Security</b> has detected an attack and blocked it."
);
parseAppsecJSONKey<string>(
"message-title",
messageTitle,
archive_in,
"Attack blocked by web application protection"
);
}
}
int
AppSecCustomResponseSpec::getHttpResponseCode() const
{
return httpResponseCode;
}
const string &
AppSecCustomResponseSpec::getMessageBody() const
{
return messageBody;
}
const string &
AppSecCustomResponseSpec::getMessageTitle() const
{
return messageTitle;
}
const string &
AppSecCustomResponseSpec::getMode() const
{
return mode;
}
const string &
AppSecCustomResponseSpec::getName() const
{
return name;
}
void
TriggersRulebase::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("log", logTriggers),
cereal::make_nvp("webUserResponse", webUserResponseTriggers)
);
}
void
AppsecTriggerAccessControlLogging::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec Trigger - Access Control Logging";
parseAppsecJSONKey<bool>("allow-events", allow_events, archive_in, false);
parseAppsecJSONKey<bool>("drop-events", drop_events, archive_in, false);
}
bool
AppsecTriggerAccessControlLogging::isAllowEvents() const
{
return allow_events;
}
bool
AppsecTriggerAccessControlLogging::isDropEvents() const
{
return drop_events;
}
void
AppsecTriggerAdditionalSuspiciousEventsLogging::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec Trigger - Additional Suspicious Events Logging";
parseAppsecJSONKey<bool>("enabled", enabled, archive_in, true);
parseAppsecJSONKey<bool>("response-body", response_body, archive_in, false);
parseAppsecJSONKey<string>("minimum-severity", minimum_severity, archive_in, "high");
}
bool
AppsecTriggerAdditionalSuspiciousEventsLogging::isEnabled() const
{
return enabled;
}
bool
AppsecTriggerAdditionalSuspiciousEventsLogging::isResponseBody() const
{
return response_body;
}
const string &
AppsecTriggerAdditionalSuspiciousEventsLogging::getMinimumSeverity() const
{
return minimum_severity;
}
void
AppsecTriggerLogging::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec Trigger Logging";
parseAppsecJSONKey<bool>("all-web-requests", all_web_requests, archive_in, false);
parseAppsecJSONKey<bool>("detect-events", detect_events, archive_in, false);
parseAppsecJSONKey<bool>("prevent-events", prevent_events, archive_in, true);
}
bool
AppsecTriggerLogging::isAllWebRequests() const
{
return all_web_requests;
}
bool
AppsecTriggerLogging::isDetectEvents() const
{
return detect_events;
}
bool
AppsecTriggerLogging::isPreventEvents() const
{
return prevent_events;
}
void
AppsecTriggerExtendedLogging::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec Trigger Extended Logging";
parseAppsecJSONKey<bool>("http-headers", http_headers, archive_in, false);
parseAppsecJSONKey<bool>("request-body", request_body, archive_in, false);
parseAppsecJSONKey<bool>("url-path", url_path, archive_in, false);
parseAppsecJSONKey<bool>("url-query", url_query, archive_in, false);
}
bool
AppsecTriggerExtendedLogging::isHttpHeaders() const
{
return http_headers;
}
bool
AppsecTriggerExtendedLogging::isRequestBody() const
{
return request_body;
}
bool
AppsecTriggerExtendedLogging::isUrlPath() const
{
return url_path;
}
bool
AppsecTriggerExtendedLogging::isUrlQuery() const
{
return url_query;
}
void
LoggingService::load(cereal::JSONInputArchive &archive_in)
{
parseAppsecJSONKey<string>("address", address, archive_in);
parseAppsecJSONKey<string>("proto", proto, archive_in);
parseAppsecJSONKey<int>("port", port, archive_in, 514);
}
const string &
LoggingService::getAddress() const
{
return address;
}
const string &
LoggingService::getProto() const
{
return proto;
}
int
LoggingService::getPort() const
{
return port;
}
void
StdoutLogging::load(cereal::JSONInputArchive &archive_in)
{
parseAppsecJSONKey<string>("format", format, archive_in, "json");
}
const string &
StdoutLogging::getFormat() const
{
return format;
}
void
AppsecTriggerLogDestination::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec Trigger LogDestination";
// TBD: support "file"
parseAppsecJSONKey<bool>("cloud", cloud, archive_in, false);
StdoutLogging stdout_log;
parseAppsecJSONKey<StdoutLogging>("stdout", stdout_log, archive_in);
agent_local = !(stdout_log.getFormat().empty());
beautify_logs = stdout_log.getFormat() == "json-formatted";
parseAppsecJSONKey<LoggingService>("syslog-service", syslog_service, archive_in);
parseAppsecJSONKey<LoggingService>("cef-service", cef_service, archive_in);
}
int
AppsecTriggerLogDestination::getCefServerUdpPort() const
{
return getCefServiceData().getPort();
}
int
AppsecTriggerLogDestination::getSyslogServerUdpPort() const
{
return getSyslogServiceData().getPort();
}
bool
AppsecTriggerLogDestination::isAgentLocal() const
{
return agent_local;
}
bool
AppsecTriggerLogDestination::shouldBeautifyLogs() const
{
return beautify_logs;
}
bool
AppsecTriggerLogDestination::getCloud() const
{
return cloud;
}
bool
AppsecTriggerLogDestination::isCefNeeded() const
{
return !getCefServiceData().getAddress().empty();
}
bool
AppsecTriggerLogDestination::isSyslogNeeded() const
{
return !getSyslogServiceData().getAddress().empty();
}
const
string & AppsecTriggerLogDestination::getSyslogServerIpv4Address() const
{
return getSyslogServiceData().getAddress();
}
const string &
AppsecTriggerLogDestination::getCefServerIpv4Address() const
{
return getCefServiceData().getAddress();
}
const LoggingService &
AppsecTriggerLogDestination::getSyslogServiceData() const
{
return syslog_service;
}
const LoggingService &
AppsecTriggerLogDestination::getCefServiceData() const
{
return cef_service;
}
void
AppsecTriggerSpec::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading AppSec trigger spec";
parseAppsecJSONKey<AppsecTriggerAccessControlLogging>(
"access-control-logging",
access_control_logging,
archive_in
);
parseAppsecJSONKey<AppsecTriggerAdditionalSuspiciousEventsLogging>(
"additional-suspicious-events-logging",
additional_suspicious_events_logging,
archive_in
);
parseAppsecJSONKey<AppsecTriggerLogging>("appsec-logging", appsec_logging, archive_in);
parseAppsecJSONKey<AppsecTriggerExtendedLogging>("extended-logging", extended_logging, archive_in);
parseAppsecJSONKey<AppsecTriggerLogDestination>("log-destination", log_destination, archive_in);
parseAppsecJSONKey<string>("name", name, archive_in);
}
const AppsecTriggerAccessControlLogging &
AppsecTriggerSpec::getAppsecTriggerAccessControlLogging() const
{
return access_control_logging;
}
const string &
AppsecTriggerSpec::getName() const
{
return name;
}
const AppsecTriggerAdditionalSuspiciousEventsLogging &
AppsecTriggerSpec::getAppsecTriggerAdditionalSuspiciousEventsLogging() const
{
return additional_suspicious_events_logging;
}
const AppsecTriggerLogging &
AppsecTriggerSpec::getAppsecTriggerLogging() const
{
return appsec_logging;
}
const AppsecTriggerExtendedLogging &
AppsecTriggerSpec::getAppsecTriggerExtendedLogging() const
{
return extended_logging;
}
const AppsecTriggerLogDestination &
AppsecTriggerSpec::getAppsecTriggerLogDestination() const
{
return log_destination;
}
void
TriggersWrapper::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("rulebase", triggers_rulebase)
);
}
// LCOV_EXCL_STOP

View File

@@ -0,0 +1,125 @@
#include "policy_maker_utils.h"
using namespace std;
USE_DEBUG_FLAG(D_K8S_POLICY);
// LCOV_EXCL_START Reason: no test exist
void
TrustedSourcesSpec::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading trusted sources spec";
parseAppsecJSONKey<int>("minNumOfSources", min_num_of_sources, archive_in, 3);
parseAppsecJSONKey<vector<string>>("sourcesIdentifiers", sources_identifiers, archive_in);
parseAppsecJSONKey<string>("name", name, archive_in);
}
int
TrustedSourcesSpec::getMinNumOfSources() const
{
return min_num_of_sources;
}
const vector<string> &
TrustedSourcesSpec::getSourcesIdentifiers() const
{
return sources_identifiers;
}
const string &
TrustedSourcesSpec::getName() const
{
return name;
}
void
SourcesIdentifiers::save(cereal::JSONOutputArchive &out_ar) const
{
out_ar(
cereal::make_nvp("sourceIdentifier", source_identifier),
cereal::make_nvp("value", value)
);
}
const string &
SourcesIdentifiers::getSourceIdent() const
{
return source_identifier;
}
void
SourceIdentifierSpec::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading trusted sources spec";
parseAppsecJSONKey<string>("sourceIdentifier", source_identifier, archive_in);
parseAppsecJSONKey<vector<string>>("value", value, archive_in);
}
const string &
SourceIdentifierSpec::getSourceIdentifier() const
{
return source_identifier;
}
const vector<string> &
SourceIdentifierSpec::getValues() const
{
return value;
}
void
SourceIdentifierSpecWrapper::load(cereal::JSONInputArchive &archive_in)
{
dbgTrace(D_K8S_POLICY) << "Loading Source Identifier Spec Wrapper";
parseAppsecJSONKey<vector<SourceIdentifierSpec>>("identifiers", identifiers, archive_in);
parseAppsecJSONKey<string>("name", name, archive_in);
}
const string &
SourceIdentifierSpecWrapper::getName() const
{
return name;
}
const vector<SourceIdentifierSpec> &
SourceIdentifierSpecWrapper::getIdentifiers() const
{
return identifiers;
}
AppSecTrustedSources::AppSecTrustedSources(
const string &_name,
int _num_of_sources,
const vector<SourcesIdentifiers> &_sources_identifiers)
:
name(_name),
num_of_sources(_num_of_sources),
sources_identifiers(_sources_identifiers)
{
try {
id = to_string(boost::uuids::random_generator()());
} catch (const boost::uuids::entropy_error &e) {
dbgWarning(D_K8S_POLICY) << "Failed to generate Trusted Sources ID. Error: " << e.what();
}
}
void
AppSecTrustedSources::save(cereal::JSONOutputArchive &out_ar) const
{
string parameter_type = "TrustedSource";
out_ar(
cereal::make_nvp("id", id),
cereal::make_nvp("name", name),
cereal::make_nvp("numOfSources", num_of_sources),
cereal::make_nvp("sourcesIdentifiers", sources_identifiers),
cereal::make_nvp("parameterType", parameter_type)
);
}
const vector<SourcesIdentifiers> &
AppSecTrustedSources::getSourcesIdentifiers() const
{
return sources_identifiers;
}
// LCOV_EXCL_STOP

View File

@@ -389,17 +389,17 @@ public:
void
writeStatusToFile()
{
auto orchestrations_status_path = getConfigurationWithDefault<string>(
filesystem_prefix + "/conf/orchestrations_status.json",
auto orchestration_status_path = getConfigurationWithDefault<string>(
filesystem_prefix + "/conf/orchestration_status.json",
"orchestration",
"Orchestration status path"
);
auto write_result =
orchestration_tools->objectToJsonFile<Status>(status, orchestrations_status_path);
orchestration_tools->objectToJsonFile<Status>(status, orchestration_status_path);
if (!write_result) {
dbgWarning(D_ORCHESTRATOR) << "Failed to write Orchestration status. File: " << orchestrations_status_path;
dbgWarning(D_ORCHESTRATOR) << "Failed to write Orchestration status. File: " << orchestration_status_path;
}
dbgTrace(D_ORCHESTRATOR) << "Orchestration status file has been updated. File: " << orchestrations_status_path;
dbgTrace(D_ORCHESTRATOR) << "Orchestration status file has been updated. File: " << orchestration_status_path;
}
void
@@ -440,10 +440,10 @@ public:
{
time = Singleton::Consume<I_TimeGet>::by<OrchestrationStatus>();
orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<OrchestrationStatus>();
filesystem_prefix = getFilesystemPathConfig();
initValues();
loadFromFile();
filesystem_prefix = getFilesystemPathConfig();
dbgTrace(D_ORCHESTRATOR)
<< "Initializing Orchestration status, file system path prefix: "
<< filesystem_prefix;
@@ -473,13 +473,13 @@ private:
void
loadFromFile()
{
auto orchestrations_status_path = getConfigurationWithDefault<string>(
filesystem_prefix + "/conf/orchestrations_status.json",
auto orchestration_status_path = getConfigurationWithDefault<string>(
filesystem_prefix + "/conf/orchestration_status.json",
"orchestration",
"Orchestration status path"
);
Maybe<Status> maybe_status_file =
orchestration_tools->jsonFileToObject<Status>(orchestrations_status_path);
orchestration_tools->jsonFileToObject<Status>(orchestration_status_path);
if (!maybe_status_file.ok()) {
dbgTrace(D_ORCHESTRATOR)
<< "Failed to load Orchestration status, start with clear status."
@@ -489,7 +489,7 @@ private:
status = maybe_status_file.unpack();
dbgInfo(D_ORCHESTRATOR) << "Orchestration status loaded from file." << " File: " << orchestrations_status_path;
dbgInfo(D_ORCHESTRATOR) << "Orchestration status loaded from file." << " File: " << orchestration_status_path;
}
const string & getLastUpdateAttempt() const override { return status.getLastUpdateAttempt(); }

View File

@@ -124,6 +124,29 @@ private:
map<string, HealthCheckStatus> field_types_status;
};
class setAgentUninstall : public ServerRest
{
public:
void
doCall() override
{
dbgTrace(D_ORCHESTRATOR) << "Send 'agent uninstall process started' log to fog";
setConfiguration(false, "Logging", "Enable bulk of logs");
LogGen log (
"Agent started uninstall process",
Audience::INTERNAL,
Severity::INFO,
Priority::URGENT,
LogField("issuingEngine", "agentUninstallProvider"),
Tags::ORCHESTRATOR
);
notify_uninstall_to_fog = true;
}
private:
S2C_PARAM(bool, notify_uninstall_to_fog);
};
class OrchestrationComp::Impl
{
public:
@@ -144,6 +167,7 @@ public:
auto rest = Singleton::Consume<I_RestApi>::by<OrchestrationComp>();
rest->addRestCall<getStatusRest>(RestAction::SHOW, "orchestration-status");
rest->addRestCall<AddProxyRest>(RestAction::ADD, "proxy");
rest->addRestCall<setAgentUninstall>(RestAction::SET, "agent-uninstall");
// Main loop of the Orchestration.
Singleton::Consume<I_MainLoop>::by<OrchestrationComp>()->addOneTimeRoutine(
I_MainLoop::RoutineType::RealTime,
@@ -982,7 +1006,7 @@ private:
const Maybe<vector<CheckUpdateRequest::Tenants>> &updated_policy_tenants,
const vector<string> &new_data_files)
{
dbgFlow(D_ORCHESTRATOR) << "Hanlding virtual files";
dbgFlow(D_ORCHESTRATOR) << "Handling virtual files";
if (!updated_policy_tenants.ok()) return;
// Sorting files by tenant id;
@@ -1053,26 +1077,31 @@ private:
}
}
for (const auto downloade_files: sorted_files) {
auto files = downloade_files.second;
for (auto it = sorted_files.begin(); it != sorted_files.end(); it++) {
const auto &downloaded_files = *it;
auto files = downloaded_files.second;
string policy_file = files[0];
string setting_file = "";
if (files.size() > 1) {
setting_file = files[1];
auto handled_settings = updateSettingsFile(
setting_file,
downloade_files.first.getTenantId(),
downloade_files.first.getPfofileId()
downloaded_files.first.getTenantId(),
downloaded_files.first.getProfileId()
);
if (handled_settings.ok()) setting_file = *handled_settings;
}
bool last_iteration = false;
if (next(it) == sorted_files.end()) last_iteration = true;
Singleton::Consume<I_ServiceController>::by<OrchestrationComp>()->updateServiceConfiguration(
policy_file,
setting_file,
new_data_files,
downloade_files.first.getTenantId(),
downloade_files.first.getPfofileId()
downloaded_files.first.getTenantId(),
downloaded_files.first.getProfileId(),
last_iteration
);
}
}
@@ -1087,9 +1116,9 @@ private:
"Conf dir"
) + (tenant_id != "" ? "tenant_" + tenant_id + "_profile_" + profile_id + "_" : "");
dbgTrace(D_ORCHESTRATOR) << "The settings directory is " << conf_dir;
auto orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<OrchestrationComp>();
string settings_file_path = conf_dir + "settings.json";
dbgTrace(D_ORCHESTRATOR) << "The settings directory is " << settings_file_path;
if (!orchestration_tools->copyFile(new_settings_file, settings_file_path)) {
dbgWarning(D_ORCHESTRATOR) << "Failed to update the settings.";
return genError("Failed to update the settings");
@@ -1278,7 +1307,7 @@ private:
int sleep_interval = policy.getErrorSleepInterval();
Maybe<void> start_state(genError("Not running yet."));
while (!(start_state = start()).ok()) {
dbgError(D_ORCHESTRATOR) << "Failed to start the Orchestration. Error: " << start_state.getErr();
dbgDebug(D_ORCHESTRATOR) << "Orchestration not started yet. Status: " << start_state.getErr();
health_check_status_listener.setStatus(
HealthCheckStatus::UNHEALTHY,
OrchestrationStatusFieldType::REGISTRATION,

View File

@@ -65,7 +65,12 @@ public:
EXPECT_CALL(rest, mockRestCall(RestAction::SHOW, "orchestration-status", _)).WillOnce(
WithArg<2>(Invoke(this, &OrchestrationMultitenancyTest::setRestStatus)));
EXPECT_CALL(
rest,
mockRestCall(RestAction::SET, "agent-uninstall", _)
).WillOnce(Return(true));
doEncrypt();
orchestration_comp.init();
}
@@ -417,7 +422,8 @@ TEST_F(OrchestrationMultitenancyTest, handle_virtual_resource)
"/etc/cp/conf/settings.json",
expected_data_types,
"",
""
"",
false
)
).WillOnce(Return(true));
@@ -428,7 +434,8 @@ TEST_F(OrchestrationMultitenancyTest, handle_virtual_resource)
"/etc/cp/conf/tenant_1236_profile_2611_settings.json",
expected_data_types,
"1236",
"2611"
"2611",
false
)
).WillOnce(Return(true));
@@ -439,7 +446,8 @@ TEST_F(OrchestrationMultitenancyTest, handle_virtual_resource)
"/etc/cp/conf/tenant_1235_profile_2311_settings.json",
expected_data_types,
"1235",
"2311"
"2311",
true
)
).WillOnce(Return(true));

View File

@@ -79,6 +79,11 @@ public:
WithArg<2>(Invoke(this, &OrchestrationTest::setRestStatus))
);
EXPECT_CALL(
rest,
mockRestCall(RestAction::SET, "agent-uninstall", _)
).WillOnce(WithArg<2>(Invoke(this, &OrchestrationTest::restHandlerAgentUninstall)));
string message_body;
EXPECT_CALL(mock_message, mockSendPersistentMessage(
false,
@@ -101,6 +106,12 @@ public:
return true;
}
bool
restHandlerAgentUninstall(const unique_ptr<RestInit> &p)
{
agent_uninstall = p->getRest();
return true;
}
void
doEncrypt()
@@ -249,6 +260,7 @@ public:
}
unique_ptr<ServerRest> rest_handler;
unique_ptr<ServerRest> agent_uninstall;
unique_ptr<ServerRest> declare_variable;
StrictMock<MockMainLoop> mock_ml;
NiceMock<MockTimeGet> mock_time_get;
@@ -295,8 +307,36 @@ private:
I_MainLoop::Routine status_routine;
};
TEST_F(OrchestrationTest, doNothing)
TEST_F(OrchestrationTest, testAgentUninstallRest)
{
EXPECT_CALL(
rest,
mockRestCall(RestAction::ADD, "proxy", _)
).WillOnce(WithArg<2>(Invoke(this, &OrchestrationTest::restHandler)));
init();
Report report;
EXPECT_CALL(mock_log, sendLog(_)).WillRepeatedly(SaveArg<0>(&report));
stringstream ss("{}");
Maybe<string> maybe_res = agent_uninstall->performRestCall(ss);
EXPECT_TRUE(maybe_res.ok());
EXPECT_EQ(maybe_res.unpack(),
"{\n"
" \"notify_uninstall_to_fog\": true\n"
"}"
);
stringstream report_ss;
{
cereal::JSONOutputArchive ar(report_ss);
report.serialize(ar);
}
string report_str = report_ss.str();
EXPECT_THAT(report_str, HasSubstr("\"eventName\": \"Agent started uninstall process\""));
EXPECT_THAT(report_str, HasSubstr("\"issuingEngine\": \"agentUninstallProvider\""));
}
TEST_F(OrchestrationTest, register_config)
@@ -530,12 +570,12 @@ TEST_F(OrchestrationTest, orchestrationPolicyUpdate)
vector<string> expected_data_types = {};
EXPECT_CALL(
mock_service_controller,
updateServiceConfiguration(policy_file_path, setting_file_path, expected_data_types, "", "")
updateServiceConfiguration(policy_file_path, setting_file_path, expected_data_types, "", "", _)
).WillOnce(Return(true));
EXPECT_CALL(
mock_service_controller,
updateServiceConfiguration(new_policy_path, "", expected_data_types, "", "")
updateServiceConfiguration(new_policy_path, "", expected_data_types, "", "", _)
).WillOnce(Return(true));
EXPECT_CALL(
@@ -633,7 +673,7 @@ TEST_F(OrchestrationTest, startOrchestrationPoliceWithFailures)
vector<string> expected_data_types = {};
EXPECT_CALL(
mock_service_controller,
updateServiceConfiguration(policy_file_path, setting_file_path, expected_data_types, "", "")
updateServiceConfiguration(policy_file_path, setting_file_path, expected_data_types, "", "", _)
).Times(2).WillRepeatedly(Return(true));
EXPECT_CALL(mock_message, setActiveFog(host_address, 443, true, MessageTypeTag::GENERIC)).WillOnce(Return(true));
@@ -753,7 +793,7 @@ TEST_F(OrchestrationTest, loadOrchestrationPolicyFromBackup)
vector<string> expected_data_types = {};
EXPECT_CALL(
mock_service_controller,
updateServiceConfiguration(policy_file_path, setting_file_path, expected_data_types, "", "")
updateServiceConfiguration(policy_file_path, setting_file_path, expected_data_types, "", "", _)
).WillOnce(Return(true));
EXPECT_CALL(mock_orchestration_tools, doesFileExist(orchestration_policy_file_path)).WillOnce(Return(true));
@@ -887,7 +927,7 @@ TEST_F(OrchestrationTest, manifestUpdate)
vector<string> expected_data_types = {};
EXPECT_CALL(
mock_service_controller,
updateServiceConfiguration(policy_file_path, setting_file_path, expected_data_types, "", "")
updateServiceConfiguration(policy_file_path, setting_file_path, expected_data_types, "", "", _)
).WillOnce(Return(true));
EXPECT_CALL(mock_orchestration_tools, doesFileExist(orchestration_policy_file_path)).WillOnce(Return(true));
@@ -1037,7 +1077,7 @@ TEST_F(OrchestrationTest, getBadPolicyUpdate)
vector<string> expected_data_types = {};
EXPECT_CALL(
mock_service_controller,
updateServiceConfiguration(policy_file_path, setting_file_path, expected_data_types, "", "")
updateServiceConfiguration(policy_file_path, setting_file_path, expected_data_types, "", "", _)
).Times(2).WillRepeatedly(Return(true));
EXPECT_CALL(mock_orchestration_tools, doesFileExist(orchestration_policy_file_path)).WillOnce(Return(true));
@@ -1118,7 +1158,7 @@ TEST_F(OrchestrationTest, getBadPolicyUpdate)
EXPECT_CALL(
mock_service_controller,
updateServiceConfiguration(string("policy path"), "", expected_data_types, "", "")).WillOnce(Return(false)
updateServiceConfiguration(string("policy path"), "", expected_data_types, "", "", _)).WillOnce(Return(false)
);
EXPECT_CALL(mock_ml, yield(A<chrono::microseconds>()))
@@ -1183,7 +1223,7 @@ TEST_F(OrchestrationTest, failedDownloadSettings)
vector<string> expected_data_types = {};
EXPECT_CALL(
mock_service_controller,
updateServiceConfiguration(policy_file_path, setting_file_path, expected_data_types, "", "")
updateServiceConfiguration(policy_file_path, setting_file_path, expected_data_types, "", "", _)
).WillOnce(Return(true));
EXPECT_CALL(mock_orchestration_tools, doesFileExist(orchestration_policy_file_path)).WillOnce(Return(true));
@@ -1401,7 +1441,7 @@ TEST_P(OrchestrationTest, orchestrationFirstRun)
vector<string> expected_data_types = {};
EXPECT_CALL(
mock_service_controller,
updateServiceConfiguration(policy_file_path, setting_file_path, expected_data_types, "", "")
updateServiceConfiguration(policy_file_path, setting_file_path, expected_data_types, "", "", _)
).WillOnce(Return(true));
EXPECT_CALL(mock_ml, yield(A<chrono::microseconds>()))
@@ -1582,13 +1622,13 @@ TEST_F(OrchestrationTest, dataUpdate)
vector<string> expected_empty_data_types = {};
ExpectationSet expectation_set = EXPECT_CALL(
mock_service_controller,
updateServiceConfiguration(policy_file_path, setting_file_path, expected_empty_data_types, "", "")
updateServiceConfiguration(policy_file_path, setting_file_path, expected_empty_data_types, "", "", _)
).WillOnce(Return(true));
vector<string> expected_ips_data_types = { "ips" };
EXPECT_CALL(
mock_service_controller,
updateServiceConfiguration("", "", expected_ips_data_types, "", "")
updateServiceConfiguration("", "", expected_ips_data_types, "", "", _)
).After(expectation_set).WillOnce(Return(true));
EXPECT_CALL(mock_orchestration_tools, doesDirectoryExist("/etc/cp/conf/data")).WillOnce(Return(true));

View File

@@ -272,7 +272,8 @@ public:
const string &new_settings_path,
const vector<string> &new_data_files,
const string &tenant_id,
const string &profile_id
const string &profile_id,
const bool last_iteration
) override;
bool isServiceInstalled(const string &service_name) override;
@@ -325,6 +326,7 @@ private:
map<int, string> services_reconf_names;
map<int, string> services_reconf_ids;
string filesystem_prefix;
bool is_multi_tenant_env = false;
};
class GetServicesPorts : public ServerRest
@@ -412,6 +414,11 @@ ServiceController::Impl::init()
filesystem_prefix = getFilesystemPathConfig();
loadRegisteredServicesFromFile();
auto agent_type = getSetting<string>("agentType");
if (agent_type.ok() && (*agent_type == "CloudNative" || *agent_type == "VirtualNSaaS")) {
is_multi_tenant_env = true;
}
}
void
@@ -592,7 +599,8 @@ ServiceController::Impl::updateServiceConfiguration(
const string &new_settings_path,
const vector<string> &new_data_files,
const string &tenant_id,
const string &profile_id)
const string &profile_id,
const bool last_iteration)
{
dbgFlow(D_ORCHESTRATOR)
<< "new_policy_path: "
@@ -746,7 +754,10 @@ ServiceController::Impl::updateServiceConfiguration(
}
}
was_policy_updated &= sendSignalForServices(nano_services_to_update, version_value);
// In a multi-tenant env, we send the signal to the services only on the last iteration
was_policy_updated &= (is_multi_tenant_env && !last_iteration) ?
true :
sendSignalForServices(nano_services_to_update, version_value);
dbgTrace(D_ORCHESTRATOR) << "was_policy_updated: " << (was_policy_updated ? "true" : "false");
@@ -965,6 +976,11 @@ ServiceController::Impl::updateReconfStatus(int id, ReconfStatus status)
dbgError(D_ORCHESTRATOR) << "Service reconfiguration monitor received illegal id :" << id;
return;
}
dbgTrace(D_ORCHESTRATOR)
<< "Updating reconf status for reconfiguration ID "
<< id
<< ". Status: "
<< static_cast<int>(status);
services_reconf_status[id] = status;
}
@@ -975,6 +991,15 @@ ServiceController::Impl::startReconfStatus(
const string &service_name,
const string &service_id)
{
dbgTrace(D_ORCHESTRATOR)
<< "Starting reconf status. Configuration ID: "
<< id
<< ", service name: "
<< service_name
<< ", service ID: "
<< service_id
<< ", status: "
<< static_cast<int>(status);
services_reconf_status.emplace(id, status);
services_reconf_names.emplace(id, service_name);
services_reconf_ids.emplace(id, service_id);

View File

@@ -122,9 +122,9 @@ LocalCommunication::getUpdate(CheckUpdateRequest &request)
}
Maybe<string>
LocalCommunication::downloadAttributeFile(const GetResourceFile &resourse_file)
LocalCommunication::downloadAttributeFile(const GetResourceFile &resource_file)
{
auto file_name = resourse_file.getFileName();
auto file_name = resource_file.getFileName();
I_OrchestrationTools *orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<LocalCommunication>();
if (file_name.compare("policy") == 0) {
@@ -163,8 +163,8 @@ LocalCommunication::downloadAttributeFile(const GetResourceFile &resourse_file)
));
}
dbgError(D_ORCHESTRATOR) << "Unknown resourse file name " << file_name;
return genError("Failed to detect resourse file name " + file_name);
dbgError(D_ORCHESTRATOR) << "Unknown resource file name " << file_name;
return genError("Failed to detect resource file name " + file_name);
}
void