mirror of
https://github.com/falcosecurity/falco.git
synced 2026-03-26 14:42:32 +00:00
Compare commits
274 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58b6496f51 | ||
|
|
9dd85bf9db | ||
|
|
6c4b267109 | ||
|
|
7c005aa9dc | ||
|
|
2f2c5c4a9b | ||
|
|
aadb76f2e9 | ||
|
|
23f4f0eee0 | ||
|
|
97373a8b6e | ||
|
|
4ecb907223 | ||
|
|
db30d0e1c7 | ||
|
|
d173ab7a9e | ||
|
|
e4e8dcf06b | ||
|
|
e8aac31890 | ||
|
|
073339eff1 | ||
|
|
001e7557e6 | ||
|
|
73f98de005 | ||
|
|
3760155ec8 | ||
|
|
d8cfaee242 | ||
|
|
e173bf89a3 | ||
|
|
f12149dc87 | ||
|
|
19a6cf74f8 | ||
|
|
c62cc5e8c0 | ||
|
|
ead40f898a | ||
|
|
8eef71b801 | ||
|
|
97883e7535 | ||
|
|
4f897e0dc0 | ||
|
|
d0ee656dac | ||
|
|
49b88c14b2 | ||
|
|
9a314d9443 | ||
|
|
2b8a88c335 | ||
|
|
4a0c9d6ccb | ||
|
|
d55cd79ebd | ||
|
|
5e7346ccb0 | ||
|
|
35d0f0603f | ||
|
|
d685e0967a | ||
|
|
be35c45590 | ||
|
|
d700d2f768 | ||
|
|
4a215ced6c | ||
|
|
f5dab2eb5a | ||
|
|
53c77ea6b5 | ||
|
|
6e56ef77fd | ||
|
|
1306fd6ac1 | ||
|
|
530f999556 | ||
|
|
86cf80d05f | ||
|
|
ed11b8833f | ||
|
|
19ab9e5f35 | ||
|
|
4a8bec09d7 | ||
|
|
3646fb6e03 | ||
|
|
88a5404d1c | ||
|
|
5a19a1d3b0 | ||
|
|
3806e62c3a | ||
|
|
25b07e134c | ||
|
|
bda7d7bb11 | ||
|
|
ab05026065 | ||
|
|
cc30fcc0cf | ||
|
|
fa7fab525f | ||
|
|
ae56a10932 | ||
|
|
676fc9efa8 | ||
|
|
ff94383ed9 | ||
|
|
655ff76c3d | ||
|
|
cacbb3928d | ||
|
|
72725a7f87 | ||
|
|
00c3fa4908 | ||
|
|
eabd3ad24b | ||
|
|
a84adbd231 | ||
|
|
04ce76becc | ||
|
|
6dbccfcac5 | ||
|
|
bd725cb655 | ||
|
|
4d29b872ab | ||
|
|
f78c816abd | ||
|
|
1d76df3831 | ||
|
|
335d79e79c | ||
|
|
ef6888181d | ||
|
|
d3083cde92 | ||
|
|
83353985f7 | ||
|
|
83b036bc0e | ||
|
|
216f56b73b | ||
|
|
17d8eea3bc | ||
|
|
d74c8d6d4d | ||
|
|
888c15c6ee | ||
|
|
eedb794fd5 | ||
|
|
83c527dd91 | ||
|
|
cbcc680c77 | ||
|
|
ad90209177 | ||
|
|
204f9ff875 | ||
|
|
87c410e49e | ||
|
|
b9925577ef | ||
|
|
ae5342c54b | ||
|
|
1324522721 | ||
|
|
7999e33aea | ||
|
|
f49a95f334 | ||
|
|
9e8687401d | ||
|
|
6ead925f51 | ||
|
|
8a3a4c4d57 | ||
|
|
ff21544186 | ||
|
|
ee2f7c50e8 | ||
|
|
5da10a3b89 | ||
|
|
f86423db76 | ||
|
|
5eed3a6638 | ||
|
|
d585343483 | ||
|
|
9e57b5b4ba | ||
|
|
47f38c8ae2 | ||
|
|
332d828204 | ||
|
|
75c6cfb414 | ||
|
|
a4199814a0 | ||
|
|
24e7e84153 | ||
|
|
70bfb2426c | ||
|
|
ce3598f801 | ||
|
|
8e6ffc6fc9 | ||
|
|
6a42f4a133 | ||
|
|
8d9dd4440f | ||
|
|
c49093005d | ||
|
|
69767bb51b | ||
|
|
7750b6f209 | ||
|
|
8c705448cc | ||
|
|
6b9fafb75f | ||
|
|
fdcd7bffd0 | ||
|
|
d989e9c2d5 | ||
|
|
996ccf555c | ||
|
|
2f82a9baa1 | ||
|
|
dfb743838e | ||
|
|
c7609192c7 | ||
|
|
4d3fc354fa | ||
|
|
43bdfce6e5 | ||
|
|
a3976463d5 | ||
|
|
1a485c3447 | ||
|
|
96529300f6 | ||
|
|
27922faa27 | ||
|
|
8a1de131f4 | ||
|
|
e1e8715a0f | ||
|
|
9ae8d281f5 | ||
|
|
c705623f9e | ||
|
|
3640871725 | ||
|
|
6d507b054c | ||
|
|
f19a1d81c6 | ||
|
|
18c7b6500d | ||
|
|
8239fa41f4 | ||
|
|
a9e7512936 | ||
|
|
f67e8bdad7 | ||
|
|
a94e6de458 | ||
|
|
3e9f8c1ef1 | ||
|
|
d20a326e09 | ||
|
|
0c290d98f8 | ||
|
|
1befb053d0 | ||
|
|
ae57718bda | ||
|
|
55ce38cf3a | ||
|
|
18571eb20d | ||
|
|
9c449901f3 | ||
|
|
4ab8d6db98 | ||
|
|
5e354859a9 | ||
|
|
f4b79296fc | ||
|
|
6bf8f34d9f | ||
|
|
f8f053c7fa | ||
|
|
b88a1cbb09 | ||
|
|
c86615f68c | ||
|
|
08df1c63cf | ||
|
|
10512b9ef9 | ||
|
|
0e52ef9971 | ||
|
|
a371a995b4 | ||
|
|
0f984c4dbe | ||
|
|
48a23121df | ||
|
|
475ed0dbeb | ||
|
|
eaccfbe82d | ||
|
|
e496c91562 | ||
|
|
cef2c2d5c1 | ||
|
|
2ee0645f25 | ||
|
|
42f8b1cd83 | ||
|
|
455be15b0b | ||
|
|
64e8feb200 | ||
|
|
eded1062cd | ||
|
|
473b94b386 | ||
|
|
226d1fb728 | ||
|
|
6319be8146 | ||
|
|
cf4672675c | ||
|
|
f035829ca2 | ||
|
|
cd471a78db | ||
|
|
65969c30f9 | ||
|
|
bb8b75a2cd | ||
|
|
b359f71511 | ||
|
|
9dcd8bccac | ||
|
|
b5667cab99 | ||
|
|
2a00a4d853 | ||
|
|
697d4427a7 | ||
|
|
bf04fed71c | ||
|
|
c005af22cc | ||
|
|
c93029ce74 | ||
|
|
076aabcea6 | ||
|
|
d8c588becf | ||
|
|
1a7611a761 | ||
|
|
7fb61ba4a3 | ||
|
|
9ab810f431 | ||
|
|
7781385769 | ||
|
|
205a8fd23b | ||
|
|
bdba37a790 | ||
|
|
19fb3458ef | ||
|
|
b0565794f5 | ||
|
|
66df790b9d | ||
|
|
749d4b4512 | ||
|
|
851033c5f4 | ||
|
|
af6f3bfeab | ||
|
|
c4d25b1d24 | ||
|
|
d434853d5f | ||
|
|
4c8e369691 | ||
|
|
b15a0458b7 | ||
|
|
d6cb8bc4bd | ||
|
|
2cc7fd9072 | ||
|
|
589829ae2f | ||
|
|
85db078dc4 | ||
|
|
23706da75e | ||
|
|
35302f6f09 | ||
|
|
375a6f66c5 | ||
|
|
e8a243d6ea | ||
|
|
7927f45d9f | ||
|
|
d9aff8d564 | ||
|
|
40e3fdd09c | ||
|
|
ba2323046a | ||
|
|
5e6f30109e | ||
|
|
f3c3de7e05 | ||
|
|
ca61f87682 | ||
|
|
113bb5cdd6 | ||
|
|
8a603c3c5d | ||
|
|
0539e948c8 | ||
|
|
5f1d04ec82 | ||
|
|
9d8fc4c8d2 | ||
|
|
09799e125d | ||
|
|
446c65007d | ||
|
|
df3728ec3f | ||
|
|
a66dda3daa | ||
|
|
eec2f5062f | ||
|
|
7dcf8f4bf7 | ||
|
|
bea91ca844 | ||
|
|
ea2ca56d5b | ||
|
|
cb51522423 | ||
|
|
9f53089bcb | ||
|
|
2a4e4d555d | ||
|
|
6a1f4f7374 | ||
|
|
98599d5e25 | ||
|
|
e7d41f8166 | ||
|
|
9075eea62f | ||
|
|
69e32f7ed1 | ||
|
|
38a7f7ada0 | ||
|
|
6a4e4eaa4f | ||
|
|
1313e77113 | ||
|
|
a1fa8edf7e | ||
|
|
d4aa7b9747 | ||
|
|
2312afe9cd | ||
|
|
6ee0b353ac | ||
|
|
28d6a293fc | ||
|
|
5ee62f66f7 | ||
|
|
b33fb6052a | ||
|
|
8448d02980 | ||
|
|
74661a7d8f | ||
|
|
e7b320b00c | ||
|
|
762500a361 | ||
|
|
8563af8a79 | ||
|
|
f7893fbd14 | ||
|
|
3b390793b9 | ||
|
|
10d47cb1f5 | ||
|
|
204892816b | ||
|
|
6156fbb4cb | ||
|
|
20b5ea8f85 | ||
|
|
cc43c721c9 | ||
|
|
230c22b674 | ||
|
|
04f3cc503c | ||
|
|
84d7020e3e | ||
|
|
0cae713412 | ||
|
|
bbbac6203c | ||
|
|
8275730bf8 | ||
|
|
de4b2fa831 | ||
|
|
943a37fcf7 | ||
|
|
3202921355 | ||
|
|
1c60dab87e | ||
|
|
044a7c153e | ||
|
|
a0f7d7cf85 |
@@ -13,7 +13,7 @@ jobs:
|
||||
command: apk update
|
||||
- run:
|
||||
name: Install build dependencies
|
||||
command: apk add g++ gcc cmake cmake make git bash perl linux-headers autoconf automake m4 libtool elfutils-dev libelf-static patch binutils
|
||||
command: apk add g++ gcc cmake make git bash perl linux-headers autoconf automake m4 libtool elfutils-dev libelf-static patch binutils
|
||||
- run:
|
||||
name: Prepare project
|
||||
command: |
|
||||
@@ -176,38 +176,6 @@ jobs:
|
||||
pushd build
|
||||
make tests
|
||||
popd
|
||||
# Build using CentOS 8
|
||||
# This build is static, dependencies are bundled in the Falco binary
|
||||
"build/centos8":
|
||||
docker:
|
||||
- image: centos:8
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Update base image
|
||||
command: dnf update -y
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: dnf install gcc gcc-c++ git make cmake autoconf automake pkg-config patch libtool elfutils-libelf-devel diffutils kernel-devel kernel-headers kernel-core clang llvm which -y
|
||||
- run:
|
||||
name: Prepare project
|
||||
command: |
|
||||
mkdir build
|
||||
pushd build
|
||||
cmake -DBUILD_BPF=On -DUSE_BUNDLED_DEPS=On ..
|
||||
popd
|
||||
- run:
|
||||
name: Build
|
||||
command: |
|
||||
pushd build
|
||||
KERNELDIR=/lib/modules/$(ls /lib/modules)/build make -j4 all
|
||||
popd
|
||||
- run:
|
||||
name: Run unit tests
|
||||
command: |
|
||||
pushd build
|
||||
make tests
|
||||
popd
|
||||
# Build using our own builder base image using centos 7
|
||||
# This build is static, dependencies are bundled in the Falco binary
|
||||
"build/centos7":
|
||||
@@ -292,6 +260,7 @@ jobs:
|
||||
BUILD_DIR: "/build-static"
|
||||
BUILD_TYPE: "release"
|
||||
SKIP_PACKAGES_TESTS: "true"
|
||||
SKIP_PLUGINS_TESTS: "true"
|
||||
steps:
|
||||
- setup_remote_docker
|
||||
- attach_workspace:
|
||||
@@ -303,7 +272,7 @@ jobs:
|
||||
path: /build-static/release/integration-tests-xunit
|
||||
"tests/driver-loader/integration":
|
||||
machine:
|
||||
image: ubuntu-1604:202004-01
|
||||
image: ubuntu-2004:202107-02
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: /tmp/ws
|
||||
@@ -390,9 +359,15 @@ jobs:
|
||||
/source/falco/scripts/publish-rpm -f /build/release/falco-${FALCO_VERSION}-x86_64.rpm -r rpm-dev
|
||||
- run:
|
||||
name: Publish bin-dev
|
||||
command: |
|
||||
FALCO_VERSION=$(cat /build/release/userspace/falco/config_falco.h | grep 'FALCO_VERSION ' | cut -d' ' -f3 | sed -e 's/^"//' -e 's/"$//')
|
||||
/source/falco/scripts/publish-bin -f /build/release/falco-${FALCO_VERSION}-x86_64.tar.gz -r bin-dev -a x86_64
|
||||
- run:
|
||||
name: Publish bin-static-dev
|
||||
command: |
|
||||
FALCO_VERSION=$(cat /build-static/release/userspace/falco/config_falco.h | grep 'FALCO_VERSION ' | cut -d' ' -f3 | sed -e 's/^"//' -e 's/"$//')
|
||||
/source/falco/scripts/publish-bin -f /build-static/release/falco-${FALCO_VERSION}-x86_64.tar.gz -r bin-dev -a x86_64
|
||||
cp -f /build-static/release/falco-${FALCO_VERSION}-x86_64.tar.gz /build-static/release/falco-${FALCO_VERSION}-static-x86_64.tar.gz
|
||||
/source/falco/scripts/publish-bin -f /build-static/release/falco-${FALCO_VERSION}-static-x86_64.tar.gz -r bin-dev -a x86_64
|
||||
"publish/packages-deb-dev":
|
||||
docker:
|
||||
- image: docker.io/debian:stable
|
||||
@@ -504,9 +479,15 @@ jobs:
|
||||
/source/falco/scripts/publish-rpm -f /build/release/falco-${FALCO_VERSION}-x86_64.rpm -r rpm
|
||||
- run:
|
||||
name: Publish bin
|
||||
command: |
|
||||
FALCO_VERSION=$(cat /build/release/userspace/falco/config_falco.h | grep 'FALCO_VERSION ' | cut -d' ' -f3 | sed -e 's/^"//' -e 's/"$//')
|
||||
/source/falco/scripts/publish-bin -f /build/release/falco-${FALCO_VERSION}-x86_64.tar.gz -r bin -a x86_64
|
||||
- run:
|
||||
name: Publish bin-static
|
||||
command: |
|
||||
FALCO_VERSION=$(cat /build-static/release/userspace/falco/config_falco.h | grep 'FALCO_VERSION ' | cut -d' ' -f3 | sed -e 's/^"//' -e 's/"$//')
|
||||
/source/falco/scripts/publish-bin -f /build-static/release/falco-${FALCO_VERSION}-x86_64.tar.gz -r bin -a x86_64
|
||||
cp -f /build-static/release/falco-${FALCO_VERSION}-x86_64.tar.gz /build-static/release/falco-${FALCO_VERSION}-static-x86_64.tar.gz
|
||||
/source/falco/scripts/publish-bin -f /build-static/release/falco-${FALCO_VERSION}-static-x86_64.tar.gz -r bin -a x86_64
|
||||
"publish/packages-deb":
|
||||
docker:
|
||||
- image: docker.io/debian:stable
|
||||
@@ -617,7 +598,6 @@ workflows:
|
||||
- "build/ubuntu-focal"
|
||||
- "build/ubuntu-focal-debug"
|
||||
- "build/ubuntu-bionic"
|
||||
- "build/centos8"
|
||||
- "build/centos7"
|
||||
- "build/centos7-debug"
|
||||
- "tests/integration":
|
||||
@@ -681,7 +661,7 @@ workflows:
|
||||
only: master
|
||||
requires:
|
||||
- publish/docker-dev
|
||||
# - "quality/static-analysis" # This is temporarly disabled: https://github.com/falcosecurity/falco/issues/1526
|
||||
# - "quality/static-analysis" # This is temporarily disabled: https://github.com/falcosecurity/falco/issues/1526
|
||||
release:
|
||||
jobs:
|
||||
- "build/musl":
|
||||
|
||||
@@ -7,7 +7,7 @@ line_width = 120
|
||||
# How many spaces to tab for indent
|
||||
tab_size = 2
|
||||
|
||||
# If arglists are longer than this, break them always
|
||||
# If arg lists are longer than this, break them always
|
||||
max_subargs_per_line = 3
|
||||
|
||||
# If true, separate flow control names from their parentheses with a space
|
||||
@@ -21,7 +21,7 @@ separate_fn_name_with_space = False
|
||||
dangle_parens = False
|
||||
|
||||
# If the statement spelling length (including space and parenthesis is larger
|
||||
# than the tab width by more than this amoung, then force reject un-nested
|
||||
# than the tab width by more than this among, then force reject un-nested
|
||||
# layouts.
|
||||
max_prefix_chars = 2
|
||||
|
||||
@@ -54,7 +54,7 @@ always_wrap = []
|
||||
algorithm_order = [0, 1, 2, 3, 4]
|
||||
|
||||
# If true, the argument lists which are known to be sortable will be sorted
|
||||
# lexicographicall
|
||||
# lexicographically
|
||||
enable_sort = True
|
||||
|
||||
# If true, the parsers may infer whether or not an argument list is sortable
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -10,11 +10,8 @@ test/.phoronix-test-suite
|
||||
test/results*.json.*
|
||||
test/build
|
||||
|
||||
userspace/engine/lua/lyaml
|
||||
userspace/engine/lua/lyaml.lua
|
||||
|
||||
.vscode/*
|
||||
|
||||
.luacheckcache
|
||||
|
||||
*.idea*
|
||||
*.idea*
|
||||
|
||||
26
ADOPTERS.md
26
ADOPTERS.md
@@ -5,7 +5,7 @@ Known end users with notable contributions to the project include:
|
||||
* IBM
|
||||
* Red Hat
|
||||
|
||||
Falco is being used by numerous other companies, both large and small, to build higher layer products and services. The list includes but is not limited to:
|
||||
Falco is being used by numerous other companies, both large and small, to build higher layer products and services. The list includes but is not limited to:
|
||||
* Equinix Metal
|
||||
* IEEE
|
||||
* Lowes
|
||||
@@ -24,8 +24,12 @@ This is a list of production adopters of Falco (in alphabetical order):
|
||||
|
||||
* [Coveo](https://www.coveo.com/) - Coveo stitches together content and data, learning from every interaction, to tailor every experience using AI to drive growth, satisfy customers and develop employee proficiency. All Falco events are centralized in our SIEM for analysis. Understanding what is running on production servers, and the context around why things are running is even more tricky now that we have further abstractions with containers and orchestration systems. Falco is giving us a good visibility inside containers and complement other Host and Network Intrusion Detection Systems. In a near future, we expect to deploy serverless functions to take action when Falco identifies patterns worth taking action for.
|
||||
|
||||
* [Fairwinds](https://fairwinds.com/) - [Fairwinds Insights](https://fairwinds.com/insights), Kubernetes governance software, integrates Falco to offer a single pane of glass view into potential security incidents. Insights adds out-of-the-box integrations and rules filter to reduce alert fatigue and improve security response. The platform adds security prevention, detection, and response capabilities to your existing Kubernetes infrastructure. Security and DevOps teams benefit from a centralized view of container security vulnerability scanning and runtime container security.
|
||||
|
||||
* [Frame.io](https://frame.io/) - Frame.io is a cloud-based (SaaS) video review and collaboration platform that enables users to securely upload source media, work-in-progress edits, dailies, and more into private workspaces where they can invite their team and clients to collaborate on projects. Understanding what is running on production servers, and the context around why things are running is even more tricky now that we have further abstractions like Docker and Kubernetes. To get this needed visibility into our system, we rely on Falco. Falco's ability to collect raw system calls such as open, connect, exec, along with their arguments offer key insights on what is happening on the production system and became the foundation of our intrusion detection and alerting system.
|
||||
|
||||
* [Giant Swarm](https://www.giantswarm.io/) - Giant Swarm manages Kubernetes clusters and infrastructure for enterprises across multiple cloud providers as well as several flavors of on-premises data centers. Our platform provisions and monitors pure "vanilla" Kubernetes clusters which can be augmented with managed solutions to many common Kubernetes challenges, including security. We use Falco for anomaly detection as part of our collection of entirely open-source tools for securing our own clusters, and offer the same capabilities to our customers as part of our [managed security offering](https://docs.giantswarm.io/app-platform/apps/security/).
|
||||
|
||||
* [GitLab](https://about.gitlab.com/direction/defend/container_host_security/) - GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate. GitLab Ultimate provides the single tool teams need to find, triage, and fix vulnerabilities in applications, services, and cloud-native environments enabling them to manage their risk. This provides them with repeatable, defensible processes that automate security and compliance policies. GitLab includes a tight integration with Falco, allowing users to defend their containerized applications from attacks while running in production.
|
||||
|
||||
* [League](https://league.com/ca/) - League provides health benefits management services to help employees understand and get the most from their benefits, and employers to provide effective, efficient plans. Falco is used to monitor our deployed services on Kubernetes, protecting against malicious access to containers which could lead to leaks of PHI or other sensitive data. The Falco alerts are logged in Stackdriver for grouping and further analysis. In the future, we're hoping for integrations with Prometheus and AlertManager as well.
|
||||
@@ -37,14 +41,16 @@ This is a list of production adopters of Falco (in alphabetical order):
|
||||
|
||||
* [Pocteo](https://pocteo.co) - Pocteo helps with Kubernetes adoption in enterprises by providing a variety of services such as training, consulting, auditing and mentoring. We build CI/CD pipelines the GitOps way, as well as design and run k8s clusters. Pocteo uses Falco as a runtime monitoring system to secure clients' workloads against suspicious behavior and ensure k8s pods immutability. We also use Falco to collect, process and act on security events through a response engine and serverless functions.
|
||||
|
||||
* [Preferral](https://www.preferral.com) - Preferral is a HIPAA-compliant platform for Referral Management and Online Referral Forms. Preferral streamlines the referral process for patients, specialists and their referral partners. By automating the referral process, referring practices spend less time on the phone, manual efforts are eliminated, and patients get the right care from the right specialist. Preferral leverages Falco to provide a Host Intrusion Detection System to meet their HIPPA compliance requirements.
|
||||
* [Preferral](https://www.preferral.com) - Preferral is a HIPAA-compliant platform for Referral Management and Online Referral Forms. Preferral streamlines the referral process for patients, specialists and their referral partners. By automating the referral process, referring practices spend less time on the phone, manual efforts are eliminated, and patients get the right care from the right specialist. Preferral leverages Falco to provide a Host Intrusion Detection System to meet their HIPAA compliance requirements.
|
||||
* https://hipaa.preferral.com/01-preferral_hipaa_compliance/
|
||||
|
||||
* [Qonto](https://qonto.com) - Qonto is a modern banking for SMEs and freelancers. Qonto provides a fully featured business account with a simplified accounting flow. Falco is used by our SecOps team to detect suspicous behaviors in our clusters.
|
||||
* [Qonto](https://qonto.com) - Qonto is a modern banking for SMEs and freelancers. Qonto provides a fully featured business account with a simplified accounting flow. Falco is used by our SecOps team to detect suspicious behaviors in our clusters.
|
||||
|
||||
* [Raft](https://goraft.tech) - Raft is a government contractor that offers cloud-native solutions across many different agencies including DoD (Department of Defense), HHS (Health and Human Services), as well as within CFPB (Consumer Finance Protection Bureau). Raft leverages Falco to detect threats in our client's Kubernetes clusters and as a Host Intrusion Detection System. Raft proudly recommends Falco across all our different projects.
|
||||
|
||||
* [Replicated](https://www.replicated.com/) - Replicated is the modern way to ship on-prem software. Replicated gives software vendors a container-based platform for easily deploying cloud native applications inside customers' environments to provide greater security and control. Replicated uses Falco as runtime security to detect threats in the Kubernetes clusters which host our critical SaaS services.
|
||||
|
||||
* [Secureworks](https://www.secureworks.com/) - Secureworks is a leading worldwide cybersecurity company with a cloud-native security product that combines the power of human intellect with security analytics to unify detection and response across cloud, network, and endpoint environments for improved security operations and outcomes. Our Taegis XDR platform and detection system processes petabytes of security relevant data to expose active threats amongst the billions of daily events from our customers. We are proud to protect our platform’s Kubernetes deployments, as well as help our customers protect their own Linux and container environments, using Falco.
|
||||
* [Secureworks](https://www.secureworks.com/) - Secureworks is a leading worldwide cybersecurity company with a cloud-native security product that combines the power of human intellect with security analytics to unify detection and response across cloud, network, and endpoint environments for improved security operations and outcomes. Our Taegis XDR platform and detection system processes petabytes of security relevant data to expose active threats amongst the billions of daily events from our customers. We are proud to protect our platform’s Kubernetes deployments, as well as help our customers protect their own Linux and container environments, using Falco.
|
||||
|
||||
* [Shopify](https://www.shopify.com) - Shopify is the leading multi-channel commerce platform. Merchants use Shopify to design, set up, and manage their stores across multiple sales channels, including mobile, web, social media, marketplaces, brick-and-mortar locations, and pop-up shops. The platform also provides merchants with a powerful back-office and a single view of their business, from payments to shipping. The Shopify platform was engineered for reliability and scale, making enterprise-level technology available to businesses of all sizes. Shopify uses Falco to complement its Host and Network Intrusion Detection Systems.
|
||||
|
||||
@@ -56,12 +62,18 @@ This is a list of production adopters of Falco (in alphabetical order):
|
||||
|
||||
* [Swissblock Technologies](https://swissblock.net/) At Swissblock we connect the dots by combining cutting-edge algorithmic trading strategies with in-depth market analysis. We route all Falco events to our control systems, both monitoring and logging. Being able to deeply analyse alerts, we can understand what is running on our Kubernetes clusters and check against security policies, specifically defined for each workload. A set of alarms notifies us in case of critical events, letting us react fast. In the near future we plan to build a little application to route Kubernetes internal events directly to Falco, fully leveraging Falco PodSecurityPolicies analyses.
|
||||
|
||||
* [Shapesecurity/F5] (https://www.shapesecurity.com/) Shapesecurity defends against application fraud attacks like Account Take Over, Credential Stuffing, Fake Accounts, etc. Required by FedRamp certification, we needed to find a FIM solution to help monitor and protect our Kubernetes clusters. Traditional FIM solutions were not scalable and not working for our environment, but with Falco we found the solution we needed. Falco's detection capabilities have helped us identify anomalous behaviour within our clusters. We leverage Sidekick (https://github.com/falcosecurity/charts/tree/master/falcosidekick) to send Falco alerts to a PubSub which in turn publishes those alerts to our SIEM (SumoLogic)
|
||||
* [Shapesecurity/F5](https://www.shapesecurity.com/) Shapesecurity defends against application fraud attacks like Account Take Over, Credential Stuffing, Fake Accounts, etc. Required by FedRamp certification, we needed to find a FIM solution to help monitor and protect our Kubernetes clusters. Traditional FIM solutions were not scalable and not working for our environment, but with Falco we found the solution we needed. Falco's detection capabilities have helped us identify anomalous behaviour within our clusters. We leverage Sidekick (https://github.com/falcosecurity/charts/tree/master/falcosidekick) to send Falco alerts to a PubSub which in turn publishes those alerts to our SIEM (SumoLogic)
|
||||
|
||||
* [Yahoo! JAPAN](https://www.yahoo.co.jp/) Yahoo! JAPAN is a leading company of internet in Japan. We build an AI Platform in our private cloud and provide it to scientists in our company. AI Platform is a multi-tenant Kubernetes environment and more flexible, faster, more efficient Machine Learning environment. Falco is used to detect unauthorized commands and malicious access and our AI Platform is monitored and alerted by Falco.
|
||||
|
||||
* [Sysdig](https://www.sysdig.com/) Sysdig originally created Falco in 2016 to detect unexpected or suspicious activity using a rules engine on top of the data that comes from the sysdig kernel system call probe. Sysdig provides tooling to help with vulnerability management, compliance, detection, incident response and forensics in Cloud-native environments. Sysdig Secure has extended Falco to include: a rule library, the ability to update macros, lists & rules via the user interface and API, automated tuning of rules, and rule creation based on profiling known system behavior. On top of the basic Falco rules, Sysdig Secure implements the concept of a "Security policy" that can comprise several rules which are evaluated for a user-defined infrastructure scope like Kubernetes namespaces, OpenShift clusters, deployment workload, cloud regions etc.
|
||||
* [Sysdig](https://www.sysdig.com/) Sysdig originally created Falco in 2016 to detect unexpected or suspicious activity using a rules engine on top of the data that comes from the sysdig kernel system call driver. Sysdig provides tooling to help with vulnerability management, compliance, detection, incident response and forensics in Cloud-native environments. Sysdig Secure has extended Falco to include: a rule library, the ability to update macros, lists & rules via the user interface and API, automated tuning of rules, and rule creation based on profiling known system behavior. On top of the basic Falco rules, Sysdig Secure implements the concept of a "Security policy" that can comprise several rules which are evaluated for a user-defined infrastructure scope like Kubernetes namespaces, OpenShift clusters, deployment workload, cloud regions etc.
|
||||
|
||||
## Projects that use Falco libs
|
||||
|
||||
* [R6/Phoenix](https://r6security.com/) is an attack surface protection company that uses moving target defense to provide fully automated, proactive and devops friendly security to its customers. There are a set of policies you can add to enable the moving target defense capabilities. Some of them are triggered by a combination of Falco's findings. You can kill, restart and rename pods according to the ever changing policies.
|
||||
|
||||
* [SysFlow](https://sysflow.io) SysFlow is a cloud-native system telemetry framework that focuses on data abstraction, behavioral analytics, and noise reduction. At its core, SysFlow exposes a compact open telemetry format that records workload behaviors by connecting event and flow representations of process control flows, file interactions, and network communications. The resulting abstraction encodes a graph structure that enables provenance reasoning on host and container environments, and fast retrieval of security-relevant information.
|
||||
|
||||
## Adding a name
|
||||
|
||||
If you would like to add your name to this file, submit a pull request with your change.
|
||||
If you would like to add your name to this file, submit a pull request with your change.
|
||||
|
||||
163
CHANGELOG.md
163
CHANGELOG.md
@@ -1,5 +1,150 @@
|
||||
# Change Log
|
||||
|
||||
## v0.31.1
|
||||
|
||||
Released on 2022-03-09
|
||||
|
||||
### Major Changes
|
||||
|
||||
|
||||
* new: add a new drop category `n_drops_scratch_map` [[#1916](https://github.com/falcosecurity/falco/pull/1916)] - [@Andreagit97](https://github.com/Andreagit97)
|
||||
* new: allow to specify multiple --cri options [[#1893](https://github.com/falcosecurity/falco/pull/1893)] - [@FedeDP](https://github.com/FedeDP)
|
||||
|
||||
|
||||
### Minor Changes
|
||||
|
||||
* refactor(userspace/falco): replace direct getopt_long() cmdline option parsing with third-party cxxopts library. [[#1886](https://github.com/falcosecurity/falco/pull/1886)] - [@mstemm](https://github.com/mstemm)
|
||||
* update: driver version is b7eb0dd [[#1923](https://github.com/falcosecurity/falco/pull/1923)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix(userspace/falco): correct plugins init config conversion from YAML to JSON [[#1907](https://github.com/falcosecurity/falco/pull/1907)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* fix(userspace/engine): for rules at the informational level being loaded at the notice level [[#1885](https://github.com/falcosecurity/falco/pull/1885)] - [@mike-stewart](https://github.com/mike-stewart)
|
||||
* chore(userspace/falco): fixes truncated -b option description. [[#1915](https://github.com/falcosecurity/falco/pull/1915)] - [@andreabonanno](https://github.com/andreabonanno)
|
||||
* update(falco): updates usage description for -o, --option [[#1903](https://github.com/falcosecurity/falco/pull/1903)] - [@andreabonanno](https://github.com/andreabonanno)
|
||||
|
||||
|
||||
### Rule Changes
|
||||
|
||||
* rule(Detect outbound connections to common miner pool ports): fix url in rule output [[#1918](https://github.com/falcosecurity/falco/pull/1918)] - [@jsoref](https://github.com/jsoref)
|
||||
* rule(macro somebody_becoming_themself): renaming macro to somebody_becoming_themselves [[#1918](https://github.com/falcosecurity/falco/pull/1918)] - [@jsoref](https://github.com/jsoref)
|
||||
* rule(list package_mgmt_binaries): `npm` added [[#1866](https://github.com/falcosecurity/falco/pull/1866)] - [@rileydakota](https://github.com/rileydakota)
|
||||
* rule(Launch Package Management Process in Container): support for detecting `npm` usage [[#1866](https://github.com/falcosecurity/falco/pull/1866)] - [@rileydakota](https://github.com/rileydakota)
|
||||
* rule(Polkit Local Privilege Escalation Vulnerability): new rule created to detect CVE-2021-4034 [[#1877](https://github.com/falcosecurity/falco/pull/1877)] - [@darryk10](https://github.com/darryk10)
|
||||
* rule(macro: modify_shell_history): avoid false-positive alerts triggered by modifications to .zsh_history.new and .zsh_history.LOCK files [[#1832](https://github.com/falcosecurity/falco/pull/1832)] - [@m4wh6k](https://github.com/m4wh6k)
|
||||
* rule(macro: truncate_shell_history): avoid false-positive alerts triggered by modifications to .zsh_history.new and .zsh_history.LOCK files [[#1832](https://github.com/falcosecurity/falco/pull/1832)] - [@m4wh6k](https://github.com/m4wh6k)
|
||||
* rule(macro sssd_writing_krb): fixed a false-positive alert that was being generated when SSSD updates /etc/krb5.keytab [[#1825](https://github.com/falcosecurity/falco/pull/1825)] - [@mac-chaffee](https://github.com/mac-chaffee)
|
||||
* rule(macro write_etc_common): fixed a false-positive alert that was being generated when SSSD updates /etc/krb5.keytab [[#1825](https://github.com/falcosecurity/falco/pull/1825)] - [@mac-chaffee](https://github.com/mac-chaffee)
|
||||
* upgrade macro(keepalived_writing_conf) [[#1742](https://github.com/falcosecurity/falco/pull/1742)] - [@pabloopez](https://github.com/pabloopez)
|
||||
* rule_output(Delete Bucket Public Access Block) typo [[#1888](https://github.com/falcosecurity/falco/pull/1888)] - [@pabloopez](https://github.com/pabloopez)
|
||||
|
||||
|
||||
### Non user-facing changes
|
||||
|
||||
* fix(build): fix civetweb linking in cmake module [[#1919](https://github.com/falcosecurity/falco/pull/1919)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* chore(userspace/engine): remove unused lua functions and state vars [[#1908](https://github.com/falcosecurity/falco/pull/1908)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* fix(userspace/falco): applies FALCO_INSTALL_CONF_FILE as the default … [[#1900](https://github.com/falcosecurity/falco/pull/1900)] - [@andreabonanno](https://github.com/andreabonanno)
|
||||
* fix(scripts): correct typo in `falco-driver-loader` help message [[#1899](https://github.com/falcosecurity/falco/pull/1899)] - [@leogr](https://github.com/leogr)
|
||||
* update(build)!: replaced various `PROBE` with `DRIVER` where necessary. [[#1887](https://github.com/falcosecurity/falco/pull/1887)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* Add [Fairwinds](https://fairwinds.com) to the adopters list [[#1917](https://github.com/falcosecurity/falco/pull/1917)] - [@sudermanjr](https://github.com/sudermanjr)
|
||||
* build(cmake): several cmake changes to speed up/simplify builds for external projects and copying files from source-to-build directories [[#1905](https://github.com/falcosecurity/falco/pull/1905)] - [@mstemm](https://github.com/mstemm)
|
||||
|
||||
|
||||
## v0.31.0
|
||||
|
||||
Released on 2022-01-31
|
||||
|
||||
### Major Changes
|
||||
|
||||
|
||||
* new: add support for plugins to extend Falco functionality to new event sources and custom fields [[#1753](https://github.com/falcosecurity/falco/pull/1753)] - [@mstemm](https://github.com/mstemm)
|
||||
* new: add ability to set User-Agent http header when sending http output. Provide default value of 'falcosecurity/falco'. [[#1850](https://github.com/falcosecurity/falco/pull/1850)] - [@yoshi314](https://github.com/yoshi314)
|
||||
* new(configuration): support defining plugin init config as a YAML [[#1852](https://github.com/falcosecurity/falco/pull/1852)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
|
||||
|
||||
### Minor Changes
|
||||
|
||||
* rules: add the official Falco ECR repository to rules [[#1817](https://github.com/falcosecurity/falco/pull/1817)] - [@calvinbui](https://github.com/calvinbui)
|
||||
* build: update CircleCI machine image for eBPF tests to a newer version of ubuntu [[#1764](https://github.com/falcosecurity/falco/pull/1764)] - [@mstemm](https://github.com/mstemm)
|
||||
* update(engine): refactor Falco engine to be agnostic to specific event sources [[#1715](https://github.com/falcosecurity/falco/pull/1715)] - [@mstemm](https://github.com/mstemm)
|
||||
* build: upgrade civetweb to v1.15 [[#1782](https://github.com/falcosecurity/falco/pull/1782)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* update: driver version is 319368f1ad778691164d33d59945e00c5752cd27 now [[#1861](https://github.com/falcosecurity/falco/pull/1861)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* build: allow using local libs source dir by setting `FALCOSECURITY_LIBS_SOURCE_DIR` in cmake [[#1791](https://github.com/falcosecurity/falco/pull/1791)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* build: the statically linked binary package is now published with the `-static` suffix [[#1873](https://github.com/falcosecurity/falco/pull/1873)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* update!: removed "--alternate-lua-dir" cmdline option as lua scripts are now embedded in Falco executable. [[#1872](https://github.com/falcosecurity/falco/pull/1872)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* build: switch to dynamic build for the binary package (`.tar.gz`) [[#1853](https://github.com/falcosecurity/falco/pull/1853)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* update: simpleconsumer filtering is now being done at kernel level [[#1846](https://github.com/falcosecurity/falco/pull/1846)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* update(scripts/falco-driver-loader): first try to load the latest kmod version, then fallback to an already installed if any [[#1863](https://github.com/falcosecurity/falco/pull/1863)] - [@leogr](https://github.com/leogr)
|
||||
* refactor: clean up --list output with better formatting and no duplicate sections across event sources. [[#1816](https://github.com/falcosecurity/falco/pull/1816)] - [@mstemm](https://github.com/mstemm)
|
||||
* update: embed .lua files used to load/compile rules into the main falco executable, for simplicity and to avoid tampering. [[#1843](https://github.com/falcosecurity/falco/pull/1843)] - [@mstemm](https://github.com/mstemm)
|
||||
* update: support non-enumerable event sources in gRPC outputs service [[#1840](https://github.com/falcosecurity/falco/pull/1840)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* docs: add jasondellaluce to OWNERS [[#1818](https://github.com/falcosecurity/falco/pull/1818)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* chore: --list option can be used to selectively list fields related to new sources that are introduced by plugins [[#1839](https://github.com/falcosecurity/falco/pull/1839)] - [@loresuso](https://github.com/loresuso)
|
||||
* update(userspace/falco): support arbitrary-depth nested values in YAML configuration [[#1792](https://github.com/falcosecurity/falco/pull/1792)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* build: bump FakeIt version to 2.0.9 [[#1797](https://github.com/falcosecurity/falco/pull/1797)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* update: allow append of new exceptions to rules [[#1780](https://github.com/falcosecurity/falco/pull/1780)] - [@sai-arigeli](https://github.com/sai-arigeli)
|
||||
* update: Linux packages are now signed with SHA256 [[#1758](https://github.com/falcosecurity/falco/pull/1758)] - [@twa16](https://github.com/twa16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix(scripts/falco-driver-loader): fix for SELinux insmod denials [[#1756](https://github.com/falcosecurity/falco/pull/1756)] - [@dwindsor](https://github.com/dwindsor)
|
||||
* fix(scripts/falco-driver-loader): correctly clean loaded drivers when using `--clean` [[#1795](https://github.com/falcosecurity/falco/pull/1795)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* fix(userspace/falco): in case output_file cannot be opened, throw a falco exception [[#1773](https://github.com/falcosecurity/falco/pull/1773)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* fix(userspace/engine): support jsonpointer escaping in rule parser [[#1777](https://github.com/falcosecurity/falco/pull/1777)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* fix(scripts/falco-driver-loader): support kernel object files in `.zst` and `.gz` compression formats [[#1863](https://github.com/falcosecurity/falco/pull/1863)] - [@leogr](https://github.com/leogr)
|
||||
* fix(engine): correctly format json output in json_event [[#1847](https://github.com/falcosecurity/falco/pull/1847)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* fix: set http output content type to text/plain when json output is disabled [[#1829](https://github.com/falcosecurity/falco/pull/1829)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* fix(userspace/falco): accept 'Content-Type' header that contains "application/json", but it is not strictly equal to it [[#1800](https://github.com/falcosecurity/falco/pull/1800)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* fix(userspace/engine): supporting enabled-only overwritten rules [[#1775](https://github.com/falcosecurity/falco/pull/1775)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
|
||||
|
||||
### Rule Changes
|
||||
|
||||
* rule(Create Symlink Over Sensitive File): corrected typo in rule output [[#1820](https://github.com/falcosecurity/falco/pull/1820)] - [@deepskyblue86](https://github.com/deepskyblue86)
|
||||
* rule(macro open_write): add support to openat2 [[#1796](https://github.com/falcosecurity/falco/pull/1796)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* rule(macro open_read): add support to openat2 [[#1796](https://github.com/falcosecurity/falco/pull/1796)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* rule(macro open_directory): add support to openat2 [[#1796](https://github.com/falcosecurity/falco/pull/1796)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* rule(Create files below dev): add support to openat2 [[#1796](https://github.com/falcosecurity/falco/pull/1796)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* rule(Container Drift Detected (open+create)): add support to openat2 [[#1796](https://github.com/falcosecurity/falco/pull/1796)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* rule(macro sensitive_mount): add containerd socket [[#1815](https://github.com/falcosecurity/falco/pull/1815)] - [@loresuso](https://github.com/loresuso)
|
||||
* rule(macro spawned_process): monitor also processes spawned by `execveat` [[#1868](https://github.com/falcosecurity/falco/pull/1868)] - [@Andreagit97](https://github.com/Andreagit97)
|
||||
* rule(Create Hardlink Over Sensitive Files): new rule to detect hard links created over sensitive files [[#1810](https://github.com/falcosecurity/falco/pull/1810)] - [@sberkovich](https://github.com/sberkovich)
|
||||
* rule(Detect crypto miners using the Stratum protocol): add `stratum2+tcp` and `stratum+ssl` protocols detection [[#1810](https://github.com/falcosecurity/falco/pull/1810)] - [@sberkovich](https://github.com/sberkovich)
|
||||
* rule(Sudo Potential Privilege Escalation): correct special case for the CVE-2021-3156 exploit [[#1810](https://github.com/falcosecurity/falco/pull/1810)] - [@sberkovich](https://github.com/sberkovich)
|
||||
* rule(list falco_hostnetwork_images): moved to k8s_audit_rules.yaml to avoid a warning when usng falco_rules.yaml only [[#1681](https://github.com/falcosecurity/falco/pull/1681)] - [@leodido](https://github.com/leodido)
|
||||
* rule(list deb_binaries): remove `apt-config` [[#1860](https://github.com/falcosecurity/falco/pull/1860)] - [@Andreagit97](https://github.com/Andreagit97)
|
||||
* rule(Launch Remote File Copy Tools in Container): add additional binaries: curl and wget. [[#1771](https://github.com/falcosecurity/falco/pull/1771)] - [@ec4n6](https://github.com/ec4n6)
|
||||
* rule(list known_sa_list): add coredns, coredns-autoscaler, endpointslicemirroring-controller, horizontal-pod-autoscaler, job-controller, node-controller (nodelifecycle), persistent-volume-binder, pv-protection-controller, pvc-protection-controller, root-ca-cert-publisher and service-account-controller as allowed service accounts in the kube-system namespace [[#1760](https://github.com/falcosecurity/falco/pull/1760)] - [@sboschman](https://github.com/sboschman)
|
||||
|
||||
|
||||
### Non user-facing changes
|
||||
|
||||
* fix: force-set evt.type for plugin source events [[#1878](https://github.com/falcosecurity/falco/pull/1878)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* fix: updated some warning strings; properly refresh lua files embedded in falco [[#1864](https://github.com/falcosecurity/falco/pull/1864)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* style(userspace/engine): avoid creating multiple versions of methods only to assume default ruleset. Use a default argument instead. [[#1754](https://github.com/falcosecurity/falco/pull/1754)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* add raft in the adopters list [[#1776](https://github.com/falcosecurity/falco/pull/1776)] - [@teshsharma](https://github.com/teshsharma)
|
||||
* build: always populate partial version variables [[#1778](https://github.com/falcosecurity/falco/pull/1778)] - [@dnwe](https://github.com/dnwe)
|
||||
* build: updated cloudtrail plugin to latest version [[#1865](https://github.com/falcosecurity/falco/pull/1865)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* replace ".." concatenation with table.concat [[#1834](https://github.com/falcosecurity/falco/pull/1834)] - [@VadimZy](https://github.com/VadimZy)
|
||||
* fix(userspace/engine): actually make m_filter_all_event_types useful by properly using it as fallback when no filter event types is provided [[#1875](https://github.com/falcosecurity/falco/pull/1875)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* fix(build): do not show plugin options in musl optimized builds [[#1871](https://github.com/falcosecurity/falco/pull/1871)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* fix(aws_cloudtrail_rules.yaml): correct required plugin versions [[#1867](https://github.com/falcosecurity/falco/pull/1867)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* docs: fix priority level "info" to "informational" [[#1858](https://github.com/falcosecurity/falco/pull/1858)] - [@Andreagit97](https://github.com/Andreagit97)
|
||||
* Field properties changes [[#1838](https://github.com/falcosecurity/falco/pull/1838)] - [@mstemm](https://github.com/mstemm)
|
||||
* update(build): updated libs to latest master version; updated plugins versions [[#1856](https://github.com/falcosecurity/falco/pull/1856)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* Add Giant Swarm to Adopters list [[#1842](https://github.com/falcosecurity/falco/pull/1842)] - [@stone-z](https://github.com/stone-z)
|
||||
* update(tests): remove `token_bucket` unit tests [[#1798](https://github.com/falcosecurity/falco/pull/1798)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* fix(build): use consistent 7-character build abbrev sha [[#1830](https://github.com/falcosecurity/falco/pull/1830)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* add Phoenix to adopters list [[#1806](https://github.com/falcosecurity/falco/pull/1806)] - [@kaldyka](https://github.com/kaldyka)
|
||||
* remove unused files in test directory [[#1801](https://github.com/falcosecurity/falco/pull/1801)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* drop Falco luajit module, use the one provided by libs [[#1788](https://github.com/falcosecurity/falco/pull/1788)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* chore(build): update libs version to 7906f7e [[#1790](https://github.com/falcosecurity/falco/pull/1790)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* Add SysFlow to list of libs adopters [[#1747](https://github.com/falcosecurity/falco/pull/1747)] - [@araujof](https://github.com/araujof)
|
||||
* build: dropped centos8 circleci build because it is useless [[#1882](https://github.com/falcosecurity/falco/pull/1882)] - [@FedeDP](https://github.com/FedeDP)
|
||||
|
||||
|
||||
## v0.30.0
|
||||
|
||||
Released on 2021-10-01
|
||||
@@ -251,8 +396,8 @@ Released on 2021-01-18
|
||||
* docs(proposals): Exceptions handling proposal [[#1376](https://github.com/falcosecurity/falco/pull/1376)] - [@mstemm](https://github.com/mstemm)
|
||||
* docs: fix a broken link of README [[#1516](https://github.com/falcosecurity/falco/pull/1516)] - [@oke-py](https://github.com/oke-py)
|
||||
* docs: adding the kubernetes privileged use case to use cases [[#1484](https://github.com/falcosecurity/falco/pull/1484)] - [@fntlnz](https://github.com/fntlnz)
|
||||
* rules(Mkdir binary dirs): Adds exe_running_docker_save as an exception as this rules can be triggerred when a container is created. [[#1386](https://github.com/falcosecurity/falco/pull/1386)] - [@jhwbarlow](https://github.com/jhwbarlow)
|
||||
* rules(Create Hidden Files): Adds exe_running_docker_save as an exception as this rules can be triggerred when a container is created. [[#1386](https://github.com/falcosecurity/falco/pull/1386)] - [@jhwbarlow](https://github.com/jhwbarlow)
|
||||
* rules(Mkdir binary dirs): Adds exe_running_docker_save as an exception as this rules can be triggered when a container is created. [[#1386](https://github.com/falcosecurity/falco/pull/1386)] - [@jhwbarlow](https://github.com/jhwbarlow)
|
||||
* rules(Create Hidden Files): Adds exe_running_docker_save as an exception as this rules can be triggered when a container is created. [[#1386](https://github.com/falcosecurity/falco/pull/1386)] - [@jhwbarlow](https://github.com/jhwbarlow)
|
||||
* docs(.circleci): welcome Jonah (Amazon) as a new Falco CI maintainer [[#1518](https://github.com/falcosecurity/falco/pull/1518)] - [@leodido](https://github.com/leodido)
|
||||
* build: falcosecurity/falco:master also available on the AWS ECR Public registry [[#1512](https://github.com/falcosecurity/falco/pull/1512)] - [@leodido](https://github.com/leodido)
|
||||
* build: falcosecurity/falco:latest also available on the AWS ECR Public registry [[#1512](https://github.com/falcosecurity/falco/pull/1512)] - [@leodido](https://github.com/leodido)
|
||||
@@ -701,7 +846,7 @@ Released on 2020-01-23
|
||||
### Bug Fixes
|
||||
|
||||
* fix: providing clang into docker-builder [[#972](https://github.com/falcosecurity/falco/pull/972)]
|
||||
* fix: prevent throwing json type error c++ exceptions outside of the falco engine when procesing k8s audit events. [[#928](https://github.com/falcosecurity/falco/pull/928)]
|
||||
* fix: prevent throwing json type error c++ exceptions outside of the falco engine when processing k8s audit events. [[#928](https://github.com/falcosecurity/falco/pull/928)]
|
||||
* fix(docker/kernel/linuxkit): correct from for falco minimal image [[#913](https://github.com/falcosecurity/falco/pull/913)]
|
||||
|
||||
### Rule Changes
|
||||
@@ -816,7 +961,7 @@ Released 2019-07-31
|
||||
|
||||
* Fix a problem that would cause prevent container metadata lookups when falco was daemonized [[#731](https://github.com/falcosecurity/falco/pull/731)]
|
||||
|
||||
* Allow rule priorites to be expressed as lowercase and a mix of lower/uppercase [[#737](https://github.com/falcosecurity/falco/pull/737)]
|
||||
* Allow rule priorities to be expressed as lowercase and a mix of lower/uppercase [[#737](https://github.com/falcosecurity/falco/pull/737)]
|
||||
|
||||
### Rule Changes
|
||||
|
||||
@@ -1011,7 +1156,7 @@ Released 2019-05-13
|
||||
|
||||
* Docker-based builder/tester: You can now build Falco using the [falco-builder](https://falco.org/docs/source/#build-using-falco-builder-container) docker image, and run regression tests using the [falco-tester](https://falco.org/docs/source/#test-using-falco-tester-container) docker image. [[#522](https://github.com/falcosecurity/falco/pull/522)] [[#584](https://github.com/falcosecurity/falco/pull/584)]
|
||||
|
||||
* Several small docs changes to improve clarity and readibility [[#524](https://github.com/falcosecurity/falco/pull/524)] [[#540](https://github.com/falcosecurity/falco/pull/540)] [[#541](https://github.com/falcosecurity/falco/pull/541)] [[#542](https://github.com/falcosecurity/falco/pull/542)]
|
||||
* Several small docs changes to improve clarity and readability [[#524](https://github.com/falcosecurity/falco/pull/524)] [[#540](https://github.com/falcosecurity/falco/pull/540)] [[#541](https://github.com/falcosecurity/falco/pull/541)] [[#542](https://github.com/falcosecurity/falco/pull/542)]
|
||||
|
||||
* Add instructions on how to enable K8s Audit Logging for kops [[#535](https://github.com/falcosecurity/falco/pull/535)]
|
||||
|
||||
@@ -1126,7 +1271,7 @@ Released 2019-01-16
|
||||
|
||||
* Fix FPs related to `apt-config`/`apt-cache`, `apk` [[#490](https://github.com/falcosecurity/falco/pull/490)]
|
||||
|
||||
* New rules `Launch Package Management Process in Container`, `Netcat Remote Code Execution in Container`, `Lauch Suspicious Network Tool in Container` look for host-level network tools like `netcat`, package management tools like `apt-get`, or network tool binaries being run in a container. [[#490](https://github.com/falcosecurity/falco/pull/490)]
|
||||
* New rules `Launch Package Management Process in Container`, `Netcat Remote Code Execution in Container`, `Launch Suspicious Network Tool in Container` look for host-level network tools like `netcat`, package management tools like `apt-get`, or network tool binaries being run in a container. [[#490](https://github.com/falcosecurity/falco/pull/490)]
|
||||
|
||||
* Fix the `inbound` and `outbound` macros so they work with sendto/recvfrom/sendmsg/recvmsg. [[#470](https://github.com/falcosecurity/falco/pull/470)]
|
||||
|
||||
@@ -1159,7 +1304,7 @@ Released 2018-11-09
|
||||
|
||||
* Better coverage (e.g. reduced FPs) for critical stack, hids systems, ufw, cloud-init, etc. [[#445](https://github.com/falcosecurity/falco/pull/445)]
|
||||
|
||||
* New rules `Launch Package Management Process in Container`, `Netcat Remote Code Execution in Container`, and `Lauch Suspicious Network Tool in Container` look for running various suspicious programs in a container. [[#461](https://github.com/falcosecurity/falco/pull/461)]
|
||||
* New rules `Launch Package Management Process in Container`, `Netcat Remote Code Execution in Container`, and `Launch Suspicious Network Tool in Container` look for running various suspicious programs in a container. [[#461](https://github.com/falcosecurity/falco/pull/461)]
|
||||
|
||||
* Misc changes to address false positives in GKE, Istio, etc. [[#455](https://github.com/falcosecurity/falco/pull/455)] [[#439](https://github.com/falcosecurity/falco/issues/439)]
|
||||
|
||||
@@ -1214,7 +1359,7 @@ Released 2018-07-24
|
||||
|
||||
### Minor Changes
|
||||
|
||||
* Rules may now have an `skip-if-unknown-filter` property. If set to true, a rule will be skipped if its condition/output property refers to a filtercheck (e.g. `fd.some-new-attibute`) that is not present in the current falco version. [[#364](https://github.com/draios/falco/pull/364)] [[#345](https://github.com/draios/falco/issues/345)]
|
||||
* Rules may now have an `skip-if-unknown-filter` property. If set to true, a rule will be skipped if its condition/output property refers to a filtercheck (e.g. `fd.some-new-attribute`) that is not present in the current falco version. [[#364](https://github.com/draios/falco/pull/364)] [[#345](https://github.com/draios/falco/issues/345)]
|
||||
* Small changes to Falco `COPYING` file so github automatically recognizes license [[#380](https://github.com/draios/falco/pull/380)]
|
||||
* New example integration showing how to connect Falco with Anchore to dynamically create falco rules based on negative scan results [[#390](https://github.com/draios/falco/pull/390)]
|
||||
* New example integration showing how to connect Falco, [nats](https://nats.io/), and K8s to run flexible "playbooks" based on Falco events [[#389](https://github.com/draios/falco/pull/389)]
|
||||
@@ -1315,7 +1460,7 @@ Released 2017-10-10
|
||||
|
||||
Released 2017-10-10
|
||||
|
||||
**Important**: the location for falco's configuration file has moved from `/etc/falco.yaml` to `/etc/falco/falco.yaml`. The default rules file has moved from `/etc/falco_rules.yaml` to `/etc/falco/falco_rules.yaml`. In addition, 0.8.0 has added a _local_ ruls file to `/etc/falco/falco_rules.local.yaml`. See [the documentation](https://github.com/draios/falco/wiki/Falco-Default-and-Local-Rules-Files) for more details.
|
||||
**Important**: the location for falco's configuration file has moved from `/etc/falco.yaml` to `/etc/falco/falco.yaml`. The default rules file has moved from `/etc/falco_rules.yaml` to `/etc/falco/falco_rules.yaml`. In addition, 0.8.0 has added a _local_ rules file to `/etc/falco/falco_rules.local.yaml`. See [the documentation](https://github.com/draios/falco/wiki/Falco-Default-and-Local-Rules-Files) for more details.
|
||||
|
||||
### Major Changes
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ if(CMAKE_BUILD_TYPE STREQUAL "debug")
|
||||
else()
|
||||
set(CMAKE_BUILD_TYPE "release")
|
||||
set(KBUILD_FLAGS "${DRAIOS_FEATURE_FLAGS}")
|
||||
add_definitions(-DBUILD_TYPE_RELEASE)
|
||||
endif()
|
||||
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
||||
|
||||
@@ -67,6 +68,7 @@ endif()
|
||||
|
||||
if(MUSL_OPTIMIZED_BUILD)
|
||||
set(MUSL_FLAGS "-static -Os -fPIE -pie")
|
||||
add_definitions(-DMUSL_OPTIMIZED)
|
||||
endif()
|
||||
|
||||
# explicitly set hardening flags
|
||||
@@ -97,8 +99,8 @@ set(CMAKE_CXX_FLAGS_RELEASE "-O3 -fno-strict-aliasing -DNDEBUG")
|
||||
include(GetFalcoVersion)
|
||||
|
||||
set(PACKAGE_NAME "falco")
|
||||
set(PROBE_NAME "falco")
|
||||
set(PROBE_DEVICE_NAME "falco")
|
||||
set(DRIVER_NAME "falco")
|
||||
set(DRIVER_DEVICE_NAME "falco")
|
||||
set(DRIVERS_REPO "https://download.falco.org/driver")
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX
|
||||
@@ -110,12 +112,12 @@ set(CMD_MAKE make)
|
||||
|
||||
include(ExternalProject)
|
||||
|
||||
# LuaJIT
|
||||
include(luajit)
|
||||
|
||||
# libs
|
||||
include(falcosecurity-libs)
|
||||
|
||||
# LuaJit provided by libs
|
||||
include(luajit)
|
||||
|
||||
# jq
|
||||
include(jq)
|
||||
|
||||
@@ -143,8 +145,13 @@ if(NOT MINIMAL_BUILD)
|
||||
|
||||
# libcurl
|
||||
include(curl)
|
||||
|
||||
# civetweb
|
||||
include(civetweb)
|
||||
endif()
|
||||
|
||||
include(cxxopts)
|
||||
|
||||
# Lpeg
|
||||
include(lpeg)
|
||||
|
||||
@@ -157,24 +164,6 @@ include(lyaml)
|
||||
# One TBB
|
||||
include(tbb)
|
||||
|
||||
if(NOT MINIMAL_BUILD)
|
||||
# civetweb
|
||||
set(CIVETWEB_SRC "${PROJECT_BINARY_DIR}/civetweb-prefix/src/civetweb/")
|
||||
set(CIVETWEB_LIB "${CIVETWEB_SRC}/install/lib/libcivetweb.a")
|
||||
set(CIVETWEB_INCLUDE_DIR "${CIVETWEB_SRC}/install/include")
|
||||
message(STATUS "Using bundled civetweb in '${CIVETWEB_SRC}'")
|
||||
ExternalProject_Add(
|
||||
civetweb
|
||||
URL "https://github.com/civetweb/civetweb/archive/v1.11.tar.gz"
|
||||
URL_HASH "SHA256=de7d5e7a2d9551d325898c71e41d437d5f7b51e754b242af897f7be96e713a42"
|
||||
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E make_directory ${CIVETWEB_SRC}/install/lib
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${CIVETWEB_SRC}/install/include
|
||||
BUILD_IN_SOURCE 1
|
||||
BUILD_COMMAND ${CMD_MAKE} COPT="-DNO_FILES" WITH_CPP=1
|
||||
BUILD_BYPRODUCTS ${CIVETWEB_LIB}
|
||||
INSTALL_COMMAND ${CMD_MAKE} COPT="-DNO_FILES" install-lib install-headers PREFIX=${CIVETWEB_SRC}/install "WITH_CPP=1")
|
||||
endif()
|
||||
|
||||
#string-view-lite
|
||||
include(DownloadStringViewLite)
|
||||
|
||||
@@ -212,6 +201,7 @@ include(static-analysis)
|
||||
# Shared build variables
|
||||
set(FALCO_SINSP_LIBRARY sinsp)
|
||||
set(FALCO_SHARE_DIR share/falco)
|
||||
set(FALCO_PLUGINS_DIR ${FALCO_SHARE_DIR}/plugins)
|
||||
set(FALCO_ABSOLUTE_SHARE_DIR "${CMAKE_INSTALL_PREFIX}/${FALCO_SHARE_DIR}")
|
||||
set(FALCO_BIN_DIR bin)
|
||||
|
||||
@@ -220,5 +210,9 @@ add_subdirectory(userspace/engine)
|
||||
add_subdirectory(userspace/falco)
|
||||
add_subdirectory(tests)
|
||||
|
||||
if(NOT MUSL_OPTIMIZED_BUILD)
|
||||
include(plugins)
|
||||
endif()
|
||||
|
||||
# Packages configuration
|
||||
include(CPackConfig)
|
||||
|
||||
2
OWNERS
2
OWNERS
@@ -4,6 +4,7 @@ approvers:
|
||||
- leodido
|
||||
- mstemm
|
||||
- leogr
|
||||
- jasondellaluce
|
||||
reviewers:
|
||||
- fntlnz
|
||||
- kaizhe
|
||||
@@ -12,3 +13,4 @@ reviewers:
|
||||
- mfdii
|
||||
- mstemm
|
||||
- leogr
|
||||
- jasondellaluce
|
||||
|
||||
@@ -95,7 +95,7 @@ Now assume `x.y.z` is the new version.
|
||||
|
||||
#### Release Manager <github handle>
|
||||
|
||||
<!-- Substitute Github handle with the release manager's one -->
|
||||
<!-- Substitute GitHub handle with the release manager's one -->
|
||||
```
|
||||
|
||||
- Finally, publish the release!
|
||||
|
||||
@@ -56,7 +56,7 @@ If a rule has been violated, Falco triggers an alert.
|
||||
### How does Falco work?
|
||||
|
||||
Falco traces kernel events and reports information about the system calls being executed at runtime.
|
||||
Falco leverages the extended berkley packet filter (eBPF) which is a kernel feature implemented for dynamic crash-resilient and secure code execution in the kernel.
|
||||
Falco leverages the extended berkeley packet filter (eBPF) which is a kernel feature implemented for dynamic crash-resilient and secure code execution in the kernel.
|
||||
Falco enriches these kernel events with information about containers running on the system.
|
||||
Falco also can consume signals from other input streams such as the containerd socket, the Kubernetes API server and the Kubernetes audit log.
|
||||
At runtime, Falco will reason about these events and assert them against configured security rules.
|
||||
@@ -113,7 +113,7 @@ Falco ultimately is a security engine. It reasons about signals coming from a sy
|
||||
|
||||
##### Anomaly detection
|
||||
|
||||
This refers to an event that occurs with something unsual, concerning, or odd occurs.
|
||||
This refers to an event that occurs with something unusual, concerning, or odd occurs.
|
||||
We can associate anomalies with unwanted behavior, and alert in their presence.
|
||||
|
||||
##### Detection tooling
|
||||
|
||||
@@ -10,5 +10,4 @@ endif()
|
||||
|
||||
if(CPACK_GENERATOR MATCHES "TGZ")
|
||||
set(CPACK_SET_DESTDIR "ON")
|
||||
set(CPACK_STRIP_FILES "OFF")
|
||||
endif()
|
||||
|
||||
@@ -45,7 +45,7 @@ string(REPLACE "\n" ";" output "${output}")
|
||||
# Parse output
|
||||
foreach(line ${output})
|
||||
set(test ${line})
|
||||
# use escape commas to handle properly test cases with commans inside the name
|
||||
# use escape commas to handle properly test cases with commands inside the name
|
||||
string(REPLACE "," "\\," test_name ${test})
|
||||
# ...and add to script
|
||||
add_command(add_test "${prefix}${test}${suffix}" ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" "${test_name}" ${extra_args})
|
||||
|
||||
@@ -14,8 +14,8 @@ include(ExternalProject)
|
||||
|
||||
set(FAKEIT_INCLUDE ${CMAKE_BINARY_DIR}/fakeit-prefix/include)
|
||||
|
||||
set(FAKEIT_EXTERNAL_URL URL https://github.com/eranpeer/fakeit/archive/2.0.5.tar.gz URL_HASH
|
||||
SHA256=298539c773baca6ecbc28914306bba19d1008e098f8adc3ad3bb00e993ecdf15)
|
||||
set(FAKEIT_EXTERNAL_URL URL https://github.com/eranpeer/fakeit/archive/2.0.9.tar.gz URL_HASH
|
||||
SHA256=dc4ee7b17a84c959019b92c20fce6dc9426e9e170b6edf84db6cb2e188520cd7)
|
||||
|
||||
ExternalProject_Add(
|
||||
fakeit-external
|
||||
|
||||
@@ -24,6 +24,7 @@ ExternalProject_Add(
|
||||
GIT_TAG "v1.4.0"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
UPDATE_COMMAND ""
|
||||
INSTALL_COMMAND
|
||||
${CMAKE_COMMAND} -E copy ${STRING_VIEW_LITE_PREFIX}/src/string-view-lite/include/nonstd/string_view.hpp
|
||||
${STRING_VIEW_LITE_INCLUDE}/nonstd/string_view.hpp)
|
||||
|
||||
@@ -21,7 +21,7 @@ if(NOT FALCO_VERSION)
|
||||
git_get_exact_tag(FALCO_TAG)
|
||||
if(NOT FALCO_TAG)
|
||||
# Obtain the closest tag
|
||||
git_describe(FALCO_VERSION "--always" "--tags")
|
||||
git_describe(FALCO_VERSION "--always" "--tags" "--abbrev=7")
|
||||
# Fallback version
|
||||
if(FALCO_VERSION MATCHES "NOTFOUND$")
|
||||
set(FALCO_VERSION "0.0.0")
|
||||
@@ -31,29 +31,33 @@ if(NOT FALCO_VERSION)
|
||||
else()
|
||||
# A tag has been found: use it as the Falco version
|
||||
set(FALCO_VERSION "${FALCO_TAG}")
|
||||
# Remove the starting "v" in case there is one
|
||||
string(REGEX REPLACE "^v(.*)" "\\1" FALCO_VERSION "${FALCO_TAG}")
|
||||
endif()
|
||||
# TODO(leodido) > ensure Falco version is semver before extracting parts Populate partial version variables
|
||||
string(REGEX MATCH "^(0|[1-9][0-9]*)" FALCO_VERSION_MAJOR "${FALCO_VERSION}")
|
||||
string(REGEX REPLACE "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\..*" "\\2" FALCO_VERSION_MINOR "${FALCO_VERSION}")
|
||||
string(REGEX REPLACE "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*).*" "\\3" FALCO_VERSION_PATCH
|
||||
"${FALCO_VERSION}")
|
||||
string(
|
||||
REGEX
|
||||
REPLACE
|
||||
"^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)-((0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*).*"
|
||||
"\\5"
|
||||
FALCO_VERSION_PRERELEASE
|
||||
"${FALCO_VERSION}")
|
||||
if(FALCO_VERSION_PRERELEASE STREQUAL "${FALCO_VERSION}")
|
||||
set(FALCO_VERSION_PRERELEASE "")
|
||||
endif()
|
||||
if(NOT FALCO_VERSION_BUILD)
|
||||
string(REGEX REPLACE ".*\\+([0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*)" "\\1" FALCO_VERSION_BUILD "${FALCO_VERSION}")
|
||||
endif()
|
||||
if(FALCO_VERSION_BUILD STREQUAL "${FALCO_VERSION}")
|
||||
set(FALCO_VERSION_BUILD "")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Remove the starting "v" in case there is one
|
||||
string(REGEX REPLACE "^v(.*)" "\\1" FALCO_VERSION "${FALCO_VERSION}")
|
||||
|
||||
# TODO(leodido) > ensure Falco version is semver before extracting parts Populate partial version variables
|
||||
string(REGEX MATCH "^(0|[1-9][0-9]*)" FALCO_VERSION_MAJOR "${FALCO_VERSION}")
|
||||
string(REGEX REPLACE "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\..*" "\\2" FALCO_VERSION_MINOR "${FALCO_VERSION}")
|
||||
string(REGEX REPLACE "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*).*" "\\3" FALCO_VERSION_PATCH
|
||||
"${FALCO_VERSION}")
|
||||
string(
|
||||
REGEX
|
||||
REPLACE
|
||||
"^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)-((0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*).*"
|
||||
"\\5"
|
||||
FALCO_VERSION_PRERELEASE
|
||||
"${FALCO_VERSION}")
|
||||
|
||||
if(FALCO_VERSION_PRERELEASE STREQUAL "${FALCO_VERSION}")
|
||||
set(FALCO_VERSION_PRERELEASE "")
|
||||
endif()
|
||||
if(NOT FALCO_VERSION_BUILD)
|
||||
string(REGEX REPLACE ".*\\+([0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*)" "\\1" FALCO_VERSION_BUILD "${FALCO_VERSION}")
|
||||
endif()
|
||||
if(FALCO_VERSION_BUILD STREQUAL "${FALCO_VERSION}")
|
||||
set(FALCO_VERSION_BUILD "")
|
||||
endif()
|
||||
|
||||
message(STATUS "Falco version: ${FALCO_VERSION}")
|
||||
|
||||
53
cmake/modules/civetweb.cmake
Normal file
53
cmake/modules/civetweb.cmake
Normal file
@@ -0,0 +1,53 @@
|
||||
#
|
||||
# Copyright (C) 2021 The Falco Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
# 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.
|
||||
#
|
||||
|
||||
set(CIVETWEB_SRC "${PROJECT_BINARY_DIR}/civetweb-prefix/src/civetweb/")
|
||||
set(CIVETWEB_LIB "${CIVETWEB_SRC}/install/lib/libcivetweb.a")
|
||||
SET(CIVETWEB_CPP_LIB "${CIVETWEB_SRC}/install/lib/libcivetweb-cpp.a")
|
||||
set(CIVETWEB_INCLUDE_DIR "${CIVETWEB_SRC}/install/include")
|
||||
message(STATUS "Using bundled civetweb in '${CIVETWEB_SRC}'")
|
||||
if (USE_BUNDLED_OPENSSL)
|
||||
ExternalProject_Add(
|
||||
civetweb
|
||||
DEPENDS openssl
|
||||
URL "https://github.com/civetweb/civetweb/archive/v1.15.tar.gz"
|
||||
URL_HASH "SHA256=90a533422944ab327a4fbb9969f0845d0dba05354f9cacce3a5005fa59f593b9"
|
||||
INSTALL_DIR ${CIVETWEB_SRC}/install
|
||||
CMAKE_ARGS
|
||||
-DBUILD_TESTING=off
|
||||
-DCMAKE_INSTALL_LIBDIR=lib
|
||||
-DCIVETWEB_BUILD_TESTING=off
|
||||
-DCIVETWEB_ENABLE_CXX=on
|
||||
-DCIVETWEB_ENABLE_SERVER_EXECUTABLE=off
|
||||
-DCIVETWEB_ENABLE_SSL_DYNAMIC_LOADING=off
|
||||
-DCIVETWEB_SERVE_NO_FILES=on
|
||||
-DCMAKE_INSTALL_PREFIX=${CIVETWEB_SRC}/install
|
||||
-DOPENSSL_ROOT_DIR:PATH=${OPENSSL_INSTALL_DIR}
|
||||
-DOPENSSL_USE_STATIC_LIBS:BOOL=TRUE
|
||||
BUILD_BYPRODUCTS ${CIVETWEB_LIB} ${CIVETWEB_CPP_LIB})
|
||||
else()
|
||||
ExternalProject_Add(
|
||||
civetweb
|
||||
URL "https://github.com/civetweb/civetweb/archive/v1.15.tar.gz"
|
||||
URL_HASH "SHA256=90a533422944ab327a4fbb9969f0845d0dba05354f9cacce3a5005fa59f593b9"
|
||||
INSTALL_DIR ${CIVETWEB_SRC}/install
|
||||
CMAKE_ARGS
|
||||
-DBUILD_TESTING=off
|
||||
-DCIVETWEB_BUILD_TESTING=off
|
||||
-DCIVETWEB_ENABLE_CXX=on
|
||||
-DCIVETWEB_ENABLE_SERVER_EXECUTABLE=off
|
||||
-DCIVETWEB_ENABLE_SSL_DYNAMIC_LOADING=off
|
||||
-DCIVETWEB_SERVE_NO_FILES=on
|
||||
-DCMAKE_INSTALL_PREFIX=${CIVETWEB_SRC}/install
|
||||
BUILD_BYPRODUCTS ${CIVETWEB_LIB} ${CIVETWEB_CPP_LIB})
|
||||
endif()
|
||||
30
cmake/modules/copy_files_to_build_dir.cmake
Normal file
30
cmake/modules/copy_files_to_build_dir.cmake
Normal file
@@ -0,0 +1,30 @@
|
||||
#
|
||||
# Copyright (C) 2022 The Falco Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
# 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.
|
||||
#
|
||||
|
||||
function(copy_files_to_build_dir source_files targetsuffix)
|
||||
|
||||
set(build_files)
|
||||
|
||||
foreach(file_path ${source_files})
|
||||
get_filename_component(trace_file ${file_path} NAME)
|
||||
list(APPEND build_files ${CMAKE_CURRENT_BINARY_DIR}/${trace_file})
|
||||
endforeach()
|
||||
|
||||
add_custom_target(copy-files-${targetsuffix} ALL
|
||||
DEPENDS ${build_files})
|
||||
|
||||
add_custom_command(OUTPUT ${build_files}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${source_files} ${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS ${source_files})
|
||||
|
||||
endfunction()
|
||||
23
cmake/modules/cxxopts.cmake
Normal file
23
cmake/modules/cxxopts.cmake
Normal file
@@ -0,0 +1,23 @@
|
||||
#
|
||||
# Copyright (C) 2022 The Falco Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
# 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.
|
||||
#
|
||||
|
||||
set(CXXOPTS_SRC "${PROJECT_BINARY_DIR}/cxxopts-prefix/src/cxxopts/")
|
||||
set(CXXOPTS_INCLUDE_DIR "${CXXOPTS_SRC}/include")
|
||||
|
||||
ExternalProject_Add(
|
||||
cxxopts
|
||||
URL "https://github.com/jarro2783/cxxopts/archive/refs/tags/v3.0.0.tar.gz"
|
||||
URL_HASH "SHA256=36f41fa2a46b3c1466613b63f3fa73dc24d912bc90d667147f1e43215a8c6d00"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
@@ -24,5 +24,4 @@ ExternalProject_Add(
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
PATCH_COMMAND patch -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/patch/libscap.patch && patch -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/patch/luajit.patch)
|
||||
TEST_COMMAND "")
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
diff --git a/userspace/libscap/scap.c b/userspace/libscap/scap.c
|
||||
index 6f51588e..5f9ea84e 100644
|
||||
--- a/userspace/libscap/scap.c
|
||||
+++ b/userspace/libscap/scap.c
|
||||
@@ -55,7 +55,7 @@ limitations under the License.
|
||||
//#define NDEBUG
|
||||
#include <assert.h>
|
||||
|
||||
-static const char *SYSDIG_BPF_PROBE_ENV = "SYSDIG_BPF_PROBE";
|
||||
+static const char *SYSDIG_BPF_PROBE_ENV = "FALCO_BPF_PROBE";
|
||||
|
||||
//
|
||||
// Probe version string size
|
||||
@@ -114,7 +114,7 @@ scap_t* scap_open_udig_int(char *error, int32_t *rc,
|
||||
static uint32_t get_max_consumers()
|
||||
{
|
||||
uint32_t max;
|
||||
- FILE *pfile = fopen("/sys/module/" PROBE_DEVICE_NAME "_probe/parameters/max_consumers", "r");
|
||||
+ FILE *pfile = fopen("/sys/module/" PROBE_DEVICE_NAME "/parameters/max_consumers", "r");
|
||||
if(pfile != NULL)
|
||||
{
|
||||
int w = fscanf(pfile, "%"PRIu32, &max);
|
||||
@@ -186,7 +186,7 @@ scap_t* scap_open_live_int(char *error, int32_t *rc,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- snprintf(buf, sizeof(buf), "%s/.sysdig/%s-bpf.o", home, PROBE_NAME);
|
||||
+ snprintf(buf, sizeof(buf), "%s/.falco/%s-bpf.o", home, PROBE_NAME);
|
||||
bpf_probe = buf;
|
||||
}
|
||||
}
|
||||
@@ -344,7 +344,7 @@ scap_t* scap_open_live_int(char *error, int32_t *rc,
|
||||
else if(errno == EBUSY)
|
||||
{
|
||||
uint32_t curr_max_consumers = get_max_consumers();
|
||||
- snprintf(error, SCAP_LASTERR_SIZE, "Too many sysdig instances attached to device %s. Current value for /sys/module/" PROBE_DEVICE_NAME "_probe/parameters/max_consumers is '%"PRIu32"'.", filename, curr_max_consumers);
|
||||
+ snprintf(error, SCAP_LASTERR_SIZE, "Too many Falco instances attached to device %s. Current value for /sys/module/" PROBE_DEVICE_NAME "/parameters/max_consumers is '%"PRIu32"'.", filename, curr_max_consumers);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2175,7 +2175,7 @@ int32_t scap_disable_dynamic_snaplen(scap_t* handle)
|
||||
|
||||
const char* scap_get_host_root()
|
||||
{
|
||||
- char* p = getenv("SYSDIG_HOST_ROOT");
|
||||
+ char* p = getenv("HOST_ROOT");
|
||||
static char env_str[SCAP_MAX_PATH_SIZE + 1];
|
||||
static bool inited = false;
|
||||
if (! inited) {
|
||||
@@ -1,57 +0,0 @@
|
||||
diff --git a/userspace/chisel/chisel.cpp b/userspace/chisel/chisel.cpp
|
||||
index 0a6e3cf8..0c2e255a 100644
|
||||
--- a/userspace/chisel/chisel.cpp
|
||||
+++ b/userspace/chisel/chisel.cpp
|
||||
@@ -98,7 +98,7 @@ void lua_stackdump(lua_State *L)
|
||||
// Lua callbacks
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef HAS_LUA_CHISELS
|
||||
-const static struct luaL_reg ll_sysdig [] =
|
||||
+const static struct luaL_Reg ll_sysdig [] =
|
||||
{
|
||||
{"set_filter", &lua_cbacks::set_global_filter},
|
||||
{"set_snaplen", &lua_cbacks::set_snaplen},
|
||||
@@ -134,7 +134,7 @@ const static struct luaL_reg ll_sysdig [] =
|
||||
{NULL,NULL}
|
||||
};
|
||||
|
||||
-const static struct luaL_reg ll_chisel [] =
|
||||
+const static struct luaL_Reg ll_chisel [] =
|
||||
{
|
||||
{"request_field", &lua_cbacks::request_field},
|
||||
{"set_filter", &lua_cbacks::set_filter},
|
||||
@@ -146,7 +146,7 @@ const static struct luaL_reg ll_chisel [] =
|
||||
{NULL,NULL}
|
||||
};
|
||||
|
||||
-const static struct luaL_reg ll_evt [] =
|
||||
+const static struct luaL_Reg ll_evt [] =
|
||||
{
|
||||
{"field", &lua_cbacks::field},
|
||||
{"get_num", &lua_cbacks::get_num},
|
||||
diff --git a/userspace/chisel/lua_parser.cpp b/userspace/chisel/lua_parser.cpp
|
||||
index 0e26617d..78810d96 100644
|
||||
--- a/userspace/chisel/lua_parser.cpp
|
||||
+++ b/userspace/chisel/lua_parser.cpp
|
||||
@@ -32,7 +32,7 @@ extern "C" {
|
||||
#include "lauxlib.h"
|
||||
}
|
||||
|
||||
-const static struct luaL_reg ll_filter [] =
|
||||
+const static struct luaL_Reg ll_filter [] =
|
||||
{
|
||||
{"rel_expr", &lua_parser_cbacks::rel_expr},
|
||||
{"bool_op", &lua_parser_cbacks::bool_op},
|
||||
diff --git a/userspace/chisel/lua_parser_api.cpp b/userspace/chisel/lua_parser_api.cpp
|
||||
index c89e9126..c3d8008a 100644
|
||||
--- a/userspace/chisel/lua_parser_api.cpp
|
||||
+++ b/userspace/chisel/lua_parser_api.cpp
|
||||
@@ -266,7 +266,7 @@ int lua_parser_cbacks::rel_expr(lua_State *ls)
|
||||
string err = "Got non-table as in-expression operand\n";
|
||||
throw sinsp_exception("parser API error");
|
||||
}
|
||||
- int n = luaL_getn(ls, 4); /* get size of table */
|
||||
+ int n = lua_objlen (ls, 4); /* get size of table */
|
||||
for (i=1; i<=n; i++)
|
||||
{
|
||||
lua_rawgeti(ls, 4, i);
|
||||
@@ -16,33 +16,42 @@ set(FALCOSECURITY_LIBS_CMAKE_WORKING_DIR "${CMAKE_BINARY_DIR}/falcosecurity-libs
|
||||
|
||||
file(MAKE_DIRECTORY ${FALCOSECURITY_LIBS_CMAKE_WORKING_DIR})
|
||||
|
||||
# The falcosecurity/libs git reference (branch name, commit hash, or tag) To update falcosecurity/libs version for the next release, change the
|
||||
# default below In case you want to test against another falcosecurity/libs version just pass the variable - ie., `cmake
|
||||
# -DFALCOSECURITY_LIBS_VERSION=dev ..`
|
||||
if(NOT FALCOSECURITY_LIBS_VERSION)
|
||||
set(FALCOSECURITY_LIBS_VERSION "3aa7a83bf7b9e6229a3824e3fd1f4452d1e95cb4")
|
||||
set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=1edb535b3778fcfb46bbeeda891f176a1bd591bebd7b89c27f04837e55a52beb")
|
||||
if(FALCOSECURITY_LIBS_SOURCE_DIR)
|
||||
set(FALCOSECURITY_LIBS_VERSION "local")
|
||||
message(STATUS "Using local falcosecurity/libs in '${FALCOSECURITY_LIBS_SOURCE_DIR}'")
|
||||
else()
|
||||
# The falcosecurity/libs git reference (branch name, commit hash, or tag) To update falcosecurity/libs version for the next release, change the
|
||||
# default below In case you want to test against another falcosecurity/libs version just pass the variable - ie., `cmake
|
||||
# -DFALCOSECURITY_LIBS_VERSION=dev ..`
|
||||
if(NOT FALCOSECURITY_LIBS_VERSION)
|
||||
set(FALCOSECURITY_LIBS_VERSION "b7eb0dd65226a8dc254d228c8d950d07bf3521d2")
|
||||
set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=0f6dcdc3b94243c91294698ee343806539af81c5b33c60c6acf83fc1aa455e85")
|
||||
endif()
|
||||
|
||||
# cd /path/to/build && cmake /path/to/source
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" -DFALCOSECURITY_LIBS_VERSION=${FALCOSECURITY_LIBS_VERSION} -DFALCOSECURITY_LIBS_CHECKSUM=${FALCOSECURITY_LIBS_CHECKSUM}
|
||||
${FALCOSECURITY_LIBS_CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${FALCOSECURITY_LIBS_CMAKE_WORKING_DIR})
|
||||
|
||||
# todo(leodido, fntlnz) > use the following one when CMake version will be >= 3.13
|
||||
|
||||
# execute_process(COMMAND "${CMAKE_COMMAND}" -B ${FALCOSECURITY_LIBS_CMAKE_WORKING_DIR} WORKING_DIRECTORY
|
||||
# "${FALCOSECURITY_LIBS_CMAKE_SOURCE_DIR}")
|
||||
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${FALCOSECURITY_LIBS_CMAKE_WORKING_DIR}")
|
||||
set(FALCOSECURITY_LIBS_SOURCE_DIR "${FALCOSECURITY_LIBS_CMAKE_WORKING_DIR}/falcosecurity-libs-prefix/src/falcosecurity-libs")
|
||||
endif()
|
||||
|
||||
# cd /path/to/build && cmake /path/to/source
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" -DFALCOSECURITY_LIBS_VERSION=${FALCOSECURITY_LIBS_VERSION} -DFALCOSECURITY_LIBS_CHECKSUM=${FALCOSECURITY_LIBS_CHECKSUM}
|
||||
${FALCOSECURITY_LIBS_CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${FALCOSECURITY_LIBS_CMAKE_WORKING_DIR})
|
||||
|
||||
# todo(leodido, fntlnz) > use the following one when CMake version will be >= 3.13
|
||||
|
||||
# execute_process(COMMAND "${CMAKE_COMMAND}" -B ${FALCOSECURITY_LIBS_CMAKE_WORKING_DIR} WORKING_DIRECTORY
|
||||
# "${FALCOSECURITY_LIBS_CMAKE_SOURCE_DIR}")
|
||||
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${FALCOSECURITY_LIBS_CMAKE_WORKING_DIR}")
|
||||
set(FALCOSECURITY_LIBS_SOURCE_DIR "${FALCOSECURITY_LIBS_CMAKE_WORKING_DIR}/falcosecurity-libs-prefix/src/falcosecurity-libs")
|
||||
|
||||
add_definitions(-D_GNU_SOURCE)
|
||||
add_definitions(-DHAS_CAPTURE)
|
||||
if(MUSL_OPTIMIZED_BUILD)
|
||||
add_definitions(-DMUSL_OPTIMIZED)
|
||||
endif()
|
||||
|
||||
set(PROBE_VERSION "${FALCOSECURITY_LIBS_VERSION}")
|
||||
set(DRIVER_VERSION "${FALCOSECURITY_LIBS_VERSION}")
|
||||
set(DRIVER_NAME "falco")
|
||||
set(DRIVER_PACKAGE_NAME "falco")
|
||||
set(SCAP_BPF_PROBE_ENV_VAR_NAME "FALCO_BPF_PROBE")
|
||||
set(SCAP_HOST_ROOT_ENV_VAR_NAME "HOST_ROOT")
|
||||
|
||||
if(NOT LIBSCAP_DIR)
|
||||
set(LIBSCAP_DIR "${FALCOSECURITY_LIBS_SOURCE_DIR}")
|
||||
@@ -60,8 +69,19 @@ set(WITH_CHISEL ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_TBB ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_B64 ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_JSONCPP ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_LUAJIT ON CACHE BOOL "")
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${FALCOSECURITY_LIBS_SOURCE_DIR}/cmake/modules")
|
||||
|
||||
include(CheckSymbolExists)
|
||||
check_symbol_exists(strlcpy "string.h" HAVE_STRLCPY)
|
||||
if(HAVE_STRLCPY)
|
||||
message(STATUS "Existing strlcpy found, will *not* use local definition by setting -DHAVE_STRLCPY.")
|
||||
add_definitions(-DHAVE_STRLCPY)
|
||||
else()
|
||||
message(STATUS "No strlcpy found, will use local definition")
|
||||
endif()
|
||||
|
||||
include(libscap)
|
||||
include(libsinsp)
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2020 The Falco Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
# 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.
|
||||
#
|
||||
|
||||
if(NOT LUAJIT_INCLUDE)
|
||||
set(LUAJIT_SRC "${PROJECT_BINARY_DIR}/luajit-prefix/src/luajit/src")
|
||||
message(STATUS "Using bundled LuaJIT in '${LUAJIT_SRC}'")
|
||||
set(LUAJIT_INCLUDE "${LUAJIT_SRC}")
|
||||
set(LUAJIT_LIB "${LUAJIT_SRC}/libluajit.a")
|
||||
externalproject_add(
|
||||
luajit
|
||||
GIT_REPOSITORY "https://github.com/LuaJIT/LuaJIT"
|
||||
GIT_TAG "1d8b747c161db457e032a023ebbff511f5de5ec2"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ${CMD_MAKE}
|
||||
BUILD_IN_SOURCE 1
|
||||
BUILD_BYPRODUCTS ${LUAJIT_LIB}
|
||||
INSTALL_COMMAND ""
|
||||
)
|
||||
endif()
|
||||
include_directories("${LUAJIT_INCLUDE}")
|
||||
@@ -11,9 +11,10 @@
|
||||
# specific language governing permissions and limitations under the License.
|
||||
#
|
||||
|
||||
set(LYAML_SRC "${PROJECT_BINARY_DIR}/lyaml-prefix/src/lyaml/ext/yaml")
|
||||
set(LYAML_LIB "${LYAML_SRC}/.libs/yaml.a")
|
||||
message(STATUS "Using bundled lyaml in '${LYAML_SRC}'")
|
||||
set(LYAML_ROOT "${PROJECT_BINARY_DIR}/lyaml-prefix/src/lyaml")
|
||||
set(LYAML_LIB "${LYAML_ROOT}/ext/yaml/.libs/yaml.a")
|
||||
set(LYAML_LUA_DIR "${LYAML_ROOT}/lib")
|
||||
message(STATUS "Using bundled lyaml in '${LYAML_ROOT}'")
|
||||
externalproject_add(
|
||||
lyaml
|
||||
DEPENDS luajit libyaml
|
||||
@@ -22,7 +23,6 @@ externalproject_add(
|
||||
BUILD_COMMAND ${CMD_MAKE}
|
||||
BUILD_IN_SOURCE 1
|
||||
BUILD_BYPRODUCTS ${LYAML_LIB}
|
||||
INSTALL_COMMAND ""
|
||||
CONFIGURE_COMMAND ./configure --enable-static CFLAGS=-I${LIBYAML_INSTALL_DIR}/include CPPFLAGS=-I${LIBYAML_INSTALL_DIR}/include LDFLAGS=-L${LIBYAML_INSTALL_DIR}/lib LIBS=-lyaml LUA=${LUAJIT_SRC}/luajit LUA_INCLUDE=-I${LUAJIT_INCLUDE}
|
||||
INSTALL_COMMAND sh -c
|
||||
"cp -R ${PROJECT_BINARY_DIR}/lyaml-prefix/src/lyaml/lib/* ${PROJECT_SOURCE_DIR}/userspace/engine/lua"
|
||||
)
|
||||
|
||||
36
cmake/modules/plugins.cmake
Normal file
36
cmake/modules/plugins.cmake
Normal file
@@ -0,0 +1,36 @@
|
||||
#
|
||||
# Copyright (C) 2021 The Falco Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
# 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(ExternalProject)
|
||||
|
||||
string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} PLUGINS_SYSTEM_NAME)
|
||||
|
||||
ExternalProject_Add(
|
||||
cloudtrail-plugin
|
||||
URL "https://download.falco.org/plugins/stable/cloudtrail-0.2.3-${PLUGINS_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR}.tar.gz"
|
||||
URL_HASH "SHA256=3dfce36f37a4f834b6078c6b78776414472a6ee775e8f262535313cc4031d0b7"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
|
||||
install(FILES "${PROJECT_BINARY_DIR}/cloudtrail-plugin-prefix/src/cloudtrail-plugin/libcloudtrail.so" DESTINATION "${FALCO_PLUGINS_DIR}")
|
||||
|
||||
ExternalProject_Add(
|
||||
json-plugin
|
||||
URL "https://download.falco.org/plugins/stable/json-0.2.2-${PLUGINS_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR}.tar.gz"
|
||||
URL_HASH "SHA256=83eb411c9f2125695875b229c6e7974e6a4cc7f028be146b79d26db30372af5e"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
|
||||
install(FILES "${PROJECT_BINARY_DIR}/json-plugin-prefix/src/json-plugin/libjson.so" DESTINATION "${FALCO_PLUGINS_DIR}")
|
||||
@@ -18,7 +18,7 @@ How to use.
|
||||
* docker run -ti falcosecurity/falco-builder bash
|
||||
|
||||
To build Falco it needs:
|
||||
- a bind-mount on the source directory (ie., the directory containing Falco and sysdig source as siblings)
|
||||
- a bind-mount on the source directory (ie., the directory containing the Falco source as sibling)
|
||||
|
||||
Optionally, you can also bind-mount the build directory.
|
||||
So, you can execute it from the Falco root directory as follows.
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
include(copy_files_to_build_dir)
|
||||
|
||||
# Note: list of rules is created at cmake time, not build time
|
||||
file(GLOB test_rule_files
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../../test/rules/*.yaml")
|
||||
|
||||
foreach(rule_file_path ${test_rule_files})
|
||||
get_filename_component(rule_file ${rule_file_path} NAME)
|
||||
add_custom_target(docker-local-rule-${rule_file} ALL
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${rule_file})
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${rule_file}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${rule_file_path} ${CMAKE_CURRENT_BINARY_DIR}/${rule_file}
|
||||
DEPENDS ${rule_file_path})
|
||||
endforeach()
|
||||
|
||||
copy_files_to_build_dir("${test_rule_files}" docker-local-rules)
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
include(copy_files_to_build_dir)
|
||||
|
||||
# Note: list of traces is created at cmake time, not build time
|
||||
file(GLOB test_trace_files
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../../test/trace_files/*.scap")
|
||||
|
||||
foreach(trace_file_path ${test_trace_files})
|
||||
get_filename_component(trace_file ${trace_file_path} NAME)
|
||||
add_custom_target(docker-local-trace-${trace_file} ALL
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${trace_file})
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${trace_file}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${trace_file_path} ${CMAKE_CURRENT_BINARY_DIR}/${trace_file}
|
||||
DEPENDS ${trace_file_path})
|
||||
endforeach()
|
||||
|
||||
copy_files_to_build_dir("${test_trace_files}" docker-local-traces)
|
||||
|
||||
@@ -20,7 +20,7 @@ RUN curl -L -o falco.tar.gz \
|
||||
RUN sed -e 's/time_format_iso_8601: false/time_format_iso_8601: true/' < /falco/etc/falco/falco.yaml > /falco/etc/falco/falco.yaml.new \
|
||||
&& mv /falco/etc/falco/falco.yaml.new /falco/etc/falco/falco.yaml
|
||||
|
||||
FROM scratch
|
||||
FROM debian:11-slim
|
||||
|
||||
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
|
||||
|
||||
|
||||
29
falco.yaml
29
falco.yaml
@@ -33,6 +33,32 @@ rules_file:
|
||||
- /etc/falco/k8s_audit_rules.yaml
|
||||
- /etc/falco/rules.d
|
||||
|
||||
|
||||
#
|
||||
# Plugins that are available for use. These plugins are not loaded by
|
||||
# default, as they require explicit configuration to point to
|
||||
# cloudtrail log files.
|
||||
#
|
||||
|
||||
# To learn more about the supported formats for
|
||||
# init_config/open_params for the cloudtrail plugin, see the README at
|
||||
# https://github.com/falcosecurity/plugins/blob/master/plugins/cloudtrail/README.md.
|
||||
plugins:
|
||||
- name: cloudtrail
|
||||
library_path: libcloudtrail.so
|
||||
init_config: ""
|
||||
open_params: ""
|
||||
- name: json
|
||||
library_path: libjson.so
|
||||
init_config: ""
|
||||
|
||||
# Setting this list to empty ensures that the above plugins are *not*
|
||||
# loaded and enabled by default. If you want to use the above plugins,
|
||||
# set a meaningful init_config/open_params for the cloudtrail plugin
|
||||
# and then change this to:
|
||||
# load_plugins: [cloudtrail, json]
|
||||
load_plugins: []
|
||||
|
||||
# If true, the times displayed in log messages and output messages
|
||||
# will be in ISO 8601. By default, times are displayed in the local
|
||||
# time zone, as governed by /etc/localtime.
|
||||
@@ -66,7 +92,7 @@ log_level: info
|
||||
# Minimum rule priority level to load and run. All rules having a
|
||||
# priority more severe than this level will be loaded/run. Can be one
|
||||
# of "emergency", "alert", "critical", "error", "warning", "notice",
|
||||
# "info", "debug".
|
||||
# "informational", "debug".
|
||||
priority: debug
|
||||
|
||||
# Whether or not output to any of the output channels below is
|
||||
@@ -220,6 +246,7 @@ program_output:
|
||||
http_output:
|
||||
enabled: false
|
||||
url: http://some.url
|
||||
user_agent: "falcosecurity/falco"
|
||||
|
||||
# Falco supports running a gRPC server with two main binding types
|
||||
# 1. Over the network with mandatory mutual TLS authentication (mTLS)
|
||||
|
||||
@@ -27,7 +27,7 @@ That's where Falco comes in. We want to make it possible for Falco to perform a
|
||||
|
||||
Transparently read a candidate PSP into an equivalent set of Falco rules that can look for the conditions in the PSP.
|
||||
|
||||
The PSP is converted into a set of Falco rules which can be either saved as a file for later use/inspection, or loaded directly so they they can monitor system calls and k8s audit activity.
|
||||
The PSP is converted into a set of Falco rules which can be either saved as a file for later use/inspection, or loaded directly so that they can monitor system calls and k8s audit activity.
|
||||
|
||||
### Non-Goals
|
||||
|
||||
@@ -51,6 +51,6 @@ No diagrams yet.
|
||||
|
||||
* We'll use [inja](https://github.com/pantor/inja) as the templating engine.
|
||||
|
||||
* For the most part, we can rely on the existing framework of rules, filter expressions, and output expressions that already exist in Falco. One significant change will be that filter fields can extract more than one "value" per event, and we'll need to define new operators to perform set comparisions betweeen values in an event and values in the comparison right-hand-side.
|
||||
* For the most part, we can rely on the existing framework of rules, filter expressions, and output expressions that already exist in Falco. One significant change will be that filter fields can extract more than one "value" per event, and we'll need to define new operators to perform set comparisons between values in an event and values in the comparison right-hand-side.
|
||||
|
||||
* This will rely heavily on existing support for [K8s Audit Events](https://falco.org/docs/event-sources/kubernetes-audit/) in Falco.
|
||||
|
||||
@@ -6,13 +6,13 @@ This is a proposal to better structure the Falco API.
|
||||
|
||||
The Falco API is a set of contracts describing how users can interacts with Falco.
|
||||
|
||||
By definiing a set of interfaces the Falco Authors intend to decouple Falco from other softwares and data (eg., from the input sources) and, at the same time, make it more extensible.
|
||||
By defining a set of interfaces the Falco Authors intend to decouple Falco from other softwares and data (eg., from the input sources) and, at the same time, make it more extensible.
|
||||
|
||||
Thus, this document intent is to propose a list of services that contistute the Falco API (targeting the first stable version of Falco, v1.0.0).
|
||||
Thus, this document intent is to propose a list of services that constitute the Falco API (targeting the first stable version of Falco, v1.0.0).
|
||||
|
||||
## Motivation
|
||||
|
||||
We want to enable users to use thirdy-party clients to interface with Falco outputs, inputs, rules, and configurations.
|
||||
We want to enable users to use third-party clients to interface with Falco outputs, inputs, rules, and configurations.
|
||||
|
||||
Such ability would enable the community to create a whole set of OSS tools, built on top of Falco.
|
||||
|
||||
@@ -94,7 +94,7 @@ This translates in having the following set of `proto` files.
|
||||
}
|
||||
```
|
||||
|
||||
- one or more `.proto` containing the commond models - ie., the already existing `schema.proto` containing source enum, etc.
|
||||
- one or more `.proto` containing the command models - ie., the already existing `schema.proto` containing source enum, etc.
|
||||
|
||||
```proto3
|
||||
# schema.proto
|
||||
|
||||
@@ -36,7 +36,7 @@ There will be no intention to cover Falco rule syntax in this proposal.
|
||||
|
||||
### Use cases
|
||||
|
||||
When new PRs are created in the area of rules, reviewers need to examine whether there are new rules, macros or lists are introduced. If yes, check wether follow the naming convention.
|
||||
When new PRs are created in the area of rules, reviewers need to examine whether there are new rules, macros or lists are introduced. If yes, check whether follow the naming convention.
|
||||
|
||||
### Diagrams
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ This is done as needed, and can best be measured by the need to cut a release an
|
||||
|
||||
### official support
|
||||
|
||||
As the need for a project grows, it can ultimately achieve the highest and most coveted status within The Falco Project. "_Offical support_."
|
||||
As the need for a project grows, it can ultimately achieve the highest and most coveted status within The Falco Project. "_Official support_."
|
||||
|
||||
The artifacts listed above are part of the official Falco release process. These artifact will be refined and amended by the [Part 2](./20200506-artifacts-scope-part-2.md).
|
||||
|
||||
@@ -111,4 +111,4 @@ Update documentation in [falco-website#184](https://github.com/falcosecurity/fal
|
||||
### Adjusting projects
|
||||
|
||||
- YAML manifest documentation to be moved to `contrib`
|
||||
- Minkube, Kind, Puppet, Ansible, etc documentation to be moved to `contrib`
|
||||
- Minikube, Kind, Puppet, Ansible, etc documentation to be moved to `contrib`
|
||||
|
||||
@@ -196,13 +196,13 @@ Exception values will most commonly be defined in rules with append: true. Here'
|
||||
|
||||
A rule exception applies if for a given event, the fields in a rule.exception match all of the values in some exception.item. For example, if a program `apk` writes to a file below `/usr/lib/alpine`, the rule will not trigger, even if the condition is met.
|
||||
|
||||
Notice that an item in a values list can be a list. This allows building exceptions with operators like "in", "pmatch", etc. that work on a list of items. The item can also be a name of an existing list. If not present surrounding parantheses will be added.
|
||||
Notice that an item in a values list can be a list. This allows building exceptions with operators like "in", "pmatch", etc. that work on a list of items. The item can also be a name of an existing list. If not present surrounding parentheses will be added.
|
||||
|
||||
Finally, note that the structure of the values property differs between the items where fields is a list of fields (proc_writer/container_writer/proc_filenames) and when it is a single field (procs_only). This changes how the condition snippet is constructed.
|
||||
|
||||
### Implementation
|
||||
|
||||
For exception items where the fields property is a list of field names, each exception can be thought of as an implicit "and not (field1 cmp1 val1 and field2 cmp2 val2 and...)" appended to the rule's condition. For exception items where the fields property is a single field name, the exception can be thought of as an implict "and not field cmp (val1, val2, ...)". In practice, that's how exceptions will be implemented.
|
||||
For exception items where the fields property is a list of field names, each exception can be thought of as an implicit "and not (field1 cmp1 val1 and field2 cmp2 val2 and...)" appended to the rule's condition. For exception items where the fields property is a single field name, the exception can be thought of as an implicit "and not field cmp (val1, val2, ...)". In practice, that's how exceptions will be implemented.
|
||||
|
||||
When a rule is parsed, the original condition will be wrapped in an extra layer of parentheses and all exception values will be appended to the condition. For example, using the example above, the resulting condition will be:
|
||||
|
||||
@@ -214,7 +214,7 @@ When a rule is parsed, the original condition will be wrapped in an extra layer
|
||||
(fd.filename in (python, go))))
|
||||
```
|
||||
|
||||
The exceptions are effectively syntatic sugar that allows expressing sets of exceptions in a concise way.
|
||||
The exceptions are effectively syntactic sugar that allows expressing sets of exceptions in a concise way.
|
||||
|
||||
### Advantages
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
This document reflects when and how we clean up the Falco artifacts from their storage location.
|
||||
|
||||
**Superseeded by**: [drivers-storage-s3 proposal](https://github.com/falcosecurity/falco/blob/master/proposals/20201025-drivers-storage-s3.md).
|
||||
**Superseded by**: [drivers-storage-s3 proposal](https://github.com/falcosecurity/falco/blob/master/proposals/20201025-drivers-storage-s3.md).
|
||||
|
||||
## Motivation
|
||||
|
||||
@@ -90,7 +90,7 @@ This way, assuming the number of prebuilt drivers does not skyrocket, we can rea
|
||||
|
||||
Notice that, in case a Falco stable release will not depend on a new driver version, this means the last two driver versions will, in this case, cover more than the two Falco stable releases.
|
||||
|
||||
### Archivation
|
||||
### Archiving
|
||||
|
||||
Since the process of building drivers is time and resource consuming, this document also proposes to move the driver versions in other storage facilities.
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ Source plugins also provide an "id", which is globally unique and is used in cap
|
||||
|
||||
An extractor plugin focuses only on field extraction from events generated by other plugins, or by the core libraries. It does *not* provide an event source, but can extract fields from other event sources. An example is json field extraction, where a plugin might be able to extract fields from arbitrary json payloads.
|
||||
|
||||
An extractor plugin provides an optional set of event sources. When the framework receives an event with an event source in the plugin's set of event sources, fields in expressions/Falco outputs will be extracted from events using the plugin. An extractor plugin can also *not* name a set of event sources. In this case, fields will be extracted from *all* events, regardless of source. In this case, the exctractor plugin must detect the format of arbitrary payloads and be able to return NULL/no value when the payload is not supported.
|
||||
An extractor plugin provides an optional set of event sources. When the framework receives an event with an event source in the plugin's set of event sources, fields in expressions/Falco outputs will be extracted from events using the plugin. An extractor plugin can also *not* name a set of event sources. In this case, fields will be extracted from *all* events, regardless of source. In this case, the extractor plugin must detect the format of arbitrary payloads and be able to return NULL/no value when the payload is not supported.
|
||||
|
||||
### Support for Plugin Events in Capture Files.
|
||||
|
||||
@@ -91,7 +91,7 @@ The libraries will do everything possible to validate the data coming from the p
|
||||
|
||||
### Plugin/Event Source registries
|
||||
|
||||
Every source plugin requires its own, unique plugin ID to interoperate with Falco and the other plugins. The plugin ID will be used by the libs to properly process incoming events (for example, when saving events to file and loading them back), and by plugins to unuambiguosly recognize their dependencies.
|
||||
Every source plugin requires its own, unique plugin ID to interoperate with Falco and the other plugins. The plugin ID will be used by the libs to properly process incoming events (for example, when saving events to file and loading them back), and by plugins to unambiguously recognize their dependencies.
|
||||
|
||||
To facilitate the allocation and distribution of plugin IDs, we will require that plugin developers request IDs for their plugins to the Falco organization. The mechanism used for plugin allocation is not determined yet and will be discussed in the future.
|
||||
|
||||
@@ -474,7 +474,7 @@ typedef struct
|
||||
// Return value: a json array of strings containing event
|
||||
// sources returned by a source plugin's get_event_source()
|
||||
// function.
|
||||
// This function is optional--if NULL then the exctractor
|
||||
// This function is optional--if NULL then the extractor
|
||||
// plugin will receive every event.
|
||||
//
|
||||
char* (*get_extract_event_sources)();
|
||||
@@ -526,7 +526,7 @@ We will also make a change to compile rules/macros/lists selectively based on th
|
||||
|
||||
### Handling Duplicate/Overlapping Fields in Plugins/Libraries Core
|
||||
|
||||
At an initial glance, adding plugins introduces the possibility of tens/hundreds of new filtercheck fields that could potentially overlap/conflict. For example, what happens if a plugin defines a "proc.name" field? However, the notion of "event source" makes these potential conflicts managable.
|
||||
At an initial glance, adding plugins introduces the possibility of tens/hundreds of new filtercheck fields that could potentially overlap/conflict. For example, what happens if a plugin defines a "proc.name" field? However, the notion of "event source" makes these potential conflicts manageable.
|
||||
|
||||
Remember that field extraction is always done in the context of an event, and each event can be mapped back to an event source. So we only need to ensure that filtercheck fields are distinct for a given event source. For example, it's perfectly valid for an AWS Cloudtrail plugin to define a proc.name field, as the events generated by that plugin are wholly separate from syscall events. For syscall events, the AWS Cloudtrail plugin is not involved and the core libraries extract the process name for the tid performing a syscall. For AWS Cloudtrail events, the core libraries are not involved in field extraction and is performed by the AWS Cloudtrail plugin instead.
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ if(NOT DEFINED FALCO_RULES_DEST_FILENAME)
|
||||
set(FALCO_LOCAL_RULES_DEST_FILENAME "falco_rules.local.yaml")
|
||||
set(FALCO_APP_RULES_DEST_FILENAME "application_rules.yaml")
|
||||
set(FALCO_K8S_AUDIT_RULES_DEST_FILENAME "k8s_audit_rules.yaml")
|
||||
set(FALCO_AWS_CLOUDTRAIL_RULES_DEST_FILENAME "aws_cloudtrail_rules.yaml")
|
||||
endif()
|
||||
|
||||
if(DEFINED FALCO_COMPONENT)
|
||||
@@ -59,5 +60,10 @@ else()
|
||||
DESTINATION "${FALCO_ETC_DIR}/rules.available"
|
||||
RENAME "${FALCO_APP_RULES_DEST_FILENAME}")
|
||||
|
||||
install(
|
||||
FILES aws_cloudtrail_rules.yaml
|
||||
DESTINATION "${FALCO_ETC_DIR}"
|
||||
RENAME "${FALCO_AWS_CLOUDTRAIL_RULES_DEST_FILENAME}")
|
||||
|
||||
install(DIRECTORY DESTINATION "${FALCO_ETC_DIR}/rules.d")
|
||||
endif()
|
||||
|
||||
442
rules/aws_cloudtrail_rules.yaml
Normal file
442
rules/aws_cloudtrail_rules.yaml
Normal file
@@ -0,0 +1,442 @@
|
||||
#
|
||||
# Copyright (C) 2022 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with 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.
|
||||
#
|
||||
|
||||
# All rules files related to plugins should require engine version 10
|
||||
- required_engine_version: 10
|
||||
|
||||
# These rules can be read by cloudtrail plugin version 0.1.0, or
|
||||
# anything semver-compatible.
|
||||
- required_plugin_versions:
|
||||
- name: cloudtrail
|
||||
version: 0.2.3
|
||||
- name: json
|
||||
version: 0.2.2
|
||||
|
||||
# Note that this rule is disabled by default. It's useful only to
|
||||
# verify that the cloudtrail plugin is sending events properly. The
|
||||
# very broad condition evt.num > 0 only works because the rule source
|
||||
# is limited to aws_cloudtrail. This ensures that the only events that
|
||||
# are matched against the rule are from the cloudtrail plugin (or
|
||||
# a different plugin with the same source).
|
||||
- rule: All Cloudtrail Events
|
||||
desc: Match all cloudtrail events.
|
||||
condition:
|
||||
evt.num > 0
|
||||
output: Some Cloudtrail Event (evtnum=%evt.num info=%evt.plugininfo ts=%evt.time.iso8601 id=%ct.id error=%ct.error)
|
||||
priority: DEBUG
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
source: aws_cloudtrail
|
||||
enabled: false
|
||||
|
||||
- rule: Console Login Through Assume Role
|
||||
desc: Detect a console login through Assume Role.
|
||||
condition:
|
||||
ct.name="ConsoleLogin" and not ct.error exists
|
||||
and ct.user.identitytype="AssumedRole"
|
||||
and json.value[/responseElements/ConsoleLogin]="Success"
|
||||
output:
|
||||
Detected a console login through Assume Role
|
||||
(principal=%ct.user.principalid,
|
||||
assumedRole=%ct.user.arn,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_console
|
||||
- aws_iam
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Console Login Without MFA
|
||||
desc: Detect a console login without MFA.
|
||||
condition:
|
||||
ct.name="ConsoleLogin" and not ct.error exists
|
||||
and ct.user.identitytype!="AssumedRole"
|
||||
and json.value[/responseElements/ConsoleLogin]="Success"
|
||||
and json.value[/additionalEventData/MFAUsed]="No"
|
||||
output:
|
||||
Detected a console login without MFA
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region)
|
||||
priority: CRITICAL
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_console
|
||||
- aws_iam
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Console Root Login Without MFA
|
||||
desc: Detect root console login without MFA.
|
||||
condition:
|
||||
ct.name="ConsoleLogin" and not ct.error exists
|
||||
and json.value[/additionalEventData/MFAUsed]="No"
|
||||
and ct.user.identitytype!="AssumedRole"
|
||||
and json.value[/responseElements/ConsoleLogin]="Success"
|
||||
and ct.user.identitytype="Root"
|
||||
output:
|
||||
Detected a root console login without MFA.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region)
|
||||
priority: CRITICAL
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_console
|
||||
- aws_iam
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Deactivate MFA for Root User
|
||||
desc: Detect deactivating MFA configuration for root.
|
||||
condition:
|
||||
ct.name="DeactivateMFADevice" and not ct.error exists
|
||||
and ct.user.identitytype="Root"
|
||||
and ct.request.username="AWS ROOT USER"
|
||||
output:
|
||||
Multi Factor Authentication configuration has been disabled for root
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
MFA serial number=%ct.request.serialnumber)
|
||||
priority: CRITICAL
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_iam
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Create AWS user
|
||||
desc: Detect creation of a new AWS user.
|
||||
condition:
|
||||
ct.name="CreateUser" and not ct.error exists
|
||||
output:
|
||||
A new AWS user has been created
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
new user created=%ct.request.username)
|
||||
priority: INFO
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_iam
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Create Group
|
||||
desc: Detect creation of a new user group.
|
||||
condition:
|
||||
ct.name="CreateGroup" and not ct.error exists
|
||||
output:
|
||||
A new user group has been created.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
group name=%ct.request.groupname)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_iam
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Delete Group
|
||||
desc: Detect deletion of a user group.
|
||||
condition:
|
||||
ct.name="DeleteGroup" and not ct.error exists
|
||||
output:
|
||||
A user group has been deleted.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
group name=%ct.request.groupname)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_iam
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: ECS Service Created
|
||||
desc: Detect a new service is created in ECS.
|
||||
condition:
|
||||
ct.src="ecs.amazonaws.com" and
|
||||
ct.name="CreateService" and
|
||||
not ct.error exists
|
||||
output:
|
||||
A new service has been created in ECS
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
cluster=%ct.request.cluster,
|
||||
service name=%ct.request.servicename,
|
||||
task definition=%ct.request.taskdefinition)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_ecs
|
||||
- aws_fargate
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: ECS Task Run or Started
|
||||
desc: Detect a new task is started in ECS.
|
||||
condition:
|
||||
ct.src="ecs.amazonaws.com" and
|
||||
(ct.name="RunTask" or ct.name="StartTask") and
|
||||
not ct.error exists
|
||||
output:
|
||||
A new task has been started in ECS
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
cluster=%ct.request.cluster,
|
||||
task definition=%ct.request.taskdefinition)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_ecs
|
||||
- aws_fargate
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Create Lambda Function
|
||||
desc: Detect creation of a Lambda function.
|
||||
condition:
|
||||
ct.name="CreateFunction20150331" and not ct.error exists
|
||||
output:
|
||||
Lambda function has been created.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
lambda function=%ct.request.functionname)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_lambda
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Update Lambda Function Code
|
||||
desc: Detect updates to a Lambda function code.
|
||||
condition:
|
||||
ct.name="UpdateFunctionCode20150331v2" and not ct.error exists
|
||||
output:
|
||||
The code of a Lambda function has been updated.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
lambda function=%ct.request.functionname)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_lambda
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Update Lambda Function Configuration
|
||||
desc: Detect updates to a Lambda function configuration.
|
||||
condition:
|
||||
ct.name="UpdateFunctionConfiguration20150331v2" and not ct.error exists
|
||||
output:
|
||||
The configuration of a Lambda function has been updated.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
lambda function=%ct.request.functionname)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_lambda
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Run Instances
|
||||
desc: Detect launching of a specified number of instances.
|
||||
condition:
|
||||
ct.name="RunInstances" and not ct.error exists
|
||||
output:
|
||||
A number of instances have been launched.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
availability zone=%ct.request.availabilityzone,
|
||||
subnet id=%ct.response.subnetid,
|
||||
reservation id=%ct.response.reservationid)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_ec2
|
||||
source: aws_cloudtrail
|
||||
|
||||
# Only instances launched on regions in this list are approved.
|
||||
- list: approved_regions
|
||||
items:
|
||||
- us-east-0
|
||||
|
||||
- rule: Run Instances in Non-approved Region
|
||||
desc: Detect launching of a specified number of instances in a non-approved region.
|
||||
condition:
|
||||
ct.name="RunInstances" and not ct.error exists and
|
||||
not ct.region in (approved_regions)
|
||||
output:
|
||||
A number of instances have been launched in a non-approved region.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
availability zone=%ct.request.availabilityzone,
|
||||
subnet id=%ct.response.subnetid,
|
||||
reservation id=%ct.response.reservationid,
|
||||
image id=%json.value[/responseElements/instancesSet/items/0/instanceId])
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_ec2
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Delete Bucket Encryption
|
||||
desc: Detect deleting configuration to use encryption for bucket storage.
|
||||
condition:
|
||||
ct.name="DeleteBucketEncryption" and not ct.error exists
|
||||
output:
|
||||
A encryption configuration for a bucket has been deleted
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
bucket=%s3.bucket)
|
||||
priority: CRITICAL
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_s3
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Delete Bucket Public Access Block
|
||||
desc: Detect deleting blocking public access to bucket.
|
||||
condition:
|
||||
ct.name="PutBucketPublicAccessBlock" and not ct.error exists and
|
||||
json.value[/requestParameters/publicAccessBlock]="" and
|
||||
(json.value[/requestParameters/PublicAccessBlockConfiguration/RestrictPublicBuckets]=false or
|
||||
json.value[/requestParameters/PublicAccessBlockConfiguration/BlockPublicPolicy]=false or
|
||||
json.value[/requestParameters/PublicAccessBlockConfiguration/BlockPublicAcls]=false or
|
||||
json.value[/requestParameters/PublicAccessBlockConfiguration/IgnorePublicAcls]=false)
|
||||
output:
|
||||
A public access block for a bucket has been deleted
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
bucket=%s3.bucket)
|
||||
priority: CRITICAL
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_s3
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: List Buckets
|
||||
desc: Detect listing of all S3 buckets.
|
||||
condition:
|
||||
ct.name="ListBuckets" and not ct.error exists
|
||||
output:
|
||||
A list of all S3 buckets has been requested.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
host=%ct.request.host)
|
||||
priority: WARNING
|
||||
enabled: false
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_s3
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Put Bucket ACL
|
||||
desc: Detect setting the permissions on an existing bucket using access control lists.
|
||||
condition:
|
||||
ct.name="PutBucketAcl" and not ct.error exists
|
||||
output:
|
||||
The permissions on an existing bucket have been set using access control lists.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
bucket name=%s3.bucket)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_s3
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: Put Bucket Policy
|
||||
desc: Detect applying an Amazon S3 bucket policy to an Amazon S3 bucket.
|
||||
condition:
|
||||
ct.name="PutBucketPolicy" and not ct.error exists
|
||||
output:
|
||||
An Amazon S3 bucket policy has been applied to an Amazon S3 bucket.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
bucket name=%s3.bucket,
|
||||
policy=%ct.request.policy)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_s3
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: CloudTrail Trail Created
|
||||
desc: Detect creation of a new trail.
|
||||
condition:
|
||||
ct.name="CreateTrail" and not ct.error exists
|
||||
output:
|
||||
A new trail has been created.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
trail name=%ct.request.name)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_cloudtrail
|
||||
source: aws_cloudtrail
|
||||
|
||||
- rule: CloudTrail Logging Disabled
|
||||
desc: The CloudTrail logging has been disabled, this could be potentially malicious.
|
||||
condition:
|
||||
ct.name="StopLogging" and not ct.error exists
|
||||
output:
|
||||
The CloudTrail logging has been disabled.
|
||||
(requesting user=%ct.user,
|
||||
requesting IP=%ct.srcip,
|
||||
AWS region=%ct.region,
|
||||
resource name=%ct.request.name)
|
||||
priority: WARNING
|
||||
tags:
|
||||
- cloud
|
||||
- aws
|
||||
- aws_cloudtrail
|
||||
source: aws_cloudtrail
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (C) 2020 The Falco Authors.
|
||||
# Copyright (C) 2022 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -29,13 +29,13 @@
|
||||
# condition: (syscall.type=read and evt.dir=> and fd.type in (file, directory))
|
||||
|
||||
- macro: open_write
|
||||
condition: (evt.type=open or evt.type=openat) and evt.is_open_write=true and fd.typechar='f' and fd.num>=0
|
||||
condition: evt.type in (open,openat,openat2) and evt.is_open_write=true and fd.typechar='f' and fd.num>=0
|
||||
|
||||
- macro: open_read
|
||||
condition: (evt.type=open or evt.type=openat) and evt.is_open_read=true and fd.typechar='f' and fd.num>=0
|
||||
condition: evt.type in (open,openat,openat2) and evt.is_open_read=true and fd.typechar='f' and fd.num>=0
|
||||
|
||||
- macro: open_directory
|
||||
condition: (evt.type=open or evt.type=openat) and evt.is_open_read=true and fd.typechar='d' and fd.num>=0
|
||||
condition: evt.type in (open,openat,openat2) and evt.is_open_read=true and fd.typechar='d' and fd.num>=0
|
||||
|
||||
- macro: never_true
|
||||
condition: (evt.num=0)
|
||||
@@ -63,11 +63,14 @@
|
||||
condition: rename or remove
|
||||
|
||||
- macro: spawned_process
|
||||
condition: evt.type = execve and evt.dir=<
|
||||
condition: evt.type in (execve, execveat) and evt.dir=<
|
||||
|
||||
- macro: create_symlink
|
||||
condition: evt.type in (symlink, symlinkat) and evt.dir=<
|
||||
|
||||
- macro: create_hardlink
|
||||
condition: evt.type in (link, linkat) and evt.dir=<
|
||||
|
||||
- macro: chmod
|
||||
condition: (evt.type in (chmod, fchmod, fchmodat) and evt.dir=<)
|
||||
|
||||
@@ -216,13 +219,13 @@
|
||||
- list: deb_binaries
|
||||
items: [dpkg, dpkg-preconfigu, dpkg-reconfigur, dpkg-divert, apt, apt-get, aptitude,
|
||||
frontend, preinst, add-apt-reposit, apt-auto-remova, apt-key,
|
||||
apt-listchanges, unattended-upgr, apt-add-reposit, apt-config, apt-cache, apt.systemd.dai
|
||||
apt-listchanges, unattended-upgr, apt-add-reposit, apt-cache, apt.systemd.dai
|
||||
]
|
||||
|
||||
# The truncated dpkg-preconfigu is intentional, process names are
|
||||
# truncated at the sysdig level.
|
||||
# truncated at the falcosecurity-libs level.
|
||||
- list: package_mgmt_binaries
|
||||
items: [rpm_binaries, deb_binaries, update-alternat, gem, pip, pip3, sane-utils.post, alternatives, chef-client, apk, snapd]
|
||||
items: [rpm_binaries, deb_binaries, update-alternat, gem, npm, pip, pip3, sane-utils.post, alternatives, chef-client, apk, snapd]
|
||||
|
||||
- macro: package_mgmt_procs
|
||||
condition: proc.name in (package_mgmt_binaries)
|
||||
@@ -333,7 +336,7 @@
|
||||
# for efficiency.
|
||||
- macro: inbound_outbound
|
||||
condition: >
|
||||
((((evt.type in (accept,listen,connect) and evt.dir=<)) or
|
||||
((((evt.type in (accept,listen,connect) and evt.dir=<)) and
|
||||
(fd.typechar = 4 or fd.typechar = 6)) and
|
||||
(fd.ip != "0.0.0.0" and fd.net != "127.0.0.0/8") and
|
||||
(evt.rawres >= 0 or evt.res = EINPROGRESS))
|
||||
@@ -561,7 +564,7 @@
|
||||
|
||||
# Qualys seems to run a variety of shell subprocesses, at various
|
||||
# levels. This checks at a few levels without the cost of a full
|
||||
# proc.aname, which traverses the full parent heirarchy.
|
||||
# proc.aname, which traverses the full parent hierarchy.
|
||||
- macro: run_by_qualys
|
||||
condition: >
|
||||
(proc.pname=qualys-cloud-ag or
|
||||
@@ -772,6 +775,9 @@
|
||||
- macro: centrify_writing_krb
|
||||
condition: (proc.name in (adjoin,addns) and fd.name startswith /etc/krb5)
|
||||
|
||||
- macro: sssd_writing_krb
|
||||
condition: (proc.name=adcli and proc.aname[2]=sssd and fd.name startswith /etc/krb5)
|
||||
|
||||
- macro: cockpit_writing_conf
|
||||
condition: >
|
||||
((proc.pname=cockpit-kube-la or proc.aname[2]=cockpit-kube-la)
|
||||
@@ -1100,7 +1106,7 @@
|
||||
condition: (proc.name=oc and fd.name startswith /etc/origin/node)
|
||||
|
||||
- macro: keepalived_writing_conf
|
||||
condition: (proc.name=keepalived and fd.name=/etc/keepalived/keepalived.conf)
|
||||
condition: (proc.name in (keepalived, kube-keepalived) and fd.name=/etc/keepalived/keepalived.conf)
|
||||
|
||||
- macro: etcd_manager_updating_dns
|
||||
condition: (container and proc.name=etcd-manager and fd.name=/etc/hosts)
|
||||
@@ -1215,6 +1221,7 @@
|
||||
and not nginx_writing_certs
|
||||
and not chef_client_writing_conf
|
||||
and not centrify_writing_krb
|
||||
and not sssd_writing_krb
|
||||
and not cockpit_writing_conf
|
||||
and not ipsec_writing_conf
|
||||
and not httpd_writing_ssl_conf
|
||||
@@ -1826,6 +1833,7 @@
|
||||
k8s.gcr.io/ip-masq-agent-amd64,
|
||||
k8s.gcr.io/kube-proxy,
|
||||
k8s.gcr.io/prometheus-to-sd,
|
||||
public.ecr.aws/falcosecurity/falco,
|
||||
quay.io/calico/node,
|
||||
sysdig/sysdig,
|
||||
sematext_images
|
||||
@@ -1854,7 +1862,7 @@
|
||||
- list: falco_sensitive_mount_images
|
||||
items: [
|
||||
docker.io/sysdig/sysdig, sysdig/sysdig,
|
||||
docker.io/falcosecurity/falco, falcosecurity/falco,
|
||||
docker.io/falcosecurity/falco, falcosecurity/falco, public.ecr.aws/falcosecurity/falco,
|
||||
gcr.io/google_containers/hyperkube,
|
||||
gcr.io/google_containers/kube-proxy, docker.io/calico/node,
|
||||
docker.io/rook/toolbox, docker.io/cloudnativelabs/kube-router, docker.io/consul,
|
||||
@@ -1870,19 +1878,6 @@
|
||||
container.image.repository in (falco_sensitive_mount_images) or
|
||||
container.image.repository startswith quay.io/sysdig/)
|
||||
|
||||
# These container images are allowed to run with hostnetwork=true
|
||||
- list: falco_hostnetwork_images
|
||||
items: [
|
||||
gcr.io/google-containers/prometheus-to-sd,
|
||||
gcr.io/projectcalico-org/typha,
|
||||
gcr.io/projectcalico-org/node,
|
||||
gke.gcr.io/gke-metadata-server,
|
||||
gke.gcr.io/kube-proxy,
|
||||
gke.gcr.io/netd-amd64,
|
||||
k8s.gcr.io/ip-masq-agent-amd64
|
||||
k8s.gcr.io/prometheus-to-sd,
|
||||
]
|
||||
|
||||
# Add conditions to this macro (probably in a separate file,
|
||||
# overwriting this macro) to specify additional containers that are
|
||||
# allowed to perform sensitive mounts.
|
||||
@@ -1905,12 +1900,13 @@
|
||||
|
||||
# For now, only considering a full mount of /etc as
|
||||
# sensitive. Ideally, this would also consider all subdirectories
|
||||
# below /etc as well, but the globbing mechanism used by sysdig
|
||||
# below /etc as well, but the globbing mechanism
|
||||
# doesn't allow exclusions of a full pattern, only single characters.
|
||||
- macro: sensitive_mount
|
||||
condition: (container.mount.dest[/proc*] != "N/A" or
|
||||
container.mount.dest[/var/run/docker.sock] != "N/A" or
|
||||
container.mount.dest[/var/run/crio/crio.sock] != "N/A" or
|
||||
container.mount.dest[/run/containerd/containerd.sock] != "N/A" or
|
||||
container.mount.dest[/var/lib/kubelet] != "N/A" or
|
||||
container.mount.dest[/var/lib/kubelet/pki] != "N/A" or
|
||||
container.mount.dest[/] != "N/A" or
|
||||
@@ -2197,7 +2193,7 @@
|
||||
# output: "sshd sent error message to syslog (error=%evt.buffer)"
|
||||
# priority: WARNING
|
||||
|
||||
- macro: somebody_becoming_themself
|
||||
- macro: somebody_becoming_themselves
|
||||
condition: ((user.name=nobody and evt.arg.uid=nobody) or
|
||||
(user.name=www-data and evt.arg.uid=www-data) or
|
||||
(user.name=_apt and evt.arg.uid=_apt) or
|
||||
@@ -2235,7 +2231,7 @@
|
||||
evt.type=setuid and evt.dir=>
|
||||
and (known_user_in_container or not container)
|
||||
and not (user.name=root or user.uid=0)
|
||||
and not somebody_becoming_themself
|
||||
and not somebody_becoming_themselves
|
||||
and not proc.name in (known_setuid_binaries, userexec_binaries, mail_binaries, docker_binaries,
|
||||
nomachine_binaries)
|
||||
and not proc.name startswith "runc:"
|
||||
@@ -2259,7 +2255,7 @@
|
||||
activity by any programs that can manage users, passwords, or permissions. sudo and su are excluded.
|
||||
Activity in containers is also excluded--some containers create custom users on top
|
||||
of a base linux distribution at startup.
|
||||
Some innocuous commandlines that don't actually change anything are excluded.
|
||||
Some innocuous command lines that don't actually change anything are excluded.
|
||||
condition: >
|
||||
spawned_process and proc.name in (user_mgmt_binaries) and
|
||||
not proc.name in (su, sudo, lastlog, nologin, unix_chkpwd) and not container and
|
||||
@@ -2295,7 +2291,7 @@
|
||||
desc: creating any files below /dev other than known programs that manage devices. Some rootkits hide files in /dev.
|
||||
condition: >
|
||||
fd.directory = /dev and
|
||||
(evt.type = creat or ((evt.type = open or evt.type = openat) and evt.arg.flags contains O_CREAT))
|
||||
(evt.type = creat or (evt.type in (open,openat,openat2) and evt.arg.flags contains O_CREAT))
|
||||
and not proc.name in (dev_creation_binaries)
|
||||
and not fd.name in (allowed_dev_files)
|
||||
and not fd.name startswith /dev/tty
|
||||
@@ -2309,7 +2305,7 @@
|
||||
# explicitly enumerate the container images that you want to allow
|
||||
# access to EC2 metadata. In this main falco rules file, there isn't
|
||||
# any way to know all the containers that should have access, so any
|
||||
# container is alllowed, by repeating the "container" macro. In the
|
||||
# container is allowed, by repeating the "container" macro. In the
|
||||
# overridden macro, the condition would look something like
|
||||
# (container.image.repository = vendor/container-1 or
|
||||
# container.image.repository = vendor/container-2 or ...)
|
||||
@@ -2363,7 +2359,8 @@
|
||||
docker.io/sysdig/sysdig, docker.io/falcosecurity/falco,
|
||||
sysdig/sysdig, falcosecurity/falco,
|
||||
fluent/fluentd-kubernetes-daemonset, prom/prometheus,
|
||||
ibm_cloud_containers)
|
||||
ibm_cloud_containers,
|
||||
public.ecr.aws/falcosecurity/falco)
|
||||
or (k8s.ns.name = "kube-system"))
|
||||
|
||||
- macro: k8s_api_server
|
||||
@@ -2571,15 +2568,15 @@
|
||||
condition: >
|
||||
(modify and (
|
||||
evt.arg.name contains "bash_history" or
|
||||
evt.arg.name contains "zsh_history" or
|
||||
evt.arg.name endswith "zsh_history" or
|
||||
evt.arg.name contains "fish_read_history" or
|
||||
evt.arg.name endswith "fish_history" or
|
||||
evt.arg.oldpath contains "bash_history" or
|
||||
evt.arg.oldpath contains "zsh_history" or
|
||||
evt.arg.oldpath endswith "zsh_history" or
|
||||
evt.arg.oldpath contains "fish_read_history" or
|
||||
evt.arg.oldpath endswith "fish_history" or
|
||||
evt.arg.path contains "bash_history" or
|
||||
evt.arg.path contains "zsh_history" or
|
||||
evt.arg.path endswith "zsh_history" or
|
||||
evt.arg.path contains "fish_read_history" or
|
||||
evt.arg.path endswith "fish_history"))
|
||||
|
||||
@@ -2587,7 +2584,7 @@
|
||||
condition: >
|
||||
(open_write and (
|
||||
fd.name contains "bash_history" or
|
||||
fd.name contains "zsh_history" or
|
||||
fd.name endswith "zsh_history" or
|
||||
fd.name contains "fish_read_history" or
|
||||
fd.name endswith "fish_history") and evt.arg.flags contains "O_TRUNC")
|
||||
|
||||
@@ -2626,7 +2623,7 @@
|
||||
items: [hyperkube, kubelet, k3s-agent]
|
||||
|
||||
# This macro should be overridden in user rules as needed. This is useful if a given application
|
||||
# should not be ignored alltogether with the user_known_chmod_applications list, but only in
|
||||
# should not be ignored altogether with the user_known_chmod_applications list, but only in
|
||||
# specific conditions.
|
||||
- macro: user_known_set_setuid_or_setgid_bit_conditions
|
||||
condition: (never_true)
|
||||
@@ -2705,8 +2702,18 @@
|
||||
create_symlink and
|
||||
(evt.arg.target in (sensitive_file_names) or evt.arg.target in (sensitive_directory_names))
|
||||
output: >
|
||||
Symlinks created over senstivie files (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline target=%evt.arg.target linkpath=%evt.arg.linkpath parent_process=%proc.pname)
|
||||
priority: NOTICE
|
||||
Symlinks created over sensitive files (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline target=%evt.arg.target linkpath=%evt.arg.linkpath parent_process=%proc.pname)
|
||||
priority: WARNING
|
||||
tags: [file, mitre_exfiltration]
|
||||
|
||||
- rule: Create Hardlink Over Sensitive Files
|
||||
desc: Detect hardlink created over sensitive files
|
||||
condition: >
|
||||
create_hardlink and
|
||||
(evt.arg.oldpath in (sensitive_file_names))
|
||||
output: >
|
||||
Hardlinks created over sensitive files (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline target=%evt.arg.oldpath linkpath=%evt.arg.newpath parent_process=%proc.pname)
|
||||
priority: WARNING
|
||||
tags: [file, mitre_exfiltration]
|
||||
|
||||
- list: miner_ports
|
||||
@@ -2802,7 +2809,7 @@
|
||||
condition: (evt.type in (sendto, sendmsg) and evt.dir=< and (fd.net != "127.0.0.0/8" and not fd.snet in (rfc_1918_addresses)) and ((minerpool_http) or (minerpool_https) or (minerpool_other)))
|
||||
|
||||
- macro: trusted_images_query_miner_domain_dns
|
||||
condition: (container.image.repository in (docker.io/falcosecurity/falco, falcosecurity/falco))
|
||||
condition: (container.image.repository in (docker.io/falcosecurity/falco, falcosecurity/falco, public.ecr.aws/falcosecurity/falco))
|
||||
append: false
|
||||
|
||||
# The rule is disabled by default.
|
||||
@@ -2811,13 +2818,13 @@
|
||||
desc: Miners typically connect to miner pools on common ports.
|
||||
condition: net_miner_pool and not trusted_images_query_miner_domain_dns
|
||||
enabled: false
|
||||
output: Outbound connection to IP/Port flagged by cryptoioc.ch (command=%proc.cmdline port=%fd.rport ip=%fd.rip container=%container.info image=%container.image.repository)
|
||||
output: Outbound connection to IP/Port flagged by https://cryptoioc.ch (command=%proc.cmdline port=%fd.rport ip=%fd.rip container=%container.info image=%container.image.repository)
|
||||
priority: CRITICAL
|
||||
tags: [network, mitre_execution]
|
||||
|
||||
- rule: Detect crypto miners using the Stratum protocol
|
||||
desc: Miners typically specify the mining pool to connect to with a URI that begins with 'stratum+tcp'
|
||||
condition: spawned_process and proc.cmdline contains "stratum+tcp"
|
||||
condition: spawned_process and (proc.cmdline contains "stratum+tcp" or proc.cmdline contains "stratum2+tcp" or proc.cmdline contains "stratum+ssl" or proc.cmdline contains "stratum2+ssl")
|
||||
output: Possible miner running (command=%proc.cmdline container=%container.info image=%container.image.repository)
|
||||
priority: CRITICAL
|
||||
tags: [process, mitre_execution]
|
||||
@@ -2953,7 +2960,7 @@
|
||||
|
||||
# The two Container Drift rules below will fire when a new executable is created in a container.
|
||||
# There are two ways to create executables - file is created with execution permissions or permissions change of existing file.
|
||||
# We will use a new sysdig filter, is_open_exec, to find all files creations with execution permission, and will trace all chmods in a container.
|
||||
# We will use a new filter, is_open_exec, to find all files creations with execution permission, and will trace all chmods in a container.
|
||||
# The use case we are targeting here is an attempt to execute code that was not shipped as part of a container (drift) -
|
||||
# an activity that might be malicious or non-compliant.
|
||||
# Two things to pay attention to:
|
||||
@@ -2986,7 +2993,7 @@
|
||||
- rule: Container Drift Detected (open+create)
|
||||
desc: New executable created in a container due to open+create
|
||||
condition: >
|
||||
evt.type in (open,openat,creat) and
|
||||
evt.type in (open,openat,openat2,creat) and
|
||||
evt.is_open_exec=true and
|
||||
container and
|
||||
not runc_writing_exec_fifo and
|
||||
@@ -3036,7 +3043,7 @@
|
||||
# A privilege escalation to root through heap-based buffer overflow
|
||||
- rule: Sudo Potential Privilege Escalation
|
||||
desc: Privilege escalation vulnerability affecting sudo (<= 1.9.5p2). Executing sudo using sudoedit -s or sudoedit -i command with command-line argument that ends with a single backslash character from an unprivileged user it's possible to elevate the user privileges to root.
|
||||
condition: spawned_process and user.uid != 0 and proc.name=sudoedit and (proc.args contains -s or proc.args contains -i) and (proc.args contains "\ " or proc.args endswith \)
|
||||
condition: spawned_process and user.uid != 0 and (proc.name=sudoedit or proc.name = sudo) and (proc.args contains -s or proc.args contains -i or proc.args contains --login) and (proc.args contains "\ " or proc.args endswith \)
|
||||
output: "Detect Sudo Privilege Escalation Exploit (CVE-2021-3156) (user=%user.name parent=%proc.pname cmdline=%proc.cmdline %container.info)"
|
||||
priority: CRITICAL
|
||||
tags: [filesystem, mitre_privilege_escalation]
|
||||
@@ -3055,7 +3062,7 @@
|
||||
condition: (proc.args="" or proc.args intersects ("-V", "-l", "-h"))
|
||||
|
||||
- rule: Mount Launched in Privileged Container
|
||||
desc: Detect file system mount happened inside a privilegd container which might lead to container escape.
|
||||
desc: Detect file system mount happened inside a privileged container which might lead to container escape.
|
||||
condition: >
|
||||
spawned_process and container
|
||||
and container.privileged=true
|
||||
@@ -3083,7 +3090,51 @@
|
||||
priority: CRITICAL
|
||||
tags: [syscall, mitre_defense_evasion]
|
||||
|
||||
- list: ingress_remote_file_copy_binaries
|
||||
items: [wget]
|
||||
|
||||
- macro: ingress_remote_file_copy_procs
|
||||
condition: (proc.name in (ingress_remote_file_copy_binaries))
|
||||
|
||||
# Users should overwrite this macro to specify conditions under which a
|
||||
# Custom condition for use of ingress remote file copy tool in container
|
||||
- macro: user_known_ingress_remote_file_copy_activities
|
||||
condition: (never_true)
|
||||
|
||||
- macro: curl_download
|
||||
condition: proc.name = curl and
|
||||
(proc.cmdline contains " > " or
|
||||
proc.cmdline contains " >> " or
|
||||
proc.cmdline contains " | " or
|
||||
proc.cmdline contains " -o " or
|
||||
proc.cmdline contains " --output " or
|
||||
proc.cmdline contains " -O " or
|
||||
proc.cmdline contains " --remote-name ")
|
||||
|
||||
- rule: Launch Ingress Remote File Copy Tools in Container
|
||||
desc: Detect ingress remote file copy tools launched in container
|
||||
condition: >
|
||||
spawned_process and
|
||||
container and
|
||||
(ingress_remote_file_copy_procs or curl_download) and
|
||||
not user_known_ingress_remote_file_copy_activities
|
||||
output: >
|
||||
Ingress remote file copy tool launched in container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline parent_process=%proc.pname
|
||||
container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
||||
priority: NOTICE
|
||||
tags: [network, process, mitre_command_and_control]
|
||||
|
||||
# This rule helps detect CVE-2021-4034:
|
||||
# A privilege escalation to root through memory corruption
|
||||
- rule: Polkit Local Privilege Escalation Vulnerability (CVE-2021-4034)
|
||||
desc: "This rule detects an attempt to exploit a privilege escalation vulnerability in Polkit's pkexec. By running specially crafted code, a local user can leverage this flaw to gain root privileges on a compromised system"
|
||||
condition:
|
||||
spawned_process and user.uid != 0 and proc.name=pkexec and proc.args = ''
|
||||
output:
|
||||
"Detect Polkit pkexec Local Privilege Escalation Exploit (CVE-2021-4034) (user=%user.loginname uid=%user.loginuid command=%proc.cmdline args=%proc.args)"
|
||||
priority: CRITICAL
|
||||
tags: [process, mitre_privilege_escalation]
|
||||
|
||||
# Application rules have moved to application_rules.yaml. Please look
|
||||
# there if you want to enable them by adding to
|
||||
# falco_rules.local.yaml.
|
||||
|
||||
|
||||
@@ -152,6 +152,19 @@
|
||||
source: k8s_audit
|
||||
tags: [k8s]
|
||||
|
||||
# These container images are allowed to run with hostnetwork=true
|
||||
- list: falco_hostnetwork_images
|
||||
items: [
|
||||
gcr.io/google-containers/prometheus-to-sd,
|
||||
gcr.io/projectcalico-org/typha,
|
||||
gcr.io/projectcalico-org/node,
|
||||
gke.gcr.io/gke-metadata-server,
|
||||
gke.gcr.io/kube-proxy,
|
||||
gke.gcr.io/netd-amd64,
|
||||
k8s.gcr.io/ip-masq-agent-amd64
|
||||
k8s.gcr.io/prometheus-to-sd,
|
||||
]
|
||||
|
||||
# Corresponds to K8s CIS Benchmark 1.7.4
|
||||
- rule: Create HostNetwork Pod
|
||||
desc: Detect an attempt to start a pod using the host network.
|
||||
@@ -302,9 +315,31 @@
|
||||
items: []
|
||||
|
||||
- list: known_sa_list
|
||||
items: ["pod-garbage-collector","resourcequota-controller","cronjob-controller","generic-garbage-collector",
|
||||
"daemon-set-controller","endpointslice-controller","deployment-controller", "replicaset-controller",
|
||||
"endpoint-controller", "namespace-controller", "statefulset-controller", "disruption-controller"]
|
||||
items: [
|
||||
coredns,
|
||||
coredns-autoscaler,
|
||||
cronjob-controller,
|
||||
daemon-set-controller,
|
||||
deployment-controller,
|
||||
disruption-controller,
|
||||
endpoint-controller,
|
||||
endpointslice-controller,
|
||||
endpointslicemirroring-controller,
|
||||
generic-garbage-collector,
|
||||
horizontal-pod-autoscaler,
|
||||
job-controller,
|
||||
namespace-controller,
|
||||
node-controller,
|
||||
persistent-volume-binder,
|
||||
pod-garbage-collector,
|
||||
pv-protection-controller,
|
||||
pvc-protection-controller,
|
||||
replicaset-controller,
|
||||
resourcequota-controller,
|
||||
root-ca-cert-publisher,
|
||||
service-account-controller,
|
||||
statefulset-controller
|
||||
]
|
||||
|
||||
- macro: trusted_sa
|
||||
condition: (ka.target.name in (known_sa_list, user_known_sa_list))
|
||||
@@ -331,7 +366,7 @@
|
||||
tags: [k8s]
|
||||
|
||||
# Detect any attempt to create a ClusterRoleBinding to the cluster-admin user
|
||||
# (exapand this to any built-in cluster role that does "sensitive" things)
|
||||
# (expand this to any built-in cluster role that does "sensitive" things)
|
||||
- rule: Attach to cluster-admin Role
|
||||
desc: Detect any attempt to create a ClusterRoleBinding to the cluster-admin user
|
||||
condition: kevt and clusterrolebinding and kcreate and ka.req.binding.role=cluster-admin
|
||||
@@ -537,7 +572,7 @@
|
||||
# cluster creation. This may signify a permission setting too broader.
|
||||
# As we can't check for role of the user on a general ka.* event, this
|
||||
# may or may not be an administrator. Customize the full_admin_k8s_users
|
||||
# list to your needs, and activate at your discrection.
|
||||
# list to your needs, and activate at your discretion.
|
||||
|
||||
# # How to test:
|
||||
# # Execute any kubectl command connected using default cluster user, as:
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
set -e
|
||||
|
||||
DKMS_PACKAGE_NAME="@PACKAGE_NAME@"
|
||||
DKMS_VERSION="@PROBE_VERSION@"
|
||||
DKMS_VERSION="@DRIVER_VERSION@"
|
||||
NAME="@PACKAGE_NAME@"
|
||||
|
||||
postinst_found=0
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
set -e
|
||||
|
||||
DKMS_PACKAGE_NAME="@PACKAGE_NAME@"
|
||||
DKMS_VERSION="@PROBE_VERSION@"
|
||||
DKMS_VERSION="@DRIVER_VERSION@"
|
||||
|
||||
case "$1" in
|
||||
remove|upgrade|deconfigure)
|
||||
|
||||
@@ -160,13 +160,26 @@ load_kernel_module_compile() {
|
||||
echo "make CC=${CURRENT_GCC} \$@" >> /tmp/falco-dkms-make
|
||||
chmod +x /tmp/falco-dkms-make
|
||||
if dkms install --directive="MAKE='/tmp/falco-dkms-make'" -m "${DRIVER_NAME}" -v "${DRIVER_VERSION}" -k "${KERNEL_RELEASE}" 2>/dev/null; then
|
||||
echo "* ${DRIVER_NAME} module installed in dkms, trying to insmod"
|
||||
if insmod "/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/${KERNEL_RELEASE}/${ARCH}/module/${DRIVER_NAME}.ko" > /dev/null 2>&1; then
|
||||
echo "* ${DRIVER_NAME} module installed in dkms"
|
||||
KO_FILE="/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/${KERNEL_RELEASE}/${ARCH}/module/${DRIVER_NAME}"
|
||||
if [ -f "$KO_FILE.ko" ]; then
|
||||
KO_FILE="$KO_FILE.ko"
|
||||
elif [ -f "$KO_FILE.ko.gz" ]; then
|
||||
KO_FILE="$KO_FILE.ko.gz"
|
||||
elif [ -f "$KO_FILE.ko.xz" ]; then
|
||||
KO_FILE="$KO_FILE.ko.xz"
|
||||
elif [ -f "$KO_FILE.ko.zst" ]; then
|
||||
KO_FILE="$KO_FILE.ko.zst"
|
||||
else
|
||||
>&2 echo "${DRIVER_NAME} module file not found"
|
||||
return
|
||||
fi
|
||||
echo "* ${DRIVER_NAME} module found: ${KO_FILE}"
|
||||
echo "* Trying insmod"
|
||||
chcon -t modules_object_t "$KO_FILE" > /dev/null 2>&1 || true
|
||||
if insmod "$KO_FILE" > /dev/null 2>&1; then
|
||||
echo "* Success: ${DRIVER_NAME} module found and loaded in dkms"
|
||||
exit 0
|
||||
elif insmod "/var/lib/dkms/${DRIVER_NAME}/${DRIVER_VERSION}/${KERNEL_RELEASE}/${ARCH}/module/${DRIVER_NAME}.ko.xz" > /dev/null 2>&1; then
|
||||
echo "* Success: ${DRIVER_NAME} module found and loaded in dkms (xz)"
|
||||
exit 0
|
||||
else
|
||||
echo "* Unable to insmod ${DRIVER_NAME} module"
|
||||
fi
|
||||
@@ -193,8 +206,13 @@ load_kernel_module_download() {
|
||||
echo "* Trying to download a prebuilt ${DRIVER_NAME} module from ${URL}"
|
||||
if curl -L --create-dirs "${FALCO_DRIVER_CURL_OPTIONS}" -o "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" "${URL}"; then
|
||||
echo "* Download succeeded"
|
||||
insmod "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" && echo "* Success: ${DRIVER_NAME} module found and inserted"
|
||||
exit $?
|
||||
chcon -t modules_object_t "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" > /dev/null 2>&1 || true
|
||||
if insmod "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}"; then
|
||||
echo "* Success: ${DRIVER_NAME} module found and inserted"
|
||||
exit 0
|
||||
else
|
||||
>&2 echo "Unable to insmod the prebuilt ${DRIVER_NAME} module"
|
||||
fi
|
||||
else
|
||||
>&2 echo "Unable to find a prebuilt ${DRIVER_NAME} module"
|
||||
return
|
||||
@@ -238,11 +256,6 @@ load_kernel_module() {
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "* Trying to load a system ${DRIVER_NAME} module, if present"
|
||||
if modprobe "${DRIVER_NAME}" > /dev/null 2>&1; then
|
||||
echo "* Success: ${DRIVER_NAME} module found and loaded with modprobe"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "* Looking for a ${DRIVER_NAME} module locally (kernel ${KERNEL_RELEASE})"
|
||||
|
||||
@@ -252,6 +265,7 @@ load_kernel_module() {
|
||||
|
||||
if [ -f "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" ]; then
|
||||
echo "* Found a prebuilt ${DRIVER_NAME} module at ${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}, loading it"
|
||||
chcon -t modules_object_t "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" > /dev/null 2>&1 || true
|
||||
insmod "${HOME}/.falco/${FALCO_KERNEL_MODULE_FILENAME}" && echo "* Success: ${DRIVER_NAME} module found and inserted"
|
||||
exit $?
|
||||
fi
|
||||
@@ -264,6 +278,13 @@ load_kernel_module() {
|
||||
load_kernel_module_compile
|
||||
fi
|
||||
|
||||
# Last try (might load a previous driver version)
|
||||
echo "* Trying to load a system ${DRIVER_NAME} module, if present"
|
||||
if modprobe "${DRIVER_NAME}" > /dev/null 2>&1; then
|
||||
echo "* Success: ${DRIVER_NAME} module found and loaded with modprobe"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Not able to download a prebuilt module nor to compile one on-the-fly
|
||||
>&2 echo "Consider compiling your own ${DRIVER_NAME} driver and loading it or getting in touch with the Falco community"
|
||||
exit 1
|
||||
@@ -296,16 +317,16 @@ clean_kernel_module() {
|
||||
return
|
||||
fi
|
||||
|
||||
DRIVER_VERSIONS=$(dkms status -m "${DRIVER_NAME}" | cut -d',' -f2 | sed -e 's/^[[:space:]]*//')
|
||||
DRIVER_VERSIONS=$(dkms status -m "${DRIVER_NAME}" | cut -d',' -f1 | sed -e 's/^[[:space:]]*//')
|
||||
if [ -z "${DRIVER_VERSIONS}" ]; then
|
||||
echo "* There is no ${DRIVER_NAME} module in dkms"
|
||||
return
|
||||
fi
|
||||
for CURRENT_VER in ${DRIVER_VERSIONS}; do
|
||||
if dkms remove -m "${DRIVER_NAME}" -v "${CURRENT_VER}" --all 2>/dev/null; then
|
||||
echo "* Removing ${DRIVER_NAME}/${CURRENT_VER} succeeded"
|
||||
if dkms remove "${CURRENT_VER}" --all 2>/dev/null; then
|
||||
echo "* Removing ${CURRENT_VER} succeeded"
|
||||
else
|
||||
echo "* Removing ${DRIVER_NAME}/${CURRENT_VER} failed"
|
||||
echo "* Removing ${CURRENT_VER} failed"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
@@ -493,7 +514,7 @@ print_usage() {
|
||||
echo " --source-only skip execution and allow sourcing in another script"
|
||||
echo ""
|
||||
echo "Environment variables:"
|
||||
echo " DRIVER_REPO specify a different URL where to look for prebuilt Falco drivers"
|
||||
echo " DRIVERS_REPO specify a different URL where to look for prebuilt Falco drivers"
|
||||
echo " DRIVER_NAME specify a different name for the driver"
|
||||
echo " DRIVER_INSECURE_DOWNLOAD whether you want to allow insecure downloads or not"
|
||||
echo ""
|
||||
@@ -526,8 +547,8 @@ if [[ -z "$MAX_RMMOD_WAIT" ]]; then
|
||||
MAX_RMMOD_WAIT=60
|
||||
fi
|
||||
|
||||
DRIVER_VERSION="@PROBE_VERSION@"
|
||||
DRIVER_NAME=${DRIVER_NAME:-"@PROBE_NAME@"}
|
||||
DRIVER_VERSION="@DRIVER_VERSION@"
|
||||
DRIVER_NAME=${DRIVER_NAME:-"@DRIVER_NAME@"}
|
||||
FALCO_VERSION="@FALCO_VERSION@"
|
||||
|
||||
DRIVER="module"
|
||||
@@ -634,4 +655,4 @@ if [ -z "$source_only" ]; then
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -23,7 +23,7 @@ add_deb() {
|
||||
cp -f $3 $1/$2
|
||||
pushd $1/$2 > /dev/null
|
||||
rm -f $(basename -- $3).asc
|
||||
gpg --detach-sign --armor $(basename -- $3)
|
||||
gpg --detach-sign --digest-algo SHA256 --armor $(basename -- $3)
|
||||
popd > /dev/null
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ update_repo() {
|
||||
${release_dir} > ${release_dir}/Release
|
||||
|
||||
# release signature
|
||||
gpg --detach-sign --armor ${release_dir}/Release
|
||||
gpg --detach-sign --digest-algo SHA256 --armor ${release_dir}/Release
|
||||
rm -f ${release_dir}/Release.gpg
|
||||
mv ${release_dir}/Release.asc ${release_dir}/Release.gpg
|
||||
|
||||
@@ -129,4 +129,4 @@ aws s3 sync ${tmp_repo_path}/dists ${s3_bucket_repo}/dists --delete --acl public
|
||||
|
||||
aws cloudfront create-invalidation --distribution-id ${AWS_CLOUDFRONT_DIST_ID} --paths ${cloudfront_path}/${debSuite}/${package}
|
||||
aws cloudfront create-invalidation --distribution-id ${AWS_CLOUDFRONT_DIST_ID} --paths ${cloudfront_path}/${debSuite}/${package}.asc
|
||||
aws cloudfront create-invalidation --distribution-id ${AWS_CLOUDFRONT_DIST_ID} --paths ${cloudfront_path}/dists/*
|
||||
aws cloudfront create-invalidation --distribution-id ${AWS_CLOUDFRONT_DIST_ID} --paths ${cloudfront_path}/dists/*
|
||||
|
||||
@@ -22,7 +22,7 @@ add_rpm() {
|
||||
cp -f $2 $1
|
||||
pushd $1 > /dev/null
|
||||
rm -f $(basename -- $2).asc
|
||||
gpg --detach-sign --armor $(basename -- $2)
|
||||
gpg --detach-sign --digest-algo SHA256 --armor $(basename -- $2)
|
||||
popd > /dev/null
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ update_repo() {
|
||||
pushd $1 > /dev/null
|
||||
createrepo --update --no-database .
|
||||
rm -f repodata/repomd.xml.asc
|
||||
gpg --detach-sign --armor repodata/repomd.xml
|
||||
gpg --detach-sign --digest-algo SHA256 --armor repodata/repomd.xml
|
||||
popd > /dev/null
|
||||
}
|
||||
|
||||
@@ -93,4 +93,4 @@ aws s3 sync ${tmp_repo_path}/repodata ${s3_bucket_repo}/repodata --delete --acl
|
||||
|
||||
aws cloudfront create-invalidation --distribution-id ${AWS_CLOUDFRONT_DIST_ID} --paths ${cloudfront_path}/${package}
|
||||
aws cloudfront create-invalidation --distribution-id ${AWS_CLOUDFRONT_DIST_ID} --paths ${cloudfront_path}/${package}.asc
|
||||
aws cloudfront create-invalidation --distribution-id ${AWS_CLOUDFRONT_DIST_ID} --paths ${cloudfront_path}/repodata/*
|
||||
aws cloudfront create-invalidation --distribution-id ${AWS_CLOUDFRONT_DIST_ID} --paths ${cloudfront_path}/repodata/*
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
mod_version="@PROBE_VERSION@"
|
||||
mod_version="@DRIVER_VERSION@"
|
||||
dkms add -m falco -v $mod_version --rpm_safe_upgrade
|
||||
if [ `uname -r | grep -c "BOOT"` -eq 0 ] && [ -e /lib/modules/`uname -r`/build/include ]; then
|
||||
dkms build -m falco -v $mod_version
|
||||
|
||||
@@ -15,5 +15,5 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
mod_version="@PROBE_VERSION@"
|
||||
mod_version="@DRIVER_VERSION@"
|
||||
dkms remove -m falco -v $mod_version --all --rpm_safe_upgrade
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
add_subdirectory(trace_files)
|
||||
|
||||
add_custom_target(test-trace-files ALL)
|
||||
add_dependencies(test-trace-files trace-files-base-scap trace-files-psp trace-files-k8s-audit)
|
||||
add_subdirectory(plugins)
|
||||
add_subdirectory(confs/plugins)
|
||||
|
||||
@@ -71,7 +71,7 @@ The `falco_traces.yaml` test suite gets generated through the `falco_traces.yaml
|
||||
|
||||
### falco_tests_package
|
||||
|
||||
The `falco_tests_package.yaml` test suite requires some additional setup steps to be succesfully run on your local machine.
|
||||
The `falco_tests_package.yaml` test suite requires some additional setup steps to be successfully run on your local machine.
|
||||
|
||||
In particular, it requires some runners (ie., docker images) to be already built and present into your local machine.
|
||||
|
||||
|
||||
16
test/confs/plugins/CMakeLists.txt
Normal file
16
test/confs/plugins/CMakeLists.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
# This list is populated at cmake time, not build time
|
||||
file(GLOB test_conf_files
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/*.yaml")
|
||||
|
||||
foreach(conf_file_path ${test_conf_files})
|
||||
get_filename_component(conf_file ${conf_file_path} NAME)
|
||||
add_custom_target(test-conf-${conf_file} ALL
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${conf_file})
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${conf_file}
|
||||
COMMAND sed -e s!BUILD_DIR!${CMAKE_BINARY_DIR}! < ${CMAKE_CURRENT_SOURCE_DIR}/${conf_file} > ${CMAKE_CURRENT_BINARY_DIR}/${conf_file}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${conf_file})
|
||||
list(APPEND PLUGINS_CONF_FILES_TARGETS test-conf-${conf_file})
|
||||
endforeach()
|
||||
|
||||
add_custom_target(conf-files-plugins ALL)
|
||||
add_dependencies(conf-files-plugins ${PLUGINS_CONF_FILES_TARGETS})
|
||||
14
test/confs/plugins/cloudtrail_json_create_instances.yaml
Normal file
14
test/confs/plugins/cloudtrail_json_create_instances.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
stdout_output:
|
||||
enabled: true
|
||||
|
||||
plugins:
|
||||
- name: cloudtrail
|
||||
library_path: BUILD_DIR/cloudtrail-plugin-prefix/src/cloudtrail-plugin/libcloudtrail.so
|
||||
init_config: ""
|
||||
open_params: "BUILD_DIR/test/trace_files/plugins/alice_start_instances.json"
|
||||
- name: json
|
||||
library_path: BUILD_DIR/json-plugin-prefix/src/json-plugin/libjson.so
|
||||
init_config: ""
|
||||
|
||||
# Optional
|
||||
load_plugins: [cloudtrail, json]
|
||||
@@ -0,0 +1,14 @@
|
||||
stdout_output:
|
||||
enabled: true
|
||||
|
||||
plugins:
|
||||
- name: cloudtrail
|
||||
library_path: BUILD_DIR/cloudtrail-plugin-prefix/src/cloudtrail-plugin/libcloudtrail.so
|
||||
init_config: ""
|
||||
open_params: "BUILD_DIR/test/trace_files/plugins/alice_start_instances_bigevent.json"
|
||||
- name: json
|
||||
library_path: BUILD_DIR/json-plugin-prefix/src/json-plugin/libjson.so
|
||||
init_config: ""
|
||||
|
||||
# Optional
|
||||
load_plugins: [cloudtrail, json]
|
||||
14
test/confs/plugins/incompatible_extract_sources.yaml
Normal file
14
test/confs/plugins/incompatible_extract_sources.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
stdout_output:
|
||||
enabled: true
|
||||
|
||||
plugins:
|
||||
- name: cloudtrail
|
||||
library_path: BUILD_DIR/cloudtrail-plugin-prefix/src/cloudtrail-plugin/libcloudtrail.so
|
||||
init_config: ""
|
||||
open_params: ""
|
||||
- name: test_extract_p1
|
||||
library_path: BUILD_DIR/test/plugins/libtest_extract_p1.so
|
||||
init_config: ""
|
||||
|
||||
# Optional
|
||||
load_plugins: [cloudtrail, test_extract_p1]
|
||||
10
test/confs/plugins/incompatible_plugin_api.yaml
Normal file
10
test/confs/plugins/incompatible_plugin_api.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
stdout_output:
|
||||
enabled: true
|
||||
|
||||
plugins:
|
||||
- name: incompatible_plugin_api
|
||||
library_path: BUILD_DIR/test/plugins/libtest_incompat_api.so
|
||||
init_config: ""
|
||||
|
||||
# Optional
|
||||
load_plugins: [incompatible_plugin_api]
|
||||
15
test/confs/plugins/multiple_source_plugins.yaml
Normal file
15
test/confs/plugins/multiple_source_plugins.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
stdout_output:
|
||||
enabled: true
|
||||
|
||||
plugins:
|
||||
- name: cloudtrail
|
||||
library_path: BUILD_DIR/cloudtrail-plugin-prefix/src/cloudtrail-plugin/libcloudtrail.so
|
||||
init_config: ""
|
||||
open_params: "BUILD_DIR/test/trace_files/plugins/alice_start_instances.json"
|
||||
- name: test_source
|
||||
library_path: BUILD_DIR/test/plugins/libtest_source.so
|
||||
init_config: ""
|
||||
open_params: ""
|
||||
|
||||
# Optional
|
||||
load_plugins: [cloudtrail, test_source]
|
||||
17
test/confs/plugins/overlap_extract_sources.yaml
Normal file
17
test/confs/plugins/overlap_extract_sources.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
stdout_output:
|
||||
enabled: true
|
||||
|
||||
plugins:
|
||||
- name: test_source
|
||||
library_path: BUILD_DIR/test/plugins/libtest_source.so
|
||||
init_config: ""
|
||||
open_params: ""
|
||||
- name: test_extract_p1
|
||||
library_path: BUILD_DIR/test/plugins/libtest_extract_p1.so
|
||||
init_config: ""
|
||||
- name: test_extract_p2
|
||||
library_path: BUILD_DIR/test/plugins/libtest_extract_p2.so
|
||||
init_config: ""
|
||||
|
||||
# Optional
|
||||
load_plugins: [test_source, test_extract_p1, test_extract_p2]
|
||||
10
test/confs/plugins/wrong_plugin_path.yaml
Normal file
10
test/confs/plugins/wrong_plugin_path.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
stdout_output:
|
||||
enabled: true
|
||||
|
||||
plugins:
|
||||
- name: wrong_plugin_path
|
||||
library_path: BUILD_DIR/test/plugins/wrong_plugin_path.so
|
||||
init_config: ""
|
||||
|
||||
# Optional
|
||||
load_plugins: [wrong_plugin_path]
|
||||
@@ -49,6 +49,7 @@ trace_files: !mux
|
||||
detect: False
|
||||
rules_file:
|
||||
- ../rules/falco_rules.yaml
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/engine_v4_k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/trust_nginx_container.yaml
|
||||
trace_file: trace_files/k8s_audit/create_nginx_pod_privileged.json
|
||||
@@ -74,6 +75,7 @@ trace_files: !mux
|
||||
detect: False
|
||||
rules_file:
|
||||
- ../rules/falco_rules.yaml
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/engine_v4_k8s_audit_rules.yaml
|
||||
- ./rules/k8s_audit/trust_nginx_container.yaml
|
||||
trace_file: trace_files/k8s_audit/create_nginx_pod_hostnetwork.json
|
||||
@@ -632,3 +634,12 @@ trace_files: !mux
|
||||
- ../rules/k8s_audit_rules.yaml
|
||||
trace_file: trace_files/k8s_audit/fal_01_003.json
|
||||
stderr_contains: 'Could not read k8s audit event line #1, "{"kind": 0}": Data not recognized as a k8s audit event, stopping'
|
||||
|
||||
json_pointer_correct_parse:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- ./rules/k8s_audit/single_rule_with_json_pointer.yaml
|
||||
detect_counts:
|
||||
- json_pointer_example: 1
|
||||
trace_file: trace_files/k8s_audit/create_nginx_pod_unprivileged.json
|
||||
@@ -82,6 +82,7 @@ class FalcoTest(Test):
|
||||
|
||||
self.exit_status = self.params.get('exit_status', '*', default=0)
|
||||
self.should_detect = self.params.get('detect', '*', default=False)
|
||||
self.check_detection_counts = self.params.get('check_detection_counts', '*', default=True)
|
||||
self.trace_file = self.params.get('trace_file', '*', default='')
|
||||
|
||||
if self.trace_file and not os.path.isabs(self.trace_file):
|
||||
@@ -94,6 +95,7 @@ class FalcoTest(Test):
|
||||
'json_include_tags_property', '*', default=True)
|
||||
self.all_events = self.params.get('all_events', '*', default=False)
|
||||
self.priority = self.params.get('priority', '*', default='debug')
|
||||
self.addl_cmdline_opts = self.params.get('addl_cmdline_opts', '*', default='')
|
||||
self.rules_file = self.params.get(
|
||||
'rules_file', '*', default=os.path.join(self.basedir, '../rules/falco_rules.yaml'))
|
||||
|
||||
@@ -130,6 +132,7 @@ class FalcoTest(Test):
|
||||
|
||||
self.conf_file = self.params.get(
|
||||
'conf_file', '*', default=os.path.join(self.basedir, '../falco.yaml'))
|
||||
self.conf_file = self.conf_file.replace("BUILD_DIR", build_dir)
|
||||
if not os.path.isabs(self.conf_file):
|
||||
self.conf_file = os.path.join(self.basedir, self.conf_file)
|
||||
|
||||
@@ -521,10 +524,10 @@ class FalcoTest(Test):
|
||||
["md5sum", "/boot/config-{}".format(kernel_release)]).rstrip()
|
||||
config_hash = md5_output.split(" ")[0]
|
||||
|
||||
probe_filename = "falco-{}-{}-{}-{}.ko".format(
|
||||
driver_filename = "falco-{}-{}-{}-{}.ko".format(
|
||||
falco_version, arch, kernel_release, config_hash)
|
||||
driver_path = os.path.join(self.falcodir, "driver", "falco.ko")
|
||||
module_path = os.path.join(self.module_dir, probe_filename)
|
||||
module_path = os.path.join(self.module_dir, driver_filename)
|
||||
self.log.debug("Copying {} to {}".format(driver_path, module_path))
|
||||
shutil.copyfile(driver_path, module_path)
|
||||
|
||||
@@ -617,9 +620,9 @@ class FalcoTest(Test):
|
||||
self.log.debug("Converted Rules: {}".format(psp_rules))
|
||||
|
||||
# Run falco
|
||||
cmd = '{} {} {} -c {} {} -o json_output={} -o json_include_output_property={} -o json_include_tags_property={} -o priority={} -v'.format(
|
||||
cmd = '{} {} {} -c {} {} -o json_output={} -o json_include_output_property={} -o json_include_tags_property={} -o priority={} -v {}'.format(
|
||||
self.falco_binary_path, self.rules_args, self.disabled_args, self.conf_file, trace_arg, self.json_output,
|
||||
self.json_include_output_property, self.json_include_tags_property, self.priority)
|
||||
self.json_include_output_property, self.json_include_tags_property, self.priority, self.addl_cmdline_opts)
|
||||
|
||||
for tag in self.disable_tags:
|
||||
cmd += ' -T {}'.format(tag)
|
||||
@@ -650,13 +653,13 @@ class FalcoTest(Test):
|
||||
self.fail("Stdout was not exactly {}".format(self.stderr_is))
|
||||
|
||||
for pattern in self.stderr_contains:
|
||||
match = re.search(pattern, res.stderr.decode("utf-8"))
|
||||
match = re.search(pattern, res.stderr.decode("utf-8"), re.DOTALL)
|
||||
if match is None:
|
||||
self.fail(
|
||||
"Stderr of falco process did not contain content matching {}".format(pattern))
|
||||
|
||||
for pattern in self.stdout_contains:
|
||||
match = re.search(pattern, res.stdout.decode("utf-8"))
|
||||
match = re.search(pattern, res.stdout.decode("utf-8"), re.DOTALL)
|
||||
if match is None:
|
||||
self.fail("Stdout of falco process '{}' did not contain content matching {}".format(
|
||||
res.stdout.decode("utf-8"), pattern))
|
||||
@@ -684,7 +687,7 @@ class FalcoTest(Test):
|
||||
self.check_rules_warnings(res)
|
||||
if len(self.rules_events) > 0:
|
||||
self.check_rules_events(res)
|
||||
if len(self.validate_rules_file) == 0:
|
||||
if len(self.validate_rules_file) == 0 and self.check_detection_counts:
|
||||
self.check_detections(res)
|
||||
if len(self.detect_counts) > 0:
|
||||
self.check_detections_by_rule(res)
|
||||
|
||||
@@ -32,20 +32,10 @@ trace_files: !mux
|
||||
- leading_not
|
||||
- not_equals_at_end
|
||||
- not_at_end
|
||||
- not_before_trailing_evttype
|
||||
- not_equals_before_trailing_evttype
|
||||
- not_equals_and_not
|
||||
- not_equals_before_in
|
||||
- not_before_in
|
||||
- not_in_before_in
|
||||
- leading_in_not_equals_before_evttype
|
||||
- leading_in_not_equals_at_evttype
|
||||
- not_with_evttypes
|
||||
- not_with_evttypes_addl
|
||||
- not_equals_before_evttype
|
||||
- not_equals_before_in_evttype
|
||||
- not_before_evttype
|
||||
- not_before_evttype_using_in
|
||||
rules_events:
|
||||
- no_warnings: [execve]
|
||||
- no_evttype: [all]
|
||||
@@ -54,8 +44,8 @@ trace_files: !mux
|
||||
- not_equals_after_evttype: [execve]
|
||||
- not_after_evttype: [execve]
|
||||
- leading_trailing_evttypes: [execve,open]
|
||||
- leading_multtrailing_evttypes: [connect,execve,open]
|
||||
- leading_multtrailing_evttypes_using_in: [connect,execve,open]
|
||||
- leading_multitrailing_evttypes: [connect,execve,open]
|
||||
- leading_multitrailing_evttypes_using_in: [connect,execve,open]
|
||||
- not_equals_at_end: [all]
|
||||
- not_at_end: [all]
|
||||
- not_before_trailing_evttype: [all]
|
||||
@@ -364,7 +354,7 @@ trace_files: !mux
|
||||
exit_status: 1
|
||||
stdout_is: |+
|
||||
1 errors:
|
||||
Rule must have exceptions or condition property
|
||||
Appended rule must have exceptions or condition property
|
||||
---
|
||||
- rule: no condition rule
|
||||
append: true
|
||||
@@ -644,6 +634,20 @@ trace_files: !mux
|
||||
rules_file:
|
||||
- rules/single_rule_enabled_flag.yaml
|
||||
trace_file: trace_files/cat_write.scap
|
||||
|
||||
disabled_rule_using_false_enabled_flag_only:
|
||||
detect: False
|
||||
rules_file:
|
||||
- rules/disabled_rule_using_enabled_flag_only.yaml
|
||||
trace_file: trace_files/cat_write.scap
|
||||
|
||||
enabled_rule_using_false_enabled_flag_only:
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- rules/enabled_rule_using_enabled_flag_only.yaml
|
||||
trace_file: trace_files/cat_write.scap
|
||||
stdout_contains: "Warning An open was seen"
|
||||
|
||||
disabled_and_enabled_rules_1:
|
||||
exit_status: 1
|
||||
@@ -1142,6 +1146,8 @@ trace_files: !mux
|
||||
detect_level: INFO
|
||||
rules_file:
|
||||
- rules/syscalls.yaml
|
||||
rules_warning:
|
||||
- detect_madvise
|
||||
detect_counts:
|
||||
- detect_madvise: 2
|
||||
- detect_open: 2
|
||||
@@ -1160,7 +1166,8 @@ trace_files: !mux
|
||||
|
||||
skip_unknown_noevt:
|
||||
detect: False
|
||||
stdout_contains: Skipping rule "Contains Unknown Event And Skipping". contains unknown filter proc.nobody
|
||||
rules_warning:
|
||||
- Contains Unknown Event And Skipping
|
||||
rules_file:
|
||||
- rules/skip_unknown_evt.yaml
|
||||
trace_file: trace_files/cat_write.scap
|
||||
@@ -1175,7 +1182,7 @@ trace_files: !mux
|
||||
exit_status: 1
|
||||
stderr_contains: |+
|
||||
Could not load rules file.*skip_unknown_error.yaml: 1 errors:
|
||||
rule "Contains Unknown Event And Not Skipping". contains unknown filter proc.nobody
|
||||
Rule Contains Unknown Event And Not Skipping: error filter_check called with nonexistent field proc.nobody
|
||||
---
|
||||
- rule: Contains Unknown Event And Not Skipping
|
||||
desc: Contains an unknown event
|
||||
@@ -1192,7 +1199,7 @@ trace_files: !mux
|
||||
exit_status: 1
|
||||
stderr_contains: |+
|
||||
Could not load rules file .*skip_unknown_unspec.yaml: 1 errors:
|
||||
rule "Contains Unknown Event And Unspecified". contains unknown filter proc.nobody
|
||||
Rule Contains Unknown Event And Unspecified: error filter_check called with nonexistent field proc.nobody
|
||||
---
|
||||
- rule: Contains Unknown Event And Unspecified
|
||||
desc: Contains an unknown event
|
||||
|
||||
@@ -177,10 +177,18 @@ trace_files: !mux
|
||||
trace_file: trace_files/cat_write.scap
|
||||
|
||||
rule_exception_append_item_not_in_rule:
|
||||
exit_status: 0
|
||||
stderr_contains: |+
|
||||
1 warnings:
|
||||
Rule My Rule with append=true: no set of fields matching name ex2
|
||||
exit_status: 1
|
||||
stdout_is: |+
|
||||
1 errors:
|
||||
Rule exception new item ex2: must have fields property with a list of fields
|
||||
---
|
||||
- rule: My Rule
|
||||
exceptions:
|
||||
- name: ex2
|
||||
values:
|
||||
- [apache, /tmp]
|
||||
append: true
|
||||
---
|
||||
validate_rules_file:
|
||||
- rules/exceptions/append_item_not_in_rule.yaml
|
||||
trace_file: trace_files/cat_write.scap
|
||||
@@ -311,4 +319,35 @@ trace_files: !mux
|
||||
- rules/exceptions/rule_exception_single_field_append.yaml
|
||||
trace_file: trace_files/cat_write.scap
|
||||
|
||||
rule_exception_new_single_field_append:
|
||||
detect: False
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- rules/exceptions/rule_exception_new_single_field_append.yaml
|
||||
trace_file: trace_files/cat_write.scap
|
||||
|
||||
rule_exception_new_second_field_append:
|
||||
detect: False
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- rules/exceptions/rule_exception_new_second_field_append.yaml
|
||||
trace_file: trace_files/cat_write.scap
|
||||
|
||||
rule_exception_new_append_no_field:
|
||||
exit_status: 1
|
||||
stdout_is: |+
|
||||
1 errors:
|
||||
Rule exception new item proc_cmdline: must have fields property with a list of fields
|
||||
---
|
||||
- rule: Open From Cat
|
||||
exceptions:
|
||||
- name: proc_cmdline
|
||||
comps: in
|
||||
values:
|
||||
- "cat /dev/null"
|
||||
append: true
|
||||
---
|
||||
validate_rules_file:
|
||||
- rules/exceptions/rule_exception_new_no_field_append.yaml
|
||||
trace_file: trace_files/cat_write.scap
|
||||
|
||||
|
||||
106
test/falco_tests_plugins.yaml
Normal file
106
test/falco_tests_plugins.yaml
Normal file
@@ -0,0 +1,106 @@
|
||||
#
|
||||
# Copyright (C) 2021 The Falco Authors.
|
||||
#
|
||||
# This file is part of Falco.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with 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.
|
||||
#
|
||||
|
||||
trace_files: !mux
|
||||
|
||||
list_plugins:
|
||||
check_detection_counts: False
|
||||
rules_file:
|
||||
- rules/plugins/cloudtrail_create_instances.yaml
|
||||
conf_file: BUILD_DIR/test/confs/plugins/cloudtrail_json_create_instances.yaml
|
||||
addl_cmdline_opts: --list-plugins
|
||||
stdout_contains: "2 Plugins Loaded.*Name: cloudtrail.*Type: source plugin.*Name: json.*Type: extractor plugin"
|
||||
|
||||
list_plugin_fields:
|
||||
check_detection_counts: False
|
||||
rules_file:
|
||||
- rules/plugins/cloudtrail_create_instances.yaml
|
||||
conf_file: BUILD_DIR/test/confs/plugins/cloudtrail_json_create_instances.yaml
|
||||
addl_cmdline_opts: --list
|
||||
stdout_contains: "ct.id"
|
||||
|
||||
detect_create_instance:
|
||||
detect: True
|
||||
detect_level: INFO
|
||||
rules_file:
|
||||
- rules/plugins/cloudtrail_create_instances.yaml
|
||||
detect_counts:
|
||||
- 'Cloudtrail Create Instance': 1
|
||||
conf_file: BUILD_DIR/test/confs/plugins/cloudtrail_json_create_instances.yaml
|
||||
|
||||
detect_create_instance_bigevent:
|
||||
detect: True
|
||||
detect_level: INFO
|
||||
rules_file:
|
||||
- rules/plugins/cloudtrail_create_instances.yaml
|
||||
detect_counts:
|
||||
- 'Cloudtrail Create Instance': 1
|
||||
conf_file: BUILD_DIR/test/confs/plugins/cloudtrail_json_create_instances_bigevent.yaml
|
||||
|
||||
multiple_source_plugins:
|
||||
exit_status: 1
|
||||
stderr_contains: "Runtime error: Can not load multiple source plugins. cloudtrail already loaded. Exiting."
|
||||
conf_file: BUILD_DIR/test/confs/plugins/multiple_source_plugins.yaml
|
||||
rules_file:
|
||||
- rules/plugins/cloudtrail_create_instances.yaml
|
||||
|
||||
incompatible_extract_sources:
|
||||
exit_status: 1
|
||||
stderr_contains: "Runtime error: Extractor plugin not compatible with event source aws_cloudtrail. Exiting."
|
||||
conf_file: BUILD_DIR/test/confs/plugins/incompatible_extract_sources.yaml
|
||||
rules_file:
|
||||
- rules/plugins/cloudtrail_create_instances.yaml
|
||||
|
||||
overlap_extract_sources:
|
||||
exit_status: 1
|
||||
stderr_contains: "Runtime error: Extractor plugins have overlapping compatible event source test_source. Exiting."
|
||||
conf_file: BUILD_DIR/test/confs/plugins/overlap_extract_sources.yaml
|
||||
rules_file:
|
||||
- rules/plugins/cloudtrail_create_instances.yaml
|
||||
|
||||
incompat_plugin_api:
|
||||
exit_status: 1
|
||||
stderr_contains: "Unsupported plugin required api version 10000000.0.0"
|
||||
conf_file: BUILD_DIR/test/confs/plugins/incompatible_plugin_api.yaml
|
||||
rules_file:
|
||||
- rules/plugins/cloudtrail_create_instances.yaml
|
||||
|
||||
incompat_plugin_rules_version:
|
||||
exit_status: 1
|
||||
stderr_contains: "Runtime error: Plugin cloudtrail version .* not compatible with required plugin version 100000.0.0. Exiting."
|
||||
conf_file: BUILD_DIR/test/confs/plugins/cloudtrail_json_create_instances.yaml
|
||||
rules_file:
|
||||
- rules/plugins/cloudtrail_incompat_plugin_version.yaml
|
||||
|
||||
wrong_plugin_path:
|
||||
exit_status: 1
|
||||
stderr_contains: "error loading plugin.*No such file or directory. Exiting"
|
||||
conf_file: BUILD_DIR/test/confs/plugins/wrong_plugin_path.yaml
|
||||
rules_file:
|
||||
- rules/plugins/cloudtrail_incompat_plugin_version.yaml
|
||||
|
||||
no_plugins_unknown_source:
|
||||
detect: False
|
||||
rules_file:
|
||||
- rules/plugins/cloudtrail_create_instances.yaml
|
||||
trace_file: trace_files/empty.scap
|
||||
rules_warning:
|
||||
- Cloudtrail Create Instance
|
||||
stderr_contains: "Rule Cloudtrail Create Instance: warning .unknown-source.: unknown source aws_cloudtrail, skipping"
|
||||
|
||||
|
||||
@@ -111,12 +111,17 @@ traces: !mux
|
||||
detect_counts:
|
||||
- "Read sensitive file untrusted": 1
|
||||
|
||||
# This should *not* generate any falco alerts as of the changes in
|
||||
# https://github.com/falcosecurity/libs/pull/94--the execve event in
|
||||
# this trace file is PPME_SYSCALL_EXECVE_18, which was deprecated by
|
||||
# PPME_SYSCALL_EXECVE_19 in 2018.
|
||||
#
|
||||
# This activity in this trace file overlaps with the activity in
|
||||
# falco-event-generator.scap so the rule is still being tested.
|
||||
run-shell-untrusted:
|
||||
trace_file: traces-positive/run-shell-untrusted.scap
|
||||
detect: True
|
||||
detect: False
|
||||
detect_level: DEBUG
|
||||
detect_counts:
|
||||
- "Run shell untrusted": 1
|
||||
|
||||
system-binaries-network-activity:
|
||||
trace_file: traces-positive/system-binaries-network-activity.scap
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2019 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with 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.
|
||||
#
|
||||
|
||||
require(jsonlite)
|
||||
library(ggplot2)
|
||||
library(GetoptLong)
|
||||
|
||||
initial.options <- commandArgs(trailingOnly = FALSE)
|
||||
file.arg.name <- "--file="
|
||||
script.name <- sub(file.arg.name, "", initial.options[grep(file.arg.name, initial.options)])
|
||||
script.basename <- dirname(script.name)
|
||||
|
||||
if (substr(script.basename, 1, 1) != '/') {
|
||||
script.basename = paste(getwd(), script.basename, sep='/')
|
||||
}
|
||||
|
||||
results = paste(script.basename, "results.json", sep='/')
|
||||
output = "./output.png"
|
||||
metric = "cpu"
|
||||
|
||||
GetoptLong(
|
||||
"results=s", "Path to results file",
|
||||
"benchmark=s", "Benchmark from results file to graph",
|
||||
"variant=s@", "Variant(s) to include in graph. Can be specified multiple times",
|
||||
"output=s", "Output graph file",
|
||||
"metric=s", "Metric to graph. Can be one of (cpu|drops)"
|
||||
)
|
||||
|
||||
if (metric == "cpu") {
|
||||
data_metric="cpu_usage"
|
||||
yaxis_label="CPU Usage (%)"
|
||||
title="Falco/Sysdig/Multimatch CPU Usage: %s"
|
||||
} else if (metric == "drops") {
|
||||
data_metric="drop_pct"
|
||||
yaxis_label="Event Drops (%)"
|
||||
title="Falco/Sysdig/Multimatch Event Drops: %s"
|
||||
}
|
||||
|
||||
res <- fromJSON(results, flatten=TRUE)
|
||||
|
||||
res2 = res[res$benchmark == benchmark & res$variant %in% variant,]
|
||||
|
||||
plot <- ggplot(data=res2, aes(x=sample, y=get(data_metric), group=variant, colour=variant)) +
|
||||
geom_line() +
|
||||
ylab(yaxis_label) +
|
||||
xlab("Time") +
|
||||
ggtitle(sprintf(title, benchmark))
|
||||
theme(legend.position=c(.2, .88));
|
||||
|
||||
print(paste("Writing graph to", output, sep=" "))
|
||||
ggsave(file=output)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2019 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with 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.
|
||||
#
|
||||
|
||||
require(jsonlite)
|
||||
library(ggplot2)
|
||||
library(reshape)
|
||||
|
||||
res <- fromJSON("/home/mstemm/results.txt", flatten=TRUE)
|
||||
|
||||
plot <- ggplot(data=res, aes(x=config, y=elapsed.real)) +
|
||||
geom_bar(stat = "summary", fun.y = "mean") +
|
||||
coord_flip() +
|
||||
facet_grid(shortfile ~ .) +
|
||||
ylab("Wall Clock Time (sec)") +
|
||||
xlab("Trace File/Program")
|
||||
|
||||
|
||||
ggsave(file="/mnt/sf_mstemm/res-real.png")
|
||||
|
||||
plot <- ggplot(data=res, aes(x=config, y=elapsed.user)) +
|
||||
geom_bar(stat = "summary", fun.y = "mean") +
|
||||
coord_flip() +
|
||||
facet_grid(shortfile ~ .) +
|
||||
ylab("User Time (sec)") +
|
||||
xlab("Trace File/Program")
|
||||
|
||||
|
||||
ggsave(file="/mnt/sf_mstemm/res-user.png")
|
||||
|
||||
res2 <- melt(res, id.vars = c("config", "shortfile"), measure.vars = c("elapsed.sys", "elapsed.user"))
|
||||
plot <- ggplot(data=res2, aes(x=config, y=value, fill=variable, order=variable)) +
|
||||
geom_bar(stat = "summary", fun.y = "mean") +
|
||||
coord_flip() +
|
||||
facet_grid(shortfile ~ .) +
|
||||
ylab("User/System Time (sec)") +
|
||||
xlab("Trace File/Program")
|
||||
|
||||
ggsave(file="/mnt/sf_mstemm/res-sys-user.png")
|
||||
13
test/plugins/CMakeLists.txt
Normal file
13
test/plugins/CMakeLists.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
add_library(test_extract_p1 SHARED test_extract.cpp)
|
||||
add_library(test_extract_p2 SHARED test_extract.cpp)
|
||||
add_library(test_source SHARED test_source.cpp)
|
||||
add_library(test_incompat_api SHARED incompat_api.cpp)
|
||||
|
||||
target_include_directories(
|
||||
test_extract_p1 PUBLIC "${LIBSCAP_INCLUDE_DIRS}")
|
||||
|
||||
target_include_directories(
|
||||
test_extract_p2 PUBLIC "${LIBSCAP_INCLUDE_DIRS}")
|
||||
|
||||
target_include_directories(
|
||||
test_source PUBLIC "${LIBSCAP_INCLUDE_DIRS}")
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2019 The Falco Authors.
|
||||
Copyright (C) 2021 The Falco Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -14,7 +14,15 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define FALCO_ENGINE_LUA_DIR "${FALCO_ABSOLUTE_SHARE_DIR}/lua/"
|
||||
#define FALCO_ENGINE_SOURCE_LUA_DIR "${PROJECT_SOURCE_DIR}/userspace/engine/lua/"
|
||||
// Don't need any function other than plugin_get_required_api_version,
|
||||
// plugin load will fail after that.
|
||||
static const char *pl_required_api_version = "10000000.0.0";
|
||||
|
||||
extern "C"
|
||||
const char* plugin_get_required_api_version()
|
||||
{
|
||||
return pl_required_api_version;
|
||||
}
|
||||
116
test/plugins/test_extract.cpp
Normal file
116
test/plugins/test_extract.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
Copyright (C) 2021 The Falco Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <plugin_info.h>
|
||||
|
||||
static const char *pl_required_api_version = "0.1.0";
|
||||
static uint32_t pl_type = TYPE_EXTRACTOR_PLUGIN;
|
||||
static const char *pl_name_base = "test_extract";
|
||||
static char pl_name[1024];
|
||||
static const char *pl_desc = "Test Plugin For Regression Tests";
|
||||
static const char *pl_contact = "github.com/falcosecurity/falco";
|
||||
static const char *pl_version = "0.1.0";
|
||||
static const char *pl_extract_sources = "[\"test_source\"]";
|
||||
static const char *pl_fields = "[]";
|
||||
|
||||
// This struct represents the state of a plugin. Just has a placeholder string value.
|
||||
typedef struct plugin_state
|
||||
{
|
||||
} plugin_state;
|
||||
|
||||
extern "C"
|
||||
const char* plugin_get_required_api_version()
|
||||
{
|
||||
return pl_required_api_version;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
uint32_t plugin_get_type()
|
||||
{
|
||||
return pl_type;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* plugin_get_name()
|
||||
{
|
||||
// Add a random-ish suffix to the end, as some tests load
|
||||
// multiple copies of this plugin
|
||||
snprintf(pl_name, sizeof(pl_name)-1, "%s%ld\n", pl_name_base, random());
|
||||
return pl_name;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* plugin_get_description()
|
||||
{
|
||||
return pl_desc;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* plugin_get_contact()
|
||||
{
|
||||
return pl_contact;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* plugin_get_version()
|
||||
{
|
||||
return pl_version;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* plugin_get_extract_event_sources()
|
||||
{
|
||||
return pl_extract_sources;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* plugin_get_fields()
|
||||
{
|
||||
return pl_fields;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* plugin_get_last_error(ss_plugin_t* s)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
ss_plugin_t* plugin_init(const char* config, int32_t* rc)
|
||||
{
|
||||
// Note: Using new/delete is okay, as long as the plugin
|
||||
// framework is not deleting the memory.
|
||||
plugin_state *ret = new plugin_state();
|
||||
*rc = SS_PLUGIN_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void plugin_destroy(ss_plugin_t* s)
|
||||
{
|
||||
plugin_state *ps = (plugin_state *) s;
|
||||
|
||||
delete(ps);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int32_t plugin_extract_fields(ss_plugin_t *s, const ss_plugin_event *evt, uint32_t num_fields, ss_plugin_extract_field *fields)
|
||||
{
|
||||
return SS_PLUGIN_SUCCESS;
|
||||
}
|
||||
161
test/plugins/test_source.cpp
Normal file
161
test/plugins/test_source.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
Copyright (C) 2021 The Falco Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with 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 <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <plugin_info.h>
|
||||
|
||||
static const char *pl_required_api_version = "0.1.0";
|
||||
static uint32_t pl_type = TYPE_SOURCE_PLUGIN;
|
||||
static uint32_t pl_id = 999;
|
||||
static const char *pl_name = "test_source";
|
||||
static const char *pl_desc = "Test Plugin For Regression Tests";
|
||||
static const char *pl_contact = "github.com/falcosecurity/falco";
|
||||
static const char *pl_version = "0.1.0";
|
||||
static const char *pl_event_source = "test_source";
|
||||
static const char *pl_fields = "[]";
|
||||
|
||||
// This struct represents the state of a plugin. Just has a placeholder string value.
|
||||
typedef struct plugin_state
|
||||
{
|
||||
} plugin_state;
|
||||
|
||||
typedef struct instance_state
|
||||
{
|
||||
} instance_state;
|
||||
|
||||
extern "C"
|
||||
const char* plugin_get_required_api_version()
|
||||
{
|
||||
return pl_required_api_version;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
uint32_t plugin_get_type()
|
||||
{
|
||||
return pl_type;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
uint32_t plugin_get_id()
|
||||
{
|
||||
return pl_id;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* plugin_get_name()
|
||||
{
|
||||
return pl_name;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* plugin_get_description()
|
||||
{
|
||||
return pl_desc;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* plugin_get_contact()
|
||||
{
|
||||
return pl_contact;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* plugin_get_version()
|
||||
{
|
||||
return pl_version;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* plugin_get_event_source()
|
||||
{
|
||||
return pl_event_source;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* plugin_get_fields()
|
||||
{
|
||||
return pl_fields;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* plugin_get_last_error(ss_plugin_t* s)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
ss_plugin_t* plugin_init(const char* config, int32_t* rc)
|
||||
{
|
||||
// Note: Using new/delete is okay, as long as the plugin
|
||||
// framework is not deleting the memory.
|
||||
plugin_state *ret = new plugin_state();
|
||||
|
||||
*rc = SS_PLUGIN_SUCCESS;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void plugin_destroy(ss_plugin_t* s)
|
||||
{
|
||||
plugin_state *ps = (plugin_state *) s;
|
||||
|
||||
delete(ps);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
ss_instance_t* plugin_open(ss_plugin_t* s, const char* params, int32_t* rc)
|
||||
{
|
||||
// Note: Using new/delete is okay, as long as the plugin
|
||||
// framework is not deleting the memory.
|
||||
instance_state *ret = new instance_state();
|
||||
*rc = SS_PLUGIN_SUCCESS;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void plugin_close(ss_plugin_t* s, ss_instance_t* i)
|
||||
{
|
||||
instance_state *istate = (instance_state *) i;
|
||||
|
||||
delete(istate);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int32_t plugin_next_batch(ss_plugin_t* s, ss_instance_t* i, uint32_t *nevts, ss_plugin_event **evts)
|
||||
{
|
||||
return SS_PLUGIN_EOF;
|
||||
}
|
||||
|
||||
// This plugin does not implement plugin_next_batch, due to the lower
|
||||
// overhead of calling C functions from the plugin framework compared
|
||||
// to calling Go functions.
|
||||
|
||||
extern "C"
|
||||
const char *plugin_event_to_string(ss_plugin_t *s, const uint8_t *data, uint32_t datalen)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int32_t plugin_extract_fields(ss_plugin_t *s, const ss_plugin_event *evt, uint32_t num_fields, ss_plugin_extract_field *fields)
|
||||
{
|
||||
return SS_PLUGIN_SUCCESS;
|
||||
}
|
||||
24
test/rules/disabled_rule_using_enabled_flag_only.yaml
Normal file
24
test/rules/disabled_rule_using_enabled_flag_only.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
#
|
||||
# Copyright (C) 2021 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with 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.
|
||||
#
|
||||
- rule: open_from_cat
|
||||
desc: A process named cat does an open
|
||||
condition: evt.type=open and proc.name=cat
|
||||
output: "An open was seen"
|
||||
priority: WARNING
|
||||
|
||||
- rule: open_from_cat
|
||||
enabled: false
|
||||
25
test/rules/enabled_rule_using_enabled_flag_only.yaml
Normal file
25
test/rules/enabled_rule_using_enabled_flag_only.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# Copyright (C) 2021 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with 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.
|
||||
#
|
||||
- rule: open_from_cat
|
||||
desc: A process named cat does an open
|
||||
condition: evt.type=open and proc.name=cat
|
||||
output: "An open was seen"
|
||||
priority: WARNING
|
||||
enabled: false
|
||||
|
||||
- rule: open_from_cat
|
||||
enabled: true
|
||||
@@ -1,6 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (C) 2019 The Falco Authors.
|
||||
# Copyright (C) 2021 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -16,10 +15,17 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
SUBJ_PID=$1
|
||||
BENCHMARK=$2
|
||||
VARIANT=$3
|
||||
RESULTS_FILE=$4
|
||||
CPU_INTERVAL=$5
|
||||
- rule: Open From Cat
|
||||
desc: A process named cat does an open
|
||||
condition: evt.type=open and proc.name=cat
|
||||
output: "An open was seen (command=%proc.cmdline)"
|
||||
priority: WARNING
|
||||
|
||||
- rule: Open From Cat
|
||||
exceptions:
|
||||
- name: proc_cmdline
|
||||
comps: in
|
||||
values:
|
||||
- "cat /dev/null"
|
||||
append: true
|
||||
|
||||
top -d $CPU_INTERVAL -b -p $SUBJ_PID | grep -E '(falco|sysdig|dragent|test_mm)' --line-buffered | awk -v benchmark=$BENCHMARK -v variant=$VARIANT '{printf("{\"time\": \"%s\", \"sample\": %d, \"benchmark\": \"%s\", \"variant\": \"%s\", \"cpu_usage\": %s},\n", strftime("%Y-%m-%d %H:%M:%S", systime(), 1), NR, benchmark, variant, $9); fflush();}' >> $RESULTS_FILE
|
||||
@@ -0,0 +1,39 @@
|
||||
#
|
||||
# Copyright (C) 2021 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with 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.
|
||||
#
|
||||
|
||||
- rule: Open From Cat
|
||||
desc: A process named cat does an open
|
||||
condition: evt.type=open and proc.name=cat
|
||||
output: "An open was seen (command=%proc.cmdline)"
|
||||
exceptions:
|
||||
- name: proc_cmdline
|
||||
fields: proc.cmdline
|
||||
comps: in
|
||||
values:
|
||||
- cat /dev/zero
|
||||
priority: WARNING
|
||||
|
||||
- rule: Open From Cat
|
||||
exceptions:
|
||||
- name: proc_cmdline_2
|
||||
fields: proc.cmdline
|
||||
comps: in
|
||||
values:
|
||||
- "cat /dev/null"
|
||||
append: true
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#
|
||||
# Copyright (C) 2021 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with 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.
|
||||
#
|
||||
|
||||
- rule: Open From Cat
|
||||
desc: A process named cat does an open
|
||||
condition: evt.type=open and proc.name=cat
|
||||
output: "An open was seen (command=%proc.cmdline)"
|
||||
priority: WARNING
|
||||
|
||||
- rule: Open From Cat
|
||||
exceptions:
|
||||
- name: proc_cmdline
|
||||
fields: proc.cmdline
|
||||
comps: in
|
||||
values:
|
||||
- "cat /dev/null"
|
||||
append: true
|
||||
|
||||
|
||||
@@ -56,13 +56,13 @@
|
||||
output: "None"
|
||||
priority: WARNING
|
||||
|
||||
- rule: leading_multtrailing_evttypes
|
||||
- rule: leading_multitrailing_evttypes
|
||||
desc: one evttype at beginning, multiple at end
|
||||
condition: evt.type=execve and proc.name=foo or evt.type=open or evt.type=connect
|
||||
output: "None"
|
||||
priority: WARNING
|
||||
|
||||
- rule: leading_multtrailing_evttypes_using_in
|
||||
- rule: leading_multitrailing_evttypes_using_in
|
||||
desc: one evttype at beginning, multiple at end, using in
|
||||
condition: evt.type=execve and proc.name=foo or evt.type in (open, connect)
|
||||
output: "None"
|
||||
|
||||
@@ -1,2 +1,24 @@
|
||||
#
|
||||
# Copyright (C) 2021 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with 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.
|
||||
#
|
||||
- rule: no condition rule
|
||||
desc: simpe rule
|
||||
condition: evt.type=open
|
||||
output: simple output
|
||||
priority: WARNING
|
||||
|
||||
- rule: no condition rule
|
||||
append: true
|
||||
@@ -246,7 +246,7 @@
|
||||
tags: [k8s]
|
||||
|
||||
# Detect any attempt to create a ClusterRoleBinding to the cluster-admin user
|
||||
# (exapand this to any built-in cluster role that does "sensitive" things)
|
||||
# (expand this to any built-in cluster role that does "sensitive" things)
|
||||
- rule: Attach to cluster-admin Role
|
||||
desc: Detect any attempt to create a ClusterRoleBinding to the cluster-admin user
|
||||
condition: kevt and clusterrolebinding and kcreate and ka.req.binding.role=cluster-admin
|
||||
|
||||
23
test/rules/k8s_audit/single_rule_with_json_pointer.yaml
Normal file
23
test/rules/k8s_audit/single_rule_with_json_pointer.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
#
|
||||
# Copyright (C) 2021 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with 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.
|
||||
#
|
||||
|
||||
- rule: json_pointer_example
|
||||
desc: A rule example using JSON Pointer (RFC 6901)
|
||||
condition: jevt.value[/annotations/authorization.k8s.io~1decision] exists and not (jevt.value[/a~1~0b] exists)
|
||||
output: "JSON Pointer Test Alert"
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
6
test/rules/plugins/cloudtrail_create_instances.yaml
Normal file
6
test/rules/plugins/cloudtrail_create_instances.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
- rule: Cloudtrail Create Instance
|
||||
desc: Detect Creating an EC2 Instance
|
||||
condition: evt.num > 0 and ct.name="StartInstances"
|
||||
output: EC2 Instance Created (evtnum=%evt.num info=%evt.plugininfo id=%ct.id user name=%json.value[/userIdentity/userName])
|
||||
priority: INFO
|
||||
source: aws_cloudtrail
|
||||
10
test/rules/plugins/cloudtrail_incompat_plugin_version.yaml
Normal file
10
test/rules/plugins/cloudtrail_incompat_plugin_version.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
- required_plugin_versions:
|
||||
- name: cloudtrail
|
||||
version: 100000.0.0
|
||||
|
||||
- rule: Cloudtrail Create Instance
|
||||
desc: Detect Creating an EC2 Instance
|
||||
condition: evt.num > 0 and ct.name="StartInstances"
|
||||
output: EC2 Instance Created (evtnum=%evt.num info=%evt.plugininfo id=%ct.id user name=%json.value[/userIdentity/userName])
|
||||
priority: INFO
|
||||
source: aws_cloudtrail
|
||||
@@ -16,10 +16,10 @@
|
||||
#
|
||||
- rule: my_rule
|
||||
desc: A process named cat does an open
|
||||
condition: evt.type=open and fd.name=not-a-real-file
|
||||
condition: (evt.type=open and fd.name=not-a-real-file)
|
||||
output: "An open of /dev/null was seen (command=%proc.cmdline)"
|
||||
priority: WARNING
|
||||
|
||||
- rule: my_rule
|
||||
append: true
|
||||
condition: or fd.name=/dev/null
|
||||
condition: or (evt.type=open and fd.name=/dev/null)
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
- macro: open_read
|
||||
condition: (evt.type=open or evt.type=openat) and evt.is_open_read=true and fd.typechar='f'
|
||||
condition: evt.type in (open,openat,openat2) and evt.is_open_read=true and fd.typechar='f'
|
||||
|
||||
- rule: open_1
|
||||
desc: open one
|
||||
|
||||
@@ -1,444 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (C) 2019 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with 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.
|
||||
#
|
||||
|
||||
#set -x
|
||||
|
||||
trap "cleanup; exit" SIGHUP SIGINT SIGTERM
|
||||
|
||||
TRACE_FILES_BASE_URL=${TRACE_FILES_BASE_URL:-"https://download.falco.org/fixtures/trace-files/"}
|
||||
|
||||
function download_trace_files() {
|
||||
|
||||
(mkdir -p $TRACEDIR && rm -rf $TRACEDIR/traces-perf && curl -fo $TRACEDIR/traces-perf.zip "${TRACE_FILES_BASE_URL}traces-perf.zip" && unzip -d $TRACEDIR $TRACEDIR/traces-perf.zip && rm -f $TRACEDIR/traces-perf.zip) || exit 1
|
||||
|
||||
}
|
||||
|
||||
function time_cmd() {
|
||||
cmd="$1"
|
||||
file="$2"
|
||||
|
||||
benchmark=`basename $file .scap`
|
||||
|
||||
echo -n "$benchmark: "
|
||||
for i in `seq 1 5`; do
|
||||
echo -n "$i "
|
||||
time=`date --iso-8601=sec`
|
||||
/usr/bin/time -a -o $RESULTS_FILE --format "{\"time\": \"$time\", \"benchmark\": \"$benchmark\", \"file\": \"$file\", \"variant\": \"$VARIANT\", \"elapsed\": {\"real\": %e, \"user\": %U, \"sys\": %S}}," $cmd >> $OUTPUT_FILE 2>&1
|
||||
done
|
||||
echo ""
|
||||
}
|
||||
|
||||
function run_falco_on() {
|
||||
file="$1"
|
||||
|
||||
if [ -z $RULES_FILE ]; then
|
||||
RULES_FILE=$SOURCE/rules/falco_rules.yaml
|
||||
fi
|
||||
|
||||
cmd="$ROOT/userspace/falco/falco -c $SOURCE/falco.yaml -r $SOURCE/rules/falco_rules.yaml --option=stdout_output.enabled=false -e $file -A"
|
||||
|
||||
time_cmd "$cmd" "$file"
|
||||
}
|
||||
|
||||
function run_sysdig_on() {
|
||||
file="$1"
|
||||
|
||||
cmd="$ROOT/userspace/sysdig/sysdig -N -z -r $file evt.type=none"
|
||||
|
||||
time_cmd "$cmd" "$file"
|
||||
}
|
||||
|
||||
function write_agent_config() {
|
||||
cat > $ROOT/userspace/dragent/dragent.yaml <<EOF
|
||||
customerid: XXX
|
||||
app_checks_enabled: false
|
||||
log:
|
||||
file_priority: info
|
||||
console_priority: info
|
||||
event_priority: info
|
||||
jmx:
|
||||
enabled: false
|
||||
statsd:
|
||||
enabled: false
|
||||
collector: collector-staging.sysdigcloud.com
|
||||
EOF
|
||||
|
||||
if [ $FALCO_AGENT == 1 ]; then
|
||||
cat >> $ROOT/userspace/dragent/dragent.yaml <<EOF
|
||||
falco_engine:
|
||||
enabled: true
|
||||
rules_filename: /etc/falco_rules.yaml
|
||||
sampling_multiplier: 0
|
||||
EOF
|
||||
else
|
||||
cat >> $ROOT/userspace/dragent/dragent.yaml <<EOF
|
||||
falco_engine:
|
||||
enabled: false
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ $AGENT_AUTODROP == 1 ]; then
|
||||
cat >> $ROOT/userspace/dragent/dragent.yaml <<EOF
|
||||
autodrop:
|
||||
enabled: true
|
||||
EOF
|
||||
else
|
||||
cat >> $ROOT/userspace/dragent/dragent.yaml <<EOF
|
||||
autodrop:
|
||||
enabled: false
|
||||
EOF
|
||||
fi
|
||||
|
||||
cat $ROOT/userspace/dragent/dragent.yaml
|
||||
}
|
||||
|
||||
function run_agent_on() {
|
||||
|
||||
file="$1"
|
||||
|
||||
write_agent_config
|
||||
|
||||
cmd="$ROOT/userspace/dragent/dragent -r $file"
|
||||
|
||||
time_cmd "$cmd" "$file"
|
||||
}
|
||||
|
||||
function run_trace() {
|
||||
|
||||
if [ ! -e $TRACEDIR ]; then
|
||||
download_trace_files
|
||||
fi
|
||||
|
||||
trace_file="$1"
|
||||
|
||||
if [ $trace_file == "all" ]; then
|
||||
files=($TRACEDIR/traces-perf/*.scap)
|
||||
else
|
||||
files=($TRACEDIR/traces-perf/$trace_file.scap)
|
||||
fi
|
||||
|
||||
for file in "${files[@]}"; do
|
||||
if [[ $ROOT == *"falco"* ]]; then
|
||||
run_falco_on "$file"
|
||||
elif [[ $ROOT == *"sysdig"* ]]; then
|
||||
run_sysdig_on "$file"
|
||||
else
|
||||
run_agent_on "$file"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
function start_monitor_cpu_usage() {
|
||||
echo " monitoring cpu usage for falcosecurity/falco program"
|
||||
|
||||
setsid bash `dirname $0`/cpu_monitor.sh $SUBJ_PID $live_test $VARIANT $RESULTS_FILE $CPU_INTERVAL &
|
||||
CPU_PID=$!
|
||||
sleep 5
|
||||
}
|
||||
|
||||
function start_subject_prog() {
|
||||
|
||||
# Do a blocking sudo command now just to ensure we have a password
|
||||
sudo bash -c ""
|
||||
|
||||
if [[ $ROOT == *"multimatch"* ]]; then
|
||||
echo " starting test_mm..."
|
||||
if [ -z $RULES_FILE ]; then
|
||||
RULES_FILE=$SOURCE/../output/rules.yaml
|
||||
fi
|
||||
sudo FALCO_STATS_EXTRA_variant=$VARIANT FALCO_STATS_EXTRA_benchmark=$live_test $ROOT/test_mm -S $SOURCE/search_order.yaml -s $STATS_FILE -r $RULES_FILE > ./prog-output.txt 2>&1 &
|
||||
elif [[ $ROOT == *"falco"* ]]; then
|
||||
echo " starting falco..."
|
||||
if [ -z $RULES_FILE ]; then
|
||||
RULES_FILE=$SOURCE/rules/falco_rules.yaml
|
||||
fi
|
||||
sudo FALCO_STATS_EXTRA_variant=$VARIANT FALCO_STATS_EXTRA_benchmark=$live_test $ROOT/userspace/falco/falco -c $SOURCE/falco.yaml -s $STATS_FILE -r $RULES_FILE --option=stdout_output.enabled=false > ./prog-output.txt -A 2>&1 &
|
||||
elif [[ $ROOT == *"sysdig"* ]]; then
|
||||
echo " starting sysdig..."
|
||||
sudo $ROOT/userspace/sysdig/sysdig -N -z evt.type=none &
|
||||
else
|
||||
echo " starting agent..."
|
||||
write_agent_config
|
||||
pushd $ROOT/userspace/dragent
|
||||
sudo ./dragent > ./prog-output.txt 2>&1 &
|
||||
popd
|
||||
fi
|
||||
|
||||
SUDO_PID=$!
|
||||
sleep 5
|
||||
if [[ $ROOT == *"agent"* ]]; then
|
||||
# The agent spawns several processes all below a main monitor
|
||||
# process. We want the child with the lowest pid.
|
||||
MON_PID=`ps -h -o pid --ppid $SUDO_PID`
|
||||
SUBJ_PID=`ps -h -o pid --ppid $MON_PID | head -1`
|
||||
else
|
||||
SUBJ_PID=`ps -h -o pid --ppid $SUDO_PID`
|
||||
fi
|
||||
|
||||
if [ -z $SUBJ_PID ]; then
|
||||
echo "Could not find pid of subject program--did it start successfully? Not continuing."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function run_htop() {
|
||||
screen -S htop-screen -d -m /usr/bin/htop -d2
|
||||
sleep 90
|
||||
screen -X -S htop-screen quit
|
||||
}
|
||||
|
||||
function run_juttle_examples() {
|
||||
pushd $SCRIPTDIR/../../juttle-engine/examples
|
||||
docker-compose -f dc-juttle-engine.yml -f aws-cloudwatch/dc-aws-cloudwatch.yml -f elastic-newstracker/dc-elastic.yml -f github-tutorial/dc-elastic.yml -f nginx_logs/dc-nginx-logs.yml -f postgres-diskstats/dc-postgres.yml -f cadvisor-influx/dc-cadvisor-influx.yml up -d
|
||||
sleep 120
|
||||
docker-compose -f dc-juttle-engine.yml -f aws-cloudwatch/dc-aws-cloudwatch.yml -f elastic-newstracker/dc-elastic.yml -f github-tutorial/dc-elastic.yml -f nginx_logs/dc-nginx-logs.yml -f postgres-diskstats/dc-postgres.yml -f cadvisor-influx/dc-cadvisor-influx.yml stop
|
||||
docker-compose -f dc-juttle-engine.yml -f aws-cloudwatch/dc-aws-cloudwatch.yml -f elastic-newstracker/dc-elastic.yml -f github-tutorial/dc-elastic.yml -f nginx_logs/dc-nginx-logs.yml -f postgres-diskstats/dc-postgres.yml -f cadvisor-influx/dc-cadvisor-influx.yml rm -fv
|
||||
popd
|
||||
}
|
||||
|
||||
function run_kubernetes_demo() {
|
||||
pushd $SCRIPTDIR/../../infrastructure/test-infrastructures/kubernetes-demo
|
||||
sudo bash run-local.sh
|
||||
sudo bash init.sh
|
||||
sleep 600
|
||||
docker stop $(docker ps -qa)
|
||||
docker rm -fv $(docker ps -qa)
|
||||
popd
|
||||
}
|
||||
|
||||
function run_live_test() {
|
||||
|
||||
live_test="$1"
|
||||
|
||||
echo "Running live test $live_test"
|
||||
|
||||
case "$live_test" in
|
||||
htop ) CPU_INTERVAL=2;;
|
||||
* ) CPU_INTERVAL=10;;
|
||||
esac
|
||||
|
||||
start_subject_prog
|
||||
start_monitor_cpu_usage
|
||||
|
||||
echo " starting live program and waiting for it to finish"
|
||||
case "$live_test" in
|
||||
htop ) run_htop ;;
|
||||
juttle-examples ) run_juttle_examples ;;
|
||||
kube-demo ) run_kubernetes_demo ;;
|
||||
* ) usage; cleanup; exit 1 ;;
|
||||
esac
|
||||
|
||||
cleanup
|
||||
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
|
||||
if [ -n "$SUBJ_PID" ] ; then
|
||||
echo " stopping falco/sysdig program $SUBJ_PID"
|
||||
sudo kill $SUBJ_PID
|
||||
fi
|
||||
|
||||
if [ -n "$CPU_PID" ] ; then
|
||||
echo " stopping cpu monitor program $CPU_PID"
|
||||
kill -- -$CPU_PID
|
||||
fi
|
||||
}
|
||||
|
||||
run_live_tests() {
|
||||
test="$1"
|
||||
|
||||
if [ $test == "all" ]; then
|
||||
tests="htop juttle-examples kube-demo"
|
||||
else
|
||||
tests=$test
|
||||
fi
|
||||
|
||||
for test in $tests; do
|
||||
run_live_test $test
|
||||
done
|
||||
}
|
||||
|
||||
function run_phoronix_test() {
|
||||
|
||||
live_test="$1"
|
||||
|
||||
case "$live_test" in
|
||||
pts/aio-stress | pts/fs-mark | pts/iozone | pts/network-loopback | pts/nginx | pts/pybench | pts/redis | pts/sqlite | pts/unpack-linux ) CPU_INTERVAL=2;;
|
||||
* ) CPU_INTERVAL=10;;
|
||||
esac
|
||||
|
||||
echo "Running phoronix test $live_test"
|
||||
|
||||
start_subject_prog
|
||||
start_monitor_cpu_usage
|
||||
|
||||
echo " starting phoronix test and waiting for it to finish"
|
||||
|
||||
TEST_RESULTS_NAME=$VARIANT FORCE_TIMES_TO_RUN=1 phoronix-test-suite default-run $live_test
|
||||
|
||||
cleanup
|
||||
|
||||
}
|
||||
|
||||
# To install and configure phoronix:
|
||||
# (redhat instructions, adapt as necessary for ubuntu or other distros)
|
||||
# - install phoronix: yum install phoronix-test-suite.noarch
|
||||
# - install dependencies not handled by phoronix: yum install libaio-devel pcre-devel popt-devel glibc-static zlib-devel nc bc
|
||||
# - fix trivial bugs in tests:
|
||||
# - edit ~/.phoronix-test-suite/installed-tests/pts/network-loopback-1.0.1/network-loopback line "nc -d -l 9999 > /dev/null &" to "nc -d -l 9999 > /dev/null &"
|
||||
# - edit ~/.phoronix-test-suite/test-profiles/pts/nginx-1.1.0/test-definition.xml line "<Arguments>-n 500000 -c 100 http://localhost:8088/test.html</Arguments>" to "<Arguments>-n 500000 -c 100 http://127.0.0.1:8088/test.html</Arguments>"
|
||||
# - phoronix batch-install <test list below>
|
||||
|
||||
function run_phoronix_tests() {
|
||||
|
||||
test="$1"
|
||||
|
||||
if [ $test == "all" ]; then
|
||||
tests="pts/aio-stress pts/apache pts/blogbench pts/compilebench pts/dbench pts/fio pts/fs-mark pts/iozone pts/network-loopback pts/nginx pts/pgbench pts/phpbench pts/postmark pts/pybench pts/redis pts/sqlite pts/unpack-linux"
|
||||
else
|
||||
tests=$test
|
||||
fi
|
||||
|
||||
for test in $tests; do
|
||||
run_phoronix_test $test
|
||||
done
|
||||
}
|
||||
|
||||
run_tests() {
|
||||
|
||||
IFS=':' read -ra PARTS <<< "$TEST"
|
||||
|
||||
case "${PARTS[0]}" in
|
||||
trace ) run_trace "${PARTS[1]}" ;;
|
||||
live ) run_live_tests "${PARTS[1]}" ;;
|
||||
phoronix ) run_phoronix_tests "${PARTS[1]}" ;;
|
||||
* ) usage; exit 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 [options]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " -h/--help: show this help"
|
||||
echo " -v/--variant: a variant name to attach to this set of test results"
|
||||
echo " -r/--root: root directory containing falco/sysdig binaries (i.e. where you ran 'cmake')"
|
||||
echo " -s/--source: root directory containing falco/sysdig source code"
|
||||
echo " -R/--results: append test results to this file"
|
||||
echo " -S/--stats: append capture statistics to this file (only works for falco/test_mm)"
|
||||
echo " -o/--output: append program output to this file"
|
||||
echo " -U/--rules: path to rules file (only applicable for falco/test_mm)"
|
||||
echo " -t/--test: test to run. Argument has the following format:"
|
||||
echo " trace:<trace>: read the specified trace file."
|
||||
echo " trace:all means run all traces"
|
||||
echo " live:<live test>: run the specified live test."
|
||||
echo " live:all means run all live tests."
|
||||
echo " possible live tests:"
|
||||
echo " live:htop: run htop -d2"
|
||||
echo " live:kube-demo: run kubernetes demo from infrastructure repo"
|
||||
echo " live:juttle-examples: run a juttle demo environment based on docker-compose"
|
||||
echo " phoronix:<test>: run the specified phoronix test."
|
||||
echo " if <test> is not 'all', it is passed directly to the command line of \"phoronix-test-suite run <test>\""
|
||||
echo " if <test> is 'all', a built-in set of phoronix tests will be chosen and run"
|
||||
echo " -T/--tracedir: Look for trace files in this directory. If doesn't exist, will download trace files from s3"
|
||||
echo " -A/--agent-autodrop: When running an agent, whether or not to enable autodrop"
|
||||
echo " -F/--falco-agent: When running an agent, whether or not to enable falco"
|
||||
}
|
||||
|
||||
OPTS=`getopt -o hv:r:s:R:S:o:U:t:T: --long help,variant:,root:,source:,results:,stats:,output:,rules:,test:,tracedir:,agent-autodrop:,falco-agent: -n $0 -- "$@"`
|
||||
|
||||
if [ $? != 0 ]; then
|
||||
echo "Exiting" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
eval set -- "$OPTS"
|
||||
|
||||
VARIANT="falco"
|
||||
ROOT=`dirname $0`/../build
|
||||
SOURCE=$ROOT
|
||||
SCRIPTDIR=`dirname $0`
|
||||
RESULTS_FILE=`dirname $0`/results.json
|
||||
STATS_FILE=`dirname $0`/capture_stats.json
|
||||
OUTPUT_FILE=`dirname $0`/program-output.txt
|
||||
RULES_FILE=
|
||||
TEST=trace:all
|
||||
TRACEDIR=/tmp/falco-perf-traces.$USER
|
||||
CPU_INTERVAL=10
|
||||
AGENT_AUTODROP=1
|
||||
FALCO_AGENT=1
|
||||
|
||||
while true; do
|
||||
case "$1" in
|
||||
-h | --help ) usage; exit 1;;
|
||||
-v | --variant ) VARIANT="$2"; shift 2;;
|
||||
-r | --root ) ROOT="$2"; shift 2;;
|
||||
-s | --source ) SOURCE="$2"; shift 2;;
|
||||
-R | --results ) RESULTS_FILE="$2"; shift 2;;
|
||||
-S | --stats ) STATS_FILE="$2"; shift 2;;
|
||||
-o | --output ) OUTPUT_FILE="$2"; shift 2;;
|
||||
-U | --rules ) RULES_FILE="$2"; shift 2;;
|
||||
-t | --test ) TEST="$2"; shift 2;;
|
||||
-T | --tracedir ) TRACEDIR="$2"; shift 2;;
|
||||
-A | --agent-autodrop ) AGENT_AUTODROP="$2"; shift 2;;
|
||||
-F | --falco-agent ) FALCO_AGENT="$2"; shift 2;;
|
||||
* ) break;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z $VARIANT ]; then
|
||||
echo "A test variant name must be provided. Not continuing."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z $ROOT ]; then
|
||||
echo "A root directory containing a falco/sysdig binary must be provided. Not continuing."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ROOT=`realpath $ROOT`
|
||||
|
||||
if [ -z $SOURCE ]; then
|
||||
echo "A source directory containing falco/sysdig source code. Not continuing."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SOURCE=`realpath $SOURCE`
|
||||
|
||||
if [ -z $RESULTS_FILE ]; then
|
||||
echo "An output file for test results must be provided. Not continuing."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z $STATS_FILE ]; then
|
||||
echo "An output file for capture statistics must be provided. Not continuing."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z $OUTPUT_FILE ]; then
|
||||
echo "An file for program output must be provided. Not continuing."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z $TEST ]; then
|
||||
echo "A test must be provided. Not continuing."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run_tests
|
||||
@@ -20,6 +20,7 @@ set -euo pipefail
|
||||
SCRIPT=$(readlink -f $0)
|
||||
SCRIPTDIR=$(dirname "$SCRIPT")
|
||||
SKIP_PACKAGES_TESTS=${SKIP_PACKAGES_TESTS:-false}
|
||||
SKIP_PLUGINS_TESTS=${SKIP_PLUGINS_TESTS:-false}
|
||||
TRACE_FILES_BASE_URL=${TRACE_FILES_BASE_URL:-"https://download.falco.org/fixtures/trace-files/"}
|
||||
|
||||
# Trace file tarballs are now versioned. Any time a substantial change
|
||||
@@ -104,6 +105,10 @@ function run_tests() {
|
||||
if [ "$SKIP_PACKAGES_TESTS" = false ] ; then
|
||||
suites+=($SCRIPTDIR/falco_tests_package.yaml)
|
||||
fi
|
||||
|
||||
if [ "$SKIP_PLUGINS_TESTS" = false ] ; then
|
||||
suites+=($SCRIPTDIR/falco_tests_plugins.yaml)
|
||||
fi
|
||||
|
||||
XUNIT_DIR="${OPT_BUILD_DIR}/integration-tests-xunit"
|
||||
mkdir -p "${XUNIT_DIR}"
|
||||
|
||||
@@ -1,19 +1,12 @@
|
||||
add_subdirectory(k8s_audit)
|
||||
add_subdirectory(psp)
|
||||
add_subdirectory(plugins)
|
||||
|
||||
include(copy_files_to_build_dir)
|
||||
|
||||
# Note: list of traces is created at cmake time, not build time
|
||||
file(GLOB test_trace_files
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/*.scap")
|
||||
|
||||
foreach(trace_file_path ${test_trace_files})
|
||||
get_filename_component(trace_file ${trace_file_path} NAME)
|
||||
add_custom_target(test-trace-${trace_file} ALL
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${trace_file})
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${trace_file}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${trace_file_path} ${CMAKE_CURRENT_BINARY_DIR}/${trace_file}
|
||||
DEPENDS ${trace_file_path})
|
||||
list(APPEND BASE_SCAP_TRACE_FILES_TARGETS test-trace-${trace_file})
|
||||
endforeach()
|
||||
copy_files_to_build_dir("${test_trace_files}" base-scap)
|
||||
|
||||
add_custom_target(trace-files-base-scap ALL)
|
||||
add_dependencies(trace-files-base-scap ${BASE_SCAP_TRACE_FILES_TARGETS})
|
||||
@@ -1,16 +1,7 @@
|
||||
include(copy_files_to_build_dir)
|
||||
|
||||
# Note: list of traces is created at cmake time, not build time
|
||||
file(GLOB test_trace_files
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/*.json")
|
||||
|
||||
foreach(trace_file_path ${test_trace_files})
|
||||
get_filename_component(trace_file ${trace_file_path} NAME)
|
||||
add_custom_target(test-trace-${trace_file} ALL
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${trace_file})
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${trace_file}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${trace_file_path} ${CMAKE_CURRENT_BINARY_DIR}/${trace_file}
|
||||
DEPENDS ${trace_file_path})
|
||||
list(APPEND K8S_AUDIT_TRACE_FILES_TARGETS test-trace-${trace_file})
|
||||
endforeach()
|
||||
|
||||
add_custom_target(trace-files-k8s-audit ALL)
|
||||
add_dependencies(trace-files-k8s-audit ${K8S_AUDIT_TRACE_FILES_TARGETS})
|
||||
copy_files_to_build_dir("${test_trace_files}" k8s-audit)
|
||||
|
||||
7
test/trace_files/plugins/CMakeLists.txt
Normal file
7
test/trace_files/plugins/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
include(copy_files_to_build_dir)
|
||||
|
||||
# Note: list of traces is created at cmake time, not build time
|
||||
file(GLOB test_trace_files
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/*.json")
|
||||
|
||||
copy_files_to_build_dir("${test_trace_files}" plugins)
|
||||
31
test/trace_files/plugins/alice_start_instances.json
Normal file
31
test/trace_files/plugins/alice_start_instances.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{"Records": [{
|
||||
"eventVersion": "1.0",
|
||||
"userIdentity": {
|
||||
"type": "IAMUser",
|
||||
"principalId": "EX_PRINCIPAL_ID",
|
||||
"arn": "arn:aws:iam::123456789012:user/Alice",
|
||||
"accessKeyId": "EXAMPLE_KEY_ID",
|
||||
"accountId": "123456789012",
|
||||
"userName": "Alice"
|
||||
},
|
||||
"eventTime": "2014-03-06T21:22:54Z",
|
||||
"eventSource": "ec2.amazonaws.com",
|
||||
"eventType": "AwsApiCall",
|
||||
"eventName": "StartInstances",
|
||||
"awsRegion": "us-east-2",
|
||||
"sourceIPAddress": "205.251.233.176",
|
||||
"userAgent": "ec2-api-tools 1.6.12.2",
|
||||
"requestParameters": {"instancesSet": {"items": [{"instanceId": "i-ebeaf9e2"}]}},
|
||||
"responseElements": {"instancesSet": {"items": [{
|
||||
"instanceId": "i-ebeaf9e2",
|
||||
"currentState": {
|
||||
"code": 0,
|
||||
"name": "pending"
|
||||
},
|
||||
"previousState": {
|
||||
"code": 80,
|
||||
"name": "stopped"
|
||||
}
|
||||
}]}}
|
||||
}]}
|
||||
|
||||
32
test/trace_files/plugins/alice_start_instances_bigevent.json
Normal file
32
test/trace_files/plugins/alice_start_instances_bigevent.json
Normal file
File diff suppressed because one or more lines are too long
@@ -1,17 +1,8 @@
|
||||
include(copy_files_to_build_dir)
|
||||
|
||||
# Note: list of traces is created at cmake time, not build time
|
||||
file(GLOB test_trace_files
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/*.json"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/*.scap")
|
||||
|
||||
foreach(trace_file_path ${test_trace_files})
|
||||
get_filename_component(trace_file ${trace_file_path} NAME)
|
||||
add_custom_target(test-trace-${trace_file} ALL
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${trace_file})
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${trace_file}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${trace_file_path} ${CMAKE_CURRENT_BINARY_DIR}/${trace_file}
|
||||
DEPENDS ${trace_file_path})
|
||||
list(APPEND PSP_TRACE_FILES_TARGETS test-trace-${trace_file})
|
||||
endforeach()
|
||||
|
||||
add_custom_target(trace-files-psp ALL)
|
||||
add_dependencies(trace-files-psp ${PSP_TRACE_FILES_TARGETS})
|
||||
copy_files_to_build_dir("${test_trace_files}" psp)
|
||||
|
||||
@@ -15,12 +15,25 @@
|
||||
# the License.
|
||||
#
|
||||
if(MINIMAL_BUILD)
|
||||
set(FALCO_TESTS_SOURCES test_base.cpp engine/test_token_bucket.cpp engine/test_rulesets.cpp engine/test_falco_utils.cpp)
|
||||
set(
|
||||
FALCO_TESTS_SOURCES
|
||||
test_base.cpp
|
||||
engine/test_rulesets.cpp
|
||||
engine/test_falco_utils.cpp
|
||||
falco/test_configuration.cpp
|
||||
)
|
||||
else()
|
||||
set(FALCO_TESTS_SOURCES test_base.cpp engine/test_token_bucket.cpp engine/test_rulesets.cpp engine/test_falco_utils.cpp falco/test_webserver.cpp)
|
||||
set(
|
||||
FALCO_TESTS_SOURCES
|
||||
test_base.cpp
|
||||
engine/test_rulesets.cpp
|
||||
engine/test_falco_utils.cpp
|
||||
falco/test_configuration.cpp
|
||||
falco/test_webserver.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
set(FALCO_TESTED_LIBRARIES falco_engine)
|
||||
set(FALCO_TESTED_LIBRARIES falco_engine ${YAMLCPP_LIB})
|
||||
|
||||
SET(FALCO_TESTS_ARGUMENTS "" CACHE STRING "Test arguments to pass to the Falco test suite")
|
||||
|
||||
@@ -46,6 +59,7 @@ if(FALCO_BUILD_TESTS)
|
||||
PUBLIC "${CATCH2_INCLUDE}"
|
||||
"${FAKEIT_INCLUDE}"
|
||||
"${PROJECT_SOURCE_DIR}/userspace/engine"
|
||||
"${PROJECT_BINARY_DIR}/userspace/falco"
|
||||
"${YAMLCPP_INCLUDE_DIR}"
|
||||
"${PROJECT_SOURCE_DIR}/userspace/falco")
|
||||
else()
|
||||
@@ -54,6 +68,7 @@ if(FALCO_BUILD_TESTS)
|
||||
PUBLIC "${CATCH2_INCLUDE}"
|
||||
"${FAKEIT_INCLUDE}"
|
||||
"${PROJECT_SOURCE_DIR}/userspace/engine"
|
||||
"${PROJECT_BINARY_DIR}/userspace/falco"
|
||||
"${YAMLCPP_INCLUDE_DIR}"
|
||||
"${CIVETWEB_INCLUDE_DIR}"
|
||||
"${PROJECT_SOURCE_DIR}/userspace/falco")
|
||||
|
||||
@@ -25,15 +25,26 @@ static uint16_t default_ruleset = 0;
|
||||
static uint16_t non_default_ruleset = 3;
|
||||
static uint16_t other_non_default_ruleset = 2;
|
||||
static std::set<std::string> tags = {"some_tag", "some_other_tag"};
|
||||
static std::set<uint32_t> event_tags = {1};
|
||||
|
||||
static std::shared_ptr<gen_event_filter> create_filter()
|
||||
{
|
||||
// The actual contents of the filters don't matter here.
|
||||
sinsp_filter_compiler compiler(NULL, "evt.type=open");
|
||||
sinsp_filter *f = compiler.compile();
|
||||
|
||||
std::shared_ptr<gen_event_filter> ret(f);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
TEST_CASE("Should enable/disable for exact match w/ default ruleset", "[rulesets]")
|
||||
{
|
||||
falco_ruleset r;
|
||||
gen_event_filter *filter = new gen_event_filter();
|
||||
std::shared_ptr<gen_event_filter> filter = create_filter();
|
||||
string rule_name = "one_rule";
|
||||
string source = "syscall";
|
||||
|
||||
r.add(rule_name, tags, event_tags, filter);
|
||||
r.add(source, rule_name, tags, filter);
|
||||
|
||||
r.enable("one_rule", exact_match, enabled);
|
||||
REQUIRE(r.num_rules_for_ruleset(default_ruleset) == 1);
|
||||
@@ -45,10 +56,11 @@ TEST_CASE("Should enable/disable for exact match w/ default ruleset", "[rulesets
|
||||
TEST_CASE("Should enable/disable for exact match w/ specific ruleset", "[rulesets]")
|
||||
{
|
||||
falco_ruleset r;
|
||||
gen_event_filter *filter = new gen_event_filter();
|
||||
std::shared_ptr<gen_event_filter> filter = create_filter();
|
||||
string rule_name = "one_rule";
|
||||
string source = "syscall";
|
||||
|
||||
r.add(rule_name, tags, event_tags, filter);
|
||||
r.add(source, rule_name, tags, filter);
|
||||
|
||||
r.enable("one_rule", exact_match, enabled, non_default_ruleset);
|
||||
REQUIRE(r.num_rules_for_ruleset(non_default_ruleset) == 1);
|
||||
@@ -64,10 +76,11 @@ TEST_CASE("Should enable/disable for exact match w/ specific ruleset", "[ruleset
|
||||
TEST_CASE("Should not enable for exact match different rule name", "[rulesets]")
|
||||
{
|
||||
falco_ruleset r;
|
||||
gen_event_filter *filter = new gen_event_filter();
|
||||
std::shared_ptr<gen_event_filter> filter = create_filter();
|
||||
string rule_name = "one_rule";
|
||||
string source = "syscall";
|
||||
|
||||
r.add(rule_name, tags, event_tags, filter);
|
||||
r.add(source, rule_name, tags, filter);
|
||||
|
||||
r.enable("some_other_rule", exact_match, enabled);
|
||||
REQUIRE(r.num_rules_for_ruleset(default_ruleset) == 0);
|
||||
@@ -76,10 +89,11 @@ TEST_CASE("Should not enable for exact match different rule name", "[rulesets]")
|
||||
TEST_CASE("Should enable/disable for exact match w/ substring and default ruleset", "[rulesets]")
|
||||
{
|
||||
falco_ruleset r;
|
||||
gen_event_filter *filter = new gen_event_filter();
|
||||
std::shared_ptr<gen_event_filter> filter = create_filter();
|
||||
string rule_name = "one_rule";
|
||||
string source = "syscall";
|
||||
|
||||
r.add(rule_name, tags, event_tags, filter);
|
||||
r.add(source, rule_name, tags, filter);
|
||||
|
||||
r.enable("one_rule", substring_match, enabled);
|
||||
REQUIRE(r.num_rules_for_ruleset(default_ruleset) == 1);
|
||||
@@ -91,10 +105,11 @@ TEST_CASE("Should enable/disable for exact match w/ substring and default rulese
|
||||
TEST_CASE("Should not enable for substring w/ exact_match", "[rulesets]")
|
||||
{
|
||||
falco_ruleset r;
|
||||
gen_event_filter *filter = new gen_event_filter();
|
||||
std::shared_ptr<gen_event_filter> filter = create_filter();
|
||||
string rule_name = "one_rule";
|
||||
string source = "syscall";
|
||||
|
||||
r.add(rule_name, tags, event_tags, filter);
|
||||
r.add(source, rule_name, tags, filter);
|
||||
|
||||
r.enable("one_", exact_match, enabled);
|
||||
REQUIRE(r.num_rules_for_ruleset(default_ruleset) == 0);
|
||||
@@ -103,10 +118,11 @@ TEST_CASE("Should not enable for substring w/ exact_match", "[rulesets]")
|
||||
TEST_CASE("Should enable/disable for prefix match w/ default ruleset", "[rulesets]")
|
||||
{
|
||||
falco_ruleset r;
|
||||
gen_event_filter *filter = new gen_event_filter();
|
||||
std::shared_ptr<gen_event_filter> filter = create_filter();
|
||||
string rule_name = "one_rule";
|
||||
string source = "syscall";
|
||||
|
||||
r.add(rule_name, tags, event_tags, filter);
|
||||
r.add(source, rule_name, tags, filter);
|
||||
|
||||
r.enable("one_", substring_match, enabled);
|
||||
REQUIRE(r.num_rules_for_ruleset(default_ruleset) == 1);
|
||||
@@ -118,10 +134,11 @@ TEST_CASE("Should enable/disable for prefix match w/ default ruleset", "[ruleset
|
||||
TEST_CASE("Should enable/disable for suffix match w/ default ruleset", "[rulesets]")
|
||||
{
|
||||
falco_ruleset r;
|
||||
gen_event_filter *filter = new gen_event_filter();
|
||||
std::shared_ptr<gen_event_filter> filter = create_filter();
|
||||
string rule_name = "one_rule";
|
||||
string source = "syscall";
|
||||
|
||||
r.add(rule_name, tags, event_tags, filter);
|
||||
r.add(source, rule_name, tags, filter);
|
||||
|
||||
r.enable("_rule", substring_match, enabled);
|
||||
REQUIRE(r.num_rules_for_ruleset(default_ruleset) == 1);
|
||||
@@ -133,10 +150,11 @@ TEST_CASE("Should enable/disable for suffix match w/ default ruleset", "[ruleset
|
||||
TEST_CASE("Should enable/disable for substring match w/ default ruleset", "[rulesets]")
|
||||
{
|
||||
falco_ruleset r;
|
||||
gen_event_filter *filter = new gen_event_filter();
|
||||
std::shared_ptr<gen_event_filter> filter = create_filter();
|
||||
string rule_name = "one_rule";
|
||||
string source = "syscall";
|
||||
|
||||
r.add(rule_name, tags, event_tags, filter);
|
||||
r.add(source, rule_name, tags, filter);
|
||||
|
||||
r.enable("ne_ru", substring_match, enabled);
|
||||
REQUIRE(r.num_rules_for_ruleset(default_ruleset) == 1);
|
||||
@@ -148,10 +166,11 @@ TEST_CASE("Should enable/disable for substring match w/ default ruleset", "[rule
|
||||
TEST_CASE("Should enable/disable for substring match w/ specific ruleset", "[rulesets]")
|
||||
{
|
||||
falco_ruleset r;
|
||||
gen_event_filter *filter = new gen_event_filter();
|
||||
std::shared_ptr<gen_event_filter> filter = create_filter();
|
||||
string rule_name = "one_rule";
|
||||
string source = "syscall";
|
||||
|
||||
r.add(rule_name, tags, event_tags, filter);
|
||||
r.add(source, rule_name, tags, filter);
|
||||
|
||||
r.enable("ne_ru", substring_match, enabled, non_default_ruleset);
|
||||
REQUIRE(r.num_rules_for_ruleset(non_default_ruleset) == 1);
|
||||
@@ -167,11 +186,12 @@ TEST_CASE("Should enable/disable for substring match w/ specific ruleset", "[rul
|
||||
TEST_CASE("Should enable/disable for tags w/ default ruleset", "[rulesets]")
|
||||
{
|
||||
falco_ruleset r;
|
||||
gen_event_filter *filter = new gen_event_filter();
|
||||
std::shared_ptr<gen_event_filter> filter = create_filter();
|
||||
string rule_name = "one_rule";
|
||||
string source = "syscall";
|
||||
std::set<std::string> want_tags = {"some_tag"};
|
||||
|
||||
r.add(rule_name, tags, event_tags, filter);
|
||||
r.add(source, rule_name, tags, filter);
|
||||
|
||||
r.enable_tags(want_tags, enabled);
|
||||
REQUIRE(r.num_rules_for_ruleset(default_ruleset) == 1);
|
||||
@@ -183,11 +203,12 @@ TEST_CASE("Should enable/disable for tags w/ default ruleset", "[rulesets]")
|
||||
TEST_CASE("Should enable/disable for tags w/ specific ruleset", "[rulesets]")
|
||||
{
|
||||
falco_ruleset r;
|
||||
gen_event_filter *filter = new gen_event_filter();
|
||||
std::shared_ptr<gen_event_filter> filter = create_filter();
|
||||
string rule_name = "one_rule";
|
||||
string source = "syscall";
|
||||
std::set<std::string> want_tags = {"some_tag"};
|
||||
|
||||
r.add(rule_name, tags, event_tags, filter);
|
||||
r.add(source, rule_name, tags, filter);
|
||||
|
||||
r.enable_tags(want_tags, enabled, non_default_ruleset);
|
||||
REQUIRE(r.num_rules_for_ruleset(non_default_ruleset) == 1);
|
||||
@@ -203,11 +224,12 @@ TEST_CASE("Should enable/disable for tags w/ specific ruleset", "[rulesets]")
|
||||
TEST_CASE("Should not enable for different tags", "[rulesets]")
|
||||
{
|
||||
falco_ruleset r;
|
||||
gen_event_filter *filter = new gen_event_filter();
|
||||
std::shared_ptr<gen_event_filter> filter = create_filter();
|
||||
string rule_name = "one_rule";
|
||||
string source = "syscall";
|
||||
std::set<std::string> want_tags = {"some_different_tag"};
|
||||
|
||||
r.add(rule_name, tags, event_tags, filter);
|
||||
r.add(source, rule_name, tags, filter);
|
||||
|
||||
r.enable_tags(want_tags, enabled);
|
||||
REQUIRE(r.num_rules_for_ruleset(non_default_ruleset) == 0);
|
||||
@@ -216,11 +238,12 @@ TEST_CASE("Should not enable for different tags", "[rulesets]")
|
||||
TEST_CASE("Should enable/disable for overlapping tags", "[rulesets]")
|
||||
{
|
||||
falco_ruleset r;
|
||||
gen_event_filter *filter = new gen_event_filter();
|
||||
std::shared_ptr<gen_event_filter> filter = create_filter();
|
||||
string rule_name = "one_rule";
|
||||
string source = "syscall";
|
||||
std::set<std::string> want_tags = {"some_tag", "some_different_tag"};
|
||||
|
||||
r.add(rule_name, tags, event_tags, filter);
|
||||
r.add(source, rule_name, tags, filter);
|
||||
|
||||
r.enable_tags(want_tags, enabled);
|
||||
REQUIRE(r.num_rules_for_ruleset(default_ruleset) == 1);
|
||||
@@ -231,16 +254,17 @@ TEST_CASE("Should enable/disable for overlapping tags", "[rulesets]")
|
||||
|
||||
TEST_CASE("Should enable/disable for incremental adding tags", "[rulesets]")
|
||||
{
|
||||
string source = "syscall";
|
||||
falco_ruleset r;
|
||||
gen_event_filter *rule1_filter = new gen_event_filter();
|
||||
std::shared_ptr<gen_event_filter> rule1_filter = create_filter();
|
||||
string rule1_name = "one_rule";
|
||||
std::set<std::string> rule1_tags = {"rule1_tag"};
|
||||
r.add(rule1_name, rule1_tags, event_tags, rule1_filter);
|
||||
r.add(source, rule1_name, rule1_tags, rule1_filter);
|
||||
|
||||
gen_event_filter *rule2_filter = new gen_event_filter();
|
||||
std::shared_ptr<gen_event_filter> rule2_filter = create_filter();
|
||||
string rule2_name = "two_rule";
|
||||
std::set<std::string> rule2_tags = {"rule2_tag"};
|
||||
r.add(rule2_name, rule2_tags, event_tags, rule2_filter);
|
||||
r.add(source, rule2_name, rule2_tags, rule2_filter);
|
||||
|
||||
std::set<std::string> want_tags;
|
||||
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2019 The Falco Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with 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 <memory>
|
||||
|
||||
#include "token_bucket.h"
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace Catch::literals;
|
||||
|
||||
TEST_CASE("token bucket default ctor", "[token_bucket]")
|
||||
{
|
||||
auto tb = std::make_shared<token_bucket>();
|
||||
|
||||
REQUIRE(tb->get_tokens() == 1);
|
||||
|
||||
SECTION("initialising with specific time, rate 2 tokens/sec")
|
||||
{
|
||||
auto max = 2.0;
|
||||
uint64_t now = 1;
|
||||
tb->init(1.0, max, now);
|
||||
REQUIRE(tb->get_last_seen() == now);
|
||||
REQUIRE(tb->get_tokens() == max);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("token bucket ctor with custom timer", "[token_bucket]")
|
||||
{
|
||||
auto t = []() -> uint64_t { return 22; };
|
||||
auto tb = std::make_shared<token_bucket>(t);
|
||||
|
||||
REQUIRE(tb->get_tokens() == 1);
|
||||
REQUIRE(tb->get_last_seen() == 22);
|
||||
}
|
||||
|
||||
TEST_CASE("token bucket with 2 tokens/sec rate, max 10 tokens", "[token_bucket]")
|
||||
{
|
||||
auto tb = std::make_shared<token_bucket>();
|
||||
tb->init(2.0, 10, 1);
|
||||
|
||||
SECTION("claiming 5 tokens")
|
||||
{
|
||||
bool claimed = tb->claim(5, 1000000001);
|
||||
REQUIRE(tb->get_last_seen() == 1000000001);
|
||||
REQUIRE(tb->get_tokens() == 5.0_a);
|
||||
REQUIRE(claimed);
|
||||
|
||||
SECTION("claiming all the 7 remaining tokens")
|
||||
{
|
||||
bool claimed = tb->claim(7, 2000000001);
|
||||
REQUIRE(tb->get_last_seen() == 2000000001);
|
||||
REQUIRE(tb->get_tokens() == 0.0_a);
|
||||
REQUIRE(claimed);
|
||||
|
||||
SECTION("claiming 1 token more than the 2 available fails")
|
||||
{
|
||||
bool claimed = tb->claim(3, 3000000001);
|
||||
REQUIRE(tb->get_last_seen() == 3000000001);
|
||||
REQUIRE(tb->get_tokens() == 2.0_a);
|
||||
REQUIRE_FALSE(claimed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("token bucket default initialization", "[token_bucket]")
|
||||
{
|
||||
token_bucket tb;
|
||||
REQUIRE(tb.get_tokens() == 1);
|
||||
}
|
||||
106
tests/falco/test_configuration.cpp
Normal file
106
tests/falco/test_configuration.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright (C) 2021 The Falco Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with 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 "configuration.h"
|
||||
#include <catch.hpp>
|
||||
|
||||
string sample_yaml =
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: 'sample_name'\n"
|
||||
" subvalue:\n"
|
||||
" subvalue2:\n"
|
||||
" boolean: true\n"
|
||||
"base_value_2:\n"
|
||||
" sample_list:\n"
|
||||
" - elem1\n"
|
||||
" - elem2\n"
|
||||
" - elem3\n"
|
||||
;
|
||||
|
||||
TEST_CASE("configuration must load YAML data", "[configuration]")
|
||||
{
|
||||
yaml_configuration conf;
|
||||
|
||||
SECTION("broken YAML")
|
||||
{
|
||||
string sample_broken_yaml = sample_yaml + " / bad_symbol";
|
||||
REQUIRE_THROWS(conf.load_from_string(sample_broken_yaml));
|
||||
}
|
||||
|
||||
SECTION("valid YAML")
|
||||
{
|
||||
REQUIRE_NOTHROW(conf.load_from_string(sample_yaml));
|
||||
}
|
||||
|
||||
SECTION("clearing and reloading")
|
||||
{
|
||||
conf.load_from_string(sample_yaml);
|
||||
REQUIRE(conf.is_defined("base_value") == true);
|
||||
conf.clear();
|
||||
REQUIRE(conf.is_defined("base_value") == false);
|
||||
conf.load_from_string(sample_yaml);
|
||||
REQUIRE(conf.is_defined("base_value") == true);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("configuration must read YAML fields", "[configuration]")
|
||||
{
|
||||
yaml_configuration conf;
|
||||
conf.load_from_string(sample_yaml);
|
||||
|
||||
SECTION("base level")
|
||||
{
|
||||
REQUIRE(conf.is_defined("base_value") == true);
|
||||
REQUIRE(conf.is_defined("base_value_2") == true);
|
||||
REQUIRE(conf.is_defined("unknown_base_value") == false);
|
||||
}
|
||||
|
||||
SECTION("arbitrary depth nesting")
|
||||
{
|
||||
REQUIRE(conf.get_scalar<int>("base_value.id", -1) == 1);
|
||||
REQUIRE(conf.get_scalar<string>("base_value.name", "none") == "sample_name");
|
||||
REQUIRE(conf.get_scalar<bool>("base_value.subvalue.subvalue2.boolean", false) == true);
|
||||
}
|
||||
|
||||
SECTION("list field elements")
|
||||
{
|
||||
REQUIRE(conf.get_scalar<string>("base_value_2.sample_list[0]", "none") == "elem1");
|
||||
REQUIRE(conf.get_scalar<string>("base_value_2.sample_list[1]", "none") == "elem2");
|
||||
REQUIRE(conf.get_scalar<string>("base_value_2.sample_list[2]", "none") == "elem3");
|
||||
}
|
||||
|
||||
SECTION("sequence")
|
||||
{
|
||||
vector<string> seq;
|
||||
conf.get_sequence(seq, "base_value_2.sample_list");
|
||||
REQUIRE(seq.size() == 3);
|
||||
REQUIRE(seq[0] == "elem1");
|
||||
REQUIRE(seq[1] == "elem2");
|
||||
REQUIRE(seq[2] == "elem3");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("configuration must modify YAML fields", "[configuration]")
|
||||
{
|
||||
string key = "base_value.subvalue.subvalue2.boolean";
|
||||
yaml_configuration conf;
|
||||
conf.load_from_string(sample_yaml);
|
||||
REQUIRE(conf.get_scalar<bool>(key, false) == true);
|
||||
conf.set_scalar<bool>(key, false);
|
||||
REQUIRE(conf.get_scalar<bool>(key, true) == false);
|
||||
conf.set_scalar<bool>(key, true);
|
||||
REQUIRE(conf.get_scalar<bool>(key, false) == true);
|
||||
}
|
||||
@@ -10,6 +10,8 @@
|
||||
# "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.
|
||||
|
||||
add_subdirectory(lua)
|
||||
|
||||
set(FALCO_ENGINE_SOURCE_FILES
|
||||
rules.cpp
|
||||
falco_common.cpp
|
||||
@@ -17,7 +19,6 @@ set(FALCO_ENGINE_SOURCE_FILES
|
||||
falco_utils.cpp
|
||||
json_evt.cpp
|
||||
ruleset.cpp
|
||||
token_bucket.cpp
|
||||
formats.cpp)
|
||||
|
||||
add_library(falco_engine STATIC ${FALCO_ENGINE_SOURCE_FILES})
|
||||
@@ -37,7 +38,8 @@ if(MINIMAL_BUILD)
|
||||
"${STRING_VIEW_LITE_INCLUDE}"
|
||||
"${LIBSCAP_INCLUDE_DIRS}"
|
||||
"${LIBSINSP_INCLUDE_DIRS}"
|
||||
"${PROJECT_BINARY_DIR}/userspace/engine")
|
||||
"${PROJECT_BINARY_DIR}/userspace/engine"
|
||||
"${PROJECT_BINARY_DIR}/userspace/engine/lua")
|
||||
else()
|
||||
target_include_directories(
|
||||
falco_engine
|
||||
@@ -49,24 +51,8 @@ else()
|
||||
"${STRING_VIEW_LITE_INCLUDE}"
|
||||
"${LIBSCAP_INCLUDE_DIRS}"
|
||||
"${LIBSINSP_INCLUDE_DIRS}"
|
||||
"${PROJECT_BINARY_DIR}/userspace/engine")
|
||||
"${PROJECT_BINARY_DIR}/userspace/engine"
|
||||
"${PROJECT_BINARY_DIR}/userspace/engine/lua")
|
||||
endif()
|
||||
|
||||
target_link_libraries(falco_engine "${FALCO_SINSP_LIBRARY}" "${LPEG_LIB}" "${LYAML_LIB}" "${LIBYAML_LIB}")
|
||||
|
||||
configure_file(config_falco_engine.h.in config_falco_engine.h)
|
||||
|
||||
if(DEFINED FALCO_COMPONENT)
|
||||
install(
|
||||
DIRECTORY lua
|
||||
DESTINATION "${FALCO_SHARE_DIR}"
|
||||
COMPONENT "${FALCO_COMPONENT}"
|
||||
FILES_MATCHING
|
||||
PATTERN *.lua)
|
||||
else()
|
||||
install(
|
||||
DIRECTORY lua
|
||||
DESTINATION "${FALCO_SHARE_DIR}"
|
||||
FILES_MATCHING
|
||||
PATTERN *.lua)
|
||||
endif()
|
||||
target_link_libraries(falco_engine "${FALCO_SINSP_LIBRARY}" "${LPEG_LIB}" "${LYAML_LIB}" "${LIBYAML_LIB}" luafiles)
|
||||
|
||||
@@ -16,9 +16,9 @@ limitations under the License.
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "config_falco_engine.h"
|
||||
#include "falco_common.h"
|
||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||
#include "falco_engine_lua_files.hh"
|
||||
|
||||
std::vector<std::string> falco_common::priority_names = {
|
||||
"Emergency",
|
||||
@@ -48,73 +48,33 @@ falco_common::~falco_common()
|
||||
}
|
||||
}
|
||||
|
||||
void falco_common::set_inspector(sinsp *inspector)
|
||||
void falco_common::init()
|
||||
{
|
||||
m_inspector = inspector;
|
||||
}
|
||||
|
||||
void falco_common::init(const char *lua_main_filename, const char *alternate_lua_dir)
|
||||
{
|
||||
ifstream is;
|
||||
string lua_dir = FALCO_ENGINE_LUA_DIR;
|
||||
string lua_main_path = lua_dir + lua_main_filename;
|
||||
|
||||
is.open(lua_main_path);
|
||||
if (!is.is_open())
|
||||
// Strings in the list lua_module_strings need to be loaded as
|
||||
// lua modules, which also involves adding them to the
|
||||
// package.module table.
|
||||
for(const auto &pair : lua_module_strings)
|
||||
{
|
||||
lua_dir = alternate_lua_dir;
|
||||
lua_main_path = lua_dir + lua_main_filename;
|
||||
lua_getglobal(m_ls, "package");
|
||||
lua_getfield(m_ls, -1, "preload");
|
||||
|
||||
is.open(lua_main_path);
|
||||
if (!is.is_open())
|
||||
if(luaL_loadstring(m_ls, pair.first))
|
||||
{
|
||||
throw falco_exception("Could not find Falco Lua entrypoint (tried " +
|
||||
string(FALCO_ENGINE_LUA_DIR) + lua_main_filename + ", " +
|
||||
string(alternate_lua_dir) + lua_main_filename + ")");
|
||||
throw falco_exception("Failed to load embedded lua code " +
|
||||
string(pair.second) + ": " + lua_tostring(m_ls, -1));
|
||||
}
|
||||
|
||||
lua_setfield(m_ls, -2, pair.second);
|
||||
}
|
||||
|
||||
// Strings in the list lua_code_strings need to be loaded and
|
||||
// evaluated so any public functions can be directly called.
|
||||
for(const auto &str : lua_code_strings)
|
||||
{
|
||||
if(luaL_loadstring(m_ls, str) || lua_pcall(m_ls, 0, 0, 0))
|
||||
{
|
||||
throw falco_exception("Failed to load + evaluate embedded lua code " +
|
||||
string(str) + ": " + lua_tostring(m_ls, -1));
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize Lua interpreter
|
||||
add_lua_path(lua_dir);
|
||||
|
||||
// Load the main program, which defines all the available functions.
|
||||
string scriptstr((istreambuf_iterator<char>(is)),
|
||||
istreambuf_iterator<char>());
|
||||
|
||||
if(luaL_loadstring(m_ls, scriptstr.c_str()) || lua_pcall(m_ls, 0, 0, 0))
|
||||
{
|
||||
throw falco_exception("Failed to load script " +
|
||||
lua_main_path + ": " + lua_tostring(m_ls, -1));
|
||||
}
|
||||
}
|
||||
|
||||
void falco_common::add_lua_path(string &path)
|
||||
{
|
||||
string cpath = string(path);
|
||||
path += "?.lua";
|
||||
cpath += "?.so";
|
||||
|
||||
lua_getglobal(m_ls, "package");
|
||||
|
||||
lua_getfield(m_ls, -1, "path");
|
||||
string cur_path = lua_tostring(m_ls, -1 );
|
||||
cur_path += ';';
|
||||
lua_pop(m_ls, 1);
|
||||
|
||||
cur_path.append(path.c_str());
|
||||
|
||||
lua_pushstring(m_ls, cur_path.c_str());
|
||||
lua_setfield(m_ls, -2, "path");
|
||||
|
||||
lua_getfield(m_ls, -1, "cpath");
|
||||
string cur_cpath = lua_tostring(m_ls, -1 );
|
||||
cur_cpath += ';';
|
||||
lua_pop(m_ls, 1);
|
||||
|
||||
cur_cpath.append(cpath.c_str());
|
||||
|
||||
lua_pushstring(m_ls, cur_cpath.c_str());
|
||||
lua_setfield(m_ls, -2, "cpath");
|
||||
|
||||
lua_pop(m_ls, 1);
|
||||
}
|
||||
|
||||
@@ -69,9 +69,7 @@ public:
|
||||
falco_common();
|
||||
virtual ~falco_common();
|
||||
|
||||
void init(const char *lua_main_filename, const char *alternate_lua_dir);
|
||||
|
||||
void set_inspector(sinsp *inspector);
|
||||
void init();
|
||||
|
||||
// Priority levels, as a vector of strings
|
||||
static std::vector<std::string> priority_names;
|
||||
@@ -93,9 +91,4 @@ protected:
|
||||
lua_State *m_ls;
|
||||
|
||||
std::mutex m_ls_semaphore;
|
||||
|
||||
sinsp *m_inspector;
|
||||
|
||||
private:
|
||||
void add_lua_path(std::string &path);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -19,10 +19,12 @@ limitations under the License.
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
#include <sinsp.h>
|
||||
#include <plugin.h>
|
||||
|
||||
#include "falco_engine.h"
|
||||
#include "falco_utils.h"
|
||||
#include "falco_engine_version.h"
|
||||
#include "config_falco_engine.h"
|
||||
|
||||
#include "formats.h"
|
||||
|
||||
@@ -37,13 +39,12 @@ extern "C" {
|
||||
|
||||
string lua_on_event = "on_event";
|
||||
string lua_print_stats = "print_stats";
|
||||
const std::string falco_engine::s_default_ruleset = "falco-default-ruleset";
|
||||
|
||||
using namespace std;
|
||||
|
||||
nlohmann::json::json_pointer falco_engine::k8s_audit_time = "/stageTimestamp"_json_pointer;
|
||||
|
||||
falco_engine::falco_engine(bool seed_rng, const std::string& alternate_lua_dir)
|
||||
: m_rules(NULL), m_next_ruleset_id(0),
|
||||
falco_engine::falco_engine(bool seed_rng)
|
||||
: m_next_ruleset_id(0),
|
||||
m_min_priority(falco_common::PRIORITY_DEBUG),
|
||||
m_sampling_ratio(1), m_sampling_multiplier(0),
|
||||
m_replace_container_info(false)
|
||||
@@ -51,29 +52,21 @@ falco_engine::falco_engine(bool seed_rng, const std::string& alternate_lua_dir)
|
||||
luaopen_lpeg(m_ls);
|
||||
luaopen_yaml(m_ls);
|
||||
|
||||
falco_common::init(m_lua_main_filename.c_str(), alternate_lua_dir.c_str());
|
||||
falco_common::init();
|
||||
falco_rules::init(m_ls);
|
||||
|
||||
m_sinsp_rules.reset(new falco_sinsp_ruleset());
|
||||
m_k8s_audit_rules.reset(new falco_ruleset());
|
||||
m_required_plugin_versions.clear();
|
||||
|
||||
if(seed_rng)
|
||||
{
|
||||
srandom((unsigned) getpid());
|
||||
}
|
||||
|
||||
m_default_ruleset_id = find_ruleset_id(m_default_ruleset);
|
||||
|
||||
// Create this now so we can potentially list filters and exit
|
||||
m_json_factory = make_shared<json_event_filter_factory>();
|
||||
m_default_ruleset_id = find_ruleset_id(s_default_ruleset);
|
||||
}
|
||||
|
||||
falco_engine::~falco_engine()
|
||||
{
|
||||
if (m_rules)
|
||||
{
|
||||
delete m_rules;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t falco_engine::engine_version()
|
||||
@@ -81,65 +74,76 @@ uint32_t falco_engine::engine_version()
|
||||
return (uint32_t) FALCO_ENGINE_VERSION;
|
||||
}
|
||||
|
||||
#define DESCRIPTION_TEXT_START 16
|
||||
|
||||
#define CONSOLE_LINE_LEN 79
|
||||
|
||||
void falco_engine::list_fields(bool names_only)
|
||||
// Return a key that uniquely represents a field class.
|
||||
// For now, we assume name + shortdesc is unique.
|
||||
static std::string fieldclass_key(const gen_event_filter_factory::filter_fieldclass_info &fld_info)
|
||||
{
|
||||
for(auto &chk_field : json_factory().get_fields())
|
||||
return fld_info.name + fld_info.shortdesc;
|
||||
}
|
||||
|
||||
void falco_engine::list_fields(std::string &source, bool verbose, bool names_only)
|
||||
{
|
||||
// Maps from field class name + short desc to list of event
|
||||
// sources for which this field class can be used.
|
||||
std::map<std::string,std::set<std::string>> fieldclass_event_sources;
|
||||
|
||||
// Do a first pass to group together classes that are
|
||||
// applicable to multiple event sources.
|
||||
for(auto &it : m_filter_factories)
|
||||
{
|
||||
if(!names_only)
|
||||
if(source != "" && source != it.first)
|
||||
{
|
||||
printf("\n----------------------\n");
|
||||
printf("Field Class: %s (%s)\n\n", chk_field.m_name.c_str(), chk_field.m_desc.c_str());
|
||||
if(chk_field.m_class_info != "")
|
||||
{
|
||||
std::string str = falco::utils::wrap_text(chk_field.m_class_info, 0, 0, CONSOLE_LINE_LEN);
|
||||
printf("%s\n", str.c_str());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
for(auto &field : chk_field.m_fields)
|
||||
for(auto &fld_class : it.second->get_fields())
|
||||
{
|
||||
printf("%s", field.m_name.c_str());
|
||||
fieldclass_event_sources[fieldclass_key(fld_class)].insert(it.first);
|
||||
}
|
||||
}
|
||||
|
||||
if(names_only)
|
||||
// The set of field classes already printed. Used to avoid
|
||||
// printing field classes multiple times for different sources
|
||||
std::set<std::string> seen_fieldclasses;
|
||||
|
||||
// In the second pass, actually print info, skipping duplicate
|
||||
// field classes and also printing info on supported sources.
|
||||
for(auto &it : m_filter_factories)
|
||||
{
|
||||
if(source != "" && source != it.first)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for(auto &fld_class : it.second->get_fields())
|
||||
{
|
||||
std::string key = fieldclass_key(fld_class);
|
||||
|
||||
if(seen_fieldclasses.find(key) != seen_fieldclasses.end())
|
||||
{
|
||||
printf("\n");
|
||||
continue;
|
||||
}
|
||||
uint32_t namelen = field.m_name.size();
|
||||
|
||||
if(namelen >= DESCRIPTION_TEXT_START)
|
||||
seen_fieldclasses.insert(key);
|
||||
|
||||
if(!names_only)
|
||||
{
|
||||
printf("\n");
|
||||
namelen = 0;
|
||||
printf("%s\n", fld_class.as_string(verbose,
|
||||
fieldclass_event_sources[fieldclass_key(fld_class)]).c_str());
|
||||
}
|
||||
|
||||
for(uint32_t l = 0; l < DESCRIPTION_TEXT_START - namelen; l++)
|
||||
else
|
||||
{
|
||||
printf(" ");
|
||||
for(auto &field : fld_class.fields)
|
||||
{
|
||||
// Skip fields with the EPF_TABLE_ONLY flag.
|
||||
if(field.tags.find("EPF_TABLE_ONLY") != field.tags.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("%s\n", field.name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
std::string desc = field.m_desc;
|
||||
switch(field.m_idx_mode)
|
||||
{
|
||||
case json_event_filter_check::IDX_REQUIRED:
|
||||
case json_event_filter_check::IDX_ALLOWED:
|
||||
desc += " (";
|
||||
desc += json_event_filter_check::s_index_mode_strs[field.m_idx_mode];
|
||||
desc += ", ";
|
||||
desc += json_event_filter_check::s_index_type_strs[field.m_idx_type];
|
||||
desc += ")";
|
||||
break;
|
||||
case json_event_filter_check::IDX_NONE:
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
std::string str = falco::utils::wrap_text(desc, namelen, DESCRIPTION_TEXT_START, CONSOLE_LINE_LEN);
|
||||
printf("%s\n", str.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -153,34 +157,18 @@ void falco_engine::load_rules(const string &rules_content, bool verbose, bool al
|
||||
|
||||
void falco_engine::load_rules(const string &rules_content, bool verbose, bool all_events, uint64_t &required_engine_version)
|
||||
{
|
||||
// The engine must have been given an inspector by now.
|
||||
if(! m_inspector)
|
||||
{
|
||||
throw falco_exception("No inspector provided");
|
||||
}
|
||||
|
||||
if(!m_sinsp_factory)
|
||||
{
|
||||
m_sinsp_factory = make_shared<sinsp_filter_factory>(m_inspector);
|
||||
}
|
||||
|
||||
if(!m_rules)
|
||||
{
|
||||
m_rules = new falco_rules(m_inspector,
|
||||
this,
|
||||
m_ls);
|
||||
m_rules.reset(new falco_rules(this,
|
||||
m_ls));
|
||||
|
||||
for(auto const &it : m_filter_factories)
|
||||
{
|
||||
m_rules->add_filter_factory(it.first, it.second);
|
||||
}
|
||||
}
|
||||
|
||||
// Note that falco_formats is added to the lua state used
|
||||
// by the falco engine only. Within the engine, only
|
||||
// formats.formatter is used, so we can unconditionally set
|
||||
// json_output to false.
|
||||
bool json_output = false;
|
||||
bool json_include_output_property = false;
|
||||
bool json_include_tags_property = false;
|
||||
falco_formats::init(m_inspector, this, m_ls, json_output, json_include_output_property, json_include_tags_property);
|
||||
|
||||
m_rules->load_rules(rules_content, verbose, all_events, m_extra, m_replace_container_info, m_min_priority, required_engine_version);
|
||||
m_rules->load_rules(rules_content, verbose, all_events, m_extra, m_replace_container_info, m_min_priority, required_engine_version, m_required_plugin_versions);
|
||||
}
|
||||
|
||||
void falco_engine::load_rules_file(const string &rules_filename, bool verbose, bool all_events)
|
||||
@@ -213,13 +201,10 @@ void falco_engine::enable_rule(const string &substring, bool enabled, const stri
|
||||
uint16_t ruleset_id = find_ruleset_id(ruleset);
|
||||
bool match_exact = false;
|
||||
|
||||
m_sinsp_rules->enable(substring, match_exact, enabled, ruleset_id);
|
||||
m_k8s_audit_rules->enable(substring, match_exact, enabled, ruleset_id);
|
||||
}
|
||||
|
||||
void falco_engine::enable_rule(const string &substring, bool enabled)
|
||||
{
|
||||
enable_rule(substring, enabled, m_default_ruleset);
|
||||
for(auto &it : m_rulesets)
|
||||
{
|
||||
it.second->enable(substring, match_exact, enabled, ruleset_id);
|
||||
}
|
||||
}
|
||||
|
||||
void falco_engine::enable_rule_exact(const string &rule_name, bool enabled, const string &ruleset)
|
||||
@@ -227,26 +212,20 @@ void falco_engine::enable_rule_exact(const string &rule_name, bool enabled, cons
|
||||
uint16_t ruleset_id = find_ruleset_id(ruleset);
|
||||
bool match_exact = true;
|
||||
|
||||
m_sinsp_rules->enable(rule_name, match_exact, enabled, ruleset_id);
|
||||
m_k8s_audit_rules->enable(rule_name, match_exact, enabled, ruleset_id);
|
||||
}
|
||||
|
||||
void falco_engine::enable_rule_exact(const string &rule_name, bool enabled)
|
||||
{
|
||||
enable_rule_exact(rule_name, enabled, m_default_ruleset);
|
||||
for(auto &it : m_rulesets)
|
||||
{
|
||||
it.second->enable(rule_name, match_exact, enabled, ruleset_id);
|
||||
}
|
||||
}
|
||||
|
||||
void falco_engine::enable_rule_by_tag(const set<string> &tags, bool enabled, const string &ruleset)
|
||||
{
|
||||
uint16_t ruleset_id = find_ruleset_id(ruleset);
|
||||
|
||||
m_sinsp_rules->enable_tags(tags, enabled, ruleset_id);
|
||||
m_k8s_audit_rules->enable_tags(tags, enabled, ruleset_id);
|
||||
}
|
||||
|
||||
void falco_engine::enable_rule_by_tag(const set<string> &tags, bool enabled)
|
||||
{
|
||||
enable_rule_by_tag(tags, enabled, m_default_ruleset);
|
||||
for(auto &it : m_rulesets)
|
||||
{
|
||||
it.second->enable_tags(tags, enabled, ruleset_id);
|
||||
}
|
||||
}
|
||||
|
||||
void falco_engine::set_min_priority(falco_common::priority_type priority)
|
||||
@@ -272,68 +251,85 @@ uint64_t falco_engine::num_rules_for_ruleset(const std::string &ruleset)
|
||||
{
|
||||
uint16_t ruleset_id = find_ruleset_id(ruleset);
|
||||
|
||||
return m_sinsp_rules->num_rules_for_ruleset(ruleset_id) +
|
||||
m_k8s_audit_rules->num_rules_for_ruleset(ruleset_id);
|
||||
uint64_t ret = 0;
|
||||
for(auto &it : m_rulesets)
|
||||
{
|
||||
ret += it.second->num_rules_for_ruleset(ruleset_id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void falco_engine::evttypes_for_ruleset(std::vector<bool> &evttypes, const std::string &ruleset)
|
||||
void falco_engine::evttypes_for_ruleset(std::string &source, std::set<uint16_t> &evttypes, const std::string &ruleset)
|
||||
{
|
||||
uint16_t ruleset_id = find_ruleset_id(ruleset);
|
||||
|
||||
return m_sinsp_rules->evttypes_for_ruleset(evttypes, ruleset_id);
|
||||
auto it = m_rulesets.find(source);
|
||||
if(it == m_rulesets.end())
|
||||
{
|
||||
string err = "Unknown event source " + source;
|
||||
throw falco_exception(err);
|
||||
}
|
||||
|
||||
it->second->evttypes_for_ruleset(evttypes, ruleset_id);
|
||||
|
||||
}
|
||||
|
||||
void falco_engine::syscalls_for_ruleset(std::vector<bool> &syscalls, const std::string &ruleset)
|
||||
std::shared_ptr<gen_event_formatter> falco_engine::create_formatter(const std::string &source,
|
||||
const std::string &output)
|
||||
{
|
||||
uint16_t ruleset_id = find_ruleset_id(ruleset);
|
||||
auto it = m_format_factories.find(source);
|
||||
|
||||
return m_sinsp_rules->syscalls_for_ruleset(syscalls, ruleset_id);
|
||||
if(it == m_format_factories.end())
|
||||
{
|
||||
string err = "Unknown event source " + source;
|
||||
throw falco_exception(err);
|
||||
}
|
||||
|
||||
return it->second->create_formatter(output);
|
||||
}
|
||||
|
||||
unique_ptr<falco_engine::rule_result> falco_engine::process_sinsp_event(sinsp_evt *ev, uint16_t ruleset_id)
|
||||
unique_ptr<falco_engine::rule_result> falco_engine::process_event(std::string &source, gen_event *ev, uint16_t ruleset_id)
|
||||
{
|
||||
if(should_drop_evt())
|
||||
{
|
||||
return unique_ptr<struct rule_result>();
|
||||
}
|
||||
|
||||
if(!m_sinsp_rules->run(ev, ruleset_id))
|
||||
auto it = m_rulesets.find(source);
|
||||
if(it == m_rulesets.end())
|
||||
{
|
||||
string err = "Unknown event source " + source;
|
||||
throw falco_exception(err);
|
||||
}
|
||||
|
||||
if (!it->second->run(ev, ruleset_id))
|
||||
{
|
||||
return unique_ptr<struct rule_result>();
|
||||
}
|
||||
|
||||
unique_ptr<struct rule_result> res(new rule_result());
|
||||
res->source = "syscall";
|
||||
res->source = source;
|
||||
|
||||
populate_rule_result(res, ev);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
unique_ptr<falco_engine::rule_result> falco_engine::process_sinsp_event(sinsp_evt *ev)
|
||||
unique_ptr<falco_engine::rule_result> falco_engine::process_event(std::string &source, gen_event *ev)
|
||||
{
|
||||
return process_sinsp_event(ev, m_default_ruleset_id);
|
||||
return process_event(source, ev, m_default_ruleset_id);
|
||||
}
|
||||
|
||||
unique_ptr<falco_engine::rule_result> falco_engine::process_k8s_audit_event(json_event *ev, uint16_t ruleset_id)
|
||||
void falco_engine::add_source(const std::string &source,
|
||||
std::shared_ptr<gen_event_filter_factory> filter_factory,
|
||||
std::shared_ptr<gen_event_formatter_factory> formatter_factory)
|
||||
{
|
||||
if(should_drop_evt())
|
||||
{
|
||||
return unique_ptr<struct rule_result>();
|
||||
}
|
||||
m_filter_factories[source] = filter_factory;
|
||||
m_format_factories[source] = formatter_factory;
|
||||
|
||||
// All k8s audit events have the single tag "1".
|
||||
if(!m_k8s_audit_rules->run((gen_event *) ev, 1, ruleset_id))
|
||||
{
|
||||
return unique_ptr<struct rule_result>();
|
||||
}
|
||||
|
||||
unique_ptr<struct rule_result> res(new rule_result());
|
||||
res->source = "k8s_audit";
|
||||
|
||||
populate_rule_result(res, ev);
|
||||
|
||||
return res;
|
||||
std::shared_ptr<falco_ruleset> ruleset(new falco_ruleset());
|
||||
m_rulesets[source] = ruleset;
|
||||
}
|
||||
|
||||
void falco_engine::populate_rule_result(unique_ptr<struct rule_result> &res, gen_event *ev)
|
||||
@@ -386,90 +382,12 @@ void falco_engine::populate_rule_result(unique_ptr<struct rule_result> &res, gen
|
||||
}
|
||||
}
|
||||
|
||||
bool falco_engine::parse_k8s_audit_json(nlohmann::json &j, std::list<json_event> &evts, bool top)
|
||||
{
|
||||
// Note that nlohmann::basic_json::value can throw nlohmann::basic_json::type_error (302, 306)
|
||||
try
|
||||
{
|
||||
// If the object is an array, call parse_k8s_audit_json again for each item.
|
||||
if(j.is_array())
|
||||
{
|
||||
if(top)
|
||||
{
|
||||
for(auto &item : j)
|
||||
{
|
||||
// Note we only handle a single top level array, to
|
||||
// avoid excessive recursion.
|
||||
if(! parse_k8s_audit_json(item, evts, false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If the kind is EventList, split it into individual events
|
||||
if(j.value("kind", "<NA>") == "EventList")
|
||||
{
|
||||
for(auto &je : j["items"])
|
||||
{
|
||||
evts.emplace_back();
|
||||
je["kind"] = "Event";
|
||||
|
||||
uint64_t ns = 0;
|
||||
if(!sinsp_utils::parse_iso_8601_utc_string(je.value(k8s_audit_time, "<NA>"), ns))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string tmp;
|
||||
sinsp_utils::ts_to_string(ns, &tmp, false, true);
|
||||
|
||||
evts.back().set_jevt(je, ns);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if(j.value("kind", "<NA>") == "Event")
|
||||
{
|
||||
evts.emplace_back();
|
||||
uint64_t ns = 0;
|
||||
if(!sinsp_utils::parse_iso_8601_utc_string(j.value(k8s_audit_time, "<NA>"), ns))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
evts.back().set_jevt(j, ns);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch(exception &e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unique_ptr<falco_engine::rule_result> falco_engine::process_k8s_audit_event(json_event *ev)
|
||||
{
|
||||
return process_k8s_audit_event(ev, m_default_ruleset_id);
|
||||
}
|
||||
|
||||
void falco_engine::describe_rule(string *rule)
|
||||
{
|
||||
return m_rules->describe_rule(rule);
|
||||
}
|
||||
|
||||
// Print statistics on the the rules that triggered
|
||||
// Print statistics on the rules that triggered
|
||||
void falco_engine::print_stats()
|
||||
{
|
||||
lua_getglobal(m_ls, lua_print_stats.c_str());
|
||||
@@ -490,29 +408,67 @@ void falco_engine::print_stats()
|
||||
|
||||
}
|
||||
|
||||
void falco_engine::add_sinsp_filter(string &rule,
|
||||
set<uint32_t> &evttypes,
|
||||
set<uint32_t> &syscalls,
|
||||
set<string> &tags,
|
||||
sinsp_filter* filter)
|
||||
void falco_engine::add_filter(std::shared_ptr<gen_event_filter> filter,
|
||||
std::string &rule,
|
||||
std::string &source,
|
||||
std::set<std::string> &tags)
|
||||
{
|
||||
m_sinsp_rules->add(rule, evttypes, syscalls, tags, filter);
|
||||
auto it = m_rulesets.find(source);
|
||||
if(it == m_rulesets.end())
|
||||
{
|
||||
string err = "Unknown event source " + source;
|
||||
throw falco_exception(err);
|
||||
}
|
||||
|
||||
it->second->add(source, rule, tags, filter);
|
||||
}
|
||||
|
||||
void falco_engine::add_k8s_audit_filter(string &rule,
|
||||
set<string> &tags,
|
||||
json_event_filter* filter)
|
||||
bool falco_engine::is_source_valid(const std::string &source)
|
||||
{
|
||||
// All k8s audit events have a single tag "1".
|
||||
std::set<uint32_t> event_tags = {1};
|
||||
return (m_rulesets.find(source) != m_rulesets.end());
|
||||
}
|
||||
|
||||
m_k8s_audit_rules->add(rule, tags, event_tags, filter);
|
||||
bool falco_engine::is_plugin_compatible(const std::string &name,
|
||||
const std::string &version,
|
||||
std::string &required_version)
|
||||
{
|
||||
sinsp_plugin::version plugin_version(version);
|
||||
|
||||
if(!plugin_version.m_valid)
|
||||
{
|
||||
throw falco_exception(string("Plugin version string ") + version + " not valid");
|
||||
}
|
||||
|
||||
if(m_required_plugin_versions.find(name) == m_required_plugin_versions.end())
|
||||
{
|
||||
// No required engine versions, so no restrictions. Compatible.
|
||||
return true;
|
||||
}
|
||||
|
||||
for(auto &rversion : m_required_plugin_versions[name])
|
||||
{
|
||||
sinsp_plugin::version req_version(rversion);
|
||||
if (!plugin_version.check(req_version))
|
||||
{
|
||||
required_version = rversion;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void falco_engine::clear_filters()
|
||||
{
|
||||
m_sinsp_rules.reset(new falco_sinsp_ruleset());
|
||||
m_k8s_audit_rules.reset(new falco_ruleset());
|
||||
m_rulesets.clear();
|
||||
|
||||
for(auto &it : m_filter_factories)
|
||||
{
|
||||
std::shared_ptr<falco_ruleset> ruleset(new falco_ruleset());
|
||||
m_rulesets[it.first] = ruleset;
|
||||
}
|
||||
|
||||
m_required_plugin_versions.clear();
|
||||
}
|
||||
|
||||
void falco_engine::set_sampling_ratio(uint32_t sampling_ratio)
|
||||
@@ -546,23 +502,3 @@ inline bool falco_engine::should_drop_evt()
|
||||
double coin = (random() * (1.0/RAND_MAX));
|
||||
return (coin >= (1.0/(m_sampling_multiplier * m_sampling_ratio)));
|
||||
}
|
||||
|
||||
sinsp_filter_factory &falco_engine::sinsp_factory()
|
||||
{
|
||||
if(!m_sinsp_factory)
|
||||
{
|
||||
throw falco_exception("No sinsp factory created yet");
|
||||
}
|
||||
|
||||
return *(m_sinsp_factory.get());
|
||||
}
|
||||
|
||||
json_event_filter_factory &falco_engine::json_factory()
|
||||
{
|
||||
if(!m_json_factory)
|
||||
{
|
||||
throw falco_exception("No json factory created yet");
|
||||
}
|
||||
|
||||
return *(m_json_factory.get());
|
||||
}
|
||||
|
||||
@@ -28,14 +28,10 @@ limitations under the License.
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "sinsp.h"
|
||||
#include "filter.h"
|
||||
|
||||
#include "json_evt.h"
|
||||
#include "gen_filter.h"
|
||||
#include "rules.h"
|
||||
#include "ruleset.h"
|
||||
|
||||
#include "config_falco_engine.h"
|
||||
#include "falco_common.h"
|
||||
|
||||
//
|
||||
@@ -47,7 +43,7 @@ limitations under the License.
|
||||
class falco_engine : public falco_common
|
||||
{
|
||||
public:
|
||||
falco_engine(bool seed_rng=true, const std::string& alternate_lua_dir=FALCO_ENGINE_SOURCE_LUA_DIR);
|
||||
falco_engine(bool seed_rng=true);
|
||||
virtual ~falco_engine();
|
||||
|
||||
// A given engine has a version which identifies the fields
|
||||
@@ -57,7 +53,8 @@ public:
|
||||
static uint32_t engine_version();
|
||||
|
||||
// Print to stdout (using printf) a description of each field supported by this engine.
|
||||
void list_fields(bool names_only=false);
|
||||
// If source is non-empty, only fields for the provided source are printed.
|
||||
void list_fields(std::string &source, bool verbose, bool names_only);
|
||||
|
||||
//
|
||||
// Load rules either directly or from a filename.
|
||||
@@ -80,25 +77,16 @@ public:
|
||||
// be passed as an argument to process_event(). This allows
|
||||
// for different sets of rules being active at once.
|
||||
//
|
||||
void enable_rule(const std::string &substring, bool enabled, const std::string &ruleset);
|
||||
|
||||
// Wrapper that assumes the default ruleset
|
||||
void enable_rule(const std::string &substring, bool enabled);
|
||||
void enable_rule(const std::string &substring, bool enabled, const std::string &ruleset = s_default_ruleset);
|
||||
|
||||
|
||||
// Like enable_rule, but the rule name must be an exact match.
|
||||
void enable_rule_exact(const std::string &rule_name, bool enabled, const std::string &ruleset);
|
||||
|
||||
// Wrapper that assumes the default ruleset
|
||||
void enable_rule_exact(const std::string &rule_name, bool enabled);
|
||||
void enable_rule_exact(const std::string &rule_name, bool enabled, const std::string &ruleset = s_default_ruleset);
|
||||
|
||||
//
|
||||
// Enable/Disable any rules with any of the provided tags (set, exact matches only)
|
||||
//
|
||||
void enable_rule_by_tag(const std::set<std::string> &tags, bool enabled, const std::string &ruleset);
|
||||
|
||||
// Wrapper that assumes the default ruleset
|
||||
void enable_rule_by_tag(const std::set<std::string> &tags, bool enabled);
|
||||
void enable_rule_by_tag(const std::set<std::string> &tags, bool enabled, const std::string &ruleset = s_default_ruleset);
|
||||
|
||||
// Only load rules having this priority or more severe.
|
||||
void set_min_priority(falco_common::priority_type priority);
|
||||
@@ -152,8 +140,8 @@ public:
|
||||
//
|
||||
void set_extra(string &extra, bool replace_container_info);
|
||||
|
||||
// **Methods Related to k8s audit log events, which are
|
||||
// **represented as json objects.
|
||||
// Represents the result of matching an event against a set of
|
||||
// rules.
|
||||
struct rule_result {
|
||||
gen_event *evt;
|
||||
std::string rule;
|
||||
@@ -164,16 +152,6 @@ public:
|
||||
std::set<std::string> tags;
|
||||
};
|
||||
|
||||
//
|
||||
// Given a raw json object, return a list of k8s audit event
|
||||
// objects that represent the object. This method handles
|
||||
// things such as EventList splitting.
|
||||
//
|
||||
// Returns true if the json object was recognized as a k8s
|
||||
// audit event(s), false otherwise.
|
||||
//
|
||||
bool parse_k8s_audit_json(nlohmann::json &j, std::list<json_event> &evts, bool top=true);
|
||||
|
||||
//
|
||||
// Given an event, check it against the set of rules in the
|
||||
// engine and if a matching rule is found, return details on
|
||||
@@ -185,84 +163,81 @@ public:
|
||||
// with a ruleset string.
|
||||
//
|
||||
// the returned rule_result is allocated and must be delete()d.
|
||||
std::unique_ptr<rule_result> process_k8s_audit_event(json_event *ev, uint16_t ruleset_id);
|
||||
std::unique_ptr<rule_result> process_event(std::string &source, gen_event *ev, uint16_t ruleset_id);
|
||||
|
||||
//
|
||||
// Wrapper assuming the default ruleset
|
||||
//
|
||||
std::unique_ptr<rule_result> process_k8s_audit_event(json_event *ev);
|
||||
std::unique_ptr<rule_result> process_event(std::string &source, gen_event *ev);
|
||||
|
||||
//
|
||||
// Add a k8s_audit filter to the engine
|
||||
// Configure the engine to support events with the provided
|
||||
// source, with the provided filter factory and formatter factory.
|
||||
//
|
||||
void add_k8s_audit_filter(std::string &rule,
|
||||
std::set<std::string> &tags,
|
||||
json_event_filter* filter);
|
||||
void add_source(const std::string &source,
|
||||
std::shared_ptr<gen_event_filter_factory> filter_factory,
|
||||
std::shared_ptr<gen_event_formatter_factory> formatter_factory);
|
||||
|
||||
// **Methods Related to Sinsp Events e.g system calls
|
||||
//
|
||||
// Given a ruleset, fill in a bitset containing the event
|
||||
// types for which this ruleset can run.
|
||||
//
|
||||
void evttypes_for_ruleset(std::vector<bool> &evttypes, const std::string &ruleset);
|
||||
// Return whether or not there is a valid filter/formatter
|
||||
// factory for this source.
|
||||
bool is_source_valid(const std::string &source);
|
||||
|
||||
//
|
||||
// Given a ruleset, fill in a bitset containing the syscalls
|
||||
// for which this ruleset can run.
|
||||
// Add a filter for the provided event source to the engine
|
||||
//
|
||||
void syscalls_for_ruleset(std::vector<bool> &syscalls, const std::string &ruleset);
|
||||
void add_filter(std::shared_ptr<gen_event_filter> filter,
|
||||
std::string &rule,
|
||||
std::string &source,
|
||||
std::set<std::string> &tags);
|
||||
|
||||
//
|
||||
// Given an event, check it against the set of rules in the
|
||||
// engine and if a matching rule is found, return details on
|
||||
// the rule that matched. If no rule matched, returns NULL.
|
||||
// Given an event source and ruleset, fill in a bitset
|
||||
// containing the event types for which this ruleset can run.
|
||||
//
|
||||
// When ruleset_id is provided, use the enabled/disabled status
|
||||
// associated with the provided ruleset. This is only useful
|
||||
// when you have previously called enable_rule/enable_rule_by_tag
|
||||
// with a ruleset string.
|
||||
//
|
||||
// the returned rule_result is allocated and must be delete()d.
|
||||
std::unique_ptr<rule_result> process_sinsp_event(sinsp_evt *ev, uint16_t ruleset_id);
|
||||
void evttypes_for_ruleset(std::string &source,
|
||||
std::set<uint16_t> &evttypes,
|
||||
const std::string &ruleset = s_default_ruleset);
|
||||
|
||||
//
|
||||
// Wrapper assuming the default ruleset
|
||||
// Given a source and output string, return an
|
||||
// gen_event_formatter that can format output strings for an
|
||||
// event.
|
||||
//
|
||||
std::unique_ptr<rule_result> process_sinsp_event(sinsp_evt *ev);
|
||||
std::shared_ptr<gen_event_formatter> create_formatter(const std::string &source,
|
||||
const std::string &output);
|
||||
|
||||
//
|
||||
// Add a filter, which is related to the specified set of
|
||||
// event types/syscalls, to the engine.
|
||||
//
|
||||
void add_sinsp_filter(std::string &rule,
|
||||
std::set<uint32_t> &evttypes,
|
||||
std::set<uint32_t> &syscalls,
|
||||
std::set<std::string> &tags,
|
||||
sinsp_filter* filter);
|
||||
|
||||
sinsp_filter_factory &sinsp_factory();
|
||||
json_event_filter_factory &json_factory();
|
||||
// Return whether the provided plugin name + version is
|
||||
// compatible with the current set of loaded rules files.
|
||||
// required_version will be filled in with the required
|
||||
// version when the method returns false.
|
||||
bool is_plugin_compatible(const std::string &name, const std::string &version, std::string &required_version);
|
||||
|
||||
private:
|
||||
|
||||
static nlohmann::json::json_pointer k8s_audit_time;
|
||||
|
||||
//
|
||||
// Determine whether the given event should be matched at all
|
||||
// against the set of rules, given the current sampling
|
||||
// ratio/multiplier.
|
||||
//
|
||||
inline bool should_drop_evt();
|
||||
shared_ptr<sinsp_filter_factory> m_sinsp_factory;
|
||||
shared_ptr<json_event_filter_factory> m_json_factory;
|
||||
|
||||
falco_rules *m_rules;
|
||||
// Maps from event source to object that can generate filters from rules
|
||||
std::map<std::string, std::shared_ptr<gen_event_filter_factory>> m_filter_factories;
|
||||
|
||||
// Maps from event source to object that can format output strings in rules
|
||||
std::map<std::string, std::shared_ptr<gen_event_formatter_factory>> m_format_factories;
|
||||
|
||||
// Maps from event source to the set of rules for that event source
|
||||
std::map<std::string, std::shared_ptr<falco_ruleset>> m_rulesets;
|
||||
|
||||
std::unique_ptr<falco_rules> m_rules;
|
||||
uint16_t m_next_ruleset_id;
|
||||
std::map<string, uint16_t> m_known_rulesets;
|
||||
falco_common::priority_type m_min_priority;
|
||||
|
||||
std::unique_ptr<falco_sinsp_ruleset> m_sinsp_rules;
|
||||
std::unique_ptr<falco_ruleset> m_k8s_audit_rules;
|
||||
// Maps from plugin to a list of required plugin versions
|
||||
// found in any loaded rules files.
|
||||
std::map<std::string, std::list<std::string>> m_required_plugin_versions;
|
||||
|
||||
void populate_rule_result(unique_ptr<struct rule_result> &res, gen_event *ev);
|
||||
|
||||
@@ -289,8 +264,7 @@ private:
|
||||
uint32_t m_sampling_ratio;
|
||||
double m_sampling_multiplier;
|
||||
|
||||
std::string m_lua_main_filename = "rule_loader.lua";
|
||||
std::string m_default_ruleset = "falco-default-ruleset";
|
||||
static const std::string s_default_ruleset;
|
||||
uint32_t m_default_ruleset_id;
|
||||
|
||||
std::string m_extra;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2020 The Falco Authors.
|
||||
Copyright (C) 2021 The Falco Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -14,11 +14,11 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// The version of rules/filter fields/etc supported by this falco
|
||||
// The version of rules/filter fields/etc supported by this Falco
|
||||
// engine.
|
||||
#define FALCO_ENGINE_VERSION (9)
|
||||
#define FALCO_ENGINE_VERSION (11)
|
||||
|
||||
// This is the result of running "falco --list -N | sha256sum" and
|
||||
// represents the fields supported by this version of falco. It's used
|
||||
// represents the fields supported by this version of Falco. It's used
|
||||
// at build time to detect a changed set of fields.
|
||||
#define FALCO_FIELDS_CHECKSUM "2f324e2e66d4b423f53600e7e0fcf2f0ff72e4a87755c490f2ae8f310aba9386"
|
||||
#define FALCO_FIELDS_CHECKSUM "4de812495f8529ac20bda2b9774462b15911a51df293d59fe9ccb6b922fdeb9d"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user