mirror of
https://github.com/openappsec/openappsec.git
synced 2025-11-17 01:41:52 +03:00
Compare commits
107 Commits
1.1.21
...
v1beta2-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9e110292a | ||
|
|
78d1bcf7c4 | ||
|
|
c90862d74c | ||
|
|
b7923dfd8c | ||
|
|
ed4e20b010 | ||
|
|
14159402e2 | ||
|
|
b74957d9d4 | ||
|
|
0c0da6d91b | ||
|
|
ef887dd1c7 | ||
|
|
6bbc89712a | ||
|
|
dd19bf6158 | ||
|
|
60facef890 | ||
|
|
a3ac05642c | ||
|
|
682b91684d | ||
|
|
ff8c5701fe | ||
|
|
796c6cf935 | ||
|
|
31ff6f2c72 | ||
|
|
eac686216b | ||
|
|
938cae1270 | ||
|
|
87cdeef42f | ||
|
|
d04ea7d3e2 | ||
|
|
6d649cf5d5 | ||
|
|
5f71946590 | ||
|
|
c75f1e88b7 | ||
|
|
c4975497eb | ||
|
|
782dfeada6 | ||
|
|
bc1eac9d39 | ||
|
|
4dacd7d009 | ||
|
|
3a34984def | ||
|
|
5aaf787cfa | ||
|
|
2c7b5818e8 | ||
|
|
c8743d4d4b | ||
|
|
d703f16e35 | ||
|
|
692c430e8a | ||
|
|
72c5594b10 | ||
|
|
2c6b6baa3b | ||
|
|
37d0f1c45f | ||
|
|
2678db9d2f | ||
|
|
52c93ad574 | ||
|
|
bd3a53041e | ||
|
|
44f40fbd1b | ||
|
|
0691f9b9cd | ||
|
|
0891dcd251 | ||
|
|
7669f0c89c | ||
|
|
39d7884bed | ||
|
|
b8783c3065 | ||
|
|
37dc9f14b4 | ||
|
|
9a1f1b5966 | ||
|
|
b0bfd3077c | ||
|
|
0469f5aa1f | ||
|
|
3578797214 | ||
|
|
16a72fdf3e | ||
|
|
87d257f268 | ||
|
|
36d8006c26 | ||
|
|
8d47795d4d | ||
|
|
f3656712b0 | ||
|
|
b1781234fd | ||
|
|
f71dca2bfa | ||
|
|
bd333818ad | ||
|
|
95e776d7a4 | ||
|
|
51c2912434 | ||
|
|
0246b73bbd | ||
|
|
919921f6d3 | ||
|
|
e9098e2845 | ||
|
|
97d042589b | ||
|
|
df7be864e2 | ||
|
|
ba8ec26344 | ||
|
|
97add465e8 | ||
|
|
38cb1f2c3b | ||
|
|
1dd9371840 | ||
|
|
f23d22a723 | ||
|
|
b51cf09190 | ||
|
|
ceb6469a7e | ||
|
|
b0ae283eed | ||
|
|
5fcb9bdc4a | ||
|
|
fb5698360b | ||
|
|
147626bc7f | ||
|
|
448991ef75 | ||
|
|
2b1ee84280 | ||
|
|
77dd288eee | ||
|
|
3cb4def82e | ||
|
|
a0dd7dd614 | ||
|
|
88eed946ec | ||
|
|
3e1ad8b0f7 | ||
|
|
bd35c421c6 | ||
|
|
9d6e883724 | ||
|
|
cd020a7ddd | ||
|
|
bb35eaf657 | ||
|
|
648f9ae2b1 | ||
|
|
47e47d706a | ||
|
|
b852809d1a | ||
|
|
a77732f84c | ||
|
|
a1a8e28019 | ||
|
|
a99c2ec4a3 | ||
|
|
f1303c1703 | ||
|
|
bd8174ead3 | ||
|
|
4ddcd2462a | ||
|
|
81433bac25 | ||
|
|
8d03b49176 | ||
|
|
84f9624c00 | ||
|
|
3ecda7b979 | ||
|
|
8f05508e02 | ||
|
|
f5b9c93fbe | ||
|
|
62b74c9a10 | ||
|
|
e3163cd4fa | ||
|
|
1e98fc8c66 | ||
|
|
6fbe272378 |
36
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
36
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
name: "Bug Report"
|
||||||
|
about: "Report a bug with open-appsec"
|
||||||
|
labels: [bug]
|
||||||
|
---
|
||||||
|
|
||||||
|
**Checklist**
|
||||||
|
- Have you checked the open-appsec troubleshooting guides - https://docs.openappsec.io/troubleshooting/troubleshooting
|
||||||
|
- Yes / No
|
||||||
|
- Have you checked the existing issues and discussions in github for the same issue
|
||||||
|
- Yes / No
|
||||||
|
- Have you checked the knwon limitations same issue - https://docs.openappsec.io/release-notes#limitations
|
||||||
|
- Yes / No
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Run '...'
|
||||||
|
3. See error '...'
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots or Logs**
|
||||||
|
If applicable, add screenshots or logs to help explain the issue.
|
||||||
|
|
||||||
|
**Environment (please complete the following information):**
|
||||||
|
- open-appsec version:
|
||||||
|
- Deployment type (Docker, Kubernetes, etc.):
|
||||||
|
- OS:
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: "Documentation & Troubleshooting"
|
||||||
|
url: "https://docs.openappsec.io/"
|
||||||
|
about: "Check the documentation before submitting an issue."
|
||||||
|
- name: "Feature Requests & Discussions"
|
||||||
|
url: "https://github.com/openappsec/openappsec/discussions"
|
||||||
|
about: "Please open a discussion for feature requests."
|
||||||
17
.github/ISSUE_TEMPLATE/nginx_version_support.md
vendored
Normal file
17
.github/ISSUE_TEMPLATE/nginx_version_support.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
name: "Nginx Version Support Request"
|
||||||
|
about: "Request for a specific Nginx version to be supported"
|
||||||
|
---
|
||||||
|
|
||||||
|
**Nginx & OS Version:**
|
||||||
|
Which Nginx and OS version are you using?
|
||||||
|
|
||||||
|
**Output of nginx -V**
|
||||||
|
Share the output of nginx -v
|
||||||
|
|
||||||
|
**Expected Behavior:**
|
||||||
|
What do you expect to happen with this version?
|
||||||
|
|
||||||
|
**Checklist**
|
||||||
|
- Have you considered a docker based deployment - find more information here https://docs.openappsec.io/getting-started/start-with-docker?
|
||||||
|
- Yes / No
|
||||||
22
README.md
22
README.md
@@ -6,7 +6,7 @@
|
|||||||
[](https://bestpractices.coreinfrastructure.org/projects/6629)
|
[](https://bestpractices.coreinfrastructure.org/projects/6629)
|
||||||
|
|
||||||
# About
|
# About
|
||||||
[open-appsec](https://www.openappsec.io) (openappsec.io) builds on machine learning to provide preemptive web app & API threat protection against OWASP-Top-10 and zero-day attacks. It can be deployed as an add-on to Kubernetes Ingress, NGINX, Envoy (soon), and API Gateways.
|
[open-appsec](https://www.openappsec.io) (openappsec.io) builds on machine learning to provide preemptive web app & API threat protection against OWASP-Top-10 and zero-day attacks. It can be deployed as an add-on to Linux, Docker or K8s deployments, on NGINX, Kong, APISIX, or Envoy.
|
||||||
|
|
||||||
The open-appsec engine learns how users normally interact with your web application. It then uses this information to automatically detect requests that fall outside of normal operations, and conducts further analysis to decide whether the request is malicious or not.
|
The open-appsec engine learns how users normally interact with your web application. It then uses this information to automatically detect requests that fall outside of normal operations, and conducts further analysis to decide whether the request is malicious or not.
|
||||||
|
|
||||||
@@ -39,13 +39,13 @@ open-appsec can be managed using multiple methods:
|
|||||||
* [Using SaaS Web Management](https://docs.openappsec.io/getting-started/using-the-web-ui-saas)
|
* [Using SaaS Web Management](https://docs.openappsec.io/getting-started/using-the-web-ui-saas)
|
||||||
|
|
||||||
open-appsec Web UI:
|
open-appsec Web UI:
|
||||||

|
<img width="1854" height="775" alt="image" src="https://github.com/user-attachments/assets/4c6f7b0a-14f3-4f02-9ab0-ddadc9979b8d" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Deployment Playgrounds (Virtual labs)
|
## Deployment Playgrounds (Virtual labs)
|
||||||
You can experiment with open-appsec using [Playgrounds](https://www.openappsec.io/playground)
|
You can experiment with open-appsec using [Playgrounds](https://www.openappsec.io/playground)
|
||||||
|
<img width="781" height="878" alt="image" src="https://github.com/user-attachments/assets/0ddee216-5cdf-4288-8c41-cc28cfbf3297" />
|
||||||

|
|
||||||
|
|
||||||
# Resources
|
# Resources
|
||||||
* [Project Website](https://openappsec.io)
|
* [Project Website](https://openappsec.io)
|
||||||
@@ -54,21 +54,15 @@ You can experiment with open-appsec using [Playgrounds](https://www.openappsec.i
|
|||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
For Kubernetes (NGINX Ingress) using the installer:
|
For Kubernetes (NGINX /Kong / APISIX / Istio) using Helm: follow [documentation](https://docs.openappsec.io/getting-started/start-with-kubernetes)
|
||||||
|
|
||||||
```bash
|
For Linux (NGINX / Kong / APISIX) using the installer (list of supported/pre-compiled NGINX attachments is available [here](https://downloads.openappsec.io/packages/supported-nginx.txt)):
|
||||||
$ wget https://downloads.openappsec.io/open-appsec-k8s-install && chmod +x open-appsec-k8s-install
|
|
||||||
$ ./open-appsec-k8s-install
|
|
||||||
```
|
|
||||||
|
|
||||||
For Kubernetes (NGINX or Kong) using Helm: follow [documentation](https://docs.openappsec.io/getting-started/start-with-kubernetes/install-using-helm-ingress-nginx-and-kong) – use this method if you’ve built your own containers.
|
|
||||||
|
|
||||||
For Linux (NGINX or Kong) using the installer (list of supported/pre-compiled NGINX attachments is available [here](https://downloads.openappsec.io/packages/supported-nginx.txt)):
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ wget https://downloads.openappsec.io/open-appsec-install && chmod +x open-appsec-install
|
$ wget https://downloads.openappsec.io/open-appsec-install && chmod +x open-appsec-install
|
||||||
$ ./open-appsec-install --auto
|
$ ./open-appsec-install --auto
|
||||||
```
|
```
|
||||||
|
For kong Lua Based plug in follow [documentation](https://docs.openappsec.io/getting-started/start-with-linux)
|
||||||
|
|
||||||
For Linux, if you’ve built your own package use the following commands:
|
For Linux, if you’ve built your own package use the following commands:
|
||||||
|
|
||||||
@@ -177,7 +171,7 @@ open-appsec code was audited by an independent third party in September-October
|
|||||||
See the [full report](https://github.com/openappsec/openappsec/blob/main/LEXFO-CHP20221014-Report-Code_audit-OPEN-APPSEC-v1.2.pdf).
|
See the [full report](https://github.com/openappsec/openappsec/blob/main/LEXFO-CHP20221014-Report-Code_audit-OPEN-APPSEC-v1.2.pdf).
|
||||||
|
|
||||||
### Reporting security vulnerabilities
|
### 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.
|
If you've found a vulnerability or a potential vulnerability in open-appsec please let us know at security-alert@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
|
# License
|
||||||
|
|||||||
@@ -95,6 +95,18 @@ getFailOpenHoldTimeout()
|
|||||||
return conf_data.getNumericalValue("fail_open_hold_timeout");
|
return conf_data.getNumericalValue("fail_open_hold_timeout");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
getHoldVerdictPollingTime()
|
||||||
|
{
|
||||||
|
return conf_data.getNumericalValue("hold_verdict_polling_time");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
getHoldVerdictRetries()
|
||||||
|
{
|
||||||
|
return conf_data.getNumericalValue("hold_verdict_retries");
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
getMaxSessionsPerMinute()
|
getMaxSessionsPerMinute()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ TEST_F(HttpAttachmentUtilTest, GetValidAttachmentConfiguration)
|
|||||||
"\"static_resources_path\": \"" + static_resources_path + "\",\n"
|
"\"static_resources_path\": \"" + static_resources_path + "\",\n"
|
||||||
"\"min_retries_for_verdict\": 1,\n"
|
"\"min_retries_for_verdict\": 1,\n"
|
||||||
"\"max_retries_for_verdict\": 3,\n"
|
"\"max_retries_for_verdict\": 3,\n"
|
||||||
|
"\"hold_verdict_retries\": 3,\n"
|
||||||
|
"\"hold_verdict_polling_time\": 1,\n"
|
||||||
"\"body_size_trigger\": 777,\n"
|
"\"body_size_trigger\": 777,\n"
|
||||||
"\"remove_server_header\": 1\n"
|
"\"remove_server_header\": 1\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
@@ -97,6 +99,8 @@ TEST_F(HttpAttachmentUtilTest, GetValidAttachmentConfiguration)
|
|||||||
EXPECT_EQ(getWaitingForVerdictThreadTimeout(), 75u);
|
EXPECT_EQ(getWaitingForVerdictThreadTimeout(), 75u);
|
||||||
EXPECT_EQ(getInspectionMode(), ngx_http_inspection_mode::BLOCKING_THREAD);
|
EXPECT_EQ(getInspectionMode(), ngx_http_inspection_mode::BLOCKING_THREAD);
|
||||||
EXPECT_EQ(getRemoveResServerHeader(), 1u);
|
EXPECT_EQ(getRemoveResServerHeader(), 1u);
|
||||||
|
EXPECT_EQ(getHoldVerdictRetries(), 3u);
|
||||||
|
EXPECT_EQ(getHoldVerdictPollingTime(), 1u);
|
||||||
|
|
||||||
EXPECT_EQ(isDebugContext("1.2.3.4", "5.6.7.8", 80, "GET", "test", "/abc"), 1);
|
EXPECT_EQ(isDebugContext("1.2.3.4", "5.6.7.8", 80, "GET", "test", "/abc"), 1);
|
||||||
EXPECT_EQ(isDebugContext("1.2.3.9", "5.6.7.8", 80, "GET", "test", "/abc"), 0);
|
EXPECT_EQ(isDebugContext("1.2.3.9", "5.6.7.8", 80, "GET", "test", "/abc"), 0);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
install(FILES Dockerfile entry.sh install-cp-agent-intelligence-service.sh install-cp-crowdsec-aux.sh DESTINATION .)
|
install(FILES Dockerfile entry.sh install-cp-agent-intelligence-service.sh install-cp-crowdsec-aux.sh self_managed_openappsec_manifest.json DESTINATION .)
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${CMAKE_INSTALL_PREFIX}/agent-docker.img
|
OUTPUT ${CMAKE_INSTALL_PREFIX}/agent-docker.img
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
FROM alpine
|
FROM alpine
|
||||||
|
|
||||||
|
ENV OPENAPPSEC_NANO_AGENT=TRUE
|
||||||
|
|
||||||
RUN apk add --no-cache -u busybox
|
RUN apk add --no-cache -u busybox
|
||||||
RUN apk add --no-cache -u zlib
|
RUN apk add --no-cache -u zlib
|
||||||
RUN apk add --no-cache bash
|
RUN apk add --no-cache bash
|
||||||
@@ -11,8 +13,12 @@ RUN apk add --no-cache libunwind
|
|||||||
RUN apk add --no-cache gdb
|
RUN apk add --no-cache gdb
|
||||||
RUN apk add --no-cache libxml2
|
RUN apk add --no-cache libxml2
|
||||||
RUN apk add --no-cache pcre2
|
RUN apk add --no-cache pcre2
|
||||||
|
RUN apk add --no-cache ca-certificates
|
||||||
RUN apk add --update coreutils
|
RUN apk add --update coreutils
|
||||||
|
|
||||||
|
|
||||||
|
COPY self_managed_openappsec_manifest.json /tmp/self_managed_openappsec_manifest.json
|
||||||
|
|
||||||
COPY install*.sh /nano-service-installers/
|
COPY install*.sh /nano-service-installers/
|
||||||
COPY entry.sh /entry.sh
|
COPY entry.sh /entry.sh
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ HTTP_TRANSACTION_HANDLER_SERVICE="install-cp-nano-service-http-transaction-handl
|
|||||||
ATTACHMENT_REGISTRATION_SERVICE="install-cp-nano-attachment-registration-manager.sh"
|
ATTACHMENT_REGISTRATION_SERVICE="install-cp-nano-attachment-registration-manager.sh"
|
||||||
ORCHESTRATION_INSTALLATION_SCRIPT="install-cp-nano-agent.sh"
|
ORCHESTRATION_INSTALLATION_SCRIPT="install-cp-nano-agent.sh"
|
||||||
CACHE_INSTALLATION_SCRIPT="install-cp-nano-agent-cache.sh"
|
CACHE_INSTALLATION_SCRIPT="install-cp-nano-agent-cache.sh"
|
||||||
|
PROMETHEUS_INSTALLATION_SCRIPT="install-cp-nano-service-prometheus.sh"
|
||||||
|
NGINX_CENTRAL_MANAGER_INSTALLATION_SCRIPT="install-cp-nano-central-nginx-manager.sh"
|
||||||
|
|
||||||
var_fog_address=
|
var_fog_address=
|
||||||
var_proxy=
|
var_proxy=
|
||||||
@@ -13,6 +15,21 @@ var_mode=
|
|||||||
var_token=
|
var_token=
|
||||||
var_ignore=
|
var_ignore=
|
||||||
init=
|
init=
|
||||||
|
active_watchdog_pid=
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
local signal="$1"
|
||||||
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Signal ${signal} was received, exiting gracefully..." >&2
|
||||||
|
if [ -n "${active_watchdog_pid}" ] && ps -p ${active_watchdog_pid} > /dev/null 2>&1; then
|
||||||
|
kill -TERM ${active_watchdog_pid} 2>/dev/null || true
|
||||||
|
wait ${active_watchdog_pid} 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
echo "Cleanup completed. Exiting now." >&2
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
trap 'cleanup SIGTERM' SIGTERM
|
||||||
|
trap 'cleanup SIGINT' SIGINT
|
||||||
|
|
||||||
if [ ! -f /nano-service-installers/$ORCHESTRATION_INSTALLATION_SCRIPT ]; then
|
if [ ! -f /nano-service-installers/$ORCHESTRATION_INSTALLATION_SCRIPT ]; then
|
||||||
echo "Error: agent installation package doesn't exist."
|
echo "Error: agent installation package doesn't exist."
|
||||||
@@ -81,6 +98,14 @@ fi
|
|||||||
/nano-service-installers/$CACHE_INSTALLATION_SCRIPT --install
|
/nano-service-installers/$CACHE_INSTALLATION_SCRIPT --install
|
||||||
/nano-service-installers/$HTTP_TRANSACTION_HANDLER_SERVICE --install
|
/nano-service-installers/$HTTP_TRANSACTION_HANDLER_SERVICE --install
|
||||||
|
|
||||||
|
if [ "$PROMETHEUS" == "true" ]; then
|
||||||
|
/nano-service-installers/$PROMETHEUS_INSTALLATION_SCRIPT --install
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$CENTRAL_NGINX_MANAGER" == "true" ]; then
|
||||||
|
/nano-service-installers/$NGINX_CENTRAL_MANAGER_INSTALLATION_SCRIPT --install
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$CROWDSEC_ENABLED" == "true" ]; then
|
if [ "$CROWDSEC_ENABLED" == "true" ]; then
|
||||||
/nano-service-installers/$INTELLIGENCE_INSTALLATION_SCRIPT --install
|
/nano-service-installers/$INTELLIGENCE_INSTALLATION_SCRIPT --install
|
||||||
/nano-service-installers/$CROWDSEC_INSTALLATION_SCRIPT --install
|
/nano-service-installers/$CROWDSEC_INSTALLATION_SCRIPT --install
|
||||||
@@ -93,25 +118,16 @@ if [ -f "$FILE" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
touch /etc/cp/watchdog/wd.startup
|
touch /etc/cp/watchdog/wd.startup
|
||||||
|
/etc/cp/watchdog/cp-nano-watchdog >/dev/null 2>&1 &
|
||||||
|
active_watchdog_pid=$!
|
||||||
while true; do
|
while true; do
|
||||||
if [ -z "$init" ]; then
|
if [ -f /tmp/restart_watchdog ]; then
|
||||||
init=true
|
|
||||||
/etc/cp/watchdog/cp-nano-watchdog >/dev/null 2>&1 &
|
|
||||||
sleep 5
|
|
||||||
active_watchdog_pid=$(pgrep -f -x -o "/bin/bash /etc/cp/watchdog/cp-nano-watchdog")
|
|
||||||
fi
|
|
||||||
|
|
||||||
current_watchdog_pid=$(pgrep -f -x -o "/bin/bash /etc/cp/watchdog/cp-nano-watchdog")
|
|
||||||
if [ ! -f /tmp/restart_watchdog ] && [ "$current_watchdog_pid" != "$active_watchdog_pid" ]; then
|
|
||||||
echo "Error: Watchdog exited abnormally"
|
|
||||||
exit 1
|
|
||||||
elif [ -f /tmp/restart_watchdog ]; then
|
|
||||||
rm -f /tmp/restart_watchdog
|
rm -f /tmp/restart_watchdog
|
||||||
kill -9 "$(pgrep -f -x -o "/bin/bash /etc/cp/watchdog/cp-nano-watchdog")"
|
kill -9 ${active_watchdog_pid}
|
||||||
/etc/cp/watchdog/cp-nano-watchdog >/dev/null 2>&1 &
|
fi
|
||||||
sleep 5
|
if [ ! "$(ps -f | grep cp-nano-watchdog | grep ${active_watchdog_pid})" ]; then
|
||||||
active_watchdog_pid=$(pgrep -f -x -o "/bin/bash /etc/cp/watchdog/cp-nano-watchdog")
|
/etc/cp/watchdog/cp-nano-watchdog >/dev/null 2>&1 &
|
||||||
|
active_watchdog_pid=$!
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sleep 5
|
sleep 5
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -31,10 +31,12 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include <boost/range/iterator_range.hpp>
|
#include <boost/range/iterator_range.hpp>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
|
|
||||||
#include "nginx_attachment_config.h"
|
#include "nginx_attachment_config.h"
|
||||||
#include "nginx_attachment_opaque.h"
|
#include "nginx_attachment_opaque.h"
|
||||||
|
#include "generic_rulebase/evaluators/trigger_eval.h"
|
||||||
#include "nginx_parser.h"
|
#include "nginx_parser.h"
|
||||||
#include "i_instance_awareness.h"
|
#include "i_instance_awareness.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
@@ -129,6 +131,7 @@ class NginxAttachment::Impl
|
|||||||
Singleton::Provide<I_StaticResourcesHandler>::From<NginxAttachment>
|
Singleton::Provide<I_StaticResourcesHandler>::From<NginxAttachment>
|
||||||
{
|
{
|
||||||
static constexpr auto INSPECT = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT;
|
static constexpr auto INSPECT = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT;
|
||||||
|
static constexpr auto LIMIT_RESPONSE_HEADERS = ngx_http_cp_verdict_e::LIMIT_RESPONSE_HEADERS;
|
||||||
static constexpr auto ACCEPT = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_ACCEPT;
|
static constexpr auto ACCEPT = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_ACCEPT;
|
||||||
static constexpr auto DROP = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP;
|
static constexpr auto DROP = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP;
|
||||||
static constexpr auto INJECT = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INJECT;
|
static constexpr auto INJECT = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INJECT;
|
||||||
@@ -260,6 +263,22 @@ public:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* ignored_headers_env = getenv("SAAS_IGNORED_UPSTREAM_HEADERS");
|
||||||
|
if (ignored_headers_env) {
|
||||||
|
string ignored_headers_str = ignored_headers_env;
|
||||||
|
ignored_headers_str = NGEN::Strings::trim(ignored_headers_str);
|
||||||
|
|
||||||
|
if (!ignored_headers_str.empty()) {
|
||||||
|
dbgInfo(D_HTTP_MANAGER)
|
||||||
|
<< "Ignoring SAAS_IGNORED_UPSTREAM_HEADERS environment variable: "
|
||||||
|
<< ignored_headers_str;
|
||||||
|
|
||||||
|
vector<string> ignored_headers_vec;
|
||||||
|
boost::split(ignored_headers_vec, ignored_headers_str, boost::is_any_of(";"));
|
||||||
|
for (const string &header : ignored_headers_vec) ignored_headers.insert(header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dbgInfo(D_NGINX_ATTACHMENT) << "Successfully initialized NGINX Attachment";
|
dbgInfo(D_NGINX_ATTACHMENT) << "Successfully initialized NGINX Attachment";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1034,7 +1053,11 @@ private:
|
|||||||
case ChunkType::REQUEST_START:
|
case ChunkType::REQUEST_START:
|
||||||
return handleStartTransaction(data, opaque);
|
return handleStartTransaction(data, opaque);
|
||||||
case ChunkType::REQUEST_HEADER:
|
case ChunkType::REQUEST_HEADER:
|
||||||
return handleMultiModifiableChunks(NginxParser::parseRequestHeaders(data), "request header", true);
|
return handleMultiModifiableChunks(
|
||||||
|
NginxParser::parseRequestHeaders(data, ignored_headers),
|
||||||
|
"request header",
|
||||||
|
true
|
||||||
|
);
|
||||||
case ChunkType::REQUEST_BODY:
|
case ChunkType::REQUEST_BODY:
|
||||||
return handleModifiableChunk(NginxParser::parseRequestBody(data), "request body", true);
|
return handleModifiableChunk(NginxParser::parseRequestBody(data), "request body", true);
|
||||||
case ChunkType::REQUEST_END: {
|
case ChunkType::REQUEST_END: {
|
||||||
@@ -1125,10 +1148,18 @@ private:
|
|||||||
handleCustomWebResponse(
|
handleCustomWebResponse(
|
||||||
SharedMemoryIPC *ipc,
|
SharedMemoryIPC *ipc,
|
||||||
vector<const char *> &verdict_data,
|
vector<const char *> &verdict_data,
|
||||||
vector<uint16_t> &verdict_data_sizes)
|
vector<uint16_t> &verdict_data_sizes,
|
||||||
|
string web_user_response_id)
|
||||||
{
|
{
|
||||||
ngx_http_cp_web_response_data_t web_response_data;
|
ngx_http_cp_web_response_data_t web_response_data;
|
||||||
|
ScopedContext ctx;
|
||||||
|
if (web_user_response_id != "") {
|
||||||
|
dbgTrace(D_NGINX_ATTACHMENT)
|
||||||
|
<< "web user response ID registered in contex: "
|
||||||
|
<< web_user_response_id;
|
||||||
|
set<string> triggers_set{web_user_response_id};
|
||||||
|
ctx.registerValue<set<GenericConfigId>>(TriggerMatcher::ctx_key, triggers_set);
|
||||||
|
}
|
||||||
WebTriggerConf web_trigger_conf = getConfigurationWithDefault<WebTriggerConf>(
|
WebTriggerConf web_trigger_conf = getConfigurationWithDefault<WebTriggerConf>(
|
||||||
WebTriggerConf::default_trigger_conf,
|
WebTriggerConf::default_trigger_conf,
|
||||||
"rulebase",
|
"rulebase",
|
||||||
@@ -1250,7 +1281,7 @@ private:
|
|||||||
if (verdict.getVerdict() == DROP) {
|
if (verdict.getVerdict() == DROP) {
|
||||||
nginx_attachment_event.addTrafficVerdictCounter(nginxAttachmentEvent::trafficVerdict::DROP);
|
nginx_attachment_event.addTrafficVerdictCounter(nginxAttachmentEvent::trafficVerdict::DROP);
|
||||||
verdict_to_send.modification_count = 1;
|
verdict_to_send.modification_count = 1;
|
||||||
return handleCustomWebResponse(ipc, verdict_fragments, fragments_sizes);
|
return handleCustomWebResponse(ipc, verdict_fragments, fragments_sizes, verdict.getWebUserResponseID());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verdict.getVerdict() == ACCEPT) {
|
if (verdict.getVerdict() == ACCEPT) {
|
||||||
@@ -1476,11 +1507,17 @@ private:
|
|||||||
opaque.activateContext();
|
opaque.activateContext();
|
||||||
|
|
||||||
FilterVerdict verdict = handleChunkedData(*chunked_data_type, inspection_data, opaque);
|
FilterVerdict verdict = handleChunkedData(*chunked_data_type, inspection_data, opaque);
|
||||||
|
|
||||||
bool is_header =
|
bool is_header =
|
||||||
*chunked_data_type == ChunkType::REQUEST_HEADER ||
|
*chunked_data_type == ChunkType::REQUEST_HEADER ||
|
||||||
*chunked_data_type == ChunkType::RESPONSE_HEADER ||
|
*chunked_data_type == ChunkType::RESPONSE_HEADER ||
|
||||||
*chunked_data_type == ChunkType::CONTENT_LENGTH;
|
*chunked_data_type == ChunkType::CONTENT_LENGTH;
|
||||||
|
|
||||||
|
if (verdict.getVerdict() == LIMIT_RESPONSE_HEADERS) {
|
||||||
|
handleVerdictResponse(verdict, attachment_ipc, transaction_data->session_id, is_header);
|
||||||
|
popData(attachment_ipc);
|
||||||
|
verdict = FilterVerdict(INSPECT);
|
||||||
|
}
|
||||||
|
|
||||||
handleVerdictResponse(verdict, attachment_ipc, transaction_data->session_id, is_header);
|
handleVerdictResponse(verdict, attachment_ipc, transaction_data->session_id, is_header);
|
||||||
|
|
||||||
bool is_final_verdict = verdict.getVerdict() == ACCEPT ||
|
bool is_final_verdict = verdict.getVerdict() == ACCEPT ||
|
||||||
@@ -1593,6 +1630,8 @@ private:
|
|||||||
return "INJECT";
|
return "INJECT";
|
||||||
case INSPECT:
|
case INSPECT:
|
||||||
return "INSPECT";
|
return "INSPECT";
|
||||||
|
case LIMIT_RESPONSE_HEADERS:
|
||||||
|
return "LIMIT_RESPONSE_HEADERS";
|
||||||
case IRRELEVANT:
|
case IRRELEVANT:
|
||||||
return "IRRELEVANT";
|
return "IRRELEVANT";
|
||||||
case RECONF:
|
case RECONF:
|
||||||
@@ -1814,6 +1853,7 @@ private:
|
|||||||
HttpAttachmentConfig attachment_config;
|
HttpAttachmentConfig attachment_config;
|
||||||
I_MainLoop::RoutineID attachment_routine_id = 0;
|
I_MainLoop::RoutineID attachment_routine_id = 0;
|
||||||
bool traffic_indicator = false;
|
bool traffic_indicator = false;
|
||||||
|
unordered_set<string> ignored_headers;
|
||||||
|
|
||||||
// Interfaces
|
// Interfaces
|
||||||
I_Socket *i_socket = nullptr;
|
I_Socket *i_socket = nullptr;
|
||||||
|
|||||||
@@ -240,6 +240,21 @@ HttpAttachmentConfig::setRetriesForVerdict()
|
|||||||
"Max retries for verdict"
|
"Max retries for verdict"
|
||||||
));
|
));
|
||||||
|
|
||||||
|
conf_data.setNumericalValue("hold_verdict_retries", getAttachmentConf<uint>(
|
||||||
|
3,
|
||||||
|
"agent.retriesForHoldVerdict.nginxModule",
|
||||||
|
"HTTP manager",
|
||||||
|
"Retries for hold verdict"
|
||||||
|
));
|
||||||
|
|
||||||
|
conf_data.setNumericalValue("hold_verdict_polling_time", getAttachmentConf<uint>(
|
||||||
|
1,
|
||||||
|
"agent.holdVerdictPollingInterval.nginxModule",
|
||||||
|
"HTTP manager",
|
||||||
|
"Hold verdict polling interval seconds"
|
||||||
|
));
|
||||||
|
|
||||||
|
|
||||||
conf_data.setNumericalValue("body_size_trigger", getAttachmentConf<uint>(
|
conf_data.setNumericalValue("body_size_trigger", getAttachmentConf<uint>(
|
||||||
200000,
|
200000,
|
||||||
"agent.reqBodySizeTrigger.nginxModule",
|
"agent.reqBodySizeTrigger.nginxModule",
|
||||||
|
|||||||
@@ -19,12 +19,15 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "virtual_modifiers.h"
|
#include "virtual_modifiers.h"
|
||||||
|
#include "agent_core_utilities.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace boost::uuids;
|
using namespace boost::uuids;
|
||||||
|
|
||||||
USE_DEBUG_FLAG(D_HTTP_MANAGER);
|
USE_DEBUG_FLAG(D_HTTP_MANAGER);
|
||||||
|
|
||||||
|
extern bool is_keep_alive_ctx;
|
||||||
|
|
||||||
NginxAttachmentOpaque::NginxAttachmentOpaque(HttpTransactionData _transaction_data)
|
NginxAttachmentOpaque::NginxAttachmentOpaque(HttpTransactionData _transaction_data)
|
||||||
:
|
:
|
||||||
TableOpaqueSerialize<NginxAttachmentOpaque>(this),
|
TableOpaqueSerialize<NginxAttachmentOpaque>(this),
|
||||||
@@ -67,6 +70,12 @@ NginxAttachmentOpaque::NginxAttachmentOpaque(HttpTransactionData _transaction_da
|
|||||||
ctx.registerValue(HttpTransactionData::uri_query_decoded, decoded_url.substr(question_mark_location + 1));
|
ctx.registerValue(HttpTransactionData::uri_query_decoded, decoded_url.substr(question_mark_location + 1));
|
||||||
}
|
}
|
||||||
ctx.registerValue(HttpTransactionData::uri_path_decoded, decoded_url);
|
ctx.registerValue(HttpTransactionData::uri_path_decoded, decoded_url);
|
||||||
|
|
||||||
|
// Register waf_tag from transaction data if available
|
||||||
|
const std::string& waf_tag = transaction_data.getWafTag();
|
||||||
|
if (!waf_tag.empty()) {
|
||||||
|
ctx.registerValue(HttpTransactionData::waf_tag_ctx, waf_tag);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NginxAttachmentOpaque::~NginxAttachmentOpaque()
|
NginxAttachmentOpaque::~NginxAttachmentOpaque()
|
||||||
@@ -119,3 +128,47 @@ NginxAttachmentOpaque::setSavedData(const string &name, const string &data, EnvK
|
|||||||
saved_data[name] = data;
|
saved_data[name] = data;
|
||||||
ctx.registerValue(name, data, log_ctx);
|
ctx.registerValue(name, data, log_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
NginxAttachmentOpaque::setKeepAliveCtx(const string &hdr_key, const string &hdr_val)
|
||||||
|
{
|
||||||
|
if (!is_keep_alive_ctx) return false;
|
||||||
|
|
||||||
|
static pair<string, string> keep_alive_hdr;
|
||||||
|
static bool keep_alive_hdr_initialized = false;
|
||||||
|
|
||||||
|
if (keep_alive_hdr_initialized) {
|
||||||
|
if (!keep_alive_hdr.first.empty() && hdr_key == keep_alive_hdr.first && hdr_val == keep_alive_hdr.second) {
|
||||||
|
dbgTrace(D_HTTP_MANAGER) << "Registering keep alive context";
|
||||||
|
ctx.registerValue("keep_alive_request_ctx", true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* saas_keep_alive_hdr_name_env = getenv("SAAS_KEEP_ALIVE_HDR_NAME");
|
||||||
|
if (saas_keep_alive_hdr_name_env) {
|
||||||
|
keep_alive_hdr.first = NGEN::Strings::trim(saas_keep_alive_hdr_name_env);
|
||||||
|
dbgInfo(D_HTTP_MANAGER) << "Using SAAS_KEEP_ALIVE_HDR_NAME environment variable: " << keep_alive_hdr.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!keep_alive_hdr.first.empty()) {
|
||||||
|
const char* saas_keep_alive_hdr_value_env = getenv("SAAS_KEEP_ALIVE_HDR_VALUE");
|
||||||
|
if (saas_keep_alive_hdr_value_env) {
|
||||||
|
keep_alive_hdr.second = NGEN::Strings::trim(saas_keep_alive_hdr_value_env);
|
||||||
|
dbgInfo(D_HTTP_MANAGER)
|
||||||
|
<< "Using SAAS_KEEP_ALIVE_HDR_VALUE environment variable: "
|
||||||
|
<< keep_alive_hdr.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!keep_alive_hdr.second.empty() && (hdr_key == keep_alive_hdr.first && hdr_val == keep_alive_hdr.second)) {
|
||||||
|
dbgTrace(D_HTTP_MANAGER) << "Registering keep alive context";
|
||||||
|
ctx.registerValue("keep_alive_request_ctx", true);
|
||||||
|
keep_alive_hdr_initialized = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_alive_hdr_initialized = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ public:
|
|||||||
EnvKeyAttr::LogSection log_ctx = EnvKeyAttr::LogSection::NONE
|
EnvKeyAttr::LogSection log_ctx = EnvKeyAttr::LogSection::NONE
|
||||||
);
|
);
|
||||||
void setApplicationState(const ApplicationState &app_state) { application_state = app_state; }
|
void setApplicationState(const ApplicationState &app_state) { application_state = app_state; }
|
||||||
|
bool setKeepAliveCtx(const std::string &hdr_key, const std::string &hdr_val);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CompressionStream *response_compression_stream;
|
CompressionStream *response_compression_stream;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ USE_DEBUG_FLAG(D_NGINX_ATTACHMENT_PARSER);
|
|||||||
Buffer NginxParser::tenant_header_key = Buffer();
|
Buffer NginxParser::tenant_header_key = Buffer();
|
||||||
static const Buffer proxy_ip_header_key("X-Forwarded-For", 15, Buffer::MemoryType::STATIC);
|
static const Buffer proxy_ip_header_key("X-Forwarded-For", 15, Buffer::MemoryType::STATIC);
|
||||||
static const Buffer source_ip("sourceip", 8, Buffer::MemoryType::STATIC);
|
static const Buffer source_ip("sourceip", 8, Buffer::MemoryType::STATIC);
|
||||||
|
bool is_keep_alive_ctx = getenv("SAAS_KEEP_ALIVE_HDR_NAME") != nullptr;
|
||||||
|
|
||||||
map<Buffer, CompressionType> NginxParser::content_encodings = {
|
map<Buffer, CompressionType> NginxParser::content_encodings = {
|
||||||
{Buffer("identity"), CompressionType::NO_COMPRESSION},
|
{Buffer("identity"), CompressionType::NO_COMPRESSION},
|
||||||
@@ -177,37 +178,70 @@ getActivetenantAndProfile(const string &str, const string &deli = ",")
|
|||||||
}
|
}
|
||||||
|
|
||||||
Maybe<vector<HttpHeader>>
|
Maybe<vector<HttpHeader>>
|
||||||
NginxParser::parseRequestHeaders(const Buffer &data)
|
NginxParser::parseRequestHeaders(const Buffer &data, const unordered_set<string> &ignored_headers)
|
||||||
{
|
{
|
||||||
auto parsed_headers = genHeaders(data);
|
auto maybe_parsed_headers = genHeaders(data);
|
||||||
if (!parsed_headers.ok()) return parsed_headers.passErr();
|
if (!maybe_parsed_headers.ok()) return maybe_parsed_headers.passErr();
|
||||||
|
|
||||||
auto i_transaction_table = Singleton::Consume<I_TableSpecific<SessionID>>::by<NginxAttachment>();
|
auto i_transaction_table = Singleton::Consume<I_TableSpecific<SessionID>>::by<NginxAttachment>();
|
||||||
|
auto parsed_headers = maybe_parsed_headers.unpack();
|
||||||
|
NginxAttachmentOpaque &opaque = i_transaction_table->getState<NginxAttachmentOpaque>();
|
||||||
|
|
||||||
for (const HttpHeader &header : *parsed_headers) {
|
if (is_keep_alive_ctx || !ignored_headers.empty()) {
|
||||||
|
bool is_last_header_removed = false;
|
||||||
|
parsed_headers.erase(
|
||||||
|
remove_if(
|
||||||
|
parsed_headers.begin(),
|
||||||
|
parsed_headers.end(),
|
||||||
|
[&opaque, &is_last_header_removed, &ignored_headers](const HttpHeader &header)
|
||||||
|
{
|
||||||
|
string hdr_key = static_cast<string>(header.getKey());
|
||||||
|
string hdr_val = static_cast<string>(header.getValue());
|
||||||
|
if (
|
||||||
|
opaque.setKeepAliveCtx(hdr_key, hdr_val)
|
||||||
|
|| ignored_headers.find(hdr_key) != ignored_headers.end()
|
||||||
|
) {
|
||||||
|
dbgTrace(D_NGINX_ATTACHMENT_PARSER) << "Header was removed from headers list: " << hdr_key;
|
||||||
|
if (header.isLastHeader()) {
|
||||||
|
dbgTrace(D_NGINX_ATTACHMENT_PARSER) << "Last header was removed from headers list";
|
||||||
|
is_last_header_removed = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
),
|
||||||
|
parsed_headers.end()
|
||||||
|
);
|
||||||
|
if (is_last_header_removed) {
|
||||||
|
dbgTrace(D_NGINX_ATTACHMENT_PARSER) << "Adjusting last header flag";
|
||||||
|
if (!parsed_headers.empty()) parsed_headers.back().setIsLastHeader();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const HttpHeader &header : parsed_headers) {
|
||||||
auto source_identifiers = getConfigurationWithDefault<UsersAllIdentifiersConfig>(
|
auto source_identifiers = getConfigurationWithDefault<UsersAllIdentifiersConfig>(
|
||||||
UsersAllIdentifiersConfig(),
|
UsersAllIdentifiersConfig(),
|
||||||
"rulebase",
|
"rulebase",
|
||||||
"usersIdentifiers"
|
"usersIdentifiers"
|
||||||
);
|
);
|
||||||
source_identifiers.parseRequestHeaders(header);
|
source_identifiers.parseRequestHeaders(header);
|
||||||
|
|
||||||
NginxAttachmentOpaque &opaque = i_transaction_table->getState<NginxAttachmentOpaque>();
|
|
||||||
opaque.addToSavedData(
|
opaque.addToSavedData(
|
||||||
HttpTransactionData::req_headers,
|
HttpTransactionData::req_headers,
|
||||||
static_cast<string>(header.getKey()) + ": " + static_cast<string>(header.getValue()) + "\r\n"
|
static_cast<string>(header.getKey()) + ": " + static_cast<string>(header.getValue()) + "\r\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
if (NginxParser::tenant_header_key == header.getKey()) {
|
const auto &header_key = header.getKey();
|
||||||
|
if (NginxParser::tenant_header_key == header_key) {
|
||||||
dbgDebug(D_NGINX_ATTACHMENT_PARSER)
|
dbgDebug(D_NGINX_ATTACHMENT_PARSER)
|
||||||
<< "Identified active tenant header. Key: "
|
<< "Identified active tenant header. Key: "
|
||||||
<< dumpHex(header.getKey())
|
<< dumpHex(header_key)
|
||||||
<< ", Value: "
|
<< ", Value: "
|
||||||
<< dumpHex(header.getValue());
|
<< dumpHex(header.getValue());
|
||||||
|
|
||||||
auto active_tenant_and_profile = getActivetenantAndProfile(header.getValue());
|
auto active_tenant_and_profile = getActivetenantAndProfile(header.getValue());
|
||||||
opaque.setSessionTenantAndProfile(active_tenant_and_profile[0], active_tenant_and_profile[1]);
|
opaque.setSessionTenantAndProfile(active_tenant_and_profile[0], active_tenant_and_profile[1]);
|
||||||
} else if (proxy_ip_header_key == header.getKey()) {
|
} else if (proxy_ip_header_key == header_key) {
|
||||||
source_identifiers.setXFFValuesToOpaqueCtx(header, UsersAllIdentifiersConfig::ExtractType::PROXYIP);
|
source_identifiers.setXFFValuesToOpaqueCtx(header, UsersAllIdentifiersConfig::ExtractType::PROXYIP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -345,12 +379,15 @@ NginxParser::parseResponseBody(const Buffer &raw_response_body, CompressionStrea
|
|||||||
Maybe<CompressionType>
|
Maybe<CompressionType>
|
||||||
NginxParser::parseContentEncoding(const vector<HttpHeader> &headers)
|
NginxParser::parseContentEncoding(const vector<HttpHeader> &headers)
|
||||||
{
|
{
|
||||||
static const Buffer content_encoding_header_key("Content-Encoding");
|
dbgFlow(D_NGINX_ATTACHMENT_PARSER) << "Parsing \"Content-Encoding\" header";
|
||||||
|
static const Buffer content_encoding_header_key("content-encoding");
|
||||||
|
|
||||||
auto it = find_if(
|
auto it = find_if(
|
||||||
headers.begin(),
|
headers.begin(),
|
||||||
headers.end(),
|
headers.end(),
|
||||||
[&] (const HttpHeader &http_header) { return http_header.getKey() == content_encoding_header_key; }
|
[&] (const HttpHeader &http_header) {
|
||||||
|
return http_header.getKey().isEqualLowerCase(content_encoding_header_key);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
if (it == headers.end()) {
|
if (it == headers.end()) {
|
||||||
dbgTrace(D_NGINX_ATTACHMENT_PARSER)
|
dbgTrace(D_NGINX_ATTACHMENT_PARSER)
|
||||||
|
|||||||
@@ -28,7 +28,10 @@ public:
|
|||||||
static Maybe<HttpTransactionData> parseStartTrasaction(const Buffer &data);
|
static Maybe<HttpTransactionData> parseStartTrasaction(const Buffer &data);
|
||||||
static Maybe<ResponseCode> parseResponseCode(const Buffer &data);
|
static Maybe<ResponseCode> parseResponseCode(const Buffer &data);
|
||||||
static Maybe<uint64_t> parseContentLength(const Buffer &data);
|
static Maybe<uint64_t> parseContentLength(const Buffer &data);
|
||||||
static Maybe<std::vector<HttpHeader>> parseRequestHeaders(const Buffer &data);
|
static Maybe<std::vector<HttpHeader>> parseRequestHeaders(
|
||||||
|
const Buffer &data,
|
||||||
|
const std::unordered_set<std::string> &ignored_headers
|
||||||
|
);
|
||||||
static Maybe<std::vector<HttpHeader>> parseResponseHeaders(const Buffer &data);
|
static Maybe<std::vector<HttpHeader>> parseResponseHeaders(const Buffer &data);
|
||||||
static Maybe<HttpBody> parseRequestBody(const Buffer &data);
|
static Maybe<HttpBody> parseRequestBody(const Buffer &data);
|
||||||
static Maybe<HttpBody> parseResponseBody(const Buffer &raw_response_body, CompressionStream *compression_stream);
|
static Maybe<HttpBody> parseResponseBody(const Buffer &raw_response_body, CompressionStream *compression_stream);
|
||||||
|
|||||||
@@ -285,17 +285,21 @@ Maybe<string>
|
|||||||
UsersAllIdentifiersConfig::parseXForwardedFor(const string &str, ExtractType type) const
|
UsersAllIdentifiersConfig::parseXForwardedFor(const string &str, ExtractType type) const
|
||||||
{
|
{
|
||||||
vector<string> header_values = split(str);
|
vector<string> header_values = split(str);
|
||||||
|
|
||||||
if (header_values.empty()) return genError("No IP found in the xff header list");
|
if (header_values.empty()) return genError("No IP found in the xff header list");
|
||||||
|
|
||||||
vector<string> xff_values = getHeaderValuesFromConfig("x-forwarded-for");
|
vector<string> xff_values = getHeaderValuesFromConfig("x-forwarded-for");
|
||||||
vector<CIDRSData> cidr_values(xff_values.begin(), xff_values.end());
|
vector<CIDRSData> cidr_values(xff_values.begin(), xff_values.end());
|
||||||
|
string last_valid_ip;
|
||||||
|
|
||||||
for (auto it = header_values.rbegin(); it != header_values.rend() - 1; ++it) {
|
for (auto it = header_values.rbegin(); it != header_values.rend() - 1; ++it) {
|
||||||
if (!IPAddr::createIPAddr(*it).ok()) {
|
if (!IPAddr::createIPAddr(*it).ok()) {
|
||||||
dbgWarning(D_NGINX_ATTACHMENT_PARSER) << "Invalid IP address found in the xff header IPs list: " << *it;
|
dbgWarning(D_NGINX_ATTACHMENT_PARSER) << "Invalid IP address found in the xff header IPs list: " << *it;
|
||||||
return genError("Invalid IP address");
|
if (last_valid_ip.empty()) {
|
||||||
|
return genError("Invalid IP address");
|
||||||
|
}
|
||||||
|
return last_valid_ip;
|
||||||
}
|
}
|
||||||
|
last_valid_ip = *it;
|
||||||
if (type == ExtractType::PROXYIP) continue;
|
if (type == ExtractType::PROXYIP) continue;
|
||||||
if (!isIpTrusted(*it, cidr_values)) {
|
if (!isIpTrusted(*it, cidr_values)) {
|
||||||
dbgDebug(D_NGINX_ATTACHMENT_PARSER) << "Found untrusted IP in the xff header IPs list: " << *it;
|
dbgDebug(D_NGINX_ATTACHMENT_PARSER) << "Found untrusted IP in the xff header IPs list: " << *it;
|
||||||
@@ -307,7 +311,10 @@ UsersAllIdentifiersConfig::parseXForwardedFor(const string &str, ExtractType typ
|
|||||||
dbgWarning(D_NGINX_ATTACHMENT_PARSER)
|
dbgWarning(D_NGINX_ATTACHMENT_PARSER)
|
||||||
<< "Invalid IP address found in the xff header IPs list: "
|
<< "Invalid IP address found in the xff header IPs list: "
|
||||||
<< header_values[0];
|
<< header_values[0];
|
||||||
return genError("Invalid IP address");
|
if (last_valid_ip.empty()) {
|
||||||
|
return genError("No Valid Ip address was found");
|
||||||
|
}
|
||||||
|
return last_valid_ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
return header_values[0];
|
return header_values[0];
|
||||||
@@ -359,6 +366,24 @@ UsersAllIdentifiersConfig::setCustomHeaderToOpaqueCtx(const HttpHeader &header)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UsersAllIdentifiersConfig::setWafTagValuesToOpaqueCtx(const HttpHeader &header) const
|
||||||
|
{
|
||||||
|
auto i_transaction_table = Singleton::Consume<I_TableSpecific<SessionID>>::by<NginxAttachment>();
|
||||||
|
if (!i_transaction_table || !i_transaction_table->hasState<NginxAttachmentOpaque>()) {
|
||||||
|
dbgDebug(D_NGINX_ATTACHMENT_PARSER) << "Can't get the transaction table";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NginxAttachmentOpaque &opaque = i_transaction_table->getState<NginxAttachmentOpaque>();
|
||||||
|
opaque.setSavedData(HttpTransactionData::waf_tag_ctx, static_cast<string>(header.getValue()));
|
||||||
|
|
||||||
|
dbgDebug(D_NGINX_ATTACHMENT_PARSER)
|
||||||
|
<< "Added waf tag to context: "
|
||||||
|
<< static_cast<string>(header.getValue());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Maybe<string>
|
Maybe<string>
|
||||||
UsersAllIdentifiersConfig::parseCookieElement(
|
UsersAllIdentifiersConfig::parseCookieElement(
|
||||||
const string::const_iterator &start,
|
const string::const_iterator &start,
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ private:
|
|||||||
if (temp_params_list.size() == 1) {
|
if (temp_params_list.size() == 1) {
|
||||||
Maybe<IPAddr> maybe_ip = IPAddr::createIPAddr(temp_params_list[0]);
|
Maybe<IPAddr> maybe_ip = IPAddr::createIPAddr(temp_params_list[0]);
|
||||||
if (!maybe_ip.ok()) return genError("Could not create IP address, " + maybe_ip.getErr());
|
if (!maybe_ip.ok()) return genError("Could not create IP address, " + maybe_ip.getErr());
|
||||||
IpAddress addr = move(ConvertToIpAddress(maybe_ip.unpackMove()));
|
IpAddress addr = ConvertToIpAddress(maybe_ip.unpackMove());
|
||||||
|
|
||||||
return move(IPRange{.start = addr, .end = addr});
|
return move(IPRange{.start = addr, .end = addr});
|
||||||
}
|
}
|
||||||
@@ -157,11 +157,11 @@ private:
|
|||||||
IPAddr max_addr = maybe_ip_max.unpackMove();
|
IPAddr max_addr = maybe_ip_max.unpackMove();
|
||||||
if (min_addr > max_addr) return genError("Could not create ip range - start greater then end");
|
if (min_addr > max_addr) return genError("Could not create ip range - start greater then end");
|
||||||
|
|
||||||
IpAddress addr_min = move(ConvertToIpAddress(move(min_addr)));
|
IpAddress addr_min = ConvertToIpAddress(move(min_addr));
|
||||||
IpAddress addr_max = move(ConvertToIpAddress(move(max_addr)));
|
IpAddress addr_max = ConvertToIpAddress(move(max_addr));
|
||||||
if (addr_max.ip_type != addr_min.ip_type) return genError("Range IP's type does not match");
|
if (addr_max.ip_type != addr_min.ip_type) return genError("Range IP's type does not match");
|
||||||
|
|
||||||
return move(IPRange{.start = move(addr_min), .end = move(addr_max)});
|
return IPRange{.start = move(addr_min), .end = move(addr_max)};
|
||||||
}
|
}
|
||||||
|
|
||||||
return genError("Illegal range received: " + range);
|
return genError("Illegal range received: " + range);
|
||||||
|
|||||||
@@ -15,18 +15,14 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <climits>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <boost/range/iterator_range.hpp>
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "table_opaque.h"
|
|
||||||
#include "http_manager_opaque.h"
|
#include "http_manager_opaque.h"
|
||||||
#include "log_generator.h"
|
#include "log_generator.h"
|
||||||
#include "http_inspection_events.h"
|
#include "http_inspection_events.h"
|
||||||
@@ -41,6 +37,7 @@ operator<<(ostream &os, const EventVerdict &event)
|
|||||||
{
|
{
|
||||||
switch (event.getVerdict()) {
|
switch (event.getVerdict()) {
|
||||||
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT: return os << "Inspect";
|
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT: return os << "Inspect";
|
||||||
|
case ngx_http_cp_verdict_e::LIMIT_RESPONSE_HEADERS: return os << "Limit Response Headers";
|
||||||
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_ACCEPT: return os << "Accept";
|
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_ACCEPT: return os << "Accept";
|
||||||
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP: return os << "Drop";
|
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP: return os << "Drop";
|
||||||
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INJECT: return os << "Inject";
|
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INJECT: return os << "Inject";
|
||||||
@@ -69,22 +66,6 @@ public:
|
|||||||
i_transaction_table = Singleton::Consume<I_Table>::by<HttpManager>();
|
i_transaction_table = Singleton::Consume<I_Table>::by<HttpManager>();
|
||||||
|
|
||||||
Singleton::Consume<I_Logging>::by<HttpManager>()->addGeneralModifier(compressAppSecLogs);
|
Singleton::Consume<I_Logging>::by<HttpManager>()->addGeneralModifier(compressAppSecLogs);
|
||||||
|
|
||||||
const char* ignored_headers_env = getenv("SAAS_IGNORED_UPSTREAM_HEADERS");
|
|
||||||
if (ignored_headers_env) {
|
|
||||||
string ignored_headers_str = ignored_headers_env;
|
|
||||||
ignored_headers_str = NGEN::Strings::removeTrailingWhitespaces(ignored_headers_str);
|
|
||||||
|
|
||||||
if (!ignored_headers_str.empty()) {
|
|
||||||
dbgInfo(D_HTTP_MANAGER)
|
|
||||||
<< "Ignoring SAAS_IGNORED_UPSTREAM_HEADERS environment variable: "
|
|
||||||
<< ignored_headers_str;
|
|
||||||
|
|
||||||
vector<string> ignored_headers_vec;
|
|
||||||
boost::split(ignored_headers_vec, ignored_headers_str, boost::is_any_of(";"));
|
|
||||||
for (const string &header : ignored_headers_vec) ignored_headers.insert(header);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FilterVerdict
|
FilterVerdict
|
||||||
@@ -109,24 +90,18 @@ public:
|
|||||||
return FilterVerdict(default_verdict);
|
return FilterVerdict(default_verdict);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_request && ignored_headers.find(static_cast<string>(event.getKey())) != ignored_headers.end()) {
|
|
||||||
dbgTrace(D_HTTP_MANAGER)
|
|
||||||
<< "Ignoring header key - "
|
|
||||||
<< static_cast<string>(event.getKey())
|
|
||||||
<< " - as it is in the ignored headers list";
|
|
||||||
return FilterVerdict(ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT);
|
|
||||||
}
|
|
||||||
|
|
||||||
ScopedContext ctx;
|
ScopedContext ctx;
|
||||||
ctx.registerValue(app_sec_marker_key, i_transaction_table->keyToString(), EnvKeyAttr::LogSection::MARKER);
|
ctx.registerValue(app_sec_marker_key, i_transaction_table->keyToString(), EnvKeyAttr::LogSection::MARKER);
|
||||||
|
|
||||||
HttpManagerOpaque &state = i_transaction_table->getState<HttpManagerOpaque>();
|
HttpManagerOpaque &state = i_transaction_table->getState<HttpManagerOpaque>();
|
||||||
string event_key = static_cast<string>(event.getKey());
|
|
||||||
if (event_key == getProfileAgentSettingWithDefault<string>("", "agent.customHeaderValueLogging")) {
|
const auto &custom_header = getProfileAgentSettingWithDefault<string>("", "agent.customHeaderValueLogging");
|
||||||
|
|
||||||
|
if (event.getKey().isEqualLowerCase(custom_header)) {
|
||||||
string event_value = static_cast<string>(event.getValue());
|
string event_value = static_cast<string>(event.getValue());
|
||||||
dbgTrace(D_HTTP_MANAGER)
|
dbgTrace(D_HTTP_MANAGER)
|
||||||
<< "Found header key and value - ("
|
<< "Found header key and value - ("
|
||||||
<< event_key
|
<< custom_header
|
||||||
<< ": "
|
<< ": "
|
||||||
<< event_value
|
<< event_value
|
||||||
<< ") that matched agent settings";
|
<< ") that matched agent settings";
|
||||||
@@ -222,7 +197,6 @@ public:
|
|||||||
if (state.getUserDefinedValue().ok()) {
|
if (state.getUserDefinedValue().ok()) {
|
||||||
ctx.registerValue("UserDefined", state.getUserDefinedValue().unpack(), EnvKeyAttr::LogSection::DATA);
|
ctx.registerValue("UserDefined", state.getUserDefinedValue().unpack(), EnvKeyAttr::LogSection::DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
return handleEvent(EndRequestEvent().performNamedQuery());
|
return handleEvent(EndRequestEvent().performNamedQuery());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,8 +324,9 @@ private:
|
|||||||
<< respond.second.getVerdict();
|
<< respond.second.getVerdict();
|
||||||
|
|
||||||
state.setApplicationVerdict(respond.first, respond.second.getVerdict());
|
state.setApplicationVerdict(respond.first, respond.second.getVerdict());
|
||||||
|
state.setApplicationWebResponse(respond.first, respond.second.getWebUserResponseByPractice());
|
||||||
}
|
}
|
||||||
FilterVerdict aggregated_verdict = state.getCurrVerdict();
|
FilterVerdict aggregated_verdict(state.getCurrVerdict(), state.getCurrWebUserResponse());
|
||||||
if (aggregated_verdict.getVerdict() == ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP) {
|
if (aggregated_verdict.getVerdict() == ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP) {
|
||||||
SecurityAppsDropEvent(state.getCurrentDropVerdictCausers()).notify();
|
SecurityAppsDropEvent(state.getCurrentDropVerdictCausers()).notify();
|
||||||
}
|
}
|
||||||
@@ -421,7 +396,6 @@ private:
|
|||||||
I_Table *i_transaction_table;
|
I_Table *i_transaction_table;
|
||||||
static const ngx_http_cp_verdict_e default_verdict;
|
static const ngx_http_cp_verdict_e default_verdict;
|
||||||
static const string app_sec_marker_key;
|
static const string app_sec_marker_key;
|
||||||
unordered_set<string> ignored_headers;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const ngx_http_cp_verdict_e HttpManager::Impl::default_verdict(ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP);
|
const ngx_http_cp_verdict_e HttpManager::Impl::default_verdict(ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP);
|
||||||
|
|||||||
@@ -32,6 +32,13 @@ HttpManagerOpaque::setApplicationVerdict(const string &app_name, ngx_http_cp_ver
|
|||||||
applications_verdicts[app_name] = verdict;
|
applications_verdicts[app_name] = verdict;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HttpManagerOpaque::setApplicationWebResponse(const string &app_name, string web_user_response_id)
|
||||||
|
{
|
||||||
|
dbgTrace(D_HTTP_MANAGER) << "Security app: " << app_name << ", has web user response: " << web_user_response_id;
|
||||||
|
applications_web_user_response[app_name] = web_user_response_id;
|
||||||
|
}
|
||||||
|
|
||||||
ngx_http_cp_verdict_e
|
ngx_http_cp_verdict_e
|
||||||
HttpManagerOpaque::getApplicationsVerdict(const string &app_name) const
|
HttpManagerOpaque::getApplicationsVerdict(const string &app_name) const
|
||||||
{
|
{
|
||||||
@@ -51,8 +58,12 @@ HttpManagerOpaque::getCurrVerdict() const
|
|||||||
for (const auto &app_verdic_pair : applications_verdicts) {
|
for (const auto &app_verdic_pair : applications_verdicts) {
|
||||||
switch (app_verdic_pair.second) {
|
switch (app_verdic_pair.second) {
|
||||||
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP:
|
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP:
|
||||||
|
dbgTrace(D_HTTP_MANAGER) << "Verdict DROP for app: " << app_verdic_pair.first;
|
||||||
|
current_web_user_response = applications_web_user_response.at(app_verdic_pair.first);
|
||||||
|
dbgTrace(D_HTTP_MANAGER) << "current_web_user_response=" << current_web_user_response;
|
||||||
return app_verdic_pair.second;
|
return app_verdic_pair.second;
|
||||||
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INJECT:
|
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INJECT:
|
||||||
|
// Sent in ResponseHeaders and ResponseBody.
|
||||||
verdict = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INJECT;
|
verdict = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INJECT;
|
||||||
break;
|
break;
|
||||||
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_ACCEPT:
|
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_ACCEPT:
|
||||||
@@ -60,11 +71,16 @@ HttpManagerOpaque::getCurrVerdict() const
|
|||||||
break;
|
break;
|
||||||
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT:
|
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT:
|
||||||
break;
|
break;
|
||||||
|
case ngx_http_cp_verdict_e::LIMIT_RESPONSE_HEADERS:
|
||||||
|
// Sent in End Request.
|
||||||
|
verdict = ngx_http_cp_verdict_e::LIMIT_RESPONSE_HEADERS;
|
||||||
|
break;
|
||||||
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_IRRELEVANT:
|
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_IRRELEVANT:
|
||||||
dbgTrace(D_HTTP_MANAGER) << "Verdict 'Irrelevant' is not yet supported. Returning Accept";
|
dbgTrace(D_HTTP_MANAGER) << "Verdict 'Irrelevant' is not yet supported. Returning Accept";
|
||||||
accepted_apps++;
|
accepted_apps++;
|
||||||
break;
|
break;
|
||||||
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_WAIT:
|
case ngx_http_cp_verdict_e::TRAFFIC_VERDICT_WAIT:
|
||||||
|
// Sent in Request Headers and Request Body.
|
||||||
verdict = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_WAIT;
|
verdict = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_WAIT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -28,10 +28,12 @@ public:
|
|||||||
HttpManagerOpaque();
|
HttpManagerOpaque();
|
||||||
|
|
||||||
void setApplicationVerdict(const std::string &app_name, ngx_http_cp_verdict_e verdict);
|
void setApplicationVerdict(const std::string &app_name, ngx_http_cp_verdict_e verdict);
|
||||||
|
void setApplicationWebResponse(const std::string &app_name, std::string web_user_response_id);
|
||||||
ngx_http_cp_verdict_e getApplicationsVerdict(const std::string &app_name) const;
|
ngx_http_cp_verdict_e getApplicationsVerdict(const std::string &app_name) const;
|
||||||
void setManagerVerdict(ngx_http_cp_verdict_e verdict) { manager_verdict = verdict; }
|
void setManagerVerdict(ngx_http_cp_verdict_e verdict) { manager_verdict = verdict; }
|
||||||
ngx_http_cp_verdict_e getManagerVerdict() const { return manager_verdict; }
|
ngx_http_cp_verdict_e getManagerVerdict() const { return manager_verdict; }
|
||||||
ngx_http_cp_verdict_e getCurrVerdict() const;
|
ngx_http_cp_verdict_e getCurrVerdict() const;
|
||||||
|
const std::string & getCurrWebUserResponse() const { return current_web_user_response; };
|
||||||
std::set<std::string> getCurrentDropVerdictCausers() const;
|
std::set<std::string> getCurrentDropVerdictCausers() const;
|
||||||
void saveCurrentDataToCache(const Buffer &full_data);
|
void saveCurrentDataToCache(const Buffer &full_data);
|
||||||
void setUserDefinedValue(const std::string &value) { user_defined_value = value; }
|
void setUserDefinedValue(const std::string &value) { user_defined_value = value; }
|
||||||
@@ -52,6 +54,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string, ngx_http_cp_verdict_e> applications_verdicts;
|
std::unordered_map<std::string, ngx_http_cp_verdict_e> applications_verdicts;
|
||||||
|
std::unordered_map<std::string, std::string> applications_web_user_response;
|
||||||
|
mutable std::string current_web_user_response;
|
||||||
ngx_http_cp_verdict_e manager_verdict = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT;
|
ngx_http_cp_verdict_e manager_verdict = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT;
|
||||||
Buffer prev_data_cache;
|
Buffer prev_data_cache;
|
||||||
uint aggregated_payload_size = 0;
|
uint aggregated_payload_size = 0;
|
||||||
|
|||||||
@@ -45,6 +45,19 @@ private:
|
|||||||
std::string host;
|
std::string host;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class EqualWafTag : public EnvironmentEvaluator<bool>, Singleton::Consume<I_Environment>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EqualWafTag(const std::vector<std::string> ¶ms);
|
||||||
|
|
||||||
|
static std::string getName() { return "EqualWafTag"; }
|
||||||
|
|
||||||
|
Maybe<bool, Context::Error> evalVariable() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string waf_tag;
|
||||||
|
};
|
||||||
|
|
||||||
class EqualListeningIP : public EnvironmentEvaluator<bool>, Singleton::Consume<I_Environment>
|
class EqualListeningIP : public EnvironmentEvaluator<bool>, Singleton::Consume<I_Environment>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -317,12 +317,12 @@ public:
|
|||||||
{
|
{
|
||||||
return url_for_cef;
|
return url_for_cef;
|
||||||
}
|
}
|
||||||
|
Flags<ReportIS::StreamType> getStreams(SecurityType security_type, bool is_action_drop_or_prevent) const;
|
||||||
|
Flags<ReportIS::Enreachments> getEnrechments(SecurityType security_type) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ReportIS::Severity getSeverity(bool is_action_drop_or_prevent) const;
|
ReportIS::Severity getSeverity(bool is_action_drop_or_prevent) const;
|
||||||
ReportIS::Priority getPriority(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;
|
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string verbosity;
|
std::string verbosity;
|
||||||
@@ -339,4 +339,32 @@ private:
|
|||||||
bool should_format_output = false;
|
bool should_format_output = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ReportTriggerConf
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// \brief Default constructor for ReportTriggerConf.
|
||||||
|
ReportTriggerConf() {}
|
||||||
|
|
||||||
|
/// \brief Preload function to register expected configuration.
|
||||||
|
static void
|
||||||
|
preload()
|
||||||
|
{
|
||||||
|
registerExpectedConfiguration<ReportTriggerConf>("rulebase", "report");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Load function to deserialize configuration from JSONInputArchive.
|
||||||
|
/// \param archive_in The JSON input archive.
|
||||||
|
void load(cereal::JSONInputArchive &archive_in);
|
||||||
|
|
||||||
|
/// \brief Get the name.
|
||||||
|
/// \return The name.
|
||||||
|
const std::string &
|
||||||
|
getName() const
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
#endif //__TRIGGERS_CONFIG_H__
|
#endif //__TRIGGERS_CONFIG_H__
|
||||||
|
|||||||
@@ -27,9 +27,18 @@ public:
|
|||||||
verdict(_verdict)
|
verdict(_verdict)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
FilterVerdict(
|
||||||
|
ngx_http_cp_verdict_e _verdict,
|
||||||
|
const std::string &_web_reponse_id)
|
||||||
|
:
|
||||||
|
verdict(_verdict),
|
||||||
|
web_user_response_id(_web_reponse_id)
|
||||||
|
{}
|
||||||
|
|
||||||
FilterVerdict(const EventVerdict &_verdict, ModifiedChunkIndex _event_idx = -1)
|
FilterVerdict(const EventVerdict &_verdict, ModifiedChunkIndex _event_idx = -1)
|
||||||
:
|
:
|
||||||
verdict(_verdict.getVerdict())
|
verdict(_verdict.getVerdict()),
|
||||||
|
web_user_response_id(_verdict.getWebUserResponseByPractice())
|
||||||
{
|
{
|
||||||
if (verdict == ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INJECT) {
|
if (verdict == ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INJECT) {
|
||||||
addModifications(_verdict.getModifications(), _event_idx);
|
addModifications(_verdict.getModifications(), _event_idx);
|
||||||
@@ -59,10 +68,12 @@ public:
|
|||||||
uint getModificationsAmount() const { return total_modifications; }
|
uint getModificationsAmount() const { return total_modifications; }
|
||||||
ngx_http_cp_verdict_e getVerdict() const { return verdict; }
|
ngx_http_cp_verdict_e getVerdict() const { return verdict; }
|
||||||
const std::vector<EventModifications> & getModifications() const { return modifications; }
|
const std::vector<EventModifications> & getModifications() const { return modifications; }
|
||||||
|
const std::string getWebUserResponseID() const { return web_user_response_id; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ngx_http_cp_verdict_e verdict = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT;
|
ngx_http_cp_verdict_e verdict = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT;
|
||||||
std::vector<EventModifications> modifications;
|
std::vector<EventModifications> modifications;
|
||||||
|
std::string web_user_response_id;
|
||||||
uint total_modifications = 0;
|
uint total_modifications = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -239,6 +239,7 @@ public:
|
|||||||
const Buffer & getValue() const { return value; }
|
const Buffer & getValue() const { return value; }
|
||||||
|
|
||||||
bool isLastHeader() const { return is_last_header; }
|
bool isLastHeader() const { return is_last_header; }
|
||||||
|
void setIsLastHeader() { is_last_header = true; }
|
||||||
uint8_t getHeaderIndex() const { return header_index; }
|
uint8_t getHeaderIndex() const { return header_index; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -375,16 +376,31 @@ public:
|
|||||||
verdict(event_verdict)
|
verdict(event_verdict)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
EventVerdict(
|
||||||
|
const ModificationList &mods,
|
||||||
|
ngx_http_cp_verdict_e event_verdict,
|
||||||
|
std::string response_id) :
|
||||||
|
modifications(mods),
|
||||||
|
verdict(event_verdict),
|
||||||
|
webUserResponseByPractice(response_id)
|
||||||
|
{}
|
||||||
|
|
||||||
// LCOV_EXCL_START - sync functions, can only be tested once the sync module exists
|
// LCOV_EXCL_START - sync functions, can only be tested once the sync module exists
|
||||||
template <typename T> void serialize(T &ar, uint) { ar(verdict); }
|
template <typename T> void serialize(T &ar, uint) { ar(verdict); }
|
||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
|
|
||||||
const ModificationList & getModifications() const { return modifications; }
|
const ModificationList & getModifications() const { return modifications; }
|
||||||
ngx_http_cp_verdict_e getVerdict() const { return verdict; }
|
ngx_http_cp_verdict_e getVerdict() const { return verdict; }
|
||||||
|
const std::string getWebUserResponseByPractice() const { return webUserResponseByPractice; }
|
||||||
|
void setWebUserResponseByPractice(const std::string id) {
|
||||||
|
dbgTrace(D_HTTP_MANAGER) << "current verdict web user response set to: " << id;
|
||||||
|
webUserResponseByPractice = id;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ModificationList modifications;
|
ModificationList modifications;
|
||||||
ngx_http_cp_verdict_e verdict = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT;
|
ngx_http_cp_verdict_e verdict = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT;
|
||||||
|
std::string webUserResponseByPractice;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __I_HTTP_EVENT_IMPL_H__
|
#endif // __I_HTTP_EVENT_IMPL_H__
|
||||||
|
|||||||
@@ -72,7 +72,8 @@ public:
|
|||||||
parsed_uri,
|
parsed_uri,
|
||||||
client_ip,
|
client_ip,
|
||||||
client_port,
|
client_port,
|
||||||
response_content_encoding
|
response_content_encoding,
|
||||||
|
waf_tag
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +92,8 @@ public:
|
|||||||
parsed_uri,
|
parsed_uri,
|
||||||
client_ip,
|
client_ip,
|
||||||
client_port,
|
client_port,
|
||||||
response_content_encoding
|
response_content_encoding,
|
||||||
|
waf_tag
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
@@ -122,6 +124,9 @@ public:
|
|||||||
response_content_encoding = _response_content_encoding;
|
response_content_encoding = _response_content_encoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string & getWafTag() const { return waf_tag; }
|
||||||
|
void setWafTag(const std::string &_waf_tag) { waf_tag = _waf_tag; }
|
||||||
|
|
||||||
static const std::string http_proto_ctx;
|
static const std::string http_proto_ctx;
|
||||||
static const std::string method_ctx;
|
static const std::string method_ctx;
|
||||||
static const std::string host_name_ctx;
|
static const std::string host_name_ctx;
|
||||||
@@ -137,6 +142,7 @@ public:
|
|||||||
static const std::string source_identifier;
|
static const std::string source_identifier;
|
||||||
static const std::string proxy_ip_ctx;
|
static const std::string proxy_ip_ctx;
|
||||||
static const std::string xff_vals_ctx;
|
static const std::string xff_vals_ctx;
|
||||||
|
static const std::string waf_tag_ctx;
|
||||||
|
|
||||||
static const CompressionType default_response_content_encoding;
|
static const CompressionType default_response_content_encoding;
|
||||||
|
|
||||||
@@ -153,6 +159,7 @@ private:
|
|||||||
uint16_t client_port;
|
uint16_t client_port;
|
||||||
bool is_request;
|
bool is_request;
|
||||||
CompressionType response_content_encoding;
|
CompressionType response_content_encoding;
|
||||||
|
std::string waf_tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __HTTP_TRANSACTION_DATA_H__
|
#endif // __HTTP_TRANSACTION_DATA_H__
|
||||||
|
|||||||
@@ -26,11 +26,12 @@ public:
|
|||||||
virtual Maybe<std::string> getArch() = 0;
|
virtual Maybe<std::string> getArch() = 0;
|
||||||
virtual std::string getAgentVersion() = 0;
|
virtual std::string getAgentVersion() = 0;
|
||||||
virtual bool isKernelVersion3OrHigher() = 0;
|
virtual bool isKernelVersion3OrHigher() = 0;
|
||||||
|
virtual bool isGw() = 0;
|
||||||
virtual bool isGwNotVsx() = 0;
|
virtual bool isGwNotVsx() = 0;
|
||||||
virtual bool isVersionAboveR8110() = 0;
|
virtual bool isVersionAboveR8110() = 0;
|
||||||
virtual bool isReverseProxy() = 0;
|
virtual bool isReverseProxy() = 0;
|
||||||
virtual bool isCloudStorageEnabled() = 0;
|
virtual bool isCloudStorageEnabled() = 0;
|
||||||
virtual Maybe<std::tuple<std::string, std::string, std::string>> parseNginxMetadata() = 0;
|
virtual Maybe<std::tuple<std::string, std::string, std::string, std::string>> parseNginxMetadata() = 0;
|
||||||
virtual Maybe<std::tuple<std::string, std::string, std::string, std::string, std::string>> readCloudMetadata() = 0;
|
virtual Maybe<std::tuple<std::string, std::string, std::string, std::string, std::string>> readCloudMetadata() = 0;
|
||||||
virtual std::map<std::string, std::string> getResolvedDetails() = 0;
|
virtual std::map<std::string, std::string> getResolvedDetails() = 0;
|
||||||
#if defined(gaia) || defined(smb)
|
#if defined(gaia) || defined(smb)
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ struct DecisionTelemetryData
|
|||||||
int responseCode;
|
int responseCode;
|
||||||
uint64_t elapsedTime;
|
uint64_t elapsedTime;
|
||||||
std::set<std::string> attackTypes;
|
std::set<std::string> attackTypes;
|
||||||
|
bool temperatureDetected;
|
||||||
|
|
||||||
DecisionTelemetryData() :
|
DecisionTelemetryData() :
|
||||||
blockType(NOT_BLOCKING),
|
blockType(NOT_BLOCKING),
|
||||||
@@ -38,7 +39,8 @@ struct DecisionTelemetryData
|
|||||||
method(POST),
|
method(POST),
|
||||||
responseCode(0),
|
responseCode(0),
|
||||||
elapsedTime(0),
|
elapsedTime(0),
|
||||||
attackTypes()
|
attackTypes(),
|
||||||
|
temperatureDetected(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "singleton.h"
|
#include "singleton.h"
|
||||||
#include "i_keywords_rule.h"
|
#include "i_keywords_rule.h"
|
||||||
#include "i_table.h"
|
#include "i_table.h"
|
||||||
|
#include "i_mainloop.h"
|
||||||
#include "i_http_manager.h"
|
#include "i_http_manager.h"
|
||||||
#include "i_environment.h"
|
#include "i_environment.h"
|
||||||
#include "http_inspection_events.h"
|
#include "http_inspection_events.h"
|
||||||
@@ -16,7 +17,8 @@ class IPSComp
|
|||||||
Singleton::Consume<I_KeywordsRule>,
|
Singleton::Consume<I_KeywordsRule>,
|
||||||
Singleton::Consume<I_Table>,
|
Singleton::Consume<I_Table>,
|
||||||
Singleton::Consume<I_Environment>,
|
Singleton::Consume<I_Environment>,
|
||||||
Singleton::Consume<I_GenericRulebase>
|
Singleton::Consume<I_GenericRulebase>,
|
||||||
|
Singleton::Consume<I_MainLoop>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
IPSComp();
|
IPSComp();
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Maybe<std::string> downloadPackage(const Package &package, bool is_clean_installation);
|
Maybe<std::string> downloadPackage(const Package &package, bool is_clean_installation);
|
||||||
|
std::string getCurrentTimestamp();
|
||||||
|
|
||||||
std::string manifest_file_path;
|
std::string manifest_file_path;
|
||||||
std::string temp_ext;
|
std::string temp_ext;
|
||||||
|
|||||||
30
components/include/prometheus_comp.h
Executable file
30
components/include/prometheus_comp.h
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
#ifndef __PROMETHEUS_COMP_H__
|
||||||
|
#define __PROMETHEUS_COMP_H__
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "component.h"
|
||||||
|
#include "singleton.h"
|
||||||
|
|
||||||
|
#include "i_rest_api.h"
|
||||||
|
#include "i_messaging.h"
|
||||||
|
#include "generic_metric.h"
|
||||||
|
|
||||||
|
class PrometheusComp
|
||||||
|
:
|
||||||
|
public Component,
|
||||||
|
Singleton::Consume<I_RestApi>,
|
||||||
|
Singleton::Consume<I_Messaging>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PrometheusComp();
|
||||||
|
~PrometheusComp();
|
||||||
|
|
||||||
|
void init() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Impl;
|
||||||
|
std::unique_ptr<Impl> pimpl;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __PROMETHEUS_COMP_H__
|
||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "generic_metric.h"
|
#include "generic_metric.h"
|
||||||
|
|
||||||
#define LOGGING_INTERVAL_IN_MINUTES 10
|
#define LOGGING_INTERVAL_IN_MINUTES 10
|
||||||
|
USE_DEBUG_FLAG(D_WAAP);
|
||||||
enum class AssetType { API, WEB, ALL, COUNT };
|
enum class AssetType { API, WEB, ALL, COUNT };
|
||||||
|
|
||||||
class WaapTelemetryEvent : public Event<WaapTelemetryEvent>
|
class WaapTelemetryEvent : public Event<WaapTelemetryEvent>
|
||||||
@@ -75,6 +76,20 @@ private:
|
|||||||
std::unordered_set<std::string> sources_seen;
|
std::unordered_set<std::string> sources_seen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WaapAdditionalTrafficTelemetrics : public WaapTelemetryBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void updateMetrics(const std::string &asset_id, const DecisionTelemetryData &data);
|
||||||
|
void initMetrics();
|
||||||
|
|
||||||
|
private:
|
||||||
|
MetricCalculations::Counter requests{this, "reservedNgenA"};
|
||||||
|
MetricCalculations::Counter sources{this, "reservedNgenB"};
|
||||||
|
MetricCalculations::Counter blocked{this, "reservedNgenC"};
|
||||||
|
MetricCalculations::Counter temperature_count{this, "reservedNgenD"};
|
||||||
|
std::unordered_set<std::string> sources_seen;
|
||||||
|
};
|
||||||
|
|
||||||
class WaapTrafficTelemetrics : public WaapTelemetryBase
|
class WaapTrafficTelemetrics : public WaapTelemetryBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -123,6 +138,7 @@ private:
|
|||||||
std::map<std::string, std::shared_ptr<WaapTrafficTelemetrics>> traffic_telemetries;
|
std::map<std::string, std::shared_ptr<WaapTrafficTelemetrics>> traffic_telemetries;
|
||||||
std::map<std::string, std::shared_ptr<WaapAttackTypesMetrics>> attack_types;
|
std::map<std::string, std::shared_ptr<WaapAttackTypesMetrics>> attack_types;
|
||||||
std::map<std::string, std::shared_ptr<WaapAttackTypesMetrics>> attack_types_telemetries;
|
std::map<std::string, std::shared_ptr<WaapAttackTypesMetrics>> attack_types_telemetries;
|
||||||
|
std::map<std::string, std::shared_ptr<WaapAdditionalTrafficTelemetrics>> additional_traffic_telemetries;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void initializeTelemetryData(
|
void initializeTelemetryData(
|
||||||
@@ -132,6 +148,7 @@ private:
|
|||||||
std::map<std::string, std::shared_ptr<T>>& telemetryMap
|
std::map<std::string, std::shared_ptr<T>>& telemetryMap
|
||||||
) {
|
) {
|
||||||
if (!telemetryMap.count(asset_id)) {
|
if (!telemetryMap.count(asset_id)) {
|
||||||
|
dbgTrace(D_WAAP) << "creating telemetry data for asset: " << data.assetName;
|
||||||
telemetryMap.emplace(asset_id, std::make_shared<T>());
|
telemetryMap.emplace(asset_id, std::make_shared<T>());
|
||||||
telemetryMap[asset_id]->init(
|
telemetryMap[asset_id]->init(
|
||||||
telemetryName,
|
telemetryName,
|
||||||
@@ -139,7 +156,9 @@ private:
|
|||||||
ReportIS::IssuingEngine::AGENT_CORE,
|
ReportIS::IssuingEngine::AGENT_CORE,
|
||||||
std::chrono::minutes(LOGGING_INTERVAL_IN_MINUTES),
|
std::chrono::minutes(LOGGING_INTERVAL_IN_MINUTES),
|
||||||
true,
|
true,
|
||||||
ReportIS::Audience::SECURITY
|
ReportIS::Audience::SECURITY,
|
||||||
|
false,
|
||||||
|
asset_id
|
||||||
);
|
);
|
||||||
|
|
||||||
telemetryMap[asset_id]->template registerContext<std::string>(
|
telemetryMap[asset_id]->template registerContext<std::string>(
|
||||||
@@ -152,29 +171,30 @@ private:
|
|||||||
std::string("Web Application"),
|
std::string("Web Application"),
|
||||||
EnvKeyAttr::LogSection::SOURCE
|
EnvKeyAttr::LogSection::SOURCE
|
||||||
);
|
);
|
||||||
telemetryMap[asset_id]->template registerContext<std::string>(
|
|
||||||
"assetId",
|
|
||||||
asset_id,
|
|
||||||
EnvKeyAttr::LogSection::SOURCE
|
|
||||||
);
|
|
||||||
telemetryMap[asset_id]->template registerContext<std::string>(
|
|
||||||
"assetName",
|
|
||||||
data.assetName,
|
|
||||||
EnvKeyAttr::LogSection::SOURCE
|
|
||||||
);
|
|
||||||
telemetryMap[asset_id]->template registerContext<std::string>(
|
|
||||||
"practiceId",
|
|
||||||
data.practiceId,
|
|
||||||
EnvKeyAttr::LogSection::SOURCE
|
|
||||||
);
|
|
||||||
telemetryMap[asset_id]->template registerContext<std::string>(
|
|
||||||
"practiceName",
|
|
||||||
data.practiceName,
|
|
||||||
EnvKeyAttr::LogSection::SOURCE
|
|
||||||
);
|
|
||||||
|
|
||||||
telemetryMap[asset_id]->registerListener();
|
telemetryMap[asset_id]->registerListener();
|
||||||
}
|
}
|
||||||
|
dbgTrace(D_WAAP) << "updating telemetry data for asset: " << data.assetName;
|
||||||
|
|
||||||
|
telemetryMap[asset_id]->template registerContext<std::string>(
|
||||||
|
"assetId",
|
||||||
|
asset_id,
|
||||||
|
EnvKeyAttr::LogSection::SOURCE
|
||||||
|
);
|
||||||
|
telemetryMap[asset_id]->template registerContext<std::string>(
|
||||||
|
"assetName",
|
||||||
|
data.assetName,
|
||||||
|
EnvKeyAttr::LogSection::SOURCE
|
||||||
|
);
|
||||||
|
telemetryMap[asset_id]->template registerContext<std::string>(
|
||||||
|
"practiceId",
|
||||||
|
data.practiceId,
|
||||||
|
EnvKeyAttr::LogSection::SOURCE
|
||||||
|
);
|
||||||
|
telemetryMap[asset_id]->template registerContext<std::string>(
|
||||||
|
"practiceName",
|
||||||
|
data.practiceName,
|
||||||
|
EnvKeyAttr::LogSection::SOURCE
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public:
|
|||||||
void parseRequestHeaders(const HttpHeader &header) const;
|
void parseRequestHeaders(const HttpHeader &header) const;
|
||||||
std::vector<std::string> getHeaderValuesFromConfig(const std::string &header_key) const;
|
std::vector<std::string> getHeaderValuesFromConfig(const std::string &header_key) const;
|
||||||
void setXFFValuesToOpaqueCtx(const HttpHeader &header, ExtractType type) const;
|
void setXFFValuesToOpaqueCtx(const HttpHeader &header, ExtractType type) const;
|
||||||
|
void setWafTagValuesToOpaqueCtx(const HttpHeader &header) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class UsersIdentifiersConfig
|
class UsersIdentifiersConfig
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class I_WaapAssetStatesManager;
|
|||||||
class I_Messaging;
|
class I_Messaging;
|
||||||
class I_AgentDetails;
|
class I_AgentDetails;
|
||||||
class I_Encryptor;
|
class I_Encryptor;
|
||||||
|
class I_WaapModelResultLogger;
|
||||||
|
|
||||||
const std::string WAAP_APPLICATION_NAME = "waap application";
|
const std::string WAAP_APPLICATION_NAME = "waap application";
|
||||||
|
|
||||||
@@ -50,7 +51,8 @@ class WaapComponent
|
|||||||
Singleton::Consume<I_AgentDetails>,
|
Singleton::Consume<I_AgentDetails>,
|
||||||
Singleton::Consume<I_Messaging>,
|
Singleton::Consume<I_Messaging>,
|
||||||
Singleton::Consume<I_Encryptor>,
|
Singleton::Consume<I_Encryptor>,
|
||||||
Singleton::Consume<I_Environment>
|
Singleton::Consume<I_Environment>,
|
||||||
|
Singleton::Consume<I_WaapModelResultLogger>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WaapComponent();
|
WaapComponent();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ add_subdirectory(ips)
|
|||||||
add_subdirectory(layer_7_access_control)
|
add_subdirectory(layer_7_access_control)
|
||||||
add_subdirectory(local_policy_mgmt_gen)
|
add_subdirectory(local_policy_mgmt_gen)
|
||||||
add_subdirectory(orchestration)
|
add_subdirectory(orchestration)
|
||||||
|
add_subdirectory(prometheus)
|
||||||
add_subdirectory(rate_limit)
|
add_subdirectory(rate_limit)
|
||||||
add_subdirectory(waap)
|
add_subdirectory(waap)
|
||||||
add_subdirectory(central_nginx_manager)
|
add_subdirectory(central_nginx_manager)
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ private:
|
|||||||
Maybe<void>
|
Maybe<void>
|
||||||
configureSyslog()
|
configureSyslog()
|
||||||
{
|
{
|
||||||
if (!getProfileAgentSettingWithDefault<bool>(true, "centralNginxManagement.syslogEnabled")) {
|
if (!getProfileAgentSettingWithDefault<bool>(false, "centralNginxManagement.syslogEnabled")) {
|
||||||
dbgTrace(D_NGINX_MANAGER) << "Syslog is disabled via settings";
|
dbgTrace(D_NGINX_MANAGER) << "Syslog is disabled via settings";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -331,6 +331,8 @@ public:
|
|||||||
logError("Could not reload central NGINX configuration. Error: " + reload_result.getErr());
|
logError("Could not reload central NGINX configuration. Error: " + reload_result.getErr());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logInfo("Central NGINX configuration has been successfully reloaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -351,11 +353,37 @@ private:
|
|||||||
{
|
{
|
||||||
LogGen log(
|
LogGen log(
|
||||||
error,
|
error,
|
||||||
|
ReportIS::Level::ACTION,
|
||||||
ReportIS::Audience::SECURITY,
|
ReportIS::Audience::SECURITY,
|
||||||
ReportIS::Severity::CRITICAL,
|
ReportIS::Severity::CRITICAL,
|
||||||
ReportIS::Priority::HIGH,
|
ReportIS::Priority::URGENT,
|
||||||
ReportIS::Tags::POLICY_INSTALLATION
|
ReportIS::Tags::POLICY_INSTALLATION
|
||||||
);
|
);
|
||||||
|
|
||||||
|
log.addToOrigin(LogField("eventTopic", "Central NGINX Management"));
|
||||||
|
log << LogField("notificationId", "4165c3b1-e9bc-44c3-888b-863e204c1bfb");
|
||||||
|
log << LogField(
|
||||||
|
"eventRemediation",
|
||||||
|
"Please verify your NGINX configuration and enforce policy again. "
|
||||||
|
"Contact Check Point support if the issue persists."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
logInfo(const string &info)
|
||||||
|
{
|
||||||
|
LogGen log(
|
||||||
|
info,
|
||||||
|
ReportIS::Level::ACTION,
|
||||||
|
ReportIS::Audience::SECURITY,
|
||||||
|
ReportIS::Severity::INFO,
|
||||||
|
ReportIS::Priority::LOW,
|
||||||
|
ReportIS::Tags::POLICY_INSTALLATION
|
||||||
|
);
|
||||||
|
|
||||||
|
log.addToOrigin(LogField("eventTopic", "Central NGINX Management"));
|
||||||
|
log << LogField("notificationId", "4165c3b1-e9bc-44c3-888b-863e204c1bfb");
|
||||||
|
log << LogField("eventRemediation", "No action required");
|
||||||
}
|
}
|
||||||
|
|
||||||
I_MainLoop *i_mainloop = nullptr;
|
I_MainLoop *i_mainloop = nullptr;
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ public:
|
|||||||
if (ignore_source_ip){
|
if (ignore_source_ip){
|
||||||
dbgDebug(D_GEO_FILTER) << "Geo protection ignoring source ip: " << source_ip;
|
dbgDebug(D_GEO_FILTER) << "Geo protection ignoring source ip: " << source_ip;
|
||||||
} else {
|
} else {
|
||||||
|
dbgTrace(D_GEO_FILTER) << "Geo protection source ip: " << source_ip;
|
||||||
ip_set.insert(convertIpAddrToString(maybe_source_ip.unpack()));
|
ip_set.insert(convertIpAddrToString(maybe_source_ip.unpack()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,6 +336,14 @@ private:
|
|||||||
ngx_http_cp_verdict_e verdict = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_IRRELEVANT;
|
ngx_http_cp_verdict_e verdict = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_IRRELEVANT;
|
||||||
I_GeoLocation *i_geo_location = Singleton::Consume<I_GeoLocation>::by<HttpGeoFilter>();
|
I_GeoLocation *i_geo_location = Singleton::Consume<I_GeoLocation>::by<HttpGeoFilter>();
|
||||||
EnumArray<I_GeoLocation::GeoLocationField, std::string> geo_location_data;
|
EnumArray<I_GeoLocation::GeoLocationField, std::string> geo_location_data;
|
||||||
|
auto env = Singleton::Consume<I_Environment>::by<HttpGeoFilter>();
|
||||||
|
string source_id;
|
||||||
|
auto maybe_source_id = env->get<std::string>(HttpTransactionData::source_identifier);
|
||||||
|
if (!maybe_source_id.ok()) {
|
||||||
|
dbgTrace(D_GEO_FILTER) << "failed to get source identifier from env";
|
||||||
|
} else {
|
||||||
|
source_id = maybe_source_id.unpack();
|
||||||
|
}
|
||||||
|
|
||||||
for (const std::string& source : sources) {
|
for (const std::string& source : sources) {
|
||||||
|
|
||||||
@@ -366,11 +375,15 @@ private:
|
|||||||
<< country_code
|
<< country_code
|
||||||
<< ", country name: "
|
<< ", country name: "
|
||||||
<< country_name
|
<< country_name
|
||||||
<< ", source ip address: "
|
<< ", ip address: "
|
||||||
<< source;
|
<< source
|
||||||
|
<< ", source identifier: "
|
||||||
|
<< source_id;
|
||||||
|
|
||||||
|
|
||||||
unordered_map<string, set<string>> exception_value_country_code = {
|
unordered_map<string, set<string>> exception_value_country_code = {
|
||||||
{"countryCode", {country_code}}
|
{"countryCode", {country_code}},
|
||||||
|
{"sourceIdentifier", {source_id}}
|
||||||
};
|
};
|
||||||
auto matched_behavior_maybe = getBehaviorsVerdict(exception_value_country_code, geo_location_data);
|
auto matched_behavior_maybe = getBehaviorsVerdict(exception_value_country_code, geo_location_data);
|
||||||
if (matched_behavior_maybe.ok()) {
|
if (matched_behavior_maybe.ok()) {
|
||||||
@@ -382,7 +395,8 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
unordered_map<string, set<string>> exception_value_country_name = {
|
unordered_map<string, set<string>> exception_value_country_name = {
|
||||||
{"countryName", {country_name}}
|
{"countryName", {country_name}},
|
||||||
|
{"sourceIdentifier", {source_id}}
|
||||||
};
|
};
|
||||||
matched_behavior_maybe = getBehaviorsVerdict(exception_value_country_name, geo_location_data);
|
matched_behavior_maybe = getBehaviorsVerdict(exception_value_country_name, geo_location_data);
|
||||||
if (matched_behavior_maybe.ok()) {
|
if (matched_behavior_maybe.ok()) {
|
||||||
|
|||||||
@@ -29,6 +29,8 @@
|
|||||||
#include "pm_hook.h"
|
#include "pm_hook.h"
|
||||||
#include "i_generic_rulebase.h"
|
#include "i_generic_rulebase.h"
|
||||||
|
|
||||||
|
#define DEFAULT_IPS_YIELD_COUNT 500
|
||||||
|
|
||||||
/// \namespace IPSSignatureSubTypes
|
/// \namespace IPSSignatureSubTypes
|
||||||
/// \brief Namespace containing subtypes for IPS signatures.
|
/// \brief Namespace containing subtypes for IPS signatures.
|
||||||
namespace IPSSignatureSubTypes
|
namespace IPSSignatureSubTypes
|
||||||
@@ -342,10 +344,17 @@ public:
|
|||||||
return is_loaded;
|
return is_loaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setYieldCounter(int new_yield_cnt)
|
||||||
|
{
|
||||||
|
yield_on_load_cnt = new_yield_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IPSSignatureMetaData metadata;
|
IPSSignatureMetaData metadata;
|
||||||
std::shared_ptr<BaseSignature> rule;
|
std::shared_ptr<BaseSignature> rule;
|
||||||
bool is_loaded;
|
bool is_loaded;
|
||||||
|
static int yield_on_load_cnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \class SignatureAndAction
|
/// \class SignatureAndAction
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ public:
|
|||||||
registerListener();
|
registerListener();
|
||||||
table = Singleton::Consume<I_Table>::by<IPSComp>();
|
table = Singleton::Consume<I_Table>::by<IPSComp>();
|
||||||
env = Singleton::Consume<I_Environment>::by<IPSComp>();
|
env = Singleton::Consume<I_Environment>::by<IPSComp>();
|
||||||
|
updateSigsYieldCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -307,6 +308,20 @@ public:
|
|||||||
|
|
||||||
EventVerdict respond (const EndTransactionEvent &) override { return ACCEPT; }
|
EventVerdict respond (const EndTransactionEvent &) override { return ACCEPT; }
|
||||||
|
|
||||||
|
void
|
||||||
|
updateSigsYieldCount()
|
||||||
|
{
|
||||||
|
const char *ips_yield_env_str = getenv("CPNANO_IPS_LOAD_YIELD_CNT");
|
||||||
|
int ips_yield_default = DEFAULT_IPS_YIELD_COUNT;
|
||||||
|
if (ips_yield_env_str != nullptr) {
|
||||||
|
dbgDebug(D_IPS) << "CPNANO_IPS_LOAD_YIELD_CNT env variable is set to " << ips_yield_env_str;
|
||||||
|
ips_yield_default = atoi(ips_yield_env_str);
|
||||||
|
}
|
||||||
|
int yield_limit = getProfileAgentSettingWithDefault<int>(ips_yield_default, "ips.sigsYieldCnt");
|
||||||
|
dbgDebug(D_IPS) << "Setting IPS yield count to " << yield_limit;
|
||||||
|
IPSSignatureSubTypes::CompleteSignature::setYieldCounter(yield_limit);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void setDrop(IPSEntry &state) { state.setDrop(); }
|
static void setDrop(IPSEntry &state) { state.setDrop(); }
|
||||||
static bool isDrop(const IPSEntry &state) { return state.isDrop(); }
|
static bool isDrop(const IPSEntry &state) { return state.isDrop(); }
|
||||||
@@ -373,6 +388,7 @@ IPSComp::preload()
|
|||||||
registerExpectedConfigFile("ips", Config::ConfigFileType::Policy);
|
registerExpectedConfigFile("ips", Config::ConfigFileType::Policy);
|
||||||
registerExpectedConfigFile("ips", Config::ConfigFileType::Data);
|
registerExpectedConfigFile("ips", Config::ConfigFileType::Data);
|
||||||
registerExpectedConfigFile("snort", Config::ConfigFileType::Policy);
|
registerExpectedConfigFile("snort", Config::ConfigFileType::Policy);
|
||||||
|
registerConfigLoadCb([this]() { pimpl->updateSigsYieldCount(); });
|
||||||
|
|
||||||
ParameterException::preload();
|
ParameterException::preload();
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ static const map<string, IPSLevel> levels = {
|
|||||||
{ "Very Low", IPSLevel::VERY_LOW }
|
{ "Very Low", IPSLevel::VERY_LOW }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int CompleteSignature::yield_on_load_cnt = DEFAULT_IPS_YIELD_COUNT;
|
||||||
|
|
||||||
static IPSLevel
|
static IPSLevel
|
||||||
getLevel(const string &level_string, const string &attr_name)
|
getLevel(const string &level_string, const string &attr_name)
|
||||||
{
|
{
|
||||||
@@ -219,6 +221,18 @@ IPSSignatureMetaData::getYear() const
|
|||||||
void
|
void
|
||||||
CompleteSignature::load(cereal::JSONInputArchive &ar)
|
CompleteSignature::load(cereal::JSONInputArchive &ar)
|
||||||
{
|
{
|
||||||
|
static int sigs_load_counter = 0;
|
||||||
|
static I_Environment *env = Singleton::Consume<I_Environment>::by<IPSComp>();
|
||||||
|
static bool post_init = false;
|
||||||
|
|
||||||
|
if (!post_init) {
|
||||||
|
auto routine_id = Singleton::Consume<I_MainLoop>::by<IPSComp>()->getCurrentRoutineId();
|
||||||
|
if (routine_id.ok()) {
|
||||||
|
post_init = true;
|
||||||
|
dbgInfo(D_IPS) << "Loading signatures post init, enabling yield with limit " << yield_on_load_cnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ar(cereal::make_nvp("protectionMetadata", metadata));
|
ar(cereal::make_nvp("protectionMetadata", metadata));
|
||||||
RuleDetection rule_detection(metadata.getName());
|
RuleDetection rule_detection(metadata.getName());
|
||||||
@@ -229,6 +243,15 @@ CompleteSignature::load(cereal::JSONInputArchive &ar)
|
|||||||
is_loaded = false;
|
is_loaded = false;
|
||||||
dbgWarning(D_IPS) << "Failed to load signature: " << e.what();
|
dbgWarning(D_IPS) << "Failed to load signature: " << e.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (post_init && (yield_on_load_cnt > 0) && (++sigs_load_counter == yield_on_load_cnt)) {
|
||||||
|
sigs_load_counter = 0;
|
||||||
|
auto maybe_is_async = env->get<bool>("Is Async Config Load");
|
||||||
|
if (maybe_is_async.ok() && *maybe_is_async == true) {
|
||||||
|
dbgTrace(D_IPS) << "Yielding after " << yield_on_load_cnt << " signatures";
|
||||||
|
Singleton::Consume<I_MainLoop>::by<IPSComp>()->yield(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MatchType
|
MatchType
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ public:
|
|||||||
{
|
{
|
||||||
comp.preload();
|
comp.preload();
|
||||||
comp.init();
|
comp.init();
|
||||||
|
auto err = genError("not coroutine");
|
||||||
|
EXPECT_CALL(mainloop, getCurrentRoutineId()).WillRepeatedly(Return(Maybe<I_MainLoop::RoutineID>(err)));
|
||||||
}
|
}
|
||||||
|
|
||||||
~ComponentTest()
|
~ComponentTest()
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ public:
|
|||||||
EntryTest()
|
EntryTest()
|
||||||
{
|
{
|
||||||
ON_CALL(table, getState(_)).WillByDefault(Return(ptr));
|
ON_CALL(table, getState(_)).WillByDefault(Return(ptr));
|
||||||
|
auto err = genError("not coroutine");
|
||||||
|
EXPECT_CALL(mock_mainloop, getCurrentRoutineId()).WillRepeatedly(Return(Maybe<I_MainLoop::RoutineID>(err)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "cptest.h"
|
#include "cptest.h"
|
||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
#include "config_component.h"
|
#include "config_component.h"
|
||||||
|
#include "mock/mock_mainloop.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace testing;
|
using namespace testing;
|
||||||
@@ -61,6 +62,9 @@ TEST(resources, basic_resource)
|
|||||||
{
|
{
|
||||||
ConfigComponent conf;
|
ConfigComponent conf;
|
||||||
::Environment env;
|
::Environment env;
|
||||||
|
NiceMock<MockMainLoop> mock_mainloop;
|
||||||
|
auto err = genError("not coroutine");
|
||||||
|
EXPECT_CALL(mock_mainloop, getCurrentRoutineId()).WillRepeatedly(Return(Maybe<I_MainLoop::RoutineID>(err)));
|
||||||
|
|
||||||
conf.preload();
|
conf.preload();
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,12 @@ public:
|
|||||||
{
|
{
|
||||||
IPSHelper::has_deobfuscation = true;
|
IPSHelper::has_deobfuscation = true;
|
||||||
generic_rulebase.preload();
|
generic_rulebase.preload();
|
||||||
|
env.preload();
|
||||||
|
env.init();
|
||||||
|
|
||||||
EXPECT_CALL(logs, getCurrentLogId()).Times(AnyNumber());
|
EXPECT_CALL(logs, getCurrentLogId()).Times(AnyNumber());
|
||||||
|
auto err = genError("not coroutine");
|
||||||
|
EXPECT_CALL(mock_mainloop, getCurrentRoutineId()).WillRepeatedly(Return(Maybe<I_MainLoop::RoutineID>(err)));
|
||||||
ON_CALL(table, getState(_)).WillByDefault(Return(&ips_state));
|
ON_CALL(table, getState(_)).WillByDefault(Return(&ips_state));
|
||||||
{
|
{
|
||||||
stringstream ss;
|
stringstream ss;
|
||||||
@@ -123,9 +128,6 @@ public:
|
|||||||
void
|
void
|
||||||
loadExceptions()
|
loadExceptions()
|
||||||
{
|
{
|
||||||
env.preload();
|
|
||||||
env.init();
|
|
||||||
|
|
||||||
BasicRuleConfig::preload();
|
BasicRuleConfig::preload();
|
||||||
registerExpectedConfiguration<ParameterException>("rulebase", "exception");
|
registerExpectedConfiguration<ParameterException>("rulebase", "exception");
|
||||||
|
|
||||||
@@ -195,6 +197,7 @@ public:
|
|||||||
void
|
void
|
||||||
load(const IPSSignaturesResource &policy, const string &severity, const string &confidence)
|
load(const IPSSignaturesResource &policy, const string &severity, const string &confidence)
|
||||||
{
|
{
|
||||||
|
Singleton::Consume<I_Environment>::from(env)->registerValue<bool>("Is Async Config Load", false);
|
||||||
setResource(policy, "IPS", "protections");
|
setResource(policy, "IPS", "protections");
|
||||||
stringstream ss;
|
stringstream ss;
|
||||||
ss << "{";
|
ss << "{";
|
||||||
|
|||||||
@@ -131,8 +131,12 @@ public:
|
|||||||
EventVerdict
|
EventVerdict
|
||||||
respond(const WaitTransactionEvent &) override
|
respond(const WaitTransactionEvent &) override
|
||||||
{
|
{
|
||||||
dbgFlow(D_L7_ACCESS_CONTROL) << "Handling wait verdict";
|
if (!isAppEnabled()) {
|
||||||
|
dbgTrace(D_L7_ACCESS_CONTROL) << "Returning Accept verdict as the Layer-7 Access Control app is disabled";
|
||||||
|
return ngx_http_cp_verdict_e::TRAFFIC_VERDICT_ACCEPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbgTrace(D_L7_ACCESS_CONTROL) << "Handling wait verdict";
|
||||||
return handleEvent();
|
return handleEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -497,7 +497,8 @@ WebAppSection::WebAppSection(
|
|||||||
const AppsecPracticeAntiBotSection &_anti_bots,
|
const AppsecPracticeAntiBotSection &_anti_bots,
|
||||||
const LogTriggerSection &parsed_log_trigger,
|
const LogTriggerSection &parsed_log_trigger,
|
||||||
const AppSecTrustedSources &parsed_trusted_sources,
|
const AppSecTrustedSources &parsed_trusted_sources,
|
||||||
const NewAppSecWebAttackProtections &protections)
|
const NewAppSecWebAttackProtections &protections,
|
||||||
|
const vector<InnerException> &exceptions)
|
||||||
:
|
:
|
||||||
application_urls(_application_urls),
|
application_urls(_application_urls),
|
||||||
asset_id(_asset_id),
|
asset_id(_asset_id),
|
||||||
@@ -541,6 +542,10 @@ WebAppSection::WebAppSection(
|
|||||||
overrides.push_back(AppSecOverride(source_ident));
|
overrides.push_back(AppSecOverride(source_ident));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const auto &exception : exceptions) {
|
||||||
|
overrides.push_back(AppSecOverride(exception));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
|
|||||||
@@ -298,7 +298,8 @@ public:
|
|||||||
const AppsecPracticeAntiBotSection &_anti_bots,
|
const AppsecPracticeAntiBotSection &_anti_bots,
|
||||||
const LogTriggerSection &parsed_log_trigger,
|
const LogTriggerSection &parsed_log_trigger,
|
||||||
const AppSecTrustedSources &parsed_trusted_sources,
|
const AppSecTrustedSources &parsed_trusted_sources,
|
||||||
const NewAppSecWebAttackProtections &protections);
|
const NewAppSecWebAttackProtections &protections,
|
||||||
|
const std::vector<InnerException> &exceptions);
|
||||||
|
|
||||||
void save(cereal::JSONOutputArchive &out_ar) const;
|
void save(cereal::JSONOutputArchive &out_ar) const;
|
||||||
|
|
||||||
|
|||||||
@@ -170,6 +170,7 @@ public:
|
|||||||
ss.str(modified_json);
|
ss.str(modified_json);
|
||||||
try {
|
try {
|
||||||
cereal::JSONInputArchive in_ar(ss);
|
cereal::JSONInputArchive in_ar(ss);
|
||||||
|
in_ar(cereal::make_nvp("apiVersion", api_version));
|
||||||
in_ar(cereal::make_nvp("spec", spec));
|
in_ar(cereal::make_nvp("spec", spec));
|
||||||
in_ar(cereal::make_nvp("metadata", meta_data));
|
in_ar(cereal::make_nvp("metadata", meta_data));
|
||||||
} catch (cereal::Exception &e) {
|
} catch (cereal::Exception &e) {
|
||||||
@@ -191,11 +192,18 @@ public:
|
|||||||
return meta_data;
|
return meta_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string &
|
||||||
|
getApiVersion() const
|
||||||
|
{
|
||||||
|
return api_version;
|
||||||
|
}
|
||||||
|
|
||||||
const T & getSpec() const { return spec; }
|
const T & getSpec() const { return spec; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T spec;
|
T spec;
|
||||||
AppsecSpecParserMetaData meta_data;
|
AppsecSpecParserMetaData meta_data;
|
||||||
|
std::string api_version;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __LOCAL_POLICY_COMMON_H__
|
#endif // __LOCAL_POLICY_COMMON_H__
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string mode;
|
|
||||||
std::vector<std::string> hosts;
|
std::vector<std::string> hosts;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -206,7 +206,8 @@ private:
|
|||||||
const RulesConfigRulebase& rule_config,
|
const RulesConfigRulebase& rule_config,
|
||||||
const std::string &practice_id, const std::string &full_url,
|
const std::string &practice_id, const std::string &full_url,
|
||||||
const std::string &default_mode,
|
const std::string &default_mode,
|
||||||
std::map<AnnotationTypes, std::string> &rule_annotations
|
std::map<AnnotationTypes, std::string> &rule_annotations,
|
||||||
|
std::vector<InnerException>
|
||||||
);
|
);
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -515,71 +515,63 @@ K8sPolicyUtils::createAppsecPolicyK8sFromV1beta2Crds(
|
|||||||
}
|
}
|
||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
|
|
||||||
bool
|
tuple<Maybe<AppsecLinuxPolicy>, Maybe<V1beta2AppsecLinuxPolicy>>
|
||||||
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
|
K8sPolicyUtils::createAppsecPolicyK8s(const string &policy_name, const string &ingress_mode) const
|
||||||
{
|
{
|
||||||
auto maybe_appsec_policy_spec = getObjectFromCluster<AppsecSpecParser<AppsecPolicySpec>>(
|
string ns_suffix = getAppSecScopeType() == "namespaced" ? "ns" : "";
|
||||||
"/apis/openappsec.io/v1beta1/policies/" + policy_name
|
string ns = getAppSecScopeType() == "namespaced" ? "namespaces/" : "";
|
||||||
|
auto maybe_v1beta2_appsec_policy_spec = getObjectFromCluster<AppsecSpecParser<NewAppsecPolicySpec>>(
|
||||||
|
"/apis/openappsec.io/v1beta2/" + ns + agent_ns + "policies" + ns_suffix + "/" + policy_name
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!maybe_appsec_policy_spec.ok() ||
|
if (!maybe_v1beta2_appsec_policy_spec.ok() ||
|
||||||
!doesVersionExist(maybe_appsec_policy_spec.unpack().getMetaData().getAnnotations(), "v1beta1")
|
maybe_v1beta2_appsec_policy_spec.unpack().getApiVersion().find("v1beta2") == std::string::npos
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
std::string v1beta1_error =
|
string policy_error = maybe_v1beta2_appsec_policy_spec.getErr();
|
||||||
maybe_appsec_policy_spec.ok() ? "There is no v1beta1 policy" : maybe_appsec_policy_spec.getErr();
|
string v1beta2_error =
|
||||||
|
maybe_v1beta2_appsec_policy_spec.ok() ? "There is no v1beta2 policy" : policy_error;
|
||||||
dbgWarning(D_LOCAL_POLICY
|
dbgWarning(D_LOCAL_POLICY
|
||||||
) << "Failed to retrieve Appsec policy with crds version: v1beta1, Trying version: v1beta2";
|
) << "Failed to retrieve Appsec policy with crds version: v1beta1, Trying version: v1beta2";
|
||||||
string ns_suffix = getAppSecScopeType() == "namespaced" ? "ns" : "";
|
auto maybe_appsec_policy_spec = getObjectFromCluster<AppsecSpecParser<AppsecPolicySpec>>(
|
||||||
string ns = getAppSecScopeType() == "namespaced" ? "namespaces/" : "";
|
"/apis/openappsec.io/v1beta1/policies/" + policy_name
|
||||||
auto maybe_v1beta2_appsec_policy_spec = getObjectFromCluster<AppsecSpecParser<NewAppsecPolicySpec>>(
|
|
||||||
"/apis/openappsec.io/v1beta2/" + ns + agent_ns + "policies" + ns_suffix + "/" + policy_name
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!maybe_v1beta2_appsec_policy_spec.ok()) {
|
if (!maybe_appsec_policy_spec.ok()) {
|
||||||
dbgWarning(D_LOCAL_POLICY)
|
dbgWarning(D_LOCAL_POLICY)
|
||||||
<< "Failed to retrieve AppSec policy. Error: " << maybe_v1beta2_appsec_policy_spec.getErr();
|
<< "Failed to retrieve AppSec policy. Error: " << maybe_appsec_policy_spec.getErr();
|
||||||
return std::make_tuple(
|
return std::make_tuple(
|
||||||
genError("Failed to retrieve AppSec v1beta1 policy. Error: " + v1beta1_error),
|
genError("Failed to retrieve AppSec v1beta1 policy. Error: " + maybe_appsec_policy_spec.getErr()),
|
||||||
genError(
|
genError(
|
||||||
"Failed to retrieve AppSec v1beta2 policy. Error: " + maybe_v1beta2_appsec_policy_spec.getErr()
|
"Failed to retrieve AppSec v1beta2 policy. Error: " + v1beta2_error
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return std::make_tuple(
|
return std::make_tuple(
|
||||||
genError("There is no v1beta1 policy"),
|
createAppsecPolicyK8sFromV1beta1Crds(maybe_appsec_policy_spec.unpack(), ingress_mode),
|
||||||
createAppsecPolicyK8sFromV1beta2Crds(maybe_v1beta2_appsec_policy_spec.unpack(), ingress_mode)
|
genError("There is no v1beta2 policy")
|
||||||
);
|
);
|
||||||
|
|
||||||
} catch (const PolicyGenException &e) {
|
} catch (const PolicyGenException &e) {
|
||||||
dbgDebug(D_LOCAL_POLICY) << "Failed in policy generation. Error: " << e.what();
|
dbgDebug(D_LOCAL_POLICY) << "Failed in policy generation. Error: " << e.what();
|
||||||
return std::make_tuple(
|
return make_tuple(
|
||||||
genError("There is no v1beta1 policy"),
|
genError("There is no v1beta1 policy"),
|
||||||
genError("Failed to retrieve AppSec v1beta2 policy. Error: " + string(e.what()))
|
genError("Failed to retrieve AppSec v1beta2 policy. Error: " + string(e.what()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_tuple(
|
return make_tuple(
|
||||||
createAppsecPolicyK8sFromV1beta1Crds(maybe_appsec_policy_spec.unpack(), ingress_mode),
|
genError("There is no v1beta1 policy"),
|
||||||
genError("There is no v1beta2 policy"));
|
createAppsecPolicyK8sFromV1beta2Crds(maybe_v1beta2_appsec_policy_spec.unpack(), ingress_mode)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T, class K>
|
template<class T, class K>
|
||||||
void
|
void
|
||||||
K8sPolicyUtils::createPolicyFromIngress(
|
K8sPolicyUtils::createPolicyFromIngress(
|
||||||
T &appsec_policy,
|
T &appsec_policy,
|
||||||
map<std::string, T> &policies,
|
map<string, T> &policies,
|
||||||
map<AnnotationKeys, string> &annotations_values,
|
map<AnnotationKeys, string> &annotations_values,
|
||||||
const SingleIngressData &item) const
|
const SingleIngressData &item) const
|
||||||
{
|
{
|
||||||
@@ -619,7 +611,7 @@ template<class T, class K>
|
|||||||
void
|
void
|
||||||
K8sPolicyUtils::createPolicyFromActivation(
|
K8sPolicyUtils::createPolicyFromActivation(
|
||||||
T &appsec_policy,
|
T &appsec_policy,
|
||||||
map<std::string, T> &policies,
|
map<string, T> &policies,
|
||||||
const EnabledPolicy &policy) const
|
const EnabledPolicy &policy) const
|
||||||
{
|
{
|
||||||
if (policies.find(policy.getName()) == policies.end()) {
|
if (policies.find(policy.getName()) == policies.end()) {
|
||||||
@@ -698,8 +690,12 @@ K8sPolicyUtils::createAppsecPolicies()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto maybe_policy_activation =
|
|
||||||
getObjectFromCluster<PolicyActivationData>("/apis/openappsec.io/v1beta2/policyactivations");
|
string ns_suffix = getAppSecScopeType() == "namespaced" ? "ns" : "";
|
||||||
|
string ns = getAppSecScopeType() == "namespaced" ? "namespaces/" : "";
|
||||||
|
auto maybe_policy_activation = getObjectFromCluster<PolicyActivationData>(
|
||||||
|
"/apis/openappsec.io/v1beta2/" + ns + agent_ns + "policyactivations" + ns_suffix
|
||||||
|
);
|
||||||
|
|
||||||
if (!maybe_policy_activation.ok()) {
|
if (!maybe_policy_activation.ok()) {
|
||||||
dbgWarning(D_LOCAL_POLICY)
|
dbgWarning(D_LOCAL_POLICY)
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ Identifier::load(cereal::JSONInputArchive &archive_in)
|
|||||||
dbgWarning(D_LOCAL_POLICY) << "AppSec identifier invalid: " << identifier;
|
dbgWarning(D_LOCAL_POLICY) << "AppSec identifier invalid: " << identifier;
|
||||||
identifier = "sourceip";
|
identifier = "sourceip";
|
||||||
}
|
}
|
||||||
parseMandatoryAppsecJSONKey<vector<string>>("value", value, archive_in);
|
parseAppsecJSONKey<vector<string>>("value", value, archive_in);
|
||||||
}
|
}
|
||||||
|
|
||||||
const string &
|
const string &
|
||||||
|
|||||||
@@ -18,14 +18,6 @@ using namespace std;
|
|||||||
|
|
||||||
USE_DEBUG_FLAG(D_LOCAL_POLICY);
|
USE_DEBUG_FLAG(D_LOCAL_POLICY);
|
||||||
|
|
||||||
static const set<string> valid_modes = {
|
|
||||||
"prevent-learn",
|
|
||||||
"detect-learn",
|
|
||||||
"prevent",
|
|
||||||
"detect",
|
|
||||||
"inactive"
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PolicyActivationMetadata::load(cereal::JSONInputArchive &archive_in)
|
PolicyActivationMetadata::load(cereal::JSONInputArchive &archive_in)
|
||||||
{
|
{
|
||||||
@@ -39,11 +31,6 @@ EnabledPolicy::load(cereal::JSONInputArchive &archive_in)
|
|||||||
dbgTrace(D_LOCAL_POLICY) << "Loading policyActivation enabled policy";
|
dbgTrace(D_LOCAL_POLICY) << "Loading policyActivation enabled policy";
|
||||||
parseMandatoryAppsecJSONKey<vector<string>>("hosts", hosts, archive_in);
|
parseMandatoryAppsecJSONKey<vector<string>>("hosts", hosts, archive_in);
|
||||||
parseAppsecJSONKey<string>("name", name, archive_in);
|
parseAppsecJSONKey<string>("name", name, archive_in);
|
||||||
parseAppsecJSONKey<string>("mode", mode, archive_in, "detect");
|
|
||||||
if (valid_modes.count(mode) == 0) {
|
|
||||||
dbgWarning(D_LOCAL_POLICY) << "AppSec policy activation mode invalid: " << mode;
|
|
||||||
mode = "detect";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const string &
|
const string &
|
||||||
|
|||||||
@@ -928,7 +928,6 @@ createMultiRulesSections(
|
|||||||
PracticeSection practice = PracticeSection(practice_id, practice_type, practice_name);
|
PracticeSection practice = PracticeSection(practice_id, practice_type, practice_name);
|
||||||
vector<ParametersSection> exceptions_result;
|
vector<ParametersSection> exceptions_result;
|
||||||
for (auto exception : exceptions) {
|
for (auto exception : exceptions) {
|
||||||
|
|
||||||
const auto &exception_name = exception.first;
|
const auto &exception_name = exception.first;
|
||||||
for (const auto &inner_exception : exception.second) {
|
for (const auto &inner_exception : exception.second) {
|
||||||
exceptions_result.push_back(ParametersSection(inner_exception.getBehaviorId(), exception_name));
|
exceptions_result.push_back(ParametersSection(inner_exception.getBehaviorId(), exception_name));
|
||||||
@@ -1220,7 +1219,8 @@ PolicyMakerUtils::createWebAppSection(
|
|||||||
const string &practice_id,
|
const string &practice_id,
|
||||||
const string &full_url,
|
const string &full_url,
|
||||||
const string &default_mode,
|
const string &default_mode,
|
||||||
map<AnnotationTypes, string> &rule_annotations)
|
map<AnnotationTypes, string> &rule_annotations,
|
||||||
|
vector<InnerException> rule_inner_exceptions)
|
||||||
{
|
{
|
||||||
auto apssec_practice =
|
auto apssec_practice =
|
||||||
getAppsecPracticeSpec<V1beta2AppsecLinuxPolicy, NewAppSecPracticeSpec>(
|
getAppsecPracticeSpec<V1beta2AppsecLinuxPolicy, NewAppSecPracticeSpec>(
|
||||||
@@ -1255,7 +1255,8 @@ PolicyMakerUtils::createWebAppSection(
|
|||||||
apssec_practice.getAntiBot(),
|
apssec_practice.getAntiBot(),
|
||||||
log_triggers[rule_annotations[AnnotationTypes::TRIGGER]],
|
log_triggers[rule_annotations[AnnotationTypes::TRIGGER]],
|
||||||
trusted_sources[rule_annotations[AnnotationTypes::TRUSTED_SOURCES]],
|
trusted_sources[rule_annotations[AnnotationTypes::TRUSTED_SOURCES]],
|
||||||
apssec_practice.getWebAttacks().getProtections()
|
apssec_practice.getWebAttacks().getProtections(),
|
||||||
|
rule_inner_exceptions
|
||||||
);
|
);
|
||||||
web_apps[rule_config.getAssetName()] = web_app;
|
web_apps[rule_config.getAssetName()] = web_app;
|
||||||
}
|
}
|
||||||
@@ -1366,7 +1367,8 @@ PolicyMakerUtils::createThreatPreventionPracticeSections(
|
|||||||
practice_id,
|
practice_id,
|
||||||
asset_name,
|
asset_name,
|
||||||
default_mode,
|
default_mode,
|
||||||
rule_annotations);
|
rule_annotations,
|
||||||
|
inner_exceptions[rule_annotations[AnnotationTypes::EXCEPTION]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,12 +41,13 @@ public:
|
|||||||
|
|
||||||
string getAgentVersion() override;
|
string getAgentVersion() override;
|
||||||
bool isKernelVersion3OrHigher() override;
|
bool isKernelVersion3OrHigher() override;
|
||||||
|
bool isGw() override;
|
||||||
bool isGwNotVsx() override;
|
bool isGwNotVsx() override;
|
||||||
bool isVersionAboveR8110() override;
|
bool isVersionAboveR8110() override;
|
||||||
bool isReverseProxy() override;
|
bool isReverseProxy() override;
|
||||||
bool isCloudStorageEnabled() override;
|
bool isCloudStorageEnabled() override;
|
||||||
Maybe<tuple<string, string, string, string, string>> readCloudMetadata() override;
|
Maybe<tuple<string, string, string, string, string>> readCloudMetadata() override;
|
||||||
Maybe<tuple<string, string, string>> parseNginxMetadata() override;
|
Maybe<tuple<string, string, string, string>> parseNginxMetadata() override;
|
||||||
#if defined(gaia) || defined(smb)
|
#if defined(gaia) || defined(smb)
|
||||||
bool compareCheckpointVersion(int cp_version, std::function<bool(int, int)> compare_operator) const override;
|
bool compareCheckpointVersion(int cp_version, std::function<bool(int, int)> compare_operator) const override;
|
||||||
#endif // gaia || smb
|
#endif // gaia || smb
|
||||||
@@ -80,7 +81,9 @@ DetailsResolver::Impl::getHostname()
|
|||||||
Maybe<string>
|
Maybe<string>
|
||||||
DetailsResolver::Impl::getPlatform()
|
DetailsResolver::Impl::getPlatform()
|
||||||
{
|
{
|
||||||
#if defined(gaia)
|
#if defined(gaia_arm)
|
||||||
|
return string("gaia_arm");
|
||||||
|
#elif defined(gaia)
|
||||||
return string("gaia");
|
return string("gaia");
|
||||||
#elif defined(arm32_rpi)
|
#elif defined(arm32_rpi)
|
||||||
return string("glibc");
|
return string("glibc");
|
||||||
@@ -165,6 +168,19 @@ DetailsResolver::Impl::isKernelVersion3OrHigher()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
DetailsResolver::Impl::isGw()
|
||||||
|
{
|
||||||
|
#if defined(gaia) || defined(smb)
|
||||||
|
static const string is_gw_cmd = "cpprod_util FwIsFirewallModule";
|
||||||
|
auto is_gw = DetailsResolvingHanlder::getCommandOutput(is_gw_cmd);
|
||||||
|
if (is_gw.ok() && !is_gw.unpack().empty()) {
|
||||||
|
return is_gw.unpack().front() == '1';
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DetailsResolver::Impl::isGwNotVsx()
|
DetailsResolver::Impl::isGwNotVsx()
|
||||||
{
|
{
|
||||||
@@ -228,7 +244,7 @@ isNoResponse(const string &cmd)
|
|||||||
return !res.ok() || res.unpack().empty();
|
return !res.ok() || res.unpack().empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe<tuple<string, string, string>>
|
Maybe<tuple<string, string, string, string>>
|
||||||
DetailsResolver::Impl::parseNginxMetadata()
|
DetailsResolver::Impl::parseNginxMetadata()
|
||||||
{
|
{
|
||||||
auto output_path = getConfigurationWithDefault<string>(
|
auto output_path = getConfigurationWithDefault<string>(
|
||||||
@@ -236,11 +252,22 @@ DetailsResolver::Impl::parseNginxMetadata()
|
|||||||
"orchestration",
|
"orchestration",
|
||||||
"Nginx metadata temp file"
|
"Nginx metadata temp file"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const string &filesystem_path_config = getFilesystemPathConfig();
|
||||||
|
|
||||||
const string srcipt_exe_cmd =
|
const string srcipt_exe_cmd =
|
||||||
getFilesystemPathConfig() +
|
filesystem_path_config +
|
||||||
"/scripts/cp-nano-makefile-generator.sh -f -o " +
|
"/scripts/cp-nano-makefile-generator.sh -f -o " +
|
||||||
output_path;
|
output_path;
|
||||||
|
|
||||||
|
const string script_fresh_exe_cmd =
|
||||||
|
filesystem_path_config +
|
||||||
|
"/scripts/cp-nano-makefile-generator-fresh.sh save --save-location " +
|
||||||
|
output_path +
|
||||||
|
" --strings_bin_path " +
|
||||||
|
filesystem_path_config +
|
||||||
|
"/bin/strings";
|
||||||
|
|
||||||
dbgTrace(D_ORCHESTRATOR) << "Details resolver, srcipt exe cmd: " << srcipt_exe_cmd;
|
dbgTrace(D_ORCHESTRATOR) << "Details resolver, srcipt exe cmd: " << srcipt_exe_cmd;
|
||||||
if (isNoResponse("which nginx") && isNoResponse("which kong")) {
|
if (isNoResponse("which nginx") && isNoResponse("which kong")) {
|
||||||
return genError("Nginx or Kong isn't installed");
|
return genError("Nginx or Kong isn't installed");
|
||||||
@@ -263,7 +290,7 @@ DetailsResolver::Impl::parseNginxMetadata()
|
|||||||
return genError("Cannot open the file with nginx metadata, File: " + output_path);
|
return genError("Cannot open the file with nginx metadata, File: " + output_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
string line;
|
string line;
|
||||||
while (getline(input_stream, line)) {
|
while (getline(input_stream, line)) {
|
||||||
lines.push_back(line);
|
lines.push_back(line);
|
||||||
}
|
}
|
||||||
@@ -277,7 +304,37 @@ DetailsResolver::Impl::parseNginxMetadata()
|
|||||||
<< " Error: " << exception.what();
|
<< " Error: " << exception.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isNoResponse("which nginx")) {
|
||||||
|
auto script_output = DetailsResolvingHanlder::getCommandOutput(script_fresh_exe_cmd);
|
||||||
|
if (!script_output.ok()) {
|
||||||
|
return genError("Failed to generate nginx fresh metadata, Error: " + script_output.getErr());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ifstream input_stream(output_path);
|
||||||
|
if (!input_stream) {
|
||||||
|
return genError("Cannot open the file with nginx fresh metadata, File: " + output_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
string line;
|
||||||
|
while (getline(input_stream, line)) {
|
||||||
|
if (line.find("NGX_MODULE_SIGNATURE") == 0) {
|
||||||
|
lines.push_back(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input_stream.close();
|
||||||
|
|
||||||
|
orchestration_tools->removeFile(output_path);
|
||||||
|
} catch (const ifstream::failure &exception) {
|
||||||
|
dbgWarning(D_ORCHESTRATOR)
|
||||||
|
<< "Cannot read the file with required nginx fresh metadata."
|
||||||
|
<< " File: " << output_path
|
||||||
|
<< " Error: " << exception.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (lines.size() == 0) return genError("Failed to read nginx metadata file");
|
if (lines.size() == 0) return genError("Failed to read nginx metadata file");
|
||||||
|
string nginx_signature;
|
||||||
string nginx_version;
|
string nginx_version;
|
||||||
string config_opt;
|
string config_opt;
|
||||||
string cc_opt;
|
string cc_opt;
|
||||||
@@ -292,6 +349,11 @@ DetailsResolver::Impl::parseNginxMetadata()
|
|||||||
nginx_version = "nginx-" + line.substr(eq_index + 1);
|
nginx_version = "nginx-" + line.substr(eq_index + 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (line.find("NGX_MODULE_SIGNATURE") != string::npos) {
|
||||||
|
auto eq_index = line.find("=");
|
||||||
|
nginx_signature = line.substr(eq_index + 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (line.find("EXTRA_CC_OPT") != string::npos) {
|
if (line.find("EXTRA_CC_OPT") != string::npos) {
|
||||||
auto eq_index = line.find("=");
|
auto eq_index = line.find("=");
|
||||||
cc_opt = line.substr(eq_index + 1);
|
cc_opt = line.substr(eq_index + 1);
|
||||||
@@ -301,7 +363,7 @@ DetailsResolver::Impl::parseNginxMetadata()
|
|||||||
if (line.back() == '\\') line.pop_back();
|
if (line.back() == '\\') line.pop_back();
|
||||||
config_opt += line;
|
config_opt += line;
|
||||||
}
|
}
|
||||||
return make_tuple(config_opt, cc_opt, nginx_version);
|
return make_tuple(config_opt, cc_opt, nginx_version, nginx_signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe<tuple<string, string, string, string, string>>
|
Maybe<tuple<string, string, string, string, string>>
|
||||||
|
|||||||
@@ -26,9 +26,7 @@
|
|||||||
Maybe<string>
|
Maybe<string>
|
||||||
checkSAMLSupportedBlade(const string &command_output)
|
checkSAMLSupportedBlade(const string &command_output)
|
||||||
{
|
{
|
||||||
// uncomment when vpn will support SAML authentication
|
string supportedBlades[3] = {"identityServer", "vpn", "cvpn"};
|
||||||
// string supportedBlades[3] = {"identityServer", "vpn", "cvpn"};
|
|
||||||
string supportedBlades[1] = {"identityServer"};
|
|
||||||
for(const string &blade : supportedBlades) {
|
for(const string &blade : supportedBlades) {
|
||||||
if (command_output.find(blade) != string::npos) {
|
if (command_output.find(blade) != string::npos) {
|
||||||
return string("true");
|
return string("true");
|
||||||
@@ -49,6 +47,17 @@ checkIDABlade(const string &command_output)
|
|||||||
return string("false");
|
return string("false");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Maybe<string>
|
||||||
|
checkVPNBlade(const string &command_output)
|
||||||
|
{
|
||||||
|
string vpnBlade = "vpn";
|
||||||
|
if (command_output.find(vpnBlade) != string::npos) {
|
||||||
|
return string("true");
|
||||||
|
}
|
||||||
|
|
||||||
|
return string("false");
|
||||||
|
}
|
||||||
|
|
||||||
Maybe<string>
|
Maybe<string>
|
||||||
checkSAMLPortal(const string &command_output)
|
checkSAMLPortal(const string &command_output)
|
||||||
{
|
{
|
||||||
@@ -60,9 +69,9 @@ checkSAMLPortal(const string &command_output)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Maybe<string>
|
Maybe<string>
|
||||||
checkPepIdaIdnStatus(const string &command_output)
|
checkInfinityIdentityEnabled(const string &command_output)
|
||||||
{
|
{
|
||||||
if (command_output.find("nac_pep_identity_next_enabled = 1") != string::npos) {
|
if (command_output.find("get_identities_from_infinity_identity (true)") != string::npos) {
|
||||||
return string("true");
|
return string("true");
|
||||||
}
|
}
|
||||||
return string("false");
|
return string("false");
|
||||||
@@ -71,7 +80,18 @@ checkPepIdaIdnStatus(const string &command_output)
|
|||||||
Maybe<string>
|
Maybe<string>
|
||||||
getRequiredNanoServices(const string &command_output)
|
getRequiredNanoServices(const string &command_output)
|
||||||
{
|
{
|
||||||
return command_output;
|
string idaRequiredServices[2] = {"idaSaml", "idaIdn"};
|
||||||
|
string platform_str = "gaia";
|
||||||
|
#if defined(gaia_arm)
|
||||||
|
platform_str = "gaia_arm";
|
||||||
|
#endif // gaia_arm
|
||||||
|
string result = "";
|
||||||
|
for(const string &serv : idaRequiredServices) {
|
||||||
|
string add_service = serv + "_" + platform_str;
|
||||||
|
result = result + add_service + ";";
|
||||||
|
}
|
||||||
|
command_output.empty(); // overcome unused variable
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe<string>
|
Maybe<string>
|
||||||
@@ -79,9 +99,6 @@ checkIDP(shared_ptr<istream> file_stream)
|
|||||||
{
|
{
|
||||||
string line;
|
string line;
|
||||||
while (getline(*file_stream, line)) {
|
while (getline(*file_stream, line)) {
|
||||||
if (line.find("<identity_portal/>") != string::npos) {
|
|
||||||
return string("false");
|
|
||||||
}
|
|
||||||
if (line.find("<central_idp ") != string::npos) {
|
if (line.find("<central_idp ") != string::npos) {
|
||||||
return string("true");
|
return string("true");
|
||||||
}
|
}
|
||||||
@@ -90,6 +107,26 @@ checkIDP(shared_ptr<istream> file_stream)
|
|||||||
return string("false");
|
return string("false");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Maybe<string>
|
||||||
|
checkVPNCIDP(shared_ptr<istream> file_stream)
|
||||||
|
{
|
||||||
|
string line;
|
||||||
|
while (getline(*file_stream, line)) {
|
||||||
|
if (line.find("<vpn") != string::npos) {
|
||||||
|
while (getline(*file_stream, line)) {
|
||||||
|
if (line.find("<central_idp ") != string::npos) {
|
||||||
|
return string("true");
|
||||||
|
}
|
||||||
|
if (line.find("</vpn>") != string::npos) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return string("false");
|
||||||
|
}
|
||||||
|
|
||||||
#endif // gaia
|
#endif // gaia
|
||||||
|
|
||||||
#if defined(gaia) || defined(smb)
|
#if defined(gaia) || defined(smb)
|
||||||
@@ -129,6 +166,17 @@ getIsAiopsRunning(const string &command_output)
|
|||||||
return command_output;
|
return command_output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Maybe<string>
|
||||||
|
getInterfaceMgmtIp(const string &command_output)
|
||||||
|
{
|
||||||
|
if (!command_output.empty()) {
|
||||||
|
return command_output;
|
||||||
|
}
|
||||||
|
|
||||||
|
return genError("Eth Management IP was not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Maybe<string>
|
Maybe<string>
|
||||||
checkHasSDWan(const string &command_output)
|
checkHasSDWan(const string &command_output)
|
||||||
{
|
{
|
||||||
@@ -342,6 +390,28 @@ getSMCBasedMgmtName(const string &command_output)
|
|||||||
return getAttr(command_output, "Mgmt object Name was not found");
|
return getAttr(command_output, "Mgmt object Name was not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Maybe<string>
|
||||||
|
getSmbObjectUid(const string &command_output)
|
||||||
|
{
|
||||||
|
static const char centrally_managed_comd_output = '0';
|
||||||
|
|
||||||
|
if (command_output.empty() || command_output[0] != centrally_managed_comd_output) {
|
||||||
|
return genError("Object UUID was not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe<string> obj_uuid = getAttrFromCpsdwanGetDataJson("uuid");
|
||||||
|
if (obj_uuid.ok()) {
|
||||||
|
return obj_uuid.unpack();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string obj_path = (getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myown.C";
|
||||||
|
auto file_stream = std::make_shared<std::ifstream>(obj_path);
|
||||||
|
if (!file_stream->is_open()) {
|
||||||
|
return genError("Failed to open the object file");
|
||||||
|
}
|
||||||
|
return getMgmtObjAttr(file_stream, "uuid ");
|
||||||
|
}
|
||||||
|
|
||||||
Maybe<string>
|
Maybe<string>
|
||||||
getSmbObjectName(const string &command_output)
|
getSmbObjectName(const string &command_output)
|
||||||
{
|
{
|
||||||
@@ -418,6 +488,14 @@ extractManagements(const string &command_output)
|
|||||||
json_output += "]";
|
json_output += "]";
|
||||||
return json_output;
|
return json_output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Maybe<string>
|
||||||
|
checkQosLegacyBlade(const string &command_output)
|
||||||
|
{
|
||||||
|
if (command_output == "true" || command_output == "false") return command_output;
|
||||||
|
|
||||||
|
return string("false");
|
||||||
|
}
|
||||||
#endif // gaia || smb
|
#endif // gaia || smb
|
||||||
|
|
||||||
#if defined(gaia)
|
#if defined(gaia)
|
||||||
|
|||||||
@@ -42,11 +42,6 @@ SHELL_PRE_CMD("gunzip local.cfg", "gunzip -c $FWDIR/state/local/FW1/local.cfg.gz
|
|||||||
#ifdef SHELL_CMD_HANDLER
|
#ifdef SHELL_CMD_HANDLER
|
||||||
#if defined(gaia) || defined(smb) || defined(smb_thx_v3) || defined(smb_sve_v2) || defined(smb_mrv_v1)
|
#if defined(gaia) || defined(smb) || defined(smb_thx_v3) || defined(smb_sve_v2) || defined(smb_mrv_v1)
|
||||||
SHELL_CMD_HANDLER("cpProductIntegrationMgmtObjectType", "cpprod_util CPPROD_IsMgmtMachine", getMgmtObjType)
|
SHELL_CMD_HANDLER("cpProductIntegrationMgmtObjectType", "cpprod_util CPPROD_IsMgmtMachine", getMgmtObjType)
|
||||||
SHELL_CMD_HANDLER(
|
|
||||||
"cpProductIntegrationMgmtObjectUid",
|
|
||||||
"mgmt_cli --format json -r true show-session | jq -r '.[\"connected-server\"].uid'",
|
|
||||||
getMgmtObjUid
|
|
||||||
)
|
|
||||||
SHELL_CMD_HANDLER("prerequisitesForHorizonTelemetry",
|
SHELL_CMD_HANDLER("prerequisitesForHorizonTelemetry",
|
||||||
"FS_PATH=<FILESYSTEM-PREFIX>; [ -f ${FS_PATH}/cp-nano-horizon-telemetry-prerequisites.log ] "
|
"FS_PATH=<FILESYSTEM-PREFIX>; [ -f ${FS_PATH}/cp-nano-horizon-telemetry-prerequisites.log ] "
|
||||||
"&& head -1 ${FS_PATH}/cp-nano-horizon-telemetry-prerequisites.log || echo ''",
|
"&& head -1 ${FS_PATH}/cp-nano-horizon-telemetry-prerequisites.log || echo ''",
|
||||||
@@ -84,6 +79,14 @@ SHELL_CMD_HANDLER("MGMT_QUID", "[ -d /opt/CPquid ] "
|
|||||||
SHELL_CMD_HANDLER("AIOPS_AGENT_ROLE", "[ -d /opt/CPOtlpAgent/custom_scripts ] "
|
SHELL_CMD_HANDLER("AIOPS_AGENT_ROLE", "[ -d /opt/CPOtlpAgent/custom_scripts ] "
|
||||||
"&& ENV_NO_FORMAT=1 /opt/CPOtlpAgent/custom_scripts/agent_role.sh",
|
"&& ENV_NO_FORMAT=1 /opt/CPOtlpAgent/custom_scripts/agent_role.sh",
|
||||||
getOtlpAgentGaiaOsRole)
|
getOtlpAgentGaiaOsRole)
|
||||||
|
SHELL_CMD_HANDLER("ETH_MGMT_IP",
|
||||||
|
"FS_PATH=<FILESYSTEM-PREFIX>;"
|
||||||
|
"VS_ID=$(echo \"${FS_PATH}\" | grep -o -E \"vs[0-9]+\" | grep -o -E \"[0-9]+\");"
|
||||||
|
"[ -z \"${VS_ID}\" ] && "
|
||||||
|
"(eth=\"$(grep 'management:interface' /config/active | awk '{print $2}')\" &&"
|
||||||
|
" ip addr show \"${eth}\" | grep inet | awk '{print $2}' | cut -d '/' -f1) || "
|
||||||
|
"(ip a | grep UP | grep -v lo | head -n 1 | cut -d ':' -f2 | tr -d ' ')",
|
||||||
|
getInterfaceMgmtIp)
|
||||||
#endif
|
#endif
|
||||||
#if defined(smb) || defined(smb_thx_v3) || defined(smb_sve_v2) || defined(smb_mrv_v1)
|
#if defined(smb) || defined(smb_thx_v3) || defined(smb_sve_v2) || defined(smb_mrv_v1)
|
||||||
SHELL_CMD_HANDLER("GLOBAL_QUID",
|
SHELL_CMD_HANDLER("GLOBAL_QUID",
|
||||||
@@ -94,6 +97,8 @@ SHELL_CMD_HANDLER("QUID",
|
|||||||
"cat $FWDIR/database/myown.C "
|
"cat $FWDIR/database/myown.C "
|
||||||
"| awk -F'[()]' '/:name/ { found=1; next } found && /:uuid/ { uid=tolower($2); print uid; exit }'",
|
"| awk -F'[()]' '/:name/ { found=1; next } found && /:uuid/ { uid=tolower($2); print uid; exit }'",
|
||||||
getQUID)
|
getQUID)
|
||||||
|
|
||||||
|
|
||||||
SHELL_CMD_HANDLER("SMO_QUID", "echo ''", getQUID)
|
SHELL_CMD_HANDLER("SMO_QUID", "echo ''", getQUID)
|
||||||
SHELL_CMD_HANDLER("MGMT_QUID", "echo ''", getQUID)
|
SHELL_CMD_HANDLER("MGMT_QUID", "echo ''", getQUID)
|
||||||
SHELL_CMD_HANDLER("AIOPS_AGENT_ROLE", "echo 'SMB'", getOtlpAgentGaiaOsRole)
|
SHELL_CMD_HANDLER("AIOPS_AGENT_ROLE", "echo 'SMB'", getOtlpAgentGaiaOsRole)
|
||||||
@@ -119,12 +124,6 @@ SHELL_CMD_HANDLER(
|
|||||||
"jq -r .lsm_profile_uuid /tmp/cpsdwan_getdata_orch.json",
|
"jq -r .lsm_profile_uuid /tmp/cpsdwan_getdata_orch.json",
|
||||||
checkLsmProfileUuid
|
checkLsmProfileUuid
|
||||||
)
|
)
|
||||||
SHELL_CMD_HANDLER(
|
|
||||||
"IP Address",
|
|
||||||
"[ $(cpprod_util FWisDAG) -eq 1 ] && echo \"Dynamic Address\" "
|
|
||||||
"|| (jq -r .main_ip /tmp/cpsdwan_getdata_orch.json)",
|
|
||||||
getGWIPAddress
|
|
||||||
)
|
|
||||||
SHELL_CMD_HANDLER(
|
SHELL_CMD_HANDLER(
|
||||||
"Version",
|
"Version",
|
||||||
"cat /etc/cp-release | grep -oE 'R[0-9]+(\\.[0-9]+)?'",
|
"cat /etc/cp-release | grep -oE 'R[0-9]+(\\.[0-9]+)?'",
|
||||||
@@ -143,19 +142,33 @@ SHELL_CMD_HANDLER(
|
|||||||
"fw ctl get int support_fec |& grep -sq \"support_fec =\";echo $?",
|
"fw ctl get int support_fec |& grep -sq \"support_fec =\";echo $?",
|
||||||
getFecApplicable
|
getFecApplicable
|
||||||
)
|
)
|
||||||
|
SHELL_CMD_HANDLER("is_legacy_qos_blade_enabled",
|
||||||
|
"cpprod_util CPPROD_GetValue FG1 ProdActive 1 | grep -q '^1$' "
|
||||||
|
"&& (cpprod_util CPPROD_GetValue FG1 FgSDWAN 1 | grep -q '^1$' && echo false || echo true) || "
|
||||||
|
"echo false",
|
||||||
|
checkQosLegacyBlade)
|
||||||
#endif //gaia || smb
|
#endif //gaia || smb
|
||||||
|
|
||||||
#if defined(gaia)
|
#if defined(gaia)
|
||||||
SHELL_CMD_HANDLER("hasSAMLSupportedBlade", "enabled_blades", checkSAMLSupportedBlade)
|
SHELL_CMD_HANDLER("hasSAMLSupportedBlade", "enabled_blades", checkSAMLSupportedBlade)
|
||||||
SHELL_CMD_HANDLER("hasIDABlade", "enabled_blades", checkIDABlade)
|
SHELL_CMD_HANDLER("hasIDABlade", "enabled_blades", checkIDABlade)
|
||||||
|
SHELL_CMD_HANDLER("hasVPNBlade", "enabled_blades", checkVPNBlade)
|
||||||
SHELL_CMD_HANDLER("hasSAMLPortal", "mpclient status nac", checkSAMLPortal)
|
SHELL_CMD_HANDLER("hasSAMLPortal", "mpclient status nac", checkSAMLPortal)
|
||||||
SHELL_CMD_HANDLER("hasIdaIdnEnabled", "fw ctl get int nac_pep_identity_next_enabled", checkPepIdaIdnStatus)
|
SHELL_CMD_HANDLER("hasInfinityIdentityEnabled",
|
||||||
SHELL_CMD_HANDLER("requiredNanoServices", "echo 'idaSaml_gaia;idaIdn_gaia;'", getRequiredNanoServices)
|
"cat $FWDIR/database/myself_objects.C | grep get_identities_from_infinity_identity",
|
||||||
|
checkInfinityIdentityEnabled
|
||||||
|
)
|
||||||
|
SHELL_CMD_HANDLER("requiredNanoServices", "echo ida", getRequiredNanoServices)
|
||||||
SHELL_CMD_HANDLER(
|
SHELL_CMD_HANDLER(
|
||||||
"cpProductIntegrationMgmtObjectName",
|
"cpProductIntegrationMgmtObjectName",
|
||||||
"mgmt_cli --format json -r true show-session | jq -r '.[\"connected-server\"].name'",
|
"mgmt_cli --format json -r true show-session | jq -r '.[\"connected-server\"].name'",
|
||||||
getMgmtObjName
|
getMgmtObjName
|
||||||
)
|
)
|
||||||
|
SHELL_CMD_HANDLER(
|
||||||
|
"cpProductIntegrationMgmtObjectUid",
|
||||||
|
"mgmt_cli --format json -r true show-session | jq -r '.[\"connected-server\"].uid'",
|
||||||
|
getMgmtObjUid
|
||||||
|
)
|
||||||
SHELL_CMD_HANDLER(
|
SHELL_CMD_HANDLER(
|
||||||
"cpProductIntegrationMgmtParentObjectName",
|
"cpProductIntegrationMgmtParentObjectName",
|
||||||
"cat $FWDIR/database/myself_objects.C "
|
"cat $FWDIR/database/myself_objects.C "
|
||||||
@@ -209,6 +222,14 @@ SHELL_CMD_HANDLER(
|
|||||||
"echo 1",
|
"echo 1",
|
||||||
extractManagements
|
extractManagements
|
||||||
)
|
)
|
||||||
|
SHELL_CMD_HANDLER(
|
||||||
|
"IP Address",
|
||||||
|
"( [ $(cpprod_util FwIsHighAvail) -eq 1 ] && [ $(cpprod_util FwIsVSX) -eq 1 ]"
|
||||||
|
"&& (jq -r .cluster_main_ip /tmp/cpsdwan_getdata_orch.json) )"
|
||||||
|
"|| ( [ $(cpprod_util FWisDAG) -eq 1 ] && echo \"Dynamic Address\" )"
|
||||||
|
"|| (jq -r .main_ip /tmp/cpsdwan_getdata_orch.json)",
|
||||||
|
getGWIPAddress
|
||||||
|
)
|
||||||
#endif //gaia
|
#endif //gaia
|
||||||
|
|
||||||
#if defined(smb) || defined(smb_thx_v3) || defined(smb_sve_v2) || defined(smb_mrv_v1)
|
#if defined(smb) || defined(smb_thx_v3) || defined(smb_sve_v2) || defined(smb_mrv_v1)
|
||||||
@@ -227,6 +248,11 @@ SHELL_CMD_HANDLER(
|
|||||||
"cpprod_util FwIsLocalMgmt",
|
"cpprod_util FwIsLocalMgmt",
|
||||||
getSmbObjectName
|
getSmbObjectName
|
||||||
)
|
)
|
||||||
|
SHELL_CMD_HANDLER(
|
||||||
|
"cpProductIntegrationMgmtObjectUid",
|
||||||
|
"cpprod_util FwIsLocalMgmt",
|
||||||
|
getSmbObjectUid
|
||||||
|
)
|
||||||
SHELL_CMD_HANDLER(
|
SHELL_CMD_HANDLER(
|
||||||
"Application Control",
|
"Application Control",
|
||||||
"cat $FWDIR/conf/active_blades.txt | grep -o 'APCL [01]' | cut -d ' ' -f2",
|
"cat $FWDIR/conf/active_blades.txt | grep -o 'APCL [01]' | cut -d ' ' -f2",
|
||||||
@@ -265,6 +291,17 @@ SHELL_CMD_HANDLER(
|
|||||||
"echo 1",
|
"echo 1",
|
||||||
extractManagements
|
extractManagements
|
||||||
)
|
)
|
||||||
|
SHELL_CMD_HANDLER(
|
||||||
|
"IP Address",
|
||||||
|
"[ $(cpprod_util FWisDAG) -eq 1 ] && echo \"Dynamic Address\" "
|
||||||
|
"|| (jq -r .main_ip /tmp/cpsdwan_getdata_orch.json)",
|
||||||
|
getGWIPAddress
|
||||||
|
)
|
||||||
|
SHELL_CMD_HANDLER(
|
||||||
|
"Hardware",
|
||||||
|
R"(ver | sed -E 's/^This is Check Point'\''s +([^ ]+).*$/\1/')",
|
||||||
|
getHardware
|
||||||
|
)
|
||||||
#endif//smb
|
#endif//smb
|
||||||
|
|
||||||
SHELL_CMD_OUTPUT("kernel_version", "uname -r")
|
SHELL_CMD_OUTPUT("kernel_version", "uname -r")
|
||||||
@@ -282,6 +319,11 @@ FILE_CONTENT_HANDLER(
|
|||||||
(getenv("SAMLPORTAL_HOME") ? string(getenv("SAMLPORTAL_HOME")) : "") + "/phpincs/spPortal/idpPolicy.xml",
|
(getenv("SAMLPORTAL_HOME") ? string(getenv("SAMLPORTAL_HOME")) : "") + "/phpincs/spPortal/idpPolicy.xml",
|
||||||
checkIDP
|
checkIDP
|
||||||
)
|
)
|
||||||
|
FILE_CONTENT_HANDLER(
|
||||||
|
"hasVPNCidpConfigured",
|
||||||
|
(getenv("SAMLPORTAL_HOME") ? string(getenv("SAMLPORTAL_HOME")) : "") + "/phpincs/spPortal/idpPolicy.xml",
|
||||||
|
checkVPNCIDP
|
||||||
|
)
|
||||||
#endif //gaia
|
#endif //gaia
|
||||||
|
|
||||||
#if defined(alpine)
|
#if defined(alpine)
|
||||||
|
|||||||
@@ -41,8 +41,13 @@ HTTPSClient::getFile(const URLParser &url, const string &out_file, bool auth_req
|
|||||||
|
|
||||||
if (!url.isOverSSL()) return genError("URL is not over SSL.");
|
if (!url.isOverSSL()) return genError("URL is not over SSL.");
|
||||||
|
|
||||||
if (getFileSSLDirect(url, out_file, token).ok()) return Maybe<void>();
|
bool skip_direct_download = (url.getQuery().find("/resources/") != string::npos);
|
||||||
dbgWarning(D_ORCHESTRATOR) << "Failed to get file over SSL directly. Trying indirectly.";
|
if (skip_direct_download) {
|
||||||
|
dbgWarning(D_ORCHESTRATOR) << "Resources path: " << url.getQuery() << ". Skipping direct download.";
|
||||||
|
} else {
|
||||||
|
if (getFileSSLDirect(url, out_file, token).ok()) return Maybe<void>();
|
||||||
|
dbgWarning(D_ORCHESTRATOR) << "Failed to get file over SSL directly. Trying indirectly.";
|
||||||
|
}
|
||||||
|
|
||||||
if (getFileSSL(url, out_file, token).ok()) return Maybe<void>();
|
if (getFileSSL(url, out_file, token).ok()) return Maybe<void>();
|
||||||
dbgWarning(D_ORCHESTRATOR) << "Failed to get file over SSL. Trying via CURL (SSL).";
|
dbgWarning(D_ORCHESTRATOR) << "Failed to get file over SSL. Trying via CURL (SSL).";
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
#include "maybe_res.h"
|
#include "maybe_res.h"
|
||||||
|
|
||||||
std::ostream &
|
std::ostream &
|
||||||
operator<<(std::ostream &os, const Maybe<std::tuple<std::string, std::string, std::string>> &)
|
operator<<(std::ostream &os, const Maybe<std::tuple<std::string, std::string, std::string, std::string>> &)
|
||||||
{
|
{
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
@@ -42,13 +42,14 @@ public:
|
|||||||
MOCK_METHOD0(getPlatform, Maybe<std::string>());
|
MOCK_METHOD0(getPlatform, Maybe<std::string>());
|
||||||
MOCK_METHOD0(getArch, Maybe<std::string>());
|
MOCK_METHOD0(getArch, Maybe<std::string>());
|
||||||
MOCK_METHOD0(getAgentVersion, std::string());
|
MOCK_METHOD0(getAgentVersion, std::string());
|
||||||
MOCK_METHOD0(isCloudStorageEnabled, bool());
|
MOCK_METHOD0(isCloudStorageEnabled, bool());
|
||||||
MOCK_METHOD0(isReverseProxy, bool());
|
MOCK_METHOD0(isReverseProxy, bool());
|
||||||
MOCK_METHOD0(isKernelVersion3OrHigher, bool());
|
MOCK_METHOD0(isKernelVersion3OrHigher, bool());
|
||||||
|
MOCK_METHOD0(isGw, bool());
|
||||||
MOCK_METHOD0(isGwNotVsx, bool());
|
MOCK_METHOD0(isGwNotVsx, bool());
|
||||||
MOCK_METHOD0(getResolvedDetails, std::map<std::string, std::string>());
|
MOCK_METHOD0(getResolvedDetails, std::map<std::string, std::string>());
|
||||||
MOCK_METHOD0(isVersionAboveR8110, bool());
|
MOCK_METHOD0(isVersionAboveR8110, bool());
|
||||||
MOCK_METHOD0(parseNginxMetadata, Maybe<std::tuple<std::string, std::string, std::string>>());
|
MOCK_METHOD0(parseNginxMetadata, Maybe<std::tuple<std::string, std::string, std::string, std::string>>());
|
||||||
MOCK_METHOD0(
|
MOCK_METHOD0(
|
||||||
readCloudMetadata, Maybe<std::tuple<std::string, std::string, std::string, std::string, std::string>>());
|
readCloudMetadata, Maybe<std::tuple<std::string, std::string, std::string, std::string, std::string>>());
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ private:
|
|||||||
string packages_dir;
|
string packages_dir;
|
||||||
string orch_service_name;
|
string orch_service_name;
|
||||||
set<string> ignore_packages;
|
set<string> ignore_packages;
|
||||||
|
Maybe<string> forbidden_versions = genError("Forbidden versions file does not exist");
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -135,7 +136,8 @@ ManifestController::Impl::init()
|
|||||||
"Ignore packages list file path"
|
"Ignore packages list file path"
|
||||||
);
|
);
|
||||||
|
|
||||||
if (Singleton::Consume<I_OrchestrationTools>::by<ManifestController>()->doesFileExist(ignore_packages_path)) {
|
auto orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<ManifestController>();
|
||||||
|
if (orchestration_tools->doesFileExist(ignore_packages_path)) {
|
||||||
try {
|
try {
|
||||||
ifstream input_stream(ignore_packages_path);
|
ifstream input_stream(ignore_packages_path);
|
||||||
if (!input_stream) {
|
if (!input_stream) {
|
||||||
@@ -156,6 +158,9 @@ ManifestController::Impl::init()
|
|||||||
<< " Error: " << f.what();
|
<< " Error: " << f.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const string forbidden_versions_path = getFilesystemPathConfig() + "/revert/forbidden_versions";
|
||||||
|
forbidden_versions = orchestration_tools->readFile(forbidden_versions_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -271,6 +276,17 @@ ManifestController::Impl::updateManifest(const string &new_manifest_file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
map<string, Package> new_packages = parsed_manifest.unpack();
|
map<string, Package> new_packages = parsed_manifest.unpack();
|
||||||
|
if (!new_packages.empty()) {
|
||||||
|
const Package &package = new_packages.begin()->second;
|
||||||
|
if (forbidden_versions.ok() &&
|
||||||
|
forbidden_versions.unpack().find(package.getVersion()) != string::npos
|
||||||
|
) {
|
||||||
|
dbgWarning(D_ORCHESTRATOR)
|
||||||
|
<< "Packages version is in the forbidden versions list. No upgrade will be performed.";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
map<string, Package> all_packages = parsed_manifest.unpack();
|
map<string, Package> all_packages = parsed_manifest.unpack();
|
||||||
map<string, Package> current_packages;
|
map<string, Package> current_packages;
|
||||||
parsed_manifest = orchestration_tools->loadPackagesFromJson(manifest_file_path);
|
parsed_manifest = orchestration_tools->loadPackagesFromJson(manifest_file_path);
|
||||||
|
|||||||
@@ -58,6 +58,9 @@ public:
|
|||||||
Debug::setUnitTestFlag(D_ORCHESTRATOR, Debug::DebugLevel::TRACE);
|
Debug::setUnitTestFlag(D_ORCHESTRATOR, Debug::DebugLevel::TRACE);
|
||||||
const string ignore_packages_file = "/etc/cp/conf/ignore-packages.txt";
|
const string ignore_packages_file = "/etc/cp/conf/ignore-packages.txt";
|
||||||
EXPECT_CALL(mock_orchestration_tools, doesFileExist(ignore_packages_file)).WillOnce(Return(false));
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist(ignore_packages_file)).WillOnce(Return(false));
|
||||||
|
Maybe<string> forbidden_versions(string("a1\na2"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, readFile("/etc/cp/revert/forbidden_versions"))
|
||||||
|
.WillOnce(Return(forbidden_versions));
|
||||||
manifest_controller.init();
|
manifest_controller.init();
|
||||||
manifest_file_path = getConfigurationWithDefault<string>(
|
manifest_file_path = getConfigurationWithDefault<string>(
|
||||||
"/etc/cp/conf/manifest.json",
|
"/etc/cp/conf/manifest.json",
|
||||||
@@ -224,6 +227,10 @@ TEST_F(ManifestControllerTest, createNewManifest)
|
|||||||
EXPECT_CALL(mock_orchestration_tools, copyFile(file_name, manifest_file_path)).WillOnce(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, copyFile(file_name, manifest_file_path)).WillOnce(Return(true));
|
||||||
EXPECT_CALL(mock_orchestration_tools, isNonEmptyFile(manifest_file_path)).WillOnce(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, isNonEmptyFile(manifest_file_path)).WillOnce(Return(true));
|
||||||
EXPECT_CALL(mock_orchestration_tools, removeFile(file_name)).WillOnce(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, removeFile(file_name)).WillOnce(Return(true));
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillOnce(Return("b"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/upgrade_status")).WillOnce(Return(false));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, writeFile(_, "/etc/cp/revert/upgrade_status", false))
|
||||||
|
.WillOnce(Return(true));
|
||||||
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,6 +370,11 @@ TEST_F(ManifestControllerTest, updateManifest)
|
|||||||
EXPECT_CALL(mock_orchestration_tools, isNonEmptyFile(manifest_file_path)).Times(2).WillRepeatedly(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, isNonEmptyFile(manifest_file_path)).Times(2).WillRepeatedly(Return(true));
|
||||||
EXPECT_CALL(mock_orchestration_tools, removeFile(file_name)).Times(2).WillRepeatedly(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, removeFile(file_name)).Times(2).WillRepeatedly(Return(true));
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillOnce(Return("b"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/upgrade_status")).WillOnce(Return(false));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, writeFile(_, "/etc/cp/revert/upgrade_status", false))
|
||||||
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
||||||
|
|
||||||
manifest =
|
manifest =
|
||||||
@@ -417,6 +429,9 @@ TEST_F(ManifestControllerTest, updateManifest)
|
|||||||
EXPECT_CALL(mock_orchestration_tools, loadPackagesFromJson(file_name)).WillOnce(Return(new_services));
|
EXPECT_CALL(mock_orchestration_tools, loadPackagesFromJson(file_name)).WillOnce(Return(new_services));
|
||||||
EXPECT_CALL(mock_orchestration_tools,
|
EXPECT_CALL(mock_orchestration_tools,
|
||||||
loadPackagesFromJson(manifest_file_path)).WillOnce(Return(old_services));
|
loadPackagesFromJson(manifest_file_path)).WillOnce(Return(old_services));
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillOnce(Return("b"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/upgrade_status")).WillRepeatedly(Return(true));
|
||||||
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,6 +493,11 @@ TEST_F(ManifestControllerTest, selfUpdate)
|
|||||||
|
|
||||||
EXPECT_CALL(mock_orchestration_tools, copyFile("/tmp/temp_file", path +
|
EXPECT_CALL(mock_orchestration_tools, copyFile("/tmp/temp_file", path +
|
||||||
temp_ext)).WillOnce(Return(true));
|
temp_ext)).WillOnce(Return(true));
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillOnce(Return("b"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/upgrade_status")).WillOnce(Return(false));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, writeFile(_, "/etc/cp/revert/upgrade_status", false))
|
||||||
|
.WillOnce(Return(true));
|
||||||
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -607,6 +627,10 @@ TEST_F(ManifestControllerTest, removeCurrentErrorPackage)
|
|||||||
EXPECT_CALL(mock_orchestration_tools, isNonEmptyFile(manifest_file_path)).WillOnce(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, isNonEmptyFile(manifest_file_path)).WillOnce(Return(true));
|
||||||
EXPECT_CALL(mock_orchestration_tools, removeFile(file_name)).WillOnce(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, removeFile(file_name)).WillOnce(Return(true));
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillOnce(Return("b"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/upgrade_status")).WillOnce(Return(false));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, writeFile(_, "/etc/cp/revert/upgrade_status", false))
|
||||||
|
.WillOnce(Return(true));
|
||||||
corrupted_packages.clear();
|
corrupted_packages.clear();
|
||||||
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
||||||
}
|
}
|
||||||
@@ -666,6 +690,10 @@ TEST_F(ManifestControllerTest, selfUpdateWithOldCopy)
|
|||||||
|
|
||||||
EXPECT_CALL(mock_orchestration_tools, copyFile("/tmp/temp_file", path +
|
EXPECT_CALL(mock_orchestration_tools, copyFile("/tmp/temp_file", path +
|
||||||
temp_ext)).WillOnce(Return(true));
|
temp_ext)).WillOnce(Return(true));
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillOnce(Return("b"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/upgrade_status")).WillOnce(Return(false));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, writeFile(_, "/etc/cp/revert/upgrade_status", false))
|
||||||
|
.WillOnce(Return(true));
|
||||||
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -722,6 +750,10 @@ TEST_F(ManifestControllerTest, selfUpdateWithOldCopyWithError)
|
|||||||
EXPECT_CALL(mock_orchestration_tools, doesFileExist(path)).WillOnce(Return(false)).WillOnce(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist(path)).WillOnce(Return(false)).WillOnce(Return(true));
|
||||||
EXPECT_CALL(mock_orchestration_tools, copyFile(path, path + backup_ext + temp_ext)).WillOnce(Return(false));
|
EXPECT_CALL(mock_orchestration_tools, copyFile(path, path + backup_ext + temp_ext)).WillOnce(Return(false));
|
||||||
EXPECT_CALL(mock_details_resolver, getHostname()).WillOnce(Return(hostname));
|
EXPECT_CALL(mock_details_resolver, getHostname()).WillOnce(Return(hostname));
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillOnce(Return("b"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/upgrade_status")).WillOnce(Return(false));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, writeFile(_, "/etc/cp/revert/upgrade_status", false))
|
||||||
|
.WillOnce(Return(true));
|
||||||
EXPECT_FALSE(i_manifest_controller->updateManifest(file_name));
|
EXPECT_FALSE(i_manifest_controller->updateManifest(file_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -798,6 +830,10 @@ TEST_F(ManifestControllerTest, installAndRemove)
|
|||||||
EXPECT_CALL(mock_orchestration_tools, isNonEmptyFile(manifest_file_path)).Times(2).WillRepeatedly(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, isNonEmptyFile(manifest_file_path)).Times(2).WillRepeatedly(Return(true));
|
||||||
EXPECT_CALL(mock_orchestration_tools, removeFile(file_name)).Times(2).WillRepeatedly(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, removeFile(file_name)).Times(2).WillRepeatedly(Return(true));
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillOnce(Return("b"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/upgrade_status")).WillOnce(Return(false));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, writeFile(_, "/etc/cp/revert/upgrade_status", false))
|
||||||
|
.WillOnce(Return(true));
|
||||||
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
||||||
|
|
||||||
string new_manifest =
|
string new_manifest =
|
||||||
@@ -858,6 +894,63 @@ TEST_F(ManifestControllerTest, installAndRemove)
|
|||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/packages/my1/my1")).Times(2)
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/packages/my1/my1")).Times(2)
|
||||||
.WillOnce(Return(false));
|
.WillOnce(Return(false));
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillOnce(Return("b"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/upgrade_status")).WillRepeatedly(Return(true));
|
||||||
|
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ManifestControllerTest, manifestWithForbiddenVersion)
|
||||||
|
{
|
||||||
|
new_services.clear();
|
||||||
|
old_services.clear();
|
||||||
|
|
||||||
|
string manifest =
|
||||||
|
"{"
|
||||||
|
" \"packages\": ["
|
||||||
|
" {"
|
||||||
|
" \"download-path\": \"http://172.23.92.135/my.sh\","
|
||||||
|
" \"relative-path\": \"\","
|
||||||
|
" \"name\": \"my\","
|
||||||
|
" \"version\": \"a1\","
|
||||||
|
" \"checksum-type\": \"sha1sum\","
|
||||||
|
" \"checksum\": \"a58bbab8020b0e6d08568714b5e582a3adf9c805\","
|
||||||
|
" \"package-type\": \"service\","
|
||||||
|
" \"require\": []"
|
||||||
|
" },"
|
||||||
|
" {"
|
||||||
|
" \"download-path\": \"http://172.23.92.135/my.sh\","
|
||||||
|
" \"relative-path\": \"\","
|
||||||
|
" \"name\": \"orchestration\","
|
||||||
|
" \"version\": \"a1\","
|
||||||
|
" \"checksum-type\": \"sha1sum\","
|
||||||
|
" \"checksum\": \"a58bbab8020b0e6d08568714b5e582a3adf9c805\","
|
||||||
|
" \"package-type\": \"service\","
|
||||||
|
" \"require\": []"
|
||||||
|
" },"
|
||||||
|
" {"
|
||||||
|
" \"download-path\": \"\","
|
||||||
|
" \"relative-path\": \"\","
|
||||||
|
" \"name\": \"waap\","
|
||||||
|
" \"version\": \"a1\","
|
||||||
|
" \"checksum-type\": \"sha1sum\","
|
||||||
|
" \"checksum\": \"\","
|
||||||
|
" \"package-type\": \"service\","
|
||||||
|
" \"status\": false,\n"
|
||||||
|
" \"message\": \"This security app isn't valid for this agent\"\n"
|
||||||
|
" }"
|
||||||
|
" ]"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
map<string, Package> manifest_services;
|
||||||
|
load(manifest, manifest_services);
|
||||||
|
checkIfFileExistsCall(manifest_services.at("my"));
|
||||||
|
|
||||||
|
|
||||||
|
load(manifest, new_services);
|
||||||
|
load(old_manifest, old_services);
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, loadPackagesFromJson(file_name)).WillOnce(Return(new_services));
|
||||||
|
|
||||||
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -947,6 +1040,10 @@ TEST_F(ManifestControllerTest, badInstall)
|
|||||||
EXPECT_CALL(mock_orchestration_tools,
|
EXPECT_CALL(mock_orchestration_tools,
|
||||||
packagesToJsonFile(corrupted_packages, corrupted_file_list)).WillOnce(Return(true));
|
packagesToJsonFile(corrupted_packages, corrupted_file_list)).WillOnce(Return(true));
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillOnce(Return("b"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/upgrade_status")).WillOnce(Return(false));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, writeFile(_, "/etc/cp/revert/upgrade_status", false))
|
||||||
|
.WillOnce(Return(true));
|
||||||
EXPECT_FALSE(i_manifest_controller->updateManifest(file_name));
|
EXPECT_FALSE(i_manifest_controller->updateManifest(file_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1112,6 +1209,12 @@ TEST_F(ManifestControllerTest, requireUpdate)
|
|||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
EXPECT_CALL(mock_orchestration_tools, isNonEmptyFile(manifest_file_path)).WillOnce(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, isNonEmptyFile(manifest_file_path)).WillOnce(Return(true));
|
||||||
EXPECT_CALL(mock_orchestration_tools, removeFile("new_manifest.json")).WillOnce(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, removeFile("new_manifest.json")).WillOnce(Return(true));
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillRepeatedly(Return("b"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/upgrade_status"))
|
||||||
|
.WillOnce(Return(false))
|
||||||
|
.WillRepeatedly(Return(true));;
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, writeFile(_, "/etc/cp/revert/upgrade_status", false))
|
||||||
|
.WillOnce(Return(true));
|
||||||
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1212,6 +1315,10 @@ TEST_F(ManifestControllerTest, sharedObjectNotInstalled)
|
|||||||
).WillOnce(Return(true));
|
).WillOnce(Return(true));
|
||||||
EXPECT_CALL(mock_orchestration_tools, copyFile("/tmp/temp_file1", path +
|
EXPECT_CALL(mock_orchestration_tools, copyFile("/tmp/temp_file1", path +
|
||||||
temp_ext)).WillOnce(Return(true));
|
temp_ext)).WillOnce(Return(true));
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillOnce(Return("b"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/upgrade_status")).WillOnce(Return(false));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, writeFile(_, "/etc/cp/revert/upgrade_status", false))
|
||||||
|
.WillOnce(Return(true));
|
||||||
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1313,6 +1420,12 @@ TEST_F(ManifestControllerTest, requireSharedObjectUpdate)
|
|||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
EXPECT_CALL(mock_orchestration_tools, removeFile("new_manifest.json"))
|
EXPECT_CALL(mock_orchestration_tools, removeFile("new_manifest.json"))
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillRepeatedly(Return("b"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/upgrade_status"))
|
||||||
|
.WillOnce(Return(false))
|
||||||
|
.WillRepeatedly(Return(true));;
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, writeFile(_, "/etc/cp/revert/upgrade_status", false))
|
||||||
|
.WillOnce(Return(true));
|
||||||
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1389,6 +1502,7 @@ TEST_F(ManifestControllerTest, failureOnDownloadSharedObject)
|
|||||||
EXPECT_CALL(mock_details_resolver, getHostname()).WillOnce(Return(string("hostname")));
|
EXPECT_CALL(mock_details_resolver, getHostname()).WillOnce(Return(string("hostname")));
|
||||||
EXPECT_CALL(mock_orchestration_tools, removeFile("/tmp/temp_file1")).WillOnce(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, removeFile("/tmp/temp_file1")).WillOnce(Return(true));
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillRepeatedly(Return("b"));
|
||||||
EXPECT_FALSE(i_manifest_controller->updateManifest(file_name));
|
EXPECT_FALSE(i_manifest_controller->updateManifest(file_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1524,6 +1638,12 @@ TEST_F(ManifestControllerTest, multiRequireUpdate)
|
|||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
EXPECT_CALL(mock_orchestration_tools, removeFile("new_manifest.json"))
|
EXPECT_CALL(mock_orchestration_tools, removeFile("new_manifest.json"))
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillRepeatedly(Return("b"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/upgrade_status"))
|
||||||
|
.WillOnce(Return(false))
|
||||||
|
.WillRepeatedly(Return(true));;
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, writeFile(_, "/etc/cp/revert/upgrade_status", false))
|
||||||
|
.WillOnce(Return(true));
|
||||||
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1610,6 +1730,12 @@ TEST_F(ManifestControllerTest, createNewManifestWithUninstallablePackage)
|
|||||||
EXPECT_CALL(mock_orchestration_tools, isNonEmptyFile(manifest_file_path)).WillOnce(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, isNonEmptyFile(manifest_file_path)).WillOnce(Return(true));
|
||||||
EXPECT_CALL(mock_orchestration_tools, removeFile(file_name)).WillOnce(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, removeFile(file_name)).WillOnce(Return(true));
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillRepeatedly(Return("b"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/upgrade_status"))
|
||||||
|
.WillOnce(Return(false))
|
||||||
|
.WillRepeatedly(Return(true));;
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, writeFile(_, "/etc/cp/revert/upgrade_status", false))
|
||||||
|
.WillOnce(Return(true));
|
||||||
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1624,7 +1750,7 @@ TEST_F(ManifestControllerTest, updateUninstallPackage)
|
|||||||
" \"download-path\": \"\","
|
" \"download-path\": \"\","
|
||||||
" \"relative-path\": \"\","
|
" \"relative-path\": \"\","
|
||||||
" \"name\": \"my\","
|
" \"name\": \"my\","
|
||||||
" \"version\": \"\","
|
" \"version\": \"c\","
|
||||||
" \"checksum-type\": \"sha1sum\","
|
" \"checksum-type\": \"sha1sum\","
|
||||||
" \"checksum\": \"\","
|
" \"checksum\": \"\","
|
||||||
" \"package-type\": \"service\","
|
" \"package-type\": \"service\","
|
||||||
@@ -1721,6 +1847,11 @@ TEST_F(ManifestControllerTest, updateUninstallPackage)
|
|||||||
EXPECT_CALL(mock_orchestration_tools, loadPackagesFromJson(file_name)).WillOnce(Return(new_services));
|
EXPECT_CALL(mock_orchestration_tools, loadPackagesFromJson(file_name)).WillOnce(Return(new_services));
|
||||||
EXPECT_CALL(mock_orchestration_tools,
|
EXPECT_CALL(mock_orchestration_tools,
|
||||||
loadPackagesFromJson(manifest_file_path)).WillOnce(Return(old_services));
|
loadPackagesFromJson(manifest_file_path)).WillOnce(Return(old_services));
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillOnce(Return("b"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/upgrade_status")).WillOnce(Return(false));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, writeFile(_, "/etc/cp/revert/upgrade_status", false))
|
||||||
|
.WillOnce(Return(true));
|
||||||
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1744,6 +1875,9 @@ public:
|
|||||||
setConfiguration<string>(ignore_packages_file, "orchestration", "Ignore packages list file path");
|
setConfiguration<string>(ignore_packages_file, "orchestration", "Ignore packages list file path");
|
||||||
writeIgnoreList(ignore_packages_file, ignore_services);
|
writeIgnoreList(ignore_packages_file, ignore_services);
|
||||||
EXPECT_CALL(mock_orchestration_tools, doesFileExist(ignore_packages_file)).WillOnce(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist(ignore_packages_file)).WillOnce(Return(true));
|
||||||
|
Maybe<string> forbidden_versions(string("a1\na2"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, readFile("/etc/cp/revert/forbidden_versions"))
|
||||||
|
.WillOnce(Return(forbidden_versions));
|
||||||
manifest_controller.init();
|
manifest_controller.init();
|
||||||
manifest_file_path = getConfigurationWithDefault<string>(
|
manifest_file_path = getConfigurationWithDefault<string>(
|
||||||
"/etc/cp/conf/manifest.json",
|
"/etc/cp/conf/manifest.json",
|
||||||
@@ -1839,6 +1973,7 @@ public:
|
|||||||
StrictMock<MockOrchestrationStatus> mock_status;
|
StrictMock<MockOrchestrationStatus> mock_status;
|
||||||
StrictMock<MockDownloader> mock_downloader;
|
StrictMock<MockDownloader> mock_downloader;
|
||||||
StrictMock<MockOrchestrationTools> mock_orchestration_tools;
|
StrictMock<MockOrchestrationTools> mock_orchestration_tools;
|
||||||
|
StrictMock<MockDetailsResolver> mock_details_resolver;
|
||||||
NiceMock<MockShellCmd> mock_shell_cmd;
|
NiceMock<MockShellCmd> mock_shell_cmd;
|
||||||
|
|
||||||
ManifestController manifest_controller;
|
ManifestController manifest_controller;
|
||||||
@@ -2122,6 +2257,12 @@ TEST_F(ManifestControllerIgnorePakckgeTest, addIgnorePackageAndUpdateNormal)
|
|||||||
EXPECT_CALL(mock_orchestration_tools, isNonEmptyFile(manifest_file_path)).WillOnce(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, isNonEmptyFile(manifest_file_path)).WillOnce(Return(true));
|
||||||
EXPECT_CALL(mock_orchestration_tools, removeFile(file_name)).WillOnce(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, removeFile(file_name)).WillOnce(Return(true));
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillRepeatedly(Return("b"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/upgrade_status"))
|
||||||
|
.WillOnce(Return(false))
|
||||||
|
.WillRepeatedly(Return(true));;
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, writeFile(_, "/etc/cp/revert/upgrade_status", false))
|
||||||
|
.WillOnce(Return(true));
|
||||||
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2387,6 +2528,12 @@ TEST_F(ManifestControllerIgnorePakckgeTest, overrideIgnoredPackageFromProfileSet
|
|||||||
EXPECT_CALL(mock_orchestration_tools, isNonEmptyFile(manifest_file_path)).WillOnce(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, isNonEmptyFile(manifest_file_path)).WillOnce(Return(true));
|
||||||
EXPECT_CALL(mock_orchestration_tools, removeFile(file_name)).WillOnce(Return(true));
|
EXPECT_CALL(mock_orchestration_tools, removeFile(file_name)).WillOnce(Return(true));
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillRepeatedly(Return("b"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/upgrade_status"))
|
||||||
|
.WillOnce(Return(false))
|
||||||
|
.WillRepeatedly(Return(true));;
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, writeFile(_, "/etc/cp/revert/upgrade_status", false))
|
||||||
|
.WillOnce(Return(true));
|
||||||
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
EXPECT_TRUE(i_manifest_controller->updateManifest(file_name));
|
||||||
|
|
||||||
EXPECT_THAT(capture_debug.str(), Not(HasSubstr("Ignoring a package from the manifest. Package name: my")));
|
EXPECT_THAT(capture_debug.str(), Not(HasSubstr("Ignoring a package from the manifest. Package name: my")));
|
||||||
@@ -2411,6 +2558,9 @@ public:
|
|||||||
doesFileExist("/etc/cp/conf/ignore-packages.txt")
|
doesFileExist("/etc/cp/conf/ignore-packages.txt")
|
||||||
).WillOnce(Return(false));
|
).WillOnce(Return(false));
|
||||||
|
|
||||||
|
Maybe<string> forbidden_versions(string("a1\na2"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, readFile("/etc/cp/revert/forbidden_versions"))
|
||||||
|
.WillOnce(Return(forbidden_versions));
|
||||||
manifest_controller.init();
|
manifest_controller.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -115,9 +115,9 @@ ManifestDiffCalculator::buildRecInstallationQueue(
|
|||||||
const map<string, Package> ¤t_packages,
|
const map<string, Package> ¤t_packages,
|
||||||
const map<string, Package> &new_packages)
|
const map<string, Package> &new_packages)
|
||||||
{
|
{
|
||||||
const vector<string> &requires = package.getRequire();
|
const vector<string> &requires_packages = package.getRequire();
|
||||||
|
|
||||||
for (const auto &require : requires) {
|
for (const auto &require : requires_packages) {
|
||||||
auto installed_package = current_packages.find(require);
|
auto installed_package = current_packages.find(require);
|
||||||
auto new_package = new_packages.find(require);
|
auto new_package = new_packages.find(require);
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "manifest_handler.h"
|
#include "manifest_handler.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@@ -201,18 +202,29 @@ ManifestHandler::installPackage(
|
|||||||
auto span_scope = i_env->startNewSpanScope(Span::ContextType::CHILD_OF);
|
auto span_scope = i_env->startNewSpanScope(Span::ContextType::CHILD_OF);
|
||||||
auto orchestration_status = Singleton::Consume<I_OrchestrationStatus>::by<ManifestHandler>();
|
auto orchestration_status = Singleton::Consume<I_OrchestrationStatus>::by<ManifestHandler>();
|
||||||
|
|
||||||
|
auto details_resolver = Singleton::Consume<I_DetailsResolver>::by<ManifestHandler>();
|
||||||
|
auto orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<ManifestHandler>();
|
||||||
|
|
||||||
auto &package = package_downloaded_file.first;
|
auto &package = package_downloaded_file.first;
|
||||||
auto &package_name = package.getName();
|
auto &package_name = package.getName();
|
||||||
auto &package_handler_path = package_downloaded_file.second;
|
auto &package_handler_path = package_downloaded_file.second;
|
||||||
|
|
||||||
dbgInfo(D_ORCHESTRATOR) << "Handling package installation. Package: " << package_name;
|
dbgInfo(D_ORCHESTRATOR) << "Handling package installation. Package: " << package_name;
|
||||||
|
|
||||||
|
string upgrade_info =
|
||||||
|
details_resolver->getAgentVersion() + " " + package.getVersion() + " " + getCurrentTimestamp();
|
||||||
|
if (!orchestration_tools->doesFileExist(getFilesystemPathConfig() + "/revert/upgrade_status") &&
|
||||||
|
!orchestration_tools->writeFile(upgrade_info, getFilesystemPathConfig() + "/revert/upgrade_status")
|
||||||
|
) {
|
||||||
|
dbgWarning(D_ORCHESTRATOR) << "Failed to write to " + getFilesystemPathConfig() + "/revert/upgrade_status";
|
||||||
|
}
|
||||||
|
|
||||||
if (package_name.compare(orch_service_name) == 0) {
|
if (package_name.compare(orch_service_name) == 0) {
|
||||||
orchestration_status->writeStatusToFile();
|
orchestration_status->writeStatusToFile();
|
||||||
bool self_update_status = selfUpdate(package, current_packages, package_handler_path);
|
bool self_update_status = selfUpdate(package, current_packages, package_handler_path);
|
||||||
if (!self_update_status) {
|
if (!self_update_status) {
|
||||||
auto details = Singleton::Consume<I_AgentDetails>::by<ManifestHandler>();
|
auto details = Singleton::Consume<I_AgentDetails>::by<ManifestHandler>();
|
||||||
auto hostname = Singleton::Consume<I_DetailsResolver>::by<ManifestHandler>()->getHostname();
|
auto hostname = details_resolver->getHostname();
|
||||||
string err_hostname = (hostname.ok() ? "on host '" + *hostname : "'" + details->getAgentId()) + "'";
|
string err_hostname = (hostname.ok() ? "on host '" + *hostname : "'" + details->getAgentId()) + "'";
|
||||||
string install_error =
|
string install_error =
|
||||||
"Warning: Agent/Gateway " +
|
"Warning: Agent/Gateway " +
|
||||||
@@ -246,7 +258,6 @@ ManifestHandler::installPackage(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
string current_installation_file = packages_dir + "/" + package_name + "/" + package_name;
|
string current_installation_file = packages_dir + "/" + package_name + "/" + package_name;
|
||||||
auto orchestration_tools = Singleton::Consume<I_OrchestrationTools>::by<ManifestHandler>();
|
|
||||||
bool is_clean_installation = !orchestration_tools->doesFileExist(current_installation_file);
|
bool is_clean_installation = !orchestration_tools->doesFileExist(current_installation_file);
|
||||||
|
|
||||||
|
|
||||||
@@ -368,3 +379,13 @@ ManifestHandler::selfUpdate(
|
|||||||
package_handler->preInstallPackage(orch_service_name, current_installation_file) &&
|
package_handler->preInstallPackage(orch_service_name, current_installation_file) &&
|
||||||
package_handler->installPackage(orch_service_name, current_installation_file, false);
|
package_handler->installPackage(orch_service_name, current_installation_file, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
ManifestHandler::getCurrentTimestamp()
|
||||||
|
{
|
||||||
|
time_t now = time(nullptr);
|
||||||
|
tm* now_tm = localtime(&now);
|
||||||
|
char timestamp[20];
|
||||||
|
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", now_tm);
|
||||||
|
return string(timestamp);
|
||||||
|
}
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ USE_DEBUG_FLAG(D_ORCHESTRATOR);
|
|||||||
static string fw_last_update_time = "";
|
static string fw_last_update_time = "";
|
||||||
#endif // gaia || smb
|
#endif // gaia || smb
|
||||||
|
|
||||||
|
static const size_t MAX_SERVER_NAME_LENGTH = 253;
|
||||||
|
|
||||||
class SetAgentUninstall
|
class SetAgentUninstall
|
||||||
:
|
:
|
||||||
public ServerRest,
|
public ServerRest,
|
||||||
@@ -103,6 +105,19 @@ public:
|
|||||||
<< "Initializing Orchestration component, file system path prefix: "
|
<< "Initializing Orchestration component, file system path prefix: "
|
||||||
<< filesystem_prefix;
|
<< filesystem_prefix;
|
||||||
|
|
||||||
|
int check_upgrade_success_interval = getSettingWithDefault<uint>(10, "successUpgradeInterval");
|
||||||
|
Singleton::Consume<I_MainLoop>::by<OrchestrationComp>()->addOneTimeRoutine(
|
||||||
|
I_MainLoop::RoutineType::Timer,
|
||||||
|
[this, check_upgrade_success_interval]()
|
||||||
|
{
|
||||||
|
Singleton::Consume<I_MainLoop>::by<OrchestrationComp>()->yield(
|
||||||
|
std::chrono::minutes(check_upgrade_success_interval)
|
||||||
|
);
|
||||||
|
processUpgradeCompletion();
|
||||||
|
},
|
||||||
|
"Orchestration successfully updated (One-Time After Interval)",
|
||||||
|
true
|
||||||
|
);
|
||||||
auto orch_policy = loadDefaultOrchestrationPolicy();
|
auto orch_policy = loadDefaultOrchestrationPolicy();
|
||||||
if (!orch_policy.ok()) {
|
if (!orch_policy.ok()) {
|
||||||
dbgWarning(D_ORCHESTRATOR) << "Failed to load Orchestration Policy. Error: " << orch_policy.getErr();
|
dbgWarning(D_ORCHESTRATOR) << "Failed to load Orchestration Policy. Error: " << orch_policy.getErr();
|
||||||
@@ -141,6 +156,113 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void
|
||||||
|
saveLastKnownOrchInfo(string curr_agent_version)
|
||||||
|
{
|
||||||
|
static const string upgrades_dir = filesystem_prefix + "/revert";
|
||||||
|
static const string last_known_orchestrator = upgrades_dir + "/last_known_working_orchestrator";
|
||||||
|
static const string current_orchestration_package =
|
||||||
|
filesystem_prefix + "/packages/orchestration/orchestration";
|
||||||
|
static const string last_known_manifest = upgrades_dir + "/last_known_manifest";
|
||||||
|
static const string current_manifest_file = getConfigurationWithDefault<string>(
|
||||||
|
filesystem_prefix + "/conf/manifest.json",
|
||||||
|
"orchestration",
|
||||||
|
"Manifest file path"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!i_orchestration_tools->copyFile(current_orchestration_package, last_known_orchestrator)) {
|
||||||
|
dbgWarning(D_ORCHESTRATOR) << "Failed to copy the orchestration package to " << upgrades_dir;
|
||||||
|
} else {
|
||||||
|
dbgInfo(D_ORCHESTRATOR) << "last known orchestrator version updated to: " << curr_agent_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!i_orchestration_tools->copyFile(current_manifest_file, last_known_manifest)) {
|
||||||
|
dbgWarning(D_ORCHESTRATOR) << "Failed to copy " << current_manifest_file << " to " << upgrades_dir;
|
||||||
|
} else {
|
||||||
|
dbgInfo(D_ORCHESTRATOR) << "last known manifest updated";
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
processUpgradeCompletion()
|
||||||
|
{
|
||||||
|
if (!is_first_check_update_success) {
|
||||||
|
int check_upgrade_success_interval = getSettingWithDefault<uint>(10, "successUpgradeInterval");
|
||||||
|
// LCOV_EXCL_START
|
||||||
|
Singleton::Consume<I_MainLoop>::by<OrchestrationComp>()->addOneTimeRoutine(
|
||||||
|
I_MainLoop::RoutineType::Timer,
|
||||||
|
[this, check_upgrade_success_interval]()
|
||||||
|
{
|
||||||
|
Singleton::Consume<I_MainLoop>::by<OrchestrationComp>()->yield(
|
||||||
|
std::chrono::minutes(check_upgrade_success_interval)
|
||||||
|
);
|
||||||
|
processUpgradeCompletion();
|
||||||
|
},
|
||||||
|
"Orchestration successfully updated",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
// LCOV_EXCL_STOP
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const string upgrades_dir = filesystem_prefix + "/revert";
|
||||||
|
static const string upgrade_status = upgrades_dir + "/upgrade_status";
|
||||||
|
static const string last_known_orchestrator = upgrades_dir + "/last_known_working_orchestrator";
|
||||||
|
static const string upgrade_failure_info_path = upgrades_dir + "/failed_upgrade_info";
|
||||||
|
|
||||||
|
I_DetailsResolver *i_details_resolver = Singleton::Consume<I_DetailsResolver>::by<OrchestrationComp>();
|
||||||
|
|
||||||
|
bool is_upgrade_status_exist = i_orchestration_tools->doesFileExist(upgrade_status);
|
||||||
|
bool is_last_known_orchestrator_exist = i_orchestration_tools->doesFileExist(last_known_orchestrator);
|
||||||
|
|
||||||
|
if (!is_upgrade_status_exist) {
|
||||||
|
if (!is_last_known_orchestrator_exist) {
|
||||||
|
saveLastKnownOrchInfo(i_details_resolver->getAgentVersion());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto maybe_upgrade_data = i_orchestration_tools->readFile(upgrade_status);
|
||||||
|
string upgrade_data, from_version, to_version;
|
||||||
|
if (maybe_upgrade_data.ok()) {
|
||||||
|
upgrade_data = maybe_upgrade_data.unpack();
|
||||||
|
istringstream stream(upgrade_data);
|
||||||
|
stream >> from_version >> to_version;
|
||||||
|
}
|
||||||
|
i_orchestration_tools->removeFile(upgrade_status);
|
||||||
|
|
||||||
|
if (i_orchestration_tools->doesFileExist(upgrade_failure_info_path)) {
|
||||||
|
string info = "Orchestration revert. ";
|
||||||
|
auto failure_info = i_orchestration_tools->readFile(upgrade_failure_info_path);
|
||||||
|
if (failure_info.ok()) info.append(failure_info.unpack());
|
||||||
|
LogGen(
|
||||||
|
info,
|
||||||
|
ReportIS::Level::ACTION,
|
||||||
|
ReportIS::Audience::INTERNAL,
|
||||||
|
ReportIS::Severity::CRITICAL,
|
||||||
|
ReportIS::Priority::URGENT,
|
||||||
|
ReportIS::Tags::ORCHESTRATOR
|
||||||
|
);
|
||||||
|
dbgError(D_ORCHESTRATOR) <<
|
||||||
|
"Error in orchestration version: " << to_version <<
|
||||||
|
". Orchestration reverted to version: " << i_details_resolver->getAgentVersion();
|
||||||
|
i_orchestration_tools->removeFile(upgrade_failure_info_path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
saveLastKnownOrchInfo(i_details_resolver->getAgentVersion());
|
||||||
|
i_orchestration_tools->writeFile(
|
||||||
|
upgrade_data + "\n",
|
||||||
|
getLogFilesPathConfig() + "/nano_agent/prev_upgrades",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
dbgWarning(D_ORCHESTRATOR) <<
|
||||||
|
"Upgrade process from version: " << from_version <<
|
||||||
|
" to version: " << to_version <<
|
||||||
|
" completed successfully";
|
||||||
|
}
|
||||||
|
|
||||||
Maybe<void>
|
Maybe<void>
|
||||||
registerToTheFog()
|
registerToTheFog()
|
||||||
{
|
{
|
||||||
@@ -1022,6 +1144,7 @@ private:
|
|||||||
UpdatesProcessResult::SUCCESS,
|
UpdatesProcessResult::SUCCESS,
|
||||||
UpdatesConfigType::GENERAL
|
UpdatesConfigType::GENERAL
|
||||||
).notify();
|
).notify();
|
||||||
|
if (!is_first_check_update_success) is_first_check_update_success = true;
|
||||||
return Maybe<void>();
|
return Maybe<void>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1342,14 +1465,18 @@ private:
|
|||||||
|
|
||||||
auto nginx_data = i_details_resolver->parseNginxMetadata();
|
auto nginx_data = i_details_resolver->parseNginxMetadata();
|
||||||
if (nginx_data.ok()) {
|
if (nginx_data.ok()) {
|
||||||
|
string nginx_signature;
|
||||||
string nginx_version;
|
string nginx_version;
|
||||||
string config_opt;
|
string config_opt;
|
||||||
string cc_opt;
|
string cc_opt;
|
||||||
tie(config_opt, cc_opt, nginx_version) = nginx_data.unpack();
|
tie(config_opt, cc_opt, nginx_version, nginx_signature) = nginx_data.unpack();
|
||||||
agent_data_report
|
agent_data_report
|
||||||
<< make_pair("nginxVersion", nginx_version)
|
<< make_pair("configureOptStatus", "Enabled")
|
||||||
<< make_pair("configureOpt", config_opt)
|
<< make_pair("moduleSignatureStatus", "Enabled")
|
||||||
<< make_pair("extraCompilerOpt", cc_opt);
|
<< make_pair("nginxSignature", nginx_signature)
|
||||||
|
<< make_pair("nginxVersion", nginx_version)
|
||||||
|
<< make_pair("configureOpt", config_opt)
|
||||||
|
<< make_pair("extraCompilerOpt", cc_opt);
|
||||||
} else {
|
} else {
|
||||||
dbgDebug(D_ORCHESTRATOR) << nginx_data.getErr();
|
dbgDebug(D_ORCHESTRATOR) << nginx_data.getErr();
|
||||||
}
|
}
|
||||||
@@ -1370,6 +1497,10 @@ private:
|
|||||||
agent_data_report << AgentReportFieldWithLabel("isKernelVersion3OrHigher", "true");
|
agent_data_report << AgentReportFieldWithLabel("isKernelVersion3OrHigher", "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i_details_resolver->isGw()) {
|
||||||
|
agent_data_report << AgentReportFieldWithLabel("isGw", "true");
|
||||||
|
}
|
||||||
|
|
||||||
if (i_details_resolver->isGwNotVsx()) {
|
if (i_details_resolver->isGwNotVsx()) {
|
||||||
agent_data_report << AgentReportFieldWithLabel("isGwNotVsx", "true");
|
agent_data_report << AgentReportFieldWithLabel("isGwNotVsx", "true");
|
||||||
}
|
}
|
||||||
@@ -1389,6 +1520,14 @@ private:
|
|||||||
|
|
||||||
agent_data_report << AgentReportFieldWithLabel("userEdition", FogCommunication::getUserEdition());
|
agent_data_report << AgentReportFieldWithLabel("userEdition", FogCommunication::getUserEdition());
|
||||||
|
|
||||||
|
agent_data_report << make_pair("registeredServer", i_agent_details->getRegisteredServer());
|
||||||
|
|
||||||
|
const char *prometheus_env = getenv("PROMETHEUS");
|
||||||
|
if (prometheus_env != nullptr) {
|
||||||
|
auto enable_prometheus = string(prometheus_env) == "true";
|
||||||
|
agent_data_report << AgentReportFieldWithLabel("enablePrometheus", enable_prometheus ? "true" : "false");
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(gaia) || defined(smb)
|
#if defined(gaia) || defined(smb)
|
||||||
if (i_details_resolver->compareCheckpointVersion(8100, greater_equal<int>())) {
|
if (i_details_resolver->compareCheckpointVersion(8100, greater_equal<int>())) {
|
||||||
agent_data_report << AgentReportFieldWithLabel("isCheckpointVersionGER81", "true");
|
agent_data_report << AgentReportFieldWithLabel("isCheckpointVersionGER81", "true");
|
||||||
@@ -1549,6 +1688,11 @@ private:
|
|||||||
<< LogField("agentType", "Orchestration")
|
<< LogField("agentType", "Orchestration")
|
||||||
<< LogField("agentVersion", Version::get());
|
<< LogField("agentVersion", Version::get());
|
||||||
|
|
||||||
|
string registered_server = getAttribute("registered-server", "registered_server");
|
||||||
|
dbgTrace(D_ORCHESTRATOR) << "Registered server: " << registered_server;
|
||||||
|
if (!registered_server.empty()) {
|
||||||
|
i_agent_details->setRegisteredServer(registered_server.substr(0, MAX_SERVER_NAME_LENGTH));
|
||||||
|
}
|
||||||
auto mainloop = Singleton::Consume<I_MainLoop>::by<OrchestrationComp>();
|
auto mainloop = Singleton::Consume<I_MainLoop>::by<OrchestrationComp>();
|
||||||
mainloop->addOneTimeRoutine(
|
mainloop->addOneTimeRoutine(
|
||||||
I_MainLoop::RoutineType::Offline,
|
I_MainLoop::RoutineType::Offline,
|
||||||
@@ -1629,7 +1773,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string server_name = getAttribute("registered-server", "registered_server");
|
string server_name = Singleton::Consume<I_AgentDetails>::by<OrchestrationComp>()->getRegisteredServer();
|
||||||
auto server = TagAndEnumManagement::convertStringToTag(server_name);
|
auto server = TagAndEnumManagement::convertStringToTag(server_name);
|
||||||
if (server_name == "'SWAG'" || server_name == "'SWAG Server'") server = Tags::WEB_SERVER_SWAG;
|
if (server_name == "'SWAG'" || server_name == "'SWAG Server'") server = Tags::WEB_SERVER_SWAG;
|
||||||
if (server.ok()) tags.insert(*server);
|
if (server.ok()) tags.insert(*server);
|
||||||
@@ -1653,7 +1797,7 @@ private:
|
|||||||
tags
|
tags
|
||||||
);
|
);
|
||||||
|
|
||||||
if (server_name != "") registration_report.addToOrigin(LogField("eventCategory", server_name));
|
registration_report.addToOrigin(LogField("eventCategory", server_name));
|
||||||
|
|
||||||
auto email = getAttribute("email-address", "user_email");
|
auto email = getAttribute("email-address", "user_email");
|
||||||
if (email != "") registration_report << LogField("userDefinedId", email);
|
if (email != "") registration_report << LogField("userDefinedId", email);
|
||||||
@@ -2065,6 +2209,7 @@ private:
|
|||||||
int failure_count = 0;
|
int failure_count = 0;
|
||||||
unsigned int sleep_interval = 0;
|
unsigned int sleep_interval = 0;
|
||||||
bool is_new_success = false;
|
bool is_new_success = false;
|
||||||
|
bool is_first_check_update_success = false;
|
||||||
OrchestrationPolicy policy;
|
OrchestrationPolicy policy;
|
||||||
UpdatesProcessReporter updates_process_reporter_listener;
|
UpdatesProcessReporter updates_process_reporter_listener;
|
||||||
HybridModeMetric hybrid_mode_metric;
|
HybridModeMetric hybrid_mode_metric;
|
||||||
@@ -2130,6 +2275,7 @@ OrchestrationComp::preload()
|
|||||||
registerExpectedSetting<vector<string>>("upgradeDay");
|
registerExpectedSetting<vector<string>>("upgradeDay");
|
||||||
registerExpectedSetting<string>("email-address");
|
registerExpectedSetting<string>("email-address");
|
||||||
registerExpectedSetting<string>("registered-server");
|
registerExpectedSetting<string>("registered-server");
|
||||||
|
registerExpectedSetting<uint>("successUpgradeInterval");
|
||||||
registerExpectedConfigFile("orchestration", Config::ConfigFileType::Policy);
|
registerExpectedConfigFile("orchestration", Config::ConfigFileType::Policy);
|
||||||
registerExpectedConfigFile("registration-data", Config::ConfigFileType::Policy);
|
registerExpectedConfigFile("registration-data", Config::ConfigFileType::Policy);
|
||||||
}
|
}
|
||||||
@@ -150,7 +150,8 @@ getNamespaceDataFromCluster()
|
|||||||
string auth_header = "Authorization: Bearer " + token;
|
string auth_header = "Authorization: Bearer " + token;
|
||||||
string connection_header = "Connection: close";
|
string connection_header = "Connection: close";
|
||||||
string host = "https://kubernetes.default.svc:443/api/v1/namespaces/";
|
string host = "https://kubernetes.default.svc:443/api/v1/namespaces/";
|
||||||
string culr_cmd = "curl -s -k -H \"" + auth_header + "\" -H \"" + connection_header + "\" " + host +
|
string culr_cmd =
|
||||||
|
"LD_LIBRARY_PATH=\"\" curl -s -k -H \"" + auth_header + "\" -H \"" + connection_header + "\" " + host +
|
||||||
" | /etc/cp/bin/cpnano_json";
|
" | /etc/cp/bin/cpnano_json";
|
||||||
|
|
||||||
auto output_res = Singleton::Consume<I_ShellCmd>::by<OrchestrationTools>()->getExecOutput(culr_cmd);
|
auto output_res = Singleton::Consume<I_ShellCmd>::by<OrchestrationTools>()->getExecOutput(culr_cmd);
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ TEST_F(OrchestrationToolsTest, setClusterId)
|
|||||||
EXPECT_CALL(
|
EXPECT_CALL(
|
||||||
mock_shell_cmd,
|
mock_shell_cmd,
|
||||||
getExecOutput(
|
getExecOutput(
|
||||||
"curl -s -k -H \"Authorization: Bearer 123\" -H \"Connection: close\" "
|
"LD_LIBRARY_PATH=\"\" curl -s -k -H \"Authorization: Bearer 123\" -H \"Connection: close\" "
|
||||||
"https://kubernetes.default.svc:443/api/v1/namespaces/ | /etc/cp/bin/cpnano_json",
|
"https://kubernetes.default.svc:443/api/v1/namespaces/ | /etc/cp/bin/cpnano_json",
|
||||||
200,
|
200,
|
||||||
false
|
false
|
||||||
|
|||||||
@@ -89,6 +89,11 @@ public:
|
|||||||
|
|
||||||
EXPECT_CALL(mock_service_controller, isServiceInstalled("Access Control")).WillRepeatedly(Return(false));
|
EXPECT_CALL(mock_service_controller, isServiceInstalled("Access Control")).WillRepeatedly(Return(false));
|
||||||
|
|
||||||
|
EXPECT_CALL(
|
||||||
|
mock_ml,
|
||||||
|
addOneTimeRoutine(_, _, "Orchestration successfully updated (One-Time After Interval)", true)
|
||||||
|
).WillOnce(DoAll(SaveArg<1>(&upgrade_routine), Return(0)));
|
||||||
|
|
||||||
// This Holding the Main Routine of the Orchestration.
|
// This Holding the Main Routine of the Orchestration.
|
||||||
EXPECT_CALL(
|
EXPECT_CALL(
|
||||||
mock_ml,
|
mock_ml,
|
||||||
@@ -135,11 +140,12 @@ public:
|
|||||||
void
|
void
|
||||||
expectDetailsResolver()
|
expectDetailsResolver()
|
||||||
{
|
{
|
||||||
Maybe<tuple<string, string, string>> no_nginx(genError("No nginx"));
|
Maybe<tuple<string, string, string, string>> no_nginx(genError("No nginx"));
|
||||||
EXPECT_CALL(mock_details_resolver, getPlatform()).WillRepeatedly(Return(string("linux")));
|
EXPECT_CALL(mock_details_resolver, getPlatform()).WillRepeatedly(Return(string("linux")));
|
||||||
EXPECT_CALL(mock_details_resolver, getArch()).WillRepeatedly(Return(string("x86_64")));
|
EXPECT_CALL(mock_details_resolver, getArch()).WillRepeatedly(Return(string("x86_64")));
|
||||||
EXPECT_CALL(mock_details_resolver, isReverseProxy()).WillRepeatedly(Return(false));
|
EXPECT_CALL(mock_details_resolver, isReverseProxy()).WillRepeatedly(Return(false));
|
||||||
EXPECT_CALL(mock_details_resolver, isKernelVersion3OrHigher()).WillRepeatedly(Return(false));
|
EXPECT_CALL(mock_details_resolver, isKernelVersion3OrHigher()).WillRepeatedly(Return(false));
|
||||||
|
EXPECT_CALL(mock_details_resolver, isGw()).WillRepeatedly(Return(false));
|
||||||
EXPECT_CALL(mock_details_resolver, isGwNotVsx()).WillRepeatedly(Return(false));
|
EXPECT_CALL(mock_details_resolver, isGwNotVsx()).WillRepeatedly(Return(false));
|
||||||
EXPECT_CALL(mock_details_resolver, isVersionAboveR8110()).WillRepeatedly(Return(false));
|
EXPECT_CALL(mock_details_resolver, isVersionAboveR8110()).WillRepeatedly(Return(false));
|
||||||
EXPECT_CALL(mock_details_resolver, parseNginxMetadata()).WillRepeatedly(Return(no_nginx));
|
EXPECT_CALL(mock_details_resolver, parseNginxMetadata()).WillRepeatedly(Return(no_nginx));
|
||||||
@@ -156,6 +162,7 @@ public:
|
|||||||
runRoutine()
|
runRoutine()
|
||||||
{
|
{
|
||||||
routine();
|
routine();
|
||||||
|
upgrade_routine();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -235,6 +242,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
I_MainLoop::Routine routine;
|
I_MainLoop::Routine routine;
|
||||||
|
I_MainLoop::Routine upgrade_routine;
|
||||||
I_MainLoop::Routine status_routine;
|
I_MainLoop::Routine status_routine;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,12 @@ public:
|
|||||||
EXPECT_CALL(mock_orchestration_tools, readFile(orchestration_policy_file_path)).WillOnce(Return(response));
|
EXPECT_CALL(mock_orchestration_tools, readFile(orchestration_policy_file_path)).WillOnce(Return(response));
|
||||||
EXPECT_CALL(mock_status, setFogAddress(host_url)).WillRepeatedly(Return());
|
EXPECT_CALL(mock_status, setFogAddress(host_url)).WillRepeatedly(Return());
|
||||||
EXPECT_CALL(mock_orchestration_tools, setClusterId());
|
EXPECT_CALL(mock_orchestration_tools, setClusterId());
|
||||||
|
|
||||||
|
EXPECT_CALL(
|
||||||
|
mock_ml,
|
||||||
|
addOneTimeRoutine(_, _, "Orchestration successfully updated (One-Time After Interval)", true)
|
||||||
|
).WillOnce(DoAll(SaveArg<1>(&upgrade_routine), Return(0)));
|
||||||
|
|
||||||
EXPECT_CALL(
|
EXPECT_CALL(
|
||||||
mock_ml,
|
mock_ml,
|
||||||
addOneTimeRoutine(I_MainLoop::RoutineType::System, _, "Orchestration runner", true)
|
addOneTimeRoutine(I_MainLoop::RoutineType::System, _, "Orchestration runner", true)
|
||||||
@@ -162,12 +168,13 @@ public:
|
|||||||
void
|
void
|
||||||
expectDetailsResolver()
|
expectDetailsResolver()
|
||||||
{
|
{
|
||||||
Maybe<tuple<string, string, string>> no_nginx(genError("No nginx"));
|
Maybe<tuple<string, string, string, string>> no_nginx(genError("No nginx"));
|
||||||
EXPECT_CALL(mock_details_resolver, getPlatform()).WillRepeatedly(Return(string("linux")));
|
EXPECT_CALL(mock_details_resolver, getPlatform()).WillRepeatedly(Return(string("linux")));
|
||||||
EXPECT_CALL(mock_details_resolver, getArch()).WillRepeatedly(Return(string("x86_64")));
|
EXPECT_CALL(mock_details_resolver, getArch()).WillRepeatedly(Return(string("x86_64")));
|
||||||
EXPECT_CALL(mock_details_resolver, isReverseProxy()).WillRepeatedly(Return(false));
|
EXPECT_CALL(mock_details_resolver, isReverseProxy()).WillRepeatedly(Return(false));
|
||||||
EXPECT_CALL(mock_details_resolver, isCloudStorageEnabled()).WillRepeatedly(Return(false));
|
EXPECT_CALL(mock_details_resolver, isCloudStorageEnabled()).WillRepeatedly(Return(false));
|
||||||
EXPECT_CALL(mock_details_resolver, isKernelVersion3OrHigher()).WillRepeatedly(Return(false));
|
EXPECT_CALL(mock_details_resolver, isKernelVersion3OrHigher()).WillRepeatedly(Return(false));
|
||||||
|
EXPECT_CALL(mock_details_resolver, isGw()).WillRepeatedly(Return(false));
|
||||||
EXPECT_CALL(mock_details_resolver, isGwNotVsx()).WillRepeatedly(Return(false));
|
EXPECT_CALL(mock_details_resolver, isGwNotVsx()).WillRepeatedly(Return(false));
|
||||||
EXPECT_CALL(mock_details_resolver, isVersionAboveR8110()).WillRepeatedly(Return(false));
|
EXPECT_CALL(mock_details_resolver, isVersionAboveR8110()).WillRepeatedly(Return(false));
|
||||||
EXPECT_CALL(mock_details_resolver, parseNginxMetadata()).WillRepeatedly(Return(no_nginx));
|
EXPECT_CALL(mock_details_resolver, parseNginxMetadata()).WillRepeatedly(Return(no_nginx));
|
||||||
@@ -281,6 +288,12 @@ public:
|
|||||||
status_routine();
|
status_routine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
runUpgradeRoutine()
|
||||||
|
{
|
||||||
|
upgrade_routine();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
preload()
|
preload()
|
||||||
{
|
{
|
||||||
@@ -359,6 +372,7 @@ private:
|
|||||||
|
|
||||||
I_MainLoop::Routine routine;
|
I_MainLoop::Routine routine;
|
||||||
I_MainLoop::Routine status_routine;
|
I_MainLoop::Routine status_routine;
|
||||||
|
I_MainLoop::Routine upgrade_routine;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -601,14 +615,6 @@ TEST_F(OrchestrationTest, check_sending_registration_data)
|
|||||||
|
|
||||||
string version = "1";
|
string version = "1";
|
||||||
EXPECT_CALL(mock_service_controller, getUpdatePolicyVersion()).WillOnce(ReturnRef(version));
|
EXPECT_CALL(mock_service_controller, getUpdatePolicyVersion()).WillOnce(ReturnRef(version));
|
||||||
|
|
||||||
EXPECT_CALL(mock_ml, yield(A<chrono::microseconds>()))
|
|
||||||
.WillOnce(Return())
|
|
||||||
.WillOnce(Invoke([] (chrono::microseconds) { throw invalid_argument("stop while loop"); }));
|
|
||||||
try {
|
|
||||||
runRoutine();
|
|
||||||
} catch (const invalid_argument& e) {}
|
|
||||||
|
|
||||||
string config_json =
|
string config_json =
|
||||||
"{\n"
|
"{\n"
|
||||||
" \"email-address\": \"fake@example.com\",\n"
|
" \"email-address\": \"fake@example.com\",\n"
|
||||||
@@ -617,9 +623,19 @@ TEST_F(OrchestrationTest, check_sending_registration_data)
|
|||||||
|
|
||||||
istringstream ss(config_json);
|
istringstream ss(config_json);
|
||||||
Singleton::Consume<Config::I_Config>::from(config_comp)->loadConfiguration(ss);
|
Singleton::Consume<Config::I_Config>::from(config_comp)->loadConfiguration(ss);
|
||||||
|
EXPECT_CALL(mock_ml, yield(A<chrono::microseconds>()))
|
||||||
|
.WillOnce(Return())
|
||||||
|
.WillOnce(Invoke([] (chrono::microseconds) { throw invalid_argument("stop while loop"); }));
|
||||||
|
try {
|
||||||
|
runRoutine();
|
||||||
|
} catch (const invalid_argument& e) {}
|
||||||
|
|
||||||
|
|
||||||
sending_routine();
|
sending_routine();
|
||||||
|
|
||||||
EXPECT_THAT(message_body, HasSubstr("\"userDefinedId\": \"fake@example.com\""));
|
EXPECT_THAT(message_body, HasSubstr("\"userDefinedId\": \"fake@example.com\""));
|
||||||
|
EXPECT_THAT(message_body, HasSubstr("\"eventCategory\""));
|
||||||
|
|
||||||
EXPECT_THAT(message_body, AnyOf(HasSubstr("\"Embedded Deployment\""), HasSubstr("\"Kubernetes Deployment\"")));
|
EXPECT_THAT(message_body, AnyOf(HasSubstr("\"Embedded Deployment\""), HasSubstr("\"Kubernetes Deployment\"")));
|
||||||
EXPECT_THAT(message_body, HasSubstr("\"NGINX Server\""));
|
EXPECT_THAT(message_body, HasSubstr("\"NGINX Server\""));
|
||||||
}
|
}
|
||||||
@@ -1004,6 +1020,11 @@ TEST_F(OrchestrationTest, loadOrchestrationPolicyFromBackup)
|
|||||||
);
|
);
|
||||||
waitForRestCall();
|
waitForRestCall();
|
||||||
|
|
||||||
|
EXPECT_CALL(
|
||||||
|
mock_ml,
|
||||||
|
addOneTimeRoutine(_, _, "Orchestration successfully updated (One-Time After Interval)", true)
|
||||||
|
);
|
||||||
|
|
||||||
EXPECT_CALL(
|
EXPECT_CALL(
|
||||||
mock_ml,
|
mock_ml,
|
||||||
addOneTimeRoutine(I_MainLoop::RoutineType::System, _, "Orchestration runner", true)
|
addOneTimeRoutine(I_MainLoop::RoutineType::System, _, "Orchestration runner", true)
|
||||||
@@ -1170,6 +1191,29 @@ TEST_F(OrchestrationTest, manifestUpdate)
|
|||||||
try {
|
try {
|
||||||
runRoutine();
|
runRoutine();
|
||||||
} catch (const invalid_argument& e) {}
|
} catch (const invalid_argument& e) {}
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/upgrade_status")).WillOnce(Return(true));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/last_known_working_orchestrator"))
|
||||||
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
|
Maybe<string> upgrade_status(string("1.1.1 1.1.2 2025-01-28 07:53:23"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, readFile("/etc/cp/revert/upgrade_status"))
|
||||||
|
.WillOnce(Return(upgrade_status));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, removeFile("/etc/cp/revert/upgrade_status")).WillOnce(Return(true));
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, doesFileExist("/etc/cp/revert/failed_upgrade_info"))
|
||||||
|
.WillOnce(Return(false));
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_details_resolver, getAgentVersion()).WillRepeatedly(Return("1.1.2"));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, copyFile(_, "/etc/cp/revert/last_known_working_orchestrator"))
|
||||||
|
.WillOnce(Return(true));
|
||||||
|
EXPECT_CALL(mock_orchestration_tools, copyFile(_, "/etc/cp/revert/last_known_manifest")).WillOnce(Return(true));
|
||||||
|
EXPECT_CALL(
|
||||||
|
mock_orchestration_tools,
|
||||||
|
writeFile("1.1.1 1.1.2 2025-01-28 07:53:23\n", "/var/log/nano_agent/prev_upgrades", true)
|
||||||
|
).WillOnce(Return(true));
|
||||||
|
EXPECT_CALL(mock_ml, yield(A<chrono::microseconds>())).WillOnce(Return());
|
||||||
|
runUpgradeRoutine();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(OrchestrationTest, getBadPolicyUpdate)
|
TEST_F(OrchestrationTest, getBadPolicyUpdate)
|
||||||
|
|||||||
@@ -208,6 +208,8 @@ ServiceDetails::sendNewConfigurations(int configuration_id, const string &policy
|
|||||||
MessageMetadata new_config_req_md("127.0.0.1", service_port);
|
MessageMetadata new_config_req_md("127.0.0.1", service_port);
|
||||||
new_config_req_md.setConnectioFlag(MessageConnectionConfig::ONE_TIME_CONN);
|
new_config_req_md.setConnectioFlag(MessageConnectionConfig::ONE_TIME_CONN);
|
||||||
new_config_req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN);
|
new_config_req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN);
|
||||||
|
new_config_req_md.setSuspension(false);
|
||||||
|
new_config_req_md.setShouldSendAccessToken(false);
|
||||||
auto res = messaging->sendSyncMessage(
|
auto res = messaging->sendSyncMessage(
|
||||||
HTTPMethod::POST,
|
HTTPMethod::POST,
|
||||||
"/set-new-configuration",
|
"/set-new-configuration",
|
||||||
|
|||||||
@@ -139,6 +139,25 @@ FogAuthenticator::RegistrationData::serialize(JSONOutputArchive &out_ar) const
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static string
|
||||||
|
getDeplymentType()
|
||||||
|
{
|
||||||
|
auto deplyment_type = Singleton::Consume<I_EnvDetails>::by<FogAuthenticator>()->getEnvType();
|
||||||
|
switch (deplyment_type) {
|
||||||
|
case EnvType::LINUX: return "Embedded";
|
||||||
|
case EnvType::DOCKER: return "Docker";
|
||||||
|
case EnvType::NON_CRD_K8S:
|
||||||
|
case EnvType::K8S: return "K8S";
|
||||||
|
case EnvType::COUNT: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbgAssertOpt(false)
|
||||||
|
<< AlertInfo(AlertTeam::CORE, "fog communication")
|
||||||
|
<< "Failed to get a legitimate deployment type: "
|
||||||
|
<< static_cast<uint>(deplyment_type);
|
||||||
|
return "Embedded";
|
||||||
|
}
|
||||||
|
|
||||||
Maybe<FogAuthenticator::UserCredentials>
|
Maybe<FogAuthenticator::UserCredentials>
|
||||||
FogAuthenticator::registerAgent(
|
FogAuthenticator::registerAgent(
|
||||||
const FogAuthenticator::RegistrationData ®_data,
|
const FogAuthenticator::RegistrationData ®_data,
|
||||||
@@ -168,10 +187,12 @@ FogAuthenticator::registerAgent(
|
|||||||
auto nginx_data = details_resolver->parseNginxMetadata();
|
auto nginx_data = details_resolver->parseNginxMetadata();
|
||||||
|
|
||||||
if (nginx_data.ok()) {
|
if (nginx_data.ok()) {
|
||||||
|
string nginx_signature;
|
||||||
string nginx_version;
|
string nginx_version;
|
||||||
string config_opt;
|
string config_opt;
|
||||||
string cc_opt;
|
string cc_opt;
|
||||||
tie(config_opt, cc_opt, nginx_version) = nginx_data.unpack();
|
tie(config_opt, cc_opt, nginx_version, nginx_signature) = nginx_data.unpack();
|
||||||
|
request << make_pair("nginxSignature", nginx_signature);
|
||||||
request << make_pair("nginxVersion", nginx_version);
|
request << make_pair("nginxVersion", nginx_version);
|
||||||
request << make_pair("configureOpt", config_opt);
|
request << make_pair("configureOpt", config_opt);
|
||||||
request << make_pair("extraCompilerOpt", cc_opt);
|
request << make_pair("extraCompilerOpt", cc_opt);
|
||||||
@@ -206,6 +227,18 @@ FogAuthenticator::registerAgent(
|
|||||||
|
|
||||||
request << make_pair("userEdition", getUserEdition());
|
request << make_pair("userEdition", getUserEdition());
|
||||||
|
|
||||||
|
const char *prometheus_env = getenv("PROMETHEUS");
|
||||||
|
if (prometheus_env != nullptr) {
|
||||||
|
request << make_pair("enablePrometheus", string(prometheus_env) == "true" ? "true" : "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getDeplymentType() == "Docker" || getDeplymentType() == "K8S") {
|
||||||
|
const char *image_version_otp = getenv("IMAGE_VERSION");
|
||||||
|
if (image_version_otp) {
|
||||||
|
request << make_pair("imageVersion", image_version_otp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (details_resolver->isReverseProxy()) {
|
if (details_resolver->isReverseProxy()) {
|
||||||
request << make_pair("reverse_proxy", "true");
|
request << make_pair("reverse_proxy", "true");
|
||||||
}
|
}
|
||||||
@@ -218,6 +251,10 @@ FogAuthenticator::registerAgent(
|
|||||||
request << make_pair("isKernelVersion3OrHigher", "true");
|
request << make_pair("isKernelVersion3OrHigher", "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (details_resolver->isGw()) {
|
||||||
|
request << make_pair("isGw", "true");
|
||||||
|
}
|
||||||
|
|
||||||
if (details_resolver->isGwNotVsx()) {
|
if (details_resolver->isGwNotVsx()) {
|
||||||
request << make_pair("isGwNotVsx", "true");
|
request << make_pair("isGwNotVsx", "true");
|
||||||
}
|
}
|
||||||
@@ -281,11 +318,14 @@ FogAuthenticator::getAccessToken(const UserCredentials &user_credentials) const
|
|||||||
static const string grant_type_string = "/oauth/token?grant_type=client_credentials";
|
static const string grant_type_string = "/oauth/token?grant_type=client_credentials";
|
||||||
TokenRequest request = TokenRequest();
|
TokenRequest request = TokenRequest();
|
||||||
|
|
||||||
MessageMetadata request_token_md;
|
MessageMetadata request_token_md(true);
|
||||||
request_token_md.insertHeader(
|
request_token_md.insertHeader(
|
||||||
"Authorization",
|
"Authorization",
|
||||||
buildBasicAuthHeader(user_credentials.getClientId(), user_credentials.getSharedSecret())
|
buildBasicAuthHeader(user_credentials.getClientId(), user_credentials.getSharedSecret())
|
||||||
);
|
);
|
||||||
|
dbgInfo(D_ORCHESTRATOR)
|
||||||
|
<< "Sending request for access token. Trace: "
|
||||||
|
<< (request_token_md.getTraceId().ok() ? request_token_md.getTraceId().unpack() : "No trace id");
|
||||||
auto request_token_status = Singleton::Consume<I_Messaging>::by<FogAuthenticator>()->sendSyncMessage(
|
auto request_token_status = Singleton::Consume<I_Messaging>::by<FogAuthenticator>()->sendSyncMessage(
|
||||||
HTTPMethod::POST,
|
HTTPMethod::POST,
|
||||||
grant_type_string,
|
grant_type_string,
|
||||||
@@ -377,9 +417,13 @@ FogAuthenticator::registerLocalAgentToFog()
|
|||||||
{
|
{
|
||||||
auto local_reg_token = getRegistrationToken();
|
auto local_reg_token = getRegistrationToken();
|
||||||
if (!local_reg_token.ok()) return;
|
if (!local_reg_token.ok()) return;
|
||||||
|
|
||||||
|
string reg_token = local_reg_token.unpack().getData();
|
||||||
|
if (reg_token.empty()) return;
|
||||||
|
|
||||||
dbgInfo(D_ORCHESTRATOR) << "Start local agent registration to the fog";
|
dbgInfo(D_ORCHESTRATOR) << "Start local agent registration to the fog";
|
||||||
|
|
||||||
string exec_command = "open-appsec-ctl --set-mode --online_mode --token " + local_reg_token.unpack().getData();
|
string exec_command = "open-appsec-ctl --set-mode --online_mode --token " + reg_token;
|
||||||
|
|
||||||
auto i_agent_details = Singleton::Consume<I_AgentDetails>::by<FogAuthenticator>();
|
auto i_agent_details = Singleton::Consume<I_AgentDetails>::by<FogAuthenticator>();
|
||||||
auto fog_address = i_agent_details->getFogDomain();
|
auto fog_address = i_agent_details->getFogDomain();
|
||||||
@@ -455,25 +499,6 @@ FogAuthenticator::getCredentialsFromFile() const
|
|||||||
return orchestration_tools->jsonStringToObject<UserCredentials>(encrypted_cred.unpack());
|
return orchestration_tools->jsonStringToObject<UserCredentials>(encrypted_cred.unpack());
|
||||||
}
|
}
|
||||||
|
|
||||||
static string
|
|
||||||
getDeplymentType()
|
|
||||||
{
|
|
||||||
auto deplyment_type = Singleton::Consume<I_EnvDetails>::by<FogAuthenticator>()->getEnvType();
|
|
||||||
switch (deplyment_type) {
|
|
||||||
case EnvType::LINUX: return "Embedded";
|
|
||||||
case EnvType::DOCKER: return "Docker";
|
|
||||||
case EnvType::NON_CRD_K8S:
|
|
||||||
case EnvType::K8S: return "K8S";
|
|
||||||
case EnvType::COUNT: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
dbgAssertOpt(false)
|
|
||||||
<< AlertInfo(AlertTeam::CORE, "fog communication")
|
|
||||||
<< "Failed to get a legitimate deployment type: "
|
|
||||||
<< static_cast<uint>(deplyment_type);
|
|
||||||
return "Embedded";
|
|
||||||
}
|
|
||||||
|
|
||||||
Maybe<FogAuthenticator::UserCredentials>
|
Maybe<FogAuthenticator::UserCredentials>
|
||||||
FogAuthenticator::getCredentials()
|
FogAuthenticator::getCredentials()
|
||||||
{
|
{
|
||||||
|
|||||||
2
components/security_apps/prometheus/CMakeLists.txt
Executable file
2
components/security_apps/prometheus/CMakeLists.txt
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
add_library(prometheus_comp prometheus_comp.cc)
|
||||||
|
add_subdirectory(prometheus_ut)
|
||||||
200
components/security_apps/prometheus/prometheus_comp.cc
Executable file
200
components/security_apps/prometheus/prometheus_comp.cc
Executable file
@@ -0,0 +1,200 @@
|
|||||||
|
#include "prometheus_comp.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <cereal/archives/json.hpp>
|
||||||
|
#include <cereal/types/map.hpp>
|
||||||
|
#include <cereal/types/vector.hpp>
|
||||||
|
#include <cereal/types/string.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "report/base_field.h"
|
||||||
|
#include "report/report_enums.h"
|
||||||
|
#include "log_generator.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "rest.h"
|
||||||
|
#include "customized_cereal_map.h"
|
||||||
|
#include "i_messaging.h"
|
||||||
|
#include "prometheus_metric_names.h"
|
||||||
|
|
||||||
|
USE_DEBUG_FLAG(D_PROMETHEUS);
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace ReportIS;
|
||||||
|
|
||||||
|
struct ServiceData
|
||||||
|
{
|
||||||
|
template <typename Archive>
|
||||||
|
void
|
||||||
|
serialize(Archive &ar)
|
||||||
|
{
|
||||||
|
ar(cereal::make_nvp("Service port", service_port));
|
||||||
|
}
|
||||||
|
|
||||||
|
int service_port;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PrometheusMetricData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PrometheusMetricData(const string &n, const string &t, const string &d) : name(n), type(t), description(d) {}
|
||||||
|
|
||||||
|
void
|
||||||
|
addElement(const string &labels, const string &value)
|
||||||
|
{
|
||||||
|
metric_labels_to_values[labels] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ostream &
|
||||||
|
print(ostream &os)
|
||||||
|
{
|
||||||
|
if (metric_labels_to_values.empty()) return os;
|
||||||
|
|
||||||
|
string representative_name = "";
|
||||||
|
if (!name.empty()) {
|
||||||
|
auto metric_name = convertMetricName(name);
|
||||||
|
!metric_name.empty() ? representative_name = metric_name : representative_name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!description.empty()) os << "# HELP " << representative_name << ' ' << description << '\n';
|
||||||
|
if (!name.empty()) os << "# TYPE " << representative_name << ' ' << type << '\n';
|
||||||
|
for (auto &entry : metric_labels_to_values) {
|
||||||
|
os << representative_name << entry.first << ' ' << entry.second << '\n';
|
||||||
|
}
|
||||||
|
os << '\n';
|
||||||
|
metric_labels_to_values.clear();
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
string name;
|
||||||
|
string type;
|
||||||
|
string description;
|
||||||
|
map<string, string> metric_labels_to_values;
|
||||||
|
};
|
||||||
|
|
||||||
|
static ostream & operator<<(ostream &os, PrometheusMetricData &metric) { return metric.print(os); }
|
||||||
|
|
||||||
|
class PrometheusComp::Impl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void
|
||||||
|
init()
|
||||||
|
{
|
||||||
|
Singleton::Consume<I_RestApi>::by<PrometheusComp>()->addGetCall(
|
||||||
|
"metrics",
|
||||||
|
[&] () { return getFormatedPrometheusMetrics(); }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
addMetrics(const vector<PrometheusData> &metrics)
|
||||||
|
{
|
||||||
|
for(auto &metric : metrics) {
|
||||||
|
auto &metric_object = getDataObject(
|
||||||
|
metric.name,
|
||||||
|
metric.type,
|
||||||
|
metric.description
|
||||||
|
);
|
||||||
|
metric_object.addElement(metric.label, metric.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PrometheusMetricData &
|
||||||
|
getDataObject(const string &name, const string &type, const string &description)
|
||||||
|
{
|
||||||
|
auto elem = prometheus_metrics.find(name);
|
||||||
|
if (elem == prometheus_metrics.end()) {
|
||||||
|
elem = prometheus_metrics.emplace(name, PrometheusMetricData(name, type, description)).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
return elem->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
map<string, ServiceData>
|
||||||
|
getServiceDetails()
|
||||||
|
{
|
||||||
|
map<string, ServiceData> registeredServices;
|
||||||
|
auto registered_services_file = getConfigurationWithDefault<string>(
|
||||||
|
getFilesystemPathConfig() + "/conf/orchestrations_registered_services.json",
|
||||||
|
"orchestration",
|
||||||
|
"Orchestration registered services"
|
||||||
|
);
|
||||||
|
ifstream file(registered_services_file);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
dbgWarning(D_PROMETHEUS) << "Failed to open file: " << registered_services_file;
|
||||||
|
return registeredServices;
|
||||||
|
}
|
||||||
|
stringstream buffer;
|
||||||
|
buffer << file.rdbuf();
|
||||||
|
try {
|
||||||
|
cereal::JSONInputArchive archive(buffer);
|
||||||
|
archive(cereal::make_nvp("Registered Services", registeredServices));
|
||||||
|
} catch (const exception& e) {
|
||||||
|
dbgWarning(D_PROMETHEUS) << "Error parsing Registered Services JSON file: " << e.what();
|
||||||
|
}
|
||||||
|
|
||||||
|
return registeredServices;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
getServicesMetrics()
|
||||||
|
{
|
||||||
|
dbgTrace(D_PROMETHEUS) << "Get all registered services metrics";
|
||||||
|
map<string, ServiceData> service_names_to_ports = getServiceDetails();
|
||||||
|
for (const auto &service : service_names_to_ports) {
|
||||||
|
I_Messaging *messaging = Singleton::Consume<I_Messaging>::by<PrometheusComp>();
|
||||||
|
MessageMetadata servie_metric_req_md("127.0.0.1", service.second.service_port);
|
||||||
|
servie_metric_req_md.setConnectioFlag(MessageConnectionConfig::ONE_TIME_CONN);
|
||||||
|
servie_metric_req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN);
|
||||||
|
auto res = messaging->sendSyncMessage(
|
||||||
|
HTTPMethod::GET,
|
||||||
|
"/service-metrics",
|
||||||
|
string(""),
|
||||||
|
MessageCategory::GENERIC,
|
||||||
|
servie_metric_req_md
|
||||||
|
);
|
||||||
|
if (!res.ok()) {
|
||||||
|
dbgWarning(D_PROMETHEUS) << "Failed to get service metrics. Service: " << service.first;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
stringstream buffer;
|
||||||
|
buffer << res.unpack().getBody();
|
||||||
|
cereal::JSONInputArchive archive(buffer);
|
||||||
|
vector<PrometheusData> metrics;
|
||||||
|
archive(cereal::make_nvp("metrics", metrics));
|
||||||
|
addMetrics(metrics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
getFormatedPrometheusMetrics()
|
||||||
|
{
|
||||||
|
MetricScrapeEvent().notify();
|
||||||
|
getServicesMetrics();
|
||||||
|
stringstream result;
|
||||||
|
for (auto &metric : prometheus_metrics) {
|
||||||
|
result << metric.second;
|
||||||
|
}
|
||||||
|
dbgTrace(D_PROMETHEUS) << "Prometheus metrics: " << result.str();
|
||||||
|
return result.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
map<string, PrometheusMetricData> prometheus_metrics;
|
||||||
|
};
|
||||||
|
|
||||||
|
PrometheusComp::PrometheusComp() : Component("Prometheus"), pimpl(make_unique<Impl>()) {}
|
||||||
|
|
||||||
|
PrometheusComp::~PrometheusComp() {}
|
||||||
|
|
||||||
|
void
|
||||||
|
PrometheusComp::init()
|
||||||
|
{
|
||||||
|
pimpl->init();
|
||||||
|
}
|
||||||
143
components/security_apps/prometheus/prometheus_metric_names.h
Executable file
143
components/security_apps/prometheus/prometheus_metric_names.h
Executable file
@@ -0,0 +1,143 @@
|
|||||||
|
#ifndef __PROMETHEUS_METRIC_NAMES_H__
|
||||||
|
#define __PROMETHEUS_METRIC_NAMES_H__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
USE_DEBUG_FLAG(D_PROMETHEUS);
|
||||||
|
|
||||||
|
std::string
|
||||||
|
convertMetricName(const std::string &original_metric_name)
|
||||||
|
{
|
||||||
|
static const std::unordered_map<std::string, std::string> original_to_representative_names = {
|
||||||
|
// HybridModeMetric
|
||||||
|
{"watchdogProcessStartupEventsSum", "nano_service_restarts_counter"},
|
||||||
|
// nginxAttachmentMetric
|
||||||
|
{"inspectVerdictSum", "traffic_inspection_verdict_inspect_counter"},
|
||||||
|
{"acceptVeridctSum", "traffic_inspection_verdict_accept_counter"},
|
||||||
|
{"dropVerdictSum", "traffic_inspection_verdict_drop_counter"},
|
||||||
|
{"injectVerdictSum", "traffic_inspection_verdict_inject_counter"},
|
||||||
|
{"irrelevantVerdictSum", "traffic_inspection_verdict_irrelevant_counter"},
|
||||||
|
{"irrelevantVerdictSum", "traffic_inspection_verdict_irrelevant_counter"},
|
||||||
|
{"reconfVerdictSum", "traffic_inspection_verdict_reconf_counter"},
|
||||||
|
{"responseInspection", "response_body_inspection_counter"},
|
||||||
|
// nginxIntakerMetric
|
||||||
|
{"successfullInspectionTransactionsSum", "successful_Inspection_counter"},
|
||||||
|
{"failopenTransactionsSum", "fail_open_Inspection_counter"},
|
||||||
|
{"failcloseTransactionsSum", "fail_close_Inspection_counter"},
|
||||||
|
{"transparentModeTransactionsSum", "transparent_mode_counter"},
|
||||||
|
{"totalTimeInTransparentModeSum", "total_time_in_transparent_mode_counter"},
|
||||||
|
{"reachInspectVerdictSum", "inspect_verdict_counter"},
|
||||||
|
{"reachAcceptVerdictSum", "accept_verdict_counter"},
|
||||||
|
{"reachDropVerdictSum", "drop_verdict_counter"},
|
||||||
|
{"reachInjectVerdictSum", "inject_verdict_counter"},
|
||||||
|
{"reachIrrelevantVerdictSum", "irrelevant_verdict_counter"},
|
||||||
|
{"reachReconfVerdictSum", "reconf_verdict_counter"},
|
||||||
|
{"requestCompressionFailureSum", "failed_requests_compression_counter"},
|
||||||
|
{"responseCompressionFailureSum", "failed_response_compression_counter"},
|
||||||
|
{"requestDecompressionFailureSum", "failed_requests_decompression_counter"},
|
||||||
|
{"responseDecompressionFailureSum", "failed_response_decompression_counter"},
|
||||||
|
{"requestCompressionSuccessSum", "successful_request_compression_counter"},
|
||||||
|
{"responseCompressionSuccessSum", "successful_response_compression_counter"},
|
||||||
|
{"requestDecompressionSuccessSum", "successful_request_decompression_counter"},
|
||||||
|
{"responseDecompressionSuccessSum", "successful_response_decompression_counter"},
|
||||||
|
{"skippedSessionsUponCorruptedZipSum", "corrupted_zip_skipped_session_counter"},
|
||||||
|
{"attachmentThreadReachedTimeoutSum", "thread_exceeded_processing_time_counter"},
|
||||||
|
{"registrationThreadReachedTimeoutSum", "failed_registration_thread_counter"},
|
||||||
|
{"requestHeaderThreadReachedTimeoutSum", "request_headers_processing_thread_timeouts_counter"},
|
||||||
|
{"requestBodyThreadReachedTimeoutSum", "request_body_processing_thread_timeouts_counter"},
|
||||||
|
{"respondHeaderThreadReachedTimeoutSum", "response_headers_processing_thread_timeouts_counter"},
|
||||||
|
{"respondBodyThreadReachedTimeoutSum", "response_body_processing_thread_timeouts_counter"},
|
||||||
|
{"attachmentThreadFailureSum", "thread_failures_counter"},
|
||||||
|
{"httpRequestProcessingReachedTimeoutSum", "request_processing_timeouts_counter"},
|
||||||
|
{"httpRequestsSizeSum", "requests_total_size_counter"},
|
||||||
|
{"httpResponsesSizeSum", "response_total_size_counter"},
|
||||||
|
{"httpRequestFailedToReachWebServerUpstreamSum", "requests_failed_reach_upstram_counter"},
|
||||||
|
{"overallSessionProcessTimeToVerdictAvgSample", "overall_processing_time_until_verdict_average"},
|
||||||
|
{"overallSessionProcessTimeToVerdictMaxSample", "overall_processing_time_until_verdict_max"},
|
||||||
|
{"overallSessionProcessTimeToVerdictMinSample", "overall_processing_time_until_verdict_min"},
|
||||||
|
{"requestProcessTimeToVerdictAvgSample", "requests_processing_time_until_verdict_average"},
|
||||||
|
{"requestProcessTimeToVerdictMaxSample", "requests_processing_time_until_verdict_max"},
|
||||||
|
{"requestProcessTimeToVerdictMinSample", "requests_processing_time_until_verdict_min"},
|
||||||
|
{"responseProcessTimeToVerdictAvgSample", "response_processing_time_until_verdict_average"},
|
||||||
|
{"responseProcessTimeToVerdictMaxSample", "response_processing_time_until_verdict_max"},
|
||||||
|
{"responseProcessTimeToVerdictMinSample", "response_processing_time_until_verdict_min"},
|
||||||
|
{"requestBodySizeUponTimeoutAvgSample", "request_body_size_average"},
|
||||||
|
{"requestBodySizeUponTimeoutMaxSample", "request_body_size_max"},
|
||||||
|
{"requestBodySizeUponTimeoutMinSample", "request_body_size_min"},
|
||||||
|
{"responseBodySizeUponTimeoutAvgSample", "response_body_size_average"},
|
||||||
|
{"responseBodySizeUponTimeoutMaxSample", "response_body_size_max"},
|
||||||
|
{"responseBodySizeUponTimeoutMinSample", "response_body_size_min"},
|
||||||
|
// WaapTelemetrics
|
||||||
|
{"reservedNgenA", "total_requests_counter"},
|
||||||
|
{"reservedNgenB", "unique_sources_counter"},
|
||||||
|
{"reservedNgenC", "requests_blocked_by_force_and_exception_counter"},
|
||||||
|
{"reservedNgenD", "requests_blocked_by_waf_counter"},
|
||||||
|
{"reservedNgenE", "requests_blocked_by_open_api_counter"},
|
||||||
|
{"reservedNgenF", "requests_blocked_by_bot_protection_counter"},
|
||||||
|
{"reservedNgenG", "requests_threat_level_info_and_no_threat_counter"},
|
||||||
|
{"reservedNgenH", "requests_threat_level_low_counter"},
|
||||||
|
{"reservedNgenI", "requests_threat_level_medium_counter"},
|
||||||
|
{"reservedNgenJ", "requests_threat_level_high_counter"},
|
||||||
|
// WaapTrafficTelemetrics
|
||||||
|
{"reservedNgenA", "post_requests_counter"},
|
||||||
|
{"reservedNgenB", "get_requests_counter"},
|
||||||
|
{"reservedNgenC", "put_requests_counter"},
|
||||||
|
{"reservedNgenD", "patch_requests_counter"},
|
||||||
|
{"reservedNgenE", "delete_requests_counter"},
|
||||||
|
{"reservedNgenF", "other_requests_counter"},
|
||||||
|
{"reservedNgenG", "2xx_status_code_responses_counter"},
|
||||||
|
{"reservedNgenH", "4xx_status_code_responses_counter"},
|
||||||
|
{"reservedNgenI", "5xx_status_code_responses_counter"},
|
||||||
|
{"reservedNgenJ", "requests_time_latency_average"},
|
||||||
|
// WaapAttackTypesMetrics
|
||||||
|
{"reservedNgenA", "sql_injection_attacks_type_counter"},
|
||||||
|
{"reservedNgenB", "vulnerability_scanning_attacks_type_counter"},
|
||||||
|
{"reservedNgenC", "path_traversal_attacks_type_counter"},
|
||||||
|
{"reservedNgenD", "ldap_injection_attacks_type_counter"},
|
||||||
|
{"reservedNgenE", "evasion_techniques_attacks_type_counter"},
|
||||||
|
{"reservedNgenF", "remote_code_execution_attacks_type_counter"},
|
||||||
|
{"reservedNgenG", "xml_extern_entity_attacks_type_counter"},
|
||||||
|
{"reservedNgenH", "cross_site_scripting_attacks_type_counter"},
|
||||||
|
{"reservedNgenI", "general_attacks_type_counter"},
|
||||||
|
// AssetsMetric
|
||||||
|
{"numberOfProtectedApiAssetsSample", "api_assets_counter"},
|
||||||
|
{"numberOfProtectedWebAppAssetsSample", "web_api_assets_counter"},
|
||||||
|
{"numberOfProtectedAssetsSample", "all_assets_counter"},
|
||||||
|
// IPSMetric
|
||||||
|
{"preventEngineMatchesSample", "prevent_action_matches_counter"},
|
||||||
|
{"detectEngineMatchesSample", "detect_action_matches_counter"},
|
||||||
|
{"ignoreEngineMatchesSample", "ignore_action_matches_counter"},
|
||||||
|
// CPUMetric
|
||||||
|
{"cpuMaxSample", "cpu_usage_percentage_max"},
|
||||||
|
{"cpuAvgSample", "cpu_usage_percentage_average"},
|
||||||
|
{"cpuSample", "cpu_usage_percentage_last_value"},
|
||||||
|
// LogMetric
|
||||||
|
{"logQueueMaxSizeSample", "logs_queue_size_max"},
|
||||||
|
{"logQueueAvgSizeSample", "logs_queue_size_average"},
|
||||||
|
{"logQueueCurrentSizeSample", "logs_queue_size_last_value"},
|
||||||
|
{"sentLogsSum", "logs_sent_counter"},
|
||||||
|
{"sentLogsBulksSum", "bulk_logs_sent_counter"},
|
||||||
|
// MemoryMetric
|
||||||
|
{"serviceVirtualMemorySizeMaxSample", "service_virtual_memory_size_kb_max"},
|
||||||
|
{"serviceVirtualMemorySizeMinSample", "service_virtual_memory_size_kb_min"},
|
||||||
|
{"serviceVirtualMemorySizeAvgSample", "service_virtual_memory_size_kb_average"},
|
||||||
|
{"serviceRssMemorySizeMaxSample", "service_physical_memory_size_kb_max"},
|
||||||
|
{"serviceRssMemorySizeMinSample", "service_physical_memory_size_kb_min"},
|
||||||
|
{"serviceRssMemorySizeAvgSample", "service_physical_memory_size_kb_average"},
|
||||||
|
{"generalTotalMemorySizeMaxSample", "general_total_used_memory_max"},
|
||||||
|
{"generalTotalMemorySizeMinSample", "general_total_used_memory_min"},
|
||||||
|
{"generalTotalMemorySizeAvgSample", "general_total_used_memory_average"},
|
||||||
|
};
|
||||||
|
|
||||||
|
auto metric_names = original_to_representative_names.find(original_metric_name);
|
||||||
|
if (metric_names != original_to_representative_names.end()) return metric_names->second;
|
||||||
|
dbgDebug(D_PROMETHEUS)
|
||||||
|
<< "Metric don't have a representative name, originl name: "
|
||||||
|
<< original_metric_name;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __PROMETHEUS_METRIC_NAMES_H__
|
||||||
8
components/security_apps/prometheus/prometheus_ut/CMakeLists.txt
Executable file
8
components/security_apps/prometheus/prometheus_ut/CMakeLists.txt
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
link_directories(${BOOST_ROOT}/lib)
|
||||||
|
link_directories(${BOOST_ROOT}/lib ${CMAKE_BINARY_DIR}/core/shmem_ipc)
|
||||||
|
|
||||||
|
add_unit_test(
|
||||||
|
prometheus_ut
|
||||||
|
"prometheus_ut.cc"
|
||||||
|
"prometheus_comp;logging;agent_details;waap_clib;table;singleton;time_proxy;metric;event_is;connkey;http_transaction_data;generic_rulebase;generic_rulebase_evaluators;ip_utilities;intelligence_is_v2;-lboost_regex;messaging;"
|
||||||
|
)
|
||||||
79
components/security_apps/prometheus/prometheus_ut/prometheus_ut.cc
Executable file
79
components/security_apps/prometheus/prometheus_ut/prometheus_ut.cc
Executable file
@@ -0,0 +1,79 @@
|
|||||||
|
#include "prometheus_comp.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "cmock.h"
|
||||||
|
#include "cptest.h"
|
||||||
|
#include "maybe_res.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "environment.h"
|
||||||
|
#include "config_component.h"
|
||||||
|
#include "agent_details.h"
|
||||||
|
#include "time_proxy.h"
|
||||||
|
#include "mock/mock_mainloop.h"
|
||||||
|
#include "mock/mock_rest_api.h"
|
||||||
|
#include "mock/mock_messaging.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace testing;
|
||||||
|
|
||||||
|
USE_DEBUG_FLAG(D_PROMETHEUS);
|
||||||
|
|
||||||
|
class PrometheusCompTest : public Test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PrometheusCompTest()
|
||||||
|
{
|
||||||
|
EXPECT_CALL(mock_rest, mockRestCall(_, "declare-boolean-variable", _)).WillOnce(Return(false));
|
||||||
|
env.preload();
|
||||||
|
config.preload();
|
||||||
|
env.init();
|
||||||
|
|
||||||
|
EXPECT_CALL(
|
||||||
|
mock_rest,
|
||||||
|
addGetCall("metrics", _)
|
||||||
|
).WillOnce(DoAll(SaveArg<1>(&get_metrics_func), Return(true)));
|
||||||
|
|
||||||
|
prometheus_comp.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
::Environment env;
|
||||||
|
ConfigComponent config;
|
||||||
|
PrometheusComp prometheus_comp;
|
||||||
|
StrictMock<MockRestApi> mock_rest;
|
||||||
|
StrictMock<MockMainLoop> mock_ml;
|
||||||
|
NiceMock<MockMessaging> mock_messaging;
|
||||||
|
unique_ptr<ServerRest> agent_uninstall;
|
||||||
|
function<string()> get_metrics_func;
|
||||||
|
CPTestTempfile status_file;
|
||||||
|
string registered_services_file_path;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(PrometheusCompTest, checkAddingMetric)
|
||||||
|
{
|
||||||
|
registered_services_file_path = cptestFnameInSrcDir(string("registered_services.json"));
|
||||||
|
setConfiguration(registered_services_file_path, "orchestration", "Orchestration registered services");
|
||||||
|
string metric_body = "{\n"
|
||||||
|
" \"metrics\": [\n"
|
||||||
|
" {\n"
|
||||||
|
" \"metric_name\": \"watchdogProcessStartupEventsSum\",\n"
|
||||||
|
" \"metric_type\": \"counter\",\n"
|
||||||
|
" \"metric_description\": \"\",\n"
|
||||||
|
" \"labels\": \"{method=\\\"post\\\",code=\\\"200\\\"}\",\n"
|
||||||
|
" \"value\": \"1534\"\n"
|
||||||
|
" }\n"
|
||||||
|
" ]\n"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
string message_body;
|
||||||
|
EXPECT_CALL(mock_messaging, sendSyncMessage(_, "/service-metrics", _, _, _))
|
||||||
|
.Times(2).WillRepeatedly(Return(HTTPResponse(HTTPStatusCode::HTTP_OK, metric_body)));
|
||||||
|
|
||||||
|
string metric_str = "# TYPE nano_service_restarts_counter counter\n"
|
||||||
|
"nano_service_restarts_counter{method=\"post\",code=\"200\"} 1534\n\n";
|
||||||
|
EXPECT_EQ(metric_str, get_metrics_func());
|
||||||
|
}
|
||||||
32
components/security_apps/prometheus/prometheus_ut/registered_services.json
Executable file
32
components/security_apps/prometheus/prometheus_ut/registered_services.json
Executable file
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"Registered Services": {
|
||||||
|
"cp-nano-orchestration": {
|
||||||
|
"Service name": "cp-nano-orchestration",
|
||||||
|
"Service ID": "cp-nano-orchestration",
|
||||||
|
"Service port": 7777,
|
||||||
|
"Relevant configs": [
|
||||||
|
"zones",
|
||||||
|
"triggers",
|
||||||
|
"rules",
|
||||||
|
"registration-data",
|
||||||
|
"parameters",
|
||||||
|
"orchestration",
|
||||||
|
"exceptions",
|
||||||
|
"agent-intelligence"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"cp-nano-prometheus": {
|
||||||
|
"Service name": "cp-nano-prometheus",
|
||||||
|
"Service ID": "cp-nano-prometheus",
|
||||||
|
"Service port": 7465,
|
||||||
|
"Relevant configs": [
|
||||||
|
"zones",
|
||||||
|
"triggers",
|
||||||
|
"rules",
|
||||||
|
"parameters",
|
||||||
|
"exceptions",
|
||||||
|
"agent-intelligence"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -250,13 +250,14 @@ public:
|
|||||||
fetchReplicaCount()
|
fetchReplicaCount()
|
||||||
{
|
{
|
||||||
string curl_cmd =
|
string curl_cmd =
|
||||||
"curl -H \"Authorization: Bearer " + kubernetes_token + "\" "
|
base_curl_cmd + " -H \"Authorization: Bearer " + kubernetes_token + "\" "
|
||||||
"https://kubernetes.default.svc.cluster.local/apis/apps/v1/namespaces/" + kubernetes_namespace +
|
"https://kubernetes.default.svc.cluster.local/apis/apps/v1/namespaces/" + kubernetes_namespace +
|
||||||
"/deployments/${AGENT_DEPLOYMENT_NAME} -k -s | jq .status.replicas";
|
"/deployments/${AGENT_DEPLOYMENT_NAME} -k -s | jq .status.replicas";
|
||||||
auto maybe_replicas = i_shell_cmd->getExecOutput(curl_cmd);
|
auto maybe_replicas = i_shell_cmd->getExecOutput(curl_cmd);
|
||||||
if (maybe_replicas.ok()) {
|
if (maybe_replicas.ok()) {
|
||||||
try {
|
try {
|
||||||
replicas = std::stoi(maybe_replicas.unpack());
|
replicas = std::stoi(maybe_replicas.unpack());
|
||||||
|
dbgTrace(D_RATE_LIMIT) << "replicas is set to " << replicas;
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
dbgWarning(D_RATE_LIMIT) << "error while converting replicas: " << e.what();
|
dbgWarning(D_RATE_LIMIT) << "error while converting replicas: " << e.what();
|
||||||
}
|
}
|
||||||
@@ -706,7 +707,9 @@ public:
|
|||||||
i_shell_cmd = Singleton::Consume<I_ShellCmd>::by<RateLimit>();
|
i_shell_cmd = Singleton::Consume<I_ShellCmd>::by<RateLimit>();
|
||||||
i_env_details = Singleton::Consume<I_EnvDetails>::by<RateLimit>();
|
i_env_details = Singleton::Consume<I_EnvDetails>::by<RateLimit>();
|
||||||
env_type = i_env_details->getEnvType();
|
env_type = i_env_details->getEnvType();
|
||||||
if (env_type == EnvType::K8S) {
|
const char *nexus_env = getenv("KUBERNETES_METADATA");
|
||||||
|
if (nexus_env == nullptr) return;
|
||||||
|
if (env_type == EnvType::K8S && string(nexus_env) == "true") {
|
||||||
kubernetes_token = i_env_details->getToken();
|
kubernetes_token = i_env_details->getToken();
|
||||||
kubernetes_namespace = i_env_details->getNameSpace();
|
kubernetes_namespace = i_env_details->getNameSpace();
|
||||||
fetchReplicaCount();
|
fetchReplicaCount();
|
||||||
@@ -742,6 +745,13 @@ private:
|
|||||||
EnvType env_type;
|
EnvType env_type;
|
||||||
string kubernetes_namespace = "";
|
string kubernetes_namespace = "";
|
||||||
string kubernetes_token = "";
|
string kubernetes_token = "";
|
||||||
|
#if defined(gaia)
|
||||||
|
const string base_curl_cmd = "curl_cli";
|
||||||
|
#elif defined(alpine)
|
||||||
|
const string base_curl_cmd = "LD_LIBRARY_PATH=/usr/lib/:/usr/lib/cpnano curl";
|
||||||
|
#else
|
||||||
|
const string base_curl_cmd = "curl";
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
RateLimit::RateLimit() : Component("RateLimit"), pimpl(make_unique<Impl>()) {}
|
RateLimit::RateLimit() : Component("RateLimit"), pimpl(make_unique<Impl>()) {}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
static const uint max_send_obj_retries = 3;
|
static const uint max_send_obj_retries = 3;
|
||||||
static const std::chrono::microseconds wait_next_attempt(5000000);
|
static const std::chrono::microseconds wait_next_attempt(5000000);
|
||||||
|
|
||||||
USE_DEBUG_FLAG(D_WAAP);
|
USE_DEBUG_FLAG(D_WAAP_SERIALIZE);
|
||||||
|
|
||||||
class RestGetFile : public ClientRest
|
class RestGetFile : public ClientRest
|
||||||
{
|
{
|
||||||
@@ -137,9 +137,13 @@ public:
|
|||||||
void setRemoteSyncEnabled(bool enabled);
|
void setRemoteSyncEnabled(bool enabled);
|
||||||
protected:
|
protected:
|
||||||
void mergeProcessedFromRemote();
|
void mergeProcessedFromRemote();
|
||||||
|
std::string getWindowId();
|
||||||
|
void waitSync();
|
||||||
std::string getPostDataUrl();
|
std::string getPostDataUrl();
|
||||||
std::string getUri();
|
std::string getUri();
|
||||||
size_t getIntervalsCount();
|
size_t getIntervalsCount();
|
||||||
|
void incrementIntervalsCount();
|
||||||
|
bool isBase();
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool sendObject(T &obj, HTTPMethod method, std::string uri)
|
bool sendObject(T &obj, HTTPMethod method, std::string uri)
|
||||||
@@ -147,13 +151,14 @@ protected:
|
|||||||
I_Messaging *messaging = Singleton::Consume<I_Messaging>::by<WaapComponent>();
|
I_Messaging *messaging = Singleton::Consume<I_Messaging>::by<WaapComponent>();
|
||||||
I_AgentDetails *agentDetails = Singleton::Consume<I_AgentDetails>::by<WaapComponent>();
|
I_AgentDetails *agentDetails = Singleton::Consume<I_AgentDetails>::by<WaapComponent>();
|
||||||
if (agentDetails->getOrchestrationMode() == OrchestrationMode::OFFLINE) {
|
if (agentDetails->getOrchestrationMode() == OrchestrationMode::OFFLINE) {
|
||||||
dbgDebug(D_WAAP) << "offline mode not sending object";
|
dbgDebug(D_WAAP_SERIALIZE) << "offline mode not sending object";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (agentDetails->getOrchestrationMode() == OrchestrationMode::HYBRID) {
|
if (agentDetails->getOrchestrationMode() == OrchestrationMode::HYBRID) {
|
||||||
MessageMetadata req_md(getSharedStorageHost(), 80);
|
MessageMetadata req_md(getSharedStorageHost(), 80);
|
||||||
req_md.insertHeader("X-Tenant-Id", agentDetails->getTenantId());
|
req_md.insertHeader("X-Tenant-Id", agentDetails->getTenantId());
|
||||||
req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN);
|
req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN);
|
||||||
|
req_md.setConnectioFlag(MessageConnectionConfig::ONE_TIME_CONN);
|
||||||
auto req_status = messaging->sendSyncMessage(
|
auto req_status = messaging->sendSyncMessage(
|
||||||
method,
|
method,
|
||||||
uri,
|
uri,
|
||||||
@@ -162,19 +167,22 @@ protected:
|
|||||||
req_md
|
req_md
|
||||||
);
|
);
|
||||||
if (!req_status.ok()) {
|
if (!req_status.ok()) {
|
||||||
dbgWarning(D_WAAP) << "failed to send request to uri: " << uri
|
dbgWarning(D_WAAP_SERIALIZE) << "failed to send request to uri: " << uri
|
||||||
<< ", error: " << req_status.getErr().toString();
|
<< ", error: " << req_status.getErr().toString();
|
||||||
}
|
}
|
||||||
return req_status.ok();
|
return req_status.ok();
|
||||||
}
|
}
|
||||||
|
MessageMetadata req_md;
|
||||||
|
req_md.setConnectioFlag(MessageConnectionConfig::ONE_TIME_FOG_CONN);
|
||||||
auto req_status = messaging->sendSyncMessage(
|
auto req_status = messaging->sendSyncMessage(
|
||||||
method,
|
method,
|
||||||
uri,
|
uri,
|
||||||
obj,
|
obj,
|
||||||
MessageCategory::GENERIC
|
MessageCategory::GENERIC,
|
||||||
|
req_md
|
||||||
);
|
);
|
||||||
if (!req_status.ok()) {
|
if (!req_status.ok()) {
|
||||||
dbgWarning(D_WAAP) << "failed to send request to uri: " << uri
|
dbgWarning(D_WAAP_SERIALIZE) << "failed to send request to uri: " << uri
|
||||||
<< ", error: " << req_status.getErr().toString();
|
<< ", error: " << req_status.getErr().toString();
|
||||||
}
|
}
|
||||||
return req_status.ok();
|
return req_status.ok();
|
||||||
@@ -188,14 +196,14 @@ protected:
|
|||||||
{
|
{
|
||||||
if (sendObject(obj, method, uri))
|
if (sendObject(obj, method, uri))
|
||||||
{
|
{
|
||||||
dbgTrace(D_WAAP) <<
|
dbgTrace(D_WAAP_SERIALIZE) <<
|
||||||
"object sent successfully after " << i << " retry attempts";
|
"object sent successfully after " << i << " retry attempts";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
dbgInfo(D_WAAP) << "Failed to send object. Attempt: " << i;
|
dbgInfo(D_WAAP_SERIALIZE) << "Failed to send object. Attempt: " << i;
|
||||||
mainloop->yield(wait_next_attempt);
|
mainloop->yield(wait_next_attempt);
|
||||||
}
|
}
|
||||||
dbgWarning(D_WAAP) << "Failed to send object to " << uri << ", reached maximum attempts: " <<
|
dbgWarning(D_WAAP_SERIALIZE) << "Failed to send object to " << uri << ", reached maximum attempts: " <<
|
||||||
max_send_obj_retries;
|
max_send_obj_retries;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -206,13 +214,14 @@ protected:
|
|||||||
I_Messaging *messaging = Singleton::Consume<I_Messaging>::by<WaapComponent>();
|
I_Messaging *messaging = Singleton::Consume<I_Messaging>::by<WaapComponent>();
|
||||||
I_AgentDetails *agentDetails = Singleton::Consume<I_AgentDetails>::by<WaapComponent>();
|
I_AgentDetails *agentDetails = Singleton::Consume<I_AgentDetails>::by<WaapComponent>();
|
||||||
if (agentDetails->getOrchestrationMode() == OrchestrationMode::OFFLINE) {
|
if (agentDetails->getOrchestrationMode() == OrchestrationMode::OFFLINE) {
|
||||||
dbgDebug(D_WAAP) << "offline mode not sending object";
|
dbgDebug(D_WAAP_SERIALIZE) << "offline mode not sending object";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (agentDetails->getOrchestrationMode() == OrchestrationMode::HYBRID) {
|
if (agentDetails->getOrchestrationMode() == OrchestrationMode::HYBRID) {
|
||||||
MessageMetadata req_md(getSharedStorageHost(), 80);
|
MessageMetadata req_md(getSharedStorageHost(), 80);
|
||||||
req_md.insertHeader("X-Tenant-Id", agentDetails->getTenantId());
|
req_md.insertHeader("X-Tenant-Id", agentDetails->getTenantId());
|
||||||
req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN);
|
req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN);
|
||||||
|
req_md.setConnectioFlag(MessageConnectionConfig::ONE_TIME_CONN);
|
||||||
return messaging->sendSyncMessageWithoutResponse(
|
return messaging->sendSyncMessageWithoutResponse(
|
||||||
method,
|
method,
|
||||||
uri,
|
uri,
|
||||||
@@ -221,11 +230,14 @@ protected:
|
|||||||
req_md
|
req_md
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
MessageMetadata req_md;
|
||||||
|
req_md.setConnectioFlag(MessageConnectionConfig::ONE_TIME_FOG_CONN);
|
||||||
return messaging->sendSyncMessageWithoutResponse(
|
return messaging->sendSyncMessageWithoutResponse(
|
||||||
method,
|
method,
|
||||||
uri,
|
uri,
|
||||||
obj,
|
obj,
|
||||||
MessageCategory::GENERIC
|
MessageCategory::GENERIC,
|
||||||
|
req_md
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,14 +249,14 @@ protected:
|
|||||||
{
|
{
|
||||||
if (sendNoReplyObject(obj, method, uri))
|
if (sendNoReplyObject(obj, method, uri))
|
||||||
{
|
{
|
||||||
dbgTrace(D_WAAP) <<
|
dbgTrace(D_WAAP_SERIALIZE) <<
|
||||||
"object sent successfully after " << i << " retry attempts";
|
"object sent successfully after " << i << " retry attempts";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
dbgInfo(D_WAAP) << "Failed to send object. Attempt: " << i;
|
dbgInfo(D_WAAP_SERIALIZE) << "Failed to send object. Attempt: " << i;
|
||||||
mainloop->yield(wait_next_attempt);
|
mainloop->yield(wait_next_attempt);
|
||||||
}
|
}
|
||||||
dbgWarning(D_WAAP) << "Failed to send object to " << uri << ", reached maximum attempts: " <<
|
dbgWarning(D_WAAP_SERIALIZE) << "Failed to send object to " << uri << ", reached maximum attempts: " <<
|
||||||
max_send_obj_retries;
|
max_send_obj_retries;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -252,14 +264,14 @@ protected:
|
|||||||
const std::string m_remotePath; // Created from tenentId + / + assetId + / + class
|
const std::string m_remotePath; // Created from tenentId + / + assetId + / + class
|
||||||
std::chrono::seconds m_interval;
|
std::chrono::seconds m_interval;
|
||||||
std::string m_owner;
|
std::string m_owner;
|
||||||
|
const std::string m_assetId;
|
||||||
|
bool m_remoteSyncEnabled;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool localSyncAndProcess();
|
bool localSyncAndProcess();
|
||||||
void updateStateFromRemoteService();
|
void updateStateFromRemoteService();
|
||||||
RemoteFilesList getProcessedFilesList();
|
RemoteFilesList getProcessedFilesList();
|
||||||
RemoteFilesList getRemoteProcessedFilesList();
|
RemoteFilesList getRemoteProcessedFilesList();
|
||||||
std::string getWindowId();
|
|
||||||
bool isBase();
|
|
||||||
std::string getLearningHost();
|
std::string getLearningHost();
|
||||||
std::string getSharedStorageHost();
|
std::string getSharedStorageHost();
|
||||||
|
|
||||||
@@ -269,8 +281,6 @@ private:
|
|||||||
size_t m_daysCount;
|
size_t m_daysCount;
|
||||||
size_t m_windowsCount;
|
size_t m_windowsCount;
|
||||||
size_t m_intervalsCounter;
|
size_t m_intervalsCounter;
|
||||||
bool m_remoteSyncEnabled;
|
|
||||||
const std::string m_assetId;
|
|
||||||
const bool m_isAssetIdUuid;
|
const bool m_isAssetIdUuid;
|
||||||
std::string m_type;
|
std::string m_type;
|
||||||
std::string m_lastProcessedModified;
|
std::string m_lastProcessedModified;
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ public:
|
|||||||
virtual const std::string getUri() const = 0;
|
virtual const std::string getUri() const = 0;
|
||||||
virtual const std::string getUriStr() const = 0;
|
virtual const std::string getUriStr() const = 0;
|
||||||
virtual const std::string& getSourceIdentifier() const = 0;
|
virtual const std::string& getSourceIdentifier() const = 0;
|
||||||
|
virtual const std::string getCurrentWebUserResponse() = 0;
|
||||||
virtual double getScore() const = 0;
|
virtual double getScore() const = 0;
|
||||||
virtual double getOtherModelScore() const = 0;
|
virtual double getOtherModelScore() const = 0;
|
||||||
virtual const std::vector<double> getScoreArray() const = 0;
|
virtual const std::vector<double> getScoreArray() const = 0;
|
||||||
@@ -130,6 +131,7 @@ public:
|
|||||||
virtual void add_request_body_chunk(const char* data, int data_len) = 0;
|
virtual void add_request_body_chunk(const char* data, int data_len) = 0;
|
||||||
virtual void end_request_body() = 0;
|
virtual void end_request_body() = 0;
|
||||||
virtual void end_request() = 0;
|
virtual void end_request() = 0;
|
||||||
|
virtual bool shouldLimitResponseHeadersInspection() = 0;
|
||||||
// Response
|
// Response
|
||||||
virtual void start_response(int response_status, int http_version) = 0;
|
virtual void start_response(int response_status, int http_version) = 0;
|
||||||
virtual void start_response_hdrs() = 0;
|
virtual void start_response_hdrs() = 0;
|
||||||
@@ -145,4 +147,7 @@ public:
|
|||||||
virtual ReportIS::Severity computeEventSeverityFromDecision() const = 0;
|
virtual ReportIS::Severity computeEventSeverityFromDecision() const = 0;
|
||||||
virtual void finish() = 0;
|
virtual void finish() = 0;
|
||||||
virtual Waf2TransactionFlags &getTransactionFlags() = 0;
|
virtual Waf2TransactionFlags &getTransactionFlags() = 0;
|
||||||
|
|
||||||
|
virtual void setTemperatureDetected(bool detected) = 0;
|
||||||
|
virtual bool wasTemperatureDetected() const = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "../waap_clib/WaapParameters.h"
|
#include "../waap_clib/WaapParameters.h"
|
||||||
#include "../waap_clib/WaapOpenRedirectPolicy.h"
|
#include "../waap_clib/WaapOpenRedirectPolicy.h"
|
||||||
#include "../waap_clib/WaapErrorDisclosurePolicy.h"
|
#include "../waap_clib/WaapErrorDisclosurePolicy.h"
|
||||||
|
#include "../waap_clib/DecisionType.h"
|
||||||
#include "../waap_clib/CsrfPolicy.h"
|
#include "../waap_clib/CsrfPolicy.h"
|
||||||
#include "../waap_clib/UserLimitsPolicy.h"
|
#include "../waap_clib/UserLimitsPolicy.h"
|
||||||
#include "../waap_clib/RateLimiting.h"
|
#include "../waap_clib/RateLimiting.h"
|
||||||
@@ -44,8 +45,8 @@ public:
|
|||||||
virtual const std::string& get_AssetId() const = 0;
|
virtual const std::string& get_AssetId() const = 0;
|
||||||
virtual const std::string& get_AssetName() const = 0;
|
virtual const std::string& get_AssetName() const = 0;
|
||||||
virtual const BlockingLevel& get_BlockingLevel() const = 0;
|
virtual const BlockingLevel& get_BlockingLevel() const = 0;
|
||||||
virtual const std::string& get_PracticeId() const = 0;
|
virtual const std::string& get_PracticeIdByPactice(DecisionType practiceType) const = 0;
|
||||||
virtual const std::string& get_PracticeName() const = 0;
|
virtual const std::string& get_PracticeNameByPactice(DecisionType practiceType) const = 0;
|
||||||
virtual const std::string& get_PracticeSubType() const = 0;
|
virtual const std::string& get_PracticeSubType() const = 0;
|
||||||
virtual const std::string& get_RuleId() const = 0;
|
virtual const std::string& get_RuleId() const = 0;
|
||||||
virtual const std::string& get_RuleName() const = 0;
|
virtual const std::string& get_RuleName() const = 0;
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ AutonomousSecurityDecision::AutonomousSecurityDecision(DecisionType type) :
|
|||||||
m_fpMitigationScore(0.0f),
|
m_fpMitigationScore(0.0f),
|
||||||
m_finalScore(0.0f),
|
m_finalScore(0.0f),
|
||||||
m_threatLevel(NO_THREAT),
|
m_threatLevel(NO_THREAT),
|
||||||
m_overridesLog(false),
|
|
||||||
m_relativeReputationMean(0.0),
|
m_relativeReputationMean(0.0),
|
||||||
m_variance(0.0)
|
m_variance(0.0)
|
||||||
{}
|
{}
|
||||||
@@ -52,10 +51,6 @@ void AutonomousSecurityDecision::setThreatLevel(ThreatLevel threatLevel)
|
|||||||
m_threatLevel = threatLevel;
|
m_threatLevel = threatLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutonomousSecurityDecision::setOverridesLog(bool overridesLog)
|
|
||||||
{
|
|
||||||
m_overridesLog = overridesLog;
|
|
||||||
}
|
|
||||||
void AutonomousSecurityDecision::setRelativeReputationMean(double relativeReputationMean)
|
void AutonomousSecurityDecision::setRelativeReputationMean(double relativeReputationMean)
|
||||||
{
|
{
|
||||||
m_relativeReputationMean = relativeReputationMean;
|
m_relativeReputationMean = relativeReputationMean;
|
||||||
@@ -80,10 +75,6 @@ ThreatLevel AutonomousSecurityDecision::getThreatLevel() const
|
|||||||
{
|
{
|
||||||
return m_threatLevel;
|
return m_threatLevel;
|
||||||
}
|
}
|
||||||
bool AutonomousSecurityDecision::getOverridesLog() const
|
|
||||||
{
|
|
||||||
return m_overridesLog;
|
|
||||||
}
|
|
||||||
double AutonomousSecurityDecision::getRelativeReputationMean() const
|
double AutonomousSecurityDecision::getRelativeReputationMean() const
|
||||||
{
|
{
|
||||||
return m_relativeReputationMean;
|
return m_relativeReputationMean;
|
||||||
|
|||||||
@@ -30,14 +30,12 @@ public:
|
|||||||
void setFpMitigationScore(double fpMitigationScore);
|
void setFpMitigationScore(double fpMitigationScore);
|
||||||
void setFinalScore(double finalScore);
|
void setFinalScore(double finalScore);
|
||||||
void setThreatLevel(ThreatLevel threatLevel);
|
void setThreatLevel(ThreatLevel threatLevel);
|
||||||
void setOverridesLog(bool overridesLog);
|
|
||||||
void setRelativeReputationMean(double relativeReputationMean);
|
void setRelativeReputationMean(double relativeReputationMean);
|
||||||
void setVariance(double variance);
|
void setVariance(double variance);
|
||||||
double getRelativeReputation() const;
|
double getRelativeReputation() const;
|
||||||
double getFpMitigationScore() const;
|
double getFpMitigationScore() const;
|
||||||
double getFinalScore() const;
|
double getFinalScore() const;
|
||||||
ThreatLevel getThreatLevel() const;
|
ThreatLevel getThreatLevel() const;
|
||||||
bool getOverridesLog() const;
|
|
||||||
double getRelativeReputationMean() const;
|
double getRelativeReputationMean() const;
|
||||||
double getVariance() const;
|
double getVariance() const;
|
||||||
|
|
||||||
@@ -46,7 +44,6 @@ private:
|
|||||||
double m_fpMitigationScore;
|
double m_fpMitigationScore;
|
||||||
double m_finalScore;
|
double m_finalScore;
|
||||||
ThreatLevel m_threatLevel;
|
ThreatLevel m_threatLevel;
|
||||||
bool m_overridesLog;
|
|
||||||
double m_relativeReputationMean;
|
double m_relativeReputationMean;
|
||||||
double m_variance;
|
double m_variance;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ add_library(waap_clib
|
|||||||
ParserJson.cc
|
ParserJson.cc
|
||||||
ParserMultipartForm.cc
|
ParserMultipartForm.cc
|
||||||
ParserRaw.cc
|
ParserRaw.cc
|
||||||
|
ParserGzip.cc
|
||||||
ParserUrlEncode.cc
|
ParserUrlEncode.cc
|
||||||
ParserXML.cc
|
ParserXML.cc
|
||||||
ParserDelimiter.cc
|
ParserDelimiter.cc
|
||||||
@@ -91,6 +92,7 @@ add_library(waap_clib
|
|||||||
ParserScreenedJson.cc
|
ParserScreenedJson.cc
|
||||||
ParserBinaryFile.cc
|
ParserBinaryFile.cc
|
||||||
RegexComparator.cc
|
RegexComparator.cc
|
||||||
|
RequestsMonitor.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
add_definitions("-Wno-unused-function")
|
add_definitions("-Wno-unused-function")
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ static in6_addr applyMaskV6(const in6_addr& addr, uint8_t prefixLength) {
|
|||||||
in6_addr maskedAddr = addr;
|
in6_addr maskedAddr = addr;
|
||||||
int fullBytes = prefixLength / 8;
|
int fullBytes = prefixLength / 8;
|
||||||
int remainingBits = prefixLength % 8;
|
int remainingBits = prefixLength % 8;
|
||||||
|
uint8_t partialByte = maskedAddr.s6_addr[fullBytes];
|
||||||
|
|
||||||
// Mask full bytes
|
// Mask full bytes
|
||||||
for (int i = fullBytes; i < 16; ++i) {
|
for (int i = fullBytes; i < 16; ++i) {
|
||||||
@@ -50,7 +51,7 @@ static in6_addr applyMaskV6(const in6_addr& addr, uint8_t prefixLength) {
|
|||||||
// Mask remaining bits
|
// Mask remaining bits
|
||||||
if (remainingBits > 0) {
|
if (remainingBits > 0) {
|
||||||
uint8_t mask = ~((1 << (8 - remainingBits)) - 1);
|
uint8_t mask = ~((1 << (8 - remainingBits)) - 1);
|
||||||
maskedAddr.s6_addr[fullBytes] &= mask;
|
maskedAddr.s6_addr[fullBytes] = partialByte & mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
return maskedAddr;
|
return maskedAddr;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -28,6 +28,8 @@
|
|||||||
#include "i_ignoreSources.h"
|
#include "i_ignoreSources.h"
|
||||||
#include "TuningDecisions.h"
|
#include "TuningDecisions.h"
|
||||||
|
|
||||||
|
static constexpr size_t defaultConfidenceMemUsage = 40 * 1024 * 1024; // 40MB
|
||||||
|
|
||||||
USE_DEBUG_FLAG(D_WAAP_CONFIDENCE_CALCULATOR);
|
USE_DEBUG_FLAG(D_WAAP_CONFIDENCE_CALCULATOR);
|
||||||
|
|
||||||
class WaapComponent;
|
class WaapComponent;
|
||||||
@@ -39,9 +41,10 @@ struct ConfidenceCalculatorParams
|
|||||||
std::chrono::minutes intervalDuration;
|
std::chrono::minutes intervalDuration;
|
||||||
double ratioThreshold;
|
double ratioThreshold;
|
||||||
bool learnPermanently;
|
bool learnPermanently;
|
||||||
|
size_t maxMemoryUsage;
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive& ar)
|
void serialize(Archive &ar)
|
||||||
{
|
{
|
||||||
size_t duration = intervalDuration.count();
|
size_t duration = intervalDuration.count();
|
||||||
ar(cereal::make_nvp("minSources", minSources),
|
ar(cereal::make_nvp("minSources", minSources),
|
||||||
@@ -50,10 +53,17 @@ struct ConfidenceCalculatorParams
|
|||||||
cereal::make_nvp("ratioThreshold", ratioThreshold),
|
cereal::make_nvp("ratioThreshold", ratioThreshold),
|
||||||
cereal::make_nvp("learnPermanently", learnPermanently));
|
cereal::make_nvp("learnPermanently", learnPermanently));
|
||||||
intervalDuration = std::chrono::minutes(duration);
|
intervalDuration = std::chrono::minutes(duration);
|
||||||
|
try {
|
||||||
|
ar(cereal::make_nvp("maxMemoryUsage", maxMemoryUsage));
|
||||||
|
} catch (cereal::Exception &e) {
|
||||||
|
maxMemoryUsage = defaultConfidenceMemUsage;
|
||||||
|
dbgTrace(D_WAAP_CONFIDENCE_CALCULATOR) << "maxMemoryUsage not found in serialized data";
|
||||||
|
ar.setNextName(nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const ConfidenceCalculatorParams& other);
|
bool operator==(const ConfidenceCalculatorParams &other);
|
||||||
friend std::ostream& operator<<(std::ostream& os, const ConfidenceCalculatorParams& ccp);
|
friend std::ostream & operator<<(std::ostream &os, const ConfidenceCalculatorParams &ccp);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ConfidenceCalculator : public SerializeToLocalAndRemoteSyncBase
|
class ConfidenceCalculator : public SerializeToLocalAndRemoteSyncBase
|
||||||
@@ -74,7 +84,6 @@ public:
|
|||||||
typedef std::list<ValuesSet> ValuesList;
|
typedef std::list<ValuesSet> ValuesList;
|
||||||
typedef UMap<Key, ValuesList> WindowsConfidentValuesList;
|
typedef UMap<Key, ValuesList> WindowsConfidentValuesList;
|
||||||
typedef UMap<Key, UMap<Val, double>> ConfidenceLevels;
|
typedef UMap<Key, UMap<Val, double>> ConfidenceLevels;
|
||||||
typedef UMap<Key, int> WindowsCounter;
|
|
||||||
typedef UMap<Key, ValueSetWithTime> ConfidenceSet;
|
typedef UMap<Key, ValueSetWithTime> ConfidenceSet;
|
||||||
|
|
||||||
ConfidenceCalculator(size_t minSources,
|
ConfidenceCalculator(size_t minSources,
|
||||||
@@ -82,19 +91,19 @@ public:
|
|||||||
std::chrono::minutes intervalDuration,
|
std::chrono::minutes intervalDuration,
|
||||||
double ratioThreshold,
|
double ratioThreshold,
|
||||||
const Val &nullObj,
|
const Val &nullObj,
|
||||||
const std::string& backupPath,
|
const std::string &backupPath,
|
||||||
const std::string& remotePath,
|
const std::string &remotePath,
|
||||||
const std::string& assetId,
|
const std::string &assetId,
|
||||||
TuningDecision* tuning = nullptr,
|
TuningDecision* tuning = nullptr,
|
||||||
I_IgnoreSources* ignoreSrc = nullptr);
|
I_IgnoreSources* ignoreSrc = nullptr);
|
||||||
|
|
||||||
~ConfidenceCalculator();
|
~ConfidenceCalculator();
|
||||||
|
|
||||||
void setOwner(const std::string& owner);
|
void setOwner(const std::string &owner);
|
||||||
|
|
||||||
void hardReset();
|
void hardReset();
|
||||||
void reset();
|
void reset();
|
||||||
bool reset(ConfidenceCalculatorParams& params);
|
bool reset(ConfidenceCalculatorParams ¶ms);
|
||||||
|
|
||||||
virtual bool postData();
|
virtual bool postData();
|
||||||
virtual void pullData(const std::vector<std::string>& files);
|
virtual void pullData(const std::vector<std::string>& files);
|
||||||
@@ -103,10 +112,12 @@ public:
|
|||||||
virtual void pullProcessedData(const std::vector<std::string>& files);
|
virtual void pullProcessedData(const std::vector<std::string>& files);
|
||||||
virtual void updateState(const std::vector<std::string>& files);
|
virtual void updateState(const std::vector<std::string>& files);
|
||||||
|
|
||||||
virtual void serialize(std::ostream& stream);
|
virtual void serialize(std::ostream &stream);
|
||||||
virtual void deserialize(std::istream& stream);
|
virtual void deserialize(std::istream &stream);
|
||||||
|
|
||||||
void mergeFromRemote(const ConfidenceSet& remote_confidence_set, bool is_first_pull);
|
Maybe<void> writeToFile(const std::string& path, const std::vector<unsigned char>& data);
|
||||||
|
|
||||||
|
void mergeFromRemote(const ConfidenceSet &remote_confidence_set, bool is_first_pull);
|
||||||
|
|
||||||
bool is_confident(const Key &key, const Val &value) const;
|
bool is_confident(const Key &key, const Val &value) const;
|
||||||
|
|
||||||
@@ -121,35 +132,50 @@ public:
|
|||||||
|
|
||||||
void calculateInterval();
|
void calculateInterval();
|
||||||
|
|
||||||
static void mergeConfidenceSets(ConfidenceSet& confidence_set,
|
static void mergeConfidenceSets(ConfidenceSet &confidence_set,
|
||||||
const ConfidenceSet& confidence_set_to_merge,
|
const ConfidenceSet &confidence_set_to_merge,
|
||||||
size_t& last_indicators_update);
|
size_t &last_indicators_update);
|
||||||
private:
|
private:
|
||||||
void loadVer0(cereal::JSONInputArchive& archive);
|
void loadVer0(cereal::JSONInputArchive &archive);
|
||||||
void loadVer1(cereal::JSONInputArchive& archive);
|
void loadVer1(cereal::JSONInputArchive &archive);
|
||||||
void loadVer2(cereal::JSONInputArchive& archive);
|
void loadVer2(cereal::JSONInputArchive &archive);
|
||||||
void loadVer3(cereal::JSONInputArchive& archive);
|
void loadVer3(cereal::JSONInputArchive &archive);
|
||||||
bool tryParseVersionBasedOnNames(
|
bool tryParseVersionBasedOnNames(
|
||||||
cereal::JSONInputArchive& archive,
|
cereal::JSONInputArchive &archive,
|
||||||
const std::string ¶ms_field_name,
|
const std::string ¶ms_field_name,
|
||||||
const std::string &indicators_update_field_name,
|
const std::string &indicators_update_field_name,
|
||||||
const std::string &windows_summary_field_name,
|
const std::string &windows_summary_field_name,
|
||||||
const std::string &confident_sets_field_name);
|
const std::string &confident_sets_field_name);
|
||||||
void convertWindowSummaryToConfidenceLevel(const WindowsConfidentValuesList& windows);
|
void convertWindowSummaryToConfidenceLevel(const WindowsConfidentValuesList &windows);
|
||||||
|
|
||||||
std::string getParamName(const Key& key);
|
void loadConfidenceLevels();
|
||||||
size_t sumSourcesWeight(const SourcesSet& sources);
|
void saveConfidenceLevels(Maybe<ConfidenceCalculator::ConfidenceLevels> confidenceLevels);
|
||||||
void mergeSourcesCounter(const Key& key, const SourcesCounters& counters);
|
void saveConfidenceLevels();
|
||||||
void removeBadSources(SourcesSet& sources, const std::vector<std::string>* badSources);
|
|
||||||
|
void saveTimeWindowLogger();
|
||||||
|
std::shared_ptr<KeyValSourcesLogger> loadTimeWindowLogger();
|
||||||
|
|
||||||
|
std::string getParamName(const Key &key);
|
||||||
|
size_t sumSourcesWeight(const SourcesSet &sources);
|
||||||
|
void removeBadSources(SourcesSet &sources, const std::vector<std::string>* badSources);
|
||||||
|
|
||||||
|
// Delete existing carry-on data files asynchronously with yields
|
||||||
|
void garbageCollector();
|
||||||
|
|
||||||
ConfidenceCalculatorParams m_params;
|
ConfidenceCalculatorParams m_params;
|
||||||
Val m_null_obj;
|
Val m_null_obj;
|
||||||
KeyValSourcesLogger m_time_window_logger;
|
std::shared_ptr<KeyValSourcesLogger> m_time_window_logger;
|
||||||
KeyValSourcesLogger m_time_window_logger_backup;
|
std::shared_ptr<KeyValSourcesLogger> m_time_window_logger_backup;
|
||||||
|
std::string m_path_to_backup;
|
||||||
ConfidenceSet m_confident_sets;
|
ConfidenceSet m_confident_sets;
|
||||||
ConfidenceLevels m_confidence_level;
|
ConfidenceLevels m_confidence_level;
|
||||||
WindowsCounter m_windows_counter;
|
|
||||||
size_t m_last_indicators_update;
|
size_t m_last_indicators_update;
|
||||||
|
size_t m_latest_index;
|
||||||
I_IgnoreSources* m_ignoreSources;
|
I_IgnoreSources* m_ignoreSources;
|
||||||
TuningDecision* m_tuning;
|
TuningDecision* m_tuning;
|
||||||
|
size_t m_estimated_memory_usage; // Variable to track estimated memory usage
|
||||||
|
size_t m_post_index;
|
||||||
|
I_MainLoop *m_mainLoop;
|
||||||
|
I_MainLoop::RoutineID m_routineId;
|
||||||
|
std::vector<std::string> m_filesToRemove;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -45,6 +45,21 @@ State::decide
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto csrfDecision = decision.getDecision(CSRF_DECISION);
|
auto csrfDecision = decision.getDecision(CSRF_DECISION);
|
||||||
|
auto autonomousDecision = decision.getDecision(AUTONOMOUS_SECURITY_DECISION);
|
||||||
|
if (autonomousDecision->shouldForceBlock())
|
||||||
|
{
|
||||||
|
dbgTrace(D_WAAP) << "Waap::CSRF::State::decide(): Autonomous decision force should block.";
|
||||||
|
csrfDecision->setBlock(true);
|
||||||
|
csrfDecision->setForceBlock(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (autonomousDecision->shouldForceAllow())
|
||||||
|
{
|
||||||
|
dbgTrace(D_WAAP) << "Waap::CSRF::State::decide(): Autonomous decision force should allow.";
|
||||||
|
csrfDecision->setBlock(false);
|
||||||
|
csrfDecision->setForceAllow(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (csrf_token.empty())
|
if (csrf_token.empty())
|
||||||
{
|
{
|
||||||
dbgTrace(D_WAAP) << "Waap::CSRF::State::decide(): missing token.";
|
dbgTrace(D_WAAP) << "Waap::CSRF::State::decide(): missing token.";
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
#ifndef __DECISION_TYPE_H__
|
#ifndef __DECISION_TYPE_H__
|
||||||
#define __DECISION_TYPE_H__
|
#define __DECISION_TYPE_H__
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
enum DecisionType
|
enum DecisionType
|
||||||
{
|
{
|
||||||
// This order determines the priority of the decisions sent to management
|
// This order determines the priority of the decisions sent to management
|
||||||
@@ -28,4 +30,35 @@ enum DecisionType
|
|||||||
// Must be kept last
|
// Must be kept last
|
||||||
NO_WAAP_DECISION
|
NO_WAAP_DECISION
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline const char *
|
||||||
|
decisionTypeToString(DecisionType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case DecisionType::AUTONOMOUS_SECURITY_DECISION:
|
||||||
|
return "AUTONOMOUS_SECURITY_DECISION";
|
||||||
|
case DecisionType::CSRF_DECISION:
|
||||||
|
return "CSRF_DECISION";
|
||||||
|
case DecisionType::OPEN_REDIRECT_DECISION:
|
||||||
|
return "OPEN_REDIRECT_DECISION";
|
||||||
|
case DecisionType::ERROR_DISCLOSURE_DECISION:
|
||||||
|
return "ERROR_DISCLOSURE_DECISION";
|
||||||
|
case DecisionType::ERROR_LIMITING_DECISION:
|
||||||
|
return "ERROR_LIMITING_DECISION";
|
||||||
|
case DecisionType::USER_LIMITS_DECISION:
|
||||||
|
return "USER_LIMITS_DECISION";
|
||||||
|
case DecisionType::RATE_LIMITING_DECISION:
|
||||||
|
return "RATE_LIMITING_DECISION";
|
||||||
|
case DecisionType::NO_WAAP_DECISION:
|
||||||
|
return "NO_WAAP_DECISION";
|
||||||
|
default:
|
||||||
|
return "INVALID_DECISION_TYPE";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream & operator<<(std::ostream& os, const DecisionType& type)
|
||||||
|
{
|
||||||
|
return os << decisionTypeToString(type);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "ParserXML.h"
|
#include "ParserXML.h"
|
||||||
#include "ParserHTML.h"
|
#include "ParserHTML.h"
|
||||||
#include "ParserBinary.h"
|
#include "ParserBinary.h"
|
||||||
|
#include "ParserGzip.h"
|
||||||
#include "ParserMultipartForm.h"
|
#include "ParserMultipartForm.h"
|
||||||
#include "ParserPercentEncode.h"
|
#include "ParserPercentEncode.h"
|
||||||
#include "ParserPairs.h"
|
#include "ParserPairs.h"
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "i_transaction.h"
|
#include "i_transaction.h"
|
||||||
#include "agent_core_utilities.h"
|
#include "agent_core_utilities.h"
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
USE_DEBUG_FLAG(D_WAAP_DEEP_PARSER);
|
USE_DEBUG_FLAG(D_WAAP_DEEP_PARSER);
|
||||||
USE_DEBUG_FLAG(D_WAAP_ULIMITS);
|
USE_DEBUG_FLAG(D_WAAP_ULIMITS);
|
||||||
@@ -93,6 +95,12 @@ DeepParser::depth() const
|
|||||||
return m_depth;
|
return m_depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool err = false;
|
||||||
|
static const SingleRegex temperature_value_re(
|
||||||
|
"^\\s*([0-9](?:\\.\\d+)?)\\s*$",
|
||||||
|
err,
|
||||||
|
"temperature_value");
|
||||||
|
|
||||||
// Called when another key/value pair is ready
|
// Called when another key/value pair is ready
|
||||||
int
|
int
|
||||||
DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int flags, size_t parser_depth)
|
DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int flags, size_t parser_depth)
|
||||||
@@ -113,6 +121,9 @@ DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int f
|
|||||||
<< parser_depth
|
<< parser_depth
|
||||||
<< " v_len = "
|
<< " v_len = "
|
||||||
<< v_len;
|
<< v_len;
|
||||||
|
|
||||||
|
dbgTrace(D_WAAP_DEEP_PARSER) << m_key;
|
||||||
|
|
||||||
// Decide whether to push/pop the value in the keystack.
|
// Decide whether to push/pop the value in the keystack.
|
||||||
bool shouldUpdateKeyStack = (flags & BUFFERED_RECEIVER_F_UNNAMED) == 0;
|
bool shouldUpdateKeyStack = (flags & BUFFERED_RECEIVER_F_UNNAMED) == 0;
|
||||||
|
|
||||||
@@ -192,6 +203,14 @@ DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int f
|
|||||||
bool isBodyPayload = (m_key.first().size() == 4 && m_key.first() == "body");
|
bool isBodyPayload = (m_key.first().size() == 4 && m_key.first() == "body");
|
||||||
|
|
||||||
|
|
||||||
|
if (isBodyPayload && v_len < 32 && k_len == 11 &&
|
||||||
|
boost::to_lower_copy(std::string(k, k_len)) == "temperature" &&
|
||||||
|
temperature_value_re.hasMatch(std::string(v, v_len))) {
|
||||||
|
m_pTransaction->setTemperatureDetected(true);
|
||||||
|
dbgTrace(D_WAAP_DEEP_PARSER) << "temperature detected, value: " << std::string(v, v_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// If csrf/antibot cookie - send to Waf2Transaction for collection of cookie value.
|
// If csrf/antibot cookie - send to Waf2Transaction for collection of cookie value.
|
||||||
if (m_depth == 1 && isCookiePayload && (m_key.str() == "x-chkp-csrf-token" || m_key.str() == "__fn1522082288")) {
|
if (m_depth == 1 && isCookiePayload && (m_key.str() == "x-chkp-csrf-token" || m_key.str() == "__fn1522082288")) {
|
||||||
std::string cur_val = std::string(v, v_len);
|
std::string cur_val = std::string(v, v_len);
|
||||||
@@ -275,13 +294,28 @@ DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int f
|
|||||||
// Detect and decode potential base64 chunks in the value before further processing
|
// Detect and decode potential base64 chunks in the value before further processing
|
||||||
|
|
||||||
bool base64ParamFound = false;
|
bool base64ParamFound = false;
|
||||||
|
size_t base64_offset = 0;
|
||||||
Waap::Util::BinaryFileType base64BinaryFileType = Waap::Util::BinaryFileType::FILE_TYPE_NONE;
|
Waap::Util::BinaryFileType base64BinaryFileType = Waap::Util::BinaryFileType::FILE_TYPE_NONE;
|
||||||
if (m_depth == 1 && flags == BUFFERED_RECEIVER_F_MIDDLE && m_key.depth() == 1 && m_key.first() != "#base64"){
|
if (m_depth == 1 && flags == BUFFERED_RECEIVER_F_MIDDLE && m_key.depth() == 1 && m_key.first() != "#base64"){
|
||||||
dbgTrace(D_WAAP_DEEP_PARSER) << " === will not check base64 since prev data block was not b64-encoded ===";
|
dbgTrace(D_WAAP_DEEP_PARSER) << " === will not check base64 since prev data block was not b64-encoded ===";
|
||||||
} else {
|
} else {
|
||||||
dbgTrace(D_WAAP_DEEP_PARSER) << " ===Processing potential base64===";
|
dbgTrace(D_WAAP_DEEP_PARSER) << " ===Processing potential base64===";
|
||||||
|
if (isUrlPayload && m_depth == 1 && cur_val[0] == '/') {
|
||||||
|
dbgTrace(D_WAAP_DEEP_PARSER) << "removing leading '/' from URL param value";
|
||||||
|
base64_offset = 1;
|
||||||
|
}
|
||||||
|
if (m_depth == 1 && (isUrlParamPayload || isRefererParamPayload) &&
|
||||||
|
k_len != 0 && (v_len == 0 || (v[0] == '=' && v_len == 1))) {
|
||||||
|
// if the value is empty or starts with '=' - replace it with key
|
||||||
|
cur_val = std::string(k, k_len);
|
||||||
|
}
|
||||||
std::string decoded_val, decoded_key;
|
std::string decoded_val, decoded_key;
|
||||||
base64_variants base64_status = Waap::Util::b64Test(cur_val, decoded_key, decoded_val, base64BinaryFileType);
|
base64_variants base64_status = Waap::Util::b64Test(
|
||||||
|
cur_val,
|
||||||
|
decoded_key,
|
||||||
|
decoded_val,
|
||||||
|
base64BinaryFileType,
|
||||||
|
base64_offset);
|
||||||
|
|
||||||
dbgTrace(D_WAAP_DEEP_PARSER)
|
dbgTrace(D_WAAP_DEEP_PARSER)
|
||||||
<< " status = "
|
<< " status = "
|
||||||
@@ -289,16 +323,50 @@ DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int f
|
|||||||
<< " key = "
|
<< " key = "
|
||||||
<< decoded_key
|
<< decoded_key
|
||||||
<< " value = "
|
<< " value = "
|
||||||
<< decoded_val;
|
<< decoded_val
|
||||||
|
<< "m_depth = "
|
||||||
|
<< m_depth;
|
||||||
|
|
||||||
switch (base64_status) {
|
switch (base64_status) {
|
||||||
case SINGLE_B64_CHUNK_CONVERT:
|
case SINGLE_B64_CHUNK_CONVERT:
|
||||||
cur_val = decoded_val;
|
if (base64_offset) {
|
||||||
|
cur_val = "/" + decoded_val;
|
||||||
|
} else {
|
||||||
|
cur_val = decoded_val;
|
||||||
|
}
|
||||||
base64ParamFound = true;
|
base64ParamFound = true;
|
||||||
break;
|
break;
|
||||||
|
case CONTINUE_DUAL_SCAN:
|
||||||
|
if (decoded_val.size() > 0) {
|
||||||
|
decoded_key = "#base64";
|
||||||
|
base64ParamFound = false;
|
||||||
|
if (base64_offset) {
|
||||||
|
decoded_val = "/" + decoded_val;
|
||||||
|
}
|
||||||
|
dbgTrace(D_WAAP_DEEP_PARSER) << m_key;
|
||||||
|
rc = onKv(
|
||||||
|
decoded_key.c_str(),
|
||||||
|
decoded_key.size(),
|
||||||
|
decoded_val.data(),
|
||||||
|
decoded_val.size(),
|
||||||
|
flags,
|
||||||
|
parser_depth
|
||||||
|
);
|
||||||
|
dbgTrace(D_WAAP_DEEP_PARSER) << "After call to onKv with suspected value rc = " << rc;
|
||||||
|
dbgTrace(D_WAAP_DEEP_PARSER) << m_key;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
dbgTrace(D_WAAP) << "base64 decode suspected and empty value. Skipping.";
|
||||||
|
base64ParamFound = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case KEY_VALUE_B64_PAIR:
|
case KEY_VALUE_B64_PAIR:
|
||||||
// going deep with new pair in case value is not empty
|
// going deep with new pair in case value is not empty
|
||||||
if (decoded_val.size() > 0) {
|
if (decoded_val.size() > 0) {
|
||||||
|
if (base64_offset) {
|
||||||
|
decoded_key = "/" + decoded_key;
|
||||||
|
}
|
||||||
cur_val = decoded_val;
|
cur_val = decoded_val;
|
||||||
base64ParamFound = true;
|
base64ParamFound = true;
|
||||||
rc = onKv(
|
rc = onKv(
|
||||||
@@ -309,9 +377,13 @@ DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int f
|
|||||||
flags,
|
flags,
|
||||||
parser_depth
|
parser_depth
|
||||||
);
|
);
|
||||||
|
dbgTrace(D_WAAP_DEEP_PARSER) << "After call to onKv with suspected value rc = " << rc;
|
||||||
dbgTrace(D_WAAP_DEEP_PARSER) << " rc = " << rc;
|
dbgTrace(D_WAAP_DEEP_PARSER) << m_key;
|
||||||
if (rc != CONTINUE_PARSING) {
|
if (rc != CONTINUE_PARSING) {
|
||||||
|
if (shouldUpdateKeyStack) {
|
||||||
|
m_key.pop("deep parser key");
|
||||||
|
}
|
||||||
|
m_depth--;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -323,7 +395,7 @@ DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int f
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (base64ParamFound) {
|
if (base64ParamFound) {
|
||||||
dbgTrace(D_WAAP_DEEP_PARSER) << "DeepParser::onKv(): pushing #base64 prefix to the key.";
|
dbgTrace(D_WAAP_DEEP_PARSER) << "pushing #base64 prefix to the key.";
|
||||||
m_key.push("#base64", 7, false);
|
m_key.push("#base64", 7, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -426,6 +498,19 @@ DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int f
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this is url_paran and key is match to nosql_key_evasion_detector_re and this is 1st and last buffer
|
||||||
|
// than add to beginning of cur_val "<key>=" where key is the key
|
||||||
|
if (flags == BUFFERED_RECEIVER_F_BOTH) {
|
||||||
|
std::string key = std::string(k, k_len);
|
||||||
|
if (Waap::Util::testNoSQLKeySuspect(key)) {
|
||||||
|
cur_val = key + "=" + cur_val;
|
||||||
|
dbgTrace(D_WAAP_DEEP_PARSER)
|
||||||
|
<< "DeepParser::onKv(): found: key = "
|
||||||
|
<< key
|
||||||
|
<< " is a candidate for NoSQL key evasion - sending to updated string for scanning.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If there's a parser in parsers stack, push the value to the top parser
|
// If there's a parser in parsers stack, push the value to the top parser
|
||||||
if (!m_parsersDeque.empty()
|
if (!m_parsersDeque.empty()
|
||||||
&& offset >= 0
|
&& offset >= 0
|
||||||
@@ -437,7 +522,6 @@ DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int f
|
|||||||
if (shouldUpdateKeyStack) {
|
if (shouldUpdateKeyStack) {
|
||||||
m_key.pop("deep parser key");
|
m_key.pop("deep parser key");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_depth--;
|
m_depth--;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -587,7 +671,6 @@ DeepParser::parseBuffer(
|
|||||||
if (shouldUpdateKeyStack) {
|
if (shouldUpdateKeyStack) {
|
||||||
m_key.pop("deep parser key");
|
m_key.pop("deep parser key");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_depth--;
|
m_depth--;
|
||||||
return DONE_PARSING;
|
return DONE_PARSING;
|
||||||
}
|
}
|
||||||
@@ -909,7 +992,6 @@ DeepParser::parseAfterMisleadingMultipartBoundaryCleaned(
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1081,7 +1163,7 @@ DeepParser::createInternalParser(
|
|||||||
<< " isBodyPayload = "
|
<< " isBodyPayload = "
|
||||||
<< isBodyPayload;
|
<< isBodyPayload;
|
||||||
//Detect sensor_data format in body and just use dedicated filter for it
|
//Detect sensor_data format in body and just use dedicated filter for it
|
||||||
if (m_depth == 1
|
if ((m_depth == 1)
|
||||||
&& isBodyPayload
|
&& isBodyPayload
|
||||||
&& Waap::Util::detectKnownSource(cur_val) == Waap::Util::SOURCE_TYPE_SENSOR_DATA) {
|
&& Waap::Util::detectKnownSource(cur_val) == Waap::Util::SOURCE_TYPE_SENSOR_DATA) {
|
||||||
m_parsersDeque.push_back(
|
m_parsersDeque.push_back(
|
||||||
@@ -1180,6 +1262,10 @@ DeepParser::createInternalParser(
|
|||||||
dbgTrace(D_WAAP_DEEP_PARSER) << "Starting to parse an HTML file";
|
dbgTrace(D_WAAP_DEEP_PARSER) << "Starting to parse an HTML file";
|
||||||
m_parsersDeque.push_back(std::make_shared<BufferedParser<ParserHTML>>(*this, parser_depth + 1));
|
m_parsersDeque.push_back(std::make_shared<BufferedParser<ParserHTML>>(*this, parser_depth + 1));
|
||||||
offset = 0;
|
offset = 0;
|
||||||
|
} else if (isBodyPayload && Waap::Util::isGzipped(cur_val)){
|
||||||
|
dbgTrace(D_WAAP_DEEP_PARSER) << "Starting to parse a gzip file";
|
||||||
|
m_parsersDeque.push_back(std::make_shared<BufferedParser<ParserGzip>>(*this, parser_depth + 1));
|
||||||
|
offset = 0;
|
||||||
} else if (cur_val.size() > 0 && signatures->php_serialize_identifier.hasMatch(cur_val)) {
|
} else if (cur_val.size() > 0 && signatures->php_serialize_identifier.hasMatch(cur_val)) {
|
||||||
// PHP value detected
|
// PHP value detected
|
||||||
dbgTrace(D_WAAP_DEEP_PARSER) << "Starting to parse phpSerializedData";
|
dbgTrace(D_WAAP_DEEP_PARSER) << "Starting to parse phpSerializedData";
|
||||||
@@ -1278,7 +1364,7 @@ DeepParser::createInternalParser(
|
|||||||
} else if (b64FileType != Waap::Util::BinaryFileType::FILE_TYPE_NONE) {
|
} else if (b64FileType != Waap::Util::BinaryFileType::FILE_TYPE_NONE) {
|
||||||
dbgTrace(D_WAAP_DEEP_PARSER) << "Starting to parse a known binary file, base64 encoded";
|
dbgTrace(D_WAAP_DEEP_PARSER) << "Starting to parse a known binary file, base64 encoded";
|
||||||
m_parsersDeque.push_back(
|
m_parsersDeque.push_back(
|
||||||
std::make_shared<BufferedParser<ParserBinaryFile>>(*this, parser_depth + 1, true, b64FileType)
|
std::make_shared<BufferedParser<ParserBinaryFile>>(*this, parser_depth + 1, false, b64FileType)
|
||||||
);
|
);
|
||||||
offset = 0;
|
offset = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ bool IndicatorsFiltersManager::shouldFilterKeyword(const std::string &key, const
|
|||||||
shouldFilter |= m_keywordsFreqFilter->shouldFilterKeyword(type, keyword);
|
shouldFilter |= m_keywordsFreqFilter->shouldFilterKeyword(type, keyword);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_matchedOverrideKeywords.size() > 0 &&
|
if (m_matchedOverrideKeywords.size() > 0 &&
|
||||||
m_matchedOverrideKeywords.find(keyword) != m_matchedOverrideKeywords.end())
|
m_matchedOverrideKeywords.find(keyword) != m_matchedOverrideKeywords.end())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,14 +37,24 @@ void KeyStack::push(const char* subkey, size_t subkeySize, bool countDepth) {
|
|||||||
m_nameDepth++;
|
m_nameDepth++;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbgTrace(D_WAAP) << "KeyStack(" << m_name << ")::push(): '" << std::string(subkey, subkeySize) <<
|
dbgTrace(D_WAAP)
|
||||||
"' => full_key='" << std::string(m_key.data(), m_key.size()) << "'";
|
<< "KeyStack("
|
||||||
|
<< m_name
|
||||||
|
<< ")::push(): '"
|
||||||
|
<< std::string(subkey, subkeySize)
|
||||||
|
<< "' => full_key='"
|
||||||
|
<< std::string(m_key.data(), m_key.size())
|
||||||
|
<< "'";
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyStack::pop(const char* log, bool countDepth) {
|
void KeyStack::pop(const char* log, bool countDepth) {
|
||||||
// Keep depth balanced even if m_key[] buffer is full
|
// Keep depth balanced even if m_key[] buffer is full
|
||||||
if (m_key.empty() || m_stack.empty()) {
|
if (m_key.empty() || m_stack.empty()) {
|
||||||
dbgDebug(D_WAAP) << "KeyStack(" << m_name << ")::pop(): [ERROR] ATTEMPT TO POP FROM EMPTY KEY STACK! " << log;
|
dbgDebug(D_WAAP)
|
||||||
|
<< "KeyStack("
|
||||||
|
<< m_name
|
||||||
|
<< ")::pop(): [ERROR] ATTEMPT TO POP FROM EMPTY KEY STACK! "
|
||||||
|
<< log;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,6 +65,22 @@ void KeyStack::pop(const char* log, bool countDepth) {
|
|||||||
// Remove last subkey.
|
// Remove last subkey.
|
||||||
m_key.erase(m_stack.back());
|
m_key.erase(m_stack.back());
|
||||||
m_stack.pop_back();
|
m_stack.pop_back();
|
||||||
dbgTrace(D_WAAP) << "KeyStack(" << m_name << ")::pop(): full_key='" <<
|
dbgTrace(D_WAAP)
|
||||||
std::string(m_key.data(), (int)m_key.size()) << "': pop_key=" << log << "'";
|
<< "KeyStack("
|
||||||
|
<< m_name
|
||||||
|
<< ")::pop(): full_key='"
|
||||||
|
<< std::string(m_key.data(), (int)m_key.size())
|
||||||
|
<< "': pop_key="
|
||||||
|
<< log
|
||||||
|
<< "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyStack::print(std::ostream &os) const
|
||||||
|
{
|
||||||
|
os
|
||||||
|
<< "KeyStack("
|
||||||
|
<< m_name
|
||||||
|
<< ")::show(): full_key='"
|
||||||
|
<< std::string(m_key.data(), (int)m_key.size())
|
||||||
|
<< "'";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ public:
|
|||||||
void pop(const char* log, bool countDepth=true);
|
void pop(const char* log, bool countDepth=true);
|
||||||
bool empty() const { return m_key.empty(); }
|
bool empty() const { return m_key.empty(); }
|
||||||
void clear() { m_key.clear(); m_stack.clear(); }
|
void clear() { m_key.clear(); m_stack.clear(); }
|
||||||
|
void print(std::ostream &os) const;
|
||||||
size_t depth() const { return m_nameDepth; }
|
size_t depth() const { return m_nameDepth; }
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return str().size();
|
return str().size();
|
||||||
|
|||||||
@@ -86,10 +86,11 @@ bool KeywordIndicatorFilter::loadParams(std::shared_ptr<Waap::Parameters::WaapPa
|
|||||||
std::to_string(CONFIDENCE_THRESHOLD)));
|
std::to_string(CONFIDENCE_THRESHOLD)));
|
||||||
std::string learnPermanentlyStr = pParams->getParamVal("learnIndicators.learnPermanently", "true");
|
std::string learnPermanentlyStr = pParams->getParamVal("learnIndicators.learnPermanently", "true");
|
||||||
params.learnPermanently = !boost::iequals(learnPermanentlyStr.c_str(), "false");
|
params.learnPermanently = !boost::iequals(learnPermanentlyStr.c_str(), "false");
|
||||||
|
params.maxMemoryUsage = std::stoul(pParams->getParamVal("learnIndicators.maxMemoryUsage",
|
||||||
|
std::to_string(CONFIDENCE_MAX_MEMORY_USAGE)));
|
||||||
|
|
||||||
std::string remoteSyncStr = pParams->getParamVal("remoteSync", "true");
|
std::string remoteSyncStr = pParams->getParamVal("remoteSync", "true");
|
||||||
bool syncEnabled = !boost::iequals(remoteSyncStr, "false");
|
bool syncEnabled = !boost::iequals(remoteSyncStr, "false");
|
||||||
|
|
||||||
dbgTrace(D_WAAP) << params << " remote sync: " << remoteSyncStr;
|
dbgTrace(D_WAAP) << params << " remote sync: " << remoteSyncStr;
|
||||||
|
|
||||||
m_confidence_calc.setRemoteSyncEnabled(syncEnabled);
|
m_confidence_calc.setRemoteSyncEnabled(syncEnabled);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#define CONFIDENCE_MIN_INTERVALS 5
|
#define CONFIDENCE_MIN_INTERVALS 5
|
||||||
#define CONFIDENCE_THRESHOLD 0.8
|
#define CONFIDENCE_THRESHOLD 0.8
|
||||||
#define CONFIDENCE_WINDOW_INTERVAL std::chrono::minutes(120)
|
#define CONFIDENCE_WINDOW_INTERVAL std::chrono::minutes(120)
|
||||||
|
#define CONFIDENCE_MAX_MEMORY_USAGE (40 * 1024 * 1024) // 40MB
|
||||||
|
|
||||||
|
|
||||||
class KeywordIndicatorFilter : public IndicatorFilterBase
|
class KeywordIndicatorFilter : public IndicatorFilterBase
|
||||||
|
|||||||
@@ -41,15 +41,16 @@ LogGenWrapper::LogGenWrapper(
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_log_gen = std::make_unique<LogGen>(
|
m_log_gen = std::make_unique<LogGen>(
|
||||||
maybe_trigger.unpack(),
|
|
||||||
title,
|
title,
|
||||||
security_type,
|
ReportIS::Level::LOG,
|
||||||
|
ReportIS::Audience::SECURITY,
|
||||||
severity,
|
severity,
|
||||||
priority,
|
priority,
|
||||||
is_action_drop_or_prevent,
|
|
||||||
ReportIS::Tags::WAF,
|
ReportIS::Tags::WAF,
|
||||||
ReportIS::Tags::THREAT_PREVENTION
|
ReportIS::Tags::THREAT_PREVENTION,
|
||||||
);
|
maybe_trigger.unpack().getStreams(security_type, is_action_drop_or_prevent),
|
||||||
|
maybe_trigger.unpack().getEnrechments(security_type)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,8 +111,7 @@ int BufferedReceiver::onKvDone()
|
|||||||
// This must be called even if m_value is empty in order to signal the BUFFERED_RECEIVER_F_LAST flag to the
|
// This must be called even if m_value is empty in order to signal the BUFFERED_RECEIVER_F_LAST flag to the
|
||||||
// receiver!
|
// receiver!
|
||||||
dbgTrace(D_WAAP_PARSER)
|
dbgTrace(D_WAAP_PARSER)
|
||||||
<< " Call onKv on the remainder of the buffer not yet pushed to the receiver "
|
<< " Call onKv on the remainder of the buffer not yet pushed to the receiver calling onKv()";
|
||||||
<< "calling onKv()";
|
|
||||||
int rc = onKv(m_key.data(), m_key.size(), m_value.data(), m_value.size(), m_flags, m_parser_depth);
|
int rc = onKv(m_key.data(), m_key.size(), m_value.data(), m_value.size(), m_flags, m_parser_depth);
|
||||||
|
|
||||||
// Reset the object's state to allow reuse for other parsers
|
// Reset the object's state to allow reuse for other parsers
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ ParserBinaryFile::detectBinaryFileHeader(const string &buf)
|
|||||||
return BinaryFileType::FILE_TYPE_NONE;
|
return BinaryFileType::FILE_TYPE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
ParserBinaryFile::push(const char *buf, size_t len)
|
ParserBinaryFile::push(const char *buf, size_t len)
|
||||||
{
|
{
|
||||||
@@ -151,7 +150,10 @@ ParserBinaryFile::push(const char *buf, size_t len)
|
|||||||
} else {
|
} else {
|
||||||
dbgTrace(D_WAAP_PARSER_BINARY_FILE) << "parsing binary. Searching for tail: " << tail;
|
dbgTrace(D_WAAP_PARSER_BINARY_FILE) << "parsing binary. Searching for tail: " << tail;
|
||||||
size_t tail_lookup_offset = (len > MAX_TAIL_LOOKUP) ? len - MAX_TAIL_LOOKUP : 0;
|
size_t tail_lookup_offset = (len > MAX_TAIL_LOOKUP) ? len - MAX_TAIL_LOOKUP : 0;
|
||||||
c = strstr(buf + tail_lookup_offset, tail.c_str());
|
c = static_cast<const char *>(memmem(buf + tail_lookup_offset,
|
||||||
|
len - tail_lookup_offset,
|
||||||
|
tail.c_str(),
|
||||||
|
tail.size()));
|
||||||
dbgTrace(D_WAAP_PARSER_BINARY_FILE) << "search result: c=" << c;
|
dbgTrace(D_WAAP_PARSER_BINARY_FILE) << "search result: c=" << c;
|
||||||
if (c) {
|
if (c) {
|
||||||
m_state = s_end;
|
m_state = s_end;
|
||||||
|
|||||||
115
components/security_apps/waap/waap_clib/ParserGzip.cc
Executable file
115
components/security_apps/waap/waap_clib/ParserGzip.cc
Executable file
@@ -0,0 +1,115 @@
|
|||||||
|
// 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 "ParserGzip.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
USE_DEBUG_FLAG(D_WAAP_PARSER_GZIP);
|
||||||
|
|
||||||
|
const std::string ParserGzip::m_parserName = "ParserGzip";
|
||||||
|
|
||||||
|
ParserGzip::ParserGzip(IParserStreamReceiver &receiver, size_t parser_depth)
|
||||||
|
:m_receiver(receiver), m_key("gzip"), m_state(s_start), m_stream(nullptr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ParserGzip::~ParserGzip() {
|
||||||
|
if (m_stream != nullptr) {
|
||||||
|
finiCompressionStream(m_stream);
|
||||||
|
m_stream = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ParserGzip::push(const char *buf, size_t len) {
|
||||||
|
dbgTrace(D_WAAP_PARSER_GZIP) << "len=" << (unsigned long int)len << ")";
|
||||||
|
|
||||||
|
if (len == 0) {
|
||||||
|
dbgTrace(D_WAAP_PARSER_GZIP) << "end of data signal! m_state=" << m_state;
|
||||||
|
|
||||||
|
// flush
|
||||||
|
if (m_state != s_start) { // only emit if at least something was pushed
|
||||||
|
if (m_receiver.onKvDone() != 0) {
|
||||||
|
m_state = s_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
DecompressionResult res;
|
||||||
|
switch (m_state) {
|
||||||
|
case s_start:
|
||||||
|
dbgTrace(D_WAAP_PARSER_GZIP) << "s_start";
|
||||||
|
if (m_receiver.onKey(m_key.data(), m_key.size()) != 0) {
|
||||||
|
m_state = s_error;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
m_stream = initCompressionStream();
|
||||||
|
m_state = s_forward;
|
||||||
|
// fallthrough //
|
||||||
|
CP_FALL_THROUGH;
|
||||||
|
case s_forward:
|
||||||
|
dbgTrace(D_WAAP_PARSER_GZIP) << "s_forward";
|
||||||
|
res = decompressData(
|
||||||
|
m_stream,
|
||||||
|
len,
|
||||||
|
reinterpret_cast<const unsigned char *>(buf));
|
||||||
|
dbgTrace(D_WAAP_PARSER_GZIP) << "res: " << res.ok
|
||||||
|
<< ", size: " << res.num_output_bytes
|
||||||
|
<< ", is last: " << res.is_last_chunk;
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
m_state = s_error;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.num_output_bytes != 0 &&
|
||||||
|
m_receiver.onValue(reinterpret_cast<const char *>(res.output), res.num_output_bytes) != 0) {
|
||||||
|
m_state = s_error;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.is_last_chunk) {
|
||||||
|
m_state = s_done;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case s_done:
|
||||||
|
if (len > 0) {
|
||||||
|
dbgTrace(D_WAAP_PARSER_GZIP) << " unexpected data after completion, len=" << len;
|
||||||
|
m_state = s_error;
|
||||||
|
return 0; // Return 0 to indicate error
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case s_error:
|
||||||
|
dbgTrace(D_WAAP_PARSER_GZIP) << "s_error";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParserGzip::finish() {
|
||||||
|
push(NULL, 0);
|
||||||
|
if (m_state != s_done) {
|
||||||
|
m_state = s_error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &
|
||||||
|
ParserGzip::name() const {
|
||||||
|
return m_parserName;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParserGzip::error() const {
|
||||||
|
return m_state == s_error;
|
||||||
|
}
|
||||||
46
components/security_apps/waap/waap_clib/ParserGzip.h
Executable file
46
components/security_apps/waap/waap_clib/ParserGzip.h
Executable file
@@ -0,0 +1,46 @@
|
|||||||
|
// 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 __PARSER_GZIP_H_
|
||||||
|
#define __PARSER_GZIP_H_
|
||||||
|
|
||||||
|
#include "ParserBase.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "compression_utils.h"
|
||||||
|
|
||||||
|
class ParserGzip : public ParserBase {
|
||||||
|
public:
|
||||||
|
ParserGzip(IParserStreamReceiver &receiver, size_t parser_depth);
|
||||||
|
virtual ~ParserGzip();
|
||||||
|
size_t push(const char *data, size_t data_len);
|
||||||
|
void finish();
|
||||||
|
virtual const std::string &name() const;
|
||||||
|
bool error() const;
|
||||||
|
virtual size_t depth() { return 1; }
|
||||||
|
private:
|
||||||
|
enum state {
|
||||||
|
s_start,
|
||||||
|
s_forward,
|
||||||
|
s_done,
|
||||||
|
s_error
|
||||||
|
};
|
||||||
|
|
||||||
|
IParserStreamReceiver &m_receiver;
|
||||||
|
std::string m_key;
|
||||||
|
state m_state;
|
||||||
|
CompressionStream * m_stream;
|
||||||
|
|
||||||
|
static const std::string m_parserName;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __PARSER_GZIP_H_
|
||||||
@@ -21,6 +21,7 @@ USE_DEBUG_FLAG(D_WAAP);
|
|||||||
|
|
||||||
const std::string ParserPDF::m_parserName = "ParserPDF";
|
const std::string ParserPDF::m_parserName = "ParserPDF";
|
||||||
const char* PDF_TAIL = "%%EOF";
|
const char* PDF_TAIL = "%%EOF";
|
||||||
|
const size_t PDF_TAIL_LEN = 5;
|
||||||
|
|
||||||
ParserPDF::ParserPDF(
|
ParserPDF::ParserPDF(
|
||||||
IParserStreamReceiver &receiver,
|
IParserStreamReceiver &receiver,
|
||||||
@@ -44,16 +45,21 @@ ParserPDF::push(const char *buf, size_t len)
|
|||||||
<< "' len="
|
<< "' len="
|
||||||
<< len;
|
<< len;
|
||||||
|
|
||||||
const char *c;
|
|
||||||
|
|
||||||
if (m_state == s_error) {
|
if (m_state == s_error) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (len == 0)
|
|
||||||
{
|
|
||||||
dbgTrace(D_WAAP_PARSER_PDF) << "ParserPDF::push(): end of stream. m_state=" << m_state;
|
|
||||||
|
|
||||||
if (m_state == s_end) {
|
if (len == 0) {
|
||||||
|
dbgTrace(D_WAAP_PARSER_PDF) << "ParserPDF::push(): end of stream. m_state=" << m_state;
|
||||||
|
if (m_state == s_body && m_tailOffset >= PDF_TAIL_LEN) {
|
||||||
|
if (m_receiver.onKey("PDF", 3) != 0) {
|
||||||
|
m_state = s_error;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (m_receiver.onValue("", 0) != 0) {
|
||||||
|
m_state = s_error;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
m_receiver.onKvDone();
|
m_receiver.onKvDone();
|
||||||
} else {
|
} else {
|
||||||
m_state = s_error;
|
m_state = s_error;
|
||||||
@@ -61,38 +67,43 @@ ParserPDF::push(const char *buf, size_t len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t start = (len > MAX_PDF_TAIL_LOOKUP) ? len - MAX_PDF_TAIL_LOOKUP : 0;
|
||||||
switch (m_state) {
|
switch (m_state) {
|
||||||
case s_start:
|
case s_start:
|
||||||
m_state = s_body;
|
m_state = s_body;
|
||||||
CP_FALL_THROUGH;
|
CP_FALL_THROUGH;
|
||||||
case s_body:
|
case s_body:
|
||||||
{
|
for (size_t i = start; i < len; i++) {
|
||||||
size_t tail_lookup_offset = (len > MAX_PDF_TAIL_LOOKUP) ? len - MAX_PDF_TAIL_LOOKUP : 0;
|
|
||||||
c = strstr(buf + tail_lookup_offset, PDF_TAIL);
|
|
||||||
dbgTrace(D_WAAP_PARSER_PDF)
|
dbgTrace(D_WAAP_PARSER_PDF)
|
||||||
<< "string to search: " << std::string(buf + tail_lookup_offset)
|
<< "ParserPDF::push(): m_tailOffset="
|
||||||
<< " c=" << c;
|
<< m_tailOffset
|
||||||
if (c) {
|
<< " buf[i]="
|
||||||
m_state = s_end;
|
<< buf[i];
|
||||||
CP_FALL_THROUGH;
|
if (m_tailOffset <= PDF_TAIL_LEN - 1) {
|
||||||
|
if (buf[i] == PDF_TAIL[m_tailOffset]) {
|
||||||
|
m_tailOffset++;
|
||||||
|
} else {
|
||||||
|
m_tailOffset = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
break;
|
if (buf[i] == '\r' || buf[i] == '\n' || buf[i] == ' ' || buf[i] == 0) {
|
||||||
|
m_tailOffset++;
|
||||||
|
} else {
|
||||||
|
m_tailOffset = 0;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case s_end:
|
dbgTrace(D_WAAP_PARSER_PDF)
|
||||||
if (m_receiver.onKey("PDF", 3) != 0) {
|
<< "ParserPDF::push()->s_body: m_tailOffset="
|
||||||
m_state = s_error;
|
<< m_tailOffset;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (m_receiver.onValue("", 0) != 0) {
|
|
||||||
m_state = s_error;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case s_error:
|
case s_error:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dbgTrace(D_WAAP_PARSER_PDF) << "ParserPDF::push(): unknown state: " << m_state;
|
dbgTrace(D_WAAP_PARSER_PDF)
|
||||||
|
<< "ParserPDF::push(): unknown state: "
|
||||||
|
<< m_state;
|
||||||
m_state = s_error;
|
m_state = s_error;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user