mirror of
https://github.com/openappsec/openappsec.git
synced 2025-11-16 01:12:18 +03:00
Compare commits
22 Commits
changing_s
...
Sep_24_202
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c10a12f6f | ||
|
|
e9f6ebd02b | ||
|
|
433c7c2d91 | ||
|
|
582791e37a | ||
|
|
a4d1fb6f7f | ||
|
|
dfbfdca1a9 | ||
|
|
36f511f449 | ||
|
|
f91f283b77 | ||
|
|
7c762e97a3 | ||
|
|
aaa1fbe8ed | ||
|
|
67e68c84c3 | ||
|
|
149a7305b7 | ||
|
|
ea20a51689 | ||
|
|
19f2383ae2 | ||
|
|
4038c18bda | ||
|
|
a9b6d2e715 | ||
|
|
81c75495cc | ||
|
|
5505022f47 | ||
|
|
b25fd8def5 | ||
|
|
702c1184ea | ||
|
|
b3cfd7e9d8 | ||
|
|
e36b990161 |
134
README.md
134
README.md
@@ -18,25 +18,41 @@ Every request to the application goes through two phases:
|
||||
|
||||
2. If the request is identified as a valid and legitimate request the request is allowed, and forwarded to your application. If, however, the request is considered suspicious or high risk, it then gets evaluated by the unsupervised model, which was trained in your specific environment. This model uses information such as the URL and the users involved to create a final confidence score that determines whether the request should be allowed or blocked.
|
||||
|
||||
## Machine Learning models
|
||||

|
||||
|
||||
open-appsec uses two models:
|
||||
|
||||
open-appsec uses two machine learning models:
|
||||
|
||||
1. A supervised model that was trained offline based on millions of requests, both malicious and benign.
|
||||
|
||||
* A basic model is provided as part of this repository. It is recommended for use in Monitor-Only and Test environments.
|
||||
* An advanced model which is more accurate and recommended for Production use can be downloaded from the [open-appsec portal](https://my.openappsec.io)->User Menu->Download advanced ML model. This model updates from time to time and you will get an email when these updates happen.
|
||||
* A **basic model** is provided as part of this repository. It is recommended for use in Monitor-Only and Test environments.
|
||||
* An **advanced model** which is more accurate and **recommended for Production** use can be downloaded from the [open-appsec portal](https://my.openappsec.io)->User Menu->Download advanced ML model. This model updates from time to time and you will get an email when these updates happen.
|
||||
|
||||
2. An unsupervised model that is being built in real time in the protected environment. This model uses traffic patterns specific to the environment.
|
||||
|
||||
|
||||
# Management
|
||||
|
||||
open-appsec can be managed using multiple methods:
|
||||
* [Declarative configuration files](https://docs.openappsec.io/getting-started/getting-started)
|
||||
* [Kubernetes Helm Charts and annotations](https://docs.openappsec.io/getting-started/getting-started)
|
||||
* [Using SaaS Web Management](https://docs.openappsec.io/getting-started/using-the-web-ui-saas)
|
||||
|
||||
open-appsec Web UI:
|
||||

|
||||
|
||||
|
||||
## Deployment Playgrounds (Virtual labs)
|
||||
You can experiment with open-appsec using [Playgrounds](https://www.openappsec.io/playground)
|
||||
|
||||

|
||||
|
||||
# Resources
|
||||
* [Project Website](https://openappsec.io)
|
||||
* [Offical Documentation](https://docs.openappsec.io/)
|
||||
* [Video Tutorials](https://www.openappsec.io/tutorials)
|
||||
* [Live Playgrounds](https://www.openappsec.io/playground)
|
||||
|
||||
|
||||
# open-appsec Installation
|
||||
# Installation
|
||||
|
||||
For Kubernetes (NGINX Ingress) using the installer:
|
||||
|
||||
@@ -63,3 +79,107 @@ $ install-cp-nano-attachment-registration-manager.sh --install
|
||||
```
|
||||
You can add the ```--token <token>``` and ```--email <email address>``` options to the first command, to get a token follow [documentation](https://docs.openappsec.io/getting-started/using-the-web-ui-saas/connect-deployed-agents-to-saas-management-k8s-and-linux).
|
||||
|
||||
For Docker: follow [documentation](https://docs.openappsec.io/getting-started/start-with-docker)
|
||||
|
||||
For more information read the [documentation](https://docs.openappsec.io/) or follow the [video tutorials](https://www.openappsec.io/tutorials).
|
||||
|
||||
# Repositories
|
||||
|
||||
open-appsec GitHub includes four main repositories:
|
||||
|
||||
* [openappsec/openappsec](https://github.com/openappsec/openappsec) the main code and logic of open-appsec. Developed in C++.
|
||||
* [openappsec/attachment](https://github.com/openappsec/attachment) connects between processes that provide HTTP data (e.g NGINX) and the open-appsec Agent security logic. Developed in C.
|
||||
* [openappsec/smartsync](https://github.com/openappsec/smartsync) in charge of correlating learning data from multiple agent instances and delivering a unified learning model for each asset. Developed in Golang.
|
||||
* [openappsec/smartsync-shared-files](https://github.com/openappsec/smartsync-shared-files) interface to physical storage used by smartsync service for storing learning data. Developed in Golang.
|
||||
|
||||
# Compilation instructions
|
||||
|
||||
## Installing external dependencies
|
||||
|
||||
Before compiling the services, you'll need to ensure the latest development versions of the following libraries:
|
||||
* Boost
|
||||
* OpenSSL
|
||||
* PCRE2
|
||||
* libxml2
|
||||
* GTest
|
||||
* GMock
|
||||
* cURL
|
||||
* Hiredis
|
||||
|
||||
An example of installing the packages on Alpine:
|
||||
|
||||
```bash
|
||||
$ apk update
|
||||
$ apk add boost-dev openssl-dev pcre2-dev libxml2-dev gtest-dev curl-dev hiredis-dev
|
||||
```
|
||||
|
||||
## Compiling and packaging the agent code
|
||||
|
||||
1. Clone this repository
|
||||
2. Run CMake command
|
||||
3. Run make install command
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/openappsec/openappsec.git
|
||||
$ cd openappsec/
|
||||
$ cmake -DCMAKE_INSTALL_PREFIX=build_out .
|
||||
$ make install
|
||||
$ make package
|
||||
```
|
||||
|
||||
## Placing the agent code inside an Alpine docker image
|
||||
|
||||
Once the agent code has been compiled and packaged, an Alpine image running it can be created. This requires permissions to execute the `docker` command.
|
||||
|
||||
```bash
|
||||
$ make docker
|
||||
```
|
||||
|
||||
This will create a local image for your docker called `agent-docker`.
|
||||
|
||||
## Deployment of the agent docker image as a container
|
||||
|
||||
To run a Nano-Agent as a container the following steps are required:
|
||||
|
||||
1. If you are using a container management system / plan on deploying the container using your CI, add the agent docker image to an accessible registry.
|
||||
2. If you are planning to manage the agent using the open-appsec UI, then make sure to obtain an agent token from the Management Portal and Enforce.
|
||||
3. Run the agent with the following command (where -e https_proxy parameter is optional):
|
||||
|
||||
`docker run -d --name=agent-container --ipc=host -v=<path to persistent location for agent config>:/etc/cp/conf -v=<path to persistent location for agent data files>:/etc/cp/data -v=<path to persistent location for agent debugs and logs>:/var/log/nano_agent -e https_proxy=<user:password@Proxy address:port> -it <agent-image> /cp-nano-agent [--token <token> | --standalone]`
|
||||
|
||||
Example:
|
||||
```bash
|
||||
$ docker run -d --name=agent-container --ipc=host -v=/home/admin/agent/conf:/etc/cp/conf -v=/home/admin/agent/data:/etc/cp/data -v=/home/admin/agent/logs:/var/log/nano_agent –e https_proxy=user:password@1.2.3.4:8080 -it agent-docker /cp-nano-agent --standalone
|
||||
$ docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
1e67f2abbfd4 agent-docker "/cp-nano-agent --hybrid-mode" 1 minute ago Up 1 minute agent-container
|
||||
```
|
||||
|
||||
Note that you are not required to use a token from the Management Portal if you are managing your security policy locally. However, you are required to use the --standalone flag in such cases. In addition, the volumes in the command are mandatory only if you wish to have persistency upon restart/upgrade/crash of the agent and its re-execution.
|
||||
Lastly, --ipc=host argument is mandatory in order for the agent to have access to shared memory with a protected attachment (NGINX server).
|
||||
|
||||
4. Create or replace the NGINX container using the [Attachment Repository](https://github.com/openappsec/attachment).
|
||||
|
||||
This will run a docker container using the agent docker image.
|
||||
|
||||
# Contributing
|
||||
We welcome everyone that wishes to share their knowledge and expertise to enhance and expand the project.
|
||||
|
||||
Please see the [Contributing Guidelines](https://github.com/openappsec/openappsec/blob/main/CONTRIBUTING.md).
|
||||
|
||||
# Security
|
||||
|
||||
### Security Audit
|
||||
open-appsec code was audited by an independent third party in September-October 2022.
|
||||
See the [full report](https://github.com/openappsec/openappsec/blob/main/LEXFO-CHP20221014-Report-Code_audit-OPEN-APPSEC-v1.2.pdf).
|
||||
|
||||
### Reporting security vulnerabilities
|
||||
If you've found a vulnerability or a potential vulnerability in open-appsec please let us know at securityalert@openappsec.io. We'll send a confirmation email to acknowledge your report within 24 hours, and we'll send an additional email when we've identified the issue positively or negatively.
|
||||
|
||||
|
||||
# License
|
||||
open-appsec is open source and available under Apache 2.0 license.
|
||||
|
||||
The basic ML model is open source and available under Apache 2.0 license.
|
||||
|
||||
The advanced ML model is open source and available under Machine Learning Model license, available upon download in the tar file.
|
||||
|
||||
@@ -58,6 +58,10 @@ fi
|
||||
|
||||
/nano-service-installers/$ORCHESTRATION_INSTALLATION_SCRIPT --install $orchestration_service_installation_flags
|
||||
|
||||
if [ -f /var/run/secrets/kubernetes.io/serviceaccount/token ]; then
|
||||
/etc/cp/orchestration/k8s-check-update-listener.sh &
|
||||
fi
|
||||
|
||||
/nano-service-installers/$ATTACHMENT_REGISTRATION_SERVICE --install
|
||||
/nano-service-installers/$HTTP_TRANSACTION_HANDLER_SERVICE --install
|
||||
|
||||
|
||||
@@ -1762,8 +1762,8 @@ private:
|
||||
&did_fail_on_purpose
|
||||
)) {
|
||||
return genError(
|
||||
"Failed to read the attachment's User ID or Group ID" +
|
||||
did_fail_on_purpose ? "[Intentional Failure]" : ""
|
||||
string("Failed to read the attachment's User ID or Group ID") +
|
||||
(did_fail_on_purpose ? "[Intentional Failure]" : "")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
#include "environment/evaluator_templates.h"
|
||||
#include "i_environment.h"
|
||||
#include "singleton.h"
|
||||
#include "debug.h"
|
||||
|
||||
USE_DEBUG_FLAG(D_RULEBASE_CONFIG);
|
||||
|
||||
using namespace std;
|
||||
using namespace EnvironmentHelper;
|
||||
@@ -55,6 +58,51 @@ EqualHost::evalVariable() const
|
||||
return lower_host_ctx == lower_host;
|
||||
}
|
||||
|
||||
WildcardHost::WildcardHost(const vector<string> ¶ms)
|
||||
{
|
||||
if (params.size() != 1) reportWrongNumberOfParams("WildcardHost", params.size(), 1, 1);
|
||||
host = params[0];
|
||||
}
|
||||
|
||||
Maybe<bool, Context::Error>
|
||||
WildcardHost::evalVariable() const
|
||||
{
|
||||
I_Environment *env = Singleton::Consume<I_Environment>::by<WildcardHost>();
|
||||
auto host_ctx = env->get<string>(HttpTransactionData::host_name_ctx);
|
||||
|
||||
if (!host_ctx.ok())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string lower_host_ctx = host_ctx.unpack();
|
||||
transform(lower_host_ctx.begin(), lower_host_ctx.end(), lower_host_ctx.begin(), ::tolower);
|
||||
|
||||
dbgTrace(D_RULEBASE_CONFIG) << "found host in current context: " << lower_host_ctx;
|
||||
|
||||
size_t pos = lower_host_ctx.find_first_of(".");
|
||||
if (pos == string::npos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
lower_host_ctx = "*" + lower_host_ctx.substr(pos, lower_host_ctx.length());
|
||||
|
||||
string lower_host = host;
|
||||
transform(lower_host.begin(), lower_host.end(), lower_host.begin(), ::tolower);
|
||||
|
||||
dbgTrace(D_RULEBASE_CONFIG)
|
||||
<< "trying to match host context with its corresponding wildcard address: "
|
||||
<< lower_host_ctx
|
||||
<< ". Matcher host: "
|
||||
<< lower_host;
|
||||
|
||||
if (lower_host_ctx == lower_host) return true;
|
||||
pos = lower_host_ctx.find_last_of(':');
|
||||
if (pos == string::npos) return false;
|
||||
lower_host_ctx = string(lower_host_ctx.data(), pos);
|
||||
return lower_host_ctx == lower_host;
|
||||
}
|
||||
|
||||
EqualListeningIP::EqualListeningIP(const vector<string> ¶ms)
|
||||
{
|
||||
if (params.size() != 1) reportWrongNumberOfParams("EqualListeningIP", params.size(), 1, 1);
|
||||
|
||||
@@ -75,6 +75,7 @@ GenericRulebase::Impl::preload()
|
||||
addMatcher<IpProtocolMatcher>();
|
||||
addMatcher<UrlMatcher>();
|
||||
addMatcher<EqualHost>();
|
||||
addMatcher<WildcardHost>();
|
||||
addMatcher<EqualListeningIP>();
|
||||
addMatcher<EqualListeningPort>();
|
||||
addMatcher<BeginWithUri>();
|
||||
|
||||
@@ -156,7 +156,7 @@ Zone::contains(const Asset &asset)
|
||||
{
|
||||
QueryRequest request;
|
||||
|
||||
for (const pair<Context::MetaDataType, string> &main_attr : asset.getAttrs()) {
|
||||
for (const auto &main_attr : asset.getAttrs()) {
|
||||
request.addCondition(Condition::EQUALS, contextKeyToString(main_attr.first), main_attr.second);
|
||||
}
|
||||
|
||||
|
||||
@@ -83,13 +83,13 @@ public:
|
||||
:
|
||||
status(raw_status)
|
||||
{
|
||||
for (const pair<string, HealthCheckStatusReply> &single_stat : descriptions) {
|
||||
for (const auto &single_stat : descriptions) {
|
||||
if (single_stat.second.getStatus() == HealthCheckStatus::HEALTHY) {
|
||||
dbgTrace(D_HEALTH_CHECK_MANAGER) << "Ignoring healthy status reply. Comp name: " << single_stat.first;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const pair<string, string> &status : single_stat.second.getExtendedStatus()) {
|
||||
for (const auto &status : single_stat.second.getExtendedStatus()) {
|
||||
errors.push_back(HealthCheckError(single_stat.first + " " + status.first, status.second));
|
||||
}
|
||||
}
|
||||
@@ -190,7 +190,7 @@ private:
|
||||
{
|
||||
general_health_aggregated_status = HealthCheckStatus::HEALTHY;
|
||||
|
||||
for (const pair<string, HealthCheckStatusReply> &reply : all_comps_health_status) {
|
||||
for (const auto &reply : all_comps_health_status) {
|
||||
HealthCheckStatus status = reply.second.getStatus();
|
||||
|
||||
dbgTrace(D_HEALTH_CHECK_MANAGER)
|
||||
|
||||
@@ -48,7 +48,7 @@ HttpManagerOpaque::getCurrVerdict() const
|
||||
|
||||
uint accepted_apps = 0;
|
||||
ngx_http_cp_verdict_e verdict = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT;
|
||||
for (const pair<string, ngx_http_cp_verdict_e> &app_verdic_pair : applications_verdicts) {
|
||||
for (const auto &app_verdic_pair : applications_verdicts) {
|
||||
switch (app_verdic_pair.second) {
|
||||
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP:
|
||||
return app_verdic_pair.second;
|
||||
|
||||
@@ -32,6 +32,19 @@ private:
|
||||
std::string host;
|
||||
};
|
||||
|
||||
class WildcardHost : public EnvironmentEvaluator<bool>, Singleton::Consume<I_Environment>
|
||||
{
|
||||
public:
|
||||
WildcardHost(const std::vector<std::string> ¶ms);
|
||||
|
||||
static std::string getName() { return "WildcardHost"; }
|
||||
|
||||
Maybe<bool, Context::Error> evalVariable() const override;
|
||||
|
||||
private:
|
||||
std::string host;
|
||||
};
|
||||
|
||||
class EqualListeningIP : public EnvironmentEvaluator<bool>, Singleton::Consume<I_Environment>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -11,52 +11,108 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// \file triggers_config.h
|
||||
/// \brief Declaration of classes WebTriggerConf and LogTriggerConf, and related functions.
|
||||
/// \author Check Point Software Technologies Ltd.
|
||||
/// \date 2022
|
||||
|
||||
#ifndef __TRIGGERS_CONFIG_H__
|
||||
#define __TRIGGERS_CONFIG_H__
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "environment/evaluator_templates.h"
|
||||
#include "cereal/archives/json.hpp"
|
||||
#include "cereal/types/string.hpp"
|
||||
#include "cereal/types/vector.hpp"
|
||||
#include "cereal/archives/json.hpp"
|
||||
#include "config.h"
|
||||
#include "environment/evaluator_templates.h"
|
||||
#include "generic_rulebase_utils.h"
|
||||
#include "i_environment.h"
|
||||
#include "i_logging.h"
|
||||
#include "singleton.h"
|
||||
#include "maybe_res.h"
|
||||
#include "config.h"
|
||||
#include "log_generator.h"
|
||||
#include "generic_rulebase_utils.h"
|
||||
#include "maybe_res.h"
|
||||
#include "singleton.h"
|
||||
|
||||
/// \class WebTriggerConf
|
||||
/// \brief Represents the configuration for a web trigger.
|
||||
class WebTriggerConf
|
||||
{
|
||||
public:
|
||||
/// \brief Default constructor for WebTriggerConf.
|
||||
WebTriggerConf();
|
||||
|
||||
/// \brief Constructor for WebTriggerConf.
|
||||
/// \param title The title of the trigger.
|
||||
/// \param body The body of the trigger.
|
||||
/// \param code The response code for the trigger.
|
||||
WebTriggerConf(const std::string &title, const std::string &body, uint code);
|
||||
|
||||
/// \brief Preload function to register expected configuration.
|
||||
static void
|
||||
preload()
|
||||
{
|
||||
registerExpectedConfiguration<WebTriggerConf>("rulebase", "webUserResponse");
|
||||
}
|
||||
|
||||
/// \brief Load function to deserialize configuration from JSONInputArchive.
|
||||
/// \param archive_in The JSON input archive.
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
/// \brief Equality operator for WebTriggerConf.
|
||||
/// \param other The WebTriggerConf to compare.
|
||||
/// \return True if the two WebTriggerConf objects are equal, otherwise false.
|
||||
bool operator==(const WebTriggerConf &other) const;
|
||||
|
||||
uint getResponseCode() const { return response_code; }
|
||||
/// \brief Get the response code for the trigger.
|
||||
/// \return The response code.
|
||||
uint
|
||||
getResponseCode() const
|
||||
{
|
||||
return response_code;
|
||||
}
|
||||
|
||||
const std::string & getResponseTitle() const { return response_title; }
|
||||
/// \brief Get the response title for the trigger.
|
||||
/// \return The response title.
|
||||
const std::string &
|
||||
getResponseTitle() const
|
||||
{
|
||||
return response_title;
|
||||
}
|
||||
|
||||
const std::string & getResponseBody() const { return response_body; }
|
||||
/// \brief Get the response body for the trigger.
|
||||
/// \return The response body.
|
||||
const std::string &
|
||||
getResponseBody() const
|
||||
{
|
||||
return response_body;
|
||||
}
|
||||
|
||||
const std::string & getDetailsLevel() const { return details_level; }
|
||||
/// \brief Get the details level for the trigger.
|
||||
/// \return The details level.
|
||||
const std::string &
|
||||
getDetailsLevel() const
|
||||
{
|
||||
return details_level;
|
||||
}
|
||||
|
||||
const std::string & getRedirectURL() const { return redirect_url; }
|
||||
/// \brief Get the redirect URL for the trigger.
|
||||
/// \return The redirect URL.
|
||||
const std::string &
|
||||
getRedirectURL() const
|
||||
{
|
||||
return redirect_url;
|
||||
}
|
||||
|
||||
bool getAddEventId() const { return add_event_id_to_header; }
|
||||
/// \brief Check if the trigger should add an event ID to the header.
|
||||
/// \return True if the trigger should add an event ID, otherwise false.
|
||||
bool
|
||||
getAddEventId() const
|
||||
{
|
||||
return add_event_id_to_header;
|
||||
}
|
||||
|
||||
/// \brief Default trigger configuration for WebTriggerConf.
|
||||
static WebTriggerConf default_trigger_conf;
|
||||
|
||||
private:
|
||||
@@ -64,17 +120,38 @@ private:
|
||||
std::string details_level;
|
||||
std::string response_body;
|
||||
std::string redirect_url;
|
||||
uint response_code;
|
||||
bool add_event_id_to_header = false;
|
||||
uint response_code;
|
||||
bool add_event_id_to_header = false;
|
||||
};
|
||||
|
||||
/// \class LogTriggerConf
|
||||
/// \brief Represents the configuration for a log trigger.
|
||||
class LogTriggerConf : Singleton::Consume<I_Logging>
|
||||
{
|
||||
public:
|
||||
enum class SecurityType { AccessControl, ThreatPrevention, Compliance, COUNT };
|
||||
enum class extendLoggingSeverity { None, High, Critical };
|
||||
/// \enum SecurityType
|
||||
/// \brief Enumerates the security types for LogTriggerConf.
|
||||
enum class SecurityType
|
||||
{
|
||||
AccessControl,
|
||||
ThreatPrevention,
|
||||
Compliance,
|
||||
COUNT
|
||||
};
|
||||
|
||||
enum class WebLogFields {
|
||||
/// \enum extendLoggingSeverity
|
||||
/// \brief Enumerates the extended logging severity for LogTriggerConf.
|
||||
enum class extendLoggingSeverity
|
||||
{
|
||||
None,
|
||||
High,
|
||||
Critical
|
||||
};
|
||||
|
||||
/// \enum WebLogFields
|
||||
/// \brief Enumerates the web log fields for LogTriggerConf.
|
||||
enum class WebLogFields
|
||||
{
|
||||
webBody,
|
||||
webHeaders,
|
||||
webRequests,
|
||||
@@ -85,17 +162,31 @@ public:
|
||||
COUNT
|
||||
};
|
||||
|
||||
/// \brief Default constructor for LogTriggerConf.
|
||||
LogTriggerConf() {}
|
||||
|
||||
/// \brief Constructor for LogTriggerConf.
|
||||
/// \param trigger_name The name of the trigger.
|
||||
/// \param log_detect Flag indicating whether to log on detect.
|
||||
/// \param log_prevent Flag indicating whether to log on prevent.
|
||||
LogTriggerConf(std::string trigger_name, bool log_detect, bool log_prevent);
|
||||
|
||||
/// \brief Preload function to register expected configuration.
|
||||
static void
|
||||
preload()
|
||||
{
|
||||
registerExpectedConfiguration<LogTriggerConf>("rulebase", "log");
|
||||
}
|
||||
|
||||
template <typename ...Tags>
|
||||
/// \brief LogGen operator for LogTriggerConf.
|
||||
/// \param title The title of the log.
|
||||
/// \param security The security type of the log.
|
||||
/// \param severity The severity of the log.
|
||||
/// \param priority The priority of the log.
|
||||
/// \param is_action_drop_or_prevent Flag indicating if the action is drop or prevent.
|
||||
/// \param tags Tags for the log.
|
||||
/// \return The LogGen object.
|
||||
template <typename... Tags>
|
||||
LogGen
|
||||
operator()(
|
||||
const std::string &title,
|
||||
@@ -103,7 +194,8 @@ public:
|
||||
ReportIS::Severity severity,
|
||||
ReportIS::Priority priority,
|
||||
bool is_action_drop_or_prevent,
|
||||
Tags ...tags) const
|
||||
Tags... tags
|
||||
) const
|
||||
{
|
||||
return LogGen(
|
||||
title,
|
||||
@@ -117,11 +209,17 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
template <typename ...Tags>
|
||||
/// \brief LogGen operator for LogTriggerConf.
|
||||
/// \param title The title of the log.
|
||||
/// \param security The security type of the log.
|
||||
/// \param is_action_drop_or_prevent Flag indicating if the action is drop or prevent.
|
||||
/// \param tags Tags for the log.
|
||||
/// \return The LogGen object.
|
||||
template <typename... Tags>
|
||||
LogGen
|
||||
operator()(const std::string &title, SecurityType security, bool is_action_drop_or_prevent, Tags ...tags) const
|
||||
operator()(const std::string &title, SecurityType security, bool is_action_drop_or_prevent, Tags... tags) const
|
||||
{
|
||||
return (*this)(
|
||||
return operator()(
|
||||
title,
|
||||
security,
|
||||
getSeverity(is_action_drop_or_prevent),
|
||||
@@ -131,30 +229,98 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Load function to deserialize configuration from JSONInputArchive.
|
||||
/// \param archive_in The JSON input archive.
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
bool isWebLogFieldActive(WebLogFields log_field) const { return log_web_fields.isSet(log_field); }
|
||||
/// \brief Check if the web log field is active for the trigger.
|
||||
/// \param log_field The web log field to check.
|
||||
/// \return True if the web log field is active, otherwise false.
|
||||
bool
|
||||
isWebLogFieldActive(WebLogFields log_field) const
|
||||
{
|
||||
return log_web_fields.isSet(log_field);
|
||||
}
|
||||
|
||||
bool isLogStreamActive(ReportIS::StreamType stream_type) const { return active_streams.isSet(stream_type); }
|
||||
/// \brief Check if the log stream is active for the trigger.
|
||||
/// \param stream_type The log stream type to check.
|
||||
/// \return True if the log stream is active, otherwise false.
|
||||
bool
|
||||
isLogStreamActive(ReportIS::StreamType stream_type) const
|
||||
{
|
||||
return active_streams.isSet(stream_type);
|
||||
}
|
||||
|
||||
bool isPreventLogActive(SecurityType security_type) const { return should_log_on_prevent.isSet(security_type); }
|
||||
/// \brief Check if the log is active on prevent for the given security type.
|
||||
/// \param security_type The security type to check.
|
||||
/// \return True if the log is active on prevent, otherwise false.
|
||||
bool
|
||||
isPreventLogActive(SecurityType security_type) const
|
||||
{
|
||||
return should_log_on_prevent.isSet(security_type);
|
||||
}
|
||||
|
||||
bool isDetectLogActive(SecurityType security_type) const { return should_log_on_detect.isSet(security_type); }
|
||||
/// \brief Check if the log is active on detect for the given security type.
|
||||
/// \param security_type The security type to check.
|
||||
/// \return True if the log is active on detect, otherwise false.
|
||||
bool
|
||||
isDetectLogActive(SecurityType security_type) const
|
||||
{
|
||||
return should_log_on_detect.isSet(security_type);
|
||||
}
|
||||
|
||||
bool isLogGeoLocationActive(SecurityType security_type) const { return log_geo_location.isSet(security_type); }
|
||||
/// \brief Check if the geo-location log is active for the given security type.
|
||||
/// \param security_type The security type to check.
|
||||
/// \return True if the geo-location log is active, otherwise false.
|
||||
bool
|
||||
isLogGeoLocationActive(SecurityType security_type) const
|
||||
{
|
||||
return log_geo_location.isSet(security_type);
|
||||
}
|
||||
|
||||
extendLoggingSeverity getExtendLoggingSeverity() const { return extend_logging_severity; }
|
||||
/// \brief Get the extended logging severity.
|
||||
/// \return The extended logging severity.
|
||||
extendLoggingSeverity
|
||||
getExtendLoggingSeverity() const
|
||||
{
|
||||
return extend_logging_severity;
|
||||
}
|
||||
|
||||
const std::string & getVerbosity() const { return verbosity; }
|
||||
const std::string & getName() const { return name; }
|
||||
/// \brief Get the verbosity.
|
||||
/// \return The verbosity.
|
||||
const std::string &
|
||||
getVerbosity() const
|
||||
{
|
||||
return verbosity;
|
||||
}
|
||||
|
||||
const std::string & getUrlForSyslog() const { return url_for_syslog; }
|
||||
const std::string & getUrlForCef() const { return url_for_cef; }
|
||||
/// \brief Get the name.
|
||||
/// \return The name.
|
||||
const std::string &
|
||||
getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
/// \brief Get the URL for syslog.
|
||||
/// \return The URL for syslog.
|
||||
const std::string &
|
||||
getUrlForSyslog() const
|
||||
{
|
||||
return url_for_syslog;
|
||||
}
|
||||
|
||||
/// \brief Get the URL for CEF.
|
||||
/// \return The URL for CEF.
|
||||
const std::string &
|
||||
getUrlForCef() const
|
||||
{
|
||||
return url_for_cef;
|
||||
}
|
||||
|
||||
private:
|
||||
ReportIS::Severity getSeverity(bool is_action_drop_or_prevent) const;
|
||||
ReportIS::Priority getPriority(bool is_action_drop_or_prevent) const;
|
||||
|
||||
Flags<ReportIS::StreamType> getStreams(SecurityType security_type, bool is_action_drop_or_prevent) const;
|
||||
Flags<ReportIS::Enreachments> getEnrechments(SecurityType security_type) const;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "i_mainloop.h"
|
||||
#include "i_socket_is.h"
|
||||
#include "i_health_check_manager.h"
|
||||
#include "i_shell_cmd.h"
|
||||
#include "component.h"
|
||||
|
||||
class HealthChecker
|
||||
@@ -25,7 +26,8 @@ class HealthChecker
|
||||
public Component,
|
||||
Singleton::Consume<I_MainLoop>,
|
||||
Singleton::Consume<I_Socket>,
|
||||
Singleton::Consume<I_Health_Check_Manager>
|
||||
Singleton::Consume<I_Health_Check_Manager>,
|
||||
Singleton::Consume<I_ShellCmd>
|
||||
{
|
||||
public:
|
||||
HealthChecker();
|
||||
|
||||
@@ -14,13 +14,15 @@
|
||||
#ifndef __I_LOCAL_POLICY_MGMT_GEN_H__
|
||||
#define __I_LOCAL_POLICY_MGMT_GEN_H__
|
||||
|
||||
#include "i_env_details.h"
|
||||
|
||||
class I_LocalPolicyMgmtGen
|
||||
{
|
||||
public:
|
||||
virtual std::string parsePolicy(const std::string &policy_version) = 0;
|
||||
virtual const std::string & getAgentPolicyPath(void) const = 0;
|
||||
virtual const std::string & getLocalPolicyPath(void) const = 0;
|
||||
virtual void setPolicyPath(const std::string &new_local_policy_path) = 0;
|
||||
virtual std::string generateAppSecLocalPolicy(
|
||||
EnvType env_type,
|
||||
const std::string &policy_version,
|
||||
const std::string &local_policy_path) = 0;
|
||||
|
||||
protected:
|
||||
~I_LocalPolicyMgmtGen() {}
|
||||
|
||||
@@ -34,6 +34,7 @@ public:
|
||||
virtual const std::string & getUpdateTime() const = 0;
|
||||
virtual const std::string & getLastManifestUpdate() const = 0;
|
||||
virtual const std::string & getPolicyVersion() const = 0;
|
||||
virtual const std::string & getWaapModelVersion() const = 0;
|
||||
virtual const std::string & getLastPolicyUpdate() const = 0;
|
||||
virtual const std::string & getLastSettingsUpdate() const = 0;
|
||||
virtual const std::string & getUpgradeMode() const = 0;
|
||||
|
||||
@@ -106,11 +106,18 @@ public:
|
||||
const std::string &profile_id = "") const = 0;
|
||||
|
||||
virtual bool isNonEmptyFile(const std::string &path) const = 0;
|
||||
virtual std::shared_ptr<std::ifstream> fileStreamWrapper(const std::string &path) const = 0;
|
||||
virtual Maybe<std::string> readFile(const std::string &path) const = 0;
|
||||
virtual bool writeFile(const std::string &text, const std::string &path) const = 0;
|
||||
virtual bool writeFile(const std::string &text, const std::string &path, bool append_mode = false) const = 0;
|
||||
virtual bool removeFile(const std::string &path) const = 0;
|
||||
virtual bool removeDirectory(const std::string &path, bool delete_content) const = 0;
|
||||
virtual void deleteVirtualTenantProfileFiles(
|
||||
const std::string &tenant_id,
|
||||
const std::string &profile_id,
|
||||
const std::string &conf_path) const = 0;
|
||||
virtual bool copyFile(const std::string &src_path, const std::string &dst_path) const = 0;
|
||||
virtual bool doesFileExist(const std::string &file_path) const = 0;
|
||||
virtual void getClusterId() const = 0;
|
||||
virtual void fillKeyInJson(
|
||||
const std::string &filename,
|
||||
const std::string &_key,
|
||||
@@ -118,6 +125,7 @@ public:
|
||||
virtual bool createDirectory(const std::string &directory_path) const = 0;
|
||||
virtual bool doesDirectoryExist(const std::string &dir_path) const = 0;
|
||||
virtual bool executeCmd(const std::string &cmd) const = 0;
|
||||
virtual void loadTenantsFromDir(const std::string &dir_path) const = 0;
|
||||
|
||||
virtual std::string base64Encode(const std::string &input) const = 0;
|
||||
virtual std::string base64Decode(const std::string &input) const = 0;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <map>
|
||||
|
||||
#include "connkey.h"
|
||||
#include "maybe_res.h"
|
||||
#include "rest.h"
|
||||
|
||||
enum class ReconfStatus { SUCCEEDED, IN_PROGRESS, FAILED, INACTIVE };
|
||||
@@ -27,6 +28,7 @@ class I_ServiceController
|
||||
{
|
||||
public:
|
||||
virtual void refreshPendingServices() = 0;
|
||||
virtual const std::string & getPolicyVersions() const = 0;
|
||||
virtual const std::string & getPolicyVersion() const = 0;
|
||||
virtual const std::string & getUpdatePolicyVersion() const = 0;
|
||||
virtual void updateReconfStatus(int id, ReconfStatus status) = 0;
|
||||
@@ -37,13 +39,13 @@ public:
|
||||
const std::string &service_id
|
||||
) = 0;
|
||||
|
||||
virtual bool
|
||||
virtual Maybe<void>
|
||||
updateServiceConfiguration(
|
||||
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 &child_tenant_id = "",
|
||||
const std::string &child_profile_id = "",
|
||||
const bool last_iteration = false
|
||||
) = 0;
|
||||
|
||||
|
||||
@@ -26,9 +26,12 @@ using OrchData = Maybe<std::string>;
|
||||
class I_UpdateCommunication
|
||||
{
|
||||
public:
|
||||
virtual Maybe<void> sendPolicyVersion(
|
||||
const std::string &policy_version,
|
||||
const std::string &policy_versions
|
||||
) const = 0;
|
||||
virtual Maybe<void> authenticateAgent() = 0;
|
||||
virtual Maybe<void> getUpdate(CheckUpdateRequest &request) = 0;
|
||||
virtual Maybe<void> sendPolicyVersion(const std::string &policy_version) const = 0;
|
||||
virtual Maybe<std::string> downloadAttributeFile(const GetResourceFile &resourse_file) = 0;
|
||||
virtual void setAddressExtenesion(const std::string &extension) = 0;
|
||||
};
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "i_environment.h"
|
||||
#include "i_tenant_manager.h"
|
||||
#include "i_package_handler.h"
|
||||
#include "i_env_details.h"
|
||||
#include "component.h"
|
||||
|
||||
class OrchestrationComp
|
||||
@@ -52,7 +53,8 @@ class OrchestrationComp
|
||||
Singleton::Consume<I_ServiceController>,
|
||||
Singleton::Consume<I_UpdateCommunication>,
|
||||
Singleton::Consume<I_Downloader>,
|
||||
Singleton::Consume<I_ManifestController>
|
||||
Singleton::Consume<I_ManifestController>,
|
||||
Singleton::Consume<I_EnvDetails>
|
||||
{
|
||||
public:
|
||||
OrchestrationComp();
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "i_time_get.h"
|
||||
#include "i_mainloop.h"
|
||||
#include "i_agent_details.h"
|
||||
#include "i_details_resolver.h"
|
||||
#include "customized_cereal_map.h"
|
||||
|
||||
class OrchestrationStatus
|
||||
@@ -32,6 +33,7 @@ class OrchestrationStatus
|
||||
Singleton::Provide<I_OrchestrationStatus>,
|
||||
Singleton::Consume<I_TimeGet>,
|
||||
Singleton::Consume<I_AgentDetails>,
|
||||
Singleton::Consume<I_DetailsResolver>,
|
||||
Singleton::Consume<I_OrchestrationTools>,
|
||||
Singleton::Consume<I_MainLoop>
|
||||
{
|
||||
|
||||
@@ -17,9 +17,26 @@
|
||||
#include <fstream>
|
||||
|
||||
#include "i_orchestration_tools.h"
|
||||
#include "i_shell_cmd.h"
|
||||
#include "i_tenant_manager.h"
|
||||
#include "component.h"
|
||||
#include "i_env_details.h"
|
||||
#include "i_messaging.h"
|
||||
#include "i_environment.h"
|
||||
#include "i_agent_details.h"
|
||||
#include "i_mainloop.h"
|
||||
|
||||
class OrchestrationTools : public Component, Singleton::Provide<I_OrchestrationTools>
|
||||
class OrchestrationTools
|
||||
:
|
||||
public Component,
|
||||
Singleton::Provide<I_OrchestrationTools>,
|
||||
Singleton::Consume<I_ShellCmd>,
|
||||
Singleton::Consume<I_TenantManager>,
|
||||
Singleton::Consume<I_EnvDetails>,
|
||||
Singleton::Consume<I_Messaging>,
|
||||
Singleton::Consume<I_Environment>,
|
||||
Singleton::Consume<I_MainLoop>,
|
||||
Singleton::Consume<I_AgentDetails>
|
||||
{
|
||||
public:
|
||||
OrchestrationTools();
|
||||
|
||||
@@ -106,6 +106,78 @@ public:
|
||||
BOTH_LABEL_OPTIONAL_PARAM(TenantError, error, "error");
|
||||
};
|
||||
|
||||
class UpgradeSchedule : public ClientRest
|
||||
{
|
||||
public:
|
||||
UpgradeSchedule() = default;
|
||||
|
||||
UpgradeSchedule(const UpgradeSchedule &other)
|
||||
{
|
||||
mode = other.mode;
|
||||
time = other.time;
|
||||
duration_hours = other.duration_hours;
|
||||
days = other.days;
|
||||
}
|
||||
|
||||
UpgradeSchedule &
|
||||
operator=(const UpgradeSchedule &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
mode = other.mode;
|
||||
time = other.time;
|
||||
duration_hours = other.duration_hours;
|
||||
days = other.days;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void init(const std::string &_upgrade_mode) { mode = _upgrade_mode; }
|
||||
|
||||
void
|
||||
init(
|
||||
const std::string &_upgrade_mode,
|
||||
const std::string &_upgrade_time,
|
||||
const uint &_upgrade_duration_hours)
|
||||
{
|
||||
init(_upgrade_mode);
|
||||
time = _upgrade_time;
|
||||
duration_hours = _upgrade_duration_hours;
|
||||
}
|
||||
|
||||
void
|
||||
init(
|
||||
const std::string &_upgrade_mode,
|
||||
const std::string &_upgrade_time,
|
||||
const uint &_upgrade_duration_hours,
|
||||
const std::vector<std::string> &_upgrade_days)
|
||||
{
|
||||
init(_upgrade_mode, _upgrade_time, _upgrade_duration_hours);
|
||||
days = _upgrade_days;
|
||||
}
|
||||
|
||||
private:
|
||||
C2S_LABEL_PARAM(std::string, mode, "upgradeMode");
|
||||
C2S_LABEL_OPTIONAL_PARAM(std::string, time, "upgradeTime");
|
||||
C2S_LABEL_OPTIONAL_PARAM(uint, duration_hours, "upgradeDurationHours");
|
||||
C2S_LABEL_OPTIONAL_PARAM(std::vector<std::string>, days, "upgradeDay");
|
||||
};
|
||||
|
||||
class LocalConfigurationSettings : public ClientRest
|
||||
{
|
||||
public:
|
||||
LocalConfigurationSettings() = default;
|
||||
|
||||
void
|
||||
setUpgradeSchedule(const UpgradeSchedule &schedule)
|
||||
{
|
||||
upgrade_schedule.setActive(true);
|
||||
upgrade_schedule.get() = schedule;
|
||||
}
|
||||
|
||||
private:
|
||||
C2S_LABEL_OPTIONAL_PARAM(UpgradeSchedule, upgrade_schedule, "upgradeSchedule");
|
||||
};
|
||||
|
||||
CheckUpdateRequest(
|
||||
const std::string &_manifest,
|
||||
const std::string &_policy,
|
||||
@@ -185,6 +257,32 @@ public:
|
||||
|
||||
void setGreedyMode() { check_all_tenants = true; }
|
||||
|
||||
void
|
||||
setUpgradeFields(const std::string &_upgrade_mode)
|
||||
{
|
||||
UpgradeSchedule upgrade_schedule;
|
||||
upgrade_schedule.init(_upgrade_mode);
|
||||
local_configuration_settings.setActive(true);
|
||||
local_configuration_settings.get().setUpgradeSchedule(upgrade_schedule);
|
||||
}
|
||||
|
||||
void
|
||||
setUpgradeFields(
|
||||
const std::string &_upgrade_mode,
|
||||
const std::string &_upgrade_time,
|
||||
const uint &_upgrade_duration_hours,
|
||||
const std::vector<std::string> &_upgrade_days)
|
||||
{
|
||||
UpgradeSchedule upgrade_schedule;
|
||||
if (!_upgrade_days.empty()) {
|
||||
upgrade_schedule.init(_upgrade_mode, _upgrade_time, _upgrade_duration_hours, _upgrade_days);
|
||||
} else {
|
||||
upgrade_schedule.init(_upgrade_mode, _upgrade_time, _upgrade_duration_hours);
|
||||
}
|
||||
local_configuration_settings.setActive(true);
|
||||
local_configuration_settings.get().setUpgradeSchedule(upgrade_schedule);
|
||||
}
|
||||
|
||||
private:
|
||||
class VirtualConfig : public ClientRest
|
||||
{
|
||||
@@ -239,6 +337,8 @@ private:
|
||||
C2S_LABEL_PARAM(std::string, checksum_type, "checksum-type");
|
||||
C2S_LABEL_PARAM(std::string, policy_version, "policyVersion");
|
||||
|
||||
C2S_LABEL_OPTIONAL_PARAM(LocalConfigurationSettings, local_configuration_settings, "localConfigurationSettings");
|
||||
|
||||
S2C_LABEL_OPTIONAL_PARAM(VirtualConfig, in_virtual_policy, "virtualPolicy");
|
||||
S2C_LABEL_OPTIONAL_PARAM(VirtualConfig, in_virtual_settings, "virtualSettings");
|
||||
};
|
||||
|
||||
32
components/include/rate_limit.h
Executable file
32
components/include/rate_limit.h
Executable file
@@ -0,0 +1,32 @@
|
||||
#ifndef __RATE_LIMIT_H_
|
||||
#define __RATE_LIMIT_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "component.h"
|
||||
#include "singleton.h"
|
||||
#include "i_mainloop.h"
|
||||
#include "i_environment.h"
|
||||
|
||||
class RateLimit
|
||||
:
|
||||
public Component,
|
||||
Singleton::Consume<I_MainLoop>,
|
||||
Singleton::Consume<I_TimeGet>,
|
||||
Singleton::Consume<I_Environment>
|
||||
{
|
||||
public:
|
||||
RateLimit();
|
||||
~RateLimit();
|
||||
|
||||
void preload() override;
|
||||
|
||||
void init() override;
|
||||
void fini() override;
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> pimpl;
|
||||
};
|
||||
|
||||
#endif // __RATE_LIMIT_H_
|
||||
142
components/include/rate_limit_config.h
Executable file
142
components/include/rate_limit_config.h
Executable file
@@ -0,0 +1,142 @@
|
||||
#ifndef __RATE_LIMIT_CONFIG_H__
|
||||
#define __RATE_LIMIT_CONFIG_H__
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <cereal/archives/json.hpp>
|
||||
|
||||
#include "debug.h"
|
||||
#include "generic_rulebase/rulebase_config.h"
|
||||
#include "generic_rulebase/triggers_config.h"
|
||||
#include "generic_rulebase/evaluators/trigger_eval.h"
|
||||
|
||||
USE_DEBUG_FLAG(D_REVERSE_PROXY);
|
||||
|
||||
class RateLimitTrigger
|
||||
{
|
||||
public:
|
||||
void
|
||||
load(cereal::JSONInputArchive &ar);
|
||||
|
||||
const std::string & getTriggerId() const { return id; }
|
||||
|
||||
private:
|
||||
std::string id;
|
||||
};
|
||||
|
||||
class RateLimitRule
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &ar);
|
||||
void prepare(const std::string &asset_id, int zone_id);
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
if (uri.empty()) {
|
||||
dbgTrace(D_REVERSE_PROXY) << "Recived empty URI in rate-limit rule";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (uri.at(0) != '/') {
|
||||
dbgWarning(D_REVERSE_PROXY)
|
||||
<< "Recived invalid rate-limit URI in rate-limit rule: "
|
||||
<< uri
|
||||
<< " rate-limit URI must start with /";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (limit <= 0) {
|
||||
dbgWarning(D_REVERSE_PROXY)
|
||||
<< "Recived invalid rate-limit limit in rate-limit rule: "
|
||||
<< limit
|
||||
<< " rate-limit rule limit must be positive";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
friend std::ostream &
|
||||
operator<<(std::ostream &os, const RateLimitRule &rule)
|
||||
{
|
||||
os << "Uri: " << rule.uri << ", Rate scope: " << rule.scope << ", Limit: " << rule.limit;
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
int getRateLimit() const { return limit; }
|
||||
const std::string & getRateLimitZone() const { return limit_req_zone_template_value; }
|
||||
const std::string & getRateLimitReq() const { return limit_req_template_value; }
|
||||
const std::string & getRateLimitUri() const { return uri; }
|
||||
const std::string & getRateLimitScope() const { return scope; }
|
||||
const LogTriggerConf & getRateLimitTrigger() const { return trigger; }
|
||||
const std::vector<RateLimitTrigger> & getRateLimitTriggers() const { return rate_limit_triggers; }
|
||||
|
||||
bool isRootLocation() const;
|
||||
|
||||
bool operator==(const RateLimitRule &rhs) { return uri == rhs.uri; }
|
||||
bool operator<(const RateLimitRule &rhs) { return uri < rhs.uri; }
|
||||
bool isExactMatch() const { return exact_match || (!uri.empty() && uri.back() != '/'); }
|
||||
void setExactMatch() { exact_match = true; }
|
||||
void appendSlash() { uri += '/'; }
|
||||
|
||||
private:
|
||||
std::string uri;
|
||||
std::string scope;
|
||||
std::string limit_req_template_value;
|
||||
std::string limit_req_zone_template_value;
|
||||
std::string cache_size = "5m";
|
||||
std::vector<RateLimitTrigger> rate_limit_triggers;
|
||||
LogTriggerConf trigger;
|
||||
int limit;
|
||||
bool exact_match = false;
|
||||
};
|
||||
|
||||
class RateLimitConfig
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &ar);
|
||||
void addSiblingRateLimitRule(RateLimitRule &rule);
|
||||
void prepare();
|
||||
|
||||
const std::vector<RateLimitRule> & getRateLimitRules() const { return rate_limit_rules; }
|
||||
const std::string & getRateLimitMode() const { return mode; }
|
||||
|
||||
const LogTriggerConf
|
||||
getRateLimitTrigger(const std::string &nginx_uri) const
|
||||
{
|
||||
const RateLimitRule rule = findLongestMatchingRule(nginx_uri);
|
||||
|
||||
std::set<std::string> rate_limit_triggers_set;
|
||||
for (const RateLimitTrigger &rate_limit_trigger : rule.getRateLimitTriggers()) {
|
||||
dbgTrace(D_REVERSE_PROXY)
|
||||
<< "Adding trigger ID: "
|
||||
<< rate_limit_trigger.getTriggerId()
|
||||
<< " of rule URI: "
|
||||
<< rule.getRateLimitUri()
|
||||
<< " to the context set";
|
||||
rate_limit_triggers_set.insert(rate_limit_trigger.getTriggerId());
|
||||
}
|
||||
|
||||
ScopedContext ctx;
|
||||
ctx.registerValue<std::set<GenericConfigId>>(TriggerMatcher::ctx_key, rate_limit_triggers_set);
|
||||
return getConfigurationWithDefault(LogTriggerConf(), "rulebase", "log");
|
||||
}
|
||||
|
||||
static void setIsActive(bool _is_active) { is_active |= _is_active; }
|
||||
|
||||
static void resetIsActive() { is_active = false; }
|
||||
|
||||
static bool isActive() { return is_active; }
|
||||
|
||||
private:
|
||||
const RateLimitRule
|
||||
findLongestMatchingRule(const std::string &nginx_uri) const;
|
||||
|
||||
static bool is_active;
|
||||
std::string mode;
|
||||
std::vector<RateLimitRule> rate_limit_rules;
|
||||
};
|
||||
|
||||
#endif // __RATE_LIMIT_CONFIG_H__
|
||||
@@ -1,4 +1,6 @@
|
||||
add_subdirectory(ips)
|
||||
add_subdirectory(layer_7_access_control)
|
||||
add_subdirectory(local_policy_mgmt_gen)
|
||||
add_subdirectory(orchestration)
|
||||
add_subdirectory(rate_limit)
|
||||
add_subdirectory(waap)
|
||||
|
||||
@@ -1,54 +1,176 @@
|
||||
// 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.
|
||||
|
||||
/// \file ips_signatures.h
|
||||
/// \brief Declaration of classes IPSSignatureSubTypes, IPSSignaturesPerContext, IPSSignatures, SnortSignatures, and
|
||||
/// related functions. \author Check Point Software Technologies Ltd. \date 2022
|
||||
|
||||
#ifndef __IPS_SIGNATURES_H__
|
||||
#define __IPS_SIGNATURES_H__
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "config.h"
|
||||
#include "parsed_context.h"
|
||||
#include "log_generator.h"
|
||||
#include "pm_hook.h"
|
||||
#include "ips_enums.h"
|
||||
#include "ips_entry.h"
|
||||
#include "i_first_tier_agg.h"
|
||||
#include "ips_entry.h"
|
||||
#include "ips_enums.h"
|
||||
#include "log_generator.h"
|
||||
#include "parsed_context.h"
|
||||
#include "pm_hook.h"
|
||||
|
||||
/// \namespace IPSSignatureSubTypes
|
||||
/// \brief Namespace containing subtypes for IPS signatures.
|
||||
namespace IPSSignatureSubTypes
|
||||
{
|
||||
using ActionResults = std::tuple<IPSSignatureSubTypes::SignatureAction, std::string, std::vector<std::string>>;
|
||||
|
||||
/// \class BaseSignature
|
||||
/// \brief Represents the base signature class.
|
||||
class BaseSignature
|
||||
{
|
||||
public:
|
||||
enum class MatchType { NO_MATCH, CACHE_MATCH, MATCH };
|
||||
/// \enum MatchType
|
||||
/// \brief Enumerates the types of matches for BaseSignature.
|
||||
enum class MatchType
|
||||
{
|
||||
NO_MATCH,
|
||||
CACHE_MATCH,
|
||||
MATCH
|
||||
};
|
||||
|
||||
virtual const std::string & getSigId() const = 0;
|
||||
/// \brief Get the ID of the signature.
|
||||
virtual const std::string &getSigId() const = 0;
|
||||
|
||||
/// \brief Get the match type for the signature.
|
||||
/// \param matched The set of patterns that matched.
|
||||
virtual MatchType getMatch(const std::set<PMPattern> &matched) const = 0;
|
||||
|
||||
/// \brief Get the set of patterns in the signature.
|
||||
virtual std::set<PMPattern> patternsInSignature() const = 0;
|
||||
virtual const std::vector<std::string> & getContext() const = 0;
|
||||
|
||||
/// \brief Get the context of the signature.
|
||||
virtual const std::vector<std::string> &getContext() const = 0;
|
||||
};
|
||||
|
||||
/// \class IPSSignatureMetaData
|
||||
/// \brief Represents the metadata for an IPS signature.
|
||||
class IPSSignatureMetaData
|
||||
{
|
||||
public:
|
||||
/// \brief Load the metadata from a JSON archive.
|
||||
/// \param ar The JSON input archive.
|
||||
void load(cereal::JSONInputArchive &ar);
|
||||
|
||||
/// \brief Set the indicators for the metadata.
|
||||
/// \param source The source indicator.
|
||||
/// \param version The version indicator.
|
||||
void setIndicators(const std::string &source, const std::string &version);
|
||||
|
||||
const std::string & getId() const { return protection_id; }
|
||||
const std::string & getName() const { return sig_name; }
|
||||
const std::string & getUpdateVersion() const { return update; }
|
||||
const std::string & getLogTitle() const { return event_log; }
|
||||
const std::string & getSource() const { return source; }
|
||||
const std::string & getFeedVersion() const { return version; }
|
||||
const std::vector<std::string> & getCveList() const { return cve_list; }
|
||||
IPSLevel getSeverity() const { return severity; }
|
||||
std::string getSeverityString() const;
|
||||
IPSLevel getConfidence() const { return confidence; }
|
||||
std::string getConfidenceString() const;
|
||||
IPSLevel getPerformance() const { return performance; }
|
||||
std::string getPerformanceString() const;
|
||||
bool isSilent() const { return is_silent; }
|
||||
std::string getIncidentType() const;
|
||||
bool isYearAtLeast(const Maybe<int> &year) const;
|
||||
Maybe<int> getYear() const;
|
||||
/// \brief Get the ID of the signature.
|
||||
const std::string &
|
||||
getId() const
|
||||
{
|
||||
return protection_id;
|
||||
}
|
||||
|
||||
/// \brief Get the name of the signature.
|
||||
const std::string &
|
||||
getName() const
|
||||
{
|
||||
return sig_name;
|
||||
}
|
||||
|
||||
/// \brief Get the update version of the signature.
|
||||
const std::string &
|
||||
getUpdateVersion() const
|
||||
{
|
||||
return update;
|
||||
}
|
||||
|
||||
/// \brief Get the log title of the signature.
|
||||
const std::string &
|
||||
getLogTitle() const
|
||||
{
|
||||
return event_log;
|
||||
}
|
||||
|
||||
/// \brief Get the source indicator of the signature.
|
||||
const std::string &
|
||||
getSource() const
|
||||
{
|
||||
return source;
|
||||
}
|
||||
|
||||
/// \brief Get the feed version of the signature.
|
||||
const std::string &
|
||||
getFeedVersion() const
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
/// \brief Get the CVE list of the signature.
|
||||
const std::vector<std::string> &
|
||||
getCveList() const
|
||||
{
|
||||
return cve_list;
|
||||
}
|
||||
|
||||
/// \brief Get the severity level of the signature.
|
||||
IPSLevel
|
||||
getSeverity() const
|
||||
{
|
||||
return severity;
|
||||
}
|
||||
|
||||
/// \brief Get the severity level as a string of the signature.
|
||||
std::string getSeverityString() const;
|
||||
|
||||
/// \brief Get the confidence level of the signature.
|
||||
IPSLevel
|
||||
getConfidence() const
|
||||
{
|
||||
return confidence;
|
||||
}
|
||||
|
||||
/// \brief Get the confidence level as a string of the signature.
|
||||
std::string getConfidenceString() const;
|
||||
|
||||
/// \brief Get the performance level of the signature.
|
||||
IPSLevel
|
||||
getPerformance() const
|
||||
{
|
||||
return performance;
|
||||
}
|
||||
|
||||
/// \brief Get the performance level as a string of the signature.
|
||||
std::string getPerformanceString() const;
|
||||
|
||||
/// \brief Check if the signature is silent.
|
||||
bool
|
||||
isSilent() const
|
||||
{
|
||||
return is_silent;
|
||||
}
|
||||
|
||||
/// \brief Get the incident type of the signature.
|
||||
std::string getIncidentType() const;
|
||||
|
||||
/// \brief Check if the signature is from a specific year or later.
|
||||
/// \param year The year to compare with.
|
||||
bool isYearAtLeast(const Maybe<int> &year) const;
|
||||
|
||||
/// \brief Get the year of the signature.
|
||||
Maybe<int> getYear() const;
|
||||
|
||||
private:
|
||||
std::string protection_id;
|
||||
@@ -65,69 +187,224 @@ private:
|
||||
bool is_silent = false;
|
||||
};
|
||||
|
||||
/// \class CompleteSignature
|
||||
/// \brief Represents a complete signature.
|
||||
class CompleteSignature
|
||||
{
|
||||
public:
|
||||
/// \brief Load the complete signature from a JSON archive.
|
||||
/// \param ar The JSON input archive.
|
||||
void load(cereal::JSONInputArchive &ar);
|
||||
|
||||
/// \brief Get the match type for the signature.
|
||||
/// \param matches The set of patterns that matched.
|
||||
BaseSignature::MatchType getMatch(const std::set<PMPattern> &matches) const;
|
||||
|
||||
/// \brief Get the set of patterns in the signature.
|
||||
std::set<PMPattern> patternsInSignature() const;
|
||||
|
||||
/// \brief Set the indicators for the complete signature.
|
||||
/// \param source The source indicator.
|
||||
/// \param version The version indicator.
|
||||
void setIndicators(const std::string &source, const std::string &version);
|
||||
|
||||
const std::vector<std::string> & getContext() const { return rule->getContext(); }
|
||||
const std::string & getId() const { return metadata.getId(); }
|
||||
const std::string & getLogTitle() const { return metadata.getLogTitle(); }
|
||||
const std::string & getName() const { return metadata.getName(); }
|
||||
const std::string & getUpdateVersion() const { return metadata.getUpdateVersion(); }
|
||||
const std::string & getSource() const { return metadata.getSource(); }
|
||||
const std::string & getFeedVersion() const { return metadata.getFeedVersion(); }
|
||||
const std::vector<std::string> & getCveList() const { return metadata.getCveList(); }
|
||||
IPSLevel getSeverity() const { return metadata.getSeverity(); }
|
||||
std::string getSeverityString() const { return metadata.getSeverityString(); }
|
||||
IPSLevel getConfidence() const { return metadata.getConfidence(); }
|
||||
std::string getConfidenceString() const { return metadata.getConfidenceString(); }
|
||||
IPSLevel getPerformance() const { return metadata.getPerformance(); }
|
||||
std::string getPerformanceString() const { return metadata.getPerformanceString(); }
|
||||
bool isSilent() const { return metadata.isSilent(); }
|
||||
std::string getIncidentType() const { return metadata.getIncidentType(); }
|
||||
/// \brief Get the context of the signature.
|
||||
const std::vector<std::string> &
|
||||
getContext() const
|
||||
{
|
||||
return rule->getContext();
|
||||
}
|
||||
|
||||
bool isYearAtLeast(const Maybe<int> &year) const { return metadata.isYearAtLeast(year); }
|
||||
Maybe<int> getYear() const { return metadata.getYear(); }
|
||||
/// \brief Get the ID of the signature.
|
||||
const std::string &
|
||||
getId() const
|
||||
{
|
||||
return metadata.getId();
|
||||
}
|
||||
|
||||
/// \brief Get the log title of the signature.
|
||||
const std::string &
|
||||
getLogTitle() const
|
||||
{
|
||||
return metadata.getLogTitle();
|
||||
}
|
||||
|
||||
/// \brief Get the name of the signature.
|
||||
const std::string &
|
||||
getName() const
|
||||
{
|
||||
return metadata.getName();
|
||||
}
|
||||
|
||||
/// \brief Get the update version of the signature.
|
||||
const std::string &
|
||||
getUpdateVersion() const
|
||||
{
|
||||
return metadata.getUpdateVersion();
|
||||
}
|
||||
|
||||
/// \brief Get the source indicator of the signature.
|
||||
const std::string &
|
||||
getSource() const
|
||||
{
|
||||
return metadata.getSource();
|
||||
}
|
||||
|
||||
/// \brief Get the feed version of the signature.
|
||||
const std::string &
|
||||
getFeedVersion() const
|
||||
{
|
||||
return metadata.getFeedVersion();
|
||||
}
|
||||
|
||||
/// \brief Get the CVE list of the signature.
|
||||
const std::vector<std::string> &
|
||||
getCveList() const
|
||||
{
|
||||
return metadata.getCveList();
|
||||
}
|
||||
|
||||
/// \brief Get the severity level of the signature.
|
||||
IPSLevel
|
||||
getSeverity() const
|
||||
{
|
||||
return metadata.getSeverity();
|
||||
}
|
||||
|
||||
/// \brief Get the severity level as a string of the signature.
|
||||
std::string
|
||||
getSeverityString() const
|
||||
{
|
||||
return metadata.getSeverityString();
|
||||
}
|
||||
|
||||
/// \brief Get the confidence level of the signature.
|
||||
IPSLevel
|
||||
getConfidence() const
|
||||
{
|
||||
return metadata.getConfidence();
|
||||
}
|
||||
|
||||
/// \brief Get the confidence level as a string of the signature.
|
||||
std::string
|
||||
getConfidenceString() const
|
||||
{
|
||||
return metadata.getConfidenceString();
|
||||
}
|
||||
|
||||
/// \brief Get the performance level of the signature.
|
||||
IPSLevel
|
||||
getPerformance() const
|
||||
{
|
||||
return metadata.getPerformance();
|
||||
}
|
||||
|
||||
/// \brief Get the performance level as a string of the signature.
|
||||
std::string
|
||||
getPerformanceString() const
|
||||
{
|
||||
return metadata.getPerformanceString();
|
||||
}
|
||||
|
||||
/// \brief Check if the signature is silent.
|
||||
bool
|
||||
isSilent() const
|
||||
{
|
||||
return metadata.isSilent();
|
||||
}
|
||||
|
||||
/// \brief Get the incident type of the signature.
|
||||
std::string
|
||||
getIncidentType() const
|
||||
{
|
||||
return metadata.getIncidentType();
|
||||
}
|
||||
|
||||
/// \brief Check if the signature is from a specific year or later.
|
||||
/// \param year The year to compare with.
|
||||
bool
|
||||
isYearAtLeast(const Maybe<int> &year) const
|
||||
{
|
||||
return metadata.isYearAtLeast(year);
|
||||
}
|
||||
|
||||
/// \brief Get the year of the signature.
|
||||
Maybe<int>
|
||||
getYear() const
|
||||
{
|
||||
return metadata.getYear();
|
||||
}
|
||||
|
||||
private:
|
||||
IPSSignatureMetaData metadata;
|
||||
std::shared_ptr<BaseSignature> rule;
|
||||
};
|
||||
|
||||
/// \class SignatureAndAction
|
||||
/// \brief Represents a signature and its associated action.
|
||||
class SignatureAndAction
|
||||
{
|
||||
public:
|
||||
SignatureAndAction(std::shared_ptr<CompleteSignature> _signature, SignatureAction _action)
|
||||
:
|
||||
signature(_signature),
|
||||
action(_action)
|
||||
/// \brief Construct a SignatureAndAction object.
|
||||
/// \param _signature The complete signature.
|
||||
/// \param _action The signature action.
|
||||
SignatureAndAction(std::shared_ptr<CompleteSignature> _signature, SignatureAction _action) :
|
||||
signature(_signature), action(_action)
|
||||
{}
|
||||
|
||||
/// \brief Check if the signature is matched for prevention.
|
||||
/// \param context_buffer The context buffer.
|
||||
/// \param pattern The set of patterns to match.
|
||||
bool isMatchedPrevent(const Buffer &context_buffer, const std::set<PMPattern> &pattern) const;
|
||||
|
||||
/// \brief Check if the signature is matched silently.
|
||||
/// \param context_buffer The context buffer.
|
||||
bool matchSilent(const Buffer &context_buffer) const;
|
||||
|
||||
/// \brief Get the set of patterns in the signature.
|
||||
std::set<PMPattern>
|
||||
patternsInSignature() const
|
||||
{
|
||||
return signature->patternsInSignature();
|
||||
}
|
||||
|
||||
bool isMatchedPrevent(const Buffer &context_buffer, const std::set<PMPattern> &pattern) const;
|
||||
bool matchSilent(const Buffer &context_buffer) const;
|
||||
std::set<PMPattern> patternsInSignature() const { return signature->patternsInSignature(); }
|
||||
const std::vector<std::string> & getContext() const { return signature->getContext(); }
|
||||
/// \brief Get the context of the signature.
|
||||
const std::vector<std::string> &
|
||||
getContext() const
|
||||
{
|
||||
return signature->getContext();
|
||||
}
|
||||
|
||||
private:
|
||||
/// \brief Get the action results for the IPS state.
|
||||
/// \param ips_state The IPS entry.
|
||||
ActionResults getAction(const IPSEntry &ips_state) const;
|
||||
|
||||
std::shared_ptr<CompleteSignature> signature;
|
||||
SignatureAction action;
|
||||
};
|
||||
} // IPSSignatureSubTypes
|
||||
} // namespace IPSSignatureSubTypes
|
||||
|
||||
/// \class IPSSignaturesPerContext
|
||||
/// \brief Represents IPS signatures per context.
|
||||
class IPSSignaturesPerContext : public Singleton::Consume<I_FirstTierAgg>
|
||||
{
|
||||
public:
|
||||
/// \brief Add a signature to the context.
|
||||
/// \param sig The signature and its associated action.
|
||||
void addSignature(const IPSSignatureSubTypes::SignatureAndAction &sig);
|
||||
|
||||
/// \brief Check if the context is matched for prevention.
|
||||
/// \param context_buffer The context buffer.
|
||||
bool isMatchedPrevent(const Buffer &context_buffer) const;
|
||||
|
||||
/// \brief Calculate the first tier for the given context name.
|
||||
/// \param ctx_name The context name.
|
||||
void calcFirstTier(const std::string &ctx_name);
|
||||
|
||||
private:
|
||||
/// \brief Get the first tier matches for the buffer.
|
||||
/// \param buffer The buffer to match.
|
||||
std::set<PMPattern> getFirstTierMatches(const Buffer &buffer) const;
|
||||
|
||||
std::map<PMPattern, std::vector<IPSSignatureSubTypes::SignatureAndAction>> signatures_per_lss;
|
||||
@@ -135,11 +412,17 @@ private:
|
||||
std::shared_ptr<PMHook> first_tier;
|
||||
};
|
||||
|
||||
/// \class IPSSignaturesResource
|
||||
/// \brief Represents IPS signatures resource.
|
||||
class IPSSignaturesResource
|
||||
{
|
||||
public:
|
||||
/// \brief Load the IPS signatures resource from a JSON archive.
|
||||
/// \param ar The JSON input archive.
|
||||
void load(cereal::JSONInputArchive &ar);
|
||||
|
||||
/// \brief Get all the signatures.
|
||||
/// \return A vector of shared pointers to CompleteSignature.
|
||||
const std::vector<std::shared_ptr<IPSSignatureSubTypes::CompleteSignature>> &
|
||||
getSignatures() const
|
||||
{
|
||||
@@ -150,11 +433,26 @@ private:
|
||||
std::vector<std::shared_ptr<IPSSignatureSubTypes::CompleteSignature>> all_signatures;
|
||||
};
|
||||
|
||||
/// \class SnortSignaturesResourceFile
|
||||
/// \brief Represents Snort signatures resource file.
|
||||
class SnortSignaturesResourceFile
|
||||
{
|
||||
public:
|
||||
/// \brief Load the Snort signatures resource file from a JSON archive.
|
||||
/// \param ar The JSON input archive.
|
||||
void load(cereal::JSONInputArchive &ar);
|
||||
bool isFile(const std::string &file_name) const { return file_name == name; }
|
||||
|
||||
/// \brief Check if the file name matches.
|
||||
/// \param file_name The name of the file.
|
||||
/// \return True if the file name matches, otherwise false.
|
||||
bool
|
||||
isFile(const std::string &file_name) const
|
||||
{
|
||||
return file_name == name;
|
||||
}
|
||||
|
||||
/// \brief Get all the signatures.
|
||||
/// \return A vector of shared pointers to CompleteSignature.
|
||||
const std::vector<std::shared_ptr<IPSSignatureSubTypes::CompleteSignature>> &
|
||||
getSignatures() const
|
||||
{
|
||||
@@ -166,11 +464,18 @@ private:
|
||||
std::vector<std::shared_ptr<IPSSignatureSubTypes::CompleteSignature>> all_signatures;
|
||||
};
|
||||
|
||||
/// \class SnortSignaturesResource
|
||||
/// \brief Represents Snort signatures resource.
|
||||
class SnortSignaturesResource
|
||||
{
|
||||
public:
|
||||
/// \brief Load the Snort signatures resource from a JSON archive.
|
||||
/// \param ar The JSON input archive.
|
||||
void load(cereal::JSONInputArchive &ar);
|
||||
|
||||
/// \brief Get all the signatures for the given file name.
|
||||
/// \param file_name The name of the file.
|
||||
/// \return A vector of shared pointers to CompleteSignature.
|
||||
const std::vector<std::shared_ptr<IPSSignatureSubTypes::CompleteSignature>> &
|
||||
getSignatures(const std::string &file_name) const
|
||||
{
|
||||
@@ -185,21 +490,74 @@ private:
|
||||
std::vector<SnortSignaturesResourceFile> files;
|
||||
};
|
||||
|
||||
/// \class IPSSignatures
|
||||
/// \brief Represents IPS signatures.
|
||||
class IPSSignatures
|
||||
{
|
||||
std::set<PMPattern> getFirstTier(const ParsedContext &context);
|
||||
|
||||
public:
|
||||
/// \brief Load the IPS signatures from a JSON archive.
|
||||
/// \param ar The JSON input archive.
|
||||
void load(cereal::JSONInputArchive &ar);
|
||||
|
||||
/// \brief Check if the context is matched for prevention.
|
||||
/// \param context_name The name of the context.
|
||||
/// \param context_buffer The context buffer.
|
||||
bool isMatchedPrevent(const std::string &context_name, const Buffer &context_buffer) const;
|
||||
bool isEmpty() const { return signatures_per_context.empty(); }
|
||||
|
||||
/// \brief Check if the IPS signatures are empty.
|
||||
/// \return True if the signatures are empty, otherwise false.
|
||||
bool
|
||||
isEmpty() const
|
||||
{
|
||||
return signatures_per_context.empty();
|
||||
}
|
||||
|
||||
/// \brief Check if the IPS signatures for the given context are empty.
|
||||
/// \param context The name of the context.
|
||||
/// \return True if the signatures for the context are empty, otherwise false.
|
||||
bool isEmpty(const std::string &context) const;
|
||||
|
||||
const std::string & getAsset() const { return asset_name; }
|
||||
const std::string & getAssetId() const { return asset_id; }
|
||||
const std::string & getPractice() const { return practice_name; }
|
||||
const std::string & getPracticeId() const { return practice_id; }
|
||||
const std::string & getSourceIdentifier() const { return source_id; }
|
||||
/// \brief Get the asset name.
|
||||
/// \return The asset name.
|
||||
const std::string &
|
||||
getAsset() const
|
||||
{
|
||||
return asset_name;
|
||||
}
|
||||
|
||||
/// \brief Get the asset ID.
|
||||
/// \return The asset ID.
|
||||
const std::string &
|
||||
getAssetId() const
|
||||
{
|
||||
return asset_id;
|
||||
}
|
||||
|
||||
/// \brief Get the practice name.
|
||||
/// \return The practice name.
|
||||
const std::string &
|
||||
getPractice() const
|
||||
{
|
||||
return practice_name;
|
||||
}
|
||||
|
||||
/// \brief Get the practice ID.
|
||||
/// \return The practice ID.
|
||||
const std::string &
|
||||
getPracticeId() const
|
||||
{
|
||||
return practice_id;
|
||||
}
|
||||
|
||||
/// \brief Get the source identifier.
|
||||
/// \return The source identifier.
|
||||
const std::string &
|
||||
getSourceIdentifier() const
|
||||
{
|
||||
return source_id;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, IPSSignaturesPerContext> signatures_per_context;
|
||||
@@ -210,21 +568,74 @@ private:
|
||||
std::string source_id;
|
||||
};
|
||||
|
||||
/// \class SnortSignatures
|
||||
/// \brief Represents Snort signatures.
|
||||
class SnortSignatures
|
||||
{
|
||||
std::set<PMPattern> getFirstTier(const ParsedContext &context);
|
||||
|
||||
public:
|
||||
/// \brief Load the Snort signatures from a JSON archive.
|
||||
/// \param ar The JSON input archive.
|
||||
void load(cereal::JSONInputArchive &ar);
|
||||
|
||||
/// \brief Check if the context is matched for prevention.
|
||||
/// \param context_name The name of the context.
|
||||
/// \param context_buffer The context buffer.
|
||||
bool isMatchedPrevent(const std::string &context_name, const Buffer &context_buffer) const;
|
||||
bool isEmpty() const { return signatures_per_context.empty(); }
|
||||
|
||||
/// \brief Check if the Snort signatures are empty.
|
||||
/// \return True if the signatures are empty, otherwise false.
|
||||
bool
|
||||
isEmpty() const
|
||||
{
|
||||
return signatures_per_context.empty();
|
||||
}
|
||||
|
||||
/// \brief Check if the Snort signatures for the given context are empty.
|
||||
/// \param context The name of the context.
|
||||
/// \return True if the signatures for the context are empty, otherwise false.
|
||||
bool isEmpty(const std::string &context) const;
|
||||
|
||||
const std::string & getAsset() const { return asset_name; }
|
||||
const std::string & getAssetId() const { return asset_id; }
|
||||
const std::string & getPractice() const { return practice_name; }
|
||||
const std::string & getPracticeId() const { return practice_id; }
|
||||
const std::string & getSourceIdentifier() const { return source_id; }
|
||||
/// \brief Get the asset name.
|
||||
/// \return The asset name.
|
||||
const std::string &
|
||||
getAsset() const
|
||||
{
|
||||
return asset_name;
|
||||
}
|
||||
|
||||
/// \brief Get the asset ID.
|
||||
/// \return The asset ID.
|
||||
const std::string &
|
||||
getAssetId() const
|
||||
{
|
||||
return asset_id;
|
||||
}
|
||||
|
||||
/// \brief Get the practice name.
|
||||
/// \return The practice name.
|
||||
const std::string &
|
||||
getPractice() const
|
||||
{
|
||||
return practice_name;
|
||||
}
|
||||
|
||||
/// \brief Get the practice ID.
|
||||
/// \return The practice ID.
|
||||
const std::string &
|
||||
getPracticeId() const
|
||||
{
|
||||
return practice_id;
|
||||
}
|
||||
|
||||
/// \brief Get the source identifier.
|
||||
/// \return The source identifier.
|
||||
const std::string &
|
||||
getSourceIdentifier() const
|
||||
{
|
||||
return source_id;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, IPSSignaturesPerContext> signatures_per_context;
|
||||
|
||||
@@ -23,6 +23,8 @@ using namespace ReportIS;
|
||||
using namespace std;
|
||||
using MatchType = BaseSignature::MatchType;
|
||||
|
||||
static const LogTriggerConf default_triger;
|
||||
|
||||
static const map<IPSLevel, Severity> severities = {
|
||||
{ IPSLevel::CRITICAL, Severity::CRITICAL },
|
||||
{ IPSLevel::HIGH, Severity::HIGH },
|
||||
@@ -396,7 +398,7 @@ SignatureAndAction::isMatchedPrevent(const Buffer &context_buffer, const set<PMP
|
||||
|
||||
dbgDebug(D_IPS) << "Signature matched - sending log";
|
||||
|
||||
auto &trigger = getConfigurationWithDefault(LogTriggerConf(), "rulebase", "log");
|
||||
auto &trigger = getConfigurationWithDefault(default_triger, "rulebase", "log");
|
||||
bool is_prevent = get<0>(override_action) == IPSSignatureSubTypes::SignatureAction::PREVENT;
|
||||
|
||||
auto severity = signature->getSeverity() < IPSLevel::HIGH ? Severity::HIGH : Severity::CRITICAL;
|
||||
|
||||
@@ -74,7 +74,7 @@ public:
|
||||
getCrowdsecEventId() const
|
||||
{
|
||||
if (!crowdsec_event_id) return genError("Empty ID");
|
||||
return LogField("externalVendorRecommendationId", crowdsec_event_id);
|
||||
return LogField("externalVendorRecommendationId", to_string(crowdsec_event_id));
|
||||
}
|
||||
|
||||
bool isMalicious() const { return type == "ban"; }
|
||||
@@ -280,6 +280,8 @@ Layer7AccessControl::Impl::generateLog(const string &source_ip, const Intelligen
|
||||
<< LogField("sourceIP", source_ip)
|
||||
<< LogField("externalVendorName", "CrowdSec")
|
||||
<< LogField("waapIncidentType", "CrowdSec")
|
||||
<< LogField("practiceSubType", "Web Access Control")
|
||||
<< LogField("practiceType", "Access Control")
|
||||
<< ip_reputation.getCrowdsecEventId()
|
||||
<< ip_reputation.getType()
|
||||
<< ip_reputation.getOrigin()
|
||||
|
||||
@@ -248,7 +248,7 @@ Layer7AccessControlTest::verifyReport(
|
||||
EXPECT_THAT(log, HasSubstr("\"destinationIP\": \"5.6.7.8\""));
|
||||
EXPECT_THAT(log, HasSubstr("\"externalVendorName\": \"CrowdSec\""));
|
||||
EXPECT_THAT(log, HasSubstr("\"waapIncidentType\": \"CrowdSec\""));
|
||||
EXPECT_THAT(log, HasSubstr("\"externalVendorRecommendationId\": 2253734"));
|
||||
EXPECT_THAT(log, HasSubstr("\"externalVendorRecommendationId\": \"2253734\""));
|
||||
EXPECT_THAT(log, HasSubstr("\"externalVendorRecommendedAction\": \"ban\""));
|
||||
EXPECT_THAT(log, HasSubstr("\"externalVendorRecommendationOrigin\": \"cscli\""));
|
||||
EXPECT_THAT(log, HasSubstr("\"externalVendorRecommendedAffectedScope\": \"1.2.3.4\""));
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
include_directories(include)
|
||||
add_library(local_policy_mgmt_gen
|
||||
appsec_practice_section.cc
|
||||
exceptions_section.cc
|
||||
ingress_data.cc
|
||||
rules_config_section.cc
|
||||
settings_section.cc
|
||||
snort_section.cc
|
||||
triggers_section.cc
|
||||
trusted_sources_section.cc
|
||||
policy_maker_utils.cc
|
||||
k8s_policy_utils.cc
|
||||
local_policy_mgmt_gen.cc
|
||||
new_appsec_policy_crd_parser.cc
|
||||
new_appsec_linux_policy.cc
|
||||
new_custom_response.cc
|
||||
new_trusted_sources.cc
|
||||
new_log_trigger.cc
|
||||
new_practice.cc
|
||||
new_exceptions.cc
|
||||
access_control_practice.cc
|
||||
configmaps.cc
|
||||
)
|
||||
245
components/security_apps/local_policy_mgmt_gen/access_control_practice.cc
Executable file
245
components/security_apps/local_policy_mgmt_gen/access_control_practice.cc
Executable file
@@ -0,0 +1,245 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "access_control_practice.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
USE_DEBUG_FLAG(D_LOCAL_POLICY);
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
|
||||
static const set<string> valid_modes = {"prevent", "detect", "inactive"};
|
||||
static const set<string> valid_units = {"minute", "second"};
|
||||
|
||||
static const std::unordered_map<std::string, std::string> key_to_mode_val = {
|
||||
{ "prevent-learn", "Prevent"},
|
||||
{ "detect-learn", "Detect"},
|
||||
{ "prevent", "Prevent"},
|
||||
{ "detect", "Detect"},
|
||||
{ "inactive", "Inactive"}
|
||||
};
|
||||
|
||||
static const std::unordered_map<std::string, std::string> key_to_units_val = {
|
||||
{ "second", "Second"},
|
||||
{ "minute", "Minute"}
|
||||
};
|
||||
|
||||
void
|
||||
RateLimitRulesTriggerSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
out_ar(
|
||||
cereal::make_nvp("id", id),
|
||||
cereal::make_nvp("name", name),
|
||||
cereal::make_nvp("type", type)
|
||||
);
|
||||
}
|
||||
|
||||
const string &
|
||||
RateLimitRulesTriggerSection::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
void
|
||||
RateLimitRulesSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
out_ar(
|
||||
cereal::make_nvp("id", id),
|
||||
cereal::make_nvp("URI", uri),
|
||||
cereal::make_nvp("scope", key_to_units_val.at(scope)),
|
||||
cereal::make_nvp("triggers", triggers),
|
||||
cereal::make_nvp("limit", limit)
|
||||
);
|
||||
}
|
||||
|
||||
RateLimitSection::RateLimitSection(
|
||||
const string &asset_name,
|
||||
const string &url,
|
||||
const string &uri,
|
||||
const std::string &_mode,
|
||||
const std::string &_practice_id,
|
||||
const std::string &_name,
|
||||
const std::vector<RateLimitRulesSection> &_rules)
|
||||
:
|
||||
mode(_mode),
|
||||
practice_id(_practice_id),
|
||||
name(_name),
|
||||
rules(_rules)
|
||||
{
|
||||
bool any = asset_name == "Any" && url == "Any" && uri == "Any";
|
||||
string asset_id = any ? "Any" : url+uri;
|
||||
context = "assetId(" + asset_id + ")";
|
||||
}
|
||||
|
||||
void
|
||||
RateLimitSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
out_ar(
|
||||
cereal::make_nvp("context", context),
|
||||
cereal::make_nvp("mode", key_to_mode_val.at(mode)),
|
||||
cereal::make_nvp("practiceId", practice_id),
|
||||
cereal::make_nvp("name", name),
|
||||
cereal::make_nvp("rules", rules)
|
||||
);
|
||||
}
|
||||
|
||||
const string &
|
||||
RateLimitSection::getId() const
|
||||
{
|
||||
return practice_id;
|
||||
}
|
||||
|
||||
const string &
|
||||
RateLimitSection::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
const string &
|
||||
RateLimitSection::getMode() const
|
||||
{
|
||||
return mode;
|
||||
}
|
||||
|
||||
void
|
||||
AccessControlRulebaseSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
vector<string> empty;
|
||||
out_ar(
|
||||
cereal::make_nvp("accessControl", empty),
|
||||
cereal::make_nvp("traditionalFirewall", empty),
|
||||
cereal::make_nvp("l4firewall", empty),
|
||||
cereal::make_nvp("rateLimit", rate_limit)
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
AccessControlRulebaseWrapper::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
out_ar(
|
||||
cereal::make_nvp("rulebase", rule_base)
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
AccessControlRateLimiteRules::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading Access control rate limite rules";
|
||||
parseAppsecJSONKey<int>("limit", limit, archive_in);
|
||||
parseAppsecJSONKey<string>("uri", uri, archive_in);
|
||||
parseAppsecJSONKey<string>("unit", unit, archive_in);
|
||||
if (valid_units.count(unit) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "Access control rate limite rules units invalid: "
|
||||
<< unit;
|
||||
}
|
||||
parseAppsecJSONKey<string>("comment", comment, archive_in);
|
||||
parseAppsecJSONKey<vector<string>>("triggers", triggers, archive_in);
|
||||
}
|
||||
|
||||
const vector<string>
|
||||
AccessControlRateLimiteRules::getTriggers() const
|
||||
{
|
||||
return triggers;
|
||||
}
|
||||
|
||||
RateLimitRulesSection
|
||||
AccessControlRateLimiteRules::createRateLimitRulesSection(const RateLimitRulesTriggerSection &trigger) const
|
||||
{
|
||||
string id = "";
|
||||
try {
|
||||
id = to_string(boost::uuids::random_generator()());
|
||||
} catch (const boost::uuids::entropy_error &e) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "Failed to create random id";
|
||||
}
|
||||
vector<RateLimitRulesTriggerSection> triggers_section;
|
||||
string trigger_name = trigger.getName().substr(trigger.getName().find("/") + 1);
|
||||
if (find(triggers.begin(), triggers.end(), trigger_name) != triggers.end()) {
|
||||
triggers_section.push_back(trigger);
|
||||
}
|
||||
return RateLimitRulesSection(
|
||||
limit,
|
||||
id,
|
||||
uri,
|
||||
unit,
|
||||
triggers_section
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
AccessControlRateLimit::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading Access control rate limit";
|
||||
parseAppsecJSONKey<string>("overrideMode", mode, archive_in, "Inactive");
|
||||
if (valid_modes.count(mode) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec access control rate limit override mode invalid: " << mode;
|
||||
}
|
||||
parseAppsecJSONKey<std::vector<AccessControlRateLimiteRules>>("rules", rules, archive_in);
|
||||
}
|
||||
|
||||
vector<RateLimitRulesSection>
|
||||
AccessControlRateLimit::createRateLimitRulesSection(const RateLimitRulesTriggerSection &trigger) const
|
||||
{
|
||||
vector<RateLimitRulesSection> rules_section;
|
||||
for (const AccessControlRateLimiteRules &rule : rules) {
|
||||
rules_section.push_back(rule.createRateLimitRulesSection(trigger));
|
||||
}
|
||||
return rules_section;
|
||||
}
|
||||
|
||||
const vector<AccessControlRateLimiteRules> &
|
||||
AccessControlRateLimit::getRules() const
|
||||
{
|
||||
return rules;
|
||||
}
|
||||
|
||||
const string &
|
||||
AccessControlRateLimit::getMode() const
|
||||
{
|
||||
return mode;
|
||||
}
|
||||
|
||||
void
|
||||
AccessControlPracticeSpec::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec practice spec";
|
||||
|
||||
parseAppsecJSONKey<string>("name", practice_name, archive_in);
|
||||
parseAppsecJSONKey<string>("appsecClassName", appsec_class_name, archive_in);
|
||||
parseAppsecJSONKey<AccessControlRateLimit>("rateLimit", rate_limit, archive_in);
|
||||
}
|
||||
|
||||
void
|
||||
AccessControlPracticeSpec::setName(const string &_name)
|
||||
{
|
||||
practice_name = _name;
|
||||
}
|
||||
|
||||
const AccessControlRateLimit &
|
||||
AccessControlPracticeSpec::geRateLimit() const
|
||||
{
|
||||
return rate_limit;
|
||||
}
|
||||
|
||||
const string &
|
||||
AccessControlPracticeSpec::getAppSecClassName() const
|
||||
{
|
||||
return appsec_class_name;
|
||||
}
|
||||
|
||||
const string &
|
||||
AccessControlPracticeSpec::getName() const
|
||||
{
|
||||
return practice_name;
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
@@ -34,6 +34,26 @@ AppSecWebBotsURI::getURI() const
|
||||
return uri;
|
||||
}
|
||||
|
||||
vector<string>
|
||||
AppSecPracticeAntiBot::getIjectedUris() const
|
||||
{
|
||||
vector<string> injected;
|
||||
for (const AppSecWebBotsURI &uri : injected_uris) {
|
||||
injected.push_back(uri.getURI());
|
||||
}
|
||||
return injected;
|
||||
}
|
||||
|
||||
vector<string>
|
||||
AppSecPracticeAntiBot::getValidatedUris() const
|
||||
{
|
||||
vector<string> validated;
|
||||
for (const AppSecWebBotsURI &uri : validated_uris) {
|
||||
validated.push_back(uri.getURI());
|
||||
}
|
||||
return validated;
|
||||
}
|
||||
|
||||
void
|
||||
AppSecPracticeAntiBot::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
@@ -52,7 +72,7 @@ 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());
|
||||
for (const AppSecWebBotsURI &uri : validated_uris) validated.push_back(uri.getURI());
|
||||
out_ar(
|
||||
cereal::make_nvp("injected", injected),
|
||||
cereal::make_nvp("validated", validated)
|
||||
@@ -295,24 +315,90 @@ TriggersInWaapSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
);
|
||||
}
|
||||
|
||||
ParsedMatch::ParsedMatch(const string &_operator, const string &_tag, const string &_value)
|
||||
:
|
||||
operator_type(_operator),
|
||||
tag(_tag),
|
||||
value(_value)
|
||||
{
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
ParsedMatch::ParsedMatch(const ExceptionMatch &exceptions)
|
||||
{
|
||||
if (exceptions.getOperator() == "equals") {
|
||||
operator_type = "basic";
|
||||
tag = exceptions.getKey();
|
||||
value = exceptions.getValue();
|
||||
} else {
|
||||
operator_type = exceptions.getOperator();
|
||||
}
|
||||
for (const ExceptionMatch &exception_match : exceptions.getMatch()) {
|
||||
parsed_match.push_back(ParsedMatch(exception_match));
|
||||
}
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
void
|
||||
ParsedMatch::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
if (parsed_match.size() > 0) {
|
||||
out_ar(cereal::make_nvp("operator", operator_type));
|
||||
int i = 0;
|
||||
for (const ParsedMatch &operand : parsed_match) {
|
||||
i++;
|
||||
out_ar(cereal::make_nvp("operand" + to_string(i), operand));
|
||||
}
|
||||
} else {
|
||||
out_ar(
|
||||
cereal::make_nvp("operator", operator_type),
|
||||
cereal::make_nvp("tag", tag),
|
||||
cereal::make_nvp("value", value)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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"}};
|
||||
parsed_match = ParsedMatch("BASIC", "sourceip", "0.0.0.0/0");
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
AppSecOverride::AppSecOverride(const InnerException &parsed_exceptions)
|
||||
:
|
||||
id(parsed_exceptions.getBehaviorId()),
|
||||
parsed_match(parsed_exceptions.getMatch())
|
||||
{
|
||||
map<string, string> behavior = {{parsed_exceptions.getBehaviorKey(), parsed_exceptions.getBehaviorValue()}};
|
||||
parsed_behavior.push_back(behavior);
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
void
|
||||
AppSecOverride::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
string parameter_type = "TrustedSource";
|
||||
if (!id.empty()) {
|
||||
out_ar(cereal::make_nvp("id", id));
|
||||
}
|
||||
out_ar(
|
||||
cereal::make_nvp("parsedBehavior", parsed_behavior),
|
||||
cereal::make_nvp("parsedMatch", parsed_match)
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
AppsecPracticeAntiBotSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
out_ar(
|
||||
cereal::make_nvp("injected", injected_uris),
|
||||
cereal::make_nvp("validated", validated_uris)
|
||||
);
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
WebAppSection::WebAppSection(
|
||||
const string &_application_urls,
|
||||
const string &_asset_id,
|
||||
@@ -321,10 +407,12 @@ WebAppSection::WebAppSection(
|
||||
const string &_rule_name,
|
||||
const string &_practice_id,
|
||||
const string &_practice_name,
|
||||
const string &_context,
|
||||
const AppSecPracticeSpec &parsed_appsec_spec,
|
||||
const LogTriggerSection &parsed_log_trigger,
|
||||
const string &default_mode,
|
||||
const AppSecTrustedSources &parsed_trusted_sources)
|
||||
const AppSecTrustedSources &parsed_trusted_sources,
|
||||
const vector<InnerException> &parsed_exceptions)
|
||||
:
|
||||
application_urls(_application_urls),
|
||||
asset_id(_asset_id),
|
||||
@@ -333,7 +421,7 @@ WebAppSection::WebAppSection(
|
||||
rule_name(_rule_name),
|
||||
practice_id(_practice_id),
|
||||
practice_name(_practice_name),
|
||||
context("practiceId(" + practice_id +")"),
|
||||
context(_context),
|
||||
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),
|
||||
@@ -351,8 +439,56 @@ WebAppSection::WebAppSection(
|
||||
for (const SourcesIdentifiers &source_ident : parsed_trusted_sources.getSourcesIdentifiers()) {
|
||||
overrides.push_back(AppSecOverride(source_ident));
|
||||
}
|
||||
|
||||
for (const InnerException &exception : parsed_exceptions) {
|
||||
overrides.push_back(AppSecOverride(exception));
|
||||
}
|
||||
}
|
||||
|
||||
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 string &_context,
|
||||
const string &_web_attack_mitigation_severity,
|
||||
const string &_web_attack_mitigation_mode,
|
||||
const PracticeAdvancedConfig &_practice_advanced_config,
|
||||
const AppsecPracticeAntiBotSection &_anti_bots,
|
||||
const LogTriggerSection &parsed_log_trigger,
|
||||
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(_context),
|
||||
web_attack_mitigation_severity(_web_attack_mitigation_severity),
|
||||
web_attack_mitigation_mode(_web_attack_mitigation_mode),
|
||||
practice_advanced_config(_practice_advanced_config),
|
||||
anti_bots(_anti_bots),
|
||||
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));
|
||||
}
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
void
|
||||
WebAppSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
@@ -536,7 +672,7 @@ AppsecPolicySpec::getSpecificRules() const
|
||||
}
|
||||
|
||||
bool
|
||||
AppsecPolicySpec::isAssetHostExist(const std::string &full_url) const
|
||||
AppsecPolicySpec::isAssetHostExist(const string &full_url) const
|
||||
{
|
||||
for (const ParsedRule &rule : specific_rules) {
|
||||
if (rule.getHost() == full_url) return true;
|
||||
@@ -558,7 +694,7 @@ AppsecLinuxPolicy::serialize(cereal::JSONInputArchive &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<AppsecException>>("exceptions", exceptions, archive_in);
|
||||
parseAppsecJSONKey<vector<TrustedSourcesSpec>>("trusted-sources", trusted_sources, archive_in);
|
||||
parseAppsecJSONKey<vector<SourceIdentifierSpecWrapper>>(
|
||||
"source-identifiers",
|
||||
@@ -591,8 +727,8 @@ AppsecLinuxPolicy::getAppSecCustomResponseSpecs() const
|
||||
return custom_responses;
|
||||
}
|
||||
|
||||
const vector<AppsecExceptionSpec> &
|
||||
AppsecLinuxPolicy::getAppsecExceptionSpecs() const
|
||||
const vector<AppsecException> &
|
||||
AppsecLinuxPolicy::getAppsecExceptions() const
|
||||
{
|
||||
return exceptions;
|
||||
}
|
||||
58
components/security_apps/local_policy_mgmt_gen/configmaps.cc
Executable file
58
components/security_apps/local_policy_mgmt_gen/configmaps.cc
Executable file
@@ -0,0 +1,58 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "configmaps.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
USE_DEBUG_FLAG(D_LOCAL_POLICY);
|
||||
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
bool
|
||||
ConfigMaps::loadJson(const std::string &json)
|
||||
{
|
||||
string modified_json = json;
|
||||
modified_json.pop_back();
|
||||
stringstream in;
|
||||
in.str(modified_json);
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading ConfigMaps data";
|
||||
try {
|
||||
cereal::JSONInputArchive in_ar(in);
|
||||
in_ar(
|
||||
cereal::make_nvp("data", data)
|
||||
);
|
||||
} catch (cereal::Exception &e) {
|
||||
dbgError(D_LOCAL_POLICY) << "Failed to load ConfigMaps JSON. Error: " << e.what();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
string
|
||||
ConfigMaps::getFileContent() const
|
||||
{
|
||||
if (data.size()) {
|
||||
return data.begin()->second;
|
||||
}
|
||||
return string();
|
||||
}
|
||||
|
||||
string
|
||||
ConfigMaps::getFileName() const
|
||||
{
|
||||
if (data.size()) {
|
||||
return data.begin()->first;
|
||||
}
|
||||
return string();
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
@@ -18,39 +18,61 @@ using namespace std;
|
||||
USE_DEBUG_FLAG(D_LOCAL_POLICY);
|
||||
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
using AttributeGetter = function<vector<string>(const AppsecExceptionSpec&)>;
|
||||
static const vector<pair<string, AttributeGetter>> attributes = {
|
||||
{"countryCode", [](const AppsecExceptionSpec& e){ return e.getCountryCode(); }},
|
||||
{"countryName", [](const AppsecExceptionSpec& e){ return e.getCountryName(); }},
|
||||
{"hostName", [](const AppsecExceptionSpec& e){ return e.getHostName(); }},
|
||||
{"paramName", [](const AppsecExceptionSpec& e){ return e.getParamName(); }},
|
||||
{"paramValue", [](const AppsecExceptionSpec& e){ return e.getParamValue(); }},
|
||||
{"protectionName", [](const AppsecExceptionSpec& e){ return e.getProtectionName(); }},
|
||||
{"sourceIdentifier", [](const AppsecExceptionSpec& e){ return e.getSourceIdentifier(); }},
|
||||
{"sourceIp", [](const AppsecExceptionSpec& e){ return e.getSourceIp(); }},
|
||||
{"url", [](const AppsecExceptionSpec& e){ return e.getUrl(); }}
|
||||
};
|
||||
static const set<string> valid_actions = {"skip", "accept", "drop", "suppressLog"};
|
||||
static const unordered_map<string, string> key_to_action = {
|
||||
{ "accept", "accept"},
|
||||
{ "drop", "reject"},
|
||||
{ "skip", "ignore"},
|
||||
{ "suppressLog", "ignore"}
|
||||
};
|
||||
|
||||
void
|
||||
AppsecExceptionSpec::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec exception spec";
|
||||
parseAppsecJSONKey<string>("name", name, archive_in);
|
||||
parseAppsecJSONKey<string>("action", action, archive_in);
|
||||
parseAppsecJSONKey<string>("action", action, archive_in, "skip");
|
||||
if (valid_actions.count(action) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec exception action invalid: " << action;
|
||||
}
|
||||
|
||||
parseAppsecJSONKey<vector<string>>("countryCode", country_code, archive_in);
|
||||
if (!country_code.empty()) conditions_number++;
|
||||
|
||||
parseAppsecJSONKey<vector<string>>("countryName", country_name, archive_in);
|
||||
if (!country_name.empty()) conditions_number++;
|
||||
|
||||
parseAppsecJSONKey<vector<string>>("hostName", host_name, archive_in);
|
||||
if (!host_name.empty()) conditions_number++;
|
||||
|
||||
parseAppsecJSONKey<vector<string>>("paramName", param_name, archive_in);
|
||||
if (!param_name.empty()) conditions_number++;
|
||||
|
||||
parseAppsecJSONKey<vector<string>>("paramValue", param_value, archive_in);
|
||||
if (!param_value.empty()) conditions_number++;
|
||||
|
||||
parseAppsecJSONKey<vector<string>>("protectionName", protection_name, archive_in);
|
||||
if (!protection_name.empty()) conditions_number++;
|
||||
|
||||
parseAppsecJSONKey<vector<string>>("sourceIdentifier", source_identifier, archive_in);
|
||||
if (!source_identifier.empty()) conditions_number++;
|
||||
|
||||
parseAppsecJSONKey<vector<string>>("sourceIp", source_ip, archive_in);
|
||||
if (!source_ip.empty()) conditions_number++;
|
||||
|
||||
parseAppsecJSONKey<vector<string>>("url", url, archive_in);
|
||||
}
|
||||
|
||||
void
|
||||
AppsecExceptionSpec::setName(const string &_name)
|
||||
{
|
||||
name = _name;
|
||||
}
|
||||
|
||||
const string &
|
||||
AppsecExceptionSpec::getName() const
|
||||
{
|
||||
return name;
|
||||
if (!url.empty()) conditions_number++;
|
||||
}
|
||||
|
||||
const string &
|
||||
@@ -113,10 +135,89 @@ AppsecExceptionSpec::getUrl() const
|
||||
return url;
|
||||
}
|
||||
|
||||
bool
|
||||
AppsecExceptionSpec::isOneCondition() const
|
||||
{
|
||||
return conditions_number == 1;
|
||||
}
|
||||
|
||||
void
|
||||
AppsecException::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec exception";
|
||||
parseAppsecJSONKey<string>("name", name, archive_in);
|
||||
archive_in(CEREAL_NVP(exception_spec));
|
||||
}
|
||||
|
||||
void
|
||||
AppsecException::setName(const string &_name)
|
||||
{
|
||||
name = _name;
|
||||
}
|
||||
|
||||
const string &
|
||||
AppsecException::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
const vector<AppsecExceptionSpec> &
|
||||
AppsecException::getExceptions() const
|
||||
{
|
||||
return exception_spec;
|
||||
}
|
||||
|
||||
ExceptionMatch::ExceptionMatch(const AppsecExceptionSpec &parsed_exception)
|
||||
:
|
||||
match_type(MatchType::Operator),
|
||||
op("and")
|
||||
{
|
||||
bool single_condition = parsed_exception.isOneCondition();
|
||||
for (auto &attrib : attributes) {
|
||||
auto &attrib_name = attrib.first;
|
||||
auto &attrib_getter = attrib.second;
|
||||
auto exceptions_value = attrib_getter(parsed_exception);
|
||||
if (exceptions_value.empty()) continue;
|
||||
if (single_condition) {
|
||||
if (exceptions_value.size() == 1) {
|
||||
match_type = MatchType::Condition;
|
||||
op = "equals";
|
||||
key = attrib_name;
|
||||
value = exceptions_value;
|
||||
return;
|
||||
} else {
|
||||
match_type = MatchType::Operator;
|
||||
op = "or";
|
||||
for (auto new_value : exceptions_value) {
|
||||
items.push_back(ExceptionMatch(attrib_name, {new_value}));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
items.push_back(ExceptionMatch(attrib_name, exceptions_value));
|
||||
}
|
||||
}
|
||||
|
||||
ExceptionMatch::ExceptionMatch(const std::string &_key, const std::vector<std::string> &values)
|
||||
{
|
||||
if (values.size() == 1) {
|
||||
match_type = MatchType::Condition;
|
||||
op = "equals";
|
||||
key = _key;
|
||||
value = values;
|
||||
} else {
|
||||
match_type = MatchType::Operator;
|
||||
op = "or";
|
||||
for (auto new_value : values) {
|
||||
items.push_back(ExceptionMatch(_key, {new_value}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExceptionMatch::ExceptionMatch(const NewAppsecException &parsed_exception)
|
||||
:
|
||||
match_type(MatchType::Operator),
|
||||
op("and")
|
||||
{
|
||||
if (!parsed_exception.getCountryCode().empty()) {
|
||||
items.push_back(ExceptionMatch("countryCode", parsed_exception.getCountryCode()));
|
||||
@@ -176,13 +277,34 @@ ExceptionMatch::save(cereal::JSONOutputArchive &out_ar) const
|
||||
}
|
||||
}
|
||||
|
||||
ExceptionBehavior::ExceptionBehavior(
|
||||
const string &_key,
|
||||
const string &_value)
|
||||
:
|
||||
key(_key),
|
||||
value(_value)
|
||||
const string &
|
||||
ExceptionMatch::getOperator() const
|
||||
{
|
||||
return op;
|
||||
}
|
||||
|
||||
const string &
|
||||
ExceptionMatch::getKey() const
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
const string &
|
||||
ExceptionMatch::getValue() const
|
||||
{
|
||||
return value[0];
|
||||
}
|
||||
|
||||
const vector<ExceptionMatch> &
|
||||
ExceptionMatch::getMatch() const
|
||||
{
|
||||
return items;
|
||||
}
|
||||
|
||||
ExceptionBehavior::ExceptionBehavior(const string &_value)
|
||||
{
|
||||
key = _value == "suppressLog" ? "log" : "action";
|
||||
value = key_to_action.at(_value);
|
||||
try {
|
||||
id = to_string(boost::uuids::random_generator()());
|
||||
} catch (const boost::uuids::entropy_error &e) {
|
||||
@@ -200,12 +322,31 @@ ExceptionBehavior::save(cereal::JSONOutputArchive &out_ar) const
|
||||
);
|
||||
}
|
||||
|
||||
const string
|
||||
const string &
|
||||
ExceptionBehavior::getBehaviorId() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
const string &
|
||||
ExceptionBehavior::getBehaviorKey() const
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
const string &
|
||||
ExceptionBehavior::getBehaviorValue() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
InnerException::InnerException(ExceptionBehavior _behavior, ExceptionMatch _match)
|
||||
:
|
||||
behavior(_behavior),
|
||||
match(_match)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
InnerException::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
@@ -215,12 +356,30 @@ InnerException::save(cereal::JSONOutputArchive &out_ar) const
|
||||
);
|
||||
}
|
||||
|
||||
const string
|
||||
const string &
|
||||
InnerException::getBehaviorId() const
|
||||
{
|
||||
return behavior.getBehaviorId();
|
||||
}
|
||||
|
||||
const string &
|
||||
InnerException::getBehaviorKey() const
|
||||
{
|
||||
return behavior.getBehaviorKey();
|
||||
}
|
||||
|
||||
const string &
|
||||
InnerException::getBehaviorValue() const
|
||||
{
|
||||
return behavior.getBehaviorValue();
|
||||
}
|
||||
|
||||
const ExceptionMatch &
|
||||
InnerException::getMatch() const
|
||||
{
|
||||
return match;
|
||||
}
|
||||
|
||||
ExceptionsRulebase::ExceptionsRulebase(
|
||||
vector<InnerException> _exceptions)
|
||||
:
|
||||
192
components/security_apps/local_policy_mgmt_gen/include/access_control_practice.h
Executable file
192
components/security_apps/local_policy_mgmt_gen/include/access_control_practice.h
Executable file
@@ -0,0 +1,192 @@
|
||||
// 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 __ACCESS_CONTROL_PRACTICE_H__
|
||||
#define __ACCESS_CONTROL_PRACTICE_H__
|
||||
|
||||
#include <string>
|
||||
#include <cereal/archives/json.hpp>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/uuid/uuid_generators.hpp>
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "local_policy_common.h"
|
||||
|
||||
class RateLimitRulesTriggerSection
|
||||
{
|
||||
public:
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
RateLimitRulesTriggerSection() {};
|
||||
|
||||
RateLimitRulesTriggerSection(
|
||||
const std::string &_id,
|
||||
const std::string &_name,
|
||||
const std::string &_type
|
||||
)
|
||||
:
|
||||
id(_id),
|
||||
name(_name),
|
||||
type(_type)
|
||||
{};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
const std::string & getName() const;
|
||||
|
||||
private:
|
||||
std::string id;
|
||||
std::string name;
|
||||
std::string type;;
|
||||
};
|
||||
|
||||
class RateLimitRulesSection
|
||||
{
|
||||
public:
|
||||
RateLimitRulesSection() {};
|
||||
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
RateLimitRulesSection(
|
||||
const int _limit,
|
||||
const std::string &_id,
|
||||
const std::string &_uri,
|
||||
const std::string &_scope,
|
||||
const std::vector<RateLimitRulesTriggerSection> &_triggers
|
||||
)
|
||||
:
|
||||
limit(_limit),
|
||||
id(_id),
|
||||
uri(_uri),
|
||||
scope(_scope),
|
||||
triggers(_triggers)
|
||||
{};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
int limit;
|
||||
std::string id;
|
||||
std::string uri;
|
||||
std::string scope;
|
||||
std::vector<RateLimitRulesTriggerSection> triggers;
|
||||
};
|
||||
|
||||
class RateLimitSection
|
||||
{
|
||||
public:
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
RateLimitSection() {};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
RateLimitSection(
|
||||
const std::string &asset_name,
|
||||
const std::string &url,
|
||||
const std::string &uri,
|
||||
const std::string &_mode,
|
||||
const std::string &_practice_id,
|
||||
const std::string &_name,
|
||||
const std::vector<RateLimitRulesSection> &_rules);
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
const std::string & getId() const;
|
||||
const std::string & getName() const;
|
||||
const std::string & getMode() const;
|
||||
|
||||
private:
|
||||
std::string context;
|
||||
std::string mode;
|
||||
std::string practice_id;
|
||||
std::string name;
|
||||
std::vector<RateLimitRulesSection> rules;
|
||||
};
|
||||
|
||||
class AccessControlRulebaseSection
|
||||
{
|
||||
public:
|
||||
AccessControlRulebaseSection() {};
|
||||
|
||||
AccessControlRulebaseSection(const std::vector<RateLimitSection> &_rate_limit) : rate_limit(_rate_limit) {};
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
std::vector<RateLimitSection> rate_limit;
|
||||
};
|
||||
|
||||
class AccessControlRulebaseWrapper
|
||||
{
|
||||
public:
|
||||
AccessControlRulebaseWrapper() {};
|
||||
|
||||
AccessControlRulebaseWrapper(
|
||||
const std::vector<RateLimitSection> &rate_limits
|
||||
)
|
||||
:
|
||||
rule_base(AccessControlRulebaseSection(rate_limits))
|
||||
{};
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
AccessControlRulebaseSection rule_base;
|
||||
};
|
||||
|
||||
class AccessControlRateLimiteRules
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const std::vector<std::string> getTriggers() const;
|
||||
RateLimitRulesSection createRateLimitRulesSection(const RateLimitRulesTriggerSection &trigger) const;
|
||||
|
||||
private:
|
||||
int limit;
|
||||
std::string uri;
|
||||
std::string unit;
|
||||
std::string comment;
|
||||
std::vector<std::string> triggers;
|
||||
};
|
||||
|
||||
class AccessControlRateLimit
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const std::vector<AccessControlRateLimiteRules> & getRules() const;
|
||||
const std::string & getMode() const;
|
||||
std::vector<RateLimitRulesSection> createRateLimitRulesSection(const RateLimitRulesTriggerSection &trigger) const;
|
||||
|
||||
private:
|
||||
std::string mode;
|
||||
std::vector<AccessControlRateLimiteRules> rules;
|
||||
};
|
||||
|
||||
class AccessControlPracticeSpec
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const AccessControlRateLimit & geRateLimit() const;
|
||||
const std::string & getAppSecClassName() const;
|
||||
const std::string & getName() const;
|
||||
void setName(const std::string &_name);
|
||||
|
||||
private:
|
||||
AccessControlRateLimit rate_limit;
|
||||
std::string appsec_class_name;
|
||||
std::string practice_name;
|
||||
};
|
||||
|
||||
#endif // __ACCESS_CONTROL_PRACTICE_H__
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "triggers_section.h"
|
||||
#include "exceptions_section.h"
|
||||
#include "trusted_sources_section.h"
|
||||
#include "new_practice.h"
|
||||
|
||||
class AppSecWebBotsURI
|
||||
{
|
||||
@@ -43,6 +44,9 @@ private:
|
||||
class AppSecPracticeAntiBot
|
||||
{
|
||||
public:
|
||||
std::vector<std::string> getIjectedUris() const;
|
||||
std::vector<std::string> getValidatedUris() const;
|
||||
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
@@ -152,6 +156,22 @@ public:
|
||||
url_max_size(parsed_appsec_spec.getWebAttacks().getMaxUrlSizeBytes())
|
||||
{}
|
||||
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
PracticeAdvancedConfig(
|
||||
int _http_header_max_size,
|
||||
int _http_request_body_max_size,
|
||||
int _json_max_object_depth,
|
||||
int _url_max_size)
|
||||
:
|
||||
http_header_max_size(_http_header_max_size),
|
||||
http_illegal_methods_allowed(0),
|
||||
http_request_body_max_size(_http_request_body_max_size),
|
||||
json_max_object_depth(_json_max_object_depth),
|
||||
url_max_size(_url_max_size)
|
||||
{}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
@@ -182,16 +202,58 @@ private:
|
||||
LogTriggerSection log;
|
||||
};
|
||||
|
||||
class AppSecOverride
|
||||
class ParsedMatch
|
||||
{
|
||||
public:
|
||||
AppSecOverride(const SourcesIdentifiers &parsed_trusted_sources);
|
||||
ParsedMatch() {}
|
||||
ParsedMatch(const std::string &_operator, const std::string &_tag, const std::string &_value);
|
||||
|
||||
ParsedMatch(const ExceptionMatch &exceptions);
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
std::string operator_type;
|
||||
std::string tag;
|
||||
std::string value;
|
||||
std::vector<ParsedMatch> parsed_match;
|
||||
};
|
||||
|
||||
class AppSecOverride
|
||||
{
|
||||
public:
|
||||
AppSecOverride(const SourcesIdentifiers &parsed_trusted_sources);
|
||||
AppSecOverride(const InnerException &parsed_exceptions);
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
std::string id;
|
||||
std::vector<std::map<std::string, std::string>> parsed_behavior;
|
||||
std::map<std::string, std::string> parsed_match;
|
||||
ParsedMatch parsed_match;
|
||||
};
|
||||
|
||||
class AppsecPracticeAntiBotSection
|
||||
{
|
||||
public:
|
||||
AppsecPracticeAntiBotSection() {};
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
AppsecPracticeAntiBotSection(const NewAppSecPracticeAntiBot &anti_bot) :
|
||||
injected_uris(anti_bot.getIjectedUris()),
|
||||
validated_uris(anti_bot.getValidatedUris())
|
||||
{};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
AppsecPracticeAntiBotSection(const AppSecPracticeAntiBot &anti_bot) :
|
||||
injected_uris(anti_bot.getIjectedUris()),
|
||||
validated_uris(anti_bot.getValidatedUris())
|
||||
{};
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
std::vector<std::string> injected_uris;
|
||||
std::vector<std::string> validated_uris;
|
||||
};
|
||||
|
||||
class WebAppSection
|
||||
@@ -207,12 +269,30 @@ public:
|
||||
const std::string &_rule_name,
|
||||
const std::string &_practice_id,
|
||||
const std::string &_practice_name,
|
||||
const std::string &_context,
|
||||
const AppSecPracticeSpec &parsed_appsec_spec,
|
||||
const LogTriggerSection &parsed_log_trigger,
|
||||
const std::string &default_mode,
|
||||
const AppSecTrustedSources &parsed_trusted_sources
|
||||
const AppSecTrustedSources &parsed_trusted_sources,
|
||||
const std::vector<InnerException> &parsed_exceptions
|
||||
);
|
||||
|
||||
WebAppSection(
|
||||
const std::string &_application_urls,
|
||||
const std::string &_asset_id,
|
||||
const std::string &_asset_name,
|
||||
const std::string &_rule_id,
|
||||
const std::string &_rule_name,
|
||||
const std::string &_practice_id,
|
||||
const std::string &_practice_name,
|
||||
const std::string &_context,
|
||||
const std::string &_web_attack_mitigation_severity,
|
||||
const std::string &_web_attack_mitigation_mode,
|
||||
const PracticeAdvancedConfig &_practice_advanced_config,
|
||||
const AppsecPracticeAntiBotSection &_anti_bots,
|
||||
const LogTriggerSection &parsed_log_trigger,
|
||||
const AppSecTrustedSources &parsed_trusted_sources);
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
@@ -230,7 +310,7 @@ private:
|
||||
bool web_attack_mitigation;
|
||||
std::vector<TriggersInWaapSection> triggers;
|
||||
PracticeAdvancedConfig practice_advanced_config;
|
||||
AppSecPracticeAntiBot anti_bots;
|
||||
AppsecPracticeAntiBotSection anti_bots;
|
||||
std::vector<AppSecTrustedSources> trusted_sources;
|
||||
std::vector<AppSecOverride> overrides;
|
||||
};
|
||||
@@ -250,7 +330,7 @@ public:
|
||||
const std::string &_web_attack_mitigation_severity,
|
||||
const std::string &_web_attack_mitigation_mode,
|
||||
bool _web_attack_mitigation,
|
||||
const AppSecPracticeSpec &parsed_appsec_spec)
|
||||
const PracticeAdvancedConfig &_practice_advanced_config)
|
||||
:
|
||||
application_urls(_application_urls),
|
||||
asset_id(_asset_id),
|
||||
@@ -264,7 +344,7 @@ public:
|
||||
web_attack_mitigation_severity(_web_attack_mitigation_severity),
|
||||
web_attack_mitigation_mode(_web_attack_mitigation_mode),
|
||||
web_attack_mitigation(_web_attack_mitigation),
|
||||
practice_advanced_config(parsed_appsec_spec)
|
||||
practice_advanced_config(_practice_advanced_config)
|
||||
{}
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
@@ -302,6 +382,7 @@ private:
|
||||
std::vector<WebAPISection> webAPIPractices;
|
||||
};
|
||||
|
||||
|
||||
class AppSecWrapper
|
||||
{
|
||||
public:
|
||||
@@ -369,7 +450,7 @@ public:
|
||||
const std::vector<AppSecPracticeSpec> &_practices,
|
||||
const std::vector<AppsecTriggerSpec> &_log_triggers,
|
||||
const std::vector<AppSecCustomResponseSpec> &_custom_responses,
|
||||
const std::vector<AppsecExceptionSpec> &_exceptions,
|
||||
const std::vector<AppsecException> &_exceptions,
|
||||
const std::vector<TrustedSourcesSpec> &_trusted_sources,
|
||||
const std::vector<SourceIdentifierSpecWrapper> &_sources_identifiers)
|
||||
:
|
||||
@@ -387,7 +468,7 @@ public:
|
||||
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<AppsecException> & getAppsecExceptions() const;
|
||||
const std::vector<TrustedSourcesSpec> & getAppsecTrustedSourceSpecs() const;
|
||||
const std::vector<SourceIdentifierSpecWrapper> & getAppsecSourceIdentifierSpecs() const;
|
||||
void addSpecificRule(const ParsedRule &_rule);
|
||||
@@ -397,7 +478,7 @@ private:
|
||||
std::vector<AppSecPracticeSpec> practices;
|
||||
std::vector<AppsecTriggerSpec> log_triggers;
|
||||
std::vector<AppSecCustomResponseSpec> custom_responses;
|
||||
std::vector<AppsecExceptionSpec> exceptions;
|
||||
std::vector<AppsecException> exceptions;
|
||||
std::vector<TrustedSourcesSpec> trusted_sources;
|
||||
std::vector<SourceIdentifierSpecWrapper> sources_identifiers;
|
||||
};
|
||||
41
components/security_apps/local_policy_mgmt_gen/include/configmaps.h
Executable file
41
components/security_apps/local_policy_mgmt_gen/include/configmaps.h
Executable file
@@ -0,0 +1,41 @@
|
||||
// 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 __CONFIGMAPS_H__
|
||||
#define __CONFIGMAPS_H__
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "rest.h"
|
||||
#include "cereal/archives/json.hpp"
|
||||
#include <cereal/types/map.hpp>
|
||||
#include "customized_cereal_map.h"
|
||||
|
||||
#include "local_policy_common.h"
|
||||
|
||||
class ConfigMaps : public ClientRest
|
||||
{
|
||||
public:
|
||||
bool loadJson(const std::string &json);
|
||||
|
||||
std::string getFileContent() const;
|
||||
std::string getFileName() const;
|
||||
|
||||
private:
|
||||
std::map<std::string, std::string> data;
|
||||
};
|
||||
|
||||
#endif // __CONFIGMAPS_H__
|
||||
@@ -24,13 +24,13 @@
|
||||
#include "debug.h"
|
||||
#include "rest.h"
|
||||
#include "local_policy_common.h"
|
||||
#include "new_exceptions.h"
|
||||
|
||||
class AppsecExceptionSpec
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const std::string & getName() const;
|
||||
const std::string & getAction() const;
|
||||
const std::vector<std::string> & getCountryCode() const;
|
||||
const std::vector<std::string> & getCountryName() const;
|
||||
@@ -41,10 +41,10 @@ public:
|
||||
const std::vector<std::string> & getSourceIdentifier() const;
|
||||
const std::vector<std::string> & getSourceIp() const;
|
||||
const std::vector<std::string> & getUrl() const;
|
||||
void setName(const std::string &_name);
|
||||
bool isOneCondition() const;
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
int conditions_number;
|
||||
std::string action;
|
||||
std::vector<std::string> country_code;
|
||||
std::vector<std::string> country_name;
|
||||
@@ -57,20 +57,42 @@ private:
|
||||
std::vector<std::string> url;
|
||||
};
|
||||
|
||||
class AppsecException
|
||||
{
|
||||
public:
|
||||
AppsecException() {};
|
||||
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
AppsecException(const std::string &_name, const std::vector<AppsecExceptionSpec> &_exception_spec)
|
||||
:
|
||||
name(_name),
|
||||
exception_spec(_exception_spec) {};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const std::string & getName() const;
|
||||
const std::vector<AppsecExceptionSpec> & getExceptions() const;
|
||||
void setName(const std::string &_name);
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
std::vector<AppsecExceptionSpec> exception_spec;
|
||||
};
|
||||
|
||||
class ExceptionMatch
|
||||
{
|
||||
public:
|
||||
ExceptionMatch() {}
|
||||
ExceptionMatch(const AppsecExceptionSpec &parsed_exception);
|
||||
ExceptionMatch(const std::string &_key, const std::vector<std::string> &_value)
|
||||
:
|
||||
match_type(MatchType::Condition),
|
||||
key(_key),
|
||||
op("in"),
|
||||
value(_value)
|
||||
{}
|
||||
ExceptionMatch(const std::string &_key, const std::vector<std::string> &_value);
|
||||
ExceptionMatch(const NewAppsecException &parsed_exception);
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
const std::string & getOperator() const;
|
||||
const std::string & getKey() const;
|
||||
const std::string & getValue() const;
|
||||
const std::vector<ExceptionMatch> & getMatch() const;
|
||||
|
||||
private:
|
||||
MatchType match_type;
|
||||
@@ -84,13 +106,12 @@ class ExceptionBehavior
|
||||
{
|
||||
public:
|
||||
ExceptionBehavior() {}
|
||||
ExceptionBehavior(
|
||||
const std::string &_key,
|
||||
const std::string &_value
|
||||
);
|
||||
ExceptionBehavior(const std::string &_value);
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
const std::string getBehaviorId() const;
|
||||
const std::string & getBehaviorId() const;
|
||||
const std::string & getBehaviorKey() const;
|
||||
const std::string & getBehaviorValue() const;
|
||||
|
||||
private:
|
||||
std::string key;
|
||||
@@ -102,15 +123,13 @@ class InnerException
|
||||
{
|
||||
public:
|
||||
InnerException() {}
|
||||
InnerException(
|
||||
ExceptionBehavior _behavior,
|
||||
ExceptionMatch _match)
|
||||
:
|
||||
behavior(_behavior),
|
||||
match(_match) {}
|
||||
InnerException(ExceptionBehavior _behavior, ExceptionMatch _match);
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
const std::string getBehaviorId() const;
|
||||
const std::string & getBehaviorId() const;
|
||||
const std::string & getBehaviorKey() const;
|
||||
const std::string & getBehaviorValue() const;
|
||||
const ExceptionMatch & getMatch() const;
|
||||
|
||||
private:
|
||||
ExceptionBehavior behavior;
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "i_env_details.h"
|
||||
#include "i_agent_details.h"
|
||||
#include "appsec_practice_section.h"
|
||||
#include "new_appsec_linux_policy.h"
|
||||
#include "policy_maker_utils.h"
|
||||
|
||||
enum class AnnotationKeys { PolicyKey, OpenAppsecIo, SyslogAddressKey, SyslogPortKey, ModeKey };
|
||||
@@ -44,8 +45,9 @@ class K8sPolicyUtils
|
||||
public:
|
||||
void init();
|
||||
|
||||
std::map<std::string, AppsecLinuxPolicy> createAppsecPoliciesFromIngresses();
|
||||
bool getClusterId() const;
|
||||
std::tuple<std::map<std::string, AppsecLinuxPolicy>, std::map<std::string, V1beta2AppsecLinuxPolicy>>
|
||||
createAppsecPoliciesFromIngresses();
|
||||
void getClusterId() const;
|
||||
|
||||
private:
|
||||
std::map<AnnotationKeys, std::string> parseIngressAnnotations(
|
||||
@@ -60,13 +62,48 @@ private:
|
||||
const ParsedRule &default_rule
|
||||
) const;
|
||||
|
||||
std::map<AnnotationTypes, std::unordered_set<std::string>> extractElementsNamesV1beta2(
|
||||
const std::vector<NewParsedRule> &specific_rules,
|
||||
const NewParsedRule &default_rule
|
||||
) const;
|
||||
|
||||
std::vector<AppsecException> extractExceptionsFromCluster(
|
||||
const std::string &crd_plural,
|
||||
const std::unordered_set<std::string> &elements_names
|
||||
) const;
|
||||
|
||||
template<class T>
|
||||
std::vector<T> extractElementsFromCluster(
|
||||
const std::string &crd_plural,
|
||||
const std::unordered_set<std::string> &elements_names
|
||||
) const;
|
||||
|
||||
Maybe<AppsecLinuxPolicy> createAppsecPolicyK8s(
|
||||
void createSnortFile(std::vector<NewAppSecPracticeSpec> &practices) const;
|
||||
|
||||
template<class T>
|
||||
std::vector<T> extractV1Beta2ElementsFromCluster(
|
||||
const std::string &crd_plural,
|
||||
const std::unordered_set<std::string> &elements_names
|
||||
) const;
|
||||
|
||||
Maybe<AppsecLinuxPolicy> createAppsecPolicyK8sFromV1beta1Crds(
|
||||
const AppsecSpecParser<AppsecPolicySpec> &appsec_policy_spe,
|
||||
const std::string &ingress_mode
|
||||
) const;
|
||||
|
||||
Maybe<V1beta2AppsecLinuxPolicy> createAppsecPolicyK8sFromV1beta2Crds(
|
||||
const AppsecSpecParser<NewAppsecPolicySpec> &appsec_policy_spe,
|
||||
const std::string &ingress_mode
|
||||
) const;
|
||||
|
||||
template<class T, class K>
|
||||
void createPolicy(
|
||||
T &appsec_policy,
|
||||
std::map<std::string, T> &policies,
|
||||
std::map<AnnotationKeys, std::string> &annotations_values,
|
||||
const SingleIngressData &item) const;
|
||||
|
||||
std::tuple<Maybe<AppsecLinuxPolicy>, Maybe<V1beta2AppsecLinuxPolicy>> createAppsecPolicyK8s(
|
||||
const std::string &policy_name,
|
||||
const std::string &ingress_mode
|
||||
) const;
|
||||
@@ -22,10 +22,13 @@
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "rest.h"
|
||||
#include "cereal/archives/json.hpp"
|
||||
#include <cereal/types/map.hpp>
|
||||
#include "customized_cereal_map.h"
|
||||
|
||||
USE_DEBUG_FLAG(D_LOCAL_POLICY);
|
||||
|
||||
enum class PracticeType { WebApplication, WebAPI };
|
||||
enum class PracticeType { WebApplication, WebAPI, RateLimit };
|
||||
enum class TriggerType { Log, WebUserResponse };
|
||||
enum class MatchType { Condition, Operator };
|
||||
|
||||
@@ -36,7 +39,8 @@ static const std::unordered_map<std::string, MatchType> string_to_match_type = {
|
||||
|
||||
static const std::unordered_map<std::string, PracticeType> string_to_practice_type = {
|
||||
{ "WebApplication", PracticeType::WebApplication },
|
||||
{ "WebAPI", PracticeType::WebAPI }
|
||||
{ "WebAPI", PracticeType::WebAPI },
|
||||
{ "RateLimit", PracticeType::RateLimit }
|
||||
};
|
||||
|
||||
static const std::unordered_map<std::string, TriggerType> string_to_trigger_type = {
|
||||
@@ -73,6 +77,26 @@ parseAppsecJSONKey(
|
||||
}
|
||||
}
|
||||
|
||||
class AppsecSpecParserMetaData
|
||||
{
|
||||
public:
|
||||
void
|
||||
load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "AppsecSpecParserMetaData load";
|
||||
parseAppsecJSONKey<std::map<std::string, std::string>>("annotations", annotations, archive_in);
|
||||
}
|
||||
|
||||
const std::map<std::string, std::string> &
|
||||
getAnnotations() const
|
||||
{
|
||||
return annotations;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, std::string> annotations;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class AppsecSpecParser : public ClientRest
|
||||
{
|
||||
@@ -90,6 +114,7 @@ public:
|
||||
try {
|
||||
cereal::JSONInputArchive in_ar(ss);
|
||||
in_ar(cereal::make_nvp("spec", spec));
|
||||
in_ar(cereal::make_nvp("metadata", meta_data));
|
||||
} catch (cereal::Exception &e) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "Failed to load spec JSON. Error: " << e.what();
|
||||
return false;
|
||||
@@ -103,10 +128,17 @@ public:
|
||||
spec.setName(_name);
|
||||
}
|
||||
|
||||
const AppsecSpecParserMetaData &
|
||||
getMetaData() const
|
||||
{
|
||||
return meta_data;
|
||||
}
|
||||
|
||||
const T & getSpec() const { return spec; }
|
||||
|
||||
private:
|
||||
T spec;
|
||||
AppsecSpecParserMetaData meta_data;
|
||||
};
|
||||
|
||||
#endif // __LOCAL_POLICY_COMMON_H__
|
||||
@@ -0,0 +1,84 @@
|
||||
// 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 __NEW_APPSEC_LINUX_POLICY_H__
|
||||
#define __NEW_APPSEC_LINUX_POLICY_H__
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#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>
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "customized_cereal_map.h"
|
||||
#include "new_appsec_policy_crd_parser.h"
|
||||
#include "new_custom_response.h"
|
||||
#include "new_exceptions.h"
|
||||
#include "new_log_trigger.h"
|
||||
#include "new_practice.h"
|
||||
#include "access_control_practice.h"
|
||||
#include "new_trusted_sources.h"
|
||||
|
||||
|
||||
class V1beta2AppsecLinuxPolicy : Singleton::Consume<I_Environment>
|
||||
{
|
||||
public:
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
V1beta2AppsecLinuxPolicy() {}
|
||||
|
||||
V1beta2AppsecLinuxPolicy(
|
||||
const NewAppsecPolicySpec &_policies,
|
||||
const std::vector<NewAppSecPracticeSpec> &_threat_prevention_practices,
|
||||
const std::vector<AccessControlPracticeSpec> &_access_control_practices,
|
||||
const std::vector<NewAppsecLogTrigger> &_log_triggers,
|
||||
const std::vector<NewAppSecCustomResponse> &_custom_responses,
|
||||
const std::vector<NewAppsecException> &_exceptions,
|
||||
const std::vector<NewTrustedSourcesSpec> &_trusted_sources,
|
||||
const std::vector<NewSourcesIdentifiers> &_sources_identifiers)
|
||||
:
|
||||
policies(_policies),
|
||||
threat_prevection_practices(_threat_prevention_practices),
|
||||
access_control_practices(_access_control_practices),
|
||||
log_triggers(_log_triggers),
|
||||
custom_responses(_custom_responses),
|
||||
exceptions(_exceptions),
|
||||
trusted_sources(_trusted_sources),
|
||||
sources_identifiers(_sources_identifiers) {}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
const NewAppsecPolicySpec & getAppsecPolicySpec() const;
|
||||
const std::vector<NewAppSecPracticeSpec> & getAppSecPracticeSpecs() const;
|
||||
const std::vector<AccessControlPracticeSpec> & getAccessControlPracticeSpecs() const;
|
||||
const std::vector<NewAppsecLogTrigger> & getAppsecTriggerSpecs() const;
|
||||
const std::vector<NewAppSecCustomResponse> & getAppSecCustomResponseSpecs() const;
|
||||
const std::vector<NewAppsecException> & getAppsecExceptions() const;
|
||||
const std::vector<NewTrustedSourcesSpec> & getAppsecTrustedSourceSpecs() const;
|
||||
const std::vector<NewSourcesIdentifiers> & getAppsecSourceIdentifierSpecs() const;
|
||||
void addSpecificRule(const NewParsedRule &_rule);
|
||||
|
||||
private:
|
||||
NewAppsecPolicySpec policies;
|
||||
std::vector<NewAppSecPracticeSpec> threat_prevection_practices;
|
||||
std::vector<AccessControlPracticeSpec> access_control_practices;
|
||||
std::vector<NewAppsecLogTrigger> log_triggers;
|
||||
std::vector<NewAppSecCustomResponse> custom_responses;
|
||||
std::vector<NewAppsecException> exceptions;
|
||||
std::vector<NewTrustedSourcesSpec> trusted_sources;
|
||||
std::vector<NewSourcesIdentifiers> sources_identifiers;
|
||||
};
|
||||
|
||||
#endif // __NEW_APPSEC_LINUX_POLICY_H__
|
||||
@@ -0,0 +1,82 @@
|
||||
// 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 __NEW_APPSEC_POLICY_CRD_PARSER_H__
|
||||
#define __NEW_APPSEC_POLICY_CRD_PARSER_H__
|
||||
|
||||
#include <string>
|
||||
#include <cereal/archives/json.hpp>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/uuid/uuid_generators.hpp>
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "rest.h"
|
||||
#include "local_policy_common.h"
|
||||
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
|
||||
class NewParsedRule
|
||||
{
|
||||
public:
|
||||
NewParsedRule() {}
|
||||
NewParsedRule(const std::string &_host) : host(_host) {}
|
||||
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const std::vector<std::string> & getLogTriggers() const;
|
||||
const std::vector<std::string> & getExceptions() const;
|
||||
const std::vector<std::string> & getPractices() const;
|
||||
const std::vector<std::string> & getAccessControlPractices() const;
|
||||
const std::string & getSourceIdentifiers() const;
|
||||
const std::string & getCustomResponse() const;
|
||||
const std::string & getTrustedSources() const;
|
||||
const std::string & getHost() const;
|
||||
const std::string & getMode() const;
|
||||
|
||||
void setHost(const std::string &_host);
|
||||
void setMode(const std::string &_mode);
|
||||
|
||||
private:
|
||||
std::vector<std::string> log_triggers;
|
||||
std::vector<std::string> exceptions;
|
||||
std::vector<std::string> threat_prevention_practices;
|
||||
std::vector<std::string> access_control_practices;
|
||||
std::string source_identifiers;
|
||||
std::string custom_response;
|
||||
std::string trusted_sources;
|
||||
std::string host;
|
||||
std::string mode;
|
||||
};
|
||||
|
||||
class NewAppsecPolicySpec : Singleton::Consume<I_Environment>
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const NewParsedRule & getDefaultRule() const;
|
||||
const std::vector<NewParsedRule> & getSpecificRules() const;
|
||||
const std::string & getAppSecClassName() const;
|
||||
bool isAssetHostExist(const std::string &full_url) const;
|
||||
void addSpecificRule(const NewParsedRule &_rule);
|
||||
|
||||
private:
|
||||
std::string appsec_class_name;
|
||||
NewParsedRule default_rule;
|
||||
std::vector<NewParsedRule> specific_rules;
|
||||
};
|
||||
|
||||
|
||||
#endif // __NEW_APPSEC_POLICY_CRD_PARSER_H__
|
||||
// LCOV_EXCL_STOP
|
||||
51
components/security_apps/local_policy_mgmt_gen/include/new_custom_response.h
Executable file
51
components/security_apps/local_policy_mgmt_gen/include/new_custom_response.h
Executable file
@@ -0,0 +1,51 @@
|
||||
// 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 __NEW_CUSTOM_RESPONSE_H__
|
||||
#define __NEW_CUSTOM_RESPONSE_H__
|
||||
|
||||
#include <string>
|
||||
#include <cereal/archives/json.hpp>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/uuid/uuid_generators.hpp>
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "local_policy_common.h"
|
||||
|
||||
class NewAppSecCustomResponse
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
int getHttpResponseCode() const;
|
||||
const std::string & getMessageBody() const;
|
||||
const std::string & getMessageTitle() const;
|
||||
const std::string & getAppSecClassName() const;
|
||||
const std::string & getMode() const;
|
||||
const std::string & getName() const;
|
||||
void setName(const std::string &_name);
|
||||
|
||||
private:
|
||||
bool redirect_add_x_event_id;
|
||||
int http_response_code;
|
||||
std::string appsec_class_name;
|
||||
std::string redirect_url;
|
||||
std::string message_title;
|
||||
std::string message_body;
|
||||
std::string mode;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
#endif // __NEW_CUSTOM_RESPONSE_H__
|
||||
67
components/security_apps/local_policy_mgmt_gen/include/new_exceptions.h
Executable file
67
components/security_apps/local_policy_mgmt_gen/include/new_exceptions.h
Executable file
@@ -0,0 +1,67 @@
|
||||
// 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 __NEW_EXCEPTIONS_H__
|
||||
#define __NEW_EXCEPTIONS_H__
|
||||
|
||||
#include <string>
|
||||
#include <cereal/archives/json.hpp>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/uuid/uuid_generators.hpp>
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "rest.h"
|
||||
#include "local_policy_common.h"
|
||||
|
||||
class NewAppsecExceptionCondition
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const std::string & getKey() const;
|
||||
const std::string & getvalue() const;
|
||||
|
||||
private:
|
||||
std::string key;
|
||||
std::string value;
|
||||
};
|
||||
|
||||
class NewAppsecException
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const std::string & getName() const;
|
||||
const std::string & getAction() const;
|
||||
const std::string & getAppSecClassName() 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;
|
||||
void setName(const std::string &_name);
|
||||
|
||||
private:
|
||||
std::string appsec_class_name;
|
||||
std::string name;
|
||||
std::string action;
|
||||
std::vector<NewAppsecExceptionCondition> conditions;
|
||||
};
|
||||
|
||||
#endif // __NEW_EXCEPTIONS_H__
|
||||
172
components/security_apps/local_policy_mgmt_gen/include/new_log_trigger.h
Executable file
172
components/security_apps/local_policy_mgmt_gen/include/new_log_trigger.h
Executable file
@@ -0,0 +1,172 @@
|
||||
// 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 __NEW_LOG_TRIGGERS_H__
|
||||
#define __NEW_LOG_TRIGGERS_H__
|
||||
|
||||
#include <cereal/archives/json.hpp>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/uuid/uuid_generators.hpp>
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "local_policy_common.h"
|
||||
#include "i_agent_details.h"
|
||||
#include "i_env_details.h"
|
||||
|
||||
class NewAppsecTriggerAccessControlLogging
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
private:
|
||||
bool allow_events = false;
|
||||
bool drop_events = false;
|
||||
};
|
||||
|
||||
class NewAppsecTriggerAdditionalSuspiciousEventsLogging : public ClientRest
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
bool isEnabled() const;
|
||||
bool isResponseBody() const;
|
||||
const std::string & getMinimumSeverity() const;
|
||||
|
||||
private:
|
||||
bool enabled = true;
|
||||
bool response_body = false;
|
||||
bool response_code = false;
|
||||
std::string minimum_severity = "high";
|
||||
};
|
||||
|
||||
class NewAppsecTriggerLogging : public ClientRest
|
||||
{
|
||||
public:
|
||||
void
|
||||
load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
bool isAllWebRequests() const;
|
||||
bool isDetectEvents() const;
|
||||
bool isPreventEvents() const;
|
||||
|
||||
private:
|
||||
bool all_web_requests = false;
|
||||
bool detect_events = false;
|
||||
bool prevent_events = true;
|
||||
};
|
||||
|
||||
class NewAppsecTriggerExtendedLogging : public ClientRest
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
bool isHttpHeaders() const;
|
||||
bool isRequestBody() const;
|
||||
bool isUrlPath() const;
|
||||
bool isUrlQuery() const;
|
||||
|
||||
private:
|
||||
bool http_headers = false;
|
||||
bool request_body = false;
|
||||
bool url_path = false;
|
||||
bool url_query = false;
|
||||
};
|
||||
|
||||
class NewLoggingService
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const std::string & getAddress() const;
|
||||
int getPort() const;
|
||||
|
||||
private:
|
||||
std::string address;
|
||||
std::string proto;
|
||||
int port = 514;
|
||||
};
|
||||
|
||||
class NewStdoutLogging
|
||||
{
|
||||
public:
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
NewStdoutLogging() : format("json") {}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
const std::string & getFormat() const;
|
||||
|
||||
private:
|
||||
std::string format;
|
||||
};
|
||||
|
||||
class NewAppsecTriggerLogDestination
|
||||
:
|
||||
public ClientRest,
|
||||
Singleton::Consume<I_AgentDetails>,
|
||||
Singleton::Consume<I_EnvDetails>
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
int getCefServerUdpPort() const;
|
||||
int getSyslogServerUdpPort() const;
|
||||
bool isAgentLocal() const;
|
||||
bool shouldBeautifyLogs() const;
|
||||
|
||||
bool getCloud() const;
|
||||
bool isK8SNeeded() const;
|
||||
bool isCefNeeded() const;
|
||||
bool isSyslogNeeded() const;
|
||||
const std::string & getSyslogServerIpv4Address() const;
|
||||
const std::string & getCefServerIpv4Address() const;
|
||||
|
||||
private:
|
||||
const NewLoggingService & getSyslogServiceData() const;
|
||||
const NewLoggingService & getCefServiceData() const;
|
||||
|
||||
bool cloud = false;
|
||||
bool k8s_service = false;
|
||||
bool agent_local = true;
|
||||
bool beautify_logs = true;
|
||||
NewLoggingService syslog_service;
|
||||
NewLoggingService cef_service;
|
||||
};
|
||||
|
||||
class NewAppsecLogTrigger
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const std::string & getName() const;
|
||||
const std::string & getAppSecClassName() const;
|
||||
void setName(const std::string &_name);
|
||||
const NewAppsecTriggerAdditionalSuspiciousEventsLogging &
|
||||
getAppsecTriggerAdditionalSuspiciousEventsLogging() const;
|
||||
const NewAppsecTriggerLogging & getAppsecTriggerLogging() const;
|
||||
const NewAppsecTriggerExtendedLogging & getAppsecTriggerExtendedLogging() const;
|
||||
const NewAppsecTriggerLogDestination & getAppsecTriggerLogDestination() const;
|
||||
|
||||
private:
|
||||
NewAppsecTriggerAccessControlLogging access_control_logging;
|
||||
NewAppsecTriggerAdditionalSuspiciousEventsLogging additional_suspicious_events_logging;
|
||||
NewAppsecTriggerLogging appsec_logging;
|
||||
NewAppsecTriggerExtendedLogging extended_logging;
|
||||
NewAppsecTriggerLogDestination log_destination;
|
||||
std::string name;
|
||||
std::string appsec_class_name;
|
||||
};
|
||||
|
||||
#endif // __NEW_LOG_TRIGGERS_H__
|
||||
589
components/security_apps/local_policy_mgmt_gen/include/new_practice.h
Executable file
589
components/security_apps/local_policy_mgmt_gen/include/new_practice.h
Executable file
@@ -0,0 +1,589 @@
|
||||
// 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 __NEW_PRACTICE_H__
|
||||
#define __NEW_PRACTICE_H__
|
||||
|
||||
#include <string>
|
||||
#include <cereal/archives/json.hpp>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/uuid/uuid_generators.hpp>
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "local_policy_common.h"
|
||||
|
||||
class IpsProtectionsRulesSection
|
||||
{
|
||||
public:
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
IpsProtectionsRulesSection() {};
|
||||
|
||||
IpsProtectionsRulesSection(
|
||||
const int _protections_from_year,
|
||||
const std::string &_action,
|
||||
const std::string &_confidence_level,
|
||||
const std::string &_performance_impact,
|
||||
const std::string &_source_identifier,
|
||||
const std::string &_severity_level
|
||||
)
|
||||
:
|
||||
protections_from_year(_protections_from_year),
|
||||
action(_action),
|
||||
confidence_level(_confidence_level),
|
||||
performance_impact(_performance_impact),
|
||||
source_identifier(_source_identifier),
|
||||
severity_level(_severity_level)
|
||||
{};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
int protections_from_year;
|
||||
std::string action;
|
||||
std::string confidence_level;
|
||||
std::string performance_impact;
|
||||
std::string source_identifier;
|
||||
std::string severity_level;
|
||||
};
|
||||
|
||||
class IpsProtectionsSection
|
||||
{
|
||||
public:
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
IpsProtectionsSection() {};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
IpsProtectionsSection(
|
||||
const std::string &_context,
|
||||
const std::string &asset_name,
|
||||
const std::string &_asset_id,
|
||||
const std::string &_practice_name,
|
||||
const std::string &_practice_id,
|
||||
const std::string &_source_identifier,
|
||||
const std::string &_mode,
|
||||
const std::vector<IpsProtectionsRulesSection> &_rules);
|
||||
|
||||
std::string & getMode();
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
std::string context;
|
||||
std::string name;
|
||||
std::string asset_id;
|
||||
std::string practice_name;
|
||||
std::string practice_id;
|
||||
std::string source_identifier;
|
||||
std::string mode;
|
||||
std::vector<IpsProtectionsRulesSection> rules;
|
||||
};
|
||||
|
||||
class IPSSection
|
||||
{
|
||||
public:
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
IPSSection() {};
|
||||
|
||||
IPSSection(const std::vector<IpsProtectionsSection> &_ips) : ips(_ips) {};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
std::vector<IpsProtectionsSection> ips;
|
||||
};
|
||||
|
||||
class IntrusionPreventionWrapper
|
||||
{
|
||||
public:
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
IntrusionPreventionWrapper() {};
|
||||
|
||||
IntrusionPreventionWrapper(const std::vector<IpsProtectionsSection> &_ips) : ips(IPSSection(_ips)) {};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
IPSSection ips;
|
||||
};
|
||||
|
||||
class NewIntrusionPrevention
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
std::vector<IpsProtectionsRulesSection> createIpsRules() const;
|
||||
const std::string & getMode() const;
|
||||
|
||||
private:
|
||||
std::string override_mode;
|
||||
std::string max_performance_impact;
|
||||
std::string min_severity_level;
|
||||
std::string high_confidence_event_action;
|
||||
std::string medium_confidence_event_action;
|
||||
std::string low_confidence_event_action;
|
||||
int min_cve_Year;
|
||||
};
|
||||
|
||||
class FileSecurityProtectionsSection
|
||||
{
|
||||
public:
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
FileSecurityProtectionsSection() {};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
FileSecurityProtectionsSection(
|
||||
int _file_size_limit,
|
||||
int _archive_file_size_limit,
|
||||
bool _allow_files_without_name,
|
||||
bool _required_file_size_limit,
|
||||
bool _required_archive_extraction,
|
||||
const std::string &_context,
|
||||
const std::string &_name,
|
||||
const std::string &_asset_id,
|
||||
const std::string &_practice_name,
|
||||
const std::string &_practice_id,
|
||||
const std::string &_action,
|
||||
const std::string &_files_without_name_action,
|
||||
const std::string &_high_confidence_action,
|
||||
const std::string &_medium_confidence_action,
|
||||
const std::string &_low_confidence_action,
|
||||
const std::string &_severity_level,
|
||||
const std::string &_file_size_limit_action,
|
||||
const std::string &_multi_level_archive_action,
|
||||
const std::string &_unopened_archive_action
|
||||
);
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
int file_size_limit;
|
||||
int archive_file_size_limit;
|
||||
bool allow_files_without_name;
|
||||
bool required_file_size_limit;
|
||||
bool required_archive_extraction;
|
||||
std::string context;
|
||||
std::string name;
|
||||
std::string asset_id;
|
||||
std::string practice_name;
|
||||
std::string practice_id;
|
||||
std::string action;
|
||||
std::string files_without_name_action;
|
||||
std::string high_confidence_action;
|
||||
std::string medium_confidence_action;
|
||||
std::string low_confidence_action;
|
||||
std::string severity_level;
|
||||
std::string file_size_limit_action;
|
||||
std::string file_size_limit_unit;
|
||||
std::string scan_max_file_size_unit;
|
||||
std::string multi_level_archive_action;
|
||||
std::string unopened_archive_action;
|
||||
};
|
||||
|
||||
class FileSecuritySection
|
||||
{
|
||||
public:
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
FileSecuritySection() {};
|
||||
|
||||
FileSecuritySection(const std::vector<FileSecurityProtectionsSection> &_file_security)
|
||||
:
|
||||
file_security(_file_security) {};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
std::vector<FileSecurityProtectionsSection> file_security;
|
||||
};
|
||||
|
||||
class FileSecurityWrapper
|
||||
{
|
||||
public:
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
FileSecurityWrapper() {};
|
||||
|
||||
FileSecurityWrapper(const std::vector<FileSecurityProtectionsSection> &_file_security)
|
||||
:
|
||||
file_security(FileSecuritySection(_file_security)) {};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
FileSecuritySection file_security;
|
||||
};
|
||||
|
||||
class NewFileSecurityArchiveInspection
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
int getArchiveFileSizeLimit() const;
|
||||
bool getrequiredArchiveExtraction() const;
|
||||
const std::string & getMultiLevelArchiveAction() const;
|
||||
const std::string & getUnopenedArchiveAction() const;
|
||||
|
||||
private:
|
||||
int scan_max_file_size;
|
||||
bool extract_archive_files;
|
||||
std::string scan_max_file_size_unit;
|
||||
std::string archived_files_within_archived_files;
|
||||
std::string archived_files_where_content_extraction_failed;
|
||||
};
|
||||
|
||||
class NewFileSecurityLargeFileInspection
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
int getFileSizeLimit() const;
|
||||
const std::string & getFileSizeLimitAction() const;
|
||||
|
||||
private:
|
||||
int file_size_limit;
|
||||
std::string file_size_limit_unit;
|
||||
std::string files_exceeding_size_limit_action;
|
||||
};
|
||||
|
||||
class NewFileSecurity
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const std::string & getOverrideMode() const;
|
||||
const NewFileSecurityArchiveInspection & getArchiveInspection() const;
|
||||
const NewFileSecurityLargeFileInspection & getLargeFileInspection() const;
|
||||
FileSecurityProtectionsSection createFileSecurityProtectionsSection(
|
||||
const std::string &context,
|
||||
const std::string &asset_name,
|
||||
const std::string &asset_id,
|
||||
const std::string &practice_name,
|
||||
const std::string &practice_id
|
||||
) const;
|
||||
|
||||
private:
|
||||
bool threat_emulation_enabled;
|
||||
std::string override_mode;
|
||||
std::string min_severity_level;
|
||||
std::string high_confidence_event_action;
|
||||
std::string medium_confidence_event_action;
|
||||
std::string low_confidence_event_action;
|
||||
std::string unnamed_files_action;
|
||||
NewFileSecurityArchiveInspection archive_inspection;
|
||||
NewFileSecurityLargeFileInspection large_file_inspection;
|
||||
};
|
||||
|
||||
class SnortProtectionsSection
|
||||
{
|
||||
public:
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
SnortProtectionsSection() {};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
SnortProtectionsSection(
|
||||
const std::string &_context,
|
||||
const std::string &_asset_name,
|
||||
const std::string &_asset_id,
|
||||
const std::string &_practice_name,
|
||||
const std::string &_practice_id,
|
||||
const std::string &_source_identifier,
|
||||
const std::string &_mode,
|
||||
const std::vector<std::string> &_files
|
||||
);
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
std::string context;
|
||||
std::string asset_name;
|
||||
std::string asset_id;
|
||||
std::string practice_name;
|
||||
std::string practice_id;
|
||||
std::string source_identifier;
|
||||
std::string mode;
|
||||
std::vector<std::string> files;
|
||||
};
|
||||
|
||||
class DetectionRules
|
||||
{
|
||||
public:
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
DetectionRules() {};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
DetectionRules(
|
||||
const std::string &_type,
|
||||
const std::string &_SSM,
|
||||
const std::string &_keywords,
|
||||
const std::vector<std::string> &_context
|
||||
);
|
||||
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
std::string type;
|
||||
std::string SSM;
|
||||
std::string keywords;
|
||||
std::vector<std::string> context;
|
||||
};
|
||||
|
||||
class ProtectionMetadata
|
||||
{
|
||||
public:
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
ProtectionMetadata() {};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
ProtectionMetadata(
|
||||
bool _silent,
|
||||
const std::string &_protection_name,
|
||||
const std::string &_severity,
|
||||
const std::string &_confidence_level,
|
||||
const std::string &_performance_impact,
|
||||
const std::string &_last_update,
|
||||
const std::string &_maintrain_id,
|
||||
const std::vector<std::string> &_tags,
|
||||
const std::vector<std::string> &_cve_list
|
||||
);
|
||||
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
bool silent;
|
||||
std::string protection_name;
|
||||
std::string severity;
|
||||
std::string confidence_level;
|
||||
std::string performance_impact;
|
||||
std::string last_update;
|
||||
std::string maintrain_id;
|
||||
std::vector<std::string> tags;
|
||||
std::vector<std::string> cve_list;
|
||||
};
|
||||
|
||||
class ProtectionsProtectionsSection
|
||||
{
|
||||
public:
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
ProtectionsProtectionsSection() {};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
ProtectionsProtectionsSection(
|
||||
const ProtectionMetadata &_protection_metadata,
|
||||
const DetectionRules &_detection_rules
|
||||
);
|
||||
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
ProtectionMetadata protection_metadata;
|
||||
DetectionRules detection_rules;
|
||||
};
|
||||
|
||||
class ProtectionsSection
|
||||
{
|
||||
public:
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
ProtectionsSection() {};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
ProtectionsSection(
|
||||
const std::vector<ProtectionsProtectionsSection> &_protections,
|
||||
const std::string &_name = "",
|
||||
const std::string &_modification_time = ""
|
||||
);
|
||||
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
const std::vector<ProtectionsProtectionsSection> & getProtections() const;
|
||||
|
||||
private:
|
||||
std::vector<ProtectionsProtectionsSection> protections;
|
||||
std::string name;
|
||||
std::string modification_time;
|
||||
};
|
||||
|
||||
class ProtectionsSectionWrapper
|
||||
{
|
||||
public:
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
ProtectionsSectionWrapper() {};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
void serialize(cereal::JSONInputArchive &archive_in);
|
||||
const std::vector<ProtectionsProtectionsSection> & getProtections() const;
|
||||
|
||||
private:
|
||||
ProtectionsSection protections;
|
||||
};
|
||||
|
||||
class SnortSection
|
||||
{
|
||||
public:
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
SnortSection() {};
|
||||
|
||||
SnortSection(
|
||||
const std::vector<SnortProtectionsSection> &_snort,
|
||||
const std::vector<ProtectionsSection> &_protections)
|
||||
:
|
||||
snort_protections(_snort),
|
||||
protections(_protections)
|
||||
{};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
const std::vector<ProtectionsSection> & getProtections() const;
|
||||
|
||||
private:
|
||||
std::vector<SnortProtectionsSection> snort_protections;
|
||||
std::vector<ProtectionsSection> protections;
|
||||
};
|
||||
|
||||
class SnortSectionWrapper
|
||||
{
|
||||
public:
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
SnortSectionWrapper() {};
|
||||
|
||||
SnortSectionWrapper(
|
||||
const std::vector<SnortProtectionsSection> &_snort,
|
||||
const std::vector<ProtectionsSection> &_protections)
|
||||
:
|
||||
snort(SnortSection(_snort, _protections))
|
||||
{};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
SnortSection snort;
|
||||
};
|
||||
|
||||
class NewSnortSignaturesAndOpenSchemaAPI
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
void addFile(const std::string &file_name);
|
||||
const std::string & getOverrideMode() const;
|
||||
const std::vector<std::string> & getConfigMap() const;
|
||||
const std::vector<std::string> & getFiles() const;
|
||||
|
||||
private:
|
||||
std::string override_mode;
|
||||
std::vector<std::string> config_map;
|
||||
std::vector<std::string> files;
|
||||
};
|
||||
|
||||
class NewAppSecWebBotsURI
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const std::string & getURI() const;
|
||||
|
||||
private:
|
||||
std::string uri;
|
||||
};
|
||||
|
||||
class NewAppSecPracticeAntiBot
|
||||
{
|
||||
public:
|
||||
std::vector<std::string> getIjectedUris() const;
|
||||
std::vector<std::string> getValidatedUris() const;
|
||||
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
std::string override_mode;
|
||||
std::vector<NewAppSecWebBotsURI> injected_uris;
|
||||
std::vector<NewAppSecWebBotsURI> validated_uris;
|
||||
};
|
||||
|
||||
class NewAppSecWebAttackProtections
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const std::string getCsrfProtectionMode() const;
|
||||
const std::string & getErrorDisclosureMode() const;
|
||||
bool getNonValidHttpMethods() const;
|
||||
const std::string getOpenRedirectMode() const;
|
||||
|
||||
private:
|
||||
std::string csrf_protection;
|
||||
std::string open_redirect;
|
||||
std::string error_disclosure;
|
||||
bool non_valid_http_methods;
|
||||
};
|
||||
|
||||
class NewAppSecPracticeWebAttacks
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
int getMaxBodySizeKb() const;
|
||||
int getMaxHeaderSizeBytes() const;
|
||||
int getMaxObjectDepth() const;
|
||||
int getMaxUrlSizeBytes() const;
|
||||
const std::string & getMinimumConfidence() const;
|
||||
const NewAppSecWebAttackProtections & getprotections() const;
|
||||
const std::string & getMode(const std::string &default_mode = "Inactive") const;
|
||||
|
||||
private:
|
||||
int max_body_size_kb;
|
||||
int max_header_size_bytes;
|
||||
int max_object_depth;
|
||||
int max_url_size_bytes;
|
||||
std::string mode;
|
||||
std::string minimum_confidence;
|
||||
NewAppSecWebAttackProtections protections;
|
||||
};
|
||||
|
||||
class NewAppSecPracticeSpec
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
NewSnortSignaturesAndOpenSchemaAPI & getSnortSignatures();
|
||||
const NewSnortSignaturesAndOpenSchemaAPI & getOpenSchemaValidation() const;
|
||||
const NewAppSecPracticeWebAttacks & getWebAttacks() const;
|
||||
const NewAppSecPracticeAntiBot & getAntiBot() const;
|
||||
const NewIntrusionPrevention & getIntrusionPrevention() const;
|
||||
const NewFileSecurity & getFileSecurity() const;
|
||||
const std::string & getAppSecClassName() const;
|
||||
const std::string & getName() const;
|
||||
void setName(const std::string &_name);
|
||||
|
||||
private:
|
||||
NewFileSecurity file_security;
|
||||
NewIntrusionPrevention intrusion_prevention;
|
||||
NewSnortSignaturesAndOpenSchemaAPI openapi_schema_validation;
|
||||
NewSnortSignaturesAndOpenSchemaAPI snort_signatures;
|
||||
NewAppSecPracticeWebAttacks web_attacks;
|
||||
NewAppSecPracticeAntiBot anti_bot;
|
||||
std::string appsec_class_name;
|
||||
std::string practice_name;
|
||||
};
|
||||
|
||||
#endif // __NEW_PRACTICE_H__
|
||||
74
components/security_apps/local_policy_mgmt_gen/include/new_trusted_sources.h
Executable file
74
components/security_apps/local_policy_mgmt_gen/include/new_trusted_sources.h
Executable file
@@ -0,0 +1,74 @@
|
||||
// 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 __NEW_TRUSTED_SOURCES_H__
|
||||
#define __NEW_TRUSTED_SOURCES_H__
|
||||
|
||||
#include <string>
|
||||
#include <cereal/archives/json.hpp>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/uuid/uuid_generators.hpp>
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "local_policy_common.h"
|
||||
|
||||
class NewTrustedSourcesSpec
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
int getMinNumOfSources() const;
|
||||
const std::vector<std::string> & getSourcesIdentifiers() const;
|
||||
const std::string & getAppSecClassName() const;
|
||||
const std::string & getName() const;
|
||||
void setName(const std::string &_name);
|
||||
|
||||
private:
|
||||
int min_num_of_sources = 0;
|
||||
std::string name;
|
||||
std::vector<std::string> sources_identifiers;
|
||||
std::string appsec_class_name;
|
||||
};
|
||||
|
||||
class Identifier
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const std::string & getIdentifier() const;
|
||||
const std::vector<std::string> & getValues() const;
|
||||
|
||||
private:
|
||||
std::string identifier;
|
||||
std::vector<std::string> value;
|
||||
};
|
||||
|
||||
class NewSourcesIdentifiers
|
||||
{
|
||||
public:
|
||||
void load(cereal::JSONInputArchive &archive_in);
|
||||
|
||||
const std::string & getName() const;
|
||||
const std::string & getAppSecClassName() const;
|
||||
const std::vector<Identifier> & getSourcesIdentifiers() const;
|
||||
void setName(const std::string &_name);
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
std::string appsec_class_name;
|
||||
std::vector<Identifier> sources_identifiers;
|
||||
};
|
||||
|
||||
#endif // __NEW_TRUSTED_SOURCES_H__
|
||||
266
components/security_apps/local_policy_mgmt_gen/include/policy_maker_utils.h
Executable file
266
components/security_apps/local_policy_mgmt_gen/include/policy_maker_utils.h
Executable file
@@ -0,0 +1,266 @@
|
||||
// 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 "i_orchestration_tools.h"
|
||||
#include "i_shell_cmd.h"
|
||||
#include "i_messaging.h"
|
||||
#include "appsec_practice_section.h"
|
||||
#include "ingress_data.h"
|
||||
#include "settings_section.h"
|
||||
#include "triggers_section.h"
|
||||
#include "local_policy_common.h"
|
||||
#include "exceptions_section.h"
|
||||
#include "rules_config_section.h"
|
||||
#include "trusted_sources_section.h"
|
||||
#include "new_appsec_linux_policy.h"
|
||||
#include "access_control_practice.h"
|
||||
|
||||
enum class AnnotationTypes {
|
||||
PRACTICE,
|
||||
THREAT_PREVENTION_PRACTICE,
|
||||
ACCESS_CONTROL_PRACTICE,
|
||||
TRIGGER,
|
||||
EXCEPTION,
|
||||
WEB_USER_RES,
|
||||
SOURCE_IDENTIFIERS,
|
||||
TRUSTED_SOURCES,
|
||||
COUNT
|
||||
};
|
||||
|
||||
class SecurityAppsWrapper
|
||||
{
|
||||
public:
|
||||
SecurityAppsWrapper(
|
||||
const AppSecWrapper &_waap,
|
||||
const TriggersWrapper &_trrigers,
|
||||
const RulesConfigWrapper &_rules,
|
||||
const IntrusionPreventionWrapper &_ips,
|
||||
const SnortSectionWrapper &_snort,
|
||||
const AccessControlRulebaseWrapper &_rate_limit,
|
||||
const FileSecurityWrapper &_file_security,
|
||||
const ExceptionsWrapper &_exceptions,
|
||||
const std::string &_policy_version)
|
||||
:
|
||||
waap(_waap),
|
||||
trrigers(_trrigers),
|
||||
rules(_rules),
|
||||
ips(_ips),
|
||||
snort(_snort),
|
||||
rate_limit(_rate_limit),
|
||||
file_security(_file_security),
|
||||
exceptions(_exceptions),
|
||||
policy_version(_policy_version) {}
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
AppSecWrapper waap;
|
||||
TriggersWrapper trrigers;
|
||||
RulesConfigWrapper rules;
|
||||
IntrusionPreventionWrapper ips;
|
||||
SnortSectionWrapper snort;
|
||||
AccessControlRulebaseWrapper rate_limit;
|
||||
FileSecurityWrapper file_security;
|
||||
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;
|
||||
};
|
||||
|
||||
class PolicyMakerUtils
|
||||
:
|
||||
Singleton::Consume<I_Environment>,
|
||||
Singleton::Consume<I_OrchestrationTools>,
|
||||
Singleton::Consume<I_Messaging>,
|
||||
Singleton::Consume<I_ShellCmd>
|
||||
{
|
||||
public:
|
||||
std::string proccesSingleAppsecPolicy(
|
||||
const std::string &policy_path,
|
||||
const std::string &policy_version,
|
||||
const std::string &local_appsec_policy_path
|
||||
);
|
||||
|
||||
template<class T, class R>
|
||||
std::string proccesMultipleAppsecPolicies(
|
||||
const std::map<std::string, T> &appsec_policies,
|
||||
const std::string &policy_version,
|
||||
const std::string &local_appsec_policy_path
|
||||
);
|
||||
|
||||
private:
|
||||
std::string getPolicyName(const std::string &policy_path);
|
||||
|
||||
template<class T>
|
||||
Maybe<T> openFileAsJson(const std::string &path);
|
||||
|
||||
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);
|
||||
|
||||
PolicyWrapper combineElementsToPolicy(const std::string &policy_version);
|
||||
|
||||
void
|
||||
createIpsSections(
|
||||
const std::string &asset_id,
|
||||
const std::string &asset_name,
|
||||
const std::string &practice_id,
|
||||
const std::string &practice_name,
|
||||
const std::string &source_identifier,
|
||||
const std::string & context,
|
||||
const V1beta2AppsecLinuxPolicy &policy,
|
||||
std::map<AnnotationTypes, std::string> &rule_annotations
|
||||
);
|
||||
|
||||
void createSnortProtecionsSection(const std::string &file_name, const std::string &practic_name);
|
||||
|
||||
void
|
||||
createSnortSections(
|
||||
const std::string & context,
|
||||
const std::string &asset_name,
|
||||
const std::string &asset_id,
|
||||
const std::string &practice_name,
|
||||
const std::string &practice_id,
|
||||
const std::string &source_identifier,
|
||||
const V1beta2AppsecLinuxPolicy &policy,
|
||||
std::map<AnnotationTypes, std::string> &rule_annotations
|
||||
);
|
||||
|
||||
void
|
||||
createFileSecuritySections(
|
||||
const std::string &asset_id,
|
||||
const std::string &asset_name,
|
||||
const std::string &practice_id,
|
||||
const std::string &practice_name,
|
||||
const std::string & context,
|
||||
const V1beta2AppsecLinuxPolicy &policy,
|
||||
std::map<AnnotationTypes, std::string> &rule_annotations
|
||||
);
|
||||
|
||||
void
|
||||
createRateLimitSection(
|
||||
const std::string &asset_name,
|
||||
const std::string &url,
|
||||
const std::string &uri,
|
||||
const std::string &trigger_id,
|
||||
const V1beta2AppsecLinuxPolicy &policy,
|
||||
std::map<AnnotationTypes, std::string> &rule_annotations
|
||||
);
|
||||
|
||||
void createWebAppSection(
|
||||
const V1beta2AppsecLinuxPolicy &policy,
|
||||
const RulesConfigRulebase& rule_config,
|
||||
const std::string &practice_id, const std::string &full_url,
|
||||
const std::string &default_mode,
|
||||
std::map<AnnotationTypes, std::string> &rule_annotations
|
||||
);
|
||||
|
||||
void
|
||||
createThreatPreventionPracticeSections(
|
||||
const std::string &asset_name,
|
||||
const std::string &url,
|
||||
const std::string &uri,
|
||||
const std::string &default_mode,
|
||||
const V1beta2AppsecLinuxPolicy &policy,
|
||||
std::map<AnnotationTypes, std::string> &rule_annotations
|
||||
);
|
||||
|
||||
template<class T, class R>
|
||||
void createPolicyElementsByRule(
|
||||
const R &rule,
|
||||
const R &default_rule,
|
||||
const T &policy,
|
||||
const std::string &policy_name
|
||||
);
|
||||
|
||||
template<class T, class R>
|
||||
void createPolicyElements(
|
||||
const std::vector<R> &rules,
|
||||
const R &default_rule,
|
||||
const T &policy,
|
||||
const std::string &policy_name
|
||||
);
|
||||
|
||||
template<class T, class R>
|
||||
void createAgentPolicyFromAppsecPolicy(const std::string &policy_name, const T &appsec_policy);
|
||||
|
||||
std::map<std::string, LogTriggerSection> log_triggers;
|
||||
std::map<std::string, WebUserResponseTriggerSection> web_user_res_triggers;
|
||||
std::map<std::string, std::vector<InnerException>> inner_exceptions;
|
||||
std::map<std::string, WebAppSection> web_apps;
|
||||
std::map<std::string, RulesConfigRulebase> rules_config;
|
||||
std::map<std::string, IpsProtectionsSection> ips;
|
||||
std::map<std::string, SnortProtectionsSection> snort;
|
||||
std::map<std::string, ProtectionsSection> snort_protections;
|
||||
std::map<std::string, FileSecurityProtectionsSection> file_security;
|
||||
std::map<std::string, RateLimitSection> rate_limit;
|
||||
std::map<std::string, UsersIdentifiersRulebase> users_identifiers;
|
||||
std::map<std::string, AppSecTrustedSources> trusted_sources;
|
||||
};
|
||||
|
||||
template<class T, class R>
|
||||
std::string
|
||||
PolicyMakerUtils::proccesMultipleAppsecPolicies(
|
||||
const std::map<std::string, T> &appsec_policies,
|
||||
const std::string &policy_version,
|
||||
const std::string &local_appsec_policy_path)
|
||||
{
|
||||
for (const auto &appsec_policy : appsec_policies) {
|
||||
createAgentPolicyFromAppsecPolicy<T, R>(appsec_policy.first, appsec_policy.second);
|
||||
}
|
||||
|
||||
PolicyWrapper policy_wrapper = combineElementsToPolicy(policy_version);
|
||||
return dumpPolicyToFile(
|
||||
policy_wrapper,
|
||||
local_appsec_policy_path
|
||||
);
|
||||
}
|
||||
|
||||
#endif // __POLICY_MAKER_UTILS_H__
|
||||
@@ -121,6 +121,8 @@ public:
|
||||
std::vector<std::string> _identifier_values
|
||||
);
|
||||
|
||||
const std::string & getIdentifier() const;
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
@@ -141,6 +143,8 @@ public:
|
||||
const std::vector<UsersIdentifier> &_source_identifiers
|
||||
);
|
||||
|
||||
const std::string & getIdentifier() const;
|
||||
|
||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||
|
||||
private:
|
||||
@@ -0,0 +1,587 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "k8s_policy_utils.h"
|
||||
#include "configmaps.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
USE_DEBUG_FLAG(D_NGINX_POLICY);
|
||||
|
||||
string
|
||||
convertAnnotationKeysTostring(const AnnotationKeys &key)
|
||||
{
|
||||
switch (key) {
|
||||
case AnnotationKeys::PolicyKey:
|
||||
return "policy";
|
||||
case AnnotationKeys::OpenAppsecIo:
|
||||
return "openappsec.io/";
|
||||
case AnnotationKeys::SyslogAddressKey:
|
||||
return "syslog";
|
||||
case AnnotationKeys::ModeKey:
|
||||
return "mode";
|
||||
default:
|
||||
return "Irrelevant key";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
K8sPolicyUtils::init()
|
||||
{
|
||||
env_details = Singleton::Consume<I_EnvDetails>::by<K8sPolicyUtils>();
|
||||
env_type = env_details->getEnvType();
|
||||
if (env_type == EnvType::K8S) {
|
||||
token = env_details->getToken();
|
||||
messaging = Singleton::Consume<I_Messaging>::by<K8sPolicyUtils>();
|
||||
conn_flags.setFlag(MessageConnConfig::SECURE_CONN);
|
||||
conn_flags.setFlag(MessageConnConfig::IGNORE_SSL_VALIDATION);
|
||||
}
|
||||
}
|
||||
|
||||
map<AnnotationKeys, string>
|
||||
K8sPolicyUtils::parseIngressAnnotations(const map<string, string> &annotations) const
|
||||
{
|
||||
map<AnnotationKeys, string> annotations_values;
|
||||
for (const auto &annotation : annotations) {
|
||||
string annotation_key = annotation.first;
|
||||
string annotation_val = annotation.second;
|
||||
if (annotation_key.find(convertAnnotationKeysTostring(AnnotationKeys::OpenAppsecIo)) != string::npos) {
|
||||
if (annotation_key.find(convertAnnotationKeysTostring(AnnotationKeys::PolicyKey)) != string::npos) {
|
||||
annotations_values[AnnotationKeys::PolicyKey] = annotation_val;
|
||||
} else if (
|
||||
annotation_key.find(convertAnnotationKeysTostring(AnnotationKeys::SyslogAddressKey)) != string::npos
|
||||
) {
|
||||
bool has_port = annotation_val.find(":");
|
||||
annotations_values[AnnotationKeys::SyslogAddressKey] =
|
||||
annotation_val.substr(0, annotation_val.find(":"));
|
||||
annotations_values[AnnotationKeys::SyslogPortKey] =
|
||||
has_port ? annotation_val.substr(annotation_val.find(":") + 1) : "";
|
||||
} else if (annotation_key.find(convertAnnotationKeysTostring(AnnotationKeys::ModeKey)) != string::npos) {
|
||||
annotations_values[AnnotationKeys::ModeKey] = annotation_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
return annotations_values;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Maybe<T, string>
|
||||
K8sPolicyUtils::getObjectFromCluster(const string &path) const
|
||||
{
|
||||
T object;
|
||||
bool res = messaging->sendObject(
|
||||
object,
|
||||
I_Messaging::Method::GET,
|
||||
"kubernetes.default.svc",
|
||||
443,
|
||||
conn_flags,
|
||||
path,
|
||||
"Authorization: Bearer " + token + "\nConnection: close"
|
||||
);
|
||||
|
||||
if (res) return object;
|
||||
|
||||
return genError(string("Was not able to get object form k8s cluser in path: " + path));
|
||||
}
|
||||
|
||||
map<AnnotationTypes, unordered_set<string>>
|
||||
K8sPolicyUtils::extractElementsNames(const vector<ParsedRule> &specific_rules, const ParsedRule &default_rule) const
|
||||
{
|
||||
map<AnnotationTypes, unordered_set<string>> policy_elements_names;
|
||||
for (const ParsedRule &specific_rule : specific_rules) {
|
||||
policy_elements_names[AnnotationTypes::EXCEPTION].insert(
|
||||
specific_rule.getExceptions().begin(),
|
||||
specific_rule.getExceptions().end()
|
||||
);
|
||||
policy_elements_names[AnnotationTypes::PRACTICE].insert(
|
||||
specific_rule.getPractices().begin(),
|
||||
specific_rule.getPractices().end()
|
||||
);
|
||||
policy_elements_names[AnnotationTypes::TRIGGER].insert(
|
||||
specific_rule.getLogTriggers().begin(),
|
||||
specific_rule.getLogTriggers().end()
|
||||
);
|
||||
policy_elements_names[AnnotationTypes::WEB_USER_RES].insert(specific_rule.getCustomResponse());
|
||||
policy_elements_names[AnnotationTypes::SOURCE_IDENTIFIERS].insert(specific_rule.getSourceIdentifiers());
|
||||
policy_elements_names[AnnotationTypes::TRUSTED_SOURCES].insert(specific_rule.getTrustedSources());
|
||||
}
|
||||
policy_elements_names[AnnotationTypes::EXCEPTION].insert(
|
||||
default_rule.getExceptions().begin(),
|
||||
default_rule.getExceptions().end()
|
||||
);
|
||||
policy_elements_names[AnnotationTypes::PRACTICE].insert(
|
||||
default_rule.getPractices().begin(),
|
||||
default_rule.getPractices().end()
|
||||
);
|
||||
policy_elements_names[AnnotationTypes::TRIGGER].insert(
|
||||
default_rule.getLogTriggers().begin(),
|
||||
default_rule.getLogTriggers().end()
|
||||
);
|
||||
policy_elements_names[AnnotationTypes::WEB_USER_RES].insert(default_rule.getCustomResponse());
|
||||
policy_elements_names[AnnotationTypes::SOURCE_IDENTIFIERS].insert(default_rule.getSourceIdentifiers());
|
||||
policy_elements_names[AnnotationTypes::TRUSTED_SOURCES].insert(default_rule.getTrustedSources());
|
||||
|
||||
return policy_elements_names;
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
void
|
||||
extractElementsFromNewRule(
|
||||
const NewParsedRule &rule,
|
||||
map<AnnotationTypes, unordered_set<string>> &policy_elements_names)
|
||||
{
|
||||
policy_elements_names[AnnotationTypes::EXCEPTION].insert(
|
||||
rule.getExceptions().begin(),
|
||||
rule.getExceptions().end()
|
||||
);
|
||||
policy_elements_names[AnnotationTypes::THREAT_PREVENTION_PRACTICE].insert(
|
||||
rule.getPractices().begin(),
|
||||
rule.getPractices().end()
|
||||
);
|
||||
policy_elements_names[AnnotationTypes::ACCESS_CONTROL_PRACTICE].insert(
|
||||
rule.getAccessControlPractices().begin(),
|
||||
rule.getAccessControlPractices().end()
|
||||
);
|
||||
policy_elements_names[AnnotationTypes::TRIGGER].insert(
|
||||
rule.getLogTriggers().begin(),
|
||||
rule.getLogTriggers().end()
|
||||
);
|
||||
policy_elements_names[AnnotationTypes::WEB_USER_RES].insert(rule.getCustomResponse());
|
||||
policy_elements_names[AnnotationTypes::SOURCE_IDENTIFIERS].insert(rule.getSourceIdentifiers());
|
||||
policy_elements_names[AnnotationTypes::TRUSTED_SOURCES].insert(rule.getTrustedSources());
|
||||
}
|
||||
|
||||
map<AnnotationTypes, unordered_set<string>>
|
||||
K8sPolicyUtils::extractElementsNamesV1beta2(
|
||||
const vector<NewParsedRule> &specific_rules,
|
||||
const NewParsedRule &default_rule) const
|
||||
{
|
||||
map<AnnotationTypes, unordered_set<string>> policy_elements_names;
|
||||
for (const NewParsedRule &specific_rule : specific_rules) {
|
||||
extractElementsFromNewRule(specific_rule, policy_elements_names);
|
||||
}
|
||||
extractElementsFromNewRule(default_rule, policy_elements_names);
|
||||
|
||||
return policy_elements_names;
|
||||
}
|
||||
|
||||
string
|
||||
getAppSecClassNameFromCluster()
|
||||
{
|
||||
auto env_res = getenv("appsecClassName");
|
||||
if (env_res != nullptr) return env_res;
|
||||
return "";
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
vector<AppsecException>
|
||||
K8sPolicyUtils::extractExceptionsFromCluster(
|
||||
const string &crd_plural,
|
||||
const unordered_set<string> &elements_names) const
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Retrieve AppSec elements. type: " << crd_plural;
|
||||
vector<AppsecException> elements;
|
||||
for (const string &element_name : elements_names) {
|
||||
dbgTrace(D_LOCAL_POLICY) << "AppSec element name: " << element_name;
|
||||
auto maybe_appsec_element = getObjectFromCluster<AppsecSpecParser<vector<AppsecExceptionSpec>>>(
|
||||
"/apis/openappsec.io/v1beta1/" + crd_plural + "/" + element_name
|
||||
);
|
||||
|
||||
if (!maybe_appsec_element.ok()) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "Failed to retrieve AppSec element. type: "
|
||||
<< crd_plural
|
||||
<< ", name: "
|
||||
<< element_name
|
||||
<< ". Error: "
|
||||
<< maybe_appsec_element.getErr();
|
||||
continue;
|
||||
}
|
||||
|
||||
AppsecSpecParser<vector<AppsecExceptionSpec>> appsec_element = maybe_appsec_element.unpack();
|
||||
elements.push_back(AppsecException(element_name, appsec_element.getSpec()));
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
vector<T>
|
||||
K8sPolicyUtils::extractElementsFromCluster(
|
||||
const string &crd_plural,
|
||||
const unordered_set<string> &elements_names) const
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Retrieve AppSec elements. type: " << crd_plural;
|
||||
vector<T> elements;
|
||||
for (const string &element_name : elements_names) {
|
||||
dbgTrace(D_LOCAL_POLICY) << "AppSec element name: " << element_name;
|
||||
auto maybe_appsec_element = getObjectFromCluster<AppsecSpecParser<T>>(
|
||||
"/apis/openappsec.io/v1beta1/" + crd_plural + "/" + element_name
|
||||
);
|
||||
|
||||
if (!maybe_appsec_element.ok()) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "Failed to retrieve AppSec element. type: "
|
||||
<< crd_plural
|
||||
<< ", name: "
|
||||
<< element_name
|
||||
<< ". Error: "
|
||||
<< maybe_appsec_element.getErr();
|
||||
continue;
|
||||
}
|
||||
|
||||
AppsecSpecParser<T> appsec_element = maybe_appsec_element.unpack();
|
||||
if (appsec_element.getSpec().getName() == "") {
|
||||
appsec_element.setName(element_name);
|
||||
}
|
||||
elements.push_back(appsec_element.getSpec());
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
template<class T>
|
||||
vector<T>
|
||||
K8sPolicyUtils::extractV1Beta2ElementsFromCluster(
|
||||
const string &crd_plural,
|
||||
const unordered_set<string> &elements_names) const
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Retrieve AppSec elements. type: " << crd_plural;
|
||||
vector<T> elements;
|
||||
for (const string &element_name : elements_names) {
|
||||
dbgTrace(D_LOCAL_POLICY) << "AppSec element name: " << element_name;
|
||||
auto maybe_appsec_element = getObjectFromCluster<AppsecSpecParser<T>>(
|
||||
"/apis/openappsec.io/v1beta2/" + crd_plural + "/" + element_name
|
||||
);
|
||||
|
||||
if (!maybe_appsec_element.ok()) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "Failed to retrieve AppSec element. type: "
|
||||
<< crd_plural
|
||||
<< ", name: "
|
||||
<< element_name
|
||||
<< ". Error: "
|
||||
<< maybe_appsec_element.getErr();
|
||||
continue;
|
||||
}
|
||||
|
||||
AppsecSpecParser<T> appsec_element = maybe_appsec_element.unpack();
|
||||
if (getAppSecClassNameFromCluster() != "" &&
|
||||
appsec_element.getSpec().getAppSecClassName() != getAppSecClassNameFromCluster()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (appsec_element.getSpec().getName() == "") {
|
||||
appsec_element.setName(element_name);
|
||||
}
|
||||
elements.push_back(appsec_element.getSpec());
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
Maybe<AppsecLinuxPolicy>
|
||||
K8sPolicyUtils::createAppsecPolicyK8sFromV1beta1Crds(
|
||||
const AppsecSpecParser<AppsecPolicySpec> &appsec_policy_spec,
|
||||
const string &ingress_mode) const
|
||||
{
|
||||
ParsedRule default_rule = appsec_policy_spec.getSpec().getDefaultRule();
|
||||
vector<ParsedRule> specific_rules = appsec_policy_spec.getSpec().getSpecificRules();
|
||||
|
||||
if (!ingress_mode.empty() && default_rule.getMode().empty()) {
|
||||
default_rule.setMode(ingress_mode);
|
||||
}
|
||||
|
||||
map<AnnotationTypes, unordered_set<string>> policy_elements_names = extractElementsNames(
|
||||
specific_rules,
|
||||
default_rule
|
||||
);
|
||||
|
||||
|
||||
vector<AppSecPracticeSpec> practices = extractElementsFromCluster<AppSecPracticeSpec>(
|
||||
"practices",
|
||||
policy_elements_names[AnnotationTypes::PRACTICE]
|
||||
);
|
||||
|
||||
vector<AppsecTriggerSpec> log_triggers = extractElementsFromCluster<AppsecTriggerSpec>(
|
||||
"logtriggers",
|
||||
policy_elements_names[AnnotationTypes::TRIGGER]
|
||||
);
|
||||
|
||||
vector<AppSecCustomResponseSpec> web_user_responses = extractElementsFromCluster<AppSecCustomResponseSpec>(
|
||||
"customresponses",
|
||||
policy_elements_names[AnnotationTypes::WEB_USER_RES]
|
||||
);
|
||||
|
||||
|
||||
vector<AppsecException> exceptions = extractExceptionsFromCluster(
|
||||
"exceptions",
|
||||
policy_elements_names[AnnotationTypes::EXCEPTION]
|
||||
);
|
||||
|
||||
vector<SourceIdentifierSpecWrapper> source_identifiers = extractElementsFromCluster<SourceIdentifierSpecWrapper>(
|
||||
"sourcesidentifiers",
|
||||
policy_elements_names[AnnotationTypes::SOURCE_IDENTIFIERS]
|
||||
);
|
||||
|
||||
vector<TrustedSourcesSpec> trusted_sources = extractElementsFromCluster<TrustedSourcesSpec>(
|
||||
"trustedsources",
|
||||
policy_elements_names[AnnotationTypes::TRUSTED_SOURCES]
|
||||
);
|
||||
|
||||
AppsecLinuxPolicy appsec_policy = AppsecLinuxPolicy(
|
||||
appsec_policy_spec.getSpec(),
|
||||
practices,
|
||||
log_triggers,
|
||||
web_user_responses,
|
||||
exceptions,
|
||||
trusted_sources,
|
||||
source_identifiers
|
||||
);
|
||||
return appsec_policy;
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
void
|
||||
K8sPolicyUtils::createSnortFile(vector<NewAppSecPracticeSpec> &practices) const
|
||||
{
|
||||
for (NewAppSecPracticeSpec &practice : practices) {
|
||||
auto orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<K8sPolicyUtils>();
|
||||
auto path = "/etc/cp/conf/snort/snort_k8s_" + practice.getName() + ".rule";
|
||||
bool append_mode = false;
|
||||
for (const string &config_map : practice.getSnortSignatures().getConfigMap())
|
||||
{
|
||||
auto maybe_configmap = getObjectFromCluster<ConfigMaps>(
|
||||
"/api/v1/namespaces/default/configmaps/" + config_map
|
||||
);
|
||||
if (!maybe_configmap.ok()) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "Failed to get configMaps from the cluster.";
|
||||
continue;
|
||||
}
|
||||
string file_content = maybe_configmap.unpack().getFileContent();
|
||||
string file_name = maybe_configmap.unpack().getFileName();
|
||||
if (!orchestration_tools->writeFile(file_content, path, append_mode)) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "Failed to update the snort_k8s_rules file.";
|
||||
continue;
|
||||
}
|
||||
append_mode = true;
|
||||
practice.getSnortSignatures().addFile(file_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<V1beta2AppsecLinuxPolicy>
|
||||
K8sPolicyUtils::createAppsecPolicyK8sFromV1beta2Crds(
|
||||
const AppsecSpecParser<NewAppsecPolicySpec> &appsec_policy_spec,
|
||||
const string &ingress_mode) const
|
||||
{
|
||||
NewParsedRule default_rule = appsec_policy_spec.getSpec().getDefaultRule();
|
||||
vector<NewParsedRule> specific_rules = appsec_policy_spec.getSpec().getSpecificRules();
|
||||
string appsec_class_name = appsec_policy_spec.getSpec().getAppSecClassName();
|
||||
|
||||
if (getAppSecClassNameFromCluster() != "" &&
|
||||
appsec_class_name != getAppSecClassNameFromCluster()) {
|
||||
return genError("Unmached appsec class name!");
|
||||
}
|
||||
|
||||
if (default_rule.getMode().empty() && !ingress_mode.empty()) {
|
||||
default_rule.setMode(ingress_mode);
|
||||
}
|
||||
|
||||
map<AnnotationTypes, unordered_set<string>> policy_elements_names = extractElementsNamesV1beta2(
|
||||
specific_rules,
|
||||
default_rule
|
||||
);
|
||||
|
||||
vector<NewAppSecPracticeSpec> threat_prevention_practices =
|
||||
extractV1Beta2ElementsFromCluster<NewAppSecPracticeSpec>(
|
||||
"threatpreventionpractices",
|
||||
policy_elements_names[AnnotationTypes::THREAT_PREVENTION_PRACTICE]
|
||||
);
|
||||
|
||||
createSnortFile(threat_prevention_practices);
|
||||
|
||||
vector<AccessControlPracticeSpec> access_control_practices =
|
||||
extractV1Beta2ElementsFromCluster<AccessControlPracticeSpec>(
|
||||
"accesscontrolpractice",
|
||||
policy_elements_names[AnnotationTypes::ACCESS_CONTROL_PRACTICE]
|
||||
);
|
||||
|
||||
vector<NewAppsecLogTrigger> log_triggers = extractV1Beta2ElementsFromCluster<NewAppsecLogTrigger>(
|
||||
"logtriggers",
|
||||
policy_elements_names[AnnotationTypes::TRIGGER]
|
||||
);
|
||||
|
||||
vector<NewAppSecCustomResponse> web_user_responses = extractV1Beta2ElementsFromCluster<NewAppSecCustomResponse>(
|
||||
"customresponses",
|
||||
policy_elements_names[AnnotationTypes::WEB_USER_RES]
|
||||
);
|
||||
|
||||
vector<NewAppsecException> exceptions = extractV1Beta2ElementsFromCluster<NewAppsecException>(
|
||||
"exceptions",
|
||||
policy_elements_names[AnnotationTypes::EXCEPTION]
|
||||
);
|
||||
|
||||
vector<NewSourcesIdentifiers> source_identifiers = extractV1Beta2ElementsFromCluster<NewSourcesIdentifiers>(
|
||||
"sourcesidentifiers",
|
||||
policy_elements_names[AnnotationTypes::SOURCE_IDENTIFIERS]
|
||||
);
|
||||
|
||||
vector<NewTrustedSourcesSpec> trusted_sources = extractV1Beta2ElementsFromCluster<NewTrustedSourcesSpec>(
|
||||
"trustedsources",
|
||||
policy_elements_names[AnnotationTypes::TRUSTED_SOURCES]
|
||||
);
|
||||
|
||||
V1beta2AppsecLinuxPolicy appsec_policy = V1beta2AppsecLinuxPolicy(
|
||||
appsec_policy_spec.getSpec(),
|
||||
threat_prevention_practices,
|
||||
access_control_practices,
|
||||
log_triggers,
|
||||
web_user_responses,
|
||||
exceptions,
|
||||
trusted_sources,
|
||||
source_identifiers
|
||||
);
|
||||
return appsec_policy;
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
bool
|
||||
doesVersionExist(const map<string, string> &annotations, const string &version)
|
||||
{
|
||||
for (auto annotation : annotations) {
|
||||
if(annotation.second.find(version) != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::tuple<Maybe<AppsecLinuxPolicy>, Maybe<V1beta2AppsecLinuxPolicy>>
|
||||
K8sPolicyUtils::createAppsecPolicyK8s(const string &policy_name, const string &ingress_mode) const
|
||||
{
|
||||
auto maybe_appsec_policy_spec = getObjectFromCluster<AppsecSpecParser<AppsecPolicySpec>>(
|
||||
"/apis/openappsec.io/v1beta1/policies/" + policy_name
|
||||
);
|
||||
|
||||
if (!maybe_appsec_policy_spec.ok() ||
|
||||
!doesVersionExist(maybe_appsec_policy_spec.unpack().getMetaData().getAnnotations(), "v1beta1")
|
||||
) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "Failed to retrieve Appsec policy with crds version: v1beta1, Trying version: v1beta2";
|
||||
auto maybe_v1beta2_appsec_policy_spec = getObjectFromCluster<AppsecSpecParser<NewAppsecPolicySpec>>(
|
||||
"/apis/openappsec.io/v1beta2/policies/" + policy_name
|
||||
);
|
||||
if(!maybe_v1beta2_appsec_policy_spec.ok()) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "Failed to retrieve AppSec policy. Error: "
|
||||
<< maybe_v1beta2_appsec_policy_spec.getErr();
|
||||
return std::make_tuple(
|
||||
genError("Failed to retrieve AppSec v1beta1 policy. Error: " + maybe_appsec_policy_spec.getErr()),
|
||||
genError(
|
||||
"Failed to retrieve AppSec v1beta2 policy. Error: " + maybe_v1beta2_appsec_policy_spec.getErr()));
|
||||
}
|
||||
return std::make_tuple(
|
||||
genError("There is no v1beta1 policy"),
|
||||
createAppsecPolicyK8sFromV1beta2Crds(maybe_v1beta2_appsec_policy_spec.unpack(), ingress_mode));
|
||||
}
|
||||
|
||||
return std::make_tuple(
|
||||
createAppsecPolicyK8sFromV1beta1Crds(maybe_appsec_policy_spec.unpack(), ingress_mode),
|
||||
genError("There is no v1beta2 policy"));
|
||||
}
|
||||
|
||||
template<class T, class K>
|
||||
void
|
||||
K8sPolicyUtils::createPolicy(
|
||||
T &appsec_policy,
|
||||
map<std::string, T> &policies,
|
||||
map<AnnotationKeys, string> &annotations_values,
|
||||
const SingleIngressData &item) const
|
||||
{
|
||||
for (const IngressDefinedRule &rule : item.getSpec().getRules()) {
|
||||
string url = rule.getHost();
|
||||
for (const IngressRulePath &uri : rule.getPathsWrapper().getRulePaths()) {
|
||||
if (!appsec_policy.getAppsecPolicySpec().isAssetHostExist(url + uri.getPath())) {
|
||||
dbgTrace(D_LOCAL_POLICY)
|
||||
<< "Inserting Host data to the specific asset set:"
|
||||
<< "URL: '"
|
||||
<< url
|
||||
<< "' uri: '"
|
||||
<< uri.getPath()
|
||||
<< "'";
|
||||
K ingress_rule = K(url + uri.getPath());
|
||||
appsec_policy.addSpecificRule(ingress_rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
policies[annotations_values[AnnotationKeys::PolicyKey]] = appsec_policy;
|
||||
}
|
||||
|
||||
|
||||
std::tuple<map<string, AppsecLinuxPolicy>, map<string, V1beta2AppsecLinuxPolicy>>
|
||||
K8sPolicyUtils::createAppsecPoliciesFromIngresses()
|
||||
{
|
||||
dbgFlow(D_LOCAL_POLICY) << "Getting all policy object from Ingresses";
|
||||
map<string, AppsecLinuxPolicy> v1bet1_policies;
|
||||
map<string, V1beta2AppsecLinuxPolicy> v1bet2_policies;
|
||||
auto maybe_ingress = getObjectFromCluster<IngressData>("/apis/networking.k8s.io/v1/ingresses");
|
||||
|
||||
if (!maybe_ingress.ok()) {
|
||||
// TBD: Error handling : INXT-31444
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "Failed to retrieve K8S Ingress configurations. Error: "
|
||||
<< maybe_ingress.getErr();
|
||||
return make_tuple(v1bet1_policies, v1bet2_policies);
|
||||
}
|
||||
|
||||
|
||||
IngressData ingress = maybe_ingress.unpack();
|
||||
for (const SingleIngressData &item : ingress.getItems()) {
|
||||
map<AnnotationKeys, string> annotations_values = parseIngressAnnotations(
|
||||
item.getMetadata().getAnnotations()
|
||||
);
|
||||
|
||||
if (annotations_values[AnnotationKeys::PolicyKey].empty()) {
|
||||
dbgInfo(D_LOCAL_POLICY) << "No policy was found in this ingress";
|
||||
continue;
|
||||
}
|
||||
|
||||
auto maybe_appsec_policy = createAppsecPolicyK8s(
|
||||
annotations_values[AnnotationKeys::PolicyKey],
|
||||
annotations_values[AnnotationKeys::ModeKey]
|
||||
);
|
||||
if (!std::get<0>(maybe_appsec_policy).ok() && !std::get<1>(maybe_appsec_policy).ok()) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "Failed to create appsec policy. Error: "
|
||||
<< std::get<1>(maybe_appsec_policy).getErr();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!std::get<0>(maybe_appsec_policy).ok()) {
|
||||
auto appsec_policy=std::get<1>(maybe_appsec_policy).unpack();
|
||||
createPolicy<V1beta2AppsecLinuxPolicy, NewParsedRule>(
|
||||
appsec_policy,
|
||||
v1bet2_policies,
|
||||
annotations_values,
|
||||
item);
|
||||
} else {
|
||||
auto appsec_policy=std::get<0>(maybe_appsec_policy).unpack();
|
||||
createPolicy<AppsecLinuxPolicy, ParsedRule>(
|
||||
appsec_policy,
|
||||
v1bet1_policies,
|
||||
annotations_values,
|
||||
item);
|
||||
}
|
||||
}
|
||||
return make_tuple(v1bet1_policies, v1bet2_policies);
|
||||
}
|
||||
@@ -43,7 +43,7 @@
|
||||
#include "include/rules_config_section.h"
|
||||
#include "include/trusted_sources_section.h"
|
||||
#include "include/policy_maker_utils.h"
|
||||
#include "include/k8s_policy_utils.h"
|
||||
#include "k8s_policy_utils.h"
|
||||
#include "i_env_details.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -64,31 +64,10 @@ public:
|
||||
void
|
||||
init()
|
||||
{
|
||||
env_details = Singleton::Consume<I_EnvDetails>::by<LocalPolicyMgmtGenerator::Impl>();
|
||||
env_type = env_details->getEnvType();
|
||||
if (env_type == EnvType::LINUX) {
|
||||
dbgInfo(D_LOCAL_POLICY) << "Initializing Linux policy generator";
|
||||
local_policy_path = getFilesystemPathConfig() + default_local_mgmt_policy_path;
|
||||
return;
|
||||
}
|
||||
dbgInfo(D_LOCAL_POLICY) << "Initializing K8S policy generator";
|
||||
k8s_policy_utils.init();
|
||||
|
||||
Singleton::Consume<I_MainLoop>::by<LocalPolicyMgmtGenerator::Impl>()->addOneTimeRoutine(
|
||||
I_MainLoop::RoutineType::Offline,
|
||||
[this] ()
|
||||
{
|
||||
while(!k8s_policy_utils.getClusterId()) {
|
||||
Singleton::Consume<I_MainLoop>::by<LocalPolicyMgmtGenerator::Impl>()->yield(chrono::seconds(1));
|
||||
}
|
||||
return;
|
||||
},
|
||||
"Get k8s cluster ID"
|
||||
);
|
||||
}
|
||||
|
||||
string
|
||||
parseLinuxPolicy(const string &policy_version)
|
||||
parseLinuxPolicy(const string &policy_version, const string &local_policy_path)
|
||||
{
|
||||
dbgFlow(D_LOCAL_POLICY) << "Starting to parse policy - embedded environment";
|
||||
|
||||
@@ -104,36 +83,34 @@ public:
|
||||
{
|
||||
dbgFlow(D_LOCAL_POLICY) << "Starting to parse policy - K8S environment";
|
||||
|
||||
map<string, AppsecLinuxPolicy> appsec_policies = k8s_policy_utils.createAppsecPoliciesFromIngresses();
|
||||
return policy_maker_utils.proccesMultipleAppsecPolicies(
|
||||
appsec_policies,
|
||||
dbgInfo(D_LOCAL_POLICY) << "Initializing K8S policy generator";
|
||||
K8sPolicyUtils k8s_policy_utils;
|
||||
k8s_policy_utils.init();
|
||||
|
||||
auto appsec_policies = k8s_policy_utils.createAppsecPoliciesFromIngresses();
|
||||
if (!std::get<0>(appsec_policies).empty()) {
|
||||
return policy_maker_utils.proccesMultipleAppsecPolicies<AppsecLinuxPolicy, ParsedRule>(
|
||||
std::get<0>(appsec_policies),
|
||||
policy_version,
|
||||
default_local_appsec_policy_path
|
||||
);
|
||||
}
|
||||
return policy_maker_utils.proccesMultipleAppsecPolicies<V1beta2AppsecLinuxPolicy, NewParsedRule>(
|
||||
std::get<1>(appsec_policies),
|
||||
policy_version,
|
||||
default_local_appsec_policy_path
|
||||
);
|
||||
}
|
||||
|
||||
string
|
||||
parsePolicy(const string &policy_version)
|
||||
generateAppSecLocalPolicy(EnvType env_type, const string &policy_version, const string &local_policy_paths)
|
||||
{
|
||||
return isK8sEnv() ? parseK8sPolicy(policy_version) : parseLinuxPolicy(policy_version);
|
||||
return env_type == EnvType::K8S ?
|
||||
parseK8sPolicy(policy_version) : parseLinuxPolicy(policy_version, local_policy_paths);
|
||||
}
|
||||
|
||||
const string & getAgentPolicyPath(void) const override { return default_local_appsec_policy_path; }
|
||||
const string & getLocalPolicyPath(void) const override { return local_policy_path; }
|
||||
void setPolicyPath(const string &new_local_policy_path) override { local_policy_path = new_local_policy_path; }
|
||||
|
||||
private:
|
||||
bool
|
||||
isK8sEnv()
|
||||
{
|
||||
return env_type == EnvType::K8S;
|
||||
}
|
||||
|
||||
I_EnvDetails* env_details = nullptr;
|
||||
EnvType env_type;
|
||||
PolicyMakerUtils policy_maker_utils;
|
||||
K8sPolicyUtils k8s_policy_utils;
|
||||
string local_policy_path;
|
||||
|
||||
};
|
||||
|
||||
72
components/security_apps/local_policy_mgmt_gen/new_appsec_linux_policy.cc
Executable file
72
components/security_apps/local_policy_mgmt_gen/new_appsec_linux_policy.cc
Executable file
@@ -0,0 +1,72 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "new_appsec_linux_policy.h"
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
|
||||
using namespace std;
|
||||
|
||||
const NewAppsecPolicySpec &
|
||||
V1beta2AppsecLinuxPolicy::getAppsecPolicySpec() const
|
||||
{
|
||||
return policies;
|
||||
}
|
||||
|
||||
const vector<NewAppSecPracticeSpec> &
|
||||
V1beta2AppsecLinuxPolicy::getAppSecPracticeSpecs() const
|
||||
{
|
||||
return threat_prevection_practices;
|
||||
}
|
||||
|
||||
const vector<AccessControlPracticeSpec> &
|
||||
V1beta2AppsecLinuxPolicy::getAccessControlPracticeSpecs() const
|
||||
{
|
||||
return access_control_practices;
|
||||
}
|
||||
|
||||
const vector<NewAppsecLogTrigger> &
|
||||
V1beta2AppsecLinuxPolicy::getAppsecTriggerSpecs() const
|
||||
{
|
||||
return log_triggers;
|
||||
}
|
||||
|
||||
const vector<NewAppSecCustomResponse> &
|
||||
V1beta2AppsecLinuxPolicy::getAppSecCustomResponseSpecs() const
|
||||
{
|
||||
return custom_responses;
|
||||
}
|
||||
|
||||
const vector<NewAppsecException> &
|
||||
V1beta2AppsecLinuxPolicy::getAppsecExceptions() const
|
||||
{
|
||||
return exceptions;
|
||||
}
|
||||
|
||||
const vector<NewTrustedSourcesSpec> &
|
||||
V1beta2AppsecLinuxPolicy::getAppsecTrustedSourceSpecs() const
|
||||
{
|
||||
return trusted_sources;
|
||||
}
|
||||
|
||||
const vector<NewSourcesIdentifiers> &
|
||||
V1beta2AppsecLinuxPolicy::getAppsecSourceIdentifierSpecs() const
|
||||
{
|
||||
return sources_identifiers;
|
||||
}
|
||||
|
||||
void
|
||||
V1beta2AppsecLinuxPolicy::addSpecificRule(const NewParsedRule &_rule)
|
||||
{
|
||||
policies.addSpecificRule(_rule);
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
154
components/security_apps/local_policy_mgmt_gen/new_appsec_policy_crd_parser.cc
Executable file
154
components/security_apps/local_policy_mgmt_gen/new_appsec_policy_crd_parser.cc
Executable file
@@ -0,0 +1,154 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "new_appsec_policy_crd_parser.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
USE_DEBUG_FLAG(D_LOCAL_POLICY);
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
|
||||
static const set<string> valid_modes = {"prevent-learn", "detect-learn", "prevent", "detect", "inactive"};
|
||||
|
||||
void
|
||||
NewParsedRule::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec NewParsedRule";
|
||||
parseAppsecJSONKey<vector<string>>("exceptions", exceptions, archive_in);
|
||||
parseAppsecJSONKey<vector<string>>("triggers", log_triggers, archive_in);
|
||||
parseAppsecJSONKey<vector<string>>("threatPreventionPractices", threat_prevention_practices, archive_in);
|
||||
parseAppsecJSONKey<vector<string>>("accessControlPractices", access_control_practices, archive_in);
|
||||
parseAppsecJSONKey<string>("mode", mode, archive_in);
|
||||
if (valid_modes.count(mode) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec New Parsed Rule mode invalid: " << mode;
|
||||
}
|
||||
parseAppsecJSONKey<string>("customResponse", custom_response, archive_in);
|
||||
parseAppsecJSONKey<string>("sourceIdentifiers", source_identifiers, archive_in);
|
||||
parseAppsecJSONKey<string>("trustedSources", trusted_sources, archive_in);
|
||||
try {
|
||||
archive_in(cereal::make_nvp("host", host));
|
||||
} catch (const cereal::Exception &e)
|
||||
{
|
||||
// The default NewParsedRule does not hold a host, so by default it will be *
|
||||
host = "*";
|
||||
}
|
||||
}
|
||||
|
||||
const vector<string> &
|
||||
NewParsedRule::getLogTriggers() const
|
||||
{
|
||||
return log_triggers;
|
||||
}
|
||||
const vector<string> &
|
||||
|
||||
NewParsedRule::getExceptions() const
|
||||
{
|
||||
return exceptions;
|
||||
}
|
||||
|
||||
const vector<string> &
|
||||
NewParsedRule::getPractices() const
|
||||
{
|
||||
return threat_prevention_practices;
|
||||
}
|
||||
|
||||
const vector<string> &
|
||||
NewParsedRule::getAccessControlPractices() const
|
||||
{
|
||||
return access_control_practices;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewParsedRule::getSourceIdentifiers() const
|
||||
{
|
||||
return source_identifiers;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewParsedRule::getCustomResponse() const
|
||||
{
|
||||
return custom_response;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewParsedRule::getTrustedSources() const
|
||||
{
|
||||
return trusted_sources;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewParsedRule::getHost() const
|
||||
{
|
||||
return host;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewParsedRule::getMode() const
|
||||
{
|
||||
return mode;
|
||||
}
|
||||
|
||||
void
|
||||
NewParsedRule::setHost(const string &_host)
|
||||
{
|
||||
host = _host;
|
||||
}
|
||||
|
||||
void
|
||||
NewParsedRule::setMode(const string &_mode)
|
||||
{
|
||||
mode = _mode;
|
||||
}
|
||||
|
||||
void
|
||||
NewAppsecPolicySpec::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec policy spec";
|
||||
parseAppsecJSONKey<string>("appsecClassName", appsec_class_name, archive_in);
|
||||
parseAppsecJSONKey<NewParsedRule>("default", default_rule, archive_in);
|
||||
parseAppsecJSONKey<vector<NewParsedRule>>("specificRules", specific_rules, archive_in);
|
||||
}
|
||||
|
||||
const NewParsedRule &
|
||||
NewAppsecPolicySpec::getDefaultRule() const
|
||||
{
|
||||
return default_rule;
|
||||
}
|
||||
|
||||
const vector<NewParsedRule> &
|
||||
NewAppsecPolicySpec::getSpecificRules() const
|
||||
{
|
||||
return specific_rules;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppsecPolicySpec::getAppSecClassName() const
|
||||
{
|
||||
return appsec_class_name;
|
||||
}
|
||||
|
||||
bool
|
||||
NewAppsecPolicySpec::isAssetHostExist(const std::string &full_url) const
|
||||
{
|
||||
for (const NewParsedRule &rule : specific_rules) {
|
||||
if (rule.getHost() == full_url) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
NewAppsecPolicySpec::addSpecificRule(const NewParsedRule &_rule)
|
||||
{
|
||||
specific_rules.push_back(_rule);
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
99
components/security_apps/local_policy_mgmt_gen/new_custom_response.cc
Executable file
99
components/security_apps/local_policy_mgmt_gen/new_custom_response.cc
Executable file
@@ -0,0 +1,99 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "new_custom_response.h"
|
||||
|
||||
#define MIN_RESPONSE_CODE 100
|
||||
#define MAX_RESPOMSE_CODE 599
|
||||
|
||||
using namespace std;
|
||||
|
||||
USE_DEBUG_FLAG(D_LOCAL_POLICY);
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
|
||||
static const set<string> valid_modes = {"block-page", "response-code-only", "redirect"};
|
||||
|
||||
void
|
||||
NewAppSecCustomResponse::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec web user response spec";
|
||||
parseAppsecJSONKey<string>("appsecClassName", appsec_class_name, archive_in);
|
||||
parseAppsecJSONKey<int>("httpResponseCode", http_response_code, archive_in, 403);
|
||||
if (http_response_code < MIN_RESPONSE_CODE || http_response_code > MAX_RESPOMSE_CODE) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec web user response code invalid: " << http_response_code;
|
||||
}
|
||||
parseAppsecJSONKey<string>("mode", mode, archive_in, "block-page");
|
||||
if (valid_modes.count(mode) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec web user response mode invalid: " << mode;
|
||||
}
|
||||
parseAppsecJSONKey<string>("name", name, archive_in);
|
||||
parseAppsecJSONKey<string>("redirectUrl", redirect_url, archive_in);
|
||||
parseAppsecJSONKey<bool>("redirectAddXEventId", redirect_add_x_event_id, archive_in);
|
||||
if (mode == "block-page") {
|
||||
parseAppsecJSONKey<string>(
|
||||
"messageBody",
|
||||
message_body,
|
||||
archive_in,
|
||||
"Openappsec's <b>Application Security</b> has detected an attack and blocked it."
|
||||
);
|
||||
parseAppsecJSONKey<string>(
|
||||
"messageTitle",
|
||||
message_title,
|
||||
archive_in,
|
||||
"Attack blocked by web application protection"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NewAppSecCustomResponse::setName(const string &_name)
|
||||
{
|
||||
name = _name;
|
||||
}
|
||||
|
||||
int
|
||||
NewAppSecCustomResponse::getHttpResponseCode() const
|
||||
{
|
||||
return http_response_code;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppSecCustomResponse::getMessageBody() const
|
||||
{
|
||||
return message_body;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppSecCustomResponse::getMessageTitle() const
|
||||
{
|
||||
return message_title;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppSecCustomResponse::getAppSecClassName() const
|
||||
{
|
||||
return appsec_class_name;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppSecCustomResponse::getMode() const
|
||||
{
|
||||
return mode;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppSecCustomResponse::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
187
components/security_apps/local_policy_mgmt_gen/new_exceptions.cc
Executable file
187
components/security_apps/local_policy_mgmt_gen/new_exceptions.cc
Executable file
@@ -0,0 +1,187 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "new_exceptions.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
USE_DEBUG_FLAG(D_LOCAL_POLICY);
|
||||
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
static const set<string> valid_actions = {"skip", "accept", "drop", "suppressLog"};
|
||||
|
||||
void
|
||||
NewAppsecExceptionCondition::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading New AppSec exception condition";
|
||||
parseAppsecJSONKey<string>("key", key, archive_in);
|
||||
parseAppsecJSONKey<string>("value", value, archive_in);
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppsecExceptionCondition::getKey() const
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppsecExceptionCondition::getvalue() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
void
|
||||
NewAppsecException::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading New AppSec exception";
|
||||
parseAppsecJSONKey<string>("name", name, archive_in);
|
||||
parseAppsecJSONKey<string>("action", action, archive_in);
|
||||
parseAppsecJSONKey<string>("appsecClassName", appsec_class_name, archive_in);
|
||||
if (valid_actions.count(action) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec exception action invalid: " << action;
|
||||
}
|
||||
parseAppsecJSONKey<vector<NewAppsecExceptionCondition>>("condition", conditions, archive_in);
|
||||
}
|
||||
|
||||
void
|
||||
NewAppsecException::setName(const string &_name)
|
||||
{
|
||||
name = _name;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppsecException::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppsecException::getAction() const
|
||||
{
|
||||
return action;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppsecException::getAppSecClassName() const
|
||||
{
|
||||
return appsec_class_name;
|
||||
}
|
||||
|
||||
const vector<string>
|
||||
NewAppsecException::getCountryCode() const
|
||||
{
|
||||
vector<string> country_codes;
|
||||
for (const NewAppsecExceptionCondition &condition : conditions) {
|
||||
if (condition.getKey() == "countryCode") {
|
||||
country_codes.push_back(condition.getvalue());
|
||||
}
|
||||
}
|
||||
return country_codes;
|
||||
}
|
||||
|
||||
const vector<string>
|
||||
NewAppsecException::getCountryName() const
|
||||
{
|
||||
vector<string> country_names;
|
||||
for (const NewAppsecExceptionCondition &condition : conditions) {
|
||||
if (condition.getKey() == "countryName") {
|
||||
country_names.push_back(condition.getvalue());
|
||||
}
|
||||
}
|
||||
return country_names;
|
||||
}
|
||||
|
||||
const vector<string>
|
||||
NewAppsecException::getHostName() const
|
||||
{
|
||||
vector<string> host_names;
|
||||
for (const NewAppsecExceptionCondition &condition : conditions) {
|
||||
if (condition.getKey() == "hostName") {
|
||||
host_names.push_back(condition.getvalue());
|
||||
}
|
||||
}
|
||||
return host_names;
|
||||
}
|
||||
|
||||
const vector<string>
|
||||
NewAppsecException::getParamName() const
|
||||
{
|
||||
vector<string> param_names;
|
||||
for (const NewAppsecExceptionCondition &condition : conditions) {
|
||||
if (condition.getKey() == "paramName") {
|
||||
param_names.push_back(condition.getvalue());
|
||||
}
|
||||
}
|
||||
return param_names;
|
||||
}
|
||||
|
||||
const vector<string>
|
||||
NewAppsecException::getParamValue() const
|
||||
{
|
||||
vector<string> param_values;
|
||||
for (const NewAppsecExceptionCondition &condition : conditions) {
|
||||
if (condition.getKey() == "paramValue") {
|
||||
param_values.push_back(condition.getvalue());
|
||||
}
|
||||
}
|
||||
return param_values;
|
||||
}
|
||||
|
||||
const vector<string>
|
||||
NewAppsecException::getProtectionName() const
|
||||
{
|
||||
vector<string> protection_names;
|
||||
for (const NewAppsecExceptionCondition &condition : conditions) {
|
||||
if (condition.getKey() == "protectionName") {
|
||||
protection_names.push_back(condition.getvalue());
|
||||
}
|
||||
}
|
||||
return protection_names;
|
||||
}
|
||||
|
||||
const vector<string>
|
||||
NewAppsecException::getSourceIdentifier() const
|
||||
{
|
||||
vector<string> source_identifiers;
|
||||
for (const NewAppsecExceptionCondition &condition : conditions) {
|
||||
if (condition.getKey() == "sourceIdentifier") {
|
||||
source_identifiers.push_back(condition.getvalue());
|
||||
}
|
||||
}
|
||||
return source_identifiers;
|
||||
}
|
||||
|
||||
const vector<string>
|
||||
NewAppsecException::getSourceIp() const
|
||||
{
|
||||
vector<string> source_ips;
|
||||
for (const NewAppsecExceptionCondition &condition : conditions) {
|
||||
if (condition.getKey() == "sourceIp") {
|
||||
source_ips.push_back(condition.getvalue());
|
||||
}
|
||||
}
|
||||
return source_ips;
|
||||
}
|
||||
|
||||
const vector<string>
|
||||
NewAppsecException::getUrl() const
|
||||
{
|
||||
vector<string> urls;
|
||||
for (const NewAppsecExceptionCondition &condition : conditions) {
|
||||
if (condition.getKey() == "url") {
|
||||
urls.push_back(condition.getvalue());
|
||||
}
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
321
components/security_apps/local_policy_mgmt_gen/new_log_trigger.cc
Executable file
321
components/security_apps/local_policy_mgmt_gen/new_log_trigger.cc
Executable file
@@ -0,0 +1,321 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "new_log_trigger.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
USE_DEBUG_FLAG(D_LOCAL_POLICY);
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
|
||||
static const set<string> valid_severities = {"high", "critical"};
|
||||
static const set<string> valid_protocols = {"tcp", "udp"};
|
||||
static const set<string> valid_formats = {"json", "json-formatted"};
|
||||
|
||||
void
|
||||
NewAppsecTriggerAccessControlLogging::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec Trigger - Access Control Logging";
|
||||
parseAppsecJSONKey<bool>("allowEvents", allow_events, archive_in, false);
|
||||
parseAppsecJSONKey<bool>("dropEvents", drop_events, archive_in, false);
|
||||
}
|
||||
|
||||
void
|
||||
NewAppsecTriggerAdditionalSuspiciousEventsLogging::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec Trigger - Additional Suspicious Events Logging";
|
||||
parseAppsecJSONKey<bool>("enabled", enabled, archive_in, true);
|
||||
parseAppsecJSONKey<bool>("responseBody", response_body, archive_in, false);
|
||||
//the old code didn't parse the responsecode so ask Noam what is the currenct default value for it
|
||||
parseAppsecJSONKey<bool>("responseCode", response_code, archive_in, false);
|
||||
parseAppsecJSONKey<string>("minSeverity", minimum_severity, archive_in, "high");
|
||||
if (valid_severities.count(minimum_severity) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec AppSec Trigger - Additional Suspicious Events Logging minimum severity invalid: "
|
||||
<< minimum_severity;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
NewAppsecTriggerAdditionalSuspiciousEventsLogging::isEnabled() const
|
||||
{
|
||||
return enabled;
|
||||
}
|
||||
|
||||
bool
|
||||
NewAppsecTriggerAdditionalSuspiciousEventsLogging::isResponseBody() const
|
||||
{
|
||||
return response_body;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppsecTriggerAdditionalSuspiciousEventsLogging::getMinimumSeverity() const
|
||||
{
|
||||
return minimum_severity;
|
||||
}
|
||||
|
||||
void
|
||||
NewAppsecTriggerLogging::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec Trigger Logging";
|
||||
parseAppsecJSONKey<bool>("detectEvents", detect_events, archive_in, false);
|
||||
parseAppsecJSONKey<bool>("preventEvents", prevent_events, archive_in, true);
|
||||
parseAppsecJSONKey<bool>("allWebRequests", all_web_requests, archive_in, false);
|
||||
}
|
||||
|
||||
bool
|
||||
NewAppsecTriggerLogging::isAllWebRequests() const
|
||||
{
|
||||
return all_web_requests;
|
||||
}
|
||||
|
||||
bool
|
||||
NewAppsecTriggerLogging::isDetectEvents() const
|
||||
{
|
||||
return detect_events;
|
||||
}
|
||||
|
||||
bool
|
||||
NewAppsecTriggerLogging::isPreventEvents() const
|
||||
{
|
||||
return prevent_events;
|
||||
}
|
||||
|
||||
void
|
||||
NewAppsecTriggerExtendedLogging::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec Trigger Extended Logging";
|
||||
parseAppsecJSONKey<bool>("httpHeaders", http_headers, archive_in, false);
|
||||
parseAppsecJSONKey<bool>("requestBody", request_body, archive_in, false);
|
||||
parseAppsecJSONKey<bool>("urlPath", url_path, archive_in, false);
|
||||
parseAppsecJSONKey<bool>("urlQuery", url_query, archive_in, false);
|
||||
}
|
||||
|
||||
bool
|
||||
NewAppsecTriggerExtendedLogging::isHttpHeaders() const
|
||||
{
|
||||
return http_headers;
|
||||
}
|
||||
|
||||
bool
|
||||
NewAppsecTriggerExtendedLogging::isRequestBody() const
|
||||
{
|
||||
return request_body;
|
||||
}
|
||||
|
||||
bool
|
||||
NewAppsecTriggerExtendedLogging::isUrlPath() const
|
||||
{
|
||||
return url_path;
|
||||
}
|
||||
|
||||
bool
|
||||
NewAppsecTriggerExtendedLogging::isUrlQuery() const
|
||||
{
|
||||
return url_query;
|
||||
}
|
||||
|
||||
void
|
||||
NewLoggingService::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
parseAppsecJSONKey<string>("address", address, archive_in);
|
||||
parseAppsecJSONKey<string>("proto", proto, archive_in);
|
||||
if (valid_protocols.count(proto) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec Logging Service - proto invalid: " << proto;
|
||||
}
|
||||
|
||||
parseAppsecJSONKey<int>("port", port, archive_in, 514);
|
||||
}
|
||||
|
||||
const string &
|
||||
NewLoggingService::getAddress() const
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
int
|
||||
NewLoggingService::getPort() const
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NewStdoutLogging::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
parseAppsecJSONKey<string>("format", format, archive_in, "json");
|
||||
if (valid_formats.count(format) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec Stdout Logging - format invalid: " << format;
|
||||
}
|
||||
}
|
||||
|
||||
const string &
|
||||
NewStdoutLogging::getFormat() const
|
||||
{
|
||||
return format;
|
||||
}
|
||||
|
||||
void
|
||||
NewAppsecTriggerLogDestination::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec Trigger LogDestination";
|
||||
// TBD: support "file"
|
||||
parseAppsecJSONKey<bool>("cloud", cloud, archive_in, false);
|
||||
auto mode = Singleton::Consume<I_AgentDetails>::by<NewAppsecTriggerLogDestination>()->getOrchestrationMode();
|
||||
auto env_type = Singleton::Consume<I_EnvDetails>::by<NewAppsecTriggerLogDestination>()->getEnvType();
|
||||
bool k8s_service_default = (mode == OrchestrationMode::HYBRID && env_type == EnvType::K8S);
|
||||
parseAppsecJSONKey<bool>("k8s-service", k8s_service, archive_in, k8s_service_default);
|
||||
|
||||
NewStdoutLogging stdout_log;
|
||||
parseAppsecJSONKey<NewStdoutLogging>("stdout", stdout_log, archive_in);
|
||||
agent_local = !(stdout_log.getFormat().empty());
|
||||
beautify_logs = stdout_log.getFormat() == "json-formatted";
|
||||
parseAppsecJSONKey<NewLoggingService>("syslogService", syslog_service, archive_in);
|
||||
parseAppsecJSONKey<NewLoggingService>("cefService", cef_service, archive_in);
|
||||
}
|
||||
|
||||
int
|
||||
NewAppsecTriggerLogDestination::getCefServerUdpPort() const
|
||||
{
|
||||
return getCefServiceData().getPort();
|
||||
}
|
||||
|
||||
int
|
||||
NewAppsecTriggerLogDestination::getSyslogServerUdpPort() const
|
||||
{
|
||||
return getSyslogServiceData().getPort();
|
||||
}
|
||||
|
||||
bool
|
||||
NewAppsecTriggerLogDestination::isAgentLocal() const
|
||||
{
|
||||
return agent_local;
|
||||
}
|
||||
|
||||
bool
|
||||
NewAppsecTriggerLogDestination::shouldBeautifyLogs() const
|
||||
{
|
||||
return beautify_logs;
|
||||
}
|
||||
|
||||
bool
|
||||
NewAppsecTriggerLogDestination::getCloud() const
|
||||
{
|
||||
return cloud;
|
||||
}
|
||||
|
||||
bool
|
||||
NewAppsecTriggerLogDestination::isK8SNeeded() const
|
||||
{
|
||||
return k8s_service;
|
||||
}
|
||||
|
||||
bool
|
||||
NewAppsecTriggerLogDestination::isCefNeeded() const
|
||||
{
|
||||
return !getCefServiceData().getAddress().empty();
|
||||
}
|
||||
|
||||
bool
|
||||
NewAppsecTriggerLogDestination::isSyslogNeeded() const
|
||||
{
|
||||
return !getSyslogServiceData().getAddress().empty();
|
||||
}
|
||||
|
||||
const
|
||||
string & NewAppsecTriggerLogDestination::getSyslogServerIpv4Address() const
|
||||
{
|
||||
return getSyslogServiceData().getAddress();
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppsecTriggerLogDestination::getCefServerIpv4Address() const
|
||||
{
|
||||
return getCefServiceData().getAddress();
|
||||
}
|
||||
|
||||
const NewLoggingService &
|
||||
NewAppsecTriggerLogDestination::getSyslogServiceData() const
|
||||
{
|
||||
return syslog_service;
|
||||
}
|
||||
|
||||
const NewLoggingService &
|
||||
NewAppsecTriggerLogDestination::getCefServiceData() const
|
||||
{
|
||||
return cef_service;
|
||||
}
|
||||
|
||||
void
|
||||
NewAppsecLogTrigger::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec log trigger";
|
||||
parseAppsecJSONKey<string>("appsecClassName", appsec_class_name, archive_in);
|
||||
parseAppsecJSONKey<NewAppsecTriggerAccessControlLogging>(
|
||||
"accessControlLogging",
|
||||
access_control_logging,
|
||||
archive_in
|
||||
);
|
||||
parseAppsecJSONKey<NewAppsecTriggerAdditionalSuspiciousEventsLogging>(
|
||||
"additionalSuspiciousEventsLogging",
|
||||
additional_suspicious_events_logging,
|
||||
archive_in
|
||||
);
|
||||
parseAppsecJSONKey<NewAppsecTriggerLogging>("appsecLogging", appsec_logging, archive_in);
|
||||
parseAppsecJSONKey<NewAppsecTriggerExtendedLogging>("extendedLogging", extended_logging, archive_in);
|
||||
parseAppsecJSONKey<NewAppsecTriggerLogDestination>("logDestination", log_destination, archive_in);
|
||||
parseAppsecJSONKey<string>("name", name, archive_in);
|
||||
}
|
||||
|
||||
void
|
||||
NewAppsecLogTrigger::setName(const string &_name)
|
||||
{
|
||||
name = _name;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppsecLogTrigger::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppsecLogTrigger::getAppSecClassName() const
|
||||
{
|
||||
return appsec_class_name;
|
||||
}
|
||||
|
||||
const NewAppsecTriggerAdditionalSuspiciousEventsLogging &
|
||||
NewAppsecLogTrigger::getAppsecTriggerAdditionalSuspiciousEventsLogging() const
|
||||
{
|
||||
return additional_suspicious_events_logging;
|
||||
}
|
||||
|
||||
const NewAppsecTriggerLogging &
|
||||
NewAppsecLogTrigger::getAppsecTriggerLogging() const
|
||||
{
|
||||
return appsec_logging;
|
||||
}
|
||||
|
||||
const NewAppsecTriggerExtendedLogging &
|
||||
NewAppsecLogTrigger::getAppsecTriggerExtendedLogging() const
|
||||
{
|
||||
return extended_logging;
|
||||
}
|
||||
|
||||
const NewAppsecTriggerLogDestination &
|
||||
NewAppsecLogTrigger::getAppsecTriggerLogDestination() const
|
||||
{
|
||||
return log_destination;
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
986
components/security_apps/local_policy_mgmt_gen/new_practice.cc
Executable file
986
components/security_apps/local_policy_mgmt_gen/new_practice.cc
Executable file
@@ -0,0 +1,986 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "new_practice.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
USE_DEBUG_FLAG(D_LOCAL_POLICY);
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
|
||||
static const set<string> performance_impacts = {"low", "medium", "high"};
|
||||
static const set<string> severity_levels = {"low", "medium", "high", "critical"};
|
||||
static const set<string> size_unit = {"bytes", "KB", "MB", "GB"};
|
||||
static const set<string> confidences_actions = {"prevent", "detect", "inactive"};
|
||||
static const set<string> valid_modes = {"prevent", "detect", "inactive", "prevent-learn", "detect-learn"};
|
||||
static const set<string> valid_confidences = {"medium", "high", "critical"};
|
||||
static const std::unordered_map<std::string, std::string> key_to_performance_impact_val = {
|
||||
{ "low", "Low or lower"},
|
||||
{ "medium", "Medium or lower"},
|
||||
{ "high", "High or lower"}
|
||||
};
|
||||
static const std::unordered_map<std::string, std::string> key_to_severity_level_val = {
|
||||
{ "low", "Low or above"},
|
||||
{ "medium", "Medium or above"},
|
||||
{ "high", "High or above"},
|
||||
{ "critical", "Critical"}
|
||||
};
|
||||
static const std::unordered_map<std::string, std::string> key_to_mode_val = {
|
||||
{ "prevent-learn", "Prevent"},
|
||||
{ "detect-learn", "Detect"},
|
||||
{ "prevent", "Prevent"},
|
||||
{ "detect", "Detect"},
|
||||
{ "inactive", "Inactive"}
|
||||
};
|
||||
static const std::unordered_map<std::string, int> unit_to_int = {
|
||||
{ "bytes", 1},
|
||||
{ "KB", 1024},
|
||||
{ "MB", 1048576},
|
||||
{ "GB", 1073741824}
|
||||
};
|
||||
|
||||
void
|
||||
NewAppSecWebBotsURI::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec Web Bots URI";
|
||||
parseAppsecJSONKey<string>("uri", uri, archive_in);
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppSecWebBotsURI::getURI() const
|
||||
{
|
||||
return uri;
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
NewAppSecPracticeAntiBot::getIjectedUris() const
|
||||
{
|
||||
vector<string> injected;
|
||||
for (const NewAppSecWebBotsURI &uri : injected_uris) injected.push_back(uri.getURI());
|
||||
return injected;
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
NewAppSecPracticeAntiBot::getValidatedUris() const
|
||||
{
|
||||
vector<string> validated;
|
||||
for (const NewAppSecWebBotsURI &uri : validated_uris) validated.push_back(uri.getURI());
|
||||
return validated;
|
||||
}
|
||||
|
||||
void
|
||||
NewAppSecPracticeAntiBot::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec Web Bots";
|
||||
parseAppsecJSONKey<vector<NewAppSecWebBotsURI>>("injectedUris", injected_uris, archive_in);
|
||||
parseAppsecJSONKey<vector<NewAppSecWebBotsURI>>("validatedUris", validated_uris, archive_in);
|
||||
parseAppsecJSONKey<string>("overrideMode", override_mode, archive_in, "Inactive");
|
||||
if (valid_modes.count(override_mode) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec Web Bots override mode invalid: " << override_mode;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NewAppSecPracticeAntiBot::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
vector<string> injected;
|
||||
vector<string> validated;
|
||||
for (const NewAppSecWebBotsURI &uri : injected_uris) injected.push_back(uri.getURI());
|
||||
for (const NewAppSecWebBotsURI &uri : validated_uris) validated.push_back(uri.getURI());
|
||||
out_ar(
|
||||
cereal::make_nvp("injected", injected),
|
||||
cereal::make_nvp("validated", validated)
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
NewAppSecWebAttackProtections::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec Web Attack Protections";
|
||||
parseAppsecJSONKey<string>("csrfEnabled", csrf_protection, archive_in, "inactive");
|
||||
parseAppsecJSONKey<string>("errorDisclosureEnabled", error_disclosure, archive_in, "inactive");
|
||||
parseAppsecJSONKey<string>("openRedirectEnabled", open_redirect, archive_in, "inactive");
|
||||
parseAppsecJSONKey<bool>("nonValidHttpMethods", non_valid_http_methods, archive_in, false);
|
||||
}
|
||||
|
||||
const string
|
||||
NewAppSecWebAttackProtections::getCsrfProtectionMode() const
|
||||
{
|
||||
if (key_to_practices_val.find(csrf_protection) == key_to_practices_val.end()) {
|
||||
dbgError(D_LOCAL_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 &
|
||||
NewAppSecWebAttackProtections::getErrorDisclosureMode() const
|
||||
{
|
||||
return error_disclosure;
|
||||
}
|
||||
|
||||
bool
|
||||
NewAppSecWebAttackProtections::getNonValidHttpMethods() const
|
||||
{
|
||||
return non_valid_http_methods;
|
||||
}
|
||||
|
||||
const string
|
||||
NewAppSecWebAttackProtections::getOpenRedirectMode() const
|
||||
{
|
||||
if (key_to_practices_val.find(open_redirect) == key_to_practices_val.end()) {
|
||||
dbgError(D_LOCAL_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
|
||||
NewAppSecPracticeWebAttacks::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec practice web attacks spec";
|
||||
parseAppsecJSONKey<NewAppSecWebAttackProtections>("protections", protections, archive_in);
|
||||
parseAppsecJSONKey<string>("overrideMode", mode, archive_in, "Unset");
|
||||
if (valid_modes.count(mode) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec practice override mode invalid: " << mode;
|
||||
}
|
||||
|
||||
if (getMode() == "Prevent") {
|
||||
parseAppsecJSONKey<string>("minimumConfidence", minimum_confidence, archive_in, "critical");
|
||||
if (valid_confidences.count(minimum_confidence) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec practice override minimum confidence invalid: "
|
||||
<< minimum_confidence;
|
||||
}
|
||||
} else {
|
||||
minimum_confidence = "Transparent";
|
||||
}
|
||||
parseAppsecJSONKey<int>("maxBodySizeKb", max_body_size_kb, archive_in, 1000000);
|
||||
parseAppsecJSONKey<int>("maxHeaderSizeBytes", max_header_size_bytes, archive_in, 102400);
|
||||
parseAppsecJSONKey<int>("maxObjectDepth", max_object_depth, archive_in, 40);
|
||||
parseAppsecJSONKey<int>("maxUrlSizeBytes", max_url_size_bytes, archive_in, 32768);
|
||||
}
|
||||
|
||||
int
|
||||
NewAppSecPracticeWebAttacks::getMaxBodySizeKb() const
|
||||
{
|
||||
return max_body_size_kb;
|
||||
}
|
||||
|
||||
int
|
||||
NewAppSecPracticeWebAttacks::getMaxHeaderSizeBytes() const
|
||||
{
|
||||
return max_header_size_bytes;
|
||||
}
|
||||
|
||||
int
|
||||
NewAppSecPracticeWebAttacks::getMaxObjectDepth() const
|
||||
{
|
||||
return max_object_depth;
|
||||
}
|
||||
|
||||
int
|
||||
NewAppSecPracticeWebAttacks::getMaxUrlSizeBytes() const
|
||||
{
|
||||
return max_url_size_bytes;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppSecPracticeWebAttacks::getMinimumConfidence() const
|
||||
{
|
||||
return minimum_confidence;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppSecPracticeWebAttacks::getMode(const string &default_mode) const
|
||||
{
|
||||
if (mode == "Unset" || (key_to_practices_val.find(mode) == key_to_practices_val.end())) {
|
||||
dbgError(D_LOCAL_POLICY) << "Couldn't find a value for key: " << mode << ". Returning " << default_mode;
|
||||
return default_mode;
|
||||
}
|
||||
return key_to_practices_val.at(mode);
|
||||
}
|
||||
|
||||
SnortProtectionsSection::SnortProtectionsSection(
|
||||
const std::string &_context,
|
||||
const std::string &_asset_name,
|
||||
const std::string &_asset_id,
|
||||
const std::string &_practice_name,
|
||||
const std::string &_practice_id,
|
||||
const std::string &_source_identifier,
|
||||
const std::string &_mode,
|
||||
const std::vector<std::string> &_files)
|
||||
:
|
||||
context(_context),
|
||||
asset_name(_asset_name),
|
||||
asset_id(_asset_id),
|
||||
practice_name(_practice_name),
|
||||
practice_id(_practice_id),
|
||||
source_identifier(_source_identifier),
|
||||
mode(_mode),
|
||||
files(_files)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SnortProtectionsSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
out_ar(
|
||||
cereal::make_nvp("context", context),
|
||||
cereal::make_nvp("mode", key_to_mode_val.at(mode)),
|
||||
cereal::make_nvp("files", files),
|
||||
cereal::make_nvp("assetName", asset_name),
|
||||
cereal::make_nvp("assetId", asset_id),
|
||||
cereal::make_nvp("practiceName", practice_name),
|
||||
cereal::make_nvp("practiceId", practice_id),
|
||||
cereal::make_nvp("sourceIdentifier", source_identifier)
|
||||
);
|
||||
}
|
||||
|
||||
DetectionRules::DetectionRules(
|
||||
const std::string &_type,
|
||||
const std::string &_SSM,
|
||||
const std::string &_keywords,
|
||||
const std::vector<std::string> &_context)
|
||||
:
|
||||
type(_type),
|
||||
SSM(_SSM),
|
||||
keywords(_keywords),
|
||||
context(_context)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
DetectionRules::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading Snort protections protections detection rules section";
|
||||
parseAppsecJSONKey<string>("type", type, archive_in);
|
||||
parseAppsecJSONKey<string>("SSM", SSM, archive_in);
|
||||
parseAppsecJSONKey<string>("keywords", keywords, archive_in);
|
||||
parseAppsecJSONKey<vector<string>>("context", context, archive_in);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
DetectionRules::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
out_ar(
|
||||
cereal::make_nvp("type", type),
|
||||
cereal::make_nvp("SSM", SSM),
|
||||
cereal::make_nvp("keywords", keywords),
|
||||
cereal::make_nvp("context", context)
|
||||
);
|
||||
}
|
||||
|
||||
ProtectionMetadata::ProtectionMetadata(
|
||||
bool _silent,
|
||||
const std::string &_protection_name,
|
||||
const std::string &_severity,
|
||||
const std::string &_confidence_level,
|
||||
const std::string &_performance_impact,
|
||||
const std::string &_last_update,
|
||||
const std::string &_maintrain_id,
|
||||
const std::vector<std::string> &_tags,
|
||||
const std::vector<std::string> &_cve_list)
|
||||
:
|
||||
silent(_silent),
|
||||
protection_name(_protection_name),
|
||||
severity(_severity),
|
||||
confidence_level(_confidence_level),
|
||||
performance_impact(_performance_impact),
|
||||
last_update(_last_update),
|
||||
maintrain_id(_maintrain_id),
|
||||
tags(_tags),
|
||||
cve_list(_cve_list)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ProtectionMetadata::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading Snort protections protections metadata section";
|
||||
parseAppsecJSONKey<bool>("silent", silent, archive_in);
|
||||
parseAppsecJSONKey<string>("protectionName", protection_name, archive_in);
|
||||
parseAppsecJSONKey<string>("severity", severity, archive_in);
|
||||
parseAppsecJSONKey<string>("confidenceLevel", confidence_level, archive_in);
|
||||
parseAppsecJSONKey<string>("performanceImpact", performance_impact, archive_in);
|
||||
parseAppsecJSONKey<string>("lastUpdate", last_update, archive_in);
|
||||
parseAppsecJSONKey<string>("maintrainId", maintrain_id, archive_in);
|
||||
parseAppsecJSONKey<vector<string>>("tags", tags, archive_in);
|
||||
parseAppsecJSONKey<vector<string>>("cveList", cve_list, archive_in);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ProtectionMetadata::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
out_ar(
|
||||
cereal::make_nvp("protectionName", protection_name),
|
||||
cereal::make_nvp("severity", severity),
|
||||
cereal::make_nvp("confidenceLevel", confidence_level),
|
||||
cereal::make_nvp("performanceImpact", performance_impact),
|
||||
cereal::make_nvp("lastUpdate", last_update),
|
||||
cereal::make_nvp("maintrainId", maintrain_id),
|
||||
cereal::make_nvp("tags", tags),
|
||||
cereal::make_nvp("cveList", cve_list),
|
||||
cereal::make_nvp("silent", silent)
|
||||
);
|
||||
}
|
||||
|
||||
ProtectionsProtectionsSection::ProtectionsProtectionsSection(
|
||||
const ProtectionMetadata &_protection_metadata,
|
||||
const DetectionRules &_detection_rules)
|
||||
:
|
||||
protection_metadata(_protection_metadata),
|
||||
detection_rules(_detection_rules)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ProtectionsProtectionsSection::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading Snort protections protections section";
|
||||
parseAppsecJSONKey<ProtectionMetadata>("protectionMetadata", protection_metadata, archive_in);
|
||||
parseAppsecJSONKey<DetectionRules>("detectionRules", detection_rules, archive_in);
|
||||
}
|
||||
|
||||
void
|
||||
ProtectionsProtectionsSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
out_ar(
|
||||
cereal::make_nvp("protectionMetadata", protection_metadata),
|
||||
cereal::make_nvp("detectionRules", detection_rules)
|
||||
);
|
||||
}
|
||||
|
||||
ProtectionsSection::ProtectionsSection(
|
||||
const std::vector<ProtectionsProtectionsSection> &_protections,
|
||||
const std::string &_name,
|
||||
const std::string &_modification_time)
|
||||
:
|
||||
protections(_protections),
|
||||
name(_name),
|
||||
modification_time(_modification_time)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ProtectionsSection::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading Snort protections section";
|
||||
parseAppsecJSONKey<vector<ProtectionsProtectionsSection>>("protections", protections, archive_in);
|
||||
}
|
||||
|
||||
void
|
||||
ProtectionsSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
out_ar(
|
||||
cereal::make_nvp("name", name),
|
||||
cereal::make_nvp("modificationTime", modification_time),
|
||||
cereal::make_nvp("protections", protections)
|
||||
);
|
||||
}
|
||||
|
||||
const vector<ProtectionsProtectionsSection> &
|
||||
ProtectionsSection::getProtections() const
|
||||
{
|
||||
return protections;
|
||||
}
|
||||
|
||||
void
|
||||
ProtectionsSectionWrapper::serialize(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading Snort Section";
|
||||
parseAppsecJSONKey<ProtectionsSection>("IPSSnortSigs", protections, archive_in);
|
||||
}
|
||||
|
||||
const vector<ProtectionsProtectionsSection> &
|
||||
ProtectionsSectionWrapper::getProtections() const
|
||||
{
|
||||
return protections.getProtections();
|
||||
}
|
||||
|
||||
void
|
||||
SnortSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
string version = "LocalVersion";
|
||||
out_ar(
|
||||
cereal::make_nvp("VersionId", version),
|
||||
cereal::make_nvp("SnortProtections", snort_protections),
|
||||
cereal::make_nvp("protections", protections)
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
SnortSectionWrapper::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
out_ar(
|
||||
cereal::make_nvp("IPSSnortSigs", snort)
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
NewSnortSignaturesAndOpenSchemaAPI::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec Snort Signatures practice";
|
||||
parseAppsecJSONKey<string>("overrideMode", override_mode, archive_in, "inactive");
|
||||
parseAppsecJSONKey<vector<string>>("configmap", config_map, archive_in);
|
||||
if (valid_modes.count(override_mode) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec Snort Signatures override mode invalid: " << override_mode;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NewSnortSignaturesAndOpenSchemaAPI::addFile(const string &file_name)
|
||||
{
|
||||
files.push_back(file_name);
|
||||
}
|
||||
|
||||
const string &
|
||||
NewSnortSignaturesAndOpenSchemaAPI::getOverrideMode() const
|
||||
{
|
||||
return override_mode;
|
||||
}
|
||||
|
||||
const vector<string> &
|
||||
NewSnortSignaturesAndOpenSchemaAPI::getFiles() const
|
||||
{
|
||||
return files;
|
||||
}
|
||||
|
||||
const vector<string> &
|
||||
NewSnortSignaturesAndOpenSchemaAPI::getConfigMap() const
|
||||
{
|
||||
return config_map;
|
||||
}
|
||||
|
||||
void
|
||||
IpsProtectionsRulesSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
vector<string> protections;
|
||||
out_ar(
|
||||
cereal::make_nvp("action", key_to_mode_val.at(action)),
|
||||
cereal::make_nvp("confidenceLevel", confidence_level),
|
||||
cereal::make_nvp("clientProtections", true),
|
||||
cereal::make_nvp("serverProtections", true),
|
||||
cereal::make_nvp("protectionTags", protections),
|
||||
cereal::make_nvp("protectionIds", protections),
|
||||
cereal::make_nvp("performanceImpact", key_to_performance_impact_val.at(performance_impact)),
|
||||
cereal::make_nvp("severityLevel", key_to_severity_level_val.at(severity_level)),
|
||||
cereal::make_nvp("protectionsFromYear", protections_from_year)
|
||||
);
|
||||
}
|
||||
|
||||
IpsProtectionsSection::IpsProtectionsSection(
|
||||
const string &_context,
|
||||
const string &asset_name,
|
||||
const string &_asset_id,
|
||||
const string &_practice_name,
|
||||
const string &_practice_id,
|
||||
const string &_source_identifier,
|
||||
const string &_mode,
|
||||
const vector<IpsProtectionsRulesSection> &_rules)
|
||||
:
|
||||
context(_context),
|
||||
name(asset_name),
|
||||
asset_id(_asset_id),
|
||||
practice_name(_practice_name),
|
||||
practice_id(_practice_id),
|
||||
source_identifier(_source_identifier),
|
||||
mode(_mode),
|
||||
rules(_rules)
|
||||
{
|
||||
}
|
||||
|
||||
std::string &
|
||||
IpsProtectionsSection::getMode()
|
||||
{
|
||||
return mode;
|
||||
}
|
||||
|
||||
void
|
||||
IpsProtectionsSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
out_ar(
|
||||
cereal::make_nvp("context", context),
|
||||
cereal::make_nvp("ruleName", name),
|
||||
cereal::make_nvp("assetName", name),
|
||||
cereal::make_nvp("assetId", asset_id),
|
||||
cereal::make_nvp("practiceName", practice_name),
|
||||
cereal::make_nvp("practiceId", practice_id),
|
||||
cereal::make_nvp("sourceIdentifier", source_identifier),
|
||||
cereal::make_nvp("defaultAction", key_to_mode_val.at(mode)),
|
||||
cereal::make_nvp("rules", rules)
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
IPSSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
out_ar(
|
||||
cereal::make_nvp("IpsProtections", ips)
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
IntrusionPreventionWrapper::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
out_ar(
|
||||
cereal::make_nvp("IPS", ips)
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
NewIntrusionPrevention::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec Intrusion Prevention practice";
|
||||
parseAppsecJSONKey<string>("overrideMode", override_mode, archive_in, "inactive");
|
||||
if (valid_modes.count(override_mode) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec Intrusion Prevention override mode invalid: " << override_mode;
|
||||
}
|
||||
parseAppsecJSONKey<string>("maxPerformanceImpact", max_performance_impact, archive_in, "low");
|
||||
if (performance_impacts.count(max_performance_impact) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec Intrusion Prevention max performance impact invalid: "
|
||||
<< max_performance_impact;
|
||||
}
|
||||
parseAppsecJSONKey<string>("minSeverityLevel", min_severity_level, archive_in, "low");
|
||||
if (severity_levels.count(min_severity_level) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec Intrusion Prevention min severity level invalid: "
|
||||
<< min_severity_level;
|
||||
}
|
||||
parseAppsecJSONKey<string>("highConfidenceEventAction", high_confidence_event_action, archive_in, "inactive");
|
||||
if (confidences_actions.count(high_confidence_event_action) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec Intrusion Prevention high confidence event invalid: "
|
||||
<< high_confidence_event_action;
|
||||
}
|
||||
parseAppsecJSONKey<string>("mediumConfidenceEventAction", medium_confidence_event_action, archive_in, "inactive");
|
||||
if (confidences_actions.count(medium_confidence_event_action) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec Intrusion Prevention medium confidence event invalid: "
|
||||
<< medium_confidence_event_action;
|
||||
}
|
||||
parseAppsecJSONKey<string>("lowConfidenceEventAction", low_confidence_event_action, archive_in, "inactive");
|
||||
if (confidences_actions.count(low_confidence_event_action) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec Intrusion Prevention low confidence event action invalid: "
|
||||
<< low_confidence_event_action;
|
||||
}
|
||||
parseAppsecJSONKey<int>("minCveYear", min_cve_Year, archive_in);
|
||||
}
|
||||
|
||||
vector<IpsProtectionsRulesSection>
|
||||
NewIntrusionPrevention::createIpsRules() const
|
||||
{
|
||||
vector<IpsProtectionsRulesSection> ips_rules;
|
||||
IpsProtectionsRulesSection high_rule(
|
||||
min_cve_Year,
|
||||
high_confidence_event_action,
|
||||
string("High"),
|
||||
max_performance_impact,
|
||||
string(""),
|
||||
min_severity_level
|
||||
);
|
||||
ips_rules.push_back(high_rule);
|
||||
|
||||
IpsProtectionsRulesSection med_rule(
|
||||
min_cve_Year,
|
||||
medium_confidence_event_action,
|
||||
string("Medium"),
|
||||
max_performance_impact,
|
||||
string(""),
|
||||
min_severity_level
|
||||
);
|
||||
ips_rules.push_back(med_rule);
|
||||
|
||||
IpsProtectionsRulesSection low_rule(
|
||||
min_cve_Year,
|
||||
low_confidence_event_action,
|
||||
string("Low"),
|
||||
max_performance_impact,
|
||||
string(""),
|
||||
min_severity_level
|
||||
);
|
||||
ips_rules.push_back(low_rule);
|
||||
|
||||
return ips_rules;
|
||||
}
|
||||
|
||||
const std::string &
|
||||
NewIntrusionPrevention::getMode() const
|
||||
{
|
||||
return override_mode;
|
||||
}
|
||||
|
||||
FileSecurityProtectionsSection::FileSecurityProtectionsSection(
|
||||
int _file_size_limit,
|
||||
int _archive_file_size_limit,
|
||||
bool _allow_files_without_name,
|
||||
bool _required_file_size_limit,
|
||||
bool _required_archive_extraction,
|
||||
const std::string &_context,
|
||||
const std::string &_name,
|
||||
const std::string &_asset_id,
|
||||
const std::string &_practice_name,
|
||||
const std::string &_practice_id,
|
||||
const std::string &_action,
|
||||
const std::string &_files_without_name_action,
|
||||
const std::string &_high_confidence_action,
|
||||
const std::string &_medium_confidence_action,
|
||||
const std::string &_low_confidence_action,
|
||||
const std::string &_severity_level,
|
||||
const std::string &_file_size_limit_action,
|
||||
const std::string &_multi_level_archive_action,
|
||||
const std::string &_unopened_archive_action)
|
||||
:
|
||||
file_size_limit(_file_size_limit),
|
||||
archive_file_size_limit(_archive_file_size_limit),
|
||||
allow_files_without_name(_allow_files_without_name),
|
||||
required_file_size_limit(_required_file_size_limit),
|
||||
required_archive_extraction(_required_archive_extraction),
|
||||
context(_context),
|
||||
name(_name),
|
||||
asset_id(_asset_id),
|
||||
practice_name(_practice_name),
|
||||
practice_id(_practice_id),
|
||||
action(_action),
|
||||
files_without_name_action(_files_without_name_action),
|
||||
high_confidence_action(_high_confidence_action),
|
||||
medium_confidence_action(_medium_confidence_action),
|
||||
low_confidence_action(_low_confidence_action),
|
||||
severity_level(_severity_level),
|
||||
file_size_limit_action(_file_size_limit_action),
|
||||
multi_level_archive_action(_multi_level_archive_action),
|
||||
unopened_archive_action(_unopened_archive_action)
|
||||
{}
|
||||
|
||||
void
|
||||
FileSecurityProtectionsSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
out_ar(
|
||||
cereal::make_nvp("context", context),
|
||||
cereal::make_nvp("ruleName", name),
|
||||
cereal::make_nvp("assetName", name),
|
||||
cereal::make_nvp("assetId", asset_id),
|
||||
cereal::make_nvp("practiceName", practice_name),
|
||||
cereal::make_nvp("practiceId", practice_id),
|
||||
cereal::make_nvp("action", key_to_mode_val.at(action)),
|
||||
cereal::make_nvp("filesWithoutNameAction", key_to_mode_val.at(files_without_name_action)),
|
||||
cereal::make_nvp("allowFilesWithoutName", allow_files_without_name),
|
||||
cereal::make_nvp("highConfidence", key_to_mode_val.at(high_confidence_action)),
|
||||
cereal::make_nvp("mediumConfidence", key_to_mode_val.at(medium_confidence_action)),
|
||||
cereal::make_nvp("lowConfidence", key_to_mode_val.at(low_confidence_action)),
|
||||
cereal::make_nvp("severityLevel", key_to_severity_level_val.at(severity_level)),
|
||||
cereal::make_nvp("fileSizeLimitAction", key_to_mode_val.at(file_size_limit_action)),
|
||||
cereal::make_nvp("fileSizeLimit", file_size_limit),
|
||||
cereal::make_nvp("requiredFileSizeLimit", required_file_size_limit),
|
||||
cereal::make_nvp("requiredArchiveExtraction", required_archive_extraction),
|
||||
cereal::make_nvp("archiveFileSizeLimit", archive_file_size_limit),
|
||||
cereal::make_nvp("MultiLevelArchiveAction", key_to_mode_val.at(multi_level_archive_action)),
|
||||
cereal::make_nvp("UnopenedArchiveAction", key_to_mode_val.at(unopened_archive_action))
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
FileSecuritySection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
out_ar(
|
||||
cereal::make_nvp("FileSecurityProtections", file_security)
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
FileSecurityWrapper::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
out_ar(
|
||||
cereal::make_nvp("FileSecurity", file_security)
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
NewFileSecurityArchiveInspection::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec File Security Archive Inspection practice";
|
||||
parseAppsecJSONKey<bool>("extractArchiveFiles", extract_archive_files, archive_in);
|
||||
parseAppsecJSONKey<int>("scanMaxFileSize", scan_max_file_size, archive_in, 0);
|
||||
parseAppsecJSONKey<string>("scanMaxFileSizeUnit", scan_max_file_size_unit, archive_in, "bytes");
|
||||
if (size_unit.count(scan_max_file_size_unit) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec File Security Archive Inspection scan max file size unit invalid: "
|
||||
<< scan_max_file_size_unit;
|
||||
}
|
||||
parseAppsecJSONKey<string>(
|
||||
"archivedFilesWithinArchivedFiles",
|
||||
archived_files_within_archived_files,
|
||||
archive_in,
|
||||
"inactive");
|
||||
if (confidences_actions.count(archived_files_within_archived_files) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec File Security Archive Inspection archived files within archived files invalid: "
|
||||
<< archived_files_within_archived_files;
|
||||
}
|
||||
parseAppsecJSONKey<string>(
|
||||
"archivedFilesWhereContentExtractionFailed",
|
||||
archived_files_where_content_extraction_failed,
|
||||
archive_in,
|
||||
"inactive");
|
||||
if (confidences_actions.count(archived_files_where_content_extraction_failed) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec File Security Archive Inspection archived files within archived file invalid: "
|
||||
<< archived_files_where_content_extraction_failed;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
NewFileSecurityArchiveInspection::getArchiveFileSizeLimit() const
|
||||
{
|
||||
if (unit_to_int.find(scan_max_file_size_unit) == unit_to_int.end()) {
|
||||
dbgError(D_LOCAL_POLICY)
|
||||
<< "Failed to find a value for "
|
||||
<< scan_max_file_size_unit
|
||||
<< ". Setting scan max file size unit to 0";
|
||||
return 0;
|
||||
}
|
||||
return (scan_max_file_size * unit_to_int.at(scan_max_file_size_unit));
|
||||
}
|
||||
|
||||
bool
|
||||
NewFileSecurityArchiveInspection::getrequiredArchiveExtraction() const
|
||||
{
|
||||
return extract_archive_files;
|
||||
}
|
||||
|
||||
const std::string &
|
||||
NewFileSecurityArchiveInspection::getMultiLevelArchiveAction() const
|
||||
{
|
||||
return archived_files_within_archived_files;
|
||||
}
|
||||
|
||||
const std::string &
|
||||
NewFileSecurityArchiveInspection::getUnopenedArchiveAction() const
|
||||
{
|
||||
return archived_files_where_content_extraction_failed;
|
||||
}
|
||||
|
||||
void
|
||||
NewFileSecurityLargeFileInspection::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec File Security large File Inspection practice";
|
||||
parseAppsecJSONKey<int>("fileSizeLimit", file_size_limit, archive_in);
|
||||
parseAppsecJSONKey<string>("fileSizeLimitUnit", file_size_limit_unit, archive_in, "bytes");
|
||||
if (size_unit.count(file_size_limit_unit) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec File Security large File Inspection file size limit unit invalid: "
|
||||
<< file_size_limit_unit;
|
||||
}
|
||||
parseAppsecJSONKey<string>(
|
||||
"filesExceedingSizeLimitAction",
|
||||
files_exceeding_size_limit_action,
|
||||
archive_in,
|
||||
"inactive");
|
||||
if (confidences_actions.count(files_exceeding_size_limit_action) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec File Security Archive Inspection archived files within archived files invalid: "
|
||||
<< files_exceeding_size_limit_action;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
NewFileSecurityLargeFileInspection::getFileSizeLimit() const
|
||||
{
|
||||
if (unit_to_int.find(file_size_limit_unit) == unit_to_int.end()) {
|
||||
dbgError(D_LOCAL_POLICY)
|
||||
<< "Failed to find a value for "
|
||||
<< file_size_limit_unit
|
||||
<< ". Setting file size limit unit to 0";
|
||||
return 0;
|
||||
}
|
||||
return (file_size_limit * unit_to_int.at(file_size_limit_unit));
|
||||
}
|
||||
|
||||
const std::string &
|
||||
NewFileSecurityLargeFileInspection::getFileSizeLimitAction() const
|
||||
{
|
||||
return files_exceeding_size_limit_action;
|
||||
}
|
||||
|
||||
void
|
||||
NewFileSecurity::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec File Security practice";
|
||||
parseAppsecJSONKey<string>("overrideMode", override_mode, archive_in, "inactive");
|
||||
if (valid_modes.count(override_mode) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec File Security override mode invalid: " << override_mode;
|
||||
}
|
||||
parseAppsecJSONKey<string>("minSeverityLevel", min_severity_level, archive_in, "low");
|
||||
if (severity_levels.count(min_severity_level) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec File Security min severity level invalid: " << min_severity_level;
|
||||
}
|
||||
parseAppsecJSONKey<string>("highConfidenceEventAction", high_confidence_event_action, archive_in, "inactive");
|
||||
if (confidences_actions.count(high_confidence_event_action) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec File Security high confidence event invalid: "
|
||||
<< high_confidence_event_action;
|
||||
}
|
||||
parseAppsecJSONKey<string>("mediumConfidenceEventAction", medium_confidence_event_action, archive_in, "inactive");
|
||||
if (confidences_actions.count(medium_confidence_event_action) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec File Security medium confidence event invalid: "
|
||||
<< medium_confidence_event_action;
|
||||
}
|
||||
parseAppsecJSONKey<string>("lowConfidenceEventAction", low_confidence_event_action, archive_in, "inactive");
|
||||
if (confidences_actions.count(low_confidence_event_action) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec File Security low confidence event action invalid: "
|
||||
<< low_confidence_event_action;
|
||||
}
|
||||
parseAppsecJSONKey<string>("unnamedFilesAction", unnamed_files_action, archive_in, "inactive");
|
||||
if (confidences_actions.count(unnamed_files_action) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "AppSec File Security low unnamed files action invalid: "
|
||||
<< unnamed_files_action;
|
||||
}
|
||||
parseAppsecJSONKey<bool>("threatEmulationEnabled", threat_emulation_enabled, archive_in);
|
||||
parseAppsecJSONKey<NewFileSecurityArchiveInspection>("archiveInspection", archive_inspection, archive_in);
|
||||
parseAppsecJSONKey<NewFileSecurityLargeFileInspection>("largeFileInspection", large_file_inspection, archive_in);
|
||||
}
|
||||
|
||||
const string &
|
||||
NewFileSecurity::getOverrideMode() const
|
||||
{
|
||||
return override_mode;
|
||||
}
|
||||
|
||||
const NewFileSecurityArchiveInspection &
|
||||
NewFileSecurity::getArchiveInspection() const
|
||||
{
|
||||
return archive_inspection;
|
||||
}
|
||||
|
||||
const NewFileSecurityLargeFileInspection &
|
||||
NewFileSecurity::getLargeFileInspection() const
|
||||
{
|
||||
return large_file_inspection;
|
||||
}
|
||||
|
||||
FileSecurityProtectionsSection
|
||||
NewFileSecurity::createFileSecurityProtectionsSection(
|
||||
const string &context,
|
||||
const string &asset_name,
|
||||
const string &asset_id,
|
||||
const string &practice_name,
|
||||
const string &practice_id) const
|
||||
{
|
||||
return FileSecurityProtectionsSection(
|
||||
getLargeFileInspection().getFileSizeLimit(),
|
||||
getArchiveInspection().getArchiveFileSizeLimit(),
|
||||
unnamed_files_action == "prevent" ? true : false,
|
||||
getLargeFileInspection().getFileSizeLimitAction() == "prevent" ? true : false,
|
||||
getArchiveInspection().getrequiredArchiveExtraction(),
|
||||
context,
|
||||
asset_name,
|
||||
asset_id,
|
||||
practice_name,
|
||||
practice_id,
|
||||
override_mode,
|
||||
unnamed_files_action,
|
||||
high_confidence_event_action,
|
||||
medium_confidence_event_action,
|
||||
low_confidence_event_action,
|
||||
min_severity_level,
|
||||
getLargeFileInspection().getFileSizeLimitAction(),
|
||||
getArchiveInspection().getMultiLevelArchiveAction(),
|
||||
getArchiveInspection().getUnopenedArchiveAction()
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
NewAppSecPracticeSpec::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading AppSec practice spec";
|
||||
parseAppsecJSONKey<NewSnortSignaturesAndOpenSchemaAPI>(
|
||||
"openapi-schema-validation",
|
||||
openapi_schema_validation,
|
||||
archive_in
|
||||
);
|
||||
parseAppsecJSONKey<string>("appsecClassName", appsec_class_name, archive_in);
|
||||
parseAppsecJSONKey<NewFileSecurity>("fileSecurity", file_security, archive_in);
|
||||
parseAppsecJSONKey<NewIntrusionPrevention>("intrusionPrevention", intrusion_prevention, archive_in);
|
||||
parseAppsecJSONKey<NewSnortSignaturesAndOpenSchemaAPI>("snortSignatures", snort_signatures, archive_in);
|
||||
parseAppsecJSONKey<NewAppSecPracticeWebAttacks>("webAttacks", web_attacks, archive_in);
|
||||
parseAppsecJSONKey<NewAppSecPracticeAntiBot>("antiBot", anti_bot, archive_in);
|
||||
parseAppsecJSONKey<string>("name", practice_name, archive_in);
|
||||
}
|
||||
|
||||
void
|
||||
NewAppSecPracticeSpec::setName(const string &_name)
|
||||
{
|
||||
practice_name = _name;
|
||||
}
|
||||
|
||||
const NewSnortSignaturesAndOpenSchemaAPI &
|
||||
NewAppSecPracticeSpec::getOpenSchemaValidation() const
|
||||
{
|
||||
return openapi_schema_validation;
|
||||
}
|
||||
|
||||
NewSnortSignaturesAndOpenSchemaAPI &
|
||||
NewAppSecPracticeSpec::getSnortSignatures()
|
||||
{
|
||||
return snort_signatures;
|
||||
}
|
||||
|
||||
const NewAppSecPracticeWebAttacks &
|
||||
NewAppSecPracticeSpec::getWebAttacks() const
|
||||
{
|
||||
return web_attacks;
|
||||
}
|
||||
|
||||
const NewAppSecPracticeAntiBot &
|
||||
NewAppSecPracticeSpec::getAntiBot() const
|
||||
{
|
||||
return anti_bot;
|
||||
}
|
||||
|
||||
const NewIntrusionPrevention &
|
||||
NewAppSecPracticeSpec::getIntrusionPrevention() const
|
||||
{
|
||||
return intrusion_prevention;
|
||||
}
|
||||
|
||||
const NewFileSecurity &
|
||||
NewAppSecPracticeSpec::getFileSecurity() const
|
||||
{
|
||||
return file_security;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppSecPracticeSpec::getAppSecClassName() const
|
||||
{
|
||||
return appsec_class_name;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewAppSecPracticeSpec::getName() const
|
||||
{
|
||||
return practice_name;
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
118
components/security_apps/local_policy_mgmt_gen/new_trusted_sources.cc
Executable file
118
components/security_apps/local_policy_mgmt_gen/new_trusted_sources.cc
Executable file
@@ -0,0 +1,118 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "new_trusted_sources.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
USE_DEBUG_FLAG(D_LOCAL_POLICY);
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
|
||||
static const set<string> valid_identifiers = {"headerkey", "JWTKey", "cookie", "sourceip", "x-forwarded-for"};
|
||||
|
||||
void
|
||||
NewTrustedSourcesSpec::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading trusted sources spec";
|
||||
parseAppsecJSONKey<string>("appsecClassName", appsec_class_name, archive_in);
|
||||
parseAppsecJSONKey<int>("minNumOfSources", min_num_of_sources, archive_in, 3);
|
||||
parseAppsecJSONKey<vector<string>>("sourcesIdentifiers", sources_identifiers, archive_in);
|
||||
parseAppsecJSONKey<string>("name", name, archive_in);
|
||||
}
|
||||
|
||||
void
|
||||
NewTrustedSourcesSpec::setName(const string &_name)
|
||||
{
|
||||
name = _name;
|
||||
}
|
||||
|
||||
int
|
||||
NewTrustedSourcesSpec::getMinNumOfSources() const
|
||||
{
|
||||
return min_num_of_sources;
|
||||
}
|
||||
|
||||
const vector<string> &
|
||||
NewTrustedSourcesSpec::getSourcesIdentifiers() const
|
||||
{
|
||||
return sources_identifiers;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewTrustedSourcesSpec::getAppSecClassName() const
|
||||
{
|
||||
return appsec_class_name;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewTrustedSourcesSpec::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
void
|
||||
Identifier::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading source identifiers spec";
|
||||
parseAppsecJSONKey<string>("sourceIdentifier", identifier, archive_in);
|
||||
if (valid_identifiers.count(identifier) == 0) {
|
||||
dbgWarning(D_LOCAL_POLICY) << "AppSec identifier invalid: " << identifier;
|
||||
}
|
||||
parseAppsecJSONKey<vector<string>>("value", value, archive_in);
|
||||
}
|
||||
|
||||
const string &
|
||||
Identifier::getIdentifier() const
|
||||
{
|
||||
return identifier;
|
||||
}
|
||||
|
||||
const vector<string> &
|
||||
Identifier::getValues() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
void
|
||||
NewSourcesIdentifiers::load(cereal::JSONInputArchive &archive_in)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Loading Sources Identifiers";
|
||||
parseAppsecJSONKey<string>("appsecClassName", appsec_class_name, archive_in);
|
||||
parseAppsecJSONKey<vector<Identifier>>("sourcesIdentifiers", sources_identifiers, archive_in);
|
||||
parseAppsecJSONKey<string>("name", name, archive_in);
|
||||
}
|
||||
|
||||
void
|
||||
NewSourcesIdentifiers::setName(const string &_name)
|
||||
{
|
||||
name = _name;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewSourcesIdentifiers::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
const string &
|
||||
NewSourcesIdentifiers::getAppSecClassName() const
|
||||
{
|
||||
return appsec_class_name;
|
||||
}
|
||||
|
||||
const vector<Identifier> &
|
||||
NewSourcesIdentifiers::getSourcesIdentifiers() const
|
||||
{
|
||||
return sources_identifiers;
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
1590
components/security_apps/local_policy_mgmt_gen/policy_maker_utils.cc
Executable file
1590
components/security_apps/local_policy_mgmt_gen/policy_maker_utils.cc
Executable file
File diff suppressed because it is too large
Load Diff
@@ -98,6 +98,7 @@ PracticeSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
);
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
ParametersSection::ParametersSection(
|
||||
const string &_id,
|
||||
const string &_name)
|
||||
@@ -120,6 +121,7 @@ ParametersSection::save(cereal::JSONOutputArchive &out_ar) const
|
||||
cereal::make_nvp("parameterType", type)
|
||||
);
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
RulesTriggerSection::RulesTriggerSection(
|
||||
const string &_name,
|
||||
@@ -249,6 +251,14 @@ UsersIdentifier::UsersIdentifier(const string &_source_identifier, vector<string
|
||||
identifier_values(_identifier_values)
|
||||
{}
|
||||
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
const string &
|
||||
UsersIdentifier::getIdentifier() const
|
||||
{
|
||||
return source_identifier;
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
void
|
||||
UsersIdentifier::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
@@ -270,6 +280,14 @@ UsersIdentifiersRulebase::UsersIdentifiersRulebase(
|
||||
source_identifiers(_source_identifiers)
|
||||
{}
|
||||
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
const string &
|
||||
UsersIdentifiersRulebase::getIdentifier() const
|
||||
{
|
||||
return source_identifiers[0].getIdentifier();
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
void
|
||||
UsersIdentifiersRulebase::save(cereal::JSONOutputArchive &out_ar) const
|
||||
{
|
||||
@@ -12,7 +12,6 @@ add_subdirectory(manifest_controller)
|
||||
add_subdirectory(update_communication)
|
||||
add_subdirectory(details_resolver)
|
||||
add_subdirectory(health_check)
|
||||
add_subdirectory(local_policy_mgmt_gen)
|
||||
add_subdirectory(env_details)
|
||||
|
||||
add_subdirectory(orchestration_ut)
|
||||
#add_subdirectory(orchestration_ut)
|
||||
|
||||
@@ -131,7 +131,7 @@ DetailsResolver::Impl::isReverseProxy()
|
||||
return is_reverse_proxy.unpack().front() == '1';
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
return getenv("DOCKER_RPM_ENABLED") && getenv("DOCKER_RPM_ENABLED") == string("true");
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -42,6 +42,16 @@ checkSamlPortal(const string &command_output)
|
||||
return genError("Current host does not have SAML Portal configured");
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getIDAGaia(const string &command_output)
|
||||
{
|
||||
if (command_output.find("Portal is running") != string::npos) {
|
||||
return string("ida_gaia");
|
||||
}
|
||||
|
||||
return genError("Current host does not have SAML Portal configured");
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
checkIDP(shared_ptr<istream> file_stream)
|
||||
{
|
||||
@@ -125,44 +135,54 @@ getMgmtObjName(shared_ptr<istream> file_stream)
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getGWIPAddress(shared_ptr<istream> file_stream)
|
||||
getGWHardware(const string &command_output)
|
||||
{
|
||||
return getMgmtObjAttr(file_stream, "ipaddr ");
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getGWHardware(shared_ptr<istream> file_stream)
|
||||
{
|
||||
Maybe<string> val = getMgmtObjAttr(file_stream, "appliance_type ");
|
||||
if(val.ok()) {
|
||||
if (val == string("software")) return string("Open server");
|
||||
if (val == string("Maestro Gateway")) return string("Maestro");
|
||||
if (!command_output.empty()) {
|
||||
if (command_output == "software") return string("Open server");
|
||||
if (command_output == "Maestro Gateway") return string("Maestro");
|
||||
return string(command_output);
|
||||
}
|
||||
return val;
|
||||
return genError("GW Hardware was not found");
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getGWApplicationControlBlade(shared_ptr<istream> file_stream)
|
||||
getAttr(const string &command_output, const string &error)
|
||||
{
|
||||
return getMgmtObjAttr(file_stream, "application_firewall_blade ");
|
||||
if (!command_output.empty()) {
|
||||
return string(command_output);
|
||||
}
|
||||
|
||||
return genError(error);
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getGWURLFilteringBlade(shared_ptr<istream> file_stream)
|
||||
getGWApplicationControlBlade(const string &command_output)
|
||||
{
|
||||
return getMgmtObjAttr(file_stream, "advanced_uf_blade ");
|
||||
return getAttr(command_output, "Application Control Blade was not found");
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getGWIPSecVPNBlade(shared_ptr<istream> file_stream)
|
||||
getGWURLFilteringBlade(const string &command_output)
|
||||
{
|
||||
return getMgmtObjAttr(file_stream, "VPN_1 ");
|
||||
return getAttr(command_output, "URL Filtering Blade was not found");
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getGWVersion(shared_ptr<istream> file_stream)
|
||||
getGWIPSecVPNBlade(const string &command_output)
|
||||
{
|
||||
return getMgmtObjAttr(file_stream, "svn_version_name ");
|
||||
return getAttr(command_output, "IPSec VPN Blade was not found");
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getGWIPAddress(const string &command_output)
|
||||
{
|
||||
return getAttr(command_output, "IP Address was not found");
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getGWVersion(const string &command_output)
|
||||
{
|
||||
return getAttr(command_output, "GW Version was not found");
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
@@ -191,56 +211,49 @@ getSmbObjectName(const string &command_output)
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getMgmtParentObjAttr(shared_ptr<istream> file_stream, const string &parent_obj, const string &attr)
|
||||
getSmbBlade(const string &command_output, const string &error)
|
||||
{
|
||||
string line;
|
||||
bool found_parent_obj = false;
|
||||
while (getline(*file_stream, line)) {
|
||||
size_t parent_obj_pos = line.find(parent_obj);
|
||||
if (parent_obj_pos != string::npos) found_parent_obj = true;
|
||||
if (!found_parent_obj) continue;
|
||||
if (command_output.front() == '1') return string("installed");
|
||||
if (command_output.front() == '0') return string("not-installed");
|
||||
|
||||
size_t attr_pos = line.find(attr);
|
||||
if (attr_pos == string::npos) continue;
|
||||
line = line.substr(attr_pos + attr.size());
|
||||
return line;
|
||||
}
|
||||
return genError("Parent object attribute was not found. Attr: " + attr);
|
||||
return genError(error);
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getSmbGWApplicationControlBlade(const string &command_output)
|
||||
{
|
||||
return getSmbBlade(command_output, "Application Control Blade was not found");
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getSmbGWURLFilteringBlade(const string &command_output)
|
||||
{
|
||||
return getSmbBlade(command_output, "URL Filterin Blade was not found");
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getSmbGWIPSecVPNBlade(const string &command_output)
|
||||
{
|
||||
return getSmbBlade(command_output, "IPSec VPN Blade was not found");
|
||||
}
|
||||
#endif // gaia || smb
|
||||
|
||||
#if defined(gaia)
|
||||
Maybe<string>
|
||||
getMgmtParentObjUid(shared_ptr<istream> file_stream)
|
||||
getMgmtParentObjUid(const string &command_output)
|
||||
{
|
||||
auto maybe_unparsed_uid = getMgmtParentObjAttr(file_stream, "cluster_object", "Uid ");
|
||||
if (!maybe_unparsed_uid.ok()) {
|
||||
return maybe_unparsed_uid;
|
||||
}
|
||||
const string &unparsed_uid = maybe_unparsed_uid.unpack();
|
||||
auto maybe_uid = chopHeadAndTail(unparsed_uid, "(\"{", "}\")");
|
||||
if (!maybe_uid.ok()) {
|
||||
return maybe_uid;
|
||||
}
|
||||
string uid = maybe_uid.unpack();
|
||||
transform(uid.begin(), uid.end(), uid.begin(), ::tolower);
|
||||
return uid;
|
||||
return getAttr(command_output, "Parent object uuid was not found");
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getMgmtParentObjName(shared_ptr<istream> file_stream)
|
||||
getMgmtParentObjName(const string &command_output)
|
||||
{
|
||||
auto maybe_unparsed_name = getMgmtParentObjAttr(file_stream, "cluster_object", "Name ");
|
||||
if (!maybe_unparsed_name.ok()) {
|
||||
return maybe_unparsed_name;
|
||||
}
|
||||
const string &unparsed_name = maybe_unparsed_name.unpack();
|
||||
return chopHeadAndTail(unparsed_name, "(", ")");
|
||||
return getAttr(command_output, "Parent object name was not found");
|
||||
}
|
||||
|
||||
#elif defined(smb)
|
||||
Maybe<string>
|
||||
getMgmtParentObjUid(const string &command_output)
|
||||
getSmbMgmtParentObjUid(const string &command_output)
|
||||
{
|
||||
if (!command_output.empty()) {
|
||||
return command_output;
|
||||
@@ -249,7 +262,7 @@ getMgmtParentObjUid(const string &command_output)
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getMgmtParentObjName(const string &command_output)
|
||||
getSmbMgmtParentObjName(const string &command_output)
|
||||
{
|
||||
if (!command_output.empty()) {
|
||||
return command_output;
|
||||
@@ -277,6 +290,34 @@ getOsRelease(shared_ptr<istream> file_stream)
|
||||
return genError("Os release was not found");
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
getWaapModelVersion(shared_ptr<istream> file_stream)
|
||||
{
|
||||
string line;
|
||||
static const int max_lines = 5;
|
||||
int i = 0;
|
||||
bool found_key = false;
|
||||
while (i < max_lines && getline(*file_stream, line)) {
|
||||
if (!found_key) {
|
||||
size_t index = line.find("\"model_version\":");
|
||||
if (index != string::npos) {
|
||||
found_key = true;
|
||||
}
|
||||
} else {
|
||||
size_t start = line.find_first_of('"');
|
||||
size_t end = line.find_last_of('"');
|
||||
if (start != string::npos && end != string::npos && end > start) {
|
||||
return line.substr(start + 1, end - start - 1);
|
||||
} else {
|
||||
return genError("Model version value unreadable");
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return genError("Model version was not found");
|
||||
}
|
||||
|
||||
#if defined(alpine)
|
||||
string &
|
||||
ltrim(string &s)
|
||||
|
||||
@@ -31,34 +31,96 @@
|
||||
#if defined(gaia) || defined(smb)
|
||||
SHELL_CMD_HANDLER("cpProductIntegrationMgmtObjectType", "cpprod_util CPPROD_IsMgmtMachine", getMgmtObjType)
|
||||
SHELL_CMD_HANDLER("hasSDWan", "[ -f $FWDIR/bin/sdwan_steering ] && echo '1' || echo '0'", checkHasSDWan)
|
||||
SHELL_CMD_HANDLER("canUpdateSDWanData", "cpsdwan get_data | jq -r .can_update_sdwan_data", checkCanUpdateSDWanData)
|
||||
SHELL_CMD_HANDLER(
|
||||
"canUpdateSDWanData",
|
||||
"CPSDWAN_NOLOGS=1 cpsdwan get_data -f can_update_sdwan_data | jq -r .can_update_sdwan_data",
|
||||
checkCanUpdateSDWanData
|
||||
)
|
||||
SHELL_CMD_HANDLER(
|
||||
"isSdwanRunning",
|
||||
"[ -v $(pidof cp-nano-sdwan) ] && echo 'false' || echo 'true'",
|
||||
checkIfSdwanRunning)
|
||||
SHELL_CMD_HANDLER(
|
||||
"IP Address",
|
||||
"cpsdwan get_data | jq -r .main_ip",
|
||||
getGWIPAddress
|
||||
)
|
||||
SHELL_CMD_HANDLER(
|
||||
"Version",
|
||||
"cat /etc/cp-release | grep -oE 'R[0-9]+(\\.[0-9]+)?'",
|
||||
getGWVersion
|
||||
)
|
||||
#endif //gaia || smb
|
||||
|
||||
#if defined(gaia)
|
||||
SHELL_CMD_HANDLER("hasSupportedBlade", "enabled_blades", checkHasSupportedBlade)
|
||||
SHELL_CMD_HANDLER("hasSamlPortal", "mpclient status saml-vpn", checkSamlPortal)
|
||||
SHELL_CMD_HANDLER("requiredNanoServices", "mpclient status saml-vpn", getIDAGaia)
|
||||
SHELL_CMD_HANDLER(
|
||||
"cpProductIntegrationMgmtParentObjectName",
|
||||
"cat $FWDIR/database/myself_objects.C "
|
||||
"| awk -F '[:()]' '/:cluster_object/ {found=1; next} found && /:Name/ {print $3; exit}'",
|
||||
getMgmtParentObjName
|
||||
)
|
||||
SHELL_CMD_HANDLER(
|
||||
"cpProductIntegrationMgmtParentObjectUid",
|
||||
"cat $FWDIR/database/myself_objects.C "
|
||||
"| awk -F'[{}]' '/:cluster_object/ { found=1; next } found && /:Uid/ { uid=tolower($2); print uid; exit }'",
|
||||
getMgmtParentObjUid
|
||||
)
|
||||
SHELL_CMD_HANDLER(
|
||||
"Hardware",
|
||||
"cat $FWDIR/database/myself_objects.C | awk -F '[:()]' '/:appliance_type/ {print $3}' | head -n 1",
|
||||
getGWHardware
|
||||
)
|
||||
SHELL_CMD_HANDLER(
|
||||
"Application Control",
|
||||
"cat $FWDIR/database/myself_objects.C | awk -F '[:()]' '/:application_firewall_blade/ {print $3}' | head -n 1",
|
||||
getGWApplicationControlBlade
|
||||
)
|
||||
SHELL_CMD_HANDLER(
|
||||
"URL Filtering",
|
||||
"cat $FWDIR/database/myself_objects.C | awk -F '[:()]' '/:advanced_uf_blade/ {print $3}' | head -n 1",
|
||||
getGWURLFilteringBlade
|
||||
)
|
||||
SHELL_CMD_HANDLER(
|
||||
"IPSec VPN",
|
||||
"cat $FWDIR/database/myself_objects.C | awk -F '[:()]' '/:VPN_1/ {print $3}' | head -n 1",
|
||||
getGWIPSecVPNBlade
|
||||
)
|
||||
#endif //gaia
|
||||
|
||||
#if defined(smb)
|
||||
SHELL_CMD_HANDLER(
|
||||
"cpProductIntegrationMgmtParentObjectName",
|
||||
"cpsdwan get_data | jq -r .cluster_name",
|
||||
getMgmtParentObjName
|
||||
getSmbMgmtParentObjName
|
||||
)
|
||||
SHELL_CMD_HANDLER(
|
||||
"cpProductIntegrationMgmtParentObjectUid",
|
||||
"cpsdwan get_data | jq -r .cluster_uuid",
|
||||
getMgmtParentObjUid
|
||||
getSmbMgmtParentObjUid
|
||||
)
|
||||
SHELL_CMD_HANDLER(
|
||||
"cpProductIntegrationMgmtObjectName",
|
||||
"cpprod_util FwIsLocalMgmt",
|
||||
getSmbObjectName
|
||||
)
|
||||
SHELL_CMD_HANDLER(
|
||||
"Application Control",
|
||||
"cat $FWDIR/conf/active_blades.txt | grep -o 'APCL [01]' | cut -d ' ' -f2",
|
||||
getSmbGWApplicationControlBlade
|
||||
)
|
||||
SHELL_CMD_HANDLER(
|
||||
"URL Filtering",
|
||||
"cat $FWDIR/conf/active_blades.txt | grep -o 'URLF [01]' | cut -d ' ' -f2",
|
||||
getSmbGWURLFilteringBlade
|
||||
)
|
||||
SHELL_CMD_HANDLER(
|
||||
"IPSec VPN",
|
||||
"cat $FWDIR/conf/active_blades.txt | grep -o 'IPS [01]' | cut -d ' ' -f2",
|
||||
getSmbGWIPSecVPNBlade
|
||||
)
|
||||
#endif//smb
|
||||
|
||||
SHELL_CMD_OUTPUT("kernel_version", "uname -r")
|
||||
@@ -73,17 +135,6 @@ SHELL_CMD_OUTPUT("helloWorld", "cat /tmp/agentHelloWorld 2>/dev/null")
|
||||
#if defined(gaia)
|
||||
|
||||
FILE_CONTENT_HANDLER("hasIdpConfigured", "/opt/CPSamlPortal/phpincs/spPortal/idpPolicy.xml", checkIDP)
|
||||
|
||||
FILE_CONTENT_HANDLER(
|
||||
"cpProductIntegrationMgmtParentObjectUid",
|
||||
(getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myself_objects.C",
|
||||
getMgmtParentObjUid
|
||||
)
|
||||
FILE_CONTENT_HANDLER(
|
||||
"cpProductIntegrationMgmtParentObjectName",
|
||||
(getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myself_objects.C",
|
||||
getMgmtParentObjName
|
||||
)
|
||||
FILE_CONTENT_HANDLER(
|
||||
"cpProductIntegrationMgmtObjectName",
|
||||
(getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myown.C",
|
||||
@@ -101,39 +152,10 @@ FILE_CONTENT_HANDLER(
|
||||
(getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myown.C",
|
||||
getMgmtObjUid
|
||||
)
|
||||
FILE_CONTENT_HANDLER(
|
||||
"IP Address",
|
||||
(getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myself_objects.C",
|
||||
getGWIPAddress
|
||||
)
|
||||
FILE_CONTENT_HANDLER(
|
||||
"Hardware",
|
||||
(getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myself_objects.C",
|
||||
getGWHardware
|
||||
)
|
||||
FILE_CONTENT_HANDLER(
|
||||
"Application Control",
|
||||
(getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myself_objects.C",
|
||||
getGWApplicationControlBlade
|
||||
)
|
||||
FILE_CONTENT_HANDLER(
|
||||
"URL Filtering",
|
||||
(getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myself_objects.C",
|
||||
getGWURLFilteringBlade
|
||||
)
|
||||
FILE_CONTENT_HANDLER(
|
||||
"IPSec VPN",
|
||||
(getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myself_objects.C",
|
||||
getGWIPSecVPNBlade
|
||||
)
|
||||
FILE_CONTENT_HANDLER(
|
||||
"Version",
|
||||
(getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myself_objects.C",
|
||||
getGWVersion
|
||||
)
|
||||
|
||||
#else // !(gaia || smb)
|
||||
FILE_CONTENT_HANDLER("os_release", "/etc/os-release", getOsRelease)
|
||||
#endif // gaia || smb
|
||||
|
||||
FILE_CONTENT_HANDLER("AppSecModelVersion", "/etc/cp/conf/waap/waap.data", getWaapModelVersion)
|
||||
|
||||
#endif // FILE_CONTENT_HANDLER
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "maybe_res.h"
|
||||
#include "enum_array.h"
|
||||
#include "i_shell_cmd.h"
|
||||
#include "i_orchestration_tools.h"
|
||||
#include "config.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -77,7 +78,8 @@ DetailsResolvingHanlder::Impl::getResolvedDetails() const
|
||||
const string &path = file_handler.second.first;
|
||||
FileContentHandler handler = file_handler.second.second;
|
||||
|
||||
shared_ptr<ifstream> in_file = make_shared<ifstream>(path);
|
||||
shared_ptr<ifstream> in_file =
|
||||
Singleton::Consume<I_OrchestrationTools>::by<DetailsResolvingHanlder>()->fileStreamWrapper(path);
|
||||
if (!in_file->is_open()) {
|
||||
dbgWarning(D_AGENT_DETAILS) << "Could not open file for processing. Path: " << path;
|
||||
continue;
|
||||
|
||||
@@ -18,11 +18,13 @@
|
||||
#include <map>
|
||||
|
||||
#include "i_shell_cmd.h"
|
||||
#include "i_orchestration_tools.h"
|
||||
#include "i_agent_details_reporter.h"
|
||||
|
||||
class DetailsResolvingHanlder
|
||||
:
|
||||
Singleton::Consume<I_ShellCmd>,
|
||||
Singleton::Consume<I_OrchestrationTools>,
|
||||
Singleton::Consume<I_AgentDetailsReporter>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -2,4 +2,4 @@ ADD_DEFINITIONS(-Wno-deprecated-declarations -Dalpine)
|
||||
|
||||
add_library(orchestration_downloader curl_client.cc downloader.cc http_client.cc https_client.cc)
|
||||
|
||||
add_subdirectory(downloader_ut)
|
||||
#add_subdirectory(downloader_ut)
|
||||
|
||||
@@ -278,6 +278,36 @@ HttpsCurl::HttpsCurl(const HttpsCurl &other) :
|
||||
HttpCurl(other),
|
||||
ca_path(other.ca_path) {}
|
||||
|
||||
bool
|
||||
HttpsCurl::downloadOpenAppsecPackages()
|
||||
{
|
||||
char errorstr[CURL_ERROR_SIZE];
|
||||
CURL* curl_handle = curl_easy_init();
|
||||
if (!curl_handle) return false;
|
||||
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 1);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
|
||||
|
||||
curl_easy_setopt(curl_handle, CURLOPT_URL, ("https://" + curl_url).c_str());
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writeResponseCallback);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &out_file);
|
||||
|
||||
curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, errorstr);
|
||||
|
||||
CURLcode res = curl_easy_perform(curl_handle);
|
||||
if (res == CURLE_OK) {
|
||||
dbgTrace(D_HTTP_REQUEST) << "CURL HTTP request successfully completed.";
|
||||
} else {
|
||||
dbgWarning(D_HTTP_REQUEST) << "CURL result " + string(curl_easy_strerror(res));
|
||||
curl_easy_cleanup(curl_handle);
|
||||
return false;
|
||||
}
|
||||
|
||||
curl_easy_cleanup(curl_handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
HttpsCurl::setCurlOpts(long timeout, HTTP_VERSION http_version)
|
||||
{
|
||||
@@ -299,9 +329,9 @@ HttpsCurl::setCurlOpts(long timeout, HTTP_VERSION http_version)
|
||||
curl_easy_setopt(curl_handle, CURLOPT_HTTP_VERSION, http_version);
|
||||
|
||||
//SSL options
|
||||
if (getProfileAgentSettingWithDefault<bool>(
|
||||
false,
|
||||
"agent.config.message.ignoreSslValidation") == false)
|
||||
if (
|
||||
getProfileAgentSettingWithDefault<bool>(false, "agent.config.message.ignoreSslValidation") == false
|
||||
)
|
||||
{
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 1L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_CTX_FUNCTION, ssl_ctx_verify_certificate);
|
||||
|
||||
@@ -105,6 +105,7 @@ public:
|
||||
static CURLcode ssl_ctx_verify_certificate(CURL *curl, void *ssl_ctx, void *opq);
|
||||
static int verify_certificate(int preverify_ok, X509_STORE_CTX *ctx);
|
||||
void setCurlOpts(long timeout = 60L, HTTP_VERSION http_version = HTTP_VERSION::HTTP_VERSION_1_1) override;
|
||||
bool downloadOpenAppsecPackages();
|
||||
|
||||
private:
|
||||
std::string ca_path;
|
||||
|
||||
@@ -51,7 +51,7 @@ TEST_F(DownloaderTest, downloadFileFromFog)
|
||||
calculateChecksum(Package::ChecksumTypes::SHA256, "/tmp/virtualSettings.download")
|
||||
).WillOnce(Return(string("123")));
|
||||
|
||||
EXPECT_CALL(mock_orchestration_tools, writeFile(fog_response, "/tmp/virtualSettings.download"))
|
||||
EXPECT_CALL(mock_orchestration_tools, writeFile(fog_response, "/tmp/virtualSettings.download", false))
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(mock_orchestration_tools, isNonEmptyFile("/tmp/virtualSettings.download")).WillOnce(Return(true));
|
||||
|
||||
@@ -183,7 +183,7 @@ TEST_F(DownloaderTest, downloadEmptyFileFromFog)
|
||||
|
||||
EXPECT_CALL(mock_communication, downloadAttributeFile(resourse_file)).WillOnce(Return(fog_response));
|
||||
|
||||
EXPECT_CALL(mock_orchestration_tools, writeFile(fog_response, "/tmp/manifest.download"))
|
||||
EXPECT_CALL(mock_orchestration_tools, writeFile(fog_response, "/tmp/manifest.download", false))
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(mock_orchestration_tools, isNonEmptyFile("/tmp/manifest.download")).WillOnce(Return(false));
|
||||
|
||||
@@ -342,13 +342,23 @@ TEST_F(DownloaderTest, download_virtual_policy)
|
||||
|
||||
EXPECT_CALL(mock_communication, downloadAttributeFile(resourse_file)).WillOnce(Return(fog_response));
|
||||
|
||||
EXPECT_CALL(mock_orchestration_tools, writeFile(tenant_0000_file, "/tmp/virtualPolicy_0000_profile_1234.download"))
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(
|
||||
mock_orchestration_tools,
|
||||
writeFile(
|
||||
tenant_0000_file,
|
||||
"/tmp/virtualPolicy_0000_profile_1234.download",
|
||||
false)
|
||||
).WillOnce(Return(true));
|
||||
|
||||
EXPECT_CALL(mock_orchestration_tools, fillKeyInJson(_, _, _)).WillRepeatedly(Return());
|
||||
|
||||
EXPECT_CALL(mock_orchestration_tools, writeFile(tenant_1111_file, "/tmp/virtualPolicy_1111_profile_1235.download"))
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(
|
||||
mock_orchestration_tools,
|
||||
writeFile(
|
||||
tenant_1111_file,
|
||||
"/tmp/virtualPolicy_1111_profile_1235.download",
|
||||
false)
|
||||
).WillOnce(Return(true));
|
||||
|
||||
map<pair<string, string>, string> expected_downloaded_files =
|
||||
{
|
||||
@@ -427,7 +437,8 @@ TEST_F(DownloaderTest, download_virtual_settings)
|
||||
mock_orchestration_tools,
|
||||
writeFile(
|
||||
tenant_0000_file,
|
||||
tenant_0000_path.str()
|
||||
tenant_0000_path.str(),
|
||||
false
|
||||
)
|
||||
).WillOnce(Return(true));
|
||||
|
||||
|
||||
@@ -179,14 +179,13 @@ private:
|
||||
Maybe<void>
|
||||
HTTPClient::getFile(const URLParser &url, ofstream &out_file, bool auth_required)
|
||||
{
|
||||
auto message = Singleton::Consume<I_Messaging>::by<HTTPClient>();
|
||||
auto load_env_proxy = message->loadProxy();
|
||||
auto proxy_config = Singleton::Consume<I_ProxyConfiguration>::by<HTTPClient>();
|
||||
auto load_env_proxy = proxy_config->loadProxy();
|
||||
if (!load_env_proxy.ok()) return load_env_proxy;
|
||||
|
||||
string token = "";
|
||||
if (auth_required) {
|
||||
auto message = Singleton::Consume<I_Messaging>::by<HTTPClient>();
|
||||
token = message->getAccessToken();
|
||||
token = Singleton::Consume<I_AgentDetails>::by<HTTPClient>()->getAccessToken();
|
||||
}
|
||||
|
||||
if (url.isOverSSL()) {
|
||||
@@ -214,15 +213,15 @@ Maybe<void>
|
||||
HTTPClient::curlGetFileOverHttp(const URLParser &url, ofstream &out_file, const string &token)
|
||||
{
|
||||
try {
|
||||
auto message = Singleton::Consume<I_Messaging>::by<HTTPClient>();
|
||||
auto proxy_config = Singleton::Consume<I_ProxyConfiguration>::by<HTTPClient>();
|
||||
|
||||
HttpCurl http_curl_client(
|
||||
url,
|
||||
out_file,
|
||||
token,
|
||||
message->getProxyDomain(ProxyProtocol::HTTPS),
|
||||
message->getProxyPort(ProxyProtocol::HTTPS),
|
||||
message->getProxyCredentials(ProxyProtocol::HTTPS));
|
||||
proxy_config->getProxyDomain(ProxyProtocol::HTTPS),
|
||||
proxy_config->getProxyPort(ProxyProtocol::HTTPS),
|
||||
proxy_config->getProxyCredentials(ProxyProtocol::HTTPS));
|
||||
|
||||
http_curl_client.setCurlOpts();
|
||||
bool connection_ok = http_curl_client.connect();
|
||||
@@ -247,12 +246,12 @@ Maybe<void>
|
||||
HTTPClient::getFileHttp(const URLParser &url, ofstream &out_file, const string &token)
|
||||
{
|
||||
try {
|
||||
auto message = Singleton::Consume<I_Messaging>::by<HTTPClient>();
|
||||
auto proxy_config = Singleton::Consume<I_ProxyConfiguration>::by<HTTPClient>();
|
||||
ClientConnection client_connection(
|
||||
url,
|
||||
message->getProxyDomain(ProxyProtocol::HTTP),
|
||||
message->getProxyPort(ProxyProtocol::HTTP),
|
||||
message->getProxyCredentials(ProxyProtocol::HTTP),
|
||||
proxy_config->getProxyDomain(ProxyProtocol::HTTP),
|
||||
proxy_config->getProxyPort(ProxyProtocol::HTTP),
|
||||
proxy_config->getProxyCredentials(ProxyProtocol::HTTP),
|
||||
token
|
||||
);
|
||||
auto handle_connect_res = client_connection.handleConnect();
|
||||
|
||||
@@ -18,9 +18,15 @@
|
||||
#include "maybe_res.h"
|
||||
#include "url_parser.h"
|
||||
#include "i_messaging.h"
|
||||
#include "i_agent_details.h"
|
||||
#include "i_proxy_configuration.h"
|
||||
|
||||
// LCOV_EXCL_START Reason: Depends on real download server.
|
||||
class HTTPClient : public Singleton::Consume<I_Messaging>
|
||||
class HTTPClient
|
||||
:
|
||||
public Singleton::Consume<I_Messaging>,
|
||||
public Singleton::Consume<I_AgentDetails>,
|
||||
public Singleton::Consume<I_ProxyConfiguration>
|
||||
{
|
||||
public:
|
||||
HTTPClient() = default;
|
||||
@@ -31,8 +37,8 @@ private:
|
||||
std::string loadCAChainDir();
|
||||
Maybe<void> getFileSSL(const URLParser &url, std::ofstream &out_file, const std::string &_token);
|
||||
Maybe<void> getFileHttp(const URLParser &url, std::ofstream &out_file, const std::string &_token);
|
||||
Maybe<void> curlGetFileOverSSL(const URLParser &url, std::ofstream &out_file, const std::string &_token);
|
||||
Maybe<void> curlGetFileOverHttp(const URLParser &url, std::ofstream &out_file, const std::string &_token);
|
||||
Maybe<void> curlGetFileOverSSL(const URLParser &url, std::ofstream &out_file, const std::string &_token);
|
||||
};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
|
||||
@@ -535,16 +535,16 @@ HTTPClient::getFileSSL(const URLParser &url, ofstream &out_file, const string &t
|
||||
}
|
||||
}
|
||||
boost::asio::io_service io_service;
|
||||
auto message = Singleton::Consume<I_Messaging>::by<HTTPClient>();
|
||||
auto proxy_config = Singleton::Consume<I_ProxyConfiguration>::by<HTTPClient>();
|
||||
|
||||
Client client(
|
||||
out_file,
|
||||
io_service,
|
||||
ctx,
|
||||
url,
|
||||
message->getProxyDomain(ProxyProtocol::HTTPS),
|
||||
message->getProxyPort(ProxyProtocol::HTTPS),
|
||||
message->getProxyCredentials(ProxyProtocol::HTTPS),
|
||||
proxy_config->getProxyDomain(ProxyProtocol::HTTPS),
|
||||
proxy_config->getProxyPort(ProxyProtocol::HTTPS),
|
||||
proxy_config->getProxyCredentials(ProxyProtocol::HTTPS),
|
||||
token
|
||||
);
|
||||
|
||||
@@ -581,19 +581,24 @@ HTTPClient::curlGetFileOverSSL(const URLParser &url, ofstream &out_file, const s
|
||||
);
|
||||
}
|
||||
|
||||
auto message = Singleton::Consume<I_Messaging>::by<HTTPClient>();
|
||||
auto proxy_config = Singleton::Consume<I_ProxyConfiguration>::by<HTTPClient>();
|
||||
|
||||
HttpsCurl ssl_curl_client(
|
||||
url,
|
||||
out_file,
|
||||
token,
|
||||
message->getProxyDomain(ProxyProtocol::HTTPS),
|
||||
message->getProxyPort(ProxyProtocol::HTTPS),
|
||||
message->getProxyCredentials(ProxyProtocol::HTTPS),
|
||||
proxy_config->getProxyDomain(ProxyProtocol::HTTPS),
|
||||
proxy_config->getProxyPort(ProxyProtocol::HTTPS),
|
||||
proxy_config->getProxyCredentials(ProxyProtocol::HTTPS),
|
||||
cert_file_path);
|
||||
|
||||
ssl_curl_client.setCurlOpts();
|
||||
bool connection_ok = ssl_curl_client.connect();
|
||||
bool connection_ok;
|
||||
if (url.getBaseURL().unpack() == "downloads.openappsec.io") {
|
||||
connection_ok = ssl_curl_client.downloadOpenAppsecPackages();
|
||||
} else {
|
||||
ssl_curl_client.setCurlOpts();
|
||||
connection_ok = ssl_curl_client.connect();
|
||||
}
|
||||
if (!connection_ok)
|
||||
{
|
||||
stringstream url_s;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "config.h"
|
||||
#include "log_generator.h"
|
||||
#include "health_check_manager.h"
|
||||
#include "agent_core_utilities.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ReportIS;
|
||||
@@ -145,9 +146,11 @@ private:
|
||||
initCloudVendorConfig()
|
||||
{
|
||||
static const map<string, pair<string, int>> ip_port_defaults_map = {
|
||||
{"Azure", make_pair("168.63.129.16", 8117)},
|
||||
{"Aws", make_pair("", 8117)}
|
||||
{"Azure", make_pair(getenv("DOCKER_RPM_ENABLED") ? "" : "168.63.129.16", 8117)},
|
||||
{"Aws", make_pair("", 8117)},
|
||||
{"Local", make_pair("", 8117)}
|
||||
};
|
||||
|
||||
auto cloud_vendor_maybe = getSetting<string>("reverseProxy", "cloudVendorName");
|
||||
if (cloud_vendor_maybe.ok()) {
|
||||
const string cloud_vendor = cloud_vendor_maybe.unpack();
|
||||
@@ -247,14 +250,63 @@ private:
|
||||
);
|
||||
}
|
||||
|
||||
HealthCheckStatus
|
||||
getStandaloneHealthStatus()
|
||||
{
|
||||
if (!getenv("DOCKER_RPM_ENABLED")) return HealthCheckStatus::IGNORED;
|
||||
|
||||
static const string standalone_cmd = "/usr/sbin/cpnano -s --docker-rpm; echo $?";
|
||||
dbgTrace(D_HEALTH_CHECK) << "Checking the standalone docker health status with command: " << standalone_cmd;
|
||||
|
||||
auto maybe_result = Singleton::Consume<I_ShellCmd>::by<HealthChecker>()->getExecOutput(standalone_cmd, 1000);
|
||||
if (!maybe_result.ok()) {
|
||||
dbgWarning(D_HEALTH_CHECK) << "Unable to get the standalone docker status. Returning unhealthy status.";
|
||||
return HealthCheckStatus::UNHEALTHY;
|
||||
}
|
||||
dbgTrace(D_HEALTH_CHECK) << "Got response: " << maybe_result.unpack();
|
||||
|
||||
auto response = NGEN::Strings::removeTrailingWhitespaces(maybe_result.unpack());
|
||||
|
||||
if (response.back() == '0') return HealthCheckStatus::HEALTHY;
|
||||
if (response.back() == '1') return HealthCheckStatus::UNHEALTHY;
|
||||
|
||||
return HealthCheckStatus::DEGRADED;
|
||||
}
|
||||
|
||||
bool
|
||||
nginxContainerIsRunning()
|
||||
{
|
||||
static const string nginx_container_name = "cp_nginx_gaia";
|
||||
static const string cmd_running =
|
||||
"docker ps --filter name=" + nginx_container_name + " --filter status=running";
|
||||
dbgTrace(D_HEALTH_CHECK) << "Checking if the container is running with the command: " << cmd_running;
|
||||
|
||||
auto maybe_result = Singleton::Consume<I_ShellCmd>::by<HealthChecker>()->getExecOutput(cmd_running);
|
||||
if (!maybe_result.ok()) {
|
||||
dbgWarning(D_HEALTH_CHECK)
|
||||
<< "Unable to get status of nginx container. return false and failing health check.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return (*maybe_result).find(nginx_container_name) != string::npos;
|
||||
}
|
||||
|
||||
void
|
||||
closeCurrentSocket(I_Socket::socketFd fd, I_MainLoop::RoutineID curr_routine) {
|
||||
dbgDebug(D_HEALTH_CHECK) << "Connection with client closed, client fd: " << fd;
|
||||
open_connections_counter--;
|
||||
i_socket->closeSocket(fd);
|
||||
client_sockets_routines.erase(curr_routine);
|
||||
}
|
||||
|
||||
void
|
||||
handleConnection()
|
||||
{
|
||||
if (open_connections_counter >= max_connections) {
|
||||
dbgDebug(D_HEALTH_CHECK)
|
||||
<< "Cannot serve new client, reached maximun open connections bound which is:"
|
||||
<< "Cannot serve new client, reached maximum open connections bound which is:"
|
||||
<< open_connections_counter
|
||||
<< "maximun allowed: "
|
||||
<< "maximum allowed: "
|
||||
<< max_connections;
|
||||
return;
|
||||
}
|
||||
@@ -276,21 +328,84 @@ private:
|
||||
|
||||
dbgDebug(D_HEALTH_CHECK) << "Successfully accepted client, client fd: " << new_client_socket;
|
||||
open_connections_counter++;
|
||||
auto curr_routine = i_mainloop->addFileRoutine(
|
||||
auto curr_routine = i_mainloop->addOneTimeRoutine(
|
||||
I_MainLoop::RoutineType::RealTime,
|
||||
new_client_socket,
|
||||
[this] ()
|
||||
{
|
||||
auto curr_routine_id = i_mainloop->getCurrentRoutineId().unpack();
|
||||
auto curr_client_socket = client_sockets_routines[curr_routine_id];
|
||||
auto data_recieved = i_socket->receiveData(curr_client_socket, sizeof(uint8_t), false);
|
||||
if (!data_recieved.ok()) {
|
||||
dbgDebug(D_HEALTH_CHECK) << "Connection with client closed, client fd: " << curr_client_socket;
|
||||
open_connections_counter--;
|
||||
i_socket->closeSocket(curr_client_socket);
|
||||
client_sockets_routines.erase(curr_routine_id);
|
||||
closeCurrentSocket(curr_client_socket, curr_routine_id);
|
||||
i_mainloop->stop();
|
||||
}
|
||||
|
||||
static const string success_response =
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Content-Length: 25\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"\r\n"
|
||||
"health check successful\r\n";
|
||||
static const vector<char> success_response_buffer(success_response.begin(), success_response.end());
|
||||
|
||||
static const string failure_response =
|
||||
"HTTP/1.1 500 Internal Server Error\r\n"
|
||||
"Content-Length: 21\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"\r\n"
|
||||
"health check failed\r\n";
|
||||
static const vector<char> failure_response_buffer(failure_response.begin(), failure_response.end());
|
||||
|
||||
static const string degraded_response =
|
||||
"HTTP/1.1 202 OK\r\n"
|
||||
"Content-Length: 22\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"\r\n"
|
||||
"health check partial\r\n";
|
||||
static const vector<char> degraded_response_buffer(degraded_response.begin(), degraded_response.end());
|
||||
|
||||
HealthCheckStatus standalone_status = getStandaloneHealthStatus();
|
||||
if (standalone_status != HealthCheckStatus::IGNORED) {
|
||||
if (standalone_status == HealthCheckStatus::HEALTHY) {
|
||||
dbgDebug(D_HEALTH_CHECK)
|
||||
<< "Standalone status is healthy, returning the following response: "
|
||||
<< success_response;
|
||||
i_socket->writeData(curr_client_socket, success_response_buffer);
|
||||
closeCurrentSocket(curr_client_socket, curr_routine_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (standalone_status == HealthCheckStatus::UNHEALTHY) {
|
||||
dbgDebug(D_HEALTH_CHECK)
|
||||
<< "Standalone status in unhealthy, returning the following response: "
|
||||
<< failure_response;
|
||||
i_socket->writeData(curr_client_socket, failure_response_buffer);
|
||||
closeCurrentSocket(curr_client_socket, curr_routine_id);
|
||||
return;
|
||||
}
|
||||
|
||||
dbgDebug(D_HEALTH_CHECK)
|
||||
<< "Standalone status was partially loaded, returning the following response: "
|
||||
<< degraded_response;
|
||||
i_socket->writeData(curr_client_socket, degraded_response_buffer);
|
||||
closeCurrentSocket(curr_client_socket, curr_routine_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nginxContainerIsRunning()) {
|
||||
dbgDebug(D_HEALTH_CHECK)
|
||||
<< "nginx conatiner is running, returning the following response: "
|
||||
<< success_response;
|
||||
i_socket->writeData(curr_client_socket, success_response_buffer);
|
||||
closeCurrentSocket(curr_client_socket, curr_routine_id);
|
||||
return;
|
||||
}
|
||||
|
||||
dbgDebug(D_HEALTH_CHECK)
|
||||
<< "nginx conatiner is not running, returning the following response: "
|
||||
<< failure_response;
|
||||
i_socket->writeData(curr_client_socket, failure_response_buffer);
|
||||
closeCurrentSocket(curr_client_socket, curr_routine_id);
|
||||
},
|
||||
"Health check probe connection handler",
|
||||
true
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "mock/mock_time_get.h"
|
||||
#include "mock/mock_socket_is.h"
|
||||
#include "mock/mock_mainloop.h"
|
||||
#include "mock/mock_shell_cmd.h"
|
||||
#include "health_check_manager.h"
|
||||
|
||||
#include "config.h"
|
||||
@@ -18,6 +19,22 @@ using namespace testing;
|
||||
|
||||
USE_DEBUG_FLAG(D_HEALTH_CHECK);
|
||||
|
||||
static const string response =
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Content-Length: 25\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"\r\n"
|
||||
"health check successful\r\n";
|
||||
static const vector<char> response_buffer(response.begin(), response.end());
|
||||
|
||||
static const string failure_response =
|
||||
"HTTP/1.1 500 Internal Server Error\r\n"
|
||||
"Content-Length: 21\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"\r\n"
|
||||
"health check failed\r\n";
|
||||
static const vector<char> failure_response_buffer(failure_response.begin(), failure_response.end());
|
||||
|
||||
class HealthCheckerTest : public testing::Test
|
||||
{
|
||||
public:
|
||||
@@ -47,6 +64,7 @@ public:
|
||||
NiceMock<MockLogging> mock_log;
|
||||
AgentDetails agent_details;
|
||||
StrictMock<MockSocketIS> mock_socket;
|
||||
NiceMock<MockShellCmd> mock_shell_cmd;
|
||||
I_Socket::socketFd server_socket = -1;
|
||||
Context ctx;
|
||||
ConfigComponent config;
|
||||
@@ -82,7 +100,7 @@ TEST_F(HealthCheckerTest, clientConnection)
|
||||
|
||||
EXPECT_CALL(
|
||||
mock_mainloop,
|
||||
addOneTimeRoutine(I_MainLoop::RoutineType::System, _, _, false)
|
||||
addOneTimeRoutine(I_MainLoop::RoutineType::System, _, "Health check probe listener startup", false)
|
||||
).WillOnce(DoAll(SaveArg<1>(&handle_probe_routine), Return(0)));
|
||||
|
||||
EXPECT_CALL(
|
||||
@@ -95,11 +113,19 @@ TEST_F(HealthCheckerTest, clientConnection)
|
||||
addFileRoutine(I_MainLoop::RoutineType::RealTime, _, _, _, true)
|
||||
).WillRepeatedly(DoAll(SaveArg<2>(&connection_handler_routine), Return(0)));
|
||||
|
||||
EXPECT_CALL(
|
||||
mock_mainloop,
|
||||
addOneTimeRoutine(I_MainLoop::RoutineType::RealTime, _, "Health check probe connection handler", true)
|
||||
).WillOnce(DoAll(SaveArg<1>(&connection_handler_routine), Return(0)));
|
||||
|
||||
int socket = 1;
|
||||
EXPECT_CALL(mock_socket, acceptSocket(1, false, ip)).WillOnce(Return(socket));
|
||||
EXPECT_CALL(mock_mainloop, getCurrentRoutineId()).WillRepeatedly(Return(0));
|
||||
EXPECT_CALL(mock_socket, receiveData(_, 1, false)).WillOnce(Return(vector<char>()));
|
||||
EXPECT_CALL(mock_shell_cmd, getExecOutput(_, _, _)).WillRepeatedly(Return(string("cp_nginx_gaia")));
|
||||
EXPECT_CALL(mock_socket, writeData(_, response_buffer)).WillOnce(Return(true));
|
||||
EXPECT_CALL(mock_socket, closeSocket(socket)).Times(2);
|
||||
|
||||
health_checker.init();
|
||||
handle_probe_routine();
|
||||
connection_handler_routine();
|
||||
@@ -168,7 +194,7 @@ TEST_F(HealthCheckerTest, connectionsLimit)
|
||||
connection_handler_routine();
|
||||
|
||||
EXPECT_THAT(
|
||||
capture_debug.str(), HasSubstr("Cannot serve new client, reached maximun open connections")
|
||||
capture_debug.str(), HasSubstr("Cannot serve new client, reached maximum open connections")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -194,10 +220,17 @@ TEST_F(HealthCheckerTest, disablingAfterEnabled)
|
||||
addFileRoutine(I_MainLoop::RoutineType::RealTime, _, _, _, true)
|
||||
).WillRepeatedly(DoAll(SaveArg<2>(&connection_handler_routine), Return(0)));
|
||||
|
||||
EXPECT_CALL(
|
||||
mock_mainloop,
|
||||
addOneTimeRoutine(I_MainLoop::RoutineType::RealTime, _, "Health check probe connection handler", true)
|
||||
).WillOnce(DoAll(SaveArg<1>(&connection_handler_routine), Return(0)));
|
||||
|
||||
int socket = 1;
|
||||
EXPECT_CALL(mock_socket, acceptSocket(1, false, ip)).WillOnce(Return(socket));
|
||||
EXPECT_CALL(mock_mainloop, getCurrentRoutineId()).WillRepeatedly(Return(0));
|
||||
EXPECT_CALL(mock_socket, receiveData(_, 1, false)).WillOnce(Return(vector<char>()));
|
||||
EXPECT_CALL(mock_shell_cmd, getExecOutput(_, _, _)).WillOnce(Return(string("cp_nginx_gaia")));
|
||||
EXPECT_CALL(mock_socket, writeData(_, response_buffer)).WillOnce(Return(true));
|
||||
EXPECT_CALL(mock_socket, closeSocket(socket)).Times(2);
|
||||
health_checker.init();
|
||||
handle_probe_routine();
|
||||
@@ -242,11 +275,20 @@ TEST_F(HealthCheckerTest, changePortIpConfig)
|
||||
addFileRoutine(I_MainLoop::RoutineType::RealTime, _, _, _, true)
|
||||
).WillRepeatedly(DoAll(SaveArg<2>(&connection_handler_routine), Return(0)));
|
||||
|
||||
EXPECT_CALL(
|
||||
mock_mainloop,
|
||||
addOneTimeRoutine(I_MainLoop::RoutineType::RealTime, _, "Health check probe connection handler", true)
|
||||
).WillOnce(DoAll(SaveArg<1>(&connection_handler_routine), Return(0)));
|
||||
|
||||
int socket = 1;
|
||||
int socket2 = 0;
|
||||
EXPECT_CALL(mock_socket, acceptSocket(1, false, ip)).WillOnce(Return(socket));
|
||||
EXPECT_CALL(mock_mainloop, getCurrentRoutineId()).WillRepeatedly(Return(0));
|
||||
EXPECT_CALL(mock_socket, receiveData(_, 1, false)).Times(2).WillRepeatedly(Return(vector<char>()));
|
||||
EXPECT_CALL(mock_shell_cmd, getExecOutput(_, _, _)).Times(2).WillRepeatedly(Return(string("cp_nginx_gaia")));
|
||||
EXPECT_CALL(mock_socket, writeData(_, response_buffer)).Times(2).WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(mock_socket, closeSocket(socket)).Times(2);
|
||||
EXPECT_CALL(mock_socket, closeSocket(socket2));
|
||||
health_checker.init();
|
||||
handle_probe_routine();
|
||||
connection_handler_routine();
|
||||
@@ -258,3 +300,44 @@ TEST_F(HealthCheckerTest, changePortIpConfig)
|
||||
setConfiguration(new_port, "Health Check", "Probe port");
|
||||
connection_handler_routine();
|
||||
}
|
||||
|
||||
TEST_F(HealthCheckerTest, FailedHealthCheck)
|
||||
{
|
||||
string ip = "1.2.3.4";
|
||||
setConfiguration(ip, "Health Check", "Probe IP");
|
||||
uint port = 11600;
|
||||
setConfiguration(port, "Health Check", "Probe port");
|
||||
|
||||
EXPECT_CALL(
|
||||
mock_mainloop,
|
||||
addOneTimeRoutine(I_MainLoop::RoutineType::System, _, _, false)
|
||||
).WillOnce(DoAll(SaveArg<1>(&handle_probe_routine), Return(0)));
|
||||
|
||||
EXPECT_CALL(
|
||||
mock_socket,
|
||||
genSocket(I_Socket::SocketType::TCP, false, true, _)
|
||||
).WillRepeatedly(Return(1));
|
||||
|
||||
EXPECT_CALL(
|
||||
mock_mainloop,
|
||||
addFileRoutine(I_MainLoop::RoutineType::RealTime, _, _, _, true)
|
||||
).WillRepeatedly(DoAll(SaveArg<2>(&connection_handler_routine), Return(0)));
|
||||
|
||||
EXPECT_CALL(
|
||||
mock_mainloop,
|
||||
addOneTimeRoutine(I_MainLoop::RoutineType::RealTime, _, "Health check probe connection handler", true)
|
||||
).WillOnce(DoAll(SaveArg<1>(&connection_handler_routine), Return(0)));
|
||||
|
||||
int socket = 1;
|
||||
EXPECT_CALL(mock_socket, acceptSocket(1, false, ip)).WillOnce(Return(socket));
|
||||
EXPECT_CALL(mock_mainloop, getCurrentRoutineId()).WillRepeatedly(Return(0));
|
||||
EXPECT_CALL(mock_socket, receiveData(_, 1, false)).WillOnce(Return(vector<char>()));
|
||||
EXPECT_CALL(mock_shell_cmd, getExecOutput(_, _, _)).WillOnce(Return(string("")));
|
||||
EXPECT_CALL(mock_socket, writeData(_, failure_response_buffer)).WillOnce(Return(true));
|
||||
EXPECT_CALL(mock_socket, closeSocket(socket)).Times(2);
|
||||
health_checker.init();
|
||||
handle_probe_routine();
|
||||
connection_handler_routine();
|
||||
connection_handler_routine();
|
||||
setConfiguration(false, "Health Check", "Probe enabled");
|
||||
}
|
||||
|
||||
@@ -24,8 +24,8 @@ USE_DEBUG_FLAG(D_ORCHESTRATOR);
|
||||
static inline string &
|
||||
trim(string &in)
|
||||
{
|
||||
in.erase(in.begin(), find_if(in.begin(), in.end(), not1(ptr_fun<int, int>(isspace))));
|
||||
in.erase(find_if(in.rbegin(), in.rend(), not1(ptr_fun<int, int>(isspace))).base(), in.end());
|
||||
in.erase(in.begin(), find_if(in.begin(), in.end(), [] (char c) { return !isspace(c); }));
|
||||
in.erase(find_if(in.rbegin(), in.rend(), [] (char c) { return !isspace(c); }).base(), in.end());
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,14 @@ class ApplyPolicyEvent : public Event<ApplyPolicyEvent>
|
||||
{
|
||||
public:
|
||||
ApplyPolicyEvent() {}
|
||||
ApplyPolicyEvent(const std::string &path) : local_policy_path(path) {}
|
||||
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
std::string getPolicyPath() const { return local_policy_path; }
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
private:
|
||||
std::string local_policy_path;
|
||||
};
|
||||
|
||||
class DeclarativePolicyUtils
|
||||
@@ -40,6 +48,7 @@ class DeclarativePolicyUtils
|
||||
Singleton::Consume<I_EnvDetails>,
|
||||
Singleton::Consume<I_AgentDetails>,
|
||||
Singleton::Consume<I_OrchestrationTools>,
|
||||
public Singleton::Consume<I_MainLoop>,
|
||||
Singleton::Consume<I_RestApi>,
|
||||
public Listener<ApplyPolicyEvent>
|
||||
{
|
||||
@@ -50,8 +59,7 @@ public:
|
||||
void
|
||||
doCall() override
|
||||
{
|
||||
Singleton::Consume<I_LocalPolicyMgmtGen>::by<DeclarativePolicyUtils>()->setPolicyPath(policy_path.get());
|
||||
ApplyPolicyEvent().notify();
|
||||
ApplyPolicyEvent(policy_path.get()).notify();
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -80,6 +88,7 @@ public:
|
||||
private:
|
||||
std::string getCleanChecksum(const std::string &unclean_checksum);
|
||||
|
||||
std::string local_policy_path;
|
||||
std::string curr_version;
|
||||
std::string curr_policy;
|
||||
bool should_apply_policy;
|
||||
|
||||
@@ -142,6 +142,7 @@ protected:
|
||||
std::string base64Encode(const std::string &in) const;
|
||||
std::string buildBasicAuthHeader(const std::string &username, const std::string &pass) const;
|
||||
std::string buildOAuth2Header(const std::string &token) const;
|
||||
std::string getUserEdition() const;
|
||||
|
||||
// This apps which the orchestrations requires them from Fog.
|
||||
std::vector<std::string> required_security_apps;
|
||||
@@ -266,17 +267,25 @@ private:
|
||||
S2C_PARAM(std::string, agentId);
|
||||
};
|
||||
|
||||
class PolicyVersionPatchRequest : public ClientRest
|
||||
class PolicyVersionPatchRequest
|
||||
{
|
||||
public:
|
||||
PolicyVersionPatchRequest(const std::string &_policy_version)
|
||||
PolicyVersionPatchRequest(const std::string &_policy_version, const std::string &_policy_versions)
|
||||
:
|
||||
policy_version(_policy_version)
|
||||
policy_version(_policy_version),
|
||||
policy_versions(_policy_versions)
|
||||
{
|
||||
}
|
||||
|
||||
Maybe<std::string>
|
||||
genJson() const
|
||||
{
|
||||
return "{ \"policyVersion\" :\"" + policy_version + "\", \"versions\": " + policy_versions + "}";
|
||||
}
|
||||
|
||||
private:
|
||||
C2S_LABEL_PARAM(std::string, policy_version, "policyVersion");
|
||||
std::string policy_version;
|
||||
std::string policy_versions;
|
||||
};
|
||||
|
||||
class TokenRequest : public ClientRest
|
||||
|
||||
@@ -41,7 +41,10 @@ public:
|
||||
void init() override;
|
||||
Maybe<void> getUpdate(CheckUpdateRequest &request) override;
|
||||
Maybe<std::string> downloadAttributeFile(const GetResourceFile &resourse_file) override;
|
||||
Maybe<void> sendPolicyVersion(const std::string &policy_version) const override;
|
||||
Maybe<void> sendPolicyVersion(
|
||||
const std::string &policy_version,
|
||||
const std::string &policy_versions
|
||||
) const override;
|
||||
|
||||
private:
|
||||
DeclarativePolicyUtils declarative_policy_utils;
|
||||
|
||||
@@ -54,6 +54,7 @@ public:
|
||||
last_update = i_orch_status->getUpdateTime();
|
||||
last_update_status = i_orch_status->getUpdateStatus();
|
||||
policy_version = i_orch_status->getPolicyVersion();
|
||||
waap_model_version = i_orch_status->getWaapModelVersion();
|
||||
last_policy_update = i_orch_status->getLastPolicyUpdate();
|
||||
last_manifest_update = i_orch_status->getLastManifestUpdate();
|
||||
last_settings_update = i_orch_status->getLastSettingsUpdate();
|
||||
@@ -72,6 +73,7 @@ private:
|
||||
S2C_LABEL_PARAM(std::string, last_update, "Last update");
|
||||
S2C_LABEL_PARAM(std::string, last_update_status, "Last update status");
|
||||
S2C_LABEL_PARAM(std::string, policy_version, "Policy version");
|
||||
S2C_LABEL_PARAM(std::string, waap_model_version, "AI model version");
|
||||
S2C_LABEL_PARAM(std::string, last_policy_update, "Last policy update");
|
||||
S2C_LABEL_PARAM(std::string, last_manifest_update, "Last manifest update");
|
||||
S2C_LABEL_PARAM(std::string, last_settings_update, "Last settings update");
|
||||
|
||||
@@ -46,7 +46,10 @@ public:
|
||||
void init() override;
|
||||
Maybe<void> getUpdate(CheckUpdateRequest &request) override;
|
||||
Maybe<std::string> downloadAttributeFile(const GetResourceFile &resourse_file) override;
|
||||
Maybe<void> sendPolicyVersion(const std::string &policy_version) const override;
|
||||
Maybe<void> sendPolicyVersion(
|
||||
const std::string &policy_version,
|
||||
const std::string &policy_versions
|
||||
) const override;
|
||||
|
||||
private:
|
||||
Maybe<std::string> getNewVersion();
|
||||
|
||||
@@ -33,7 +33,10 @@ public:
|
||||
|
||||
Maybe<std::string> downloadAttributeFile(const GetResourceFile &resourse_file) override;
|
||||
void setAddressExtenesion(const std::string &extension) override;
|
||||
Maybe<void> sendPolicyVersion(const std::string &policy_version) const override;
|
||||
Maybe<void> sendPolicyVersion(
|
||||
const std::string &policy_version,
|
||||
const std::string &policy_versions
|
||||
) const override;
|
||||
|
||||
private:
|
||||
std::string getChecksum(const std::string &file_path);
|
||||
|
||||
@@ -45,6 +45,7 @@ public:
|
||||
MOCK_CONST_METHOD0(getUpdateTime, const std::string&());
|
||||
MOCK_CONST_METHOD0(getLastManifestUpdate, const std::string&());
|
||||
MOCK_CONST_METHOD0(getPolicyVersion, const std::string&());
|
||||
MOCK_CONST_METHOD0(getWaapModelVersion, const std::string&());
|
||||
MOCK_CONST_METHOD0(getLastPolicyUpdate, const std::string&());
|
||||
MOCK_CONST_METHOD0(getLastSettingsUpdate, const std::string&());
|
||||
MOCK_CONST_METHOD0(getUpgradeMode, const std::string&());
|
||||
|
||||
@@ -55,5 +55,11 @@ public:
|
||||
MOCK_CONST_METHOD1(executeCmd, bool(const std::string &));
|
||||
MOCK_CONST_METHOD1(base64Encode, std::string(const std::string &));
|
||||
MOCK_CONST_METHOD1(base64Decode, std::string(const std::string &));
|
||||
MOCK_CONST_METHOD2(removeDirectory, bool(const std::string &, bool delete_content));
|
||||
MOCK_CONST_METHOD1(loadTenantsFromDir, void(const std::string &));
|
||||
MOCK_CONST_METHOD3(
|
||||
deleteVirtualTenantProfileFiles,
|
||||
void(const std::string &tenant_id, const std::string &profile_id, const std::string &conf_path)
|
||||
);
|
||||
};
|
||||
#endif // __MOCK_ORCHESTRATION_TOOLS_H__
|
||||
|
||||
@@ -38,14 +38,16 @@ public:
|
||||
|
||||
MOCK_CONST_METHOD0(getUpdatePolicyVersion, const std::string &());
|
||||
|
||||
MOCK_CONST_METHOD0(getPolicyVersions, const std::string &());
|
||||
|
||||
MOCK_METHOD6(
|
||||
updateServiceConfiguration,
|
||||
bool(
|
||||
Maybe<void>(
|
||||
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 &child_tenant_id,
|
||||
const std::string &child_profile_id,
|
||||
const bool last_iteration
|
||||
)
|
||||
);
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
MOCK_METHOD1(getUpdate, Maybe<void>(CheckUpdateRequest &));
|
||||
MOCK_METHOD1(downloadAttributeFile, Maybe<std::string>(const GetResourceFile &));
|
||||
MOCK_METHOD1(setAddressExtenesion, void(const std::string &));
|
||||
MOCK_CONST_METHOD1(sendPolicyVersion, Maybe<void>(const std::string &));
|
||||
MOCK_CONST_METHOD2(sendPolicyVersion, Maybe<void>(const std::string &, const std::string &));
|
||||
};
|
||||
|
||||
#endif // __MOCK_UPDATE_COMMUNICATION_H__
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
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 k8s_policy_utils.cc namespace_data.cc)
|
||||
@@ -1,106 +0,0 @@
|
||||
// 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 __K8S_POLICY_COMMON_H__
|
||||
#define __K8S_POLICY_COMMON_H__
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <cereal/archives/json.hpp>
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "rest.h"
|
||||
|
||||
USE_DEBUG_FLAG(D_LOCAL_POLICY);
|
||||
// LCOV_EXCL_START Reason: no test exist
|
||||
enum class PracticeType { WebApplication, WebAPI };
|
||||
enum class TriggerType { Log, WebUserResponse };
|
||||
enum class MatchType { Condition, Operator };
|
||||
|
||||
static const std::unordered_map<std::string, MatchType> string_to_match_type = {
|
||||
{ "condition", MatchType::Condition },
|
||||
{ "operator", MatchType::Operator }
|
||||
};
|
||||
|
||||
static const std::unordered_map<std::string, PracticeType> string_to_practice_type = {
|
||||
{ "WebApplication", PracticeType::WebApplication },
|
||||
{ "WebAPI", PracticeType::WebAPI }
|
||||
};
|
||||
|
||||
static const std::unordered_map<std::string, TriggerType> string_to_trigger_type = {
|
||||
{ "log", TriggerType::Log },
|
||||
{ "WebUserResponse", TriggerType::WebUserResponse }
|
||||
};
|
||||
|
||||
static const std::unordered_map<std::string, std::string> key_to_practices_val = {
|
||||
{ "prevent-learn", "Prevent"},
|
||||
{ "detect-learn", "Detect"},
|
||||
{ "prevent", "Prevent"},
|
||||
{ "detect", "Detect"},
|
||||
{ "inactive", "Inactive"}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
parseAppsecJSONKey(
|
||||
const std::string &key_name,
|
||||
T &value,
|
||||
cereal::JSONInputArchive &archive_in,
|
||||
const T &default_value = T())
|
||||
{
|
||||
try {
|
||||
archive_in(cereal::make_nvp(key_name, value));
|
||||
} catch (const cereal::Exception &e) {
|
||||
archive_in.setNextName(nullptr);
|
||||
value = default_value;
|
||||
dbgDebug(D_LOCAL_POLICY)
|
||||
<< "Could not parse the required key. Key: "
|
||||
<< key_name
|
||||
<< ", Error: "
|
||||
<< e.what();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class AppsecSpecParser : public ClientRest
|
||||
{
|
||||
public:
|
||||
AppsecSpecParser() = default;
|
||||
AppsecSpecParser(const T &_spec) : spec(_spec) {}
|
||||
|
||||
bool
|
||||
loadJson(const std::string &json)
|
||||
{
|
||||
std::string modified_json = json;
|
||||
modified_json.pop_back();
|
||||
std::stringstream ss;
|
||||
ss.str(modified_json);
|
||||
try {
|
||||
cereal::JSONInputArchive in_ar(ss);
|
||||
in_ar(cereal::make_nvp("spec", spec));
|
||||
} catch (cereal::Exception &e) {
|
||||
dbgError(D_LOCAL_POLICY) << "Failed to load spec JSON. Error: " << e.what();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const T & getSpec() const { return spec; }
|
||||
|
||||
private:
|
||||
T spec;
|
||||
};
|
||||
// LCOV_EXCL_STOP
|
||||
#endif // __K8S_POLICY_COMMON_H__
|
||||
@@ -1,157 +0,0 @@
|
||||
// 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 "i_orchestration_tools.h"
|
||||
#include "i_shell_cmd.h"
|
||||
#include "i_messaging.h"
|
||||
#include "appsec_practice_section.h"
|
||||
#include "ingress_data.h"
|
||||
#include "settings_section.h"
|
||||
#include "triggers_section.h"
|
||||
#include "local_policy_common.h"
|
||||
#include "exceptions_section.h"
|
||||
#include "rules_config_section.h"
|
||||
#include "trusted_sources_section.h"
|
||||
|
||||
enum class AnnotationTypes {
|
||||
PRACTICE,
|
||||
TRIGGER,
|
||||
EXCEPTION,
|
||||
WEB_USER_RES,
|
||||
SOURCE_IDENTIFIERS,
|
||||
TRUSTED_SOURCES,
|
||||
COUNT
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
class PolicyMakerUtils
|
||||
:
|
||||
Singleton::Consume<I_Environment>,
|
||||
Singleton::Consume<I_OrchestrationTools>,
|
||||
Singleton::Consume<I_Messaging>,
|
||||
Singleton::Consume<I_ShellCmd>
|
||||
{
|
||||
public:
|
||||
std::string proccesSingleAppsecPolicy(
|
||||
const std::string &policy_path,
|
||||
const std::string &policy_version,
|
||||
const std::string &local_appsec_policy_path
|
||||
);
|
||||
|
||||
std::string proccesMultipleAppsecPolicies(
|
||||
const std::map<std::string, AppsecLinuxPolicy> &appsec_policies,
|
||||
const std::string &policy_version,
|
||||
const std::string &local_appsec_policy_path
|
||||
);
|
||||
|
||||
private:
|
||||
std::string getPolicyName(const std::string &policy_path);
|
||||
|
||||
Maybe<AppsecLinuxPolicy> openPolicyAsJson(const std::string &policy_path);
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
void createAgentPolicyFromAppsecPolicy(const std::string &policy_name, const AppsecLinuxPolicy &appsec_policy);
|
||||
|
||||
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;
|
||||
std::map<std::string, UsersIdentifiersRulebase> users_identifiers;
|
||||
std::map<std::string, AppSecTrustedSources> trusted_sources;
|
||||
};
|
||||
|
||||
#endif // __POLICY_MAKER_UTILS_H__
|
||||
@@ -1,343 +0,0 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "k8s_policy_utils.h"
|
||||
#include "namespace_data.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
USE_DEBUG_FLAG(D_NGINX_POLICY);
|
||||
|
||||
string
|
||||
convertAnnotationKeysTostring(const AnnotationKeys &key)
|
||||
{
|
||||
switch (key) {
|
||||
case AnnotationKeys::PolicyKey:
|
||||
return "policy";
|
||||
case AnnotationKeys::OpenAppsecIo:
|
||||
return "openappsec.io/";
|
||||
case AnnotationKeys::SyslogAddressKey:
|
||||
return "syslog";
|
||||
case AnnotationKeys::ModeKey:
|
||||
return "mode";
|
||||
default:
|
||||
return "Irrelevant key";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
K8sPolicyUtils::init()
|
||||
{
|
||||
env_details = Singleton::Consume<I_EnvDetails>::by<K8sPolicyUtils>();
|
||||
env_type = env_details->getEnvType();
|
||||
if (env_type == EnvType::K8S) {
|
||||
token = env_details->getToken();
|
||||
messaging = Singleton::Consume<I_Messaging>::by<K8sPolicyUtils>();
|
||||
conn_flags.setFlag(MessageConnConfig::SECURE_CONN);
|
||||
conn_flags.setFlag(MessageConnConfig::IGNORE_SSL_VALIDATION);
|
||||
}
|
||||
}
|
||||
|
||||
map<AnnotationKeys, string>
|
||||
K8sPolicyUtils::parseIngressAnnotations(const map<string, string> &annotations) const
|
||||
{
|
||||
map<AnnotationKeys, string> annotations_values;
|
||||
for (const pair<string, string> &annotation : annotations) {
|
||||
string annotation_key = annotation.first;
|
||||
string annotation_val = annotation.second;
|
||||
if (annotation_key.find(convertAnnotationKeysTostring(AnnotationKeys::OpenAppsecIo)) != string::npos) {
|
||||
if (annotation_key.find(convertAnnotationKeysTostring(AnnotationKeys::PolicyKey)) != string::npos) {
|
||||
annotations_values[AnnotationKeys::PolicyKey] = annotation_val;
|
||||
} else if (
|
||||
annotation_key.find(convertAnnotationKeysTostring(AnnotationKeys::SyslogAddressKey)) != string::npos
|
||||
) {
|
||||
bool has_port = annotation_val.find(":");
|
||||
annotations_values[AnnotationKeys::SyslogAddressKey] =
|
||||
annotation_val.substr(0, annotation_val.find(":"));
|
||||
annotations_values[AnnotationKeys::SyslogPortKey] =
|
||||
has_port ? annotation_val.substr(annotation_val.find(":") + 1) : "";
|
||||
} else if (annotation_key.find(convertAnnotationKeysTostring(AnnotationKeys::ModeKey)) != string::npos) {
|
||||
annotations_values[AnnotationKeys::ModeKey] = annotation_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
return annotations_values;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Maybe<T, string>
|
||||
K8sPolicyUtils::getObjectFromCluster(const string &path) const
|
||||
{
|
||||
T object;
|
||||
bool res = messaging->sendObject(
|
||||
object,
|
||||
I_Messaging::Method::GET,
|
||||
"kubernetes.default.svc",
|
||||
443,
|
||||
conn_flags,
|
||||
path,
|
||||
"Authorization: Bearer " + token + "\nConnection: close"
|
||||
);
|
||||
|
||||
if (res) return object;
|
||||
|
||||
return genError(string("Was not able to get object form k8s cluser in path: " + path));
|
||||
}
|
||||
|
||||
map<AnnotationTypes, unordered_set<string>>
|
||||
K8sPolicyUtils::extractElementsNames(const vector<ParsedRule> &specific_rules, const ParsedRule &default_rule) const
|
||||
{
|
||||
map<AnnotationTypes, unordered_set<string>> policy_elements_names;
|
||||
for (const ParsedRule &specific_rule : specific_rules) {
|
||||
policy_elements_names[AnnotationTypes::EXCEPTION].insert(
|
||||
specific_rule.getExceptions().begin(),
|
||||
specific_rule.getExceptions().end()
|
||||
);
|
||||
policy_elements_names[AnnotationTypes::PRACTICE].insert(
|
||||
specific_rule.getPractices().begin(),
|
||||
specific_rule.getPractices().end()
|
||||
);
|
||||
policy_elements_names[AnnotationTypes::TRIGGER].insert(
|
||||
specific_rule.getLogTriggers().begin(),
|
||||
specific_rule.getLogTriggers().end()
|
||||
);
|
||||
policy_elements_names[AnnotationTypes::WEB_USER_RES].insert(specific_rule.getCustomResponse());
|
||||
policy_elements_names[AnnotationTypes::SOURCE_IDENTIFIERS].insert(specific_rule.getSourceIdentifiers());
|
||||
policy_elements_names[AnnotationTypes::TRUSTED_SOURCES].insert(specific_rule.getTrustedSources());
|
||||
}
|
||||
policy_elements_names[AnnotationTypes::EXCEPTION].insert(
|
||||
default_rule.getExceptions().begin(),
|
||||
default_rule.getExceptions().end()
|
||||
);
|
||||
policy_elements_names[AnnotationTypes::PRACTICE].insert(
|
||||
default_rule.getPractices().begin(),
|
||||
default_rule.getPractices().end()
|
||||
);
|
||||
policy_elements_names[AnnotationTypes::TRIGGER].insert(
|
||||
default_rule.getLogTriggers().begin(),
|
||||
default_rule.getLogTriggers().end()
|
||||
);
|
||||
policy_elements_names[AnnotationTypes::WEB_USER_RES].insert(default_rule.getCustomResponse());
|
||||
policy_elements_names[AnnotationTypes::SOURCE_IDENTIFIERS].insert(default_rule.getSourceIdentifiers());
|
||||
policy_elements_names[AnnotationTypes::TRUSTED_SOURCES].insert(default_rule.getTrustedSources());
|
||||
|
||||
return policy_elements_names;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
vector<T>
|
||||
K8sPolicyUtils::extractElementsFromCluster(
|
||||
const string &crd_plural,
|
||||
const unordered_set<string> &elements_names) const
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Retrieve AppSec elements. type: " << crd_plural;
|
||||
vector<T> elements;
|
||||
for (const string &element_name : elements_names) {
|
||||
dbgTrace(D_LOCAL_POLICY) << "AppSec element name: " << element_name;
|
||||
auto maybe_appsec_element = getObjectFromCluster<AppsecSpecParser<T>>(
|
||||
"/apis/openappsec.io/v1beta1/" + crd_plural + "/" + element_name
|
||||
);
|
||||
|
||||
if (!maybe_appsec_element.ok()) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "Failed to retrieve AppSec element. type: "
|
||||
<< crd_plural
|
||||
<< ", name: "
|
||||
<< element_name
|
||||
<< ". Error: "
|
||||
<< maybe_appsec_element.getErr();
|
||||
continue;
|
||||
}
|
||||
|
||||
AppsecSpecParser<T> appsec_element = maybe_appsec_element.unpack();
|
||||
if (appsec_element.getSpec().getName() == "") {
|
||||
appsec_element.setName(element_name);
|
||||
}
|
||||
elements.push_back(appsec_element.getSpec());
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
Maybe<AppsecLinuxPolicy>
|
||||
K8sPolicyUtils::createAppsecPolicyK8s(const string &policy_name, const string &ingress_mode) const
|
||||
{
|
||||
auto maybe_appsec_policy_spec = getObjectFromCluster<AppsecSpecParser<AppsecPolicySpec>>(
|
||||
"/apis/openappsec.io/v1beta1/policies/" + policy_name
|
||||
);
|
||||
if (!maybe_appsec_policy_spec.ok()) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "Failed to retrieve AppSec policy. Error: "
|
||||
<< maybe_appsec_policy_spec.getErr();
|
||||
return genError("Failed to retrieve AppSec policy. Error: " + maybe_appsec_policy_spec.getErr());
|
||||
}
|
||||
AppsecSpecParser<AppsecPolicySpec> appsec_policy_spec = maybe_appsec_policy_spec.unpack();
|
||||
ParsedRule default_rule = appsec_policy_spec.getSpec().getDefaultRule();
|
||||
vector<ParsedRule> specific_rules = appsec_policy_spec.getSpec().getSpecificRules();
|
||||
|
||||
if (!ingress_mode.empty() && default_rule.getMode().empty()) {
|
||||
default_rule.setMode(ingress_mode);
|
||||
}
|
||||
|
||||
map<AnnotationTypes, unordered_set<string>> policy_elements_names = extractElementsNames(
|
||||
specific_rules,
|
||||
default_rule
|
||||
);
|
||||
|
||||
|
||||
vector<AppSecPracticeSpec> practices = extractElementsFromCluster<AppSecPracticeSpec>(
|
||||
"practices",
|
||||
policy_elements_names[AnnotationTypes::PRACTICE]
|
||||
);
|
||||
|
||||
vector<AppsecTriggerSpec> log_triggers = extractElementsFromCluster<AppsecTriggerSpec>(
|
||||
"logtriggers",
|
||||
policy_elements_names[AnnotationTypes::TRIGGER]
|
||||
);
|
||||
|
||||
vector<AppSecCustomResponseSpec> web_user_responses = extractElementsFromCluster<AppSecCustomResponseSpec>(
|
||||
"customresponses",
|
||||
policy_elements_names[AnnotationTypes::WEB_USER_RES]
|
||||
);
|
||||
|
||||
vector<AppsecExceptionSpec> exceptions = extractElementsFromCluster<AppsecExceptionSpec>(
|
||||
"exceptions",
|
||||
policy_elements_names[AnnotationTypes::EXCEPTION]
|
||||
);
|
||||
|
||||
vector<SourceIdentifierSpecWrapper> source_identifiers = extractElementsFromCluster<SourceIdentifierSpecWrapper>(
|
||||
"sourcesidentifiers",
|
||||
policy_elements_names[AnnotationTypes::SOURCE_IDENTIFIERS]
|
||||
);
|
||||
|
||||
vector<TrustedSourcesSpec> trusted_sources = extractElementsFromCluster<TrustedSourcesSpec>(
|
||||
"trustedsources",
|
||||
policy_elements_names[AnnotationTypes::TRUSTED_SOURCES]
|
||||
);
|
||||
|
||||
AppsecLinuxPolicy appsec_policy = AppsecLinuxPolicy(
|
||||
appsec_policy_spec.getSpec(),
|
||||
practices,
|
||||
log_triggers,
|
||||
web_user_responses,
|
||||
exceptions,
|
||||
trusted_sources,
|
||||
source_identifiers
|
||||
);
|
||||
return appsec_policy;
|
||||
}
|
||||
|
||||
map<string, AppsecLinuxPolicy>
|
||||
K8sPolicyUtils::createAppsecPoliciesFromIngresses()
|
||||
{
|
||||
dbgFlow(D_LOCAL_POLICY) << "Getting all policy object from Ingresses";
|
||||
map<string, AppsecLinuxPolicy> policies;
|
||||
auto maybe_ingress = getObjectFromCluster<IngressData>("/apis/networking.k8s.io/v1/ingresses");
|
||||
|
||||
if (!maybe_ingress.ok()) {
|
||||
// TBD: Error handling : INXT-31444
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "Failed to retrieve K8S Ingress configurations. Error: "
|
||||
<< maybe_ingress.getErr();
|
||||
return policies;
|
||||
}
|
||||
|
||||
IngressData ingress = maybe_ingress.unpack();
|
||||
for (const SingleIngressData &item : ingress.getItems()) {
|
||||
map<AnnotationKeys, string> annotations_values = parseIngressAnnotations(
|
||||
item.getMetadata().getAnnotations()
|
||||
);
|
||||
|
||||
if (annotations_values[AnnotationKeys::PolicyKey].empty()) {
|
||||
dbgInfo(D_LOCAL_POLICY) << "No policy was found in this ingress";
|
||||
continue;
|
||||
}
|
||||
|
||||
Maybe<AppsecLinuxPolicy> maybe_appsec_policy = createAppsecPolicyK8s(
|
||||
annotations_values[AnnotationKeys::PolicyKey],
|
||||
annotations_values[AnnotationKeys::ModeKey]
|
||||
);
|
||||
if (!maybe_appsec_policy.ok()) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "Failed to create appsec policy. Error: "
|
||||
<< maybe_appsec_policy.getErr();
|
||||
continue;
|
||||
}
|
||||
|
||||
AppsecLinuxPolicy appsec_policy = maybe_appsec_policy.unpack();
|
||||
for (const IngressDefinedRule &rule : item.getSpec().getRules()) {
|
||||
string url = rule.getHost();
|
||||
for (const IngressRulePath &uri : rule.getPathsWrapper().getRulePaths()) {
|
||||
if (!appsec_policy.getAppsecPolicySpec().isAssetHostExist(url + uri.getPath())) {
|
||||
dbgTrace(D_LOCAL_POLICY)
|
||||
<< "Inserting Host data to the specific asset set:"
|
||||
<< "URL: '"
|
||||
<< url
|
||||
<< "' uri: '"
|
||||
<< uri.getPath()
|
||||
<< "'";
|
||||
ParsedRule ingress_rule = ParsedRule(url + uri.getPath());
|
||||
appsec_policy.addSpecificRule(ingress_rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
policies[annotations_values[AnnotationKeys::PolicyKey]] = appsec_policy;
|
||||
}
|
||||
return policies;
|
||||
}
|
||||
|
||||
bool
|
||||
isPlaygroundEnv()
|
||||
{
|
||||
const char *env_string = getenv("PLAYGROUND");
|
||||
|
||||
if (env_string == nullptr) return false;
|
||||
string env_value = env_string;
|
||||
transform(env_value.begin(), env_value.end(), env_value.begin(), ::tolower);
|
||||
|
||||
return env_value == "true";
|
||||
}
|
||||
|
||||
bool
|
||||
K8sPolicyUtils::getClusterId() const
|
||||
{
|
||||
string playground_uid = isPlaygroundEnv() ? "playground-" : "";
|
||||
|
||||
dbgTrace(D_LOCAL_POLICY) << "Getting cluster UID";
|
||||
auto maybe_namespaces_data = getObjectFromCluster<NamespaceData>("/api/v1/namespaces/");
|
||||
|
||||
if (!maybe_namespaces_data.ok()) {
|
||||
dbgWarning(D_LOCAL_POLICY)
|
||||
<< "Failed to retrieve K8S namespace data. Error: "
|
||||
<< maybe_namespaces_data.getErr();
|
||||
return false;
|
||||
}
|
||||
|
||||
NamespaceData namespaces_data = maybe_namespaces_data.unpack();
|
||||
|
||||
Maybe<string> maybe_ns_uid = namespaces_data.getNamespaceUidByName("kube-system");
|
||||
if (!maybe_ns_uid.ok()) {
|
||||
dbgWarning(D_LOCAL_POLICY) << maybe_ns_uid.getErr();
|
||||
return false;
|
||||
}
|
||||
string uid = playground_uid + maybe_ns_uid.unpack();
|
||||
dbgTrace(D_LOCAL_POLICY) << "Found k8s cluster UID: " << uid;
|
||||
I_Environment *env = Singleton::Consume<I_Environment>::by<K8sPolicyUtils>();
|
||||
env->getConfigurationContext().registerValue<string>(
|
||||
"k8sClusterId",
|
||||
uid,
|
||||
EnvKeyAttr::LogSection::SOURCE
|
||||
);
|
||||
I_AgentDetails *i_agent_details = Singleton::Consume<I_AgentDetails>::by<K8sPolicyUtils>();
|
||||
i_agent_details->setClusterId(uid);
|
||||
return true;
|
||||
}
|
||||
@@ -1,812 +0,0 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "policy_maker_utils.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
USE_DEBUG_FLAG(D_NGINX_POLICY);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
string
|
||||
PolicyMakerUtils::getPolicyName(const string &policy_path)
|
||||
{
|
||||
string policy_name;
|
||||
if (policy_path.find_last_of("/") != string::npos) {
|
||||
policy_name = policy_path.substr(policy_path.find_last_of("/") + 1);
|
||||
} else {
|
||||
policy_name = policy_path;
|
||||
}
|
||||
if (policy_name.find(".") != string::npos) {
|
||||
return policy_name.substr(0, policy_name.find("."));
|
||||
}
|
||||
return policy_name;
|
||||
}
|
||||
|
||||
Maybe<AppsecLinuxPolicy>
|
||||
PolicyMakerUtils::openPolicyAsJson(const string &policy_path)
|
||||
{
|
||||
auto maybe_policy_as_json = Singleton::Consume<I_ShellCmd>::by<PolicyMakerUtils>()->getExecOutput(
|
||||
getFilesystemPathConfig() + "/bin/yq " + policy_path + " -o json"
|
||||
);
|
||||
|
||||
if (!maybe_policy_as_json.ok()) {
|
||||
dbgDebug(D_NGINX_POLICY) << "Could not convert policy from yaml to json";
|
||||
return genError("Could not convert policy from yaml to json. Error: " + maybe_policy_as_json.getErr());
|
||||
}
|
||||
|
||||
auto i_orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<PolicyMakerUtils>();
|
||||
auto maybe_policy = i_orchestration_tools->jsonStringToObject<AppsecLinuxPolicy>(
|
||||
maybe_policy_as_json.unpack()
|
||||
);
|
||||
|
||||
if (!maybe_policy.ok()) {
|
||||
string error = "Policy in path: " + policy_path + " was not loaded. Error: " + maybe_policy.getErr();
|
||||
dbgDebug(D_NGINX_POLICY) << error;
|
||||
return genError(error);
|
||||
}
|
||||
return maybe_policy.unpack();
|
||||
}
|
||||
|
||||
void
|
||||
PolicyMakerUtils::clearElementsMaps()
|
||||
{
|
||||
log_triggers.clear();
|
||||
web_user_res_triggers.clear();
|
||||
inner_exceptions.clear();
|
||||
web_apps.clear();
|
||||
rules_config.clear();
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START Reason: no test exist - needed for NGINX config
|
||||
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;
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
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)
|
||||
{
|
||||
clearElementsMaps();
|
||||
|
||||
stringstream ss;
|
||||
{
|
||||
cereal::JSONOutputArchive ar(ss);
|
||||
policy.save(ar);
|
||||
}
|
||||
string policy_str = ss.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 logToK8sService = trigger_spec.getAppsecTriggerLogDestination().isK8SNeeded();
|
||||
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,
|
||||
logToK8sService,
|
||||
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;
|
||||
}
|
||||
|
||||
vector<SourcesIdentifiers>
|
||||
addSourceIdentifiersToTrustedSource(
|
||||
const string &source_identifeir_from_trust,
|
||||
const SourceIdentifierSpec &src_ident
|
||||
)
|
||||
{
|
||||
vector<SourcesIdentifiers> generated_trusted_json;
|
||||
if (src_ident.getValues().empty()) {
|
||||
generated_trusted_json.push_back(
|
||||
SourcesIdentifiers(src_ident.getSourceIdentifier(), source_identifeir_from_trust)
|
||||
);
|
||||
} else {
|
||||
for (const string &val : src_ident.getValues()) {
|
||||
string src_key = src_ident.getSourceIdentifier() + ":" + val;
|
||||
generated_trusted_json.push_back(SourcesIdentifiers(src_key, source_identifeir_from_trust));
|
||||
}
|
||||
}
|
||||
|
||||
return generated_trusted_json;
|
||||
}
|
||||
|
||||
AppSecTrustedSources
|
||||
createTrustedSourcesSection(
|
||||
const string &treusted_sources_annotation_name,
|
||||
const string &source_identifier_annotation_name,
|
||||
const AppsecLinuxPolicy &policy)
|
||||
{
|
||||
TrustedSourcesSpec treusted_sources_spec = getAppsecTrustedSourceSpecs(treusted_sources_annotation_name, policy);
|
||||
SourceIdentifierSpecWrapper source_identifiers_spec = getAppsecSourceIdentifierSpecs(
|
||||
source_identifier_annotation_name,
|
||||
policy
|
||||
);
|
||||
|
||||
vector<SourcesIdentifiers> generated_trusted_json;
|
||||
for (const SourceIdentifierSpec &src_ident : source_identifiers_spec.getIdentifiers()) {
|
||||
for (const string &source_identifeir_from_trust : treusted_sources_spec.getSourcesIdentifiers()) {
|
||||
vector<SourcesIdentifiers> tmp_trusted = addSourceIdentifiersToTrustedSource(
|
||||
source_identifeir_from_trust,
|
||||
src_ident
|
||||
);
|
||||
generated_trusted_json.insert(generated_trusted_json.end(), tmp_trusted.begin(), tmp_trusted.end());
|
||||
}
|
||||
}
|
||||
|
||||
AppSecTrustedSources treusted_sources(
|
||||
treusted_sources_spec.getName(),
|
||||
treusted_sources_spec.getMinNumOfSources(),
|
||||
generated_trusted_json
|
||||
);
|
||||
|
||||
return treusted_sources;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
UsersIdentifiersRulebase
|
||||
createUserIdentifiers (
|
||||
const string &source_identifier_annotation_name,
|
||||
const AppsecLinuxPolicy &policy,
|
||||
const string &context
|
||||
)
|
||||
{
|
||||
string jwt_identifier = "";
|
||||
vector<string> jwt_identifier_values;
|
||||
vector<UsersIdentifier> user_ident_vec;
|
||||
SourceIdentifierSpecWrapper source_identifiers_spec = getAppsecSourceIdentifierSpecs(
|
||||
source_identifier_annotation_name,
|
||||
policy
|
||||
);
|
||||
|
||||
for (const SourceIdentifierSpec &src_ident : source_identifiers_spec.getIdentifiers()) {
|
||||
if (src_ident.getSourceIdentifier() == "JWTKey") {
|
||||
jwt_identifier = "JWTKey";
|
||||
jwt_identifier_values.insert(
|
||||
jwt_identifier_values.end(),
|
||||
src_ident.getValues().begin(),
|
||||
src_ident.getValues().end()
|
||||
);
|
||||
user_ident_vec.push_back(UsersIdentifier("authorization", src_ident.getValues()));
|
||||
} else {
|
||||
user_ident_vec.push_back(UsersIdentifier(src_ident.getSourceIdentifier(), src_ident.getValues()));
|
||||
}
|
||||
}
|
||||
UsersIdentifiersRulebase users_ident = UsersIdentifiersRulebase(
|
||||
context,
|
||||
jwt_identifier,
|
||||
jwt_identifier_values,
|
||||
user_ident_vec
|
||||
);
|
||||
|
||||
return users_ident;
|
||||
}
|
||||
|
||||
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), convertMapToVector(users_identifiers));
|
||||
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::TRUSTED_SOURCES].empty() &&
|
||||
!rule_annotations[AnnotationTypes::SOURCE_IDENTIFIERS].empty() &&
|
||||
!trusted_sources.count(rule_annotations[AnnotationTypes::TRUSTED_SOURCES])
|
||||
) {
|
||||
trusted_sources[rule_annotations[AnnotationTypes::TRUSTED_SOURCES]] =
|
||||
createTrustedSourcesSection(
|
||||
rule_annotations[AnnotationTypes::TRUSTED_SOURCES],
|
||||
rule_annotations[AnnotationTypes::SOURCE_IDENTIFIERS],
|
||||
policy
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!rule_annotations[AnnotationTypes::PRACTICE].empty() &&
|
||||
!web_apps.count(rule_annotations[AnnotationTypes::PRACTICE])
|
||||
) {
|
||||
trusted_sources[rule_annotations[AnnotationTypes::TRUSTED_SOURCES]] =
|
||||
createTrustedSourcesSection(
|
||||
rule_annotations[AnnotationTypes::TRUSTED_SOURCES],
|
||||
rule_annotations[AnnotationTypes::SOURCE_IDENTIFIERS],
|
||||
policy
|
||||
);
|
||||
}
|
||||
|
||||
if (!rule_annotations[AnnotationTypes::PRACTICE].empty()) {
|
||||
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;
|
||||
|
||||
if (!rule_annotations[AnnotationTypes::SOURCE_IDENTIFIERS].empty()) {
|
||||
UsersIdentifiersRulebase user_identifiers = createUserIdentifiers(
|
||||
rule_annotations[AnnotationTypes::SOURCE_IDENTIFIERS],
|
||||
policy,
|
||||
rule_config.getContext()
|
||||
);
|
||||
users_identifiers[rule_annotations[AnnotationTypes::SOURCE_IDENTIFIERS]] = user_identifiers;
|
||||
}
|
||||
|
||||
if (!web_apps.count(rule_annotations[AnnotationTypes::PRACTICE])) {
|
||||
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(),
|
||||
trusted_sources[rule_annotations[AnnotationTypes::TRUSTED_SOURCES]]
|
||||
);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PolicyMakerUtils::createAgentPolicyFromAppsecPolicy(const string &policy_name, const AppsecLinuxPolicy &appsec_policy)
|
||||
{
|
||||
dbgTrace(D_LOCAL_POLICY) << "Proccesing policy, name: " << policy_name;
|
||||
|
||||
ParsedRule default_rule = appsec_policy.getAppsecPolicySpec().getDefaultRule();
|
||||
|
||||
// add default rule to policy
|
||||
createPolicyElementsByRule(default_rule, default_rule, appsec_policy, policy_name);
|
||||
|
||||
vector<ParsedRule> specific_rules = appsec_policy.getAppsecPolicySpec().getSpecificRules();
|
||||
createPolicyElements(specific_rules, default_rule, appsec_policy, policy_name);
|
||||
}
|
||||
|
||||
string
|
||||
PolicyMakerUtils::proccesSingleAppsecPolicy(
|
||||
const string &policy_path,
|
||||
const string &policy_version,
|
||||
const string &local_appsec_policy_path)
|
||||
{
|
||||
Maybe<AppsecLinuxPolicy> maybe_policy = openPolicyAsJson(policy_path);
|
||||
if (!maybe_policy.ok()){
|
||||
dbgWarning(D_LOCAL_POLICY) << maybe_policy.getErr();
|
||||
return "";
|
||||
}
|
||||
createAgentPolicyFromAppsecPolicy(getPolicyName(policy_path), maybe_policy.unpack());
|
||||
|
||||
PolicyWrapper policy_wrapper = combineElementsToPolicy(policy_version);
|
||||
return dumpPolicyToFile(
|
||||
policy_wrapper,
|
||||
local_appsec_policy_path
|
||||
);
|
||||
}
|
||||
|
||||
string
|
||||
PolicyMakerUtils::proccesMultipleAppsecPolicies(
|
||||
const map<string, AppsecLinuxPolicy> &appsec_policies,
|
||||
const string &policy_version,
|
||||
const string &local_appsec_policy_path)
|
||||
{
|
||||
for (const auto &appsec_policy : appsec_policies) {
|
||||
createAgentPolicyFromAppsecPolicy(appsec_policy.first, appsec_policy.second);
|
||||
}
|
||||
|
||||
PolicyWrapper policy_wrapper = combineElementsToPolicy(policy_version);
|
||||
return dumpPolicyToFile(
|
||||
policy_wrapper,
|
||||
local_appsec_policy_path
|
||||
);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user