mirror of
https://github.com/falcosecurity/falco.git
synced 2026-03-20 11:42:06 +00:00
Compare commits
322 Commits
embeddable
...
add-app-ac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98bc8703c9 | ||
|
|
b7a92cc154 | ||
|
|
9e4f0888e8 | ||
|
|
db2e2b19b3 | ||
|
|
481d25f8ee | ||
|
|
c07c327d87 | ||
|
|
149fc1e237 | ||
|
|
f9a9ed984c | ||
|
|
df219b5e1d | ||
|
|
3fbc90e99e | ||
|
|
ad42baed7a | ||
|
|
31111ab87b | ||
|
|
7d6b46218f | ||
|
|
fded42c203 | ||
|
|
5ff9101b95 | ||
|
|
36acd6dfbf | ||
|
|
4819748ab0 | ||
|
|
f7a5dd0d5b | ||
|
|
4705a92c49 | ||
|
|
a5d3663c75 | ||
|
|
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 | ||
|
|
bb81133201 | ||
|
|
46d5266ac8 | ||
|
|
3414ca5361 | ||
|
|
0eb170cf5f | ||
|
|
21fa6e9505 | ||
|
|
b82cbb1b59 | ||
|
|
d033868ab9 | ||
|
|
7c98d0047c | ||
|
|
c7d9b6ee7f | ||
|
|
8273e57598 | ||
|
|
b0562242e8 | ||
|
|
ca66b84e5a | ||
|
|
7c9ec9fc17 | ||
|
|
9ea43c2663 | ||
|
|
4d55847bd4 | ||
|
|
a684bec007 | ||
|
|
812aa9b566 | ||
|
|
e0f8b81692 | ||
|
|
874809351f | ||
|
|
4527228ef8 | ||
|
|
e684c95e23 | ||
|
|
2390ca447a | ||
|
|
af0e6da375 | ||
|
|
84e7d3f18f | ||
|
|
2a8c0e8bb7 | ||
|
|
f28688551c | ||
|
|
b12d37a3b8 | ||
|
|
5e027c7fe2 |
@@ -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
|
||||
@@ -403,7 +378,7 @@ jobs:
|
||||
name: Setup
|
||||
command: |
|
||||
apt update -y
|
||||
apt-get install apt-utils bzip2 gpg python python-pip -y
|
||||
apt-get install apt-utils bzip2 gpg python python3-pip -y
|
||||
pip install awscli
|
||||
echo $GPG_KEY | base64 -d | gpg --import
|
||||
- run:
|
||||
@@ -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
|
||||
@@ -517,7 +498,7 @@ jobs:
|
||||
name: Setup
|
||||
command: |
|
||||
apt update -y
|
||||
apt-get install apt-utils bzip2 gpg python python-pip -y
|
||||
apt-get install apt-utils bzip2 gpg python python3-pip -y
|
||||
pip install awscli
|
||||
echo $GPG_KEY | base64 -d | gpg --import
|
||||
- run:
|
||||
@@ -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,12 +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 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.
|
||||
|
||||
@@ -54,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.
|
||||
|
||||
208
CHANGELOG.md
208
CHANGELOG.md
@@ -1,5 +1,195 @@
|
||||
# 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)
|
||||
|
||||
### Security Fixes
|
||||
|
||||
* Fix for a TOCTOU issue that could lead to rule bypass (CVE-2022-26316). For more information, see the [advisory](https://github.com/falcosecurity/falco/security/advisories/GHSA-6v9j-2vm2-ghf7).
|
||||
|
||||
### 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
|
||||
|
||||
### Major Changes
|
||||
|
||||
* new: add `--k8s-node` command-line options, which allows filtering by a node when requesting metadata of pods to the K8s API server [[#1671](https://github.com/falcosecurity/falco/pull/1671)] - [@leogr](https://github.com/leogr)
|
||||
* new(outputs): expose rule tags and event source in gRPC and json outputs [[#1714](https://github.com/falcosecurity/falco/pull/1714)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* new(userspace/falco): add customizable metadata fetching params [[#1667](https://github.com/falcosecurity/falco/pull/1667)] - [@zuc](https://github.com/zuc)
|
||||
|
||||
|
||||
### Minor Changes
|
||||
|
||||
* update: bump driver version to 3aa7a83bf7b9e6229a3824e3fd1f4452d1e95cb4 [[#1744](https://github.com/falcosecurity/falco/pull/1744)] - [@zuc](https://github.com/zuc)
|
||||
* docs: clarify that previous Falco drivers will remain available at https://download.falco.org and no automated cleanup is run anymore [[#1738](https://github.com/falcosecurity/falco/pull/1738)] - [@leodido](https://github.com/leodido)
|
||||
* update(outputs): add configuration option for tags in json outputs [[#1733](https://github.com/falcosecurity/falco/pull/1733)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix(scripts): correct standard output redirection in systemd config (DEB and RPM packages) [[#1697](https://github.com/falcosecurity/falco/pull/1697)] - [@chirabino](https://github.com/chirabino)
|
||||
* fix(scripts): correct lookup order when trying multiple `gcc` versions in the `falco-driver-loader` script [[#1716](https://github.com/falcosecurity/falco/pull/1716)] - [@Spartan-65](https://github.com/Spartan-65)
|
||||
|
||||
|
||||
### Rule Changes
|
||||
|
||||
* rule(list miner_domains): add new miner domains [[#1729](https://github.com/falcosecurity/falco/pull/1729)] - [@AlbertoPellitteri](https://github.com/AlbertoPellitteri)
|
||||
* rule(list https_miner_domains): add new miner domains [[#1729](https://github.com/falcosecurity/falco/pull/1729)] - [@AlbertoPellitteri](https://github.com/AlbertoPellitteri)
|
||||
|
||||
|
||||
### Non user-facing changes
|
||||
|
||||
* add Qonto as adopter [[#1717](https://github.com/falcosecurity/falco/pull/1717)] - [@Issif](https://github.com/Issif)
|
||||
* docs(proposals): proposal for a libs plugin system [[#1637](https://github.com/falcosecurity/falco/pull/1637)] - [@ldegio](https://github.com/ldegio)
|
||||
* build: remove unused `ncurses` dependency [[#1658](https://github.com/falcosecurity/falco/pull/1658)] - [@leogr](https://github.com/leogr)
|
||||
* build(.circleci): use new Debian 11 package names for python-pip [[#1712](https://github.com/falcosecurity/falco/pull/1712)] - [@zuc](https://github.com/zuc)
|
||||
* build(docker): adding libssl-dev, upstream image reference pinned to `debian:buster` [[#1719](https://github.com/falcosecurity/falco/pull/1719)] - [@michalschott](https://github.com/michalschott)
|
||||
* fix(test): avoid output_strictly_contains failures [[#1724](https://github.com/falcosecurity/falco/pull/1724)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* Remove duplicate allowed ecr registry rule [[#1725](https://github.com/falcosecurity/falco/pull/1725)] - [@TomKeyte](https://github.com/TomKeyte)
|
||||
* docs(RELEASE.md): switch to 3 releases per year [[#1711](https://github.com/falcosecurity/falco/pull/1711)] - [@leogr](https://github.com/leogr)
|
||||
|
||||
|
||||
## v0.29.1
|
||||
|
||||
Released on 2021-06-29
|
||||
@@ -209,8 +399,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)
|
||||
@@ -659,7 +849,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
|
||||
@@ -774,7 +964,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
|
||||
|
||||
@@ -969,7 +1159,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)]
|
||||
|
||||
@@ -1084,7 +1274,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)]
|
||||
|
||||
@@ -1117,7 +1307,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)]
|
||||
|
||||
@@ -1172,7 +1362,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)]
|
||||
@@ -1273,7 +1463,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
|
||||
|
||||
45
README.md
45
README.md
@@ -5,7 +5,7 @@
|
||||
|
||||
[](https://circleci.com/gh/falcosecurity/falco) [](https://bestpractices.coreinfrastructure.org/projects/2317) [](COPYING)
|
||||
|
||||
Want to talk? Join us on the [#falco](https://kubernetes.slack.com/archives/CMWH3EH32) channel in the [Kubernetes Slack](https://slack.k8s.io).
|
||||
Want to talk? Join us on the [#falco](https://kubernetes.slack.com/messages/falco) channel in the [Kubernetes Slack](https://slack.k8s.io).
|
||||
|
||||
### Latest releases
|
||||
|
||||
@@ -58,10 +58,25 @@ Notes:
|
||||
---
|
||||
|
||||
The Falco Project, originally created by [Sysdig](https://sysdig.com), is an incubating [CNCF](https://cncf.io) open source cloud native runtime security tool.
|
||||
Falco makes it easy to consume kernel events, and enrich those events with information from Kubernetes and the rest of the cloud native stack.
|
||||
Falco makes it easy to consume kernel events, and enrich those events with information from Kubernetes and the rest of the cloud native stack.
|
||||
Falco can also be extended to other data sources by using plugins.
|
||||
Falco has a rich set of security rules specifically built for Kubernetes, Linux, and cloud-native.
|
||||
If a rule is violated in a system, Falco will send an alert notifying the user of the violation and its severity.
|
||||
|
||||
### What can Falco detect?
|
||||
|
||||
Falco can detect and alert on any behavior that involves making Linux system calls.
|
||||
Falco alerts can be triggered by the use of specific system calls, their arguments, and by properties of the calling process.
|
||||
For example, Falco can easily detect incidents including but not limited to:
|
||||
|
||||
- A shell is running inside a container or pod in Kubernetes.
|
||||
- A container is running in privileged mode, or is mounting a sensitive path, such as `/proc`, from the host.
|
||||
- A server process is spawning a child process of an unexpected type.
|
||||
- Unexpected read of a sensitive file, such as `/etc/shadow`.
|
||||
- A non-device file is written to `/dev`.
|
||||
- A standard system binary, such as `ls`, is making an outbound network connection.
|
||||
- A privileged pod is started in a Kubernetes cluster.
|
||||
|
||||
### Installing Falco
|
||||
|
||||
If you would like to run Falco in **production** please adhere to the [official installation guide](https://falco.org/docs/getting-started/installation/).
|
||||
@@ -90,20 +105,22 @@ The Falco Project supports various SDKs for this endpoint.
|
||||
| Rust | [client-rs](https://github.com/falcosecurity/client-rs) |
|
||||
| Python | [client-py](https://github.com/falcosecurity/client-py) |
|
||||
|
||||
### Plugins
|
||||
|
||||
### What can Falco detect?
|
||||
Falco comes with a [plugin framework](https://falco.org/docs/plugins/) that extends it to potentially any cloud detection scenario. Plugins are shared libraries that conform to a documented API and allow for:
|
||||
|
||||
Falco can detect and alert on any behavior that involves making Linux system calls.
|
||||
Falco alerts can be triggered by the use of specific system calls, their arguments, and by properties of the calling process.
|
||||
For example, Falco can easily detect incidents including but not limited to:
|
||||
- Adding new event sources that can be used in rules;
|
||||
- Adding the ability to define new fields and extract information from events.
|
||||
|
||||
The Falco Project maintains [various plugins](https://github.com/falcosecurity/plugins) and provides SDKs for plugin development.
|
||||
|
||||
|
||||
##### SDKs
|
||||
|
||||
| Language | Repository |
|
||||
|----------|-------------------------------------------------------------------------------|
|
||||
| Go | [falcosecurity/plugin-sdk-go](https://github.com/falcosecurity/plugin-sdk-go) |
|
||||
|
||||
- A shell is running inside a container or pod in Kubernetes.
|
||||
- A container is running in privileged mode, or is mounting a sensitive path, such as `/proc`, from the host.
|
||||
- A server process is spawning a child process of an unexpected type.
|
||||
- Unexpected read of a sensitive file, such as `/etc/shadow`.
|
||||
- A non-device file is written to `/dev`.
|
||||
- A standard system binary, such as `ls`, is making an outbound network connection.
|
||||
- A privileged pod is started in a Kubernetes cluster.
|
||||
|
||||
### Documentation
|
||||
|
||||
@@ -115,7 +132,7 @@ To get involved with The Falco Project please visit [the community repository](h
|
||||
|
||||
How to reach out?
|
||||
|
||||
- Join the #falco channel on the [Kubernetes Slack](https://slack.k8s.io)
|
||||
- Join the [#falco](https://kubernetes.slack.com/messages/falco) channel on the [Kubernetes Slack](https://slack.k8s.io)
|
||||
- [Join the Falco mailing list](https://lists.cncf.io/g/cncf-falco-dev)
|
||||
- [Read the Falco documentation](https://falco.org/docs/)
|
||||
|
||||
|
||||
@@ -4,7 +4,9 @@ Our release process is mostly automated, but we still need some manual steps to
|
||||
|
||||
Changes and new features are grouped in [milestones](https://github.com/falcosecurity/falco/milestones), the milestone with the next version represents what is going to be released.
|
||||
|
||||
A release happens every two months ([as per community discussion](https://github.com/falcosecurity/community/blob/master/meeting-notes/2020-09-30.md#agenda)), and we need to assign owners for each (usually we pair a new person with an experienced one). Assignees and the due date are proposed during the [weekly community call](https://github.com/falcosecurity/community). Note that hotfix releases can happen as soon as it is needed.
|
||||
Falco releases are due to happen 3 times per year. Our current schedule sees a new release by the end of January, May, and September each year. Hotfix releases can happen whenever it's needed.
|
||||
|
||||
Moreover, we need to assign owners for each release (usually we pair a new person with an experienced one). Assignees and the due date are proposed during the [weekly community call](https://github.com/falcosecurity/community).
|
||||
|
||||
Finally, on the proposed due date the assignees for the upcoming release proceed with the processes described below.
|
||||
|
||||
@@ -93,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
|
||||
@@ -143,6 +143,10 @@ Sometimes this word is incorrectly used to refer to a `probe`.
|
||||
|
||||
The global term for the software that sends events from the kernel. Such as the eBPF `probe` or the `kernel module`.
|
||||
|
||||
#### Plugin
|
||||
|
||||
Used to describe a dynamic shared library (`.so` files in Unix, `.dll` files in Windows) that conforms to a documented API and allows to extend Falco's capabilities.
|
||||
|
||||
#### Falco
|
||||
|
||||
The name of the project, and also the name of [the main engine](https://github.com/falcosecurity/falco) that the rest of the project is built on.
|
||||
|
||||
@@ -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 "17f5df52a7d9ed6bb12d3b1768460def8439936d")
|
||||
set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=34a2a466f1e5045591f102de2bc812d9b4f0d5874094cc73b97a7970fb2a3a18")
|
||||
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,4 +1,4 @@
|
||||
FROM debian:stable
|
||||
FROM debian:buster
|
||||
|
||||
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
|
||||
|
||||
@@ -30,6 +30,7 @@ RUN apt-get update \
|
||||
libc6-dev \
|
||||
libelf-dev \
|
||||
libmpx2 \
|
||||
libssl-dev \
|
||||
llvm-7 \
|
||||
netcat \
|
||||
xz-utils \
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
41
falco.yaml
41
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.
|
||||
@@ -46,6 +72,12 @@ json_output: false
|
||||
# (user=root ....") in the json output.
|
||||
json_include_output_property: true
|
||||
|
||||
# When using json output, whether or not to include the "tags" property
|
||||
# itself in the json output. If set to true, outputs caused by rules
|
||||
# with no tags will have a "tags" field set to an empty array. If set to
|
||||
# false, the "tags" field will not be included in the json output at all.
|
||||
json_include_tags_property: true
|
||||
|
||||
# Send information logs to stderr and/or syslog Note these are *not* security
|
||||
# notification logs! These are just Falco lifecycle (and possibly error) logs.
|
||||
log_stderr: true
|
||||
@@ -60,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
|
||||
@@ -214,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)
|
||||
@@ -249,3 +282,9 @@ grpc:
|
||||
# Make sure to have a consumer for them or leave this disabled.
|
||||
grpc_output:
|
||||
enabled: false
|
||||
|
||||
# Container orchestrator metadata fetching params
|
||||
metadata_download:
|
||||
max_mb: 100
|
||||
chunk_wait_us: 1000
|
||||
watch_freq_sec: 1
|
||||
|
||||
@@ -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,6 +2,8 @@
|
||||
|
||||
This document reflects when and how we clean up the Falco artifacts from their storage location.
|
||||
|
||||
**Superseded by**: [drivers-storage-s3 proposal](https://github.com/falcosecurity/falco/blob/master/proposals/20201025-drivers-storage-s3.md).
|
||||
|
||||
## Motivation
|
||||
|
||||
The [bintray](https://bintray.com/falcosecurity) open-source plan offers 10GB free space for storing artifacts.
|
||||
@@ -88,15 +90,25 @@ 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.
|
||||
|
||||
The candidate is an AWS S3 bucket responsible for holding the deleted driver version files.
|
||||
|
||||
#### Notice
|
||||
|
||||
The current mechanism the Falco community uses to store the Falco drivers is explained by the [drivers-storage-s3](https://github.com/falcosecurity/falco/blob/master/proposals/20201025-drivers-storage-s3.md) proposal.
|
||||
|
||||
### Implementation
|
||||
|
||||
The [test-infra](https://github.com/falcosecurity/test-infra) CI, specifically its part dedicated to run the **Drivers Build Grid** that runs every time it detects changes into the `driverkit` directory of the [test-infra](https://github.com/falcosecurity/test-infra) repository,
|
||||
will have a new job - called `drivers/cleanup` - responsible for removing all the Falco driver versions except the last two.
|
||||
|
||||
This job will be triggered after the `drivers/publish` completed successfully on the master branch.
|
||||
This job will be triggered after the `drivers/publish` completed successfully on the master branch.
|
||||
|
||||
#### Notice
|
||||
|
||||
At the moment of writing (2021 09 28) the `drivers/cleanup` job is no more in place.
|
||||
|
||||
Pragmatically, this means that the older Falco drivers will remain available in their [S3 bucket](https://download.falco.org/?prefix=driver/).
|
||||
|
||||
613
proposals/20210501-plugin-system.md
Normal file
613
proposals/20210501-plugin-system.md
Normal file
@@ -0,0 +1,613 @@
|
||||
# Plugin System
|
||||
|
||||
## Summary
|
||||
|
||||
This is a proposal to create an infrastructure to extend the functionality of the Falco libraries via plugins.
|
||||
|
||||
Plugins will allow users to easily extend the functionality of the libraries and, as a consequence, of Falco and any other tool based on the libraries.
|
||||
|
||||
This proposal, in particular, focuses on two types of plugins: source plugins and extractor plugins.
|
||||
|
||||
## Motivation
|
||||
|
||||
[libscap](https://github.com/falcosecurity/libs/tree/master/userspace/libscap) and [libsinsp](https://github.com/falcosecurity/libs/tree/master/userspace/libsinsp) provide a powerful data capture framework, with a rich set of features that includes:
|
||||
|
||||
- data capture
|
||||
- trace files management
|
||||
- enrichment
|
||||
- filtering
|
||||
- formatting and screen rendering
|
||||
- Lua scripting (chisels)
|
||||
|
||||
These features have been designed with one specific input in mind: system calls. However, they are generically adaptable to a broad set of inputs, such as cloud logs.
|
||||
|
||||
With this proposal, we want to dramatically extend the scope of what the libraries, Falco and other tools can be applied to. We want to do it in a way that is easy, efficient and empowers anyone in the community to write a plugin.
|
||||
|
||||
## Goals
|
||||
|
||||
- To design and implement a plugin framework that makes the libraries more modular and extensible
|
||||
- To have a framework that is easy to use
|
||||
- To support dynamic loading of plugins, so that the libraries can be extended without having to be recompiled and relinked
|
||||
- To enable users to write plugins in any language, with a particular focus on Go, C and C++
|
||||
- To have an efficient plugin framework so that, performance-wise, writing a plugin is as close as possible as extending the libraries internal source code
|
||||
- To make it possible to write plugins for Linux, MacOS and Windows
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- To implement plugins other than source and extractor: to be approached as separate task
|
||||
- To document the plugin framework and interface: to be approached as separate task
|
||||
|
||||
## Proposal
|
||||
|
||||
### Plugin Common Information
|
||||
|
||||
Both source and extractor plugins have the following:
|
||||
|
||||
- A required api version, to ensure compatibility with the plugin framework.
|
||||
- A name
|
||||
- A description
|
||||
- A version
|
||||
- A contact field for the plugin authors (website, github repo, twitter, etc).
|
||||
- Functions to initialize and destroy the plugin internal state.
|
||||
|
||||
### Plugin types
|
||||
|
||||
Initially, we will implement support for two types of plugins: source plugins and extractor plugins.
|
||||
|
||||
#### Source Plugin
|
||||
|
||||
A source plugin implements a new sinsp/scap event source. It has the ability to "open" and "close" a session that provides events. It also has the ability to return an event to the plugin framework via a next() method. Events returned by source plugins have an "event source", which describes the information in the event. This is distinct from the plugin name to allow for multiple kinds of plugins to generate the same kind of events. For example, there might be plugins gke-audit-bridge, eks-audit-bridge, ibmcloud-audit-bridge, etc. that all fetch [K8s Audit](https://kubernetes.io/docs/tasks/debug-application-cluster/audit/) information. The plugins would have different names but would have the same event source "k8s_audit".
|
||||
|
||||
Source plugins also have the ability to extract information from events based on fields. For example, a field proc.name extracts a process name from a syscall event. The plugin returns a set of supported fields, and there are functions to extract a value given an event and field. The plugin framework can then build filtering expressions/Falco rule conditions based on these fields combined with relational and/or logical operators. For example, given an expression "ct.name=root and ct.region=us-east-1", the plugin framework handles parsing the expression, calling the plugin to extract values for a given event, and determining the result of the expression. In a Falco output string like "An EC2 Node was created (name=%ec2.name region=%ct.region)", the plugin framework handles parsing the output string, calling the plugin to extract values for a given event, and building the resolved string.
|
||||
|
||||
Source plugins also provide an "id", which is globally unique and is used in capture files (see below).
|
||||
|
||||
#### Extractor Plugin
|
||||
|
||||
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 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.
|
||||
|
||||
libscap will define a new event type called "pluginevent" that contains two fields:
|
||||
|
||||
* "plugin ID": This uniquely identifies the plugin that generated this event.
|
||||
* "event_data": This is a variable-length data buffer containing the event data, as returned by the plugin.
|
||||
|
||||
Defining an event for plugins allows creating capture files from plugins. These capture files can be saved, read, filtered, etc, like any other capture file, allowing for later analysis/display/etc.
|
||||
|
||||
### Plugins format
|
||||
|
||||
Plugins are dynamic libraries (.so files in Unix, .dll files in windows) that export a minimum set of functions that the libraries will recognize.
|
||||
|
||||
Plugins are versioned using semantic versioning to minimize regressions and compatibility issues.
|
||||
|
||||
Plugins can be written in any language, as long as they export the required functions. Go, however, is the preferred language to write plugins, followed by C/C++.
|
||||
|
||||
### Protecting from plugin issues
|
||||
|
||||
The libraries will do everything possible to validate the data coming from the plugins and protect Falco and the other consumers from corrupted data. However, for performance reasons, plugins will be "trusted": they will run in the same thread and address space as Falco and they could crash the program. We assume that the user will be in control of plugin loading and will make sure only trusted plugins are loaded/packaged with Falco.
|
||||
|
||||
### 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 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.
|
||||
|
||||
Similarly, plugin developers must register event sources with the Falco organization. This allows coordination between plugins that wish to provide compatible payloads, and to allow extractor plugins to know what data format is associated with a given event source.
|
||||
|
||||
### golang plugin SDK
|
||||
|
||||
To facilitate the development of plugins written in go, an SDK has been developed. We intend this SDK (and future SDKs for other languages) to be part of the Falco organization. For this reason, we submitted the following incubation request: https://github.com/falcosecurity/evolution/issues/62
|
||||
|
||||
### Proposed API (subject to change)
|
||||
|
||||
```c
|
||||
// This struct represents an event returned by the plugin, and is used
|
||||
// below in next()/next_batch().
|
||||
// - data: pointer to a memory buffer pointer. The plugin will set it
|
||||
// to point to the memory containing the next event. Once returned,
|
||||
// the memory is owned by the plugin framework and will be freed via
|
||||
// a call to free().
|
||||
// - datalen: pointer to a 32bit integer. The plugin will set it the size of the
|
||||
// buffer pointed by data.
|
||||
// - ts: the event timestamp. Can be (uint64_t)-1, in which case the engine will
|
||||
// automatically fill the event time with the current time.
|
||||
typedef struct ss_plugin_event
|
||||
{
|
||||
uint8_t *data;
|
||||
uint32_t datalen;
|
||||
uint64_t ts;
|
||||
} ss_plugin_event;
|
||||
|
||||
//
|
||||
// This is the opaque pointer to the state of a plugin.
|
||||
// It points to any data that might be needed plugin-wise. It is
|
||||
// allocated by init() and must be destroyed by destroy().
|
||||
// It is defined as void because the engine doesn't care what it is
|
||||
// and it treats is as opaque.
|
||||
//
|
||||
typedef void ss_plugin_t;
|
||||
|
||||
//
|
||||
// This is the opaque pointer to the state of an open instance of the source
|
||||
// plugin.
|
||||
// It points to any data that is needed while a capture is running. It is
|
||||
// allocated by open() and must be destroyed by close().
|
||||
// It is defined as void because the engine doesn't care what it is
|
||||
// and it treats is as opaque.
|
||||
//
|
||||
typedef void ss_instance_t;
|
||||
|
||||
//
|
||||
// Interface for a sinsp/scap source plugin
|
||||
//
|
||||
//
|
||||
// NOTE: For all functions below that return a char *, the memory
|
||||
// pointed to by the char * must be allocated by the plugin using
|
||||
// malloc() and should be freed by the caller using free().
|
||||
//
|
||||
// For each function below, the exported symbol from the dynamic
|
||||
// library should have a prefix of "plugin_"
|
||||
// (e.g. plugin_get_required_api_version, plugin_init, etc.)
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
//
|
||||
// Return the version of the plugin API used by this plugin.
|
||||
// Required: yes
|
||||
// Return value: the API version string, in the following format:
|
||||
// "<major>.<minor>.<patch>", e.g. "1.2.3".
|
||||
// NOTE: to ensure correct interoperability between the engine and the plugins,
|
||||
// we use a semver approach. Plugins are required to specify the version
|
||||
// of the API they run against, and the engine will take care of checking
|
||||
// and enforcing compatibility.
|
||||
//
|
||||
char* (*get_required_api_version)();
|
||||
//
|
||||
// Return the plugin type.
|
||||
// Required: yes
|
||||
// Should return TYPE_SOURCE_PLUGIN. It still makes sense to
|
||||
// have a function get_type() as the plugin interface will
|
||||
// often dlsym() functions from shared libraries, and can't
|
||||
// inspect any C struct type.
|
||||
//
|
||||
uint32_t (*get_type)();
|
||||
//
|
||||
// Initialize the plugin and, if needed, allocate its state.
|
||||
// Required: yes
|
||||
// Arguments:
|
||||
// - config: a string with the plugin configuration. The format of the
|
||||
// string is chosen by the plugin itself.
|
||||
// - rc: pointer to an integer that will contain the initialization result,
|
||||
// as a SCAP_* value (e.g. SCAP_SUCCESS=0, SCAP_FAILURE=1)
|
||||
// Return value: pointer to the plugin state that will be treated as opaque
|
||||
// by the engine and passed to the other plugin functions.
|
||||
// If rc is SCAP_FAILURE, this function should return NULL.
|
||||
//
|
||||
ss_plugin_t* (*init)(char* config, int32_t* rc);
|
||||
//
|
||||
// Destroy the plugin and, if plugin state was allocated, free it.
|
||||
// Required: yes
|
||||
//
|
||||
void (*destroy)(ss_plugin_t* s);
|
||||
//
|
||||
// Return a string with the error that was last generated by
|
||||
// the plugin.
|
||||
// Required: yes
|
||||
//
|
||||
// In cases where any other api function returns an error, the
|
||||
// plugin should be prepared to return a human-readable error
|
||||
// string with more context for the error. The plugin manager
|
||||
// calls get_last_error() to access that string.
|
||||
//
|
||||
char* (*get_last_error)(ss_plugin_t* s);
|
||||
//
|
||||
// Return the unique ID of the plugin.
|
||||
// Required: yes
|
||||
// EVERY SOURCE PLUGIN (see get_type()) MUST OBTAIN AN OFFICIAL ID FROM THE
|
||||
// FALCOSECURITY ORGANIZATION, OTHERWISE IT WON'T PROPERLY COEXIST WITH OTHER PLUGINS.
|
||||
//
|
||||
uint32_t (*get_id)();
|
||||
//
|
||||
// Return the name of the plugin, which will be printed when displaying
|
||||
// information about the plugin.
|
||||
// Required: yes
|
||||
//
|
||||
char* (*get_name)();
|
||||
//
|
||||
// Return the descriptions of the plugin, which will be printed when displaying
|
||||
// information about the plugin or its events.
|
||||
// Required: yes
|
||||
//
|
||||
char* (*get_description)();
|
||||
//
|
||||
// Return a string containing contact info (url, email, twitter, etc) for
|
||||
// the plugin authors.
|
||||
// Required: yes
|
||||
//
|
||||
char* (*get_contact)();
|
||||
//
|
||||
// Return the version of this plugin itself
|
||||
// Required: yes
|
||||
// Return value: a string with a version identifier, in the following format:
|
||||
// "<major>.<minor>.<patch>", e.g. "1.2.3".
|
||||
// This differs from the api version in that this versions the
|
||||
// plugin itself, as compared to the plugin interface. When
|
||||
// reading capture files, the major version of the plugin that
|
||||
// generated events must match the major version of the plugin
|
||||
// used to read events.
|
||||
//
|
||||
char* (*get_version)();
|
||||
//
|
||||
// Return a string describing the events generated by this source plugin.
|
||||
// Required: yes
|
||||
// Example event sources would be strings like "syscall",
|
||||
// "k8s_audit", etc. The source can be used by extractor
|
||||
// plugins to filter the events they receive.
|
||||
//
|
||||
char* (*get_event_source)();
|
||||
//
|
||||
// Return the list of extractor fields exported by this plugin. Extractor
|
||||
// fields can be used in Falco rule conditions and sysdig filters.
|
||||
// Required: no
|
||||
// Return value: a string with the list of fields encoded as a json
|
||||
// array.
|
||||
// Each field entry is a json object with the following properties:
|
||||
// "type": one of "string", "uint64"
|
||||
// "name": a string with a name for the field
|
||||
// "desc": a string with a description of the field
|
||||
// Example return value:
|
||||
// [
|
||||
// {"type": "string", "name": "field1", "desc": "Describing field 1"},
|
||||
// {"type": "uint64", "name": "field2", "desc": "Describing field 2"}
|
||||
// ]
|
||||
char* (*get_fields)();
|
||||
//
|
||||
// Open the source and start a capture.
|
||||
// Required: yes
|
||||
// Arguments:
|
||||
// - s: the plugin state returned by init()
|
||||
// - params: the open parameters, as a string. The format is defined by the plugin
|
||||
// itsef
|
||||
// - rc: pointer to an integer that will contain the open result, as a SCAP_* value
|
||||
// (e.g. SCAP_SUCCESS=0, SCAP_FAILURE=1)
|
||||
// Return value: a pointer to the open context that will be passed to next(),
|
||||
// close(), event_to_string() and extract_*.
|
||||
//
|
||||
ss_instance_t* (*open)(ss_plugin_t* s, char* params, int32_t* rc);
|
||||
//
|
||||
// Close a capture.
|
||||
// Required: yes
|
||||
// Arguments:
|
||||
// - s: the plugin context, returned by init(). Can be NULL.
|
||||
// - h: the capture context, returned by open(). Can be NULL.
|
||||
//
|
||||
void (*close)(ss_plugin_t* s, ss_instance_t* h);
|
||||
//
|
||||
// Return the next event.
|
||||
// Required: yes
|
||||
// Arguments:
|
||||
// - s: the plugin context, returned by init(). Can be NULL.
|
||||
// - h: the capture context, returned by open(). Can be NULL.
|
||||
//
|
||||
// - evt: pointer to a ss_plugin_event pointer. The plugin should
|
||||
// allocate a ss_plugin_event struct using malloc(), as well as
|
||||
// allocate the data buffer within the ss_plugin_event struct.
|
||||
// Both the struct and data buffer are owned by the plugin framework
|
||||
// and will free them using free().
|
||||
//
|
||||
// Return value: the status of the operation (e.g. SCAP_SUCCESS=0, SCAP_FAILURE=1,
|
||||
// SCAP_TIMEOUT=-1)
|
||||
//
|
||||
int32_t (*next)(ss_plugin_t* s, ss_instance_t* h, ss_plugin_event **evt);
|
||||
//
|
||||
// Return the read progress.
|
||||
// Required: no
|
||||
// Arguments:
|
||||
// - progress_pct: the read progress, as a number between 0 (no data has been read)
|
||||
// and 10000 (100% of the data has been read). This encoding allows the engine to
|
||||
// print progress decimals without requiring to deal with floating point numbers
|
||||
// (which could cause incompatibility problems with some languages).
|
||||
// Return value: a string representation of the read
|
||||
// progress. This might include the progress percentage
|
||||
// combined with additional context added by the plugin. If
|
||||
// NULL, progress_pct should be used.
|
||||
// NOTE: reporting progress is optional and in some case could be impossible. However,
|
||||
// when possible, it's recommended as it provides valuable information to the
|
||||
// user.
|
||||
//
|
||||
char* (*get_progress)(ss_plugin_t* s, ss_instance_t* h, uint32_t* progress_pct);
|
||||
//
|
||||
// Return a text representation of an event generated by this source plugin.
|
||||
// Required: yes
|
||||
// Arguments:
|
||||
// - data: the buffer from an event produced by next().
|
||||
// - datalen: the length of the buffer from an event produced by next().
|
||||
// Return value: the text representation of the event. This is used, for example,
|
||||
// by sysdig to print a line for the given event.
|
||||
//
|
||||
char *(*event_to_string)(ss_plugin_t *s, const uint8_t *data, uint32_t datalen);
|
||||
//
|
||||
// Extract a filter field value from an event.
|
||||
// We offer multiple versions of extract(), differing from each other only in
|
||||
// the type of the value they return (string, integer...).
|
||||
// Required: no
|
||||
// Arguments:
|
||||
// - evtnum: the number of the event that is bein processed
|
||||
// - id: the numeric identifier of the field to extract. It corresponds to the
|
||||
// position of the field in the array returned by get_fields().
|
||||
// - arg: the field argument, if an argument has been specified for the field,
|
||||
// otherwise it's NULL. For example:
|
||||
// * if the field specified by the user is foo.bar[pippo], arg will be the
|
||||
// string "pippo"
|
||||
// * if the field specified by the user is foo.bar, arg will be NULL
|
||||
// - data: the buffer produced by next().
|
||||
// - datalen: the length of the buffer produced by next().
|
||||
// - field_present: nonzero if the field is present for the given event.
|
||||
// Return value: the produced value of the filter field. For extract_str(), a
|
||||
// NULL return value means that the field is missing for the given event.
|
||||
//
|
||||
char *(*extract_str)(ss_plugin_t *s, uint64_t evtnum, const char * field, const char *arg, uint8_t *data, uint32_t datalen);
|
||||
uint64_t (*extract_u64)(ss_plugin_t *s, uint64_t evtnum, const char *field, const char *arg, uint8_t *data, uint32_t datalen, uint32_t *field_present);
|
||||
//
|
||||
// This is an optional, internal, function used to speed up event capture by
|
||||
// batching the calls to next().
|
||||
// On success:
|
||||
// - nevts will be filled in with the number of events.
|
||||
// - evts: pointer to an ss_plugin_event pointer. The plugin should
|
||||
// allocate an array of contiguous ss_plugin_event structs using malloc(),
|
||||
// as well as allocate each data buffer within each ss_plugin_event
|
||||
// struct using malloc(). Both the array of structs and each data buffer are
|
||||
// owned by the plugin framework and will free them using free().
|
||||
// Required: no
|
||||
//
|
||||
int32_t (*next_batch)(ss_plugin_t* s, ss_instance_t* h, uint32_t *nevts, ss_plugin_event **evts);
|
||||
//
|
||||
// This is an optional, internal, function used to speed up value extraction
|
||||
// Required: no
|
||||
//
|
||||
int32_t (*register_async_extractor)(ss_plugin_t *s, async_extractor_info *info);
|
||||
|
||||
//
|
||||
// The following members are PRIVATE for the engine and should not be touched.
|
||||
//
|
||||
ss_plugin_t* state;
|
||||
ss_instance_t* handle;
|
||||
uint32_t id;
|
||||
char *name;
|
||||
} source_plugin_info;
|
||||
|
||||
//
|
||||
// Interface for a sinsp/scap extractor plugin
|
||||
//
|
||||
//
|
||||
// NOTE: For all functions below that return a char *, the memory
|
||||
// pointed to by the char * must be allocated by the plugin using
|
||||
// malloc() and should be freed by the caller using free().
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
//
|
||||
// Return the version of the plugin API used by this plugin.
|
||||
// Required: yes
|
||||
// Return value: the API version string, in the following format:
|
||||
// "<major>.<minor>.<patch>", e.g. "1.2.3".
|
||||
// NOTE: to ensure correct interoperability between the engine and the plugins,
|
||||
// we use a semver approach. Plugins are required to specify the version
|
||||
// of the API they run against, and the engine will take care of checking
|
||||
// and enforcing compatibility.
|
||||
//
|
||||
char* (*get_required_api_version)();
|
||||
//
|
||||
// Return the plugin type.
|
||||
// Required: yes
|
||||
// Should return TYPE_EXTRACTOR_PLUGIN. It still makes sense to
|
||||
// have a function get_type() as the plugin interface will
|
||||
// often dlsym() functions from shared libraries, and can't
|
||||
// inspect any C struct type.
|
||||
//
|
||||
uint32_t (*get_type)();
|
||||
//
|
||||
// Initialize the plugin and, if needed, allocate its state.
|
||||
// Required: yes
|
||||
// Arguments:
|
||||
// - config: a string with the plugin configuration. The format of the
|
||||
// string is chosen by the plugin itself.
|
||||
// - rc: pointer to an integer that will contain the initialization result,
|
||||
// as a SCAP_* value (e.g. SCAP_SUCCESS=0, SCAP_FAILURE=1)
|
||||
// Return value: pointer to the plugin state that will be treated as opaque
|
||||
// by the engine and passed to the other plugin functions.
|
||||
//
|
||||
ss_plugin_t* (*init)(char* config, int32_t* rc);
|
||||
//
|
||||
// Destroy the plugin and, if plugin state was allocated, free it.
|
||||
// Required: yes
|
||||
//
|
||||
void (*destroy)(ss_plugin_t* s);
|
||||
//
|
||||
// Return a string with the error that was last generated by
|
||||
// the plugin.
|
||||
// Required: yes
|
||||
//
|
||||
// In cases where any other api function returns an error, the
|
||||
// plugin should be prepared to return a human-readable error
|
||||
// string with more context for the error. The plugin manager
|
||||
// calls get_last_error() to access that string.
|
||||
//
|
||||
char* (*get_last_error)(ss_plugin_t* s);
|
||||
//
|
||||
// Return the name of the plugin, which will be printed when displaying
|
||||
// information about the plugin.
|
||||
// Required: yes
|
||||
//
|
||||
char* (*get_name)();
|
||||
//
|
||||
// Return the descriptions of the plugin, which will be printed when displaying
|
||||
// information about the plugin or its events.
|
||||
// Required: yes
|
||||
//
|
||||
char* (*get_description)();
|
||||
//
|
||||
// Return a string containing contact info (url, email, twitter, etc) for
|
||||
// the plugin author.
|
||||
// Required: yes
|
||||
//
|
||||
char* (*get_contact)();
|
||||
//
|
||||
// Return the version of this plugin itself
|
||||
// Required: yes
|
||||
// Return value: a string with a version identifier, in the following format:
|
||||
// "<major>.<minor>.<patch>", e.g. "1.2.3".
|
||||
// This differs from the api version in that this versions the
|
||||
// plugin itself, as compared to the plugin interface. When
|
||||
// reading capture files, the major version of the plugin that
|
||||
// generated events must match the major version of the plugin
|
||||
// used to read events.
|
||||
//
|
||||
char* (*get_version)();
|
||||
//
|
||||
// Return a string describing the event sources that this
|
||||
// extractor plugin can consume.
|
||||
// Required: no
|
||||
// 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 extractor
|
||||
// plugin will receive every event.
|
||||
//
|
||||
char* (*get_extract_event_sources)();
|
||||
//
|
||||
// Return the list of extractor fields exported by this plugin. Extractor
|
||||
// fields can be used in Falco rules and sysdig filters.
|
||||
// Required: yes
|
||||
// Return value: a string with the list of fields encoded as a json
|
||||
// array.
|
||||
//
|
||||
char* (*get_fields)();
|
||||
//
|
||||
// Extract a filter field value from an event.
|
||||
// We offer multiple versions of extract(), differing from each other only in
|
||||
// the type of the value they return (string, integer...).
|
||||
// Required: for plugins of type TYPE_EXTRACTOR_PLUGIN only
|
||||
// Arguments:
|
||||
// - evtnum: the number of the event that is being processed
|
||||
// - id: the numeric identifier of the field to extract. It corresponds to the
|
||||
// position of the field in the array returned by get_fields().
|
||||
// - arg: the field argument, if an argument has been specified for the field,
|
||||
// otherwise it's NULL. For example:
|
||||
// * if the field specified by the user is foo.bar[pippo], arg will be the
|
||||
// string "pippo"
|
||||
// * if the field specified by the user is foo.bar, arg will be NULL
|
||||
// - data: the buffer produced by next().
|
||||
// - datalen: the length of the buffer produced by next().
|
||||
// - field_present: nonzero if the field is present for the given event.
|
||||
// Return value: the produced value of the filter field. For extract_str(), a
|
||||
// NULL return value means that the field is missing for the given event.
|
||||
//
|
||||
char *(*extract_str)(ss_plugin_t *s, uint64_t evtnum, const char *field, const char *arg, uint8_t *data, uint32_t datalen);
|
||||
uint64_t (*extract_u64)(ss_plugin_t *s, uint64_t evtnum, const char *field, const char *arg, uint8_t *data, uint32_t datalen, uint32_t *field_present);
|
||||
} extractor_plugin_info;
|
||||
|
||||
```
|
||||
|
||||
### Event Sources and Falco Rules
|
||||
|
||||
Falco rules already have the notion of a "source", using the source property in rules objects, and there are currently two kinds of event sources: "syscall" and "k8s_audit". We will use the source property in Falco rules to map a given rule to the event source on which the rule runs.
|
||||
|
||||
For example, given a plugin with source "aws_cloudtrail", and a Falco rule with source "aws_cloudtrail", the rule will be evaluated for any events generated by the plugin.
|
||||
|
||||
Similarly, an extractor plugin that includes "aws_cloudtrail" in its set of event sources will have the opportunity to extract information from aws_cloudtrail events if a matching field is found in the rule's condition, exception, or output properties.
|
||||
|
||||
This, combined with the restrictions below, allows a set of loaded rules files to contain a mix of rules for plugins as well as "core" syscall/k8s_audit events.
|
||||
|
||||
We will also make a change to compile rules/macros/lists selectively based on the set of loaded plugins (specifically, their event sources), instead of unconditionally as Falco is started. This is especially important for macros, which do not contain a source property, but might contain fields that are only implemented by a given plugin.
|
||||
|
||||
### 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 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.
|
||||
|
||||
We only need to ensure the following:
|
||||
|
||||
* That only one plugin is loaded at a time that exports a given event source. For example, the libraries can load either a gke-audit-bridge plugin with event source k8s_audit, or eks-audit-bridge with event source k8s_audit, but not both.
|
||||
* That for a mix of source and extractor plugins having the same event source, that the fields are distinct. For example, a source plugin with source k8s_audit can export ka.* fields, and an extractor plugin with event source k8s_audit can export a jevt.value[/...] field, and the appropriate plugin will be used to extract fields from k8s_audit events as fields are parsed from condition expressions/output format strings.
|
||||
|
||||
### Plugin Versions and Falco Rules
|
||||
|
||||
To allow rules files to document the plugin versions they are compatible with, we will add a new top-level field `required_plugin_versions` to the Falco rules file format. The field is optional, and if not provided no plugin compatibility checks will be performed. The syntax of `required_plugin_versions` will be the following:
|
||||
|
||||
```yaml
|
||||
- required_plugin_versions:
|
||||
- name: <plugin_name>
|
||||
version: x.y.z
|
||||
...
|
||||
```
|
||||
|
||||
Below required_plugin_versions is a list of objects, where each object has `name` and `version` properties. If a plugin is loaded, and if an entry in `required_plugin_versions` has a matching name, then the loaded plugin version must be semver compatible with the version property.
|
||||
|
||||
Falco can load multiple rules files, and each file may contain its own `required_plugin_versions` property. In this case, name+version pairs across all files will be merged, and in the case of duplicate names all provided versions must be compatible.
|
||||
|
||||
### Loading the plugins
|
||||
|
||||
The mechanics of loading a plugin are implemented in the libraries and leverage the dynamic library functionality of the operating system (dlopen/dlsym in unix, LoadLibrary/GetProcAddress in Windows). The plugin loading code also ensures that:
|
||||
|
||||
- the plugin is valid, i.e. that it exports the set of expected symbols
|
||||
- the plugin has an api version number that is compatible with the libraries instance
|
||||
- that only one source plugin is loaded at a time for a given event source
|
||||
- if a mix of source and extractor plugins are loaded for a given event source, that the exported fields have unique names that don't overlap across plugins
|
||||
|
||||
#### Loading plugins in falcosecurity/libs
|
||||
|
||||
At the libraries level, loading plugins is handled via the static method:
|
||||
|
||||
```c++
|
||||
void sinsp_plugin::register_plugin(sinsp* inspector, string filepath, char* config, ...)
|
||||
```
|
||||
|
||||
filepath points to a dynamic library containing code that exports plugin API functions. config contains arbitrary config content which is passed to init().
|
||||
|
||||
Note that the code using the libraries is responsible for determining the location of plugin libraries and their configuration.
|
||||
|
||||
#### Loading plugins in falcosecurity/falco
|
||||
|
||||
Falco will control/configure loading plugins via the new "plugins" property in falco.yaml. Here's an example:
|
||||
|
||||
```yaml
|
||||
plugins:
|
||||
- name: aws_cloudtrail
|
||||
library_path: aws_cloudtrail/plugin.so
|
||||
init_config: "..."
|
||||
open_params: "..."
|
||||
- name: http_json
|
||||
library_path: http_json/plugin.so
|
||||
init_config_file: http_json/config.txt
|
||||
open_params_file: http_json/params.txt
|
||||
|
||||
# Optional
|
||||
load_plugins: [aws_cloudtrail]
|
||||
```
|
||||
|
||||
A new "plugins" property in falco.yaml will define the set of plugins that can be loaded by Falco. The property contains a list of objects, with the following properties:
|
||||
|
||||
* name: Only used for load_plugins, but by convention should be the same as the value returned by the name() api function.
|
||||
* library_path: a path to the shared library. The path can be relative, in which case it is relative to Falco's "share" directory under a "plugins" subdirectory e.g. /usr/share/falco/plugins.
|
||||
* init_config: If present, the exact configuration text that will be provided as an argument to the init() function.
|
||||
* init_config_file: If present, the provided file will be read and the contents will be provided as an argument to the init() function.
|
||||
* open_params: If present, the exact params text that will be provided as an argument to the open() function.
|
||||
* open_params_file: If present, the provided file will be read and the contents will be provided as an argument to the open() function.
|
||||
|
||||
For a given yaml object in the plugins list, only one of init_config/init_config_file and one of open_params/open_params_file can be provided at a time.
|
||||
|
||||
A new "load_plugins" property in falco.yaml will allow for loading a subset of the plugins defined in plugins. If present, only the plugins with the provided names will be loaded.
|
||||
|
||||
### Examples
|
||||
|
||||
We have an initial version working, consisting of:
|
||||
|
||||
* A version of falcosecurity/libs that supports the [plugin framework](https://github.com/falcosecurity/libs/tree/new/plugin-system-api-additions)
|
||||
* Support code and examples for [writing plugins in go](https://github.com/mstemm/libsinsp-plugin-sdk-go/tree/new/plugin-system-api-additions)
|
||||
* A [cloudtrail](https://github.com/mstemm/plugins/tree/new/plugin-system-api-additions) plugin that can generate events from cloudtrail logs and extract fields from those events.
|
||||
* A version of Falco that uses all of the above to [load and evaluate rules with plugins](https://github.com/leogr/falco/tree/new/plugin-system-api-additions)
|
||||
@@ -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))
|
||||
@@ -440,6 +443,9 @@
|
||||
- list: shell_config_directories
|
||||
items: [/etc/zsh]
|
||||
|
||||
- macro: user_known_shell_config_modifiers
|
||||
condition: (never_true)
|
||||
|
||||
- rule: Modify Shell Configuration File
|
||||
desc: Detect attempt to modify shell configuration files
|
||||
condition: >
|
||||
@@ -449,6 +455,7 @@
|
||||
fd.directory in (shell_config_directories))
|
||||
and not proc.name in (shell_binaries)
|
||||
and not exe_running_docker_save
|
||||
and not user_known_shell_config_modifiers
|
||||
output: >
|
||||
a shell configuration file has been modified (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pcmdline=%proc.pcmdline file=%fd.name container_id=%container.id image=%container.image.repository)
|
||||
priority:
|
||||
@@ -561,7 +568,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 +779,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 +1110,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 +1225,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
|
||||
@@ -1755,7 +1766,6 @@
|
||||
(container.image.repository startswith "602401143452.dkr.ecr" or
|
||||
container.image.repository startswith "877085696533.dkr.ecr" or
|
||||
container.image.repository startswith "800184023465.dkr.ecr" or
|
||||
container.image.repository startswith "602401143452.dkr.ecr" or
|
||||
container.image.repository startswith "918309763551.dkr.ecr" or
|
||||
container.image.repository startswith "961992271922.dkr.ecr" or
|
||||
container.image.repository startswith "590381155156.dkr.ecr" or
|
||||
@@ -1827,6 +1837,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
|
||||
@@ -1855,7 +1866,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,
|
||||
@@ -1871,19 +1882,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.
|
||||
@@ -1906,12 +1904,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
|
||||
@@ -2198,7 +2197,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
|
||||
@@ -2236,7 +2235,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:"
|
||||
@@ -2260,7 +2259,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
|
||||
@@ -2296,7 +2295,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
|
||||
@@ -2310,7 +2309,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 ...)
|
||||
@@ -2364,7 +2363,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
|
||||
@@ -2572,15 +2572,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"))
|
||||
|
||||
@@ -2588,7 +2588,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")
|
||||
|
||||
@@ -2627,7 +2627,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)
|
||||
@@ -2706,8 +2706,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
|
||||
@@ -2747,7 +2757,12 @@
|
||||
"xmr-eu1.nanopool.org","xmr-eu2.nanopool.org",
|
||||
"xmr-jp1.nanopool.org","xmr-us-east1.nanopool.org",
|
||||
"xmr-us-west1.nanopool.org","xmr.crypto-pool.fr",
|
||||
"xmr.pool.minergate.com", "rx.unmineable.com"
|
||||
"xmr.pool.minergate.com", "rx.unmineable.com",
|
||||
"ss.antpool.com","dash.antpool.com",
|
||||
"eth.antpool.com","zec.antpool.com",
|
||||
"xmc.antpool.com","btm.antpool.com",
|
||||
"stratum-dash.antpool.com","stratum-xmc.antpool.com",
|
||||
"stratum-btm.antpool.com"
|
||||
]
|
||||
|
||||
- list: https_miner_domains
|
||||
@@ -2764,7 +2779,12 @@
|
||||
"stratum-ltc.antpool.com",
|
||||
"stratum-zec.antpool.com",
|
||||
"stratum.antpool.com",
|
||||
"xmr.crypto-pool.fr"
|
||||
"xmr.crypto-pool.fr",
|
||||
"ss.antpool.com",
|
||||
"stratum-dash.antpool.com",
|
||||
"stratum-xmc.antpool.com",
|
||||
"stratum-btm.antpool.com",
|
||||
"btm.antpool.com"
|
||||
]
|
||||
|
||||
- list: http_miner_domains
|
||||
@@ -2793,7 +2813,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.
|
||||
@@ -2802,13 +2822,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]
|
||||
@@ -2944,7 +2964,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:
|
||||
@@ -2977,7 +2997,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
|
||||
@@ -3027,7 +3047,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]
|
||||
@@ -3045,13 +3065,17 @@
|
||||
- macro: mount_info
|
||||
condition: (proc.args="" or proc.args intersects ("-V", "-l", "-h"))
|
||||
|
||||
- macro: user_known_mount_in_privileged_containers
|
||||
condition: (never_true)
|
||||
|
||||
- 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
|
||||
and proc.name=mount
|
||||
and not mount_info
|
||||
and not user_known_mount_in_privileged_containers
|
||||
output: Mount was executed inside a privileged container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline %container.info image=%container.image.repository:%container.image.tag)
|
||||
priority: WARNING
|
||||
tags: [container, cis, mitre_lateral_movement]
|
||||
@@ -3074,7 +3098,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)
|
||||
|
||||
@@ -154,19 +154,32 @@ load_kernel_module_compile() {
|
||||
fi
|
||||
|
||||
# Try to compile using all the available gcc versions
|
||||
for CURRENT_GCC in $(which gcc) $(ls "$(dirname "$(which gcc)")"/gcc-* | grep 'gcc-[0-9]\+' | sort -r); do
|
||||
for CURRENT_GCC in $(which gcc) $(ls "$(dirname "$(which gcc)")"/gcc-* | grep 'gcc-[0-9]\+' | sort -n -r -k 2 -t -); do
|
||||
echo "* Trying to dkms install ${DRIVER_NAME} module with GCC ${CURRENT_GCC}"
|
||||
echo "#!/usr/bin/env bash" > /tmp/falco-dkms-make
|
||||
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/*
|
||||
|
||||
@@ -19,6 +19,7 @@ ProtectSystem=full
|
||||
ProtectKernelTunables=true
|
||||
RestrictRealtime=true
|
||||
RestrictAddressFamilies=~AF_PACKET
|
||||
StandardOutput=null
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -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]
|
||||
@@ -43,6 +43,12 @@ json_output: false
|
||||
# (user=root ....") in the json output.
|
||||
json_include_output_property: true
|
||||
|
||||
# When using json output, whether or not to include the "tags" property
|
||||
# itself in the json output. If set to true, outputs caused by rules
|
||||
# with no tags will have a "tags" field set to an empty array. If set to
|
||||
# false, the "tags" field will not be included in the json output at all.
|
||||
json_include_tags_property: true
|
||||
|
||||
# Send information logs to stderr and/or syslog Note these are *not* security
|
||||
# notification logs! These are just Falco lifecycle (and possibly error) logs.
|
||||
log_stderr: true
|
||||
|
||||
@@ -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):
|
||||
@@ -90,8 +91,11 @@ class FalcoTest(Test):
|
||||
self.json_output = self.params.get('json_output', '*', default=False)
|
||||
self.json_include_output_property = self.params.get(
|
||||
'json_include_output_property', '*', default=True)
|
||||
self.json_include_tags_property = self.params.get(
|
||||
'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'))
|
||||
|
||||
@@ -128,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)
|
||||
|
||||
@@ -388,10 +393,11 @@ class FalcoTest(Test):
|
||||
for line in res.stdout.decode("utf-8").splitlines():
|
||||
if line.startswith('{'):
|
||||
obj = json.loads(line)
|
||||
attrs = ['time', 'rule', 'priority']
|
||||
if self.json_include_output_property:
|
||||
attrs = ['time', 'rule', 'priority', 'output']
|
||||
else:
|
||||
attrs = ['time', 'rule', 'priority']
|
||||
attrs.append('output')
|
||||
if self.json_include_tags_property:
|
||||
attrs.append('tags')
|
||||
for attr in attrs:
|
||||
if not attr in obj:
|
||||
self.fail(
|
||||
@@ -409,10 +415,15 @@ class FalcoTest(Test):
|
||||
else:
|
||||
actual = open(output['actual']).read()
|
||||
|
||||
if expected not in actual:
|
||||
self.fail("Output '{}' does not strictly contains the expected content '{}'".format(
|
||||
output['actual'], output['expected']))
|
||||
return False
|
||||
actual_cursor = actual
|
||||
expected_lines = expected.splitlines()
|
||||
for line in expected_lines:
|
||||
pos = actual_cursor.find(line)
|
||||
if pos < 0:
|
||||
self.fail("Output '{}' does not strictly contains the expected content '{}'".format(
|
||||
output['actual'], output['expected']))
|
||||
return False
|
||||
actual_cursor = actual_cursor[pos + len(line):]
|
||||
|
||||
return True
|
||||
|
||||
@@ -513,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)
|
||||
|
||||
@@ -609,8 +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 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.priority)
|
||||
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.addl_cmdline_opts)
|
||||
|
||||
for tag in self.disable_tags:
|
||||
cmd += ' -T {}'.format(tag)
|
||||
@@ -641,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))
|
||||
@@ -675,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
|
||||
@@ -688,7 +692,7 @@ trace_files: !mux
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- rules/single_rule.yaml
|
||||
- rules/single_rule_with_tags.yaml
|
||||
conf_file: confs/stdout_output.yaml
|
||||
trace_file: trace_files/cat_write.scap
|
||||
time_iso_8601: true
|
||||
@@ -721,7 +725,7 @@ trace_files: !mux
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- rules/single_rule.yaml
|
||||
- rules/single_rule_with_tags.yaml
|
||||
conf_file: confs/grpc_unix_socket.yaml
|
||||
trace_file: trace_files/cat_write.scap
|
||||
run_duration: 5
|
||||
@@ -745,6 +749,10 @@ trace_files: !mux
|
||||
# For the hostname, since we don't know that beforehand,
|
||||
# only check the field presence
|
||||
- "hostname: "
|
||||
#tags
|
||||
- "tags: \"filesystem\""
|
||||
- "tags: \"process\""
|
||||
- "tags: \"testing\""
|
||||
|
||||
detect_counts:
|
||||
detect: True
|
||||
@@ -1107,6 +1115,25 @@ trace_files: !mux
|
||||
trace_file: trace_files/cat_write.scap
|
||||
stdout_contains: "^(?!.*Warning An open of /dev/null was seen.*)"
|
||||
|
||||
json_output_no_tags_property:
|
||||
json_output: True
|
||||
json_include_tags_property: False
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- rules/rule_append.yaml
|
||||
trace_file: trace_files/cat_write.scap
|
||||
stdout_contains: "^(?!.*\"tags\":[ ]*\\[.*\\],.*)"
|
||||
|
||||
json_output_empty_tags_property:
|
||||
json_output: True
|
||||
detect: True
|
||||
detect_level: WARNING
|
||||
rules_file:
|
||||
- rules/rule_append.yaml
|
||||
trace_file: trace_files/cat_write.scap
|
||||
stdout_contains: "^(.*\"tags\":[ ]*\\[\\],.*)"
|
||||
|
||||
in_operator_netmasks:
|
||||
detect: True
|
||||
detect_level: INFO
|
||||
@@ -1119,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
|
||||
@@ -1137,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
|
||||
@@ -1152,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
|
||||
@@ -1169,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
|
||||
|
||||
|
||||
122
test/falco_tests_plugins.yaml
Normal file
122
test/falco_tests_plugins.yaml
Normal file
@@ -0,0 +1,122 @@
|
||||
#
|
||||
# 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: "Can not load multiple source plugins. cloudtrail already loaded."
|
||||
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: "Extractor plugin not compatible with event source aws_cloudtrail."
|
||||
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: "Extractor plugins have overlapping compatible event source test_source."
|
||||
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: "Plugin cloudtrail version .* not compatible with required plugin version 100000.0.0."
|
||||
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"
|
||||
|
||||
no_plugins_unknown_source_macro:
|
||||
detect: False
|
||||
rules_file:
|
||||
- rules/plugins/cloudtrail_macro.yaml
|
||||
trace_file: trace_files/empty.scap
|
||||
stderr_contains: "Macro Some Cloudtrail Macro: warning .unknown-source.: unknown source aws_cloudtrail, skipping"
|
||||
|
||||
no_plugins_unknown_source_rule_exception:
|
||||
detect: False
|
||||
rules_file:
|
||||
- rules/plugins/cloudtrail_create_instances_exceptions.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,8 +1,8 @@
|
||||
{"output":"2016-08-04T16:17:57.881781397+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","time":"2016-08-04T16:17:57.881781397Z", "output_fields": {"evt.time.iso8601":1470327477881781397,"proc.cmdline":"cat /dev/null"}}
|
||||
{"output":"2016-08-04T16:17:57.881785348+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","time":"2016-08-04T16:17:57.881785348Z", "output_fields": {"evt.time.iso8601":1470327477881785348,"proc.cmdline":"cat /dev/null"}}
|
||||
{"output":"2016-08-04T16:17:57.881796705+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","time":"2016-08-04T16:17:57.881796705Z", "output_fields": {"evt.time.iso8601":1470327477881796705,"proc.cmdline":"cat /dev/null"}}
|
||||
{"output":"2016-08-04T16:17:57.881799840+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","time":"2016-08-04T16:17:57.881799840Z", "output_fields": {"evt.time.iso8601":1470327477881799840,"proc.cmdline":"cat /dev/null"}}
|
||||
{"output":"2016-08-04T16:17:57.882003104+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","time":"2016-08-04T16:17:57.882003104Z", "output_fields": {"evt.time.iso8601":1470327477882003104,"proc.cmdline":"cat /dev/null"}}
|
||||
{"output":"2016-08-04T16:17:57.882008208+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","time":"2016-08-04T16:17:57.882008208Z", "output_fields": {"evt.time.iso8601":1470327477882008208,"proc.cmdline":"cat /dev/null"}}
|
||||
{"output":"2016-08-04T16:17:57.882045694+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","time":"2016-08-04T16:17:57.882045694Z", "output_fields": {"evt.time.iso8601":1470327477882045694,"proc.cmdline":"cat /dev/null"}}
|
||||
{"output":"2016-08-04T16:17:57.882054739+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","time":"2016-08-04T16:17:57.882054739Z", "output_fields": {"evt.time.iso8601":1470327477882054739,"proc.cmdline":"cat /dev/null"}}
|
||||
{"output":"2016-08-04T16:17:57.881781397+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","source":"syscall","tags":["filesystem","process","testing"],"time":"2016-08-04T16:17:57.881781397Z", "output_fields": {"evt.time.iso8601":1470327477881781397,"proc.cmdline":"cat /dev/null"}}
|
||||
{"output":"2016-08-04T16:17:57.881785348+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","source":"syscall","tags":["filesystem","process","testing"],"time":"2016-08-04T16:17:57.881785348Z", "output_fields": {"evt.time.iso8601":1470327477881785348,"proc.cmdline":"cat /dev/null"}}
|
||||
{"output":"2016-08-04T16:17:57.881796705+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","source":"syscall","tags":["filesystem","process","testing"],"time":"2016-08-04T16:17:57.881796705Z", "output_fields": {"evt.time.iso8601":1470327477881796705,"proc.cmdline":"cat /dev/null"}}
|
||||
{"output":"2016-08-04T16:17:57.881799840+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","source":"syscall","tags":["filesystem","process","testing"],"time":"2016-08-04T16:17:57.881799840Z", "output_fields": {"evt.time.iso8601":1470327477881799840,"proc.cmdline":"cat /dev/null"}}
|
||||
{"output":"2016-08-04T16:17:57.882003104+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","source":"syscall","tags":["filesystem","process","testing"],"time":"2016-08-04T16:17:57.882003104Z", "output_fields": {"evt.time.iso8601":1470327477882003104,"proc.cmdline":"cat /dev/null"}}
|
||||
{"output":"2016-08-04T16:17:57.882008208+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","source":"syscall","tags":["filesystem","process","testing"],"time":"2016-08-04T16:17:57.882008208Z", "output_fields": {"evt.time.iso8601":1470327477882008208,"proc.cmdline":"cat /dev/null"}}
|
||||
{"output":"2016-08-04T16:17:57.882045694+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","source":"syscall","tags":["filesystem","process","testing"],"time":"2016-08-04T16:17:57.882045694Z", "output_fields": {"evt.time.iso8601":1470327477882045694,"proc.cmdline":"cat /dev/null"}}
|
||||
{"output":"2016-08-04T16:17:57.882054739+0000: Warning An open was seen (command=cat /dev/null)","priority":"Warning","rule":"open_from_cat","source":"syscall","tags":["filesystem","process","testing"],"time":"2016-08-04T16:17:57.882054739Z", "output_fields": {"evt.time.iso8601":1470327477882054739,"proc.cmdline":"cat /dev/null"}}
|
||||
|
||||
@@ -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}")
|
||||
28
test/plugins/incompat_api.cpp
Normal file
28
test/plugins/incompat_api.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
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 <stdlib.h>
|
||||
|
||||
// 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
|
||||
@@ -0,0 +1,9 @@
|
||||
- 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])
|
||||
exceptions:
|
||||
- name: user_secreid
|
||||
fields: [aws.user, aws.region]
|
||||
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
|
||||
4
test/rules/plugins/cloudtrail_macro.yaml
Normal file
4
test/rules/plugins/cloudtrail_macro.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
- macro: Some Cloudtrail Macro
|
||||
condition: aws.user=bob
|
||||
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)
|
||||
|
||||
34
test/rules/single_rule_with_tags.yaml
Normal file
34
test/rules/single_rule_with_tags.yaml
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
- required_engine_version: 2
|
||||
|
||||
- list: cat_binaries
|
||||
items: [cat]
|
||||
|
||||
- list: cat_capable_binaries
|
||||
items: [cat_binaries]
|
||||
|
||||
- macro: is_cat
|
||||
condition: proc.name in (cat_capable_binaries)
|
||||
|
||||
- rule: open_from_cat
|
||||
desc: A process named cat does an open
|
||||
condition: evt.type=open and is_cat
|
||||
output: "An open was seen (command=%proc.cmdline)"
|
||||
priority: WARNING
|
||||
tags: [filesystem, process, testing]
|
||||
@@ -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,33 @@
|
||||
# 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
|
||||
${PROJECT_SOURCE_DIR}/userspace/falco/app_runnable_action.cpp
|
||||
${PROJECT_SOURCE_DIR}/userspace/falco/app_action_manager.cpp
|
||||
${PROJECT_SOURCE_DIR}/userspace/falco/logger.cpp
|
||||
test_base.cpp
|
||||
engine/test_rulesets.cpp
|
||||
engine/test_falco_utils.cpp
|
||||
falco/test_actions.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
|
||||
${PROJECT_SOURCE_DIR}/userspace/falco/app_runnable_action.cpp
|
||||
${PROJECT_SOURCE_DIR}/userspace/falco/app_action_manager.cpp
|
||||
${PROJECT_SOURCE_DIR}/userspace/falco/logger.cpp
|
||||
test_base.cpp
|
||||
engine/test_rulesets.cpp
|
||||
engine/test_falco_utils.cpp
|
||||
falco/test_actions.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 +67,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 +76,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;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user