mirror of
https://github.com/falcosecurity/falco.git
synced 2026-03-20 11:42:06 +00:00
Compare commits
95 Commits
0.42.0-rc2
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07d627a8e6 | ||
|
|
4f22143c6e | ||
|
|
9f767e409e | ||
|
|
e0c810c9d2 | ||
|
|
8c6ab2387f | ||
|
|
e1f16c0464 | ||
|
|
bb404863b4 | ||
|
|
7994460666 | ||
|
|
9aed480082 | ||
|
|
61be9ec4dd | ||
|
|
6d20070f27 | ||
|
|
59dae06e13 | ||
|
|
426fe3dabc | ||
|
|
cf0d2eb15a | ||
|
|
8989870d26 | ||
|
|
526dc9afef | ||
|
|
8171176e31 | ||
|
|
6fdb686b7a | ||
|
|
7554de160a | ||
|
|
31e92b88bc | ||
|
|
17ebbecec9 | ||
|
|
e816587a8d | ||
|
|
12b8bf8522 | ||
|
|
a43e1ac7f3 | ||
|
|
865284dffe | ||
|
|
514470abd1 | ||
|
|
b511b54d21 | ||
|
|
43aaffc4e0 | ||
|
|
33a2ce53fd | ||
|
|
387499546f | ||
|
|
ae9c2fbbc3 | ||
|
|
89975f1af8 | ||
|
|
b9b526e493 | ||
|
|
cca5356911 | ||
|
|
d0b6c138f9 | ||
|
|
bb8f6fa136 | ||
|
|
9d55804371 | ||
|
|
5baf13b80a | ||
|
|
69581443ae | ||
|
|
9324799b1a | ||
|
|
aad403f9d3 | ||
|
|
929b27b897 | ||
|
|
abcc058605 | ||
|
|
40fda7a874 | ||
|
|
da8644b73e | ||
|
|
c93a6a8bd9 | ||
|
|
c72a8151e5 | ||
|
|
edcb7a5dca | ||
|
|
3dabda4b7d | ||
|
|
2ddcb51ebf | ||
|
|
8009d71bb2 | ||
|
|
e7a68bde45 | ||
|
|
3d603af362 | ||
|
|
ab5a1fc1ea | ||
|
|
66555b9f4a | ||
|
|
b463f30ff9 | ||
|
|
2d06fa0963 | ||
|
|
697a807b55 | ||
|
|
9616b6945d | ||
|
|
879455453d | ||
|
|
600a256f1f | ||
|
|
0c039bc163 | ||
|
|
8b01753f6e | ||
|
|
d41a95ab11 | ||
|
|
48c7bc78b6 | ||
|
|
50d4c4c879 | ||
|
|
e34a6b28eb | ||
|
|
f4df5681fd | ||
|
|
fd4609884a | ||
|
|
817551ee25 | ||
|
|
6a152d338b | ||
|
|
11e8f82c6c | ||
|
|
03adda8656 | ||
|
|
1582018a2c | ||
|
|
0c6b926cd6 | ||
|
|
0b2724450f | ||
|
|
a9e8063e58 | ||
|
|
5b53681d2f | ||
|
|
2d9f1f1abc | ||
|
|
df3beba2e4 | ||
|
|
ecbf70b354 | ||
|
|
01fe75b0fd | ||
|
|
1b1b391724 | ||
|
|
bf60a61c52 | ||
|
|
6091fb18a0 | ||
|
|
d79ed7b951 | ||
|
|
bda65653cc | ||
|
|
933fb7e823 | ||
|
|
c9e920b1f7 | ||
|
|
9e188d75bc | ||
|
|
5d6f6135ac | ||
|
|
9eacf5e58f | ||
|
|
45ffa8e315 | ||
|
|
18e8e264a0 | ||
|
|
d443201229 |
3
.github/workflows/bump-libs.yaml
vendored
3
.github/workflows/bump-libs.yaml
vendored
@@ -6,6 +6,9 @@ on:
|
||||
schedule:
|
||||
- cron: '30 6 * * 1' # on each monday 6:30
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
# Checks if any concurrent jobs is running for kernels CI and eventually cancel it.
|
||||
concurrency:
|
||||
group: bump-libs-ci
|
||||
|
||||
4
.github/workflows/codeql.yaml
vendored
4
.github/workflows/codeql.yaml
vendored
@@ -59,11 +59,11 @@ jobs:
|
||||
run: sudo apt update -y
|
||||
|
||||
- name: Install build dependencies
|
||||
run: sudo DEBIAN_FRONTEND=noninteractive apt install libssl-dev libc-ares-dev libprotobuf-dev protobuf-compiler libyaml-cpp-dev libgrpc++-dev protobuf-compiler-grpc rpm libelf-dev cmake build-essential libcurl4-openssl-dev linux-headers-$(uname -r) clang llvm git -y
|
||||
run: sudo DEBIAN_FRONTEND=noninteractive apt install libssl-dev libc-ares-dev libyaml-cpp-dev rpm libelf-dev cmake build-essential libcurl4-openssl-dev linux-headers-$(uname -r) clang llvm git -y
|
||||
|
||||
- name: Prepare project
|
||||
run: |
|
||||
cmake -B build -S . -DBUILD_BPF=On -DBUILD_FALCO_MODERN_BPF=Off -DUSE_BUNDLED_DEPS=Off -DUSE_BUNDLED_NLOHMANN_JSON=On -DUSE_BUNDLED_CXXOPTS=On -DUSE_BUNDLED_CPPHTTPLIB=On
|
||||
cmake -B build -S . -DBUILD_FALCO_MODERN_BPF=Off -DUSE_BUNDLED_DEPS=Off -DUSE_BUNDLED_NLOHMANN_JSON=On -DUSE_BUNDLED_CXXOPTS=On -DUSE_BUNDLED_CPPHTTPLIB=On
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
|
||||
3
.github/workflows/format.yaml
vendored
3
.github/workflows/format.yaml
vendored
@@ -6,6 +6,9 @@ on:
|
||||
- master
|
||||
- "release/**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
format:
|
||||
name: format code 🐲
|
||||
|
||||
3
.github/workflows/master.yaml
vendored
3
.github/workflows/master.yaml
vendored
@@ -3,6 +3,9 @@ on:
|
||||
push:
|
||||
branches: [master]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
# Checks if any concurrent jobs is running for master CI and eventually cancel it
|
||||
concurrency:
|
||||
group: ci-master
|
||||
|
||||
3
.github/workflows/release.yaml
vendored
3
.github/workflows/release.yaml
vendored
@@ -3,6 +3,9 @@ on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
# Checks if any concurrent jobs is running for release CI and eventually cancel it.
|
||||
concurrency:
|
||||
group: ci-release
|
||||
|
||||
3
.github/workflows/reusable_build_dev.yaml
vendored
3
.github/workflows/reusable_build_dev.yaml
vendored
@@ -57,7 +57,7 @@ jobs:
|
||||
|
||||
- name: Install build dependencies (non-minimal)
|
||||
if: inputs.minimal != true
|
||||
run: sudo DEBIAN_FRONTEND=noninteractive apt install libssl-dev libc-ares-dev libprotobuf-dev protobuf-compiler libgrpc++-dev protobuf-compiler-grpc rpm libcurl4-openssl-dev linux-headers-$(uname -r) clang llvm -y
|
||||
run: sudo DEBIAN_FRONTEND=noninteractive apt install libssl-dev libc-ares-dev rpm libcurl4-openssl-dev linux-headers-$(uname -r) clang llvm -y
|
||||
|
||||
- name: Prepare project
|
||||
run: |
|
||||
@@ -65,7 +65,6 @@ jobs:
|
||||
-DBUILD_FALCO_UNIT_TESTS=On \
|
||||
-DCMAKE_BUILD_TYPE=${{ inputs.build_type }} \
|
||||
-DBUILD_FALCO_MODERN_BPF=Off \
|
||||
-DBUILD_BPF=${{ inputs.minimal == true && 'OFF' || 'ON' }} \
|
||||
-DBUILD_DRIVER=${{ inputs.minimal == true && 'OFF' || 'ON' }} \
|
||||
-DMINIMAL_BUILD=${{ inputs.minimal == true && 'ON' || 'OFF' }} \
|
||||
-DUSE_ASAN=${{ inputs.sanitizers == true && 'ON' || 'OFF' }} \
|
||||
|
||||
11
.github/workflows/reusable_build_packages.yaml
vendored
11
.github/workflows/reusable_build_packages.yaml
vendored
@@ -31,7 +31,7 @@ on:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
permissions:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
@@ -73,8 +73,8 @@ jobs:
|
||||
|
||||
- name: Install systemd rpm macros
|
||||
run: |
|
||||
wget https://www.rpmfind.net/linux/centos-stream/9-stream/BaseOS/${{ inputs.arch }}/os/Packages/systemd-rpm-macros-252-51.el9.noarch.rpm
|
||||
sudo alien -d -i systemd-rpm-macros-252-51.el9.noarch.rpm
|
||||
wget https://www.rpmfind.net/linux/centos-stream/9-stream/BaseOS/${{ inputs.arch }}/os/Packages/systemd-rpm-macros-252-59.el9.noarch.rpm
|
||||
sudo alien -d -i systemd-rpm-macros-252-59.el9.noarch.rpm
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
@@ -97,7 +97,6 @@ jobs:
|
||||
-DFALCO_ETC_DIR=/etc/falco \
|
||||
-DMODERN_BPF_SKEL_DIR=/tmp \
|
||||
-DBUILD_DRIVER=Off \
|
||||
-DBUILD_BPF=Off \
|
||||
-DUSE_JEMALLOC=${{ inputs.use_jemalloc }} \
|
||||
-DUSE_MIMALLOC=${{ inputs.use_mimalloc }} \
|
||||
-DFALCO_VERSION=${{ inputs.version }}
|
||||
@@ -170,7 +169,6 @@ jobs:
|
||||
-DFALCO_ETC_DIR=/etc/falco \
|
||||
-DMODERN_BPF_SKEL_DIR=/tmp \
|
||||
-DBUILD_DRIVER=Off \
|
||||
-DBUILD_BPF=Off \
|
||||
-DUSE_JEMALLOC=${{ inputs.use_jemalloc }} \
|
||||
-DUSE_MIMALLOC=${{ inputs.use_mimalloc }} \
|
||||
-DFALCO_VERSION=${{ inputs.version }}
|
||||
@@ -219,7 +217,6 @@ jobs:
|
||||
-DFALCO_ETC_DIR=/etc/falco \
|
||||
-DMODERN_BPF_SKEL_DIR=/tmp \
|
||||
-DBUILD_DRIVER=Off \
|
||||
-DBUILD_BPF=Off \
|
||||
-DUSE_JEMALLOC=Off \
|
||||
-DUSE_MIMALLOC=Off \
|
||||
-DUSE_ASAN=On \
|
||||
@@ -265,7 +262,7 @@ jobs:
|
||||
cmake -B build -S . \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCPACK_GENERATOR=TGZ \
|
||||
-DBUILD_BPF=Off -DBUILD_DRIVER=Off \
|
||||
-DBUILD_DRIVER=Off \
|
||||
-DUSE_JEMALLOC=${{ inputs.use_jemalloc }} \
|
||||
-DUSE_MIMALLOC=${{ inputs.use_mimalloc }} \
|
||||
-DUSE_BUNDLED_DEPS=On \
|
||||
|
||||
@@ -82,11 +82,6 @@ jobs:
|
||||
GPG_KEY: ${{ secrets.GPG_KEY }}
|
||||
run: printenv GPG_KEY | gpg --import -
|
||||
|
||||
- name: Sign rpms
|
||||
run: |
|
||||
rpmsign --define '_gpg_name Falcosecurity Package Signing' --addsign /tmp/falco-build-rpm/falco-*.rpm
|
||||
rpm -qp --qf '%|DSAHEADER?{%{DSAHEADER:pgpsig}}:{%|RSAHEADER?{%{RSAHEADER:pgpsig}}:{(none)}|}|\n' /tmp/falco-build-rpm/falco-*.rpm
|
||||
|
||||
- name: Publish wasm
|
||||
run: |
|
||||
./scripts/publish-wasm -f /tmp/falco-wasm/falco-${{ inputs.version }}-wasm.tar.gz
|
||||
|
||||
2
.github/workflows/staticanalysis.yaml
vendored
2
.github/workflows/staticanalysis.yaml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
run: |
|
||||
cmake -B build -S . \
|
||||
-DCMAKE_BUILD_TYPE="release" \
|
||||
-DUSE_BUNDLED_DEPS=On -DUSE_DYNAMIC_LIBELF=Off -DBUILD_WARNINGS_AS_ERRORS=ON -DCREATE_TEST_TARGETS=Off -DBUILD_BPF=Off -DBUILD_DRIVER=Off
|
||||
-DUSE_BUNDLED_DEPS=On -DUSE_DYNAMIC_LIBELF=Off -DBUILD_WARNINGS_AS_ERRORS=ON -DCREATE_TEST_TARGETS=Off -DBUILD_DRIVER=Off
|
||||
cmake --build build -j4 --target cppcheck
|
||||
cmake --build build -j4 --target cppcheck_htmlreport
|
||||
|
||||
|
||||
137
CHANGELOG.md
137
CHANGELOG.md
@@ -1,5 +1,142 @@
|
||||
# Change Log
|
||||
|
||||
## v0.43.0
|
||||
|
||||
Released on 2026-01-28
|
||||
|
||||
### Breaking Changes :warning:
|
||||
|
||||
* fix(userspace)!: show source config path only in debug builds [[#3787](https://github.com/falcosecurity/falco/pull/3787)] - [@leogr](https://github.com/leogr)
|
||||
|
||||
|
||||
|
||||
### Minor Changes
|
||||
|
||||
* chore(userspace): deprecate `--gvisor-generate-config` CLI option [[#3784](https://github.com/falcosecurity/falco/pull/3784)] - [@ekoops](https://github.com/ekoops)
|
||||
* docs: add deprecation notice for legacy eBPF in pkg install dialog [[#3786](https://github.com/falcosecurity/falco/pull/3786)] - [@ekoops](https://github.com/ekoops)
|
||||
* chore: [NOTICE] The GPG key used to sign DEB/RPM packages has been rotated, and all existing packages have been re-signed. New key fingerprint: `478B2FBBC75F4237B731DA4365106822B35B1B1F` [[#3753](https://github.com/falcosecurity/falco/pull/3753)] - [@leogr](https://github.com/leogr)
|
||||
* chore(scripts/falcoctl): increase follow interval to 1 week [[#3757](https://github.com/falcosecurity/falco/pull/3757)] - [@leogr](https://github.com/leogr)
|
||||
* docs: add deprecation notice for legacy eBPF, gVisor and gRPC usage [[#3763](https://github.com/falcosecurity/falco/pull/3763)] - [@ekoops](https://github.com/ekoops)
|
||||
* chore(userspace): deprecate legacy eBPF probe, gVisor engine and gRPC [[#3763](https://github.com/falcosecurity/falco/pull/3763)] - [@ekoops](https://github.com/ekoops)
|
||||
* chore(engine): emit warning when the deprecated `evt.latency` field family is used in a rule condition or output [[#3744](https://github.com/falcosecurity/falco/pull/3744)] - [@irozzo-1A](https://github.com/irozzo-1A)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix: prevent null pointer crash on `popen()` failure in output_program [[#3722](https://github.com/falcosecurity/falco/pull/3722)] - [@vietcgi](https://github.com/vietcgi)
|
||||
* fix: correct falcoctl.yaml path in debian conffiles [[#3745](https://github.com/falcosecurity/falco/pull/3745)] - [@leogr](https://github.com/leogr)
|
||||
|
||||
|
||||
|
||||
### Non user-facing changes
|
||||
|
||||
* chore(cmake): bump falcoctl dependency version to `0.12.2` [[#3790](https://github.com/falcosecurity/falco/pull/3790)] - [@ekoops](https://github.com/ekoops)
|
||||
* chore(cmake): bump falcoctl dependency version to `0.12.1` [[#3777](https://github.com/falcosecurity/falco/pull/3777)] - [@ekoops](https://github.com/ekoops)
|
||||
* chore(cmake): bump container plugin version to `0.6.1` [[#3780](https://github.com/falcosecurity/falco/pull/3780)] - [@ekoops](https://github.com/ekoops)
|
||||
* fix(userspace/engine): missing closing quote in deprecated field warning [[#3779](https://github.com/falcosecurity/falco/pull/3779)] - [@leogr](https://github.com/leogr)
|
||||
* chore(.github): Put back gpg key rotation workflow [[#3772](https://github.com/falcosecurity/falco/pull/3772)] - [@irozzo-1A](https://github.com/irozzo-1A)
|
||||
* chore(cmake): bump libs/drivers to `0.23.1`/`9.1.0+driver` [[#3769](https://github.com/falcosecurity/falco/pull/3769)] - [@ekoops](https://github.com/ekoops)
|
||||
* revert: chore(.github): temporary action for GPG key rotation [[#3766](https://github.com/falcosecurity/falco/pull/3766)] - [@leogr](https://github.com/leogr)
|
||||
* chore(cmake): bump container plugin version to 0.6.0 [[#3768](https://github.com/falcosecurity/falco/pull/3768)] - [@irozzo-1A](https://github.com/irozzo-1A)
|
||||
* docs(proposals): add proposal for legacy probe, gVisor engine and gRPC output deprecation [[#3755](https://github.com/falcosecurity/falco/pull/3755)] - [@ekoops](https://github.com/ekoops)
|
||||
* chore(cmake): bump libs/drivers to `0.23.0`/`9.1.0+driver` [[#3760](https://github.com/falcosecurity/falco/pull/3760)] - [@ekoops](https://github.com/ekoops)
|
||||
* update(cmake): update libs and driver to latest master [[#3754](https://github.com/falcosecurity/falco/pull/3754)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* fix(metrics): Add null check for state.outputs in metrics collection [[#3740](https://github.com/falcosecurity/falco/pull/3740)] - [@adduali1310](https://github.com/adduali1310)
|
||||
* chore(cmake): bump libs to `0.23.0-rc2` [[#3759](https://github.com/falcosecurity/falco/pull/3759)] - [@ekoops](https://github.com/ekoops)
|
||||
* chore(cmake): bump libs/drivers to `0.23.0-rc1`/`9.1.0-rc1+driver` [[#3758](https://github.com/falcosecurity/falco/pull/3758)] - [@ekoops](https://github.com/ekoops)
|
||||
* fix(ci): revert changes to mitigate rate-limitar change [[#3752](https://github.com/falcosecurity/falco/pull/3752)] - [@irozzo-1A](https://github.com/irozzo-1A)
|
||||
* update(cmake): update libs and driver to latest master [[#3723](https://github.com/falcosecurity/falco/pull/3723)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* Reduce image size [[#3746](https://github.com/falcosecurity/falco/pull/3746)] - [@jfcoz](https://github.com/jfcoz)
|
||||
* docs(RELEASE.md): specify target branch association upon release creation [[#3717](https://github.com/falcosecurity/falco/pull/3717)] - [@ekoops](https://github.com/ekoops)
|
||||
* docs(RELEASE.md): fix `rn2md` cmd generating changelogs [[#3709](https://github.com/falcosecurity/falco/pull/3709)] - [@ekoops](https://github.com/ekoops)
|
||||
* docs(RELEASE.md): fix PRs filtering expr for checking release notes [[#3708](https://github.com/falcosecurity/falco/pull/3708)] - [@ekoops](https://github.com/ekoops)
|
||||
* docs(RELEASE.md): fix PRs filtering expression text [[#3707](https://github.com/falcosecurity/falco/pull/3707)] - [@ekoops](https://github.com/ekoops)
|
||||
|
||||
### Statistics
|
||||
|
||||
| MERGED PRS | NUMBER |
|
||||
|-----------------|--------|
|
||||
| Not user-facing | 21 |
|
||||
| Release note | 11 |
|
||||
| Total | 32 |
|
||||
|
||||
## v0.42.0
|
||||
|
||||
Released on 2025-10-22
|
||||
|
||||
|
||||
### Major Changes
|
||||
|
||||
* feat: add `falco_libs.thread_table_auto_purging_interval_s` and `thread_table_auto_purging_thread_timeout_s` configuration options [[#3670](https://github.com/falcosecurity/falco/pull/3670)] - [@ekoops](https://github.com/ekoops)
|
||||
* feat: log plugin version info at loading time [[#3657](https://github.com/falcosecurity/falco/pull/3657)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* feat: ability to add statically defined fields via `static_fields` configuration [[#3557](https://github.com/falcosecurity/falco/pull/3557)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* feat(engine): emit warning when a rule containing the `evt.dir` field in output is encountered [[#3697](https://github.com/falcosecurity/falco/pull/3697)] - [@irozzo-1A](https://github.com/irozzo-1A)
|
||||
* feat(engine): emit warning when a rule containing a condition on the deprecated `evt.dir` field is encountered [[#3690](https://github.com/falcosecurity/falco/pull/3690)] - [@irozzo-1A](https://github.com/irozzo-1A)
|
||||
* new: ability to record `.scap` files (capture feature) [[#3645](https://github.com/falcosecurity/falco/pull/3645)] - [@leogr](https://github.com/leogr)
|
||||
* new(docker): includes sha on the image labels [[#3658](https://github.com/falcosecurity/falco/pull/3658)] - [@jcchavezs](https://github.com/jcchavezs)
|
||||
* new(cmake,userspace,ci): add mimalloc support [[#3616](https://github.com/falcosecurity/falco/pull/3616)] - [@FedeDP](https://github.com/FedeDP)
|
||||
|
||||
|
||||
### Minor Changes
|
||||
|
||||
* docs(falco.yaml): refactor config documentation [[#3685](https://github.com/falcosecurity/falco/pull/3685)] - [@leogr](https://github.com/leogr)
|
||||
* build: fix `debian:buster` apt debian repo URL in `:driver-loader-buster` container image [[#3644](https://github.com/falcosecurity/falco/pull/3644)] - [@ekoops](https://github.com/ekoops)
|
||||
* build: updagrade libs to version 0.22.1 [[#3705](https://github.com/falcosecurity/falco/pull/3705)] - [@irozzo-1A](https://github.com/irozzo-1A)
|
||||
* build: upgrade drivers to v9.0.0+driver [[#3701](https://github.com/falcosecurity/falco/pull/3701)] - [@irozzo-1A](https://github.com/irozzo-1A)
|
||||
* build: upgrade cpp-httplib to v0.23.1 [[#3647](https://github.com/falcosecurity/falco/pull/3647)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* update: upgrade default ruleset to v5.0.0 [[#3700](https://github.com/falcosecurity/falco/pull/3700)] - [@leogr](https://github.com/leogr)
|
||||
* build: upgrade `falcoctl` to v0.11.4 [[#3694](https://github.com/falcosecurity/falco/pull/3694)] - [@leogr](https://github.com/leogr)
|
||||
* chore(prometheus): deprecate enter events drop stats [[#3675](https://github.com/falcosecurity/falco/pull/3675)] - [@irozzo-1A](https://github.com/irozzo-1A)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix(cmake): correct abseil-cpp for alpine build [[#3598](https://github.com/falcosecurity/falco/pull/3598)] - [@RomanenkoDenys](https://github.com/RomanenkoDenys)
|
||||
* fix: enable handling of multiple actions configured with `syscall_event_drops.actions` [[#3676](https://github.com/falcosecurity/falco/pull/3676)] - [@terror96](https://github.com/terror96)
|
||||
* fix: disable dry-run restarts when Falco runs with config-watching disabled [[#3640](https://github.com/falcosecurity/falco/pull/3640)] - [@Proximyst](https://github.com/Proximyst)
|
||||
|
||||
|
||||
|
||||
### Non user-facing changes
|
||||
|
||||
* fix(userspace/falco): correct default duration calculation [[#3715](https://github.com/falcosecurity/falco/pull/3715)] - [@leogr](https://github.com/leogr)
|
||||
* chore(falcoctl): update falco rules to version 5 [[#3712](https://github.com/falcosecurity/falco/pull/3712)] - [@irozzo-1A](https://github.com/irozzo-1A)
|
||||
* doc(OWNERS): move incertum (Melissa Kilby) to emeritus_approvers [[#3605](https://github.com/falcosecurity/falco/pull/3605)] - [@incertum](https://github.com/incertum)
|
||||
* update(cmake): update libs and driver to latest master [[#3689](https://github.com/falcosecurity/falco/pull/3689)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* chore(docker): use new `ENV` syntax in place of deprecated one [[#3696](https://github.com/falcosecurity/falco/pull/3696)] - [@ekoops](https://github.com/ekoops)
|
||||
* chore(cmake/modules): update rules to 5.0.0-rc1 [[#3698](https://github.com/falcosecurity/falco/pull/3698)] - [@leogr](https://github.com/leogr)
|
||||
* fix(userspace/engine): fix logger date format [[#3672](https://github.com/falcosecurity/falco/pull/3672)] - [@ekoops](https://github.com/ekoops)
|
||||
* docs(OWNERS): add `ekoops`(Leonardo Di Giovanna) as approver [[#3688](https://github.com/falcosecurity/falco/pull/3688)] - [@ekoops](https://github.com/ekoops)
|
||||
* update(cmake): update libs and driver to latest master [[#3665](https://github.com/falcosecurity/falco/pull/3665)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* Refactor: cppcheck cleanups [[#3649](https://github.com/falcosecurity/falco/pull/3649)] - [@sgaist](https://github.com/sgaist)
|
||||
* update(userspace/engine): update falco engine version and checksum [[#3648](https://github.com/falcosecurity/falco/pull/3648)] - [@ekoops](https://github.com/ekoops)
|
||||
* update(cmake): update libs and driver to latest master [[#3662](https://github.com/falcosecurity/falco/pull/3662)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* update(cmake): update libs and driver to latest master [[#3661](https://github.com/falcosecurity/falco/pull/3661)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* update(cmake): update libs and driver to latest master [[#3653](https://github.com/falcosecurity/falco/pull/3653)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* chore(ci): disable mimalloc for master builds. [[#3655](https://github.com/falcosecurity/falco/pull/3655)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* chore(deps): Bump submodules/falcosecurity-rules from `1208816` to `be38001` [[#3651](https://github.com/falcosecurity/falco/pull/3651)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* docs(falco.yaml): avoid out-of-sync config options for `container` pl… [[#3650](https://github.com/falcosecurity/falco/pull/3650)] - [@leogr](https://github.com/leogr)
|
||||
* update(cmake): update libs and driver to latest master [[#3636](https://github.com/falcosecurity/falco/pull/3636)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* update(CHANGELOG.md): release 0.41.3 (cherry-pick) [[#3634](https://github.com/falcosecurity/falco/pull/3634)] - [@ekoops](https://github.com/ekoops)
|
||||
* update(cmake): update libs and driver to latest master [[#3628](https://github.com/falcosecurity/falco/pull/3628)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* update(CHANGELOG.md): release 0.41.2 (cherry-pick) [[#3623](https://github.com/falcosecurity/falco/pull/3623)] - [@ekoops](https://github.com/ekoops)
|
||||
* update(cmake): update libs and driver to latest master [[#3618](https://github.com/falcosecurity/falco/pull/3618)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* update(cmake): update libs and driver to latest master [[#3602](https://github.com/falcosecurity/falco/pull/3602)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* chore(falco.yaml): clean up plugins config leftover [[#3596](https://github.com/falcosecurity/falco/pull/3596)] - [@leogr](https://github.com/leogr)
|
||||
* chore(deps): Bump submodules/falcosecurity-rules from `b4437c4` to `4d51b18` [[#3607](https://github.com/falcosecurity/falco/pull/3607)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* update(docs): cherry pick CHANGELOG. [[#3600](https://github.com/falcosecurity/falco/pull/3600)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* update(cmake): update libs and driver to latest master [[#3592](https://github.com/falcosecurity/falco/pull/3592)] - [@github-actions[bot]](https://github.com/apps/github-actions)
|
||||
* update(docs): bumped changelog for release 0.41.0, master sync [[#3586](https://github.com/falcosecurity/falco/pull/3586)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* chore(deps): Bump submodules/falcosecurity-rules from `cb17833` to `b4437c4` [[#3578](https://github.com/falcosecurity/falco/pull/3578)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
|
||||
### Statistics
|
||||
|
||||
| MERGED PRS | NUMBER |
|
||||
|-----------------|--------|
|
||||
| Not user-facing | 29 |
|
||||
| Release note | 23 |
|
||||
| Total | 52 |
|
||||
|
||||
## v0.41.3
|
||||
|
||||
Released on 2025-07-01
|
||||
|
||||
@@ -29,6 +29,17 @@ option(BUILD_FALCO_UNIT_TESTS "Build falco unit tests" OFF)
|
||||
option(USE_ASAN "Build with AddressSanitizer" OFF)
|
||||
option(USE_UBSAN "Build with UndefinedBehaviorSanitizer" OFF)
|
||||
option(UBSAN_HALT_ON_ERROR "Halt on error when building with UBSan" ON)
|
||||
option(USE_GPERFTOOLS "Build with gperftools CPU profiler support" OFF)
|
||||
option(USE_FRAME_POINTER "Build with frame pointers for accurate profiling" OFF)
|
||||
|
||||
# Enable frame pointers by default when using gperftools for accurate stack traces
|
||||
if(USE_GPERFTOOLS AND NOT USE_FRAME_POINTER)
|
||||
set(USE_FRAME_POINTER
|
||||
ON
|
||||
CACHE BOOL "Build with frame pointers for accurate profiling" FORCE
|
||||
)
|
||||
message(STATUS "Enabling USE_FRAME_POINTER since USE_GPERFTOOLS is enabled")
|
||||
endif()
|
||||
|
||||
# Mem allocators - linux only for now
|
||||
if(NOT WIN32
|
||||
@@ -64,27 +75,12 @@ elseif(EMSCRIPTEN)
|
||||
OFF
|
||||
CACHE BOOL "" FORCE
|
||||
)
|
||||
set(BUILD_BPF
|
||||
OFF
|
||||
CACHE BOOL "" FORCE
|
||||
)
|
||||
set(CPACK_GENERATOR
|
||||
TGZ
|
||||
CACHE BOOL "" FORCE
|
||||
)
|
||||
endif()
|
||||
|
||||
# gVisor is currently only supported on Linux x86_64
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64"
|
||||
AND CMAKE_SYSTEM_NAME MATCHES "Linux"
|
||||
AND NOT MINIMAL_BUILD
|
||||
)
|
||||
option(BUILD_FALCO_GVISOR "Build gVisor support for Falco" ON)
|
||||
if(BUILD_FALCO_GVISOR)
|
||||
add_definitions(-DHAS_GVISOR)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Modern BPF is not supported on not Linux systems and in MINIMAL_BUILD
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT MINIMAL_BUILD)
|
||||
option(BUILD_FALCO_MODERN_BPF "Build modern BPF support for Falco" ON)
|
||||
@@ -133,11 +129,6 @@ set(DRIVER_NAME "falco")
|
||||
set(DRIVER_DEVICE_NAME "falco")
|
||||
set(DRIVERS_REPO "https://download.falco.org/driver")
|
||||
|
||||
# If no path is provided, try to search the BPF probe in: `home/.falco/falco-bpf.o` This is the same
|
||||
# fallback that we had in the libraries: `SCAP_PROBE_BPF_FILEPATH`.
|
||||
set(FALCO_PROBE_BPF_FILEPATH ".${DRIVER_NAME}/${DRIVER_NAME}-bpf.o")
|
||||
add_definitions(-DFALCO_PROBE_BPF_FILEPATH="${FALCO_PROBE_BPF_FILEPATH}")
|
||||
|
||||
if(NOT DEFINED FALCO_COMPONENT_NAME)
|
||||
set(FALCO_COMPONENT_NAME "${CMAKE_PROJECT_NAME}")
|
||||
endif()
|
||||
@@ -153,6 +144,8 @@ set(CMD_MAKE make)
|
||||
|
||||
include(ExternalProject)
|
||||
|
||||
include(cxxopts)
|
||||
|
||||
# libs
|
||||
include(falcosecurity-libs)
|
||||
|
||||
@@ -197,8 +190,6 @@ if(NOT WIN32
|
||||
include(cpp-httplib)
|
||||
endif()
|
||||
|
||||
include(cxxopts)
|
||||
|
||||
# One TBB
|
||||
if(NOT EMSCRIPTEN)
|
||||
include(tbb)
|
||||
@@ -206,15 +197,17 @@ endif()
|
||||
|
||||
include(zlib)
|
||||
include(valijson)
|
||||
|
||||
# CPU Profiling with gperftools
|
||||
if(USE_GPERFTOOLS)
|
||||
include(gperftools)
|
||||
endif()
|
||||
if(NOT MINIMAL_BUILD)
|
||||
if(NOT WIN32
|
||||
AND NOT APPLE
|
||||
AND NOT EMSCRIPTEN
|
||||
)
|
||||
include(cares)
|
||||
include(protobuf)
|
||||
# gRPC
|
||||
include(grpc)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -288,11 +281,17 @@ if(NOT WIN32
|
||||
AND NOT MUSL_OPTIMIZED_BUILD
|
||||
)
|
||||
include(falcoctl)
|
||||
set(CONTAINER_VERSION "0.6.1")
|
||||
if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
set(CONTAINER_HASH "008989992ed1f31b3ffb94ba6b64ca5a8e2f91611a10c9d6213c5c0a499d0679")
|
||||
else() # arm64
|
||||
set(CONTAINER_HASH "f90a700b4c2b411b23e7cc461b61a316b242994aad853c3e6baf12481fb6f6c9")
|
||||
endif()
|
||||
include(container_plugin)
|
||||
|
||||
# Generate a binary_dir/falco.yaml that automatically enables the plugin to be used for local
|
||||
# testing.
|
||||
configure_file(${CMAKE_SOURCE_DIR}/falco.yaml ${CMAKE_BINARY_DIR} COPYONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/falco.yaml ${CMAKE_BINARY_DIR} COPYONLY)
|
||||
# The custom target configures the plugin and set its path
|
||||
add_custom_target(
|
||||
container
|
||||
|
||||
@@ -27,7 +27,7 @@ The `pre-commit` framework allows you to automatically install different `git-ho
|
||||
|
||||
1. The `clang-format` hook: this is a `pre-commit` git hook that runs `clang-format` on your staged changes.
|
||||
2. The `cmake-format` hook: this is a `pre-commit` git hook that runs `cmake-format` on your staged changes.
|
||||
3. The `DCO signed-off` hook: this is a `pre-commit-msg` git hook that adds the `DCO` on your commit if not present. This hook is not strictly related to the coding style so we will talk about it in a separate section: [Add DCO signed-off to your commits](#add-dco-signed-off-to-your-commits).
|
||||
3. The `DCO signed-off` hook: this is a `pre-commit-msg` git hook that adds the `DCO` on your commit if not present. This hook is not strictly related to the coding style so we will talk about it in a separate section: [Add DCO signed-off to your commits](#add-dco-signed-off-to-your-commits-).
|
||||
|
||||
Now let's see what we need to use `pre-commit` framework.
|
||||
|
||||
@@ -47,7 +47,7 @@ This simple command allows you to install the two `pre-commit` git hooks, `clang
|
||||
pre-commit install --install-hooks --hook-type pre-commit --overwrite
|
||||
```
|
||||
|
||||
If you want to install also the `pre-commit-msg` git hook for the DCO you have to type the following command, but be sure to have configured all you need as said in the [dedicated section]((#add-dco-signed-off-to-your-commits))
|
||||
If you want to install also the `pre-commit-msg` git hook for the DCO you have to type the following command, but be sure to have configured all you need as said in the [dedicated section](#add-dco-signed-off-to-your-commits-)
|
||||
|
||||
```bash
|
||||
pre-commit install --install-hooks --hook-type prepare-commit-msg --overwrite
|
||||
@@ -81,7 +81,7 @@ To install `cmake-format` you can follow the official documentation [here](https
|
||||
|
||||
##### Step 2
|
||||
|
||||
Once you have installed the __right__ versions of the 2 tools, you can simply type `make format-all` from the root directory of the project (`/libs`) to format all your code according to the coding style.
|
||||
Once you have installed the __right__ versions of the 2 tools, you can simply type `make format-all` from the root directory of the project to format all your code according to the coding style.
|
||||
|
||||
Remember to do that before submitting a new patch upstream! 😁
|
||||
|
||||
@@ -93,7 +93,7 @@ Obviously, you can also install the 2 tools locally and enable some extension of
|
||||
|
||||
### Introduction
|
||||
|
||||
Another requirement for contributing to the `libs` repository, is applying the [DCO](https://cert-manager.io/docs/contributing/sign-off/) to every commit you want to push upstream.
|
||||
Another requirement for contributing to the `falco` repository, is applying the [DCO](https://cert-manager.io/docs/contributing/sign-off/) to every commit you want to push upstream.
|
||||
Before doing this you have to configure your git user `name` and `email` if you haven't already done it. To check your actual `name` and `email` type:
|
||||
|
||||
```bash
|
||||
|
||||
1
OWNERS
1
OWNERS
@@ -9,6 +9,7 @@ approvers:
|
||||
- ekoops
|
||||
reviewers:
|
||||
- kaizhe
|
||||
- irozzo-1A
|
||||
emeritus_approvers:
|
||||
- fntlnz
|
||||
- kris-nova
|
||||
|
||||
@@ -74,8 +74,6 @@ Here's an example of a `cmake` command that will enable everything you need for
|
||||
```bash
|
||||
cmake \
|
||||
-DUSE_BUNDLED_DEPS=ON \
|
||||
-DBUILD_LIBSCAP_GVISOR=ON \
|
||||
-DBUILD_BPF=ON \
|
||||
-DBUILD_DRIVER=ON \
|
||||
-DBUILD_FALCO_MODERN_BPF=ON \
|
||||
-DCREATE_TEST_TARGETS=ON \
|
||||
@@ -113,7 +111,7 @@ Please refer to the [Contributing](https://github.com/falcosecurity/.github/blob
|
||||
|
||||
1. The first lines of code at the base of Falco were written some time ago, where Go didn't yet have the same level of maturity and adoption as today.
|
||||
2. The Falco execution model is sequential and mono-thread due to the statefulness requirements of the tool, and so most of the concurrency-related selling points of the Go runtime would not be leveraged at all.
|
||||
3. The Falco code deals with very low-level programming in many places (e.g. some headers are shared with the eBPF probe and the Kernel module), and we all know that interfacing Go with C is possible but brings tons of complexity and tradeoffs to the table.
|
||||
3. The Falco code deals with very low-level programming in many places, and we all know that interfacing Go with C is possible but brings tons of complexity and tradeoffs to the table.
|
||||
4. As a security tool meant to consume a crazy high throughput of events per second, Falco needs to squeeze performance in all hot paths at runtime and requires deep control on memory allocation, which the Go runtime can't provide (there's also garbage collection involved).
|
||||
5. Although Go didn't suit the engineering requirements of the core of Falco, we still thought that it could be a good candidate for writing Falco extensions through the plugin system. This is the main reason we gave special attention and high priority to the development of the plugin-sdk-go.
|
||||
6. Go is not a requirement for having statically-linked binaries. In fact, we provide fully-static Falco builds since few years. The only issue with those is that the plugin system can't be supported with the current dynamic library model we currently have.
|
||||
|
||||
22
RELEASE.md
22
RELEASE.md
@@ -48,11 +48,10 @@ Alternatively Falco binaries or plugins can be downloaded from the Falco Artifac
|
||||
|
||||
> Note: This section specifically applies to non-modern BPF drivers.
|
||||
|
||||
The Falco Project publishes all drivers for each release for popular kernel versions / distros and `x86_64` and `aarch64` architectures to the Falco project's managed Artifacts repo. The Artifacts repo follows standard directory level conventions. The respective driver object file is prefixed by distro and named / versioned by kernel release - `$(uname -r)`. Pre-compiled drivers are released with a [best effort](https://github.com/falcosecurity/falco/blob/master/proposals/20200818-artifacts-storage.md#notice) notice. This is because gcc (`kmod`) and clang (`bpf`) compilers sometimes fail to build the artifacts for a specific kernel version. More details around driver versioning and driver compatibility are provided in the [Falco Components Versioning](#falco-components-versioning) section. Short preview: If you use the standard Falco setup leveraging driver-loader, [driver-loader script](https://github.com/falcosecurity/falco/blob/master/scripts/falco-driver-loader) will fetch the kernel space artifact (object file) corresponding to the default `DRIVER_VERSION` Falco was shipped with.
|
||||
The Falco Project publishes all drivers for each release for popular kernel versions / distros and `x86_64` and `aarch64` architectures to the Falco project's managed Artifacts repo. The Artifacts repo follows standard directory level conventions. The respective driver object file is prefixed by distro and named / versioned by kernel release - `$(uname -r)`. Pre-compiled drivers are released with a [best effort](https://github.com/falcosecurity/falco/blob/master/proposals/20200818-artifacts-storage.md#notice) notice. This is because gcc (`kmod`) sometimes fails to build the artifacts for a specific kernel version. More details around driver versioning and driver compatibility are provided in the [Falco Components Versioning](#falco-components-versioning) section. Short preview: If you use the standard Falco setup leveraging driver-loader, [driver-loader script](https://github.com/falcosecurity/falco/blob/master/scripts/falco-driver-loader) will fetch the kernel space artifact (object file) corresponding to the default `DRIVER_VERSION` Falco was shipped with.
|
||||
|
||||
- [Falco Artifacts Repo Drivers Root](https://download.falco.org/?prefix=driver/)
|
||||
- Option 1: Kernel module (`.ko` files) - all under same driver version directory
|
||||
- Option 2: eBPF (`.o` files) - all under same driver version directory
|
||||
- Kernel module (`.ko` files) - all under same driver version directory
|
||||
|
||||
|
||||
### Timeline
|
||||
@@ -87,10 +86,10 @@ Before proceeding with the release, make sure to complete the following preparat
|
||||
- Double-check, by using the following filters, if there is any closed issue/merge PR with no milestone assigned:
|
||||
- `is:issue state:closed no:milestone closed:>YYYY-MM-DD`
|
||||
[filter](https://github.com/falcosecurity/falco/issues?q=is%3Aissue%20state%3Aclosed%20no%3Amilestone%20closed%3A%3EYYYY-MM-DD)
|
||||
- `is:pr state:closed no:milestone closed:>YYYY-MM-DD`
|
||||
- `is:pr is:merged no:milestone closed:>YYYY-MM-DD`
|
||||
[filter](https://github.com/falcosecurity/falco/pulls?q=is%3Apr+is%3Amerged+no%3Amilestone+closed%3A%3EYYYY-MM-DD)
|
||||
- Assign any issue/PR identified in the previous point to the milestone corresponding to the currently undergoing release
|
||||
- Check the release note block of every PR matching the `is:pr is:merged closed:>YYYY-MM-DD` [filter](https://github.com/falcosecurity/falco/pulls?q=is%3Apr+is%3Amerged+closed%3A%3EYYYY-MM-DD)
|
||||
- Check the release note block of every PR matching the `is:pr is:merged milestone:M.m.p` [filter](https://github.com/falcosecurity/falco/pulls?q=is%3Apr+is%3Amerged+milestone%3AM.m.p)
|
||||
- Ensure the release note block follows the [commit convention](https://github.com/falcosecurity/.github/blob/master/CONTRIBUTING.md#commit-convention), otherwise fix its content
|
||||
- If the PR has no milestone, assign it to the milestone currently undergoing release
|
||||
|
||||
@@ -116,7 +115,7 @@ The release PR is meant to be made against the respective `release/M.m.x` branch
|
||||
- If any, manually correct it then open an issue to automate version number bumping later
|
||||
- Versions table in the `README.md` updates itself automatically
|
||||
- Generate the change log using [rn2md](https://github.com/leodido/rn2md):
|
||||
- Execute `rn2md -r falcosecurity/falco -m M.m.p -b release/M.m.x`
|
||||
- Execute `rn2md -r falcosecurity/falco -m M.m.p`
|
||||
- In case `rn2md` emits error try to generate an GitHub OAuth access token and provide it with the `-t` flag
|
||||
- Add the latest changes on top the previous `CHANGELOG.md`
|
||||
- Submit a PR with the above modifications
|
||||
@@ -129,16 +128,18 @@ The release PR is meant to be made against the respective `release/M.m.x` branch
|
||||
Core maintainers and/or the release manager can decide to publish pre-releases at any time before the final release
|
||||
is live for development and testing purposes.
|
||||
|
||||
The prerelease tag must be formatted as `M.m.p-r` where `r` is the prerelease version information (e.g. `0.35.0-rc1`.)
|
||||
The pre-release must be associated with a newly created tag. The tag is intended to be created while drafting the new pre-release through the GitHub form (this is indeed the only way to correctly associate the tag with a target branch; more on this below).
|
||||
The pre-release tag must be formatted as `M.m.p-r`, where `r` is the pre-release version information (e.g. `0.35.0-rc1`).
|
||||
|
||||
To do so:
|
||||
To create both pre-release tag and pre-release, do the following:
|
||||
|
||||
- [Draft a new release](https://github.com/falcosecurity/falco/releases/new)
|
||||
- Use `M.m.p-r` both as tag version and release title.
|
||||
- Use `M.m.p-r` both as tag version and release title
|
||||
- Associate `release/M.m.x` as "target branch" for the new tag
|
||||
- Check the "Set as a pre-release" checkbox and make sure "Set as the latest release" is unchecked
|
||||
- It is recommended to add a brief description so that other contributors will understand the reason why the prerelease is published
|
||||
- Publish the prerelease!
|
||||
- The release pipeline will start automatically. Packages will be uploaded to the `-dev` bucket and container images will be tagged with the specified tag.
|
||||
- The release pipeline will start automatically. Packages will be uploaded to the `-dev` bucket and container images will be tagged with the specified tag
|
||||
|
||||
In order to check the status of the release pipeline click on the [GitHub Actions tab](https://github.com/falcosecurity/falco/actions?query=event%3Arelease) in the Falco repository and filter by release.
|
||||
|
||||
@@ -150,6 +151,7 @@ Assume `M.m.p` is the new version.
|
||||
|
||||
- [Draft a new release](https://github.com/falcosecurity/falco/releases/new)
|
||||
- Use `M.m.p` both as tag version and release title
|
||||
- Associate `release/M.m.x` as "target branch" for the new tag
|
||||
- Do NOT fill body, since it will be autogenerated by the [github release workflow](.github/workflows/release.yaml)
|
||||
- Publish the release!
|
||||
- The release pipeline will start automatically upon publication and all packages and container images will be uploaded to the stable repositories.
|
||||
|
||||
@@ -53,15 +53,10 @@ Notice the capitalization of the following terms.
|
||||
|
||||
This section contains key terms specifically used within the context of The Falco Project. For a more comprehensive list of Falco-related terminology, we invite you to visit the [Glossary](https://falco.org/docs/reference/glossary/) page on our official website.
|
||||
|
||||
#### eBPF Probe
|
||||
|
||||
Used to describe the `.o` object that would be dynamically loaded into the kernel as a secure and stable (e)BPF probe.
|
||||
This is one option used to pass kernel events up to userspace for Falco to consume.
|
||||
|
||||
#### Modern eBPF Probe
|
||||
|
||||
More robust [eBPF probe](#ebpf-probe), which brings the CO-RE paradigm, better performances, and maintainability.
|
||||
Unlike the legacy probe, the modern eBPF probe is not shipped as a separate artifact but bundled into the Falco binary itself.
|
||||
Robust eBPF probe, which brings the CO-RE paradigm, better performances, and maintainability.
|
||||
The modern eBPF probe is not shipped as a separate artifact but bundled into the Falco binary itself.
|
||||
This is one option used to pass kernel events up to userspace for Falco to consume.
|
||||
|
||||
#### Kernel Module
|
||||
@@ -71,7 +66,7 @@ This is one option used to pass kernel events up to userspace for Falco to consu
|
||||
|
||||
#### Driver
|
||||
|
||||
The global term for the software that sends events from the kernel. Such as the [eBPF probe](#ebpf-probe), the [Modern eBPF probe](#modern-ebpf-probe), or the [Kernel Module](#kernel-module).
|
||||
The global term for the software that sends events from the kernel. Such as the [Modern eBPF probe](#modern-ebpf-probe), or the [Kernel Module](#kernel-module).
|
||||
|
||||
#### Plugin
|
||||
|
||||
|
||||
@@ -29,11 +29,6 @@ if(CPACK_GENERATOR MATCHES "DEB" OR CPACK_GENERATOR MATCHES "RPM")
|
||||
CPACK_INSTALL_COMMANDS
|
||||
"cp scripts/systemd/falco-kmod.service _CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}/usr/lib/systemd/system"
|
||||
)
|
||||
list(
|
||||
APPEND
|
||||
CPACK_INSTALL_COMMANDS
|
||||
"cp scripts/systemd/falco-bpf.service _CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}/usr/lib/systemd/system"
|
||||
)
|
||||
list(
|
||||
APPEND
|
||||
CPACK_INSTALL_COMMANDS
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
/etc/falco/falco.yaml
|
||||
/etc/falco/falcoctl.yaml
|
||||
/etc/falco/falco_rules.local.yaml
|
||||
/etc/falcoctl/falcoctl.yaml
|
||||
|
||||
@@ -23,6 +23,7 @@ endif()
|
||||
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "debug")
|
||||
set(KBUILD_FLAGS "${FALCO_EXTRA_DEBUG_FLAGS} ${FALCO_EXTRA_FEATURE_FLAGS}")
|
||||
add_definitions(-DBUILD_TYPE_DEBUG)
|
||||
elseif(CMAKE_BUILD_TYPE STREQUAL "relwithdebinfo")
|
||||
set(KBUILD_FLAGS "${FALCO_EXTRA_FEATURE_FLAGS}")
|
||||
add_definitions(-DBUILD_TYPE_RELWITHDEBINFO)
|
||||
@@ -59,10 +60,6 @@ if(NOT MSVC)
|
||||
if(USE_ASAN)
|
||||
set(FALCO_SECURITY_FLAGS "${FALCO_SECURITY_FLAGS} -fsanitize=address")
|
||||
endif()
|
||||
# todo(leogr): this should be passed down to libs cmake modules RTLD_DEEPBIND flag is
|
||||
# incompatible with sanitizer runtime (see https://github.com/google/sanitizers/issues/611 for
|
||||
# details)
|
||||
add_compile_definitions(DISABLE_RTLD_DEEPBIND=$<IF:$<BOOL:${USE_ASAN}>,1,0>)
|
||||
|
||||
if(USE_UBSAN)
|
||||
set(FALCO_SECURITY_FLAGS "${FALCO_SECURITY_FLAGS} -fsanitize=undefined")
|
||||
@@ -71,6 +68,10 @@ if(NOT MSVC)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(USE_FRAME_POINTER)
|
||||
set(FALCO_SECURITY_FLAGS "${FALCO_SECURITY_FLAGS} -fno-omit-frame-pointer")
|
||||
endif()
|
||||
|
||||
set(CMAKE_COMMON_FLAGS
|
||||
"${FALCO_SECURITY_FLAGS} -Wall -ggdb ${FALCO_EXTRA_FEATURE_FLAGS} ${MINIMAL_BUILD_FLAGS} ${MUSL_FLAGS}"
|
||||
)
|
||||
|
||||
@@ -24,7 +24,7 @@ if(CXXOPTS_INCLUDE_DIR)
|
||||
elseif(NOT USE_BUNDLED_CXXOPTS)
|
||||
find_package(cxxopts CONFIG REQUIRED)
|
||||
get_target_property(CXXOPTS_INCLUDE_DIR cxxopts::cxxopts INTERFACE_INCLUDE_DIRECTORIES)
|
||||
else()
|
||||
elseif(NOT TARGET cxxopts)
|
||||
set(CXXOPTS_SRC "${PROJECT_BINARY_DIR}/cxxopts-prefix/src/cxxopts/")
|
||||
set(CXXOPTS_INCLUDE_DIR "${CXXOPTS_SRC}/include")
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright (C) 2025 The Falco Authors.
|
||||
# Copyright (C) 2026 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
|
||||
@@ -35,9 +35,9 @@ else()
|
||||
# FALCOSECURITY_LIBS_VERSION. In case you want to test against another driver version (or
|
||||
# branch, or commit) just pass the variable - ie., `cmake -DDRIVER_VERSION=dev ..`
|
||||
if(NOT DRIVER_VERSION)
|
||||
set(DRIVER_VERSION "1de61cd2b7abcfbb492b5da7fbeaef5b0a5c0f20")
|
||||
set(DRIVER_VERSION "7b08f8a0a12b56d59eab73052e637ca123623f61")
|
||||
set(DRIVER_CHECKSUM
|
||||
"SHA256=fe98c0343954a7789c6cef692480905a60d943de657385d109b537e23689146e"
|
||||
"SHA256=43c72a98e48d04177c8223ccdfe88de6f09958f2330b6b9ee26882f1a77e369f"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -20,16 +20,16 @@ option(ADD_FALCOCTL_DEPENDENCY "Add falcoctl dependency while building falco" ON
|
||||
if(ADD_FALCOCTL_DEPENDENCY)
|
||||
string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} FALCOCTL_SYSTEM_NAME)
|
||||
|
||||
set(FALCOCTL_VERSION "0.11.4")
|
||||
set(FALCOCTL_VERSION "0.12.2")
|
||||
|
||||
message(STATUS "Building with falcoctl: ${FALCOCTL_VERSION}")
|
||||
|
||||
if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
set(FALCOCTL_SYSTEM_PROC_GO "amd64")
|
||||
set(FALCOCTL_HASH "8015cadcb4328abcbf140c3ca88031cd46426f7f3279d2802f0937ab1e41d66c")
|
||||
set(FALCOCTL_HASH "7e0e232aa73825383d3382b3af8a38466289a768f9c1c7f25bd7e11a3ed6980a")
|
||||
else() # aarch64
|
||||
set(FALCOCTL_SYSTEM_PROC_GO "arm64")
|
||||
set(FALCOCTL_HASH "246874f1168abb7a8463509c6191ede460e5a2b8a39058ef5c4a17b67cb86c85")
|
||||
set(FALCOCTL_HASH "9b7dd75189f997da6423bcdb5dfe68840f20c56f95d30d323d26d0c4bd75a8e3")
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright (C) 2025 The Falco Authors.
|
||||
# Copyright (C) 2026 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
|
||||
@@ -42,9 +42,9 @@ else()
|
||||
# version (or branch, or commit) just pass the variable - ie., `cmake
|
||||
# -DFALCOSECURITY_LIBS_VERSION=dev ..`
|
||||
if(NOT FALCOSECURITY_LIBS_VERSION)
|
||||
set(FALCOSECURITY_LIBS_VERSION "1de61cd2b7abcfbb492b5da7fbeaef5b0a5c0f20")
|
||||
set(FALCOSECURITY_LIBS_VERSION "7b08f8a0a12b56d59eab73052e637ca123623f61")
|
||||
set(FALCOSECURITY_LIBS_CHECKSUM
|
||||
"SHA256=fe98c0343954a7789c6cef692480905a60d943de657385d109b537e23689146e"
|
||||
"SHA256=43c72a98e48d04177c8223ccdfe88de6f09958f2330b6b9ee26882f1a77e369f"
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -87,11 +87,8 @@ if(NOT LIBS_DIR)
|
||||
set(LIBS_DIR "${FALCOSECURITY_LIBS_SOURCE_DIR}")
|
||||
endif()
|
||||
|
||||
# configure gVisor support
|
||||
set(BUILD_LIBSCAP_GVISOR
|
||||
${BUILD_FALCO_GVISOR}
|
||||
CACHE BOOL ""
|
||||
)
|
||||
# todo(ekoops): remove this once we remove gvisor from libs
|
||||
option(BUILD_LIBSCAP_GVISOR OFF)
|
||||
|
||||
# configure modern BPF support
|
||||
set(BUILD_LIBSCAP_MODERN_BPF
|
||||
@@ -108,6 +105,10 @@ set(BUILD_LIBSCAP_EXAMPLES
|
||||
OFF
|
||||
CACHE BOOL ""
|
||||
)
|
||||
set(BUILD_LIBSINSP_EXAMPLES
|
||||
OFF
|
||||
CACHE BOOL ""
|
||||
)
|
||||
|
||||
set(USE_BUNDLED_TBB
|
||||
ON
|
||||
|
||||
132
cmake/modules/gperftools.cmake
Normal file
132
cmake/modules/gperftools.cmake
Normal file
@@ -0,0 +1,132 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright (C) 2026 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.
|
||||
#
|
||||
|
||||
# gperftools CPU profiler support This module provides: GPERFTOOLS_INCLUDE_DIR (include directory)
|
||||
# and GPERFTOOLS_PROFILER_LIB (the profiler library path)
|
||||
|
||||
option(USE_BUNDLED_GPERFTOOLS "Build gperftools from source" ${USE_BUNDLED_DEPS})
|
||||
|
||||
if(GPERFTOOLS_INCLUDE_DIR)
|
||||
# Already have gperftools configured
|
||||
elseif(NOT USE_BUNDLED_GPERFTOOLS)
|
||||
# Use system gperftools
|
||||
find_path(
|
||||
GPERFTOOLS_INCLUDE_DIR
|
||||
NAMES gperftools/profiler.h
|
||||
PATHS /usr/include /usr/local/include
|
||||
)
|
||||
|
||||
find_library(
|
||||
GPERFTOOLS_PROFILER_LIB
|
||||
NAMES profiler
|
||||
PATHS /usr/lib /usr/local/lib /usr/lib/x86_64-linux-gnu /usr/lib/aarch64-linux-gnu
|
||||
)
|
||||
|
||||
if(GPERFTOOLS_INCLUDE_DIR AND GPERFTOOLS_PROFILER_LIB)
|
||||
message(
|
||||
STATUS
|
||||
"Found system gperftools: include: ${GPERFTOOLS_INCLUDE_DIR}, lib: ${GPERFTOOLS_PROFILER_LIB}"
|
||||
)
|
||||
else()
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Couldn't find system gperftools. Install it or use -DUSE_BUNDLED_GPERFTOOLS=ON\n"
|
||||
" Ubuntu/Debian: sudo apt-get install libgoogle-perftools-dev\n"
|
||||
" Fedora/RHEL: sudo dnf install gperftools-devel\n"
|
||||
" macOS: brew install gperftools"
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
# Build gperftools from source
|
||||
set(GPERFTOOLS_SRC "${PROJECT_BINARY_DIR}/gperftools-prefix/src/gperftools")
|
||||
set(GPERFTOOLS_INCLUDE_DIR "${GPERFTOOLS_SRC}/src")
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(GPERFTOOLS_LIB_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
else()
|
||||
set(GPERFTOOLS_LIB_SUFFIX ${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
endif()
|
||||
|
||||
# The library is built in .libs subdirectory
|
||||
set(GPERFTOOLS_PROFILER_LIB "${GPERFTOOLS_SRC}/.libs/libprofiler${GPERFTOOLS_LIB_SUFFIX}")
|
||||
|
||||
# gperftools version 2.15 (latest stable as of 2024)
|
||||
set(GPERFTOOLS_VERSION "2.15")
|
||||
set(GPERFTOOLS_URL
|
||||
"https://github.com/gperftools/gperftools/releases/download/gperftools-${GPERFTOOLS_VERSION}/gperftools-${GPERFTOOLS_VERSION}.tar.gz"
|
||||
)
|
||||
set(GPERFTOOLS_URL_HASH
|
||||
"SHA256=c69fef855628c81ef56f12e3c58f2b7ce1f326c0a1fe783e5cae0b88cbbe9a80"
|
||||
)
|
||||
|
||||
message(STATUS "Building gperftools ${GPERFTOOLS_VERSION} from source")
|
||||
|
||||
# Configure options for gperftools
|
||||
set(GPERFTOOLS_CONFIGURE_ARGS --enable-cpu-profiler --disable-heap-profiler
|
||||
--disable-heap-checker --disable-debugalloc
|
||||
)
|
||||
|
||||
# Check if libunwind is available for better stack traces
|
||||
find_library(LIBUNWIND_LIBRARY NAMES unwind)
|
||||
if(LIBUNWIND_LIBRARY)
|
||||
list(APPEND GPERFTOOLS_CONFIGURE_ARGS --enable-libunwind)
|
||||
message(STATUS "gperftools: libunwind found, enabling for better stack traces")
|
||||
else()
|
||||
list(APPEND GPERFTOOLS_CONFIGURE_ARGS --disable-libunwind)
|
||||
message(STATUS "gperftools: libunwind not found, using frame pointers for stack traces")
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(
|
||||
gperftools
|
||||
PREFIX "${PROJECT_BINARY_DIR}/gperftools-prefix"
|
||||
URL "${GPERFTOOLS_URL}"
|
||||
URL_HASH "${GPERFTOOLS_URL_HASH}"
|
||||
CONFIGURE_COMMAND <SOURCE_DIR>/configure ${GPERFTOOLS_CONFIGURE_ARGS}
|
||||
BUILD_COMMAND ${CMD_MAKE} ${PROCESSOUR_COUNT_MAKE_FLAG}
|
||||
BUILD_IN_SOURCE 1
|
||||
INSTALL_COMMAND ""
|
||||
UPDATE_COMMAND ""
|
||||
BUILD_BYPRODUCTS ${GPERFTOOLS_PROFILER_LIB}
|
||||
)
|
||||
|
||||
install(
|
||||
FILES "${GPERFTOOLS_PROFILER_LIB}"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/${LIBS_PACKAGE_NAME}"
|
||||
COMPONENT "libs-deps"
|
||||
OPTIONAL
|
||||
)
|
||||
endif()
|
||||
|
||||
# Create a custom target so we can always depend on 'gperftools' regardless of bundled/system
|
||||
if(NOT TARGET gperftools)
|
||||
add_custom_target(gperftools)
|
||||
endif()
|
||||
|
||||
# Add include directory globally
|
||||
include_directories(${GPERFTOOLS_INCLUDE_DIR})
|
||||
|
||||
# Add compile definition so code can detect profiling support
|
||||
add_compile_definitions(HAS_GPERFTOOLS)
|
||||
|
||||
# Wrap the profiler library with --whole-archive to ensure the profiler's initialization code is
|
||||
# linked even though we don't call ProfilerStart() directly. This is required for the CPUPROFILE
|
||||
# environment variable to work.
|
||||
set(GPERFTOOLS_PROFILER_LIB "-Wl,--whole-archive" "${GPERFTOOLS_PROFILER_LIB}"
|
||||
"-Wl,--no-whole-archive"
|
||||
)
|
||||
|
||||
message(STATUS "gperftools CPU profiler enabled")
|
||||
message(STATUS " Include dir: ${GPERFTOOLS_INCLUDE_DIR}")
|
||||
message(STATUS " Library: ${GPERFTOOLS_PROFILER_LIB}")
|
||||
@@ -1,278 +0,0 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright (C) 2023 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.
|
||||
#
|
||||
|
||||
option(USE_BUNDLED_GRPC "Enable building of the bundled grpc" ${USE_BUNDLED_DEPS})
|
||||
|
||||
if(GRPC_INCLUDE)
|
||||
# we already have grpc
|
||||
elseif(NOT USE_BUNDLED_GRPC)
|
||||
# gRPC
|
||||
find_package(gRPC CONFIG)
|
||||
if(gRPC_FOUND)
|
||||
message(STATUS "Using gRPC ${gRPC_VERSION}")
|
||||
set(GPR_LIB gRPC::gpr)
|
||||
set(GRPC_LIB gRPC::grpc)
|
||||
set(GRPCPP_LIB gRPC::grpc++)
|
||||
|
||||
# gRPC C++ plugin
|
||||
get_target_property(GRPC_CPP_PLUGIN gRPC::grpc_cpp_plugin LOCATION)
|
||||
if(NOT GRPC_CPP_PLUGIN)
|
||||
message(FATAL_ERROR "System grpc_cpp_plugin not found")
|
||||
endif()
|
||||
|
||||
# gRPC include dir + properly handle grpc{++,pp}
|
||||
get_target_property(GRPC_INCLUDE gRPC::grpc++ INTERFACE_INCLUDE_DIRECTORIES)
|
||||
find_path(
|
||||
GRPCXX_INCLUDE
|
||||
NAMES grpc++/grpc++.h
|
||||
PATHS ${GRPC_INCLUDE}
|
||||
)
|
||||
if(NOT GRPCXX_INCLUDE)
|
||||
find_path(
|
||||
GRPCPP_INCLUDE
|
||||
NAMES grpcpp/grpcpp.h
|
||||
PATHS ${GRPC_INCLUDE}
|
||||
)
|
||||
add_definitions(-DGRPC_INCLUDE_IS_GRPCPP=1)
|
||||
endif()
|
||||
else()
|
||||
# Fallback to manually find libraries; Some distro, namely Ubuntu focal, do not install gRPC
|
||||
# config cmake module
|
||||
find_library(GPR_LIB NAMES gpr)
|
||||
if(GPR_LIB)
|
||||
message(STATUS "Found gpr lib: ${GPR_LIB}")
|
||||
else()
|
||||
message(FATAL_ERROR "Couldn't find system gpr")
|
||||
endif()
|
||||
find_path(GRPCXX_INCLUDE NAMES grpc++/grpc++.h)
|
||||
if(GRPCXX_INCLUDE)
|
||||
set(GRPC_INCLUDE ${GRPCXX_INCLUDE})
|
||||
else()
|
||||
find_path(GRPCPP_INCLUDE NAMES grpcpp/grpcpp.h)
|
||||
set(GRPC_INCLUDE ${GRPCPP_INCLUDE})
|
||||
add_definitions(-DGRPC_INCLUDE_IS_GRPCPP=1)
|
||||
endif()
|
||||
find_library(GRPC_LIB NAMES grpc)
|
||||
find_library(GRPCPP_LIB NAMES grpc++)
|
||||
if(GRPC_INCLUDE
|
||||
AND GRPC_LIB
|
||||
AND GRPCPP_LIB
|
||||
)
|
||||
message(
|
||||
STATUS
|
||||
"Found grpc: include: ${GRPC_INCLUDE}, C lib: ${GRPC_LIB}, C++ lib: ${GRPCPP_LIB}"
|
||||
)
|
||||
else()
|
||||
message(FATAL_ERROR "Couldn't find system grpc")
|
||||
endif()
|
||||
find_program(GRPC_CPP_PLUGIN grpc_cpp_plugin)
|
||||
if(NOT GRPC_CPP_PLUGIN)
|
||||
message(FATAL_ERROR "System grpc_cpp_plugin not found")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
include(cares)
|
||||
include(protobuf)
|
||||
include(zlib)
|
||||
include(openssl)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(GRPC_OPENSSL_STATIC_LIBS_OPTION FALSE)
|
||||
else()
|
||||
set(GRPC_OPENSSL_STATIC_LIBS_OPTION TRUE)
|
||||
endif()
|
||||
include(re2)
|
||||
set(GRPC_SRC "${PROJECT_BINARY_DIR}/grpc-prefix/src/grpc")
|
||||
set(GRPC_INSTALL_DIR "${GRPC_SRC}/target")
|
||||
set(GRPC_INCLUDE "${GRPC_INSTALL_DIR}/include" "${GRPC_SRC}/third_party/abseil-cpp")
|
||||
set(GPR_LIB "${GRPC_SRC}/libgpr.a")
|
||||
set(GRPC_LIB "${GRPC_SRC}/libgrpc.a")
|
||||
set(GRPCPP_LIB "${GRPC_SRC}/libgrpc++.a")
|
||||
set(GRPC_CPP_PLUGIN "${GRPC_SRC}/grpc_cpp_plugin")
|
||||
set(GRPC_MAIN_LIBS "")
|
||||
list(
|
||||
APPEND
|
||||
GRPC_MAIN_LIBS
|
||||
"${GPR_LIB}"
|
||||
"${GRPC_LIB}"
|
||||
"${GRPCPP_LIB}"
|
||||
"${GRPC_SRC}/libgrpc++_alts.a"
|
||||
"${GRPC_SRC}/libgrpc++_error_details.a"
|
||||
"${GRPC_SRC}/libgrpc++_reflection.a"
|
||||
"${GRPC_SRC}/libgrpc++_unsecure.a"
|
||||
"${GRPC_SRC}/libgrpc_plugin_support.a"
|
||||
"${GRPC_SRC}/libgrpc_unsecure.a"
|
||||
"${GRPC_SRC}/libgrpcpp_channelz.a"
|
||||
)
|
||||
|
||||
get_filename_component(PROTOC_DIR ${PROTOC} PATH)
|
||||
|
||||
if(NOT TARGET grpc)
|
||||
message(STATUS "Using bundled grpc in '${GRPC_SRC}'")
|
||||
|
||||
# fixme(leogr): this workaround is required to inject the missing deps (built by gRCP
|
||||
# cmakefiles) into target_link_libraries later note: the list below is manually generated
|
||||
# starting from the output of pkg-config --libs grpc++
|
||||
set(GRPC_LIBRARIES "")
|
||||
list(
|
||||
APPEND
|
||||
GRPC_LIBRARIES
|
||||
"${GRPC_SRC}/libaddress_sorting.a"
|
||||
"${GRPC_SRC}/libupb.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/hash/libabsl_hash.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/hash/libabsl_city.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/hash/libabsl_low_level_hash.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/container/libabsl_raw_hash_set.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/container/libabsl_hashtablez_sampler.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/status/libabsl_statusor.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/status/libabsl_status.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/strings/libabsl_cord.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/strings/libabsl_cordz_functions.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/profiling/libabsl_exponential_biased.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/types/libabsl_bad_optional_access.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/types/libabsl_bad_variant_access.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/strings/libabsl_str_format_internal.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/synchronization/libabsl_synchronization.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/synchronization/libabsl_graphcycles_internal.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/debugging/libabsl_stacktrace.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/debugging/libabsl_symbolize.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/debugging/libabsl_debugging_internal.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/debugging/libabsl_demangle_internal.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/base/libabsl_malloc_internal.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/time/libabsl_time.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/time/libabsl_civil_time.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/strings/libabsl_strings.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/strings/libabsl_strings_internal.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/base/libabsl_base.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/base/libabsl_spinlock_wait.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/numeric/libabsl_int128.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/base/libabsl_throw_delegate.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/base/libabsl_raw_logging_internal.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/base/libabsl_log_severity.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/time/libabsl_time_zone.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/strings/libabsl_cord_internal.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/strings/libabsl_cordz_info.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/strings/libabsl_cordz_handle.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/random/libabsl_random_internal_pool_urbg.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/random/libabsl_random_internal_randen.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/random/libabsl_random_internal_randen_hwaes.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/random/libabsl_random_internal_randen_hwaes_impl.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/random/libabsl_random_internal_randen_slow.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/random/libabsl_random_internal_seed_material.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/random/libabsl_random_internal_platform.a"
|
||||
"${GRPC_SRC}/third_party/abseil-cpp/absl/random/libabsl_random_seed_gen_exception.a"
|
||||
)
|
||||
|
||||
# Make abseil-cpp build compatible with gcc-13 See
|
||||
# https://patchwork.yoctoproject.org/project/oe/patch/20230518093301.2938164-1-Martin.Jansa@gmail.com/
|
||||
# TO BE DROPPED once we finally upgrade grpc...
|
||||
set(GRPC_PATCH_CMD
|
||||
sh
|
||||
-c
|
||||
"sed -i '20s/^/#include <cstdint>/' ${GRPC_SRC}/third_party/abseil-cpp/absl/strings/internal/str_format/extension.h"
|
||||
&&
|
||||
sh
|
||||
-c
|
||||
"sed -i 's|off64_t|off_t|g' ${GRPC_SRC}/third_party/abseil-cpp/absl/base/internal/direct_mmap.h"
|
||||
)
|
||||
|
||||
# Zig workaround: Add a PATCH_COMMAND to grpc cmake to fixup emitted -march by abseil-cpp
|
||||
# cmake module, making it use a name understood by zig for arm64. See
|
||||
# https://github.com/abseil/abseil-cpp/blob/master/absl/copts/GENERATED_AbseilCopts.cmake#L226.
|
||||
if(CMAKE_C_COMPILER MATCHES "zig")
|
||||
message(STATUS "Enabling zig workaround for abseil-cpp")
|
||||
set(GRPC_PATCH_CMD
|
||||
${GRPC_PATCH_CMD}
|
||||
&&
|
||||
sh
|
||||
-c
|
||||
"sed -i 's/armv8-a/cortex_a57/g' ${GRPC_SRC}/third_party/abseil-cpp/absl/copts/GENERATED_AbseilCopts.cmake"
|
||||
)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(
|
||||
grpc
|
||||
PREFIX "${PROJECT_BINARY_DIR}/grpc-prefix"
|
||||
DEPENDS openssl protobuf c-ares zlib re2
|
||||
GIT_REPOSITORY https://github.com/grpc/grpc.git
|
||||
GIT_TAG v1.44.0
|
||||
GIT_SUBMODULES "third_party/abseil-cpp"
|
||||
CMAKE_CACHE_ARGS
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=${GRPC_INSTALL_DIR}
|
||||
-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
|
||||
-DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=${ENABLE_PIC}
|
||||
-DgRPC_INSTALL:BOOL=OFF
|
||||
# disable unused stuff
|
||||
-DgRPC_BUILD_TESTS:BOOL=OFF
|
||||
-DgRPC_BUILD_CSHARP_EXT:BOOL=OFF
|
||||
-DgRPC_BUILD_GRPC_CSHARP_PLUGIN:BOOL=OFF
|
||||
-DgRPC_BUILD_GRPC_NODE_PLUGIN:BOOL=OFF
|
||||
-DgRPC_BUILD_GRPC_OBJECTIVE_C_PLUGIN:BOOL=OFF
|
||||
-DgRPC_BUILD_GRPC_PHP_PLUGIN:BOOL=OFF
|
||||
-DgRPC_BUILD_GRPC_PYTHON_PLUGIN:BOOL=OFF
|
||||
-DgRPC_BUILD_GRPC_RUBY_PLUGIN:BOOL=OFF
|
||||
# deps provided by us
|
||||
# https://github.com/grpc/grpc/blob/v1.32.0/cmake/modules/Findc-ares.cmake
|
||||
-DgRPC_CARES_PROVIDER:STRING=package
|
||||
-Dc-ares_DIR:PATH=${CARES_SRC}
|
||||
-Dc-ares_INCLUDE_DIR:PATH=${CARES_INCLUDE}
|
||||
-Dc-ares_LIBRARY:PATH=${CARES_LIB}
|
||||
# https://cmake.org/cmake/help/v3.6/module/FindProtobuf.html
|
||||
-DgRPC_PROTOBUF_PROVIDER:STRING=package
|
||||
-DCMAKE_CXX_FLAGS:STRING=-I${PROTOBUF_INCLUDE}
|
||||
-DProtobuf_INCLUDE_DIR:PATH=${PROTOBUF_INCLUDE}
|
||||
-DProtobuf_LIBRARY:PATH=${PROTOBUF_LIB}
|
||||
-DProtobuf_PROTOC_LIBRARY:PATH=${PROTOC_LIB}
|
||||
-DProtobuf_PROTOC_EXECUTABLE:PATH=${PROTOC}
|
||||
# https://cmake.org/cmake/help/v3.6/module/FindOpenSSL.html
|
||||
-DgRPC_SSL_PROVIDER:STRING=package
|
||||
-DOPENSSL_ROOT_DIR:PATH=${OPENSSL_INSTALL_DIR}
|
||||
-DOPENSSL_USE_STATIC_LIBS:BOOL=${GRPC_OPENSSL_STATIC_LIBS_OPTION}
|
||||
# https://cmake.org/cmake/help/v3.6/module/FindZLIB.html
|
||||
-DgRPC_ZLIB_PROVIDER:STRING=package
|
||||
-DZLIB_ROOT:STRING=${ZLIB_SRC}
|
||||
# RE2
|
||||
-DgRPC_RE2_PROVIDER:STRING=package
|
||||
-Dre2_DIR:PATH=${RE2_DIR}
|
||||
BUILD_IN_SOURCE 1
|
||||
BUILD_BYPRODUCTS ${GRPC_LIB} ${GRPCPP_LIB} ${GPR_LIB} ${GRPC_LIBRARIES}
|
||||
# Keep installation files into the local ${GRPC_INSTALL_DIR} since here is the case when
|
||||
# we are embedding gRPC
|
||||
UPDATE_COMMAND ""
|
||||
PATCH_COMMAND ${GRPC_PATCH_CMD}
|
||||
INSTALL_COMMAND DESTDIR= ${CMAKE_MAKE_PROGRAM} install
|
||||
)
|
||||
install(
|
||||
FILES ${GRPC_MAIN_LIBS}
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/${LIBS_PACKAGE_NAME}"
|
||||
COMPONENT "libs-deps"
|
||||
)
|
||||
install(
|
||||
FILES ${GRPC_LIBRARIES}
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/${LIBS_PACKAGE_NAME}"
|
||||
COMPONENT "libs-deps"
|
||||
)
|
||||
install(
|
||||
DIRECTORY "${GRPC_SRC}/target/include/"
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${LIBS_PACKAGE_NAME}"
|
||||
COMPONENT "libs-deps"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT TARGET grpc)
|
||||
add_custom_target(grpc)
|
||||
endif()
|
||||
|
||||
include_directories("${GRPC_INCLUDE}")
|
||||
@@ -18,9 +18,9 @@ include(ExternalProject)
|
||||
|
||||
if(NOT DEFINED FALCOSECURITY_RULES_FALCO_PATH)
|
||||
# falco_rules.yaml
|
||||
set(FALCOSECURITY_RULES_FALCO_VERSION "falco-rules-5.0.0-rc1")
|
||||
set(FALCOSECURITY_RULES_FALCO_VERSION "falco-rules-5.0.0")
|
||||
set(FALCOSECURITY_RULES_FALCO_CHECKSUM
|
||||
"SHA256=0dd309a8d6ef2e98600da117a958c399d8c682ca7b27883528ccf5ed39867545"
|
||||
"SHA256=ca87d972e102a9f960fed41f90d2736a73079fcc7e787187028f455ad58b1637"
|
||||
)
|
||||
set(FALCOSECURITY_RULES_FALCO_PATH
|
||||
"${PROJECT_BINARY_DIR}/falcosecurity-rules-falco-prefix/src/falcosecurity-rules-falco/falco_rules.yaml"
|
||||
|
||||
@@ -17,11 +17,12 @@ LABEL usage="docker run -i -t --privileged -v /root/.falco:/root/.falco -v /proc
|
||||
ARG TARGETARCH
|
||||
|
||||
ARG VERSION_BUCKET=deb
|
||||
ENV VERSION_BUCKET=${VERSION_BUCKET}
|
||||
|
||||
ENV FALCO_VERSION=${FALCO_VERSION}
|
||||
ENV HOST_ROOT=/host
|
||||
ENV HOME=/root
|
||||
ARG HOST_ROOT=/host
|
||||
ARG HOME=/root
|
||||
ENV FALCO_VERSION="${FALCO_VERSION}" \
|
||||
VERSION_BUCKET="${VERSION_BUCKET}" \
|
||||
HOST_ROOT="${HOST_ROOT}" \
|
||||
HOME="${HOME}"
|
||||
|
||||
RUN cp /etc/skel/.bashrc /root && cp /etc/skel/.profile /root
|
||||
|
||||
@@ -136,6 +137,6 @@ RUN curl -L -o binutils_2.30-22_${TARGETARCH}.deb https://download.falco.org/dep
|
||||
&& dpkg -i *binutils*.deb \
|
||||
&& rm -f *binutils*.deb
|
||||
|
||||
COPY ./docker/driver-loader-buster/docker-entrypoint.sh /
|
||||
COPY docker/driver-loader-buster/docker-entrypoint.sh /
|
||||
|
||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright (C) 2023 The Falco Authors.
|
||||
# Copyright (C) 2026 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -27,7 +27,6 @@ print_usage() {
|
||||
echo " auto leverage automatic driver selection logic (default)"
|
||||
echo " modern_ebpf modern eBPF CORE probe"
|
||||
echo " kmod kernel module"
|
||||
echo " ebpf eBPF probe"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --help show this help message"
|
||||
@@ -59,7 +58,7 @@ driver=
|
||||
has_opts=
|
||||
while test $# -gt 0; do
|
||||
case "$1" in
|
||||
auto|kmod|ebpf|modern_ebpf)
|
||||
auto|kmod|modern_ebpf)
|
||||
if [ -n "$driver" ]; then
|
||||
>&2 echo "Only one driver per invocation"
|
||||
print_usage
|
||||
@@ -120,7 +119,7 @@ if [ "$driver" != "auto" ]; then
|
||||
/usr/bin/falcoctl driver config --type $driver
|
||||
else
|
||||
# Needed because we need to configure Falco to start with correct driver
|
||||
/usr/bin/falcoctl driver config --type modern_ebpf --type kmod --type ebpf
|
||||
/usr/bin/falcoctl driver config --type modern_ebpf --type kmod
|
||||
fi
|
||||
|
||||
/usr/bin/falcoctl driver install --compile=$ENABLE_COMPILE --download=$ENABLE_DOWNLOAD --http-insecure=$HTTP_INSECURE --http-headers="$FALCOCTL_DRIVER_HTTP_HEADERS"
|
||||
|
||||
@@ -27,7 +27,6 @@ print_usage() {
|
||||
echo " auto leverage automatic driver selection logic (default)"
|
||||
echo " modern_ebpf modern eBPF CORE probe"
|
||||
echo " kmod kernel module"
|
||||
echo " ebpf eBPF probe"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --help show this help message"
|
||||
@@ -64,7 +63,7 @@ extra_args=
|
||||
|
||||
while test $# -gt 0; do
|
||||
case "$1" in
|
||||
auto|kmod|ebpf|modern_ebpf)
|
||||
auto|kmod|modern_ebpf)
|
||||
if [ -n "$driver" ]; then
|
||||
>&2 echo "Only one driver per invocation"
|
||||
print_usage
|
||||
@@ -133,7 +132,7 @@ if [ "$driver" != "auto" ]; then
|
||||
/usr/bin/falcoctl driver config --type $driver
|
||||
else
|
||||
# Needed because we need to configure Falco to start with correct driver
|
||||
/usr/bin/falcoctl driver config --type modern_ebpf --type kmod --type ebpf
|
||||
/usr/bin/falcoctl driver config --type modern_ebpf --type kmod
|
||||
fi
|
||||
|
||||
/usr/bin/falcoctl driver install --compile=$ENABLE_COMPILE --download=$ENABLE_DOWNLOAD --http-insecure=$HTTP_INSECURE --http-headers="$FALCOCTL_DRIVER_HTTP_HEADERS" $extra_args
|
||||
|
||||
@@ -15,14 +15,15 @@ LABEL org.opencontainers.image.authors='The Falco Authors https://falco.org' \
|
||||
LABEL usage="docker run -i -t --privileged -v /var/run/docker.sock:/host/var/run/docker.sock -v /proc:/host/proc:ro -v /etc:/host/etc:ro falcosecurity/falco:latest-debian"
|
||||
|
||||
ARG VERSION_BUCKET=deb
|
||||
ARG HOST_ROOT=/host
|
||||
ARG HOME=/root
|
||||
|
||||
ENV FALCO_VERSION=${FALCO_VERSION}
|
||||
ENV VERSION_BUCKET=${VERSION_BUCKET}
|
||||
ENV FALCO_VERSION="${FALCO_VERSION}" \
|
||||
VERSION_BUCKET="${VERSION_BUCKET}" \
|
||||
HOST_ROOT="${HOST_ROOT}" \
|
||||
HOME="${HOME}"
|
||||
|
||||
ENV HOST_ROOT=/host
|
||||
ENV HOME=/root
|
||||
|
||||
RUN apt-get -y update && apt-get -y install ca-certificates curl jq ca-certificates gnupg2 \
|
||||
RUN apt-get -y update && apt-get -y install curl jq ca-certificates gnupg2 \
|
||||
&& apt clean -y && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /
|
||||
@@ -35,6 +36,6 @@ RUN curl -s https://falco.org/repo/falcosecurity-packages.asc | apt-key add - \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Change the falco config within the container to enable ISO 8601 output.
|
||||
ADD ./config/falco.iso8601_timeformat.yaml /etc/falco/config.d/
|
||||
ADD config/falco.iso8601_timeformat.yaml /etc/falco/config.d/
|
||||
|
||||
CMD ["/usr/bin/falco"]
|
||||
|
||||
@@ -16,30 +16,33 @@ LABEL usage="docker run -i -t --privileged -v /var/run/docker.sock:/host/var/run
|
||||
# NOTE: for the "least privileged" use case, please refer to the official documentation
|
||||
|
||||
ARG VERSION_BUCKET=bin
|
||||
ARG HOST_ROOT=/host
|
||||
ARG HOME=/root
|
||||
|
||||
ENV FALCO_VERSION=${FALCO_VERSION}
|
||||
ENV VERSION_BUCKET=${VERSION_BUCKET}
|
||||
ENV HOST_ROOT=/host
|
||||
ENV HOME=/root
|
||||
ENV FALCO_VERSION="${FALCO_VERSION}" \
|
||||
VERSION_BUCKET="${VERSION_BUCKET}" \
|
||||
HOST_ROOT="${HOST_ROOT}" \
|
||||
HOME="${HOME}"
|
||||
|
||||
RUN apk update && apk add curl ca-certificates jq libstdc++
|
||||
|
||||
WORKDIR /
|
||||
|
||||
RUN FALCO_VERSION_URLENCODED=$(echo -n ${FALCO_VERSION}|jq -sRr @uri) && \
|
||||
RUN ARCH=$(uname -m) && \
|
||||
FALCO_VERSION_URLENCODED=$(echo -n "${FALCO_VERSION}" | jq -sRr @uri) && \
|
||||
echo "Downloading Falco ${FALCO_VERSION} for ${ARCH}" && \
|
||||
curl -L -o falco.tar.gz \
|
||||
https://download.falco.org/packages/${VERSION_BUCKET}/$(uname -m)/falco-${FALCO_VERSION_URLENCODED}-$(uname -m).tar.gz && \
|
||||
https://download.falco.org/packages/${VERSION_BUCKET}/${ARCH}/falco-${FALCO_VERSION_URLENCODED}-${ARCH}.tar.gz && \
|
||||
tar -xvf falco.tar.gz && \
|
||||
rm -f falco.tar.gz && \
|
||||
mv falco-${FALCO_VERSION}-$(uname -m) falco && \
|
||||
mv falco-${FALCO_VERSION}-${ARCH} falco && \
|
||||
rm -rf /falco/usr/src/falco-* && \
|
||||
cp -r /falco/* / && \
|
||||
rm -rf /falco
|
||||
rm -rf /falco && \
|
||||
rm -rf /usr/bin/falcoctl /etc/falcoctl/
|
||||
|
||||
|
||||
# Change the falco config within the container to enable ISO 8601 output.
|
||||
ADD ./config/falco.iso8601_timeformat.yaml /etc/falco/config.d/
|
||||
|
||||
# Falcoctl is not included here.
|
||||
RUN rm -rf /usr/bin/falcoctl /etc/falcoctl/
|
||||
ADD config/falco.iso8601_timeformat.yaml /etc/falco/config.d/
|
||||
|
||||
CMD ["/usr/bin/falco"]
|
||||
|
||||
98
falco.yaml
98
falco.yaml
@@ -70,9 +70,7 @@
|
||||
# file_output [Stable]
|
||||
# http_output [Stable]
|
||||
# program_output [Stable]
|
||||
# grpc_output [Stable]
|
||||
# Falco exposed services
|
||||
# grpc [Stable]
|
||||
# webserver [Stable]
|
||||
# Falco logging / alerting / metrics related to software functioning (basic)
|
||||
# log_stderr [Stable]
|
||||
@@ -285,9 +283,7 @@ rules_files:
|
||||
#
|
||||
# Available engines:
|
||||
# - `kmod`: Kernel Module
|
||||
# - `ebpf`: Legacy eBPF probe
|
||||
# - `modern_ebpf`: Modern eBPF (CO-RE eBPF probe)
|
||||
# - `gvisor`: gVisor sandbox
|
||||
# - `replay`: Replay a scap trace file
|
||||
# - `nodriver`: No driver is injected into the system.
|
||||
# This is useful to debug and to run plugins with 'syscall' source.
|
||||
@@ -357,15 +353,14 @@ rules_files:
|
||||
#
|
||||
################### `cpus_for_each_buffer` (modern_ebpf only)
|
||||
#
|
||||
# The modern_ebpf driver in Falco utilizes the new BPF ring buffer, which has a
|
||||
# different memory footprint compared to the current BPF driver that uses the
|
||||
# perf buffer. The Falco core maintainers have discussed the differences and
|
||||
# their implications, particularly in Kubernetes environments where limits need
|
||||
# to be carefully set to avoid interference with the Falco daemonset deployment
|
||||
# from the OOM killer. Based on guidance received from the kernel mailing list,
|
||||
# it is recommended to assign multiple CPUs to one buffer instead of allocating
|
||||
# a buffer for each CPU individually. This helps optimize resource allocation
|
||||
# and prevent potential issues related to memory usage.
|
||||
# The modern_ebpf driver in Falco utilizes the new BPF ring buffer. The Falco
|
||||
# core maintainers have discussed the differences and their implications,
|
||||
# particularly in Kubernetes environments where limits need to be carefully set
|
||||
# to avoid interference with the Falco daemonset deployment from the OOM
|
||||
# killer. Based on guidance received from the kernel mailing list, it is
|
||||
# recommended to assign multiple CPUs to one buffer instead of allocating a
|
||||
# buffer for each CPU individually. This helps optimize resource allocation and
|
||||
# prevent potential issues related to memory usage.
|
||||
#
|
||||
# This is an index that controls how many CPUs you want to assign to a single
|
||||
# syscall buffer (ring buffer). By default, for modern_ebpf every syscall buffer
|
||||
@@ -438,12 +433,6 @@ engine:
|
||||
kmod:
|
||||
buf_size_preset: 4
|
||||
drop_failed_exit: false
|
||||
# -- Engine-specific configuration for Legacy eBPF (ebpf) engine.
|
||||
ebpf:
|
||||
# -- Path to the elf file to load.
|
||||
probe: ${HOME}/.falco/falco-bpf.o
|
||||
buf_size_preset: 4
|
||||
drop_failed_exit: false
|
||||
# -- Engine-specific configuration for Modern eBPF (modern_ebpf) engine.
|
||||
modern_ebpf:
|
||||
cpus_for_each_buffer: 2
|
||||
@@ -453,15 +442,6 @@ engine:
|
||||
replay:
|
||||
# -- Path to the capture file to replay (eg: /path/to/file.scap)
|
||||
capture_file: ""
|
||||
# -- Engine-specific configuration for gVisor (gvisor) engine.
|
||||
gvisor:
|
||||
# -- A Falco-compatible configuration file can be generated with
|
||||
# '--gvisor-generate-config' and utilized for both runsc and Falco.
|
||||
config: ""
|
||||
# -- Set gVisor root directory for storage of container state when used
|
||||
# in conjunction with 'gvisor.config'. The 'gvisor.root' to be passed
|
||||
# is the one usually passed to 'runsc --root' flag.
|
||||
root: ""
|
||||
|
||||
##################
|
||||
# Falco captures #
|
||||
@@ -737,7 +717,7 @@ outputs_queue:
|
||||
# With this setting you can add more information to the Falco output message, customizable by
|
||||
# rule, tag or source.
|
||||
# You can also add additional data that will appear in the output_fields property
|
||||
# of JSON formatted messages or gRPC output but will not be part of the regular output message.
|
||||
# of JSON formatted messages but will not be part of the regular output message.
|
||||
# This allows you to add custom fields that can help you filter your Falco events without
|
||||
# polluting the message text.
|
||||
#
|
||||
@@ -798,7 +778,7 @@ append_output:
|
||||
# Falco outputs channels #
|
||||
##########################
|
||||
|
||||
# Falco supports various output channels, such as syslog, stdout, file, gRPC,
|
||||
# Falco supports various output channels, such as syslog, stdout, file,
|
||||
# webhook, and more. You can enable or disable these channels as needed to
|
||||
# control where Falco alerts and log messages are directed. This flexibility
|
||||
# allows seamless integration with your preferred logging and alerting systems.
|
||||
@@ -894,68 +874,10 @@ program_output:
|
||||
# -- The program to execute.
|
||||
program: "jq '{text: .output}' | curl -d @- -X POST https://hooks.slack.com/services/XXX"
|
||||
|
||||
# [Stable] `grpc_output`
|
||||
#
|
||||
# -- Use gRPC as an output service.
|
||||
#
|
||||
# gRPC is a modern and high-performance framework for remote procedure calls
|
||||
# (RPC). It utilizes protocol buffers for efficient data serialization. The gRPC
|
||||
# output in Falco provides a modern and efficient way to integrate with other
|
||||
# systems. By default the setting is turned off. Enabling this option stores
|
||||
# output events in memory until they are consumed by a gRPC client. Ensure that
|
||||
# you have a consumer for the output events or leave it disabled.
|
||||
grpc_output:
|
||||
# -- Enable gRPC as an output service.
|
||||
enabled: false
|
||||
|
||||
##########################
|
||||
# Falco exposed services #
|
||||
##########################
|
||||
|
||||
# [Stable] `grpc`
|
||||
#
|
||||
# Falco provides support for running a gRPC server using two main binding types:
|
||||
# 1. Over the network with mandatory mutual TLS authentication (mTLS), which
|
||||
# ensures secure communication
|
||||
# 2. Local Unix socket binding with no authentication. By default, the
|
||||
# gRPC server in Falco is turned off with no enabled services (see
|
||||
# `grpc_output` setting).
|
||||
#
|
||||
# To configure the gRPC server in Falco, you can make the following changes to
|
||||
# the options:
|
||||
#
|
||||
# - Uncomment the relevant configuration options related to the gRPC server.
|
||||
# - Update the paths of the generated certificates for mutual TLS authentication
|
||||
# if you choose to use mTLS.
|
||||
# - Specify the address to bind and expose the gRPC server.
|
||||
# - Adjust the threadiness configuration to control the number of threads and
|
||||
# contexts used by the server.
|
||||
#
|
||||
# Keep in mind that if any issues arise while creating the gRPC server, the
|
||||
# information will be logged, but it will not stop the main Falco daemon.
|
||||
#
|
||||
# gRPC server using mTLS
|
||||
# grpc:
|
||||
# enabled: true
|
||||
# bind_address: "0.0.0.0:5060"
|
||||
# # When the `threadiness` value is set to 0, Falco will automatically determine
|
||||
# # the appropriate number of threads based on the number of online cores in the system.
|
||||
# threadiness: 0
|
||||
# private_key: "/etc/falco/certs/server.key"
|
||||
# cert_chain: "/etc/falco/certs/server.crt"
|
||||
# root_certs: "/etc/falco/certs/ca.crt"
|
||||
#
|
||||
# gRPC server using a local unix socket (see default below)
|
||||
grpc:
|
||||
# -- Enable the gRPC server.
|
||||
enabled: false
|
||||
# -- Address to bind and expose the gRPC server. Use either a local unix socket with
|
||||
# no authentication, or a network address with mTLS.
|
||||
bind_address: "unix:///run/falco/falco.sock"
|
||||
# -- When the `threadiness` value is set to 0, Falco will automatically determine
|
||||
# the appropriate number of threads based on the number of online cores in the system.
|
||||
threadiness: 0
|
||||
|
||||
# [Stable] `webserver`
|
||||
#
|
||||
# -- Falco supports an embedded webserver that runs within the Falco process,
|
||||
|
||||
186
proposals/20251205-multi-thread-falco-design.md
Normal file
186
proposals/20251205-multi-thread-falco-design.md
Normal file
@@ -0,0 +1,186 @@
|
||||
# Multi-Threaded Falco High-Level Design (Working draft)
|
||||
|
||||
## Summary
|
||||
|
||||
This document outlines a high-level design for implementing multi-threading in Falco. The goal of this proposal is to overcome Falco's single-threaded architecture to improve scalability in scenarios where the amount of events produced cannot be processed in a single thread. This is achieved by leveraging multiple threads for event processing, rule evaluation, and output handling, enabling Falco to better utilize multi-core systems and reduce event drops under high event rates.
|
||||
|
||||
## Goals
|
||||
|
||||
* Address the problems related to single CPU core saturation, leading to dropped events.
|
||||
* Minimize the performance impact on the single threaded usage, that remains the default.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
* This document does not cover low-level implementation details that will be addressed in specific design documents for each component or directly in the implementation phase.
|
||||
* This document does not focus on performance optimization, the primary goal is scalability improvements to handle higher event rates that exceed single-thread processing capacity.
|
||||
|
||||
## Success Metrics
|
||||
|
||||
The success of this multi-threading initiative will be measured by the following key metrics:
|
||||
|
||||
* **Event Drop Rate Reduction**: The primary success metric is the reduction in event drops under high event rates. A successful implementation should significantly reduce or eliminate event drops that occur when a single thread cannot keep up with the event rate.
|
||||
* **Throughput Scaling**: The system should demonstrate improved throughput (events processed per second) that scales with the number of worker threads, up to a reasonable limit based on available CPU cores and workload characteristics.
|
||||
* **CPU Utilization**: Multi-threaded Falco should better utilize available CPU cores, with worker threads distributing load across multiple cores instead of saturating a single core.
|
||||
* **Single-Threaded Performance Preservation**: The single-threaded mode (default) should maintain its current performance characteristics, with minimal or no performance regression when multi-threading is disabled.
|
||||
|
||||
These metrics will be evaluated through benchmarking and real-world deployment scenarios to validate that the multi-threaded architecture achieves its scalability goals without compromising correctness or introducing significant overhead.
|
||||
|
||||
## High-Level Design
|
||||
|
||||
### Current Architecture
|
||||
|
||||

|
||||
|
||||
* The kernel driver (via kmod or eBPF) writes events into per-CPU ring buffers. Each CPU has its own buffer to avoid lock contention. We have a ring buffer per CPU core, and a single userspace.
|
||||
* Userspace (libscap) performs an `O(n_cpus)` scan on every next() call, it peeks at the head event from each ring buffer, finds the event with the minimum timestamp across all buffers and returns that event to Falco for processing. The consumer position is only advanced after the event has been consumed (on the next call), ensuring the caller can safely read the event data and avoiding the need to perform copies of the event data.
|
||||
* Libsinsp processes the events sequentially as they are received from libscap, building a stateful representation of the system and providing the necessary context for rule evaluation.
|
||||
* Falco evaluates the rules against the processed events and generates alerts based on the defined security policies.
|
||||
|
||||
### Proposed Architecture Overview
|
||||
|
||||

|
||||
|
||||
* The kernel driver (modern eBPF probe) routes events into per-partition ring buffers based on TGID. The routing logic executes in kernel space (within the eBPF program), where each event's TGID is hashed and used to select the target ring buffer. Only the modern eBPF probe is supported, as it relies on [BPF_MAP_TYPE_RINGBUF](https://docs.ebpf.io/linux/map-type/BPF_MAP_TYPE_RINGBUF/) which does not have a per-CPU design as opposed to the `BPF_MAP_TYPE_PERF_EVENT_ARRAY` used by the legacy eBPF probe.
|
||||
* Each ring buffer is associated with an event loop worker thread that processes events from its assigned ring buffer.
|
||||
* The `libsinsp` state (e.g., the thread state) is maintained in a shared data structure, allowing all workers to access data pushed by other workers. This is crucial for handling events like clone() that rely on data written by other partitions. This requires designing lightweight synchronization mechanisms to ensure efficient access to shared state without introducing significant contention. A dedicated proposal document will address the design of the shared state and synchronization mechanisms, and data consistency.
|
||||
* Falco's rule evaluation is performed in parallel by multiple worker threads, each evaluating rules against the events they process. Current Falco plugins are not supposed to be thread-safe. A dedicated proposal document will address the design of a thread-safe plugin architecture.
|
||||
* **Output handling** is already designed for multi-threaded access. The `falco_outputs` class implements a thread-safe, queue-based architecture using Intel TBB's `concurrent_bounded_queue`, which is specifically designed for multi-producer, single-consumer scenarios. Multiple worker threads can concurrently call `handle_event()` to enqueue alert messages using the thread-safe `try_push()` operation. A dedicated output worker thread consumes messages from the queue using `pop()` and sends them to all configured outputs (stdout, file, syslog, gRPC, HTTP, etc.). This design is already proven in production, as Falco's multi-source support (where different event sources run in separate threads) already uses this same queue concurrently. The existing implementation requires no changes to support multi-threaded event processing. Note that while outputs are processed in order within the queue, alerts from different worker threads may be interleaved, meaning strict temporal ordering of alerts across different processes is not guaranteed. This is acceptable for security monitoring use cases where the primary concern is detecting and reporting security events rather than maintaining precise event ordering.
|
||||
|
||||
### Work Partitioning Strategies
|
||||
|
||||
A crucial and challenging design aspect is partitioning the work to achieve a good trade-off among the following properties:
|
||||
|
||||
1. **Even load balancing** between threads
|
||||
2. **Low contention** on shared data (or no shared data)
|
||||
3. **Avoiding temporal inconsistencies and causality violations** (e.g., processing a file-opening event before the related process-forking event)
|
||||
|
||||
The first two properties are primarily focused on performance, while the third is essential for the correctness of the solution. These aspects are intrinsically linked.
|
||||
|
||||
Based on the analysis below, **Static Partitioning by TGID** is the proposed approach for the initial implementation.
|
||||
|
||||
#### Static Partitioning by TGID (Thread Group ID / Process ID)
|
||||
|
||||
Events are routed based on the TGID in kernel space (within the eBPF program) to a ring buffer dedicated to a specific partition. The routing logic executes at the point where events are captured, before they are written to any ring buffer. This partition is then consumed by a dedicated worker thread in userspace. The routing in the eBPF program can be accomplished with a simple hash and modulo operation, depending on the desired number of worker threads:
|
||||
|
||||
```
|
||||
ring_buffer_index = hash(event->tgid) % num_workers
|
||||
```
|
||||
|
||||
The hash function and number of workers are configured at eBPF program initialization time, allowing the kernel to route events directly to the appropriate ring buffer without userspace intervention.
|
||||
|
||||
**Pros:**
|
||||
|
||||
* **Reduced need for thread synchronization**: While structures keeping thread group data are shared across all worker threads and require synchronization, TGID partitioning minimizes cross-partition access. For data stored per thread-group (such as file descriptors), TGID partitioning guarantees a single writer (the worker thread assigned to that TGID), resulting in low contention since the data is mostly accessed by the same partition. Synchronization is needed only in two specific cases:
|
||||
1. **Clone/fork events**: When handling clone/fork events, the worker thread needs to access thread information from the parent thread, which may reside in a different partition. This requires synchronization to read the parent's state (e.g., file descriptors, environment variables) that will be inherited by the child.
|
||||
2. **Proc exit events**: When a process exits, reparenting logic may need to access thread information from other partitions to handle child processes that are being reparented to a different thread group.
|
||||
* Guarantee of sequential order processing of events related to the same thread group/process, as they are handled by the same worker thread. This limits the chance of temporal inconsistencies.
|
||||
|
||||
**Cons:**
|
||||
|
||||
* **Load Imbalance / "Hot" Process Vulnerability**: This static partitioning is susceptible to uneven worker load distribution, as a small number of high-activity ("hot") processes can overload the specific worker thread assigned to their TGID, creating a bottleneck.
|
||||
* **Cross-Partition Temporal Inconsistency**: Events that require information from a parent thread (e.g., fork/clone events) can still lead to causality issues. If the parent's related event is handled by a different, lagging partition, the required context might be incomplete or arrive out of order. Note that load imbalance amplifies this issue. Missing thread information is easy to detect, but there are also cases where information is present but not up-to-date or ahead of the time the clone event happened.
|
||||
|
||||
**Ancestor information during rule evaluation**: When evaluating rules that require ancestor information, the worker thread may need to access thread data from other partitions. Falco rules commonly check ancestor process attributes using fields that traverse the process hierarchy. Based on actual usage in Falco rules, commonly used ancestor fields include:
|
||||
|
||||
- `proc.aname` / `proc.aname[N]` - ancestor process name (where N is the generation level: 1=parent, 2=grandparent, 3=great-grandparent, etc., up to at least level 7)
|
||||
- `proc.aexepath[N]` - ancestor executable path (e.g., `proc.aexepath[2]` for grandparent)
|
||||
- `proc.aexe[N]` - ancestor executable (e.g., `proc.aexe[2]` for grandparent)
|
||||
|
||||
Accessing stale or "ahead" ancestor data (where the ancestor's state may be out of date or from events processed by other partitions with different timestamps) could lead to false positives or false negatives in rule evaluation. We acknowledge this potential issue and plan to assess its impact and determine appropriate mitigations once we have a running prototype.
|
||||
|
||||
**Mitigations:**
|
||||
|
||||
* **Last-Resort Fetching**: Fetching the thread information from a different channel to resolve the drift (e.g., proc scan, eBPF iterator). This solution is considered as a last resort because it risks slowing down the event processing loop, potentially negating the performance benefits of multi-threading.
|
||||
|
||||
* **Context Synchronization**: Wait for the required thread information to become available. This can be decomposed into two orthogonal concerns:
|
||||
|
||||
**How to handle the wait:**
|
||||
|
||||
* **Wait/Sleep (Blocking)**: The worker thread blocks (sleeping or spinning) until the required data becomes available. Simple to implement, but the worker is idle during the wait, reducing throughput.
|
||||
* **Deferring (Non-blocking)**: The event is copied/buffered for later processing; the worker continues with other events from its ring buffer. More complex (requires event copying, a pending queue, and a retry mechanism), but keeps the worker productive.
|
||||
|
||||
**How to detect data readiness:**
|
||||
|
||||
* **Polling**: Periodically check if the required data is available (spin-check for Wait/Sleep, or periodic retry for Deferring). Simple but wastes CPU cycles.
|
||||
* **Signaling**: Partitions proactively notify each other when data is ready. More efficient but requires coordination infrastructure (e.g., condition variables, eventfd, or message queues).
|
||||
|
||||
These combine into four possible approaches:
|
||||
|
||||
| | Polling | Signaling |
|
||||
|---|---------|-----------|
|
||||
| **Wait/Sleep** | Spin-check until ready | Sleep on condition variable, wake on signal |
|
||||
| **Deferring** | Periodically retry deferred events | Process deferred events when signaled |
|
||||
|
||||
**Synchronization point**: A natural synchronization point is the **clone exit parent event**. At this point, the parent process has completed setting up the child's initial state (inherited file descriptors, environment, etc.), making it safe to start processing events for the newly created thread group.
|
||||
|
||||
**Special case — `vfork()` / `CLONE_VFORK`**: When `vfork()` is used, the parent thread is blocked until the child calls `exec()` or exits, delaying the clone exit parent event. An alternative synchronization point may be needed (e.g., adding back clone enter parent).
|
||||
|
||||
### Other Considered Approaches
|
||||
|
||||
#### Static Partitioning by TID (Thread ID)
|
||||
|
||||
Similar to the previous approach, but events are routed by TID instead of TGID.
|
||||
|
||||
**Pros:**
|
||||
|
||||
* Guarantee of sequential order processing of events related to the same thread, as they are handled by the same worker thread. This limits the chance of temporal inconsistencies.
|
||||
* Good enough load balancing between partitions.
|
||||
|
||||
**Cons:**
|
||||
|
||||
* **Cross-Partition Temporal Inconsistency**: This approach can lead to temporal inconsistencies when accessing/writing information from/to other processes or from the Thread Group Leader (e.g., environment, file descriptor information is stored in the thread group leader).
|
||||
|
||||
#### Static Partitioning by CPU Core
|
||||
|
||||
This approach routes events based on the CPU core where the event was captured. Each CPU core has its own ring buffer (per-CPU buffers), and multiple CPU buffers are assigned to the same partition. Each partition is consumed by a dedicated worker thread that reads from all the per-CPU buffers assigned to it. The number of partitions does not necessarily match the number of CPU cores—a single partition can read from multiple per-CPU buffers, allowing flexibility in choosing the number of worker threads independently from the number of CPU cores. This leverages the existing per-CPU ring buffer infrastructure used by the kernel module (kmod) and legacy eBPF probe, where events are written to per-CPU buffers that are then grouped into partitions consumed by worker threads.
|
||||
|
||||
**Pros:**
|
||||
|
||||
* **Natural Load Distribution**: Events are naturally distributed across CPUs based on where processes execute, providing inherent load balancing that reflects actual system activity.
|
||||
* **No Routing Logic Required**: Uses the existing per-CPU ring buffer design, eliminating the need for custom routing logic in kernel or userspace. CPU cores are simply mapped to partitions (e.g., via modulo operation: `partition = cpu_id % num_workers`), and each worker thread reads from all per-CPU buffers assigned to its partition.
|
||||
* **Low Synchronization Overhead**: Events from per-CPU buffers assigned to the same partition are processed sequentially by the same worker thread, reducing cross-thread synchronization needs.
|
||||
* **Flexible Partitioning**: The number of partitions (and thus worker threads) can be chosen independently from the number of CPU cores, allowing optimization based on workload characteristics rather than hardware topology.
|
||||
|
||||
**Cons:**
|
||||
|
||||
* **Cross-CPU Temporal Inconsistency**: Events from the same process or thread group can be processed by different worker threads if the process migrates between CPUs, leading to potential temporal inconsistencies and causality violations. This is particularly problematic for multi-threaded applications that may execute on different CPUs.
|
||||
* **Process Migration Effects**: CPU migration can cause events from the same process to be processed out of order, as events captured on different CPUs are handled by different worker threads.
|
||||
* **Load Imbalance with CPU Grouping**: When multiple per-CPU buffers are assigned to the same partition, the worker thread must process events from all assigned buffers. If the activity levels across these CPUs are uneven, the worker thread may experience load imbalance, with some partitions handling more active CPUs than others. The worker thread must also coordinate reading from multiple buffers, potentially using techniques similar to the current `O(n_cpus)` scan to maintain event ordering.
|
||||
* **Modern eBPF Probe Limitation**: The modern eBPF probe uses `BPF_MAP_TYPE_RINGBUF`, which does not have a per-CPU design. This approach would only be viable with the kernel module (kmod) or legacy eBPF probe that use `BPF_MAP_TYPE_PERF_EVENT_ARRAY` with per-CPU buffers.
|
||||
|
||||
#### Functional Partitioning (Pipelining)
|
||||
|
||||
Instead of partitioning the data, this approach partitions the work by splitting processing into phases:
|
||||
|
||||
1. **Parsing**: Runs in a single thread, the state is updated in this phase.
|
||||
2. **Rules evaluation**: Runs in a thread chosen from a worker thread pool, the state is accessed but not modified.
|
||||
|
||||
**Pros:**
|
||||
|
||||
* The state handling remains single-threaded, avoiding any synchronization issue on the write side.
|
||||
* The load balancing of the Rules evaluation phase is good as it does not require any form of stickiness. Every worker can take whatever event, and a simple round-robin policy can be applied.
|
||||
|
||||
**Cons:**
|
||||
|
||||
* The "Parsing" stage is likely to become the bottleneck; a single thread here limits total throughput regardless of how many cores you have.
|
||||
* As we are parallelizing parsing and rules evaluation phases, we need an MVCC (multi-version concurrency control) technique to maintain multiple levels of state to use the state at the right point in time during rules evaluation.
|
||||
* Processing multiple events in parallel involves changes at the driver and libscap level. At the moment we are processing one event at a time from the driver memory without copying. To be able to process multiple events in parallel, we need to adapt the ring-buffer to make sure that `next()` does not consume the event. We would also need some flow control (e.g., backpressure) to avoid processing too many events in parallel. This problem would arise only if the rules evaluation phase is slower than the parsing phase.
|
||||
|
||||
#### Comparison Summary
|
||||
|
||||
| Approach | Load Balancing | Contention | Temporal Consistency |
|
||||
|----------|----------------|------------|----------------------|
|
||||
| TGID | Moderate (hot process risk) | Low | Good (within process) |
|
||||
| TID | Good | Higher | Partial (thread-level only) |
|
||||
| CPU Core | Good | Low | Poor (process migration issues) |
|
||||
| Pipelining | Good (rules evaluation phase) | Low (writes) | Requires MVCC |
|
||||
|
||||
#### Rationale for TGID Partitioning
|
||||
|
||||
TGID partitioning was chosen because it offers the best balance between synchronization complexity and correctness guarantees. TID partitioning increases cross-partition access for thread group leader data (e.g., file descriptor table, working directory, environment variables), increasing the coordination cost. Per-CPU partitioning, while leveraging existing infrastructure, suffers from process migration issues that can cause significant temporal inconsistencies when processes move between CPUs. Functional partitioning, while elegant in its separation of concerns, introduces a single-threaded bottleneck in the parsing phase that limits scalability regardless of available cores, and requires complex MVCC mechanisms for data consistency and mechanisms for handling multiple events in parallel.
|
||||
|
||||
### Risks and Mitigations
|
||||
|
||||
- **Increased Complexity**: Multi-threading introduces complexity in terms of synchronization and state management. Mitigation: Careful design of shared state and synchronization mechanisms, along with thorough testing.
|
||||
- **Synchronization Overhead vs Performance Gains**: The overhead of synchronization might negate the performance benefits of multi-threading. Mitigation: Use lightweight synchronization techniques and minimize shared state access.
|
||||
- **Synchronization Overhead vs Data Consistency**: In order to keep the synchronization overhead low with the shared state, we might need to relax some data consistency guarantees. Mitigation: Analyze the trade-offs and ensure that any relaxed guarantees do not compromise security.
|
||||
@@ -0,0 +1,128 @@
|
||||
# Legacy eBPF probe, gVisor libscap engine and gRPC output deprecations
|
||||
|
||||
## Summary
|
||||
|
||||
This proposal aims to formalize motivations and procedures for deprecating the legacy eBPF probe, the gRPC output and
|
||||
the gVisor libscap engine.
|
||||
|
||||
One of the key objectives of Falco is to maintain a seamless user experience, regardless of the system call event source
|
||||
actually used. This objective imposes strong requirements among all drivers and engines acting as system call source
|
||||
(i.e.: gVisor libscap engine), feature parity, among each other, above all. Feature parity raises challenges from both
|
||||
technical and maintainability perspectives, and these challenges are not justified if the driver/engine is no/little
|
||||
used. For these reasons, this document aims for raising consensus regarding the legacy eBPF probe and gRPC output
|
||||
deprecation.
|
||||
|
||||
Similar arguments could be raised in favor of the gRPC output deprecation: this output requires dependency on the
|
||||
gRPC framework, that introduces a non-negligible build time overhead and maintainability burden (especially in a C++
|
||||
codebase), not justified by the little usage of the output.
|
||||
|
||||
Upcoming evidences of non-negligible use of the gVisor engine and the gRPC output could be addressed by providing a
|
||||
separate source plugin in case of gVisor, and a Falco Sidekick output as a replacement of the gRPC output.
|
||||
|
||||
## Motivation
|
||||
|
||||
### Legacy eBPF probe deprecation
|
||||
|
||||
The following matrix details the current minimum kernel version officially supported by each driver, for each
|
||||
architecture:
|
||||
|
||||
| | Kernel module | legacy eBPF probe | Modern eBPF probe | Status |
|
||||
| ----------- |----------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------| ----------------- | ------ |
|
||||
| **x86_64** | >= 3.10 | >= 4.14 | >= 5.8 | _STABLE_ |
|
||||
| **aarch64** | >= [3.16](https://github.com/torvalds/linux/commit/055b1212d141f1f398fca548f8147787c0b6253f) | >= 4.17 | >= 5.8 | _STABLE_ |
|
||||
| **s390x** | >= 3.10 | >= [5.5](https://github.com/torvalds/linux/commit/6ae08ae3dea) | >= 5.8 | _EXPERIMENTAL_ |
|
||||
| **riscv64** | >= [5.0](https://github.com/torvalds/linux/commit/5aeb1b36cedd3a1dfdbfe368629fed52dee34103) | N/A | N/A | _EXPERIMENTAL_ |
|
||||
| **ppc64le** | >= 3.10 | >= [5.1](https://github.com/torvalds/linux/commit/ed1cd6deb013a11959d17a94e35ce159197632da) | >= 5.8 | _STABLE_ |
|
||||
|
||||
The legacy eBPF probe strives to provide a little more coverage than the modern eBPF one. This increased coverage comes
|
||||
at cost of flexibility and maintainability. Indeed:
|
||||
1. it cannot leverage CORE eBPF features - as a result, falcosecurity must maintain a great number of officially
|
||||
supported eBPF objects, each one built for a specific officially-supported kernel flavor; this increases the
|
||||
maintainability burden and makes the system less flexible to kernel configurations/structures changes
|
||||
2. old kernel versions support is difficult to retain - the verifier imposes huge limitations on old kernel versions,
|
||||
and any tiny change easily result in the verifier rejecting the code
|
||||
3. it is difficult to keep it up to date with other drivers - some desired features cannot be implemented in any way
|
||||
using eBPF on old kernel flavors, due to lack of eBPF helpers/program types or verifier limitations (e.g.: there is no
|
||||
way of implementing a synchronous data harvesting mechanism like the one provided by BPF iterators). As falcosecurity
|
||||
strives for feature parity among drivers, this imposes a big limitation on the other drivers. Please notice that:
|
||||
1. the kernel module is unconstrained on the nature of feature it can support
|
||||
2. the modern eBPF probe can easily rely on CORE features to probe for kernel features and use them if available
|
||||
|
||||
Besides the above, the legacy eBPF probe provides support for a range of versions that is entirely contained by the
|
||||
kernel module supported range. Additionally, different distro kernel flavors already back-port features required by the
|
||||
modern eBPF, enabling its usage on kernel older than `5.8`.
|
||||
|
||||
The above considerations, together with the evidence of its little usage, make the legacy eBPF probe a good candidate
|
||||
for deprecation.
|
||||
|
||||
### gVisor libscap engine deprecation
|
||||
|
||||
gVisor libscap engine implements a system call event source by leveraging events coming from gVisor itself through gRPC.
|
||||
|
||||
There is evidence that this engine is little used. Moreover, gVisor doesn't provide all information required to build
|
||||
all supported event types, indeed resulting in a system call source not completely equivalent to the ones provided by
|
||||
drivers. Finally, it requires `falcosecurity/libs` being dependent on protobuf, this latter introducing a non-negligible
|
||||
build time overhead and maintainability burden.
|
||||
|
||||
Deprecating it would allow to streamline system call event sources alignment, maintainability, and reduce build time for
|
||||
both `falcosecurity/falco` and `falcosecurity/libs`.
|
||||
|
||||
### gRPC output deprecation
|
||||
|
||||
The gRPC output provides a mechanism through which a gRPC client can subscribe to the Falco alerts stream. This output
|
||||
leverages a gRPC server embedded into Falco.
|
||||
|
||||
As for the legacy eBPF probe and the gVisor libscap engine, there is evidence that this output is little used. Also,
|
||||
similarly to the gVisor libscap engine, this requires Falco being dependent on the protobuf, and additionally, on the
|
||||
entire C++ gRPC framework. Finally, the little amount of data that is sent through the gRPC stream, and the
|
||||
communication model (only involving a one-way communication from the server to the client) doesn't justify the need of
|
||||
using gRPC.
|
||||
|
||||
Deprecating it would allow to reduce the build system, streamline maintainability, and reduce build time for
|
||||
`falcosecurity/falco`.
|
||||
|
||||
## Goals
|
||||
|
||||
* Deprecate the legacy eBPF probe, the gVisor libscap engine, and the gRPC output
|
||||
* Detail a plan to follow during the deprecation period, before completely remove any of the aforementioned components
|
||||
|
||||
## Non-goals
|
||||
|
||||
* Implement a gVisor source plugin as gVisor libscap engine alternative
|
||||
* Implement the gRPC output as Falco Sidekick output
|
||||
* Detail a plan to follow after taking the decision to completely remove any of the aforementioned components
|
||||
|
||||
## The plan
|
||||
|
||||
This section aims to detail the plan to follow contextually and after the deprecation mark, but before taking any
|
||||
definitive removal decision about the legacy eBPF probe, the gVisor libscap engine, and the gRPC output (collectively
|
||||
referred to hereinafter as "the components" or simply "components").
|
||||
|
||||
The deprecation of these components introduces user-facing changes that must be addressed as prescribed by the current
|
||||
deprecation policy for "non-backward compatible user-facing changes" (see
|
||||
[20231220-features-adoption-and-deprecation.md#deprecation-policy](./20231220-features-adoption-and-deprecation.md#deprecation-policy)).
|
||||
|
||||
All components are stable, and considering that deprecations will first be enforced in the stable Falco version `0.43.0`
|
||||
(ante `1.0.0`), the minimum deprecation period length is 1 release: this means that components cannot be removed before
|
||||
Falco `0.44.0`.
|
||||
|
||||
At high level, the action plan is to inform users, during the deprecation period, about the deprecation: this is
|
||||
achieved by emitting a deprecation notice if the user try to leverage any of the feature exposed by any component, and
|
||||
by updating the website in any of the relevant areas.
|
||||
|
||||
During the deprecation period, but before taking decision to remove the components, projects belonging to the
|
||||
`falcosecurity` organization will be updated to not use/rely on any of these. Specifically:
|
||||
- on `falcosecurity/libs`, any CI job building and testing the legacy eBPF probe will be removed
|
||||
- on `falcosecurity/kernel-testing`, playbooks will not build and test the legacy eBPF probe anymore
|
||||
- on `falcosecurity/event-generator`, the internal gRPC alert retriever will be replaced with an HTTP alert retriever,
|
||||
leveraging the existing HTTP output.
|
||||
|
||||
## The non-plan
|
||||
|
||||
This proposal does not address any design or implementation aspect of the gVisor engine and gRPC output replacement, nor
|
||||
formalizes in any way the conditions under which a replacement should be delivered. Upcoming evidences of non-negligible
|
||||
use of the gVisor engine and the gRPC output may be addressed by providing a separate source plugin in case of gVisor,
|
||||
and a Falco Sidekick output as a replacement of the gRPC output, but these latter possibilities should be intended as
|
||||
suggestions, and will not constraint in any way any related future choice.
|
||||
|
||||
Finally, this proposal doesn't detail any aspect of the eventual removal.
|
||||
BIN
proposals/images/falco-architecture.png
Normal file
BIN
proposals/images/falco-architecture.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 132 KiB |
BIN
proposals/images/falco-multi-thread-architecture.png
Normal file
BIN
proposals/images/falco-multi-thread-architecture.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 152 KiB |
@@ -24,10 +24,6 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
"${PROJECT_SOURCE_DIR}/scripts/systemd/falco-kmod.service"
|
||||
"${PROJECT_BINARY_DIR}/scripts/systemd" COPYONLY
|
||||
)
|
||||
configure_file(
|
||||
"${PROJECT_SOURCE_DIR}/scripts/systemd/falco-bpf.service"
|
||||
"${PROJECT_BINARY_DIR}/scripts/systemd" COPYONLY
|
||||
)
|
||||
configure_file(
|
||||
"${PROJECT_SOURCE_DIR}/scripts/systemd/falco-modern-bpf.service"
|
||||
"${PROJECT_BINARY_DIR}/scripts/systemd" COPYONLY
|
||||
@@ -68,9 +64,6 @@ if(NOT WIN32
|
||||
if(BUILD_DRIVER)
|
||||
list(APPEND FALCOCTL_DRIVER_TYPES_LIST "kmod")
|
||||
endif()
|
||||
if(BUILD_BPF)
|
||||
list(APPEND FALCOCTL_DRIVER_TYPES_LIST "ebpf")
|
||||
endif()
|
||||
string(REPLACE ";" ", " FALCOCTL_DRIVER_TYPES "${FALCOCTL_DRIVER_TYPES_LIST}")
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/falcoctl/falcoctl.yaml.in
|
||||
|
||||
@@ -25,12 +25,10 @@ CHOICE=
|
||||
# Every time we call this script we want to stat from a clean state.
|
||||
echo "[POST-INSTALL] Disable all possible 'falco' services:"
|
||||
systemctl --system stop 'falco-kmod.service' || true
|
||||
systemctl --system stop 'falco-bpf.service' || true
|
||||
systemctl --system stop 'falco-modern-bpf.service' || true
|
||||
systemctl --system stop 'falco-custom.service' || true
|
||||
systemctl --system stop 'falcoctl-artifact-follow.service' || true
|
||||
systemctl --system disable 'falco-kmod.service' || true
|
||||
systemctl --system disable 'falco-bpf.service' || true
|
||||
systemctl --system disable 'falco-modern-bpf.service' || true
|
||||
systemctl --system disable 'falco-custom.service' || true
|
||||
systemctl --system disable 'falcoctl-artifact-follow.service' || true
|
||||
@@ -47,11 +45,8 @@ if [ "$1" = "configure" ]; then
|
||||
kmod)
|
||||
CHOICE=3
|
||||
;;
|
||||
ebpf)
|
||||
CHOICE=4
|
||||
;;
|
||||
modern_ebpf)
|
||||
CHOICE=5
|
||||
CHOICE=4
|
||||
;;
|
||||
esac
|
||||
if [ -z $CHOICE ] && [ -x /usr/bin/dialog ] && [ "${FALCO_FRONTEND}" != "noninteractive" ]; then
|
||||
@@ -60,8 +55,7 @@ if [ "$1" = "configure" ]; then
|
||||
1 "Manual configuration (no unit is started)" \
|
||||
2 "Automatic selection" \
|
||||
3 "Kmod" \
|
||||
4 "eBPF" \
|
||||
5 "Modern eBPF" \
|
||||
4 "Modern eBPF" \
|
||||
2>&1 >/dev/tty)
|
||||
fi
|
||||
# "auto" case is not managed here since it is already the default, so no CHOICE=2
|
||||
@@ -73,9 +67,6 @@ if [ "$1" = "configure" ]; then
|
||||
chosen_driver="kmod"
|
||||
;;
|
||||
4)
|
||||
chosen_driver="ebpf"
|
||||
;;
|
||||
5)
|
||||
chosen_driver="modern_ebpf"
|
||||
;;
|
||||
esac
|
||||
@@ -83,7 +74,7 @@ if [ "$1" = "configure" ]; then
|
||||
echo "[POST-INSTALL] Configure falcoctl '$chosen_driver' driver type:"
|
||||
if [ "$chosen_driver" = "auto" ]; then
|
||||
# Configure falcoctl to enable all drivers
|
||||
falcoctl driver config --type "modern_ebpf" --type "kmod" --type "ebpf"
|
||||
falcoctl driver config --type "modern_ebpf" --type "kmod"
|
||||
# Load the actually automatic chosen driver
|
||||
chosen_driver=$(falcoctl driver printenv | grep DRIVER= | cut -d'"' -f2)
|
||||
else
|
||||
@@ -124,11 +115,6 @@ case "$chosen_driver" in
|
||||
falcoctl driver install --download=false
|
||||
chosen_unit="kmod"
|
||||
;;
|
||||
"ebpf")
|
||||
echo "[POST-INSTALL] Call 'falcoctl driver install for ebpf':"
|
||||
falcoctl driver install
|
||||
chosen_unit="bpf"
|
||||
;;
|
||||
"modern_ebpf")
|
||||
chosen_unit="modern-bpf"
|
||||
;;
|
||||
|
||||
@@ -25,7 +25,6 @@ set -e
|
||||
if [ -d /run/systemd/system ] && [ "$1" = remove ]; then
|
||||
echo "[POST-REMOVE] Disable all Falco services:"
|
||||
systemctl --system disable 'falco-kmod.service' || true
|
||||
systemctl --system disable 'falco-bpf.service' || true
|
||||
systemctl --system disable 'falco-modern-bpf.service' || true
|
||||
systemctl --system disable 'falco-custom.service' || true
|
||||
systemctl --system disable 'falcoctl-artifact-follow.service' || true
|
||||
|
||||
@@ -26,7 +26,6 @@ case "$1" in
|
||||
remove|upgrade|deconfigure)
|
||||
echo "[PRE-REMOVE] Stop all Falco services:"
|
||||
systemctl --system stop 'falco-kmod.service' || true
|
||||
systemctl --system stop 'falco-bpf.service' || true
|
||||
systemctl --system stop 'falco-modern-bpf.service' || true
|
||||
systemctl --system stop 'falco-custom.service' || true
|
||||
systemctl --system stop 'falcoctl-artifact-follow.service' || true
|
||||
|
||||
@@ -7,10 +7,10 @@ driver:
|
||||
hostroot: "/"
|
||||
artifact:
|
||||
follow:
|
||||
every: 6h0m0s
|
||||
every: 168h0m0s
|
||||
falcoVersions: http://localhost:8765/versions
|
||||
refs:
|
||||
- falco-rules:4
|
||||
- falco-rules:5
|
||||
indexes:
|
||||
- name: falcosecurity
|
||||
url: https://falcosecurity.github.io/falcoctl/index.yaml
|
||||
|
||||
@@ -14,6 +14,16 @@ check_program() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Sign RPM packages with embedded GPG signature using rpmsign
|
||||
#
|
||||
# $@: paths of RPM files to sign.
|
||||
rpmsign_packages() {
|
||||
echo "Signing RPM packages with rpmsign..."
|
||||
rpmsign --define '_gpg_name Falcosecurity Package Signing' --resign "$@"
|
||||
echo "Verifying RPM signatures..."
|
||||
rpm -qp --qf '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}: %|DSAHEADER?{%{DSAHEADER:pgpsig}}:{%|RSAHEADER?{%{RSAHEADER:pgpsig}}:{(none)}|}|\n' "$@"
|
||||
}
|
||||
|
||||
# Updates the signature of a RPM package in the local repository
|
||||
#
|
||||
# $1: path of the repository.
|
||||
@@ -127,6 +137,8 @@ fi
|
||||
check_program createrepo
|
||||
check_program gpg
|
||||
check_program aws
|
||||
check_program rpmsign
|
||||
check_program rpm
|
||||
|
||||
# settings
|
||||
s3_bucket_repo="s3://falco-distribution/packages/${repo}"
|
||||
@@ -140,19 +152,32 @@ aws s3 cp ${s3_bucket_repo} ${tmp_repo_path} --recursive
|
||||
|
||||
# update signatures for all existing packages
|
||||
if [ "${sign_all}" ]; then
|
||||
# collect all RPM files
|
||||
rpm_files=()
|
||||
for file in ${tmp_repo_path}/*; do
|
||||
if [ -f "$file" ]; then # exclude directories, symlinks, etc...
|
||||
if [[ ! $file == *.asc ]]; then # exclude signature files
|
||||
package=$(basename -- ${file})
|
||||
echo "Signing ${package}..."
|
||||
sign_rpm ${tmp_repo_path} ${file}
|
||||
|
||||
echo "Syncing ${package}.asc to ${s3_bucket_repo}..."
|
||||
aws s3 cp ${tmp_repo_path}/${package}.asc ${s3_bucket_repo}/${package}.asc --acl public-read
|
||||
fi
|
||||
if [ -f "$file" ] && [[ $file == *.rpm ]]; then
|
||||
rpm_files+=("$file")
|
||||
fi
|
||||
done
|
||||
|
||||
# sign all RPM packages with embedded GPG signature
|
||||
if [ ${#rpm_files[@]} -gt 0 ]; then
|
||||
rpmsign_packages "${rpm_files[@]}"
|
||||
fi
|
||||
|
||||
# create detached signatures and upload
|
||||
for file in "${rpm_files[@]}"; do
|
||||
package=$(basename -- ${file})
|
||||
echo "Creating detached signature for ${package}..."
|
||||
sign_rpm ${tmp_repo_path} ${file}
|
||||
|
||||
echo "Syncing ${package} and ${package}.asc to ${s3_bucket_repo}..."
|
||||
aws s3 cp ${tmp_repo_path}/${package} ${s3_bucket_repo}/${package} --acl public-read
|
||||
aws s3 cp ${tmp_repo_path}/${package}.asc ${s3_bucket_repo}/${package}.asc --acl public-read
|
||||
done
|
||||
aws cloudfront create-invalidation --distribution-id ${AWS_CLOUDFRONT_DIST_ID} --paths ${cloudfront_path}/*.rpm
|
||||
aws cloudfront create-invalidation --distribution-id ${AWS_CLOUDFRONT_DIST_ID} --paths ${cloudfront_path}/*.asc
|
||||
update_repo ${tmp_repo_path}
|
||||
sign_repo ${tmp_repo_path}
|
||||
fi
|
||||
|
||||
@@ -161,8 +186,9 @@ if [[ ${repo} == "rpm-dev" ]]; then
|
||||
reduce_dir_size ${tmp_repo_path} 10 rpm
|
||||
fi
|
||||
|
||||
# update the repo by adding new packages
|
||||
# sign and add new packages to the repo
|
||||
if ! [ ${#files[@]} -eq 0 ]; then
|
||||
rpmsign_packages "${files[@]}"
|
||||
for file in "${files[@]}"; do
|
||||
echo "Adding ${file}..."
|
||||
add_rpm ${tmp_repo_path} ${file}
|
||||
|
||||
@@ -24,12 +24,10 @@ CHOICE=
|
||||
# Every time we call this script we want to stat from a clean state.
|
||||
echo "[POST-INSTALL] Disable all possible enabled 'falco' service:"
|
||||
systemctl --system stop 'falco-kmod.service' || true
|
||||
systemctl --system stop 'falco-bpf.service' || true
|
||||
systemctl --system stop 'falco-modern-bpf.service' || true
|
||||
systemctl --system stop 'falco-custom.service' || true
|
||||
systemctl --system stop 'falcoctl-artifact-follow.service' || true
|
||||
systemctl --system disable 'falco-kmod.service' || true
|
||||
systemctl --system disable 'falco-bpf.service' || true
|
||||
systemctl --system disable 'falco-modern-bpf.service' || true
|
||||
systemctl --system disable 'falco-custom.service' || true
|
||||
systemctl --system disable 'falcoctl-artifact-follow.service' || true
|
||||
@@ -46,11 +44,8 @@ if [ $1 -ge 1 ]; then
|
||||
kmod)
|
||||
CHOICE=3
|
||||
;;
|
||||
ebpf)
|
||||
CHOICE=4
|
||||
;;
|
||||
modern_ebpf)
|
||||
CHOICE=5
|
||||
CHOICE=4
|
||||
;;
|
||||
esac
|
||||
if [ -z $CHOICE ] && [ -x /usr/bin/dialog ] && [ "${FALCO_FRONTEND}" != "noninteractive" ]; then
|
||||
@@ -59,8 +54,7 @@ if [ $1 -ge 1 ]; then
|
||||
1 "Manual configuration (no unit is started)" \
|
||||
2 "Automatic selection" \
|
||||
3 "Kmod" \
|
||||
4 "eBPF" \
|
||||
5 "Modern eBPF" \
|
||||
4 "Modern eBPF" \
|
||||
2>&1 >/dev/tty)
|
||||
fi
|
||||
# "auto" case is not managed here since it is already the default, so no CHOICE=2
|
||||
@@ -72,9 +66,6 @@ if [ $1 -ge 1 ]; then
|
||||
chosen_driver="kmod"
|
||||
;;
|
||||
4)
|
||||
chosen_driver="ebpf"
|
||||
;;
|
||||
5)
|
||||
chosen_driver="modern_ebpf"
|
||||
;;
|
||||
esac
|
||||
@@ -82,7 +73,7 @@ if [ $1 -ge 1 ]; then
|
||||
echo "[POST-INSTALL] Configure falcoctl '$chosen_driver' driver type:"
|
||||
if [ "$chosen_driver" = "auto" ]; then
|
||||
# Configure falcoctl to enable all drivers
|
||||
falcoctl driver config --type "modern_ebpf" --type "kmod" --type "ebpf"
|
||||
falcoctl driver config --type "modern_ebpf" --type "kmod"
|
||||
# Load the actually automatic chosen driver
|
||||
chosen_driver=$(falcoctl driver printenv | grep DRIVER= | cut -d'"' -f2)
|
||||
else
|
||||
@@ -123,11 +114,6 @@ case "$chosen_driver" in
|
||||
falcoctl driver install --download=false
|
||||
chosen_unit="kmod"
|
||||
;;
|
||||
"ebpf")
|
||||
echo "[POST-INSTALL] Call 'falcoctl driver install for ebpf':"
|
||||
falcoctl driver install
|
||||
chosen_unit="bpf"
|
||||
;;
|
||||
"modern_ebpf")
|
||||
chosen_unit="modern-bpf"
|
||||
;;
|
||||
|
||||
@@ -21,7 +21,6 @@ set -e
|
||||
if [ -d /run/systemd/system ] && [ $1 -eq 0 ]; then
|
||||
echo "[POST-REMOVE] Disable all Falco services:"
|
||||
systemctl --system disable 'falco-kmod.service'|| true
|
||||
systemctl --system disable 'falco-bpf.service' || true
|
||||
systemctl --system disable 'falco-modern-bpf.service' || true
|
||||
systemctl --system disable 'falco-custom.service' || true
|
||||
systemctl --system disable 'falcoctl-artifact-follow.service' || true
|
||||
|
||||
@@ -20,7 +20,6 @@ set -e
|
||||
# Currently running falco service uses the driver, so stop it before driver cleanup
|
||||
echo "[PRE-REMOVE] Stop all Falco services:"
|
||||
systemctl --system stop 'falco-kmod.service' || true
|
||||
systemctl --system stop 'falco-bpf.service' || true
|
||||
systemctl --system stop 'falco-modern-bpf.service' || true
|
||||
systemctl --system stop 'falco-custom.service' || true
|
||||
systemctl --system stop 'falcoctl-artifact-follow.service' || true
|
||||
@@ -36,7 +35,6 @@ falcoctl driver cleanup
|
||||
# if preuninstall:
|
||||
# `systemd-update-helper remove-system-units <service>`
|
||||
%systemd_preun 'falco-kmod.service'
|
||||
%systemd_preun 'falco-bpf.service'
|
||||
%systemd_preun 'falco-modern-bpf.service'
|
||||
%systemd_preun 'falco-custom.service'
|
||||
%systemd_preun 'falcoctl-artifact-follow.service'
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
[Unit]
|
||||
Description=Falco: Container Native Runtime Security with ebpf
|
||||
Documentation=https://falco.org/docs/
|
||||
Before=falcoctl-artifact-follow.service
|
||||
Wants=falcoctl-artifact-follow.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
ExecStart=/usr/bin/falco -o engine.kind=ebpf
|
||||
ExecReload=kill -1 $MAINPID
|
||||
UMask=0077
|
||||
TimeoutSec=30
|
||||
RestartSec=15s
|
||||
Restart=on-failure
|
||||
PrivateTmp=true
|
||||
NoNewPrivileges=yes
|
||||
ProtectHome=read-only
|
||||
ProtectSystem=full
|
||||
ProtectKernelTunables=true
|
||||
RestrictRealtime=true
|
||||
RestrictAddressFamilies=~AF_PACKET
|
||||
StandardOutput=null
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Alias=falco.service
|
||||
@@ -1,7 +1,7 @@
|
||||
[Unit]
|
||||
Description=Falcoctl Artifact Follow: automatic artifacts update service
|
||||
Documentation=https://falco.org/docs/
|
||||
PartOf=falco-bpf.service falco-kmod.service falco-modern-bpf.service falco-custom.service
|
||||
PartOf=falco-kmod.service falco-modern-bpf.service falco-custom.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
|
||||
Submodule submodules/falcosecurity-rules updated: db9405d6c2...e63b765e23
@@ -25,8 +25,7 @@ FetchContent_Declare(
|
||||
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
# Create a libscap_test_var.h file with some variables used by our tests for example the kmod path
|
||||
# or the bpf path.
|
||||
# Create a libscap_test_var.h file with some variables used by our tests (e.g: the kmod path).
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/falco_test_var.h.in ${CMAKE_CURRENT_BINARY_DIR}/falco_test_var.h
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@ Under `unit_tests/engine` and `unit_tests/falco` directories, we have different
|
||||
## Build and Run
|
||||
|
||||
```bash
|
||||
cmake -DMINIMAL_BUILD=On -DBUILD_BPF=Off -DBUILD_DRIVER=Off -DBUILD_FALCO_UNIT_TESTS=On ..
|
||||
cmake -DMINIMAL_BUILD=On -DBUILD_DRIVER=Off -DBUILD_FALCO_UNIT_TESTS=On ..
|
||||
make falco_unit_tests
|
||||
sudo ./unit_tests/falco_unit_tests
|
||||
```
|
||||
|
||||
@@ -1328,6 +1328,162 @@ TEST_F(test_falco_engine, empty_string_source_addl_rule) {
|
||||
EXPECT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
}
|
||||
|
||||
// Phase 1: Schema correctness — no false positives for valid rule properties
|
||||
|
||||
TEST_F(test_falco_engine, rule_with_warn_evttypes) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule description
|
||||
condition: evt.type = close
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
warn_evttypes: false
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_with_skip_if_unknown_filter) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule description
|
||||
condition: evt.type = close
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
skip-if-unknown-filter: true
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, override_replace_warn_evttypes) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule description
|
||||
condition: evt.type = close
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
warn_evttypes: true
|
||||
|
||||
- rule: test_rule
|
||||
warn_evttypes: false
|
||||
override:
|
||||
warn_evttypes: replace
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, override_replace_capture) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule description
|
||||
condition: evt.type = close
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
|
||||
- rule: test_rule
|
||||
capture: true
|
||||
override:
|
||||
capture: replace
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, override_replace_tags) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule description
|
||||
condition: evt.type = close
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
tags: [filesystem]
|
||||
|
||||
- rule: test_rule
|
||||
tags: [network]
|
||||
override:
|
||||
tags: replace
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
}
|
||||
|
||||
// Phase 2: Unknown key detection
|
||||
|
||||
TEST_F(test_falco_engine, rule_unknown_key) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule description
|
||||
condition: evt.type = close
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
typo_field: some_value
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
|
||||
ASSERT_TRUE(check_warning_message("Unknown key 'typo_field'"));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, list_unknown_key) {
|
||||
std::string rules_content = R"END(
|
||||
- list: my_list
|
||||
items: [cat, bash]
|
||||
typo_field: some_value
|
||||
|
||||
- rule: test_rule
|
||||
desc: test rule description
|
||||
condition: evt.type = close and proc.name in (my_list)
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
|
||||
ASSERT_TRUE(check_warning_message("Unknown key 'typo_field'"));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, macro_unknown_key) {
|
||||
std::string rules_content = R"END(
|
||||
- macro: my_macro
|
||||
condition: evt.type = close
|
||||
typo_field: some_value
|
||||
|
||||
- rule: test_rule
|
||||
desc: test rule description
|
||||
condition: my_macro
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
|
||||
ASSERT_TRUE(check_warning_message("Unknown key 'typo_field'"));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, list_cross_type_key_priority) {
|
||||
std::string rules_content = R"END(
|
||||
- list: my_list
|
||||
items: [cat, bash]
|
||||
priority: INFO
|
||||
|
||||
- rule: test_rule
|
||||
desc: test rule description
|
||||
condition: evt.type = close and proc.name in (my_list)
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
|
||||
// The flat-union schema accepts 'priority' on a list (validation_ok),
|
||||
// but procedural detection catches the cross-type misuse.
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_TRUE(check_warning_message("Unknown key 'priority'"));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, deprecated_field_in_output) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule_with_evt_dir_in_output
|
||||
|
||||
@@ -31,19 +31,11 @@ TEST(ActionLoadConfig, check_kmod_engine_config) {
|
||||
EXPECT_EQ(s.config->m_kmod.m_buf_size_preset, 2);
|
||||
EXPECT_FALSE(s.config->m_kmod.m_drop_failed_exit);
|
||||
|
||||
// Check that all other engine params are empty
|
||||
EXPECT_TRUE(s.config->m_ebpf.m_probe_path.empty());
|
||||
EXPECT_EQ(s.config->m_ebpf.m_buf_size_preset, 0);
|
||||
EXPECT_FALSE(s.config->m_ebpf.m_drop_failed_exit);
|
||||
|
||||
EXPECT_EQ(s.config->m_modern_ebpf.m_cpus_for_each_buffer, 0);
|
||||
EXPECT_EQ(s.config->m_modern_ebpf.m_buf_size_preset, 0);
|
||||
EXPECT_FALSE(s.config->m_modern_ebpf.m_drop_failed_exit);
|
||||
|
||||
EXPECT_TRUE(s.config->m_replay.m_capture_file.empty());
|
||||
|
||||
EXPECT_TRUE(s.config->m_gvisor.m_config.empty());
|
||||
EXPECT_TRUE(s.config->m_gvisor.m_root.empty());
|
||||
}
|
||||
|
||||
TEST(ActionLoadConfig, check_modern_engine_config) {
|
||||
@@ -63,14 +55,7 @@ TEST(ActionLoadConfig, check_modern_engine_config) {
|
||||
EXPECT_EQ(s.config->m_kmod.m_buf_size_preset, 0);
|
||||
EXPECT_FALSE(s.config->m_kmod.m_drop_failed_exit);
|
||||
|
||||
EXPECT_TRUE(s.config->m_ebpf.m_probe_path.empty());
|
||||
EXPECT_EQ(s.config->m_ebpf.m_buf_size_preset, 0);
|
||||
EXPECT_FALSE(s.config->m_ebpf.m_drop_failed_exit);
|
||||
|
||||
EXPECT_TRUE(s.config->m_replay.m_capture_file.empty());
|
||||
|
||||
EXPECT_TRUE(s.config->m_gvisor.m_config.empty());
|
||||
EXPECT_TRUE(s.config->m_gvisor.m_root.empty());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -25,16 +25,9 @@ engine:
|
||||
kmod:
|
||||
buf_size_preset: 2
|
||||
drop_failed_exit: false
|
||||
ebpf:
|
||||
probe: /path/to/probe.o
|
||||
buf_size_preset: 7
|
||||
drop_failed_exit: true
|
||||
modern_ebpf:
|
||||
cpus_for_each_buffer: 2
|
||||
buf_size_preset: 4
|
||||
drop_failed_exit: false
|
||||
replay:
|
||||
capture_file: /path/to/file.scap
|
||||
gvisor:
|
||||
config: /path/to/gvisor_config.yaml
|
||||
root: ""
|
||||
|
||||
@@ -25,16 +25,9 @@ engine:
|
||||
kmod:
|
||||
buf_size_preset: 1
|
||||
drop_failed_exit: true
|
||||
ebpf:
|
||||
probe: /path/to/probe.o
|
||||
buf_size_preset: 4
|
||||
drop_failed_exit: false
|
||||
modern_ebpf:
|
||||
cpus_for_each_buffer: 1
|
||||
# missing `buf_size_preset` should be defaulted
|
||||
drop_failed_exit: true
|
||||
replay:
|
||||
capture_file: /path/to/file.scap
|
||||
gvisor:
|
||||
config: /path/to/gvisor_config.yaml
|
||||
root: ""
|
||||
|
||||
@@ -21,6 +21,7 @@ add_library(
|
||||
filter_ruleset.cpp
|
||||
evttype_index_ruleset.cpp
|
||||
formats.cpp
|
||||
field_formatter.cpp
|
||||
filter_details_resolver.cpp
|
||||
filter_macro_resolver.cpp
|
||||
filter_warning_resolver.cpp
|
||||
|
||||
@@ -42,6 +42,7 @@ limitations under the License.
|
||||
#include "falco_engine_version.h"
|
||||
|
||||
#include "formats.h"
|
||||
#include "field_formatter.h"
|
||||
|
||||
#include "evttype_index_ruleset.h"
|
||||
|
||||
@@ -117,7 +118,7 @@ static std::string fieldclass_key(const sinsp_filter_factory::filter_fieldclass_
|
||||
void falco_engine::list_fields(const std::string &source,
|
||||
bool verbose,
|
||||
bool names_only,
|
||||
bool markdown) const {
|
||||
output_format format) const {
|
||||
// Maps from field class name + short desc to list of event
|
||||
// sources for which this field class can be used.
|
||||
std::map<std::string, std::set<std::string>> fieldclass_event_sources;
|
||||
@@ -138,6 +139,10 @@ void falco_engine::list_fields(const std::string &source,
|
||||
// printing field classes multiple times for different sources
|
||||
std::set<std::string> seen_fieldclasses;
|
||||
|
||||
// Create the appropriate formatter and use it
|
||||
auto formatter = FieldFormatter::create(format, verbose);
|
||||
formatter->begin();
|
||||
|
||||
// In the second pass, actually print info, skipping duplicate
|
||||
// field classes and also printing info on supported sources.
|
||||
for(const auto &it : m_sources) {
|
||||
@@ -160,21 +165,15 @@ void falco_engine::list_fields(const std::string &source,
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("%s\n", field.name.c_str());
|
||||
formatter->print_field_name(field.name);
|
||||
}
|
||||
} else if(markdown) {
|
||||
printf("%s\n",
|
||||
fld_class.as_markdown(fieldclass_event_sources[fieldclass_key(fld_class)])
|
||||
.c_str());
|
||||
} else {
|
||||
printf("%s\n",
|
||||
fld_class
|
||||
.as_string(verbose,
|
||||
fieldclass_event_sources[fieldclass_key(fld_class)])
|
||||
.c_str());
|
||||
formatter->print_fieldclass(fld_class, fieldclass_event_sources[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
formatter->end();
|
||||
}
|
||||
|
||||
std::unique_ptr<load_result> falco_engine::load_rules(const std::string &rules_content,
|
||||
|
||||
@@ -34,6 +34,7 @@ limitations under the License.
|
||||
#include "falco_source.h"
|
||||
#include "falco_load_result.h"
|
||||
#include "filter_details_resolver.h"
|
||||
#include "output_format.h"
|
||||
|
||||
//
|
||||
// This class acts as the primary interface between a program and the
|
||||
@@ -62,7 +63,10 @@ public:
|
||||
|
||||
// Print to stdout (using printf) a description of each field supported by this engine.
|
||||
// If source is non-empty, only fields for the provided source are printed.
|
||||
void list_fields(const std::string &source, bool verbose, bool names_only, bool markdown) const;
|
||||
void list_fields(const std::string &source,
|
||||
bool verbose,
|
||||
bool names_only,
|
||||
output_format format) const;
|
||||
|
||||
// Provide an alternate rule reader, collector, and compiler
|
||||
// to compile any rules provided via load_rules*
|
||||
@@ -201,11 +205,10 @@ public:
|
||||
const std::set<std::string> &tags,
|
||||
const std::string &rule);
|
||||
|
||||
// You can optionally add fields that will only show up in the object
|
||||
// output (e.g. json, gRPC) alongside other output_fields
|
||||
// and not in the text message output.
|
||||
// You can add two types of fields: formatted which will act like
|
||||
// an additional output format that appears in the output field
|
||||
// You can optionally add fields that will only show up in the object output (e.g. json)
|
||||
// alongside other output_fields and not in the text message output. You can add two types of
|
||||
// fields: formatted which will act like an additional output format that appears in the output
|
||||
// field
|
||||
void add_extra_output_formatted_field(const std::string &key,
|
||||
const std::string &format,
|
||||
const std::string &source,
|
||||
|
||||
@@ -20,7 +20,7 @@ limitations under the License.
|
||||
|
||||
// The version of this Falco engine
|
||||
#define FALCO_ENGINE_VERSION_MAJOR 0
|
||||
#define FALCO_ENGINE_VERSION_MINOR 57
|
||||
#define FALCO_ENGINE_VERSION_MINOR 60
|
||||
#define FALCO_ENGINE_VERSION_PATCH 0
|
||||
|
||||
#define FALCO_ENGINE_VERSION \
|
||||
@@ -36,4 +36,4 @@ limitations under the License.
|
||||
// It represents the fields supported by this version of Falco,
|
||||
// the event types, and the underlying driverevent schema. It's used to
|
||||
// detetect changes in engine version in our CI jobs.
|
||||
#define FALCO_ENGINE_CHECKSUM "a9787fa5f87bfec984774540fa9c0282c06ea04696625c3a90898bb108c5cb16"
|
||||
#define FALCO_ENGINE_CHECKSUM "17c1ac99576c032a58895a10f7091cf777008a1059b7f1bff3c78a6451b17fdf"
|
||||
|
||||
@@ -73,12 +73,12 @@ static const std::string warning_codes[] = {"LOAD_UNKNOWN_SOURCE",
|
||||
"LOAD_EXCEPTION_NAME_NOT_UNIQUE",
|
||||
"LOAD_INVALID_MACRO_NAME",
|
||||
"LOAD_INVALID_LIST_NAME",
|
||||
"LOAD_COMPILE_CONDITION"};
|
||||
"LOAD_COMPILE_CONDITION",
|
||||
"LOAD_UNKNOWN_KEY"};
|
||||
|
||||
// Compile-time check to ensure warning_codes array has the correct size
|
||||
static_assert(std::size(warning_codes) ==
|
||||
static_cast<int>(falco::load_result::warning_code::LOAD_COMPILE_CONDITION) +
|
||||
1,
|
||||
static_cast<int>(falco::load_result::warning_code::LOAD_UNKNOWN_KEY) + 1,
|
||||
"warning_codes array size must match the last warning_code enum value + 1");
|
||||
|
||||
const std::string& falco::load_result::warning_code_str(warning_code wc) {
|
||||
@@ -98,12 +98,12 @@ static const std::string warning_strings[] = {"Unknown event source",
|
||||
"Multiple exceptions defined with the same name",
|
||||
"Invalid macro name",
|
||||
"Invalid list name",
|
||||
"Warning in rule condition"};
|
||||
"Warning in rule condition",
|
||||
"Unknown key in item definition"};
|
||||
|
||||
// Compile-time check to ensure warning_strings array has the correct size
|
||||
static_assert(std::size(warning_strings) ==
|
||||
static_cast<int>(falco::load_result::warning_code::LOAD_COMPILE_CONDITION) +
|
||||
1,
|
||||
static_cast<int>(falco::load_result::warning_code::LOAD_UNKNOWN_KEY) + 1,
|
||||
"warning_strings array size must match the last warning_code enum value + 1");
|
||||
|
||||
const std::string& falco::load_result::warning_str(warning_code wc) {
|
||||
@@ -131,19 +131,25 @@ static const std::string warning_descs[] = {
|
||||
"A rule is defining multiple exceptions with the same name",
|
||||
"A macro is defined with an invalid name",
|
||||
"A list is defined with an invalid name",
|
||||
"A rule condition or output have been parsed with a warning"};
|
||||
"A rule condition or output have been parsed with a warning",
|
||||
"An item in the rules content contains an unrecognized key. The key will be ignored. "
|
||||
"This may indicate a typo or a property placed on the wrong item type."};
|
||||
|
||||
// Compile-time check to ensure warning_descs array has the correct size
|
||||
static_assert(std::size(warning_descs) ==
|
||||
static_cast<int>(falco::load_result::warning_code::LOAD_COMPILE_CONDITION) +
|
||||
1,
|
||||
static_cast<int>(falco::load_result::warning_code::LOAD_UNKNOWN_KEY) + 1,
|
||||
"warning_descs array size must match the last warning_code enum value + 1");
|
||||
|
||||
const std::string& falco::load_result::warning_desc(warning_code wc) {
|
||||
return warning_descs[static_cast<int>(wc)];
|
||||
}
|
||||
|
||||
static const std::string deprecated_fields[] = {"evt.dir"};
|
||||
static const std::string deprecated_fields[] = {"evt.dir",
|
||||
"evt.latency",
|
||||
"evt.latency.s",
|
||||
"evt.latency.ns",
|
||||
"evt.latency.human",
|
||||
"evt.wait_latency"};
|
||||
|
||||
// Compile-time check to ensure deprecated_fields array has the correct size
|
||||
static_assert(
|
||||
@@ -155,10 +161,19 @@ const std::string& falco::load_result::deprecated_field_str(deprecated_field df)
|
||||
return deprecated_fields[static_cast<int>(df)];
|
||||
}
|
||||
|
||||
// Shared description suffix for latency fields
|
||||
static const std::string latency_field_desc_suffix =
|
||||
"field is not available due to the drop of enter events.";
|
||||
|
||||
static const std::string deprecated_field_descs[] = {
|
||||
"due to the drop of enter events, 'evt.dir = <' always evaluates to true, and 'evt.dir = "
|
||||
">' always evaluates to false. The rule expression can be simplified by removing the "
|
||||
"condition on 'evt.dir'"};
|
||||
"condition on 'evt.dir'",
|
||||
latency_field_desc_suffix,
|
||||
latency_field_desc_suffix,
|
||||
latency_field_desc_suffix,
|
||||
latency_field_desc_suffix,
|
||||
latency_field_desc_suffix};
|
||||
|
||||
// Compile-time check to ensure deprecated_field_descs array has the correct size
|
||||
static_assert(
|
||||
|
||||
@@ -62,7 +62,8 @@ public:
|
||||
LOAD_EXCEPTION_NAME_NOT_UNIQUE,
|
||||
LOAD_INVALID_MACRO_NAME,
|
||||
LOAD_INVALID_LIST_NAME,
|
||||
LOAD_COMPILE_CONDITION
|
||||
LOAD_COMPILE_CONDITION,
|
||||
LOAD_UNKNOWN_KEY
|
||||
};
|
||||
|
||||
// The warning code as a string
|
||||
@@ -75,7 +76,15 @@ public:
|
||||
// impact.
|
||||
static const std::string& warning_desc(warning_code ec);
|
||||
|
||||
enum class deprecated_field { DEPRECATED_FIELD_EVT_DIR, DEPRECATED_FIELD_NOT_FOUND };
|
||||
enum class deprecated_field {
|
||||
DEPRECATED_FIELD_EVT_DIR,
|
||||
DEPRECATED_FIELD_EVT_LATENCY,
|
||||
DEPRECATED_FIELD_EVT_LATENCY_S,
|
||||
DEPRECATED_FIELD_EVT_LATENCY_NS,
|
||||
DEPRECATED_FIELD_EVT_LATENCY_HUMAN,
|
||||
DEPRECATED_FIELD_EVT_WAIT_LATENCY,
|
||||
DEPRECATED_FIELD_NOT_FOUND
|
||||
};
|
||||
|
||||
// The deprecated field as a string
|
||||
static const std::string& deprecated_field_str(deprecated_field df);
|
||||
|
||||
122
userspace/engine/field_formatter.cpp
Normal file
122
userspace/engine/field_formatter.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2026 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 "field_formatter.h"
|
||||
#include "formats.h"
|
||||
|
||||
using namespace falco;
|
||||
|
||||
// Factory method
|
||||
std::unique_ptr<FieldFormatter> FieldFormatter::create(output_format format, bool verbose) {
|
||||
switch(format) {
|
||||
case output_format::JSON:
|
||||
return std::make_unique<JsonFieldFormatter>(verbose);
|
||||
case output_format::MARKDOWN:
|
||||
return std::make_unique<MarkdownFieldFormatter>(verbose);
|
||||
case output_format::TEXT:
|
||||
default:
|
||||
return std::make_unique<TextFieldFormatter>(verbose);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// TextFieldFormatter implementation
|
||||
// ============================================================================
|
||||
|
||||
TextFieldFormatter::TextFieldFormatter(bool verbose): m_verbose(verbose) {}
|
||||
|
||||
void TextFieldFormatter::begin() {
|
||||
// Nothing to do for text format
|
||||
}
|
||||
|
||||
void TextFieldFormatter::print_fieldclass(
|
||||
const sinsp_filter_factory::filter_fieldclass_info& fld_class,
|
||||
const std::set<std::string>& event_sources) {
|
||||
printf("%s\n", fld_class.as_string(m_verbose, event_sources).c_str());
|
||||
}
|
||||
|
||||
void TextFieldFormatter::print_field_name(const std::string& name) {
|
||||
printf("%s\n", name.c_str());
|
||||
}
|
||||
|
||||
void TextFieldFormatter::end() {
|
||||
// Nothing to do for text format
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// MarkdownFieldFormatter implementation
|
||||
// ============================================================================
|
||||
|
||||
MarkdownFieldFormatter::MarkdownFieldFormatter(bool verbose): m_verbose(verbose) {}
|
||||
|
||||
void MarkdownFieldFormatter::begin() {
|
||||
// Nothing to do for markdown format
|
||||
}
|
||||
|
||||
void MarkdownFieldFormatter::print_fieldclass(
|
||||
const sinsp_filter_factory::filter_fieldclass_info& fld_class,
|
||||
const std::set<std::string>& event_sources) {
|
||||
printf("%s\n", fld_class.as_markdown(event_sources).c_str());
|
||||
}
|
||||
|
||||
void MarkdownFieldFormatter::print_field_name(const std::string& name) {
|
||||
printf("%s\n", name.c_str());
|
||||
}
|
||||
|
||||
void MarkdownFieldFormatter::end() {
|
||||
// Nothing to do for markdown format
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// JsonFieldFormatter implementation
|
||||
// ============================================================================
|
||||
|
||||
JsonFieldFormatter::JsonFieldFormatter(bool verbose): m_verbose(verbose) {}
|
||||
|
||||
void JsonFieldFormatter::begin() {
|
||||
m_fieldclasses_array = nlohmann::json::array();
|
||||
m_fieldnames_array = nlohmann::json::array();
|
||||
m_has_fieldclasses = false;
|
||||
m_has_fieldnames = false;
|
||||
}
|
||||
|
||||
void JsonFieldFormatter::print_fieldclass(
|
||||
const sinsp_filter_factory::filter_fieldclass_info& fld_class,
|
||||
const std::set<std::string>& event_sources) {
|
||||
std::string json_str = fld_class.as_json(event_sources);
|
||||
if(!json_str.empty()) {
|
||||
m_fieldclasses_array.push_back(nlohmann::json::parse(json_str));
|
||||
m_has_fieldclasses = true;
|
||||
}
|
||||
}
|
||||
|
||||
void JsonFieldFormatter::print_field_name(const std::string& name) {
|
||||
m_fieldnames_array.push_back(name);
|
||||
m_has_fieldnames = true;
|
||||
}
|
||||
|
||||
void JsonFieldFormatter::end() {
|
||||
nlohmann::json root;
|
||||
|
||||
if(m_has_fieldclasses) {
|
||||
root["fieldclasses"] = m_fieldclasses_array;
|
||||
printf("%s\n", root.dump(2).c_str());
|
||||
} else if(m_has_fieldnames) {
|
||||
root["fieldnames"] = m_fieldnames_array;
|
||||
printf("%s\n", root.dump(2).c_str());
|
||||
}
|
||||
}
|
||||
102
userspace/engine/field_formatter.h
Normal file
102
userspace/engine/field_formatter.h
Normal file
@@ -0,0 +1,102 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2026 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <libsinsp/sinsp.h>
|
||||
|
||||
enum class output_format;
|
||||
|
||||
namespace falco {
|
||||
|
||||
// Abstract formatter interface for field listing
|
||||
class FieldFormatter {
|
||||
public:
|
||||
virtual ~FieldFormatter() = default;
|
||||
|
||||
// Initialize formatter
|
||||
virtual void begin() = 0;
|
||||
|
||||
// Print a field class with its event sources
|
||||
virtual void print_fieldclass(const sinsp_filter_factory::filter_fieldclass_info& fld_class,
|
||||
const std::set<std::string>& event_sources) = 0;
|
||||
|
||||
// Print a single field name (for names_only mode)
|
||||
virtual void print_field_name(const std::string& name) = 0;
|
||||
|
||||
// Finalize and output
|
||||
virtual void end() = 0;
|
||||
|
||||
// Factory method
|
||||
static std::unique_ptr<FieldFormatter> create(output_format format, bool verbose);
|
||||
};
|
||||
|
||||
// Text formatter (default)
|
||||
class TextFieldFormatter : public FieldFormatter {
|
||||
public:
|
||||
explicit TextFieldFormatter(bool verbose);
|
||||
|
||||
void begin() override;
|
||||
void print_fieldclass(const sinsp_filter_factory::filter_fieldclass_info& fld_class,
|
||||
const std::set<std::string>& event_sources) override;
|
||||
void print_field_name(const std::string& name) override;
|
||||
void end() override;
|
||||
|
||||
private:
|
||||
bool m_verbose;
|
||||
};
|
||||
|
||||
// Markdown formatter
|
||||
class MarkdownFieldFormatter : public FieldFormatter {
|
||||
public:
|
||||
explicit MarkdownFieldFormatter(bool verbose);
|
||||
|
||||
void begin() override;
|
||||
void print_fieldclass(const sinsp_filter_factory::filter_fieldclass_info& fld_class,
|
||||
const std::set<std::string>& event_sources) override;
|
||||
void print_field_name(const std::string& name) override;
|
||||
void end() override;
|
||||
|
||||
private:
|
||||
bool m_verbose;
|
||||
};
|
||||
|
||||
// JSON formatter
|
||||
class JsonFieldFormatter : public FieldFormatter {
|
||||
public:
|
||||
explicit JsonFieldFormatter(bool verbose);
|
||||
|
||||
void begin() override;
|
||||
void print_fieldclass(const sinsp_filter_factory::filter_fieldclass_info& fld_class,
|
||||
const std::set<std::string>& event_sources) override;
|
||||
void print_field_name(const std::string& name) override;
|
||||
void end() override;
|
||||
|
||||
private:
|
||||
bool m_verbose;
|
||||
nlohmann::json m_fieldclasses_array;
|
||||
nlohmann::json m_fieldnames_array;
|
||||
bool m_has_fieldclasses{false};
|
||||
bool m_has_fieldnames{false};
|
||||
};
|
||||
|
||||
} // namespace falco
|
||||
@@ -125,5 +125,13 @@ void filter_details_resolver::visitor::visit(ast::field_expr* e) {
|
||||
|
||||
void filter_details_resolver::visitor::visit(ast::field_transformer_expr* e) {
|
||||
m_details.transformers.insert(e->transformer);
|
||||
e->value->accept(this);
|
||||
for(auto& value : e->values) {
|
||||
value->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
void filter_details_resolver::visitor::visit(ast::transformer_list_expr* e) {
|
||||
for(auto& child : e->children) {
|
||||
child->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ private:
|
||||
void visit(libsinsp::filter::ast::binary_check_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::field_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::field_transformer_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::transformer_list_expr* e) override;
|
||||
|
||||
filter_details& m_details;
|
||||
bool m_expect_list;
|
||||
|
||||
@@ -105,6 +105,10 @@ void filter_macro_resolver::visitor::visit(ast::field_transformer_expr* e) {
|
||||
m_node_substitute = nullptr;
|
||||
}
|
||||
|
||||
void filter_macro_resolver::visitor::visit(ast::transformer_list_expr* e) {
|
||||
m_node_substitute = nullptr;
|
||||
}
|
||||
|
||||
void filter_macro_resolver::visitor::visit(ast::identifier_expr* e) {
|
||||
const auto& macro = m_macros.find(e->identifier);
|
||||
if(macro != m_macros.end() && macro->second) // skip null-ptr macros
|
||||
|
||||
@@ -121,6 +121,7 @@ private:
|
||||
void visit(libsinsp::filter::ast::binary_check_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::field_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::field_transformer_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::transformer_list_expr* e) override;
|
||||
};
|
||||
|
||||
std::vector<value_info> m_errors;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 The Falco Authors.
|
||||
Copyright (C) 2026 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.
|
||||
@@ -17,14 +17,4 @@ limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "outputs.h"
|
||||
|
||||
namespace falco {
|
||||
namespace outputs {
|
||||
|
||||
class output_grpc : public abstract_output {
|
||||
void output(const message *msg) override;
|
||||
};
|
||||
|
||||
} // namespace outputs
|
||||
} // namespace falco
|
||||
enum class output_format { TEXT, MARKDOWN, JSON };
|
||||
@@ -97,6 +97,12 @@ const char rule_schema_string[] = LONG_STRING_CONST(
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"warn_evttypes": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skip-if-unknown-filter": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [],
|
||||
@@ -150,7 +156,7 @@ const char rule_schema_string[] = LONG_STRING_CONST(
|
||||
"append",
|
||||
"replace"
|
||||
],
|
||||
"title": "Priority"
|
||||
"title": "OverriddenItem"
|
||||
},
|
||||
"Override": {
|
||||
"type": "object",
|
||||
@@ -176,6 +182,21 @@ const char rule_schema_string[] = LONG_STRING_CONST(
|
||||
},
|
||||
"exceptions": {
|
||||
"$ref": "#/definitions/OverriddenItem"
|
||||
},
|
||||
"capture": {
|
||||
"$ref": "#/definitions/OverriddenItem"
|
||||
},
|
||||
"capture_duration": {
|
||||
"$ref": "#/definitions/OverriddenItem"
|
||||
},
|
||||
"tags": {
|
||||
"$ref": "#/definitions/OverriddenItem"
|
||||
},
|
||||
"warn_evttypes": {
|
||||
"$ref": "#/definitions/OverriddenItem"
|
||||
},
|
||||
"skip-if-unknown-filter": {
|
||||
"$ref": "#/definitions/OverriddenItem"
|
||||
}
|
||||
},
|
||||
"minProperties": 1,
|
||||
|
||||
@@ -216,7 +216,7 @@ struct deprecated_field_warning : warning {
|
||||
|
||||
std::string as_string() const override {
|
||||
return warning::as_string() + ": field '" + falco::load_result::deprecated_field_str(df) +
|
||||
"' is deprecated";
|
||||
"'";
|
||||
};
|
||||
std::string description() const override {
|
||||
return warning::description() + ": " + falco::load_result::deprecated_field_desc(df);
|
||||
|
||||
@@ -346,7 +346,8 @@ void rule_loader::compiler::compile_macros_infos(const configuration& cfg,
|
||||
static bool err_is_unknown_type_or_field(const std::string& err) {
|
||||
return err.find("nonexistent field") != std::string::npos ||
|
||||
err.find("invalid formatting token") != std::string::npos ||
|
||||
err.find("unknown event type") != std::string::npos;
|
||||
err.find("unknown event type") != std::string::npos ||
|
||||
err.find("unknown filter:") != std::string::npos;
|
||||
}
|
||||
|
||||
bool rule_loader::compiler::compile_condition(const configuration& cfg,
|
||||
|
||||
@@ -404,6 +404,23 @@ static void read_rule_exceptions(
|
||||
exceptions = decoded;
|
||||
}
|
||||
|
||||
static void warn_unknown_keys(const YAML::Node& item,
|
||||
const std::set<std::string>& expected_keys,
|
||||
rule_loader::configuration& cfg,
|
||||
const rule_loader::context& ctx) {
|
||||
if(!item.IsMap()) {
|
||||
return;
|
||||
}
|
||||
for(auto it = item.begin(); it != item.end(); ++it) {
|
||||
std::string key = it->first.as<std::string>();
|
||||
if(expected_keys.find(key) == expected_keys.end()) {
|
||||
cfg.res->add_warning(falco::load_result::warning_code::LOAD_UNKNOWN_KEY,
|
||||
"Unknown key '" + key + "'. The key will be ignored.",
|
||||
ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline static bool check_update_expected(std::set<std::string>& expected_keys,
|
||||
const std::set<std::string>& overrides,
|
||||
const std::string& override_type,
|
||||
@@ -460,6 +477,10 @@ void rule_loader::reader::read_item(rule_loader::configuration& cfg,
|
||||
}
|
||||
|
||||
collector.define(cfg, v);
|
||||
|
||||
static const std::set<std::string> expected_required_engine_version_keys{
|
||||
"required_engine_version"};
|
||||
warn_unknown_keys(item, expected_required_engine_version_keys, cfg, ctx);
|
||||
} else if(item["required_plugin_versions"].IsDefined()) {
|
||||
const YAML::Node& req_plugin_vers = item["required_plugin_versions"];
|
||||
rule_loader::context ctx(req_plugin_vers,
|
||||
@@ -514,6 +535,14 @@ void rule_loader::reader::read_item(rule_loader::configuration& cfg,
|
||||
|
||||
collector.define(cfg, v);
|
||||
}
|
||||
|
||||
static const std::set<std::string> expected_required_plugin_versions_keys{
|
||||
"required_plugin_versions"};
|
||||
rule_loader::context rpv_ctx(item,
|
||||
rule_loader::context::REQUIRED_PLUGIN_VERSIONS,
|
||||
"",
|
||||
parent);
|
||||
warn_unknown_keys(item, expected_required_plugin_versions_keys, cfg, rpv_ctx);
|
||||
} else if(item["list"].IsDefined()) {
|
||||
std::string name;
|
||||
// Using tmp context until name is decoded
|
||||
@@ -559,6 +588,12 @@ void rule_loader::reader::read_item(rule_loader::configuration& cfg,
|
||||
} else {
|
||||
collector.define(cfg, v);
|
||||
}
|
||||
|
||||
static const std::set<std::string> expected_list_keys{"list",
|
||||
"items",
|
||||
"append",
|
||||
"override"};
|
||||
warn_unknown_keys(item, expected_list_keys, cfg, ctx);
|
||||
} else if(item["macro"].IsDefined()) {
|
||||
std::string name;
|
||||
// Using tmp context until name is decoded
|
||||
@@ -610,6 +645,12 @@ void rule_loader::reader::read_item(rule_loader::configuration& cfg,
|
||||
} else {
|
||||
collector.define(cfg, v);
|
||||
}
|
||||
|
||||
static const std::set<std::string> expected_macro_keys{"macro",
|
||||
"condition",
|
||||
"append",
|
||||
"override"};
|
||||
warn_unknown_keys(item, expected_macro_keys, cfg, ctx);
|
||||
} else if(item["rule"].IsDefined()) {
|
||||
std::string name;
|
||||
|
||||
@@ -898,6 +939,23 @@ void rule_loader::reader::read_item(rule_loader::configuration& cfg,
|
||||
collector.define(cfg, v);
|
||||
}
|
||||
}
|
||||
|
||||
static const std::set<std::string> expected_rule_keys{"rule",
|
||||
"condition",
|
||||
"output",
|
||||
"desc",
|
||||
"priority",
|
||||
"source",
|
||||
"enabled",
|
||||
"capture",
|
||||
"capture_duration",
|
||||
"warn_evttypes",
|
||||
"skip-if-unknown-filter",
|
||||
"tags",
|
||||
"exceptions",
|
||||
"override",
|
||||
"append"};
|
||||
warn_unknown_keys(item, expected_rule_keys, cfg, ctx);
|
||||
} else {
|
||||
rule_loader::context ctx(item, rule_loader::context::RULES_CONTENT_ITEM, "", parent);
|
||||
cfg.res->add_warning(falco::load_result::warning_code::LOAD_UNKNOWN_ITEM,
|
||||
|
||||
@@ -34,23 +34,22 @@ add_library(
|
||||
app/actions/load_plugins.cpp
|
||||
app/actions/load_rules_files.cpp
|
||||
app/actions/process_events.cpp
|
||||
app/actions/print_generated_gvisor_config.cpp
|
||||
app/actions/print_help.cpp
|
||||
app/actions/print_ignored_events.cpp
|
||||
app/actions/print_kernel_version.cpp
|
||||
app/actions/print_plugin_info.cpp
|
||||
app/actions/print_support.cpp
|
||||
app/actions/print_syscall_events.cpp
|
||||
app/actions/event_formatter.cpp
|
||||
app/actions/print_version.cpp
|
||||
app/actions/print_page_size.cpp
|
||||
app/actions/configure_syscall_buffer_size.cpp
|
||||
app/actions/configure_syscall_buffer_num.cpp
|
||||
app/actions/select_event_sources.cpp
|
||||
app/actions/start_grpc_server.cpp
|
||||
app/actions/start_webserver.cpp
|
||||
app/actions/validate_rules_files.cpp
|
||||
app/actions/create_requested_paths.cpp
|
||||
app/actions/close_inspectors.cpp
|
||||
app/actions/cleanup_outputs.cpp
|
||||
app/actions/print_config_schema.cpp
|
||||
app/actions/print_rule_schema.cpp
|
||||
configuration.cpp
|
||||
@@ -75,59 +74,31 @@ if(USE_JEMALLOC OR USE_MIMALLOC)
|
||||
list(APPEND FALCO_LIBRARIES ${MALLOC_LIB})
|
||||
endif()
|
||||
|
||||
if(USE_GPERFTOOLS)
|
||||
list(APPEND FALCO_DEPENDENCIES gperftools)
|
||||
list(APPEND FALCO_LIBRARIES "${GPERFTOOLS_PROFILER_LIB}")
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
target_sources(falco_application PRIVATE outputs_program.cpp outputs_syslog.cpp)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT MINIMAL_BUILD)
|
||||
target_sources(
|
||||
falco_application
|
||||
PRIVATE outputs_grpc.cpp
|
||||
outputs_http.cpp
|
||||
falco_metrics.cpp
|
||||
webserver.cpp
|
||||
grpc_context.cpp
|
||||
grpc_request_context.cpp
|
||||
grpc_server.cpp
|
||||
grpc_context.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc
|
||||
target_sources(falco_application PRIVATE outputs_http.cpp falco_metrics.cpp webserver.cpp)
|
||||
|
||||
list(APPEND FALCO_INCLUDE_DIRECTORIES FALCO_INCLUDE_DIRECTORIES "${OPENSSL_INCLUDE_DIR}"
|
||||
"${CARES_INCLUDE}"
|
||||
)
|
||||
|
||||
list(
|
||||
APPEND
|
||||
FALCO_INCLUDE_DIRECTORIES
|
||||
FALCO_INCLUDE_DIRECTORIES
|
||||
"${OPENSSL_INCLUDE_DIR}"
|
||||
"${GRPC_INCLUDE}"
|
||||
"${GRPCPP_INCLUDE}"
|
||||
"${PROTOBUF_INCLUDE}"
|
||||
"${CARES_INCLUDE}"
|
||||
)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND USE_BUNDLED_GRPC)
|
||||
list(APPEND FALCO_DEPENDENCIES grpc)
|
||||
if(TARGET c-ares)
|
||||
list(APPEND FALCO_DEPENDENCIES c-ares)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND USE_BUNDLED_CURL)
|
||||
list(APPEND FALCO_DEPENDENCIES curl)
|
||||
endif()
|
||||
|
||||
list(
|
||||
APPEND
|
||||
FALCO_LIBRARIES
|
||||
httplib::httplib
|
||||
"${CURL_LIBRARIES}"
|
||||
"${GRPCPP_LIB}"
|
||||
"${GRPC_LIB}"
|
||||
"${GPR_LIB}"
|
||||
"${GRPC_LIBRARIES}"
|
||||
"${PROTOBUF_LIB}"
|
||||
"${CARES_LIB}"
|
||||
)
|
||||
list(APPEND FALCO_LIBRARIES httplib::httplib "${CURL_LIBRARIES}" "${CARES_LIB}")
|
||||
endif()
|
||||
|
||||
if(EMSCRIPTEN)
|
||||
@@ -157,37 +128,6 @@ if(EMSCRIPTEN)
|
||||
target_link_options(falco PRIVATE "-sEXPORTED_FUNCTIONS=['_main','_htons','_ntohs']")
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT MINIMAL_BUILD)
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.h
|
||||
COMMENT "Generate gRPC API"
|
||||
# Falco gRPC Version API
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/version.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=.
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/version.proto
|
||||
COMMAND
|
||||
${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=.
|
||||
--plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN} ${CMAKE_CURRENT_SOURCE_DIR}/version.proto
|
||||
# Falco gRPC Outputs API
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=.
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto ${CMAKE_CURRENT_SOURCE_DIR}/schema.proto
|
||||
COMMAND
|
||||
${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=.
|
||||
--plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN} ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
# strip the Falco binary when releasing using musl
|
||||
if(MUSL_OPTIMIZED_BUILD AND CMAKE_BUILD_TYPE STREQUAL "release")
|
||||
add_custom_command(
|
||||
|
||||
@@ -27,7 +27,6 @@ namespace actions {
|
||||
falco::app::run_result configure_interesting_sets(falco::app::state& s);
|
||||
falco::app::run_result configure_syscall_buffer_size(falco::app::state& s);
|
||||
falco::app::run_result configure_syscall_buffer_num(const falco::app::state& s);
|
||||
falco::app::run_result create_requested_paths(falco::app::state& s);
|
||||
falco::app::run_result create_signal_handlers(falco::app::state& s);
|
||||
falco::app::run_result pidfile(const falco::app::state& s);
|
||||
falco::app::run_result init_falco_engine(falco::app::state& s);
|
||||
@@ -39,7 +38,6 @@ falco::app::run_result load_config(const falco::app::state& s);
|
||||
falco::app::run_result load_plugins(falco::app::state& s);
|
||||
falco::app::run_result load_rules_files(falco::app::state& s);
|
||||
falco::app::run_result print_config_schema(falco::app::state& s);
|
||||
falco::app::run_result print_generated_gvisor_config(falco::app::state& s);
|
||||
falco::app::run_result print_help(falco::app::state& s);
|
||||
falco::app::run_result print_ignored_events(const falco::app::state& s);
|
||||
falco::app::run_result print_kernel_version(const falco::app::state& s);
|
||||
@@ -52,13 +50,12 @@ falco::app::run_result print_version(falco::app::state& s);
|
||||
falco::app::run_result process_events(falco::app::state& s);
|
||||
falco::app::run_result require_config_file(const falco::app::state& s);
|
||||
falco::app::run_result select_event_sources(falco::app::state& s);
|
||||
falco::app::run_result start_grpc_server(falco::app::state& s);
|
||||
falco::app::run_result start_webserver(falco::app::state& s);
|
||||
falco::app::run_result stop_grpc_server(falco::app::state& s);
|
||||
falco::app::run_result stop_webserver(falco::app::state& s);
|
||||
falco::app::run_result unregister_signal_handlers(falco::app::state& s);
|
||||
falco::app::run_result validate_rules_files(falco::app::state& s);
|
||||
falco::app::run_result close_inspectors(falco::app::state& s);
|
||||
falco::app::run_result cleanup_outputs(falco::app::state& s);
|
||||
|
||||
}; // namespace actions
|
||||
}; // namespace app
|
||||
|
||||
29
userspace/falco/app/actions/cleanup_outputs.cpp
Normal file
29
userspace/falco/app/actions/cleanup_outputs.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2025 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 "actions.h"
|
||||
|
||||
using namespace falco::app;
|
||||
using namespace falco::app::actions;
|
||||
|
||||
falco::app::run_result falco::app::actions::cleanup_outputs(falco::app::state& s) {
|
||||
if(s.outputs) {
|
||||
s.outputs.reset();
|
||||
s.engine->print_stats();
|
||||
}
|
||||
return run_result::ok();
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 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 "actions.h"
|
||||
#include "falco_utils.h"
|
||||
#include <sys/stat.h>
|
||||
#include <filesystem>
|
||||
|
||||
using namespace falco::app;
|
||||
using namespace falco::app::actions;
|
||||
|
||||
static int create_dir(const std::string &path);
|
||||
|
||||
falco::app::run_result falco::app::actions::create_requested_paths(falco::app::state &s) {
|
||||
if(s.is_gvisor()) {
|
||||
// This is bad: parsing gvisor config to get endpoint
|
||||
// to be able to auto-create the path to the file for the user.
|
||||
std::ifstream reader(s.config->m_gvisor.m_config);
|
||||
if(reader.fail()) {
|
||||
return run_result::fatal(s.config->m_gvisor.m_config + ": cannot open file");
|
||||
}
|
||||
|
||||
nlohmann::json parsed_json;
|
||||
std::string gvisor_socket;
|
||||
try {
|
||||
parsed_json = nlohmann::json::parse(reader);
|
||||
} catch(const std::exception &e) {
|
||||
return run_result::fatal(s.config->m_gvisor.m_config +
|
||||
": cannot parse JSON: " + e.what());
|
||||
}
|
||||
|
||||
try {
|
||||
gvisor_socket = parsed_json["trace_session"]["sinks"][0]["config"]["endpoint"];
|
||||
} catch(const std::exception &e) {
|
||||
return run_result::fatal(s.config->m_gvisor.m_config +
|
||||
": failed to fetch config.endpoint: " + e.what());
|
||||
}
|
||||
|
||||
int ret = create_dir(gvisor_socket);
|
||||
if(ret != 0) {
|
||||
return run_result::fatal(gvisor_socket + ": " + strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
if(s.config->m_grpc_enabled && !s.config->m_grpc_bind_address.empty()) {
|
||||
if(falco::utils::network::is_unix_scheme(s.config->m_grpc_bind_address)) {
|
||||
auto server_path = s.config->m_grpc_bind_address.substr(
|
||||
falco::utils::network::UNIX_SCHEME.length());
|
||||
int ret = create_dir(server_path);
|
||||
if(ret != 0) {
|
||||
return run_result::fatal(server_path + ": " + strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: eventually other files written by Falco whose destination is
|
||||
// customizable by users, must be handled here.
|
||||
return run_result::ok();
|
||||
}
|
||||
|
||||
// This function operates like `mkdir -p` excluding the last part of
|
||||
// the path which we assume to be the filename.
|
||||
static int create_dir(const std::string &path) {
|
||||
std::filesystem::path dirPath(path);
|
||||
|
||||
try {
|
||||
std::filesystem::create_directories(dirPath.parent_path());
|
||||
} catch(const std::exception &ex) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
199
userspace/falco/app/actions/event_formatter.cpp
Normal file
199
userspace/falco/app/actions/event_formatter.cpp
Normal file
@@ -0,0 +1,199 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2026 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 "event_formatter.h"
|
||||
|
||||
#include <libsinsp/sinsp.h>
|
||||
#include <libsinsp/event.h>
|
||||
|
||||
using namespace falco::app::actions;
|
||||
|
||||
static bool is_flag_type(ppm_param_type type) {
|
||||
return (type == PT_FLAGS8 || type == PT_FLAGS16 || type == PT_FLAGS32 ||
|
||||
type == PT_ENUMFLAGS8 || type == PT_ENUMFLAGS16 || type == PT_ENUMFLAGS32);
|
||||
}
|
||||
|
||||
// Factory method
|
||||
std::unique_ptr<EventFormatter> EventFormatter::create(output_format format) {
|
||||
switch(format) {
|
||||
case output_format::JSON:
|
||||
return std::make_unique<JsonFormatter>();
|
||||
case output_format::MARKDOWN:
|
||||
return std::make_unique<MarkdownFormatter>();
|
||||
case output_format::TEXT:
|
||||
default:
|
||||
return std::make_unique<TextFormatter>();
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// TextFormatter implementation
|
||||
// ============================================================================
|
||||
|
||||
void TextFormatter::begin(const std::string& schema_version) {
|
||||
printf("The events below are valid for Falco *Schema Version*: %s\n", schema_version.c_str());
|
||||
}
|
||||
|
||||
void TextFormatter::begin_category(const std::string& category) {
|
||||
printf("## %s\n\n", category.c_str());
|
||||
}
|
||||
|
||||
void TextFormatter::print_event(const event_entry& e) {
|
||||
char dir = e.is_enter ? '>' : '<';
|
||||
printf("%c %s(", dir, e.name.c_str());
|
||||
|
||||
for(uint32_t k = 0; k < e.info->nparams; k++) {
|
||||
if(k != 0) {
|
||||
printf(", ");
|
||||
}
|
||||
print_param(&e.info->params[k]);
|
||||
}
|
||||
|
||||
printf(")\n");
|
||||
}
|
||||
|
||||
void TextFormatter::end_category() {
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void TextFormatter::end() {
|
||||
// Nothing to do for text format
|
||||
}
|
||||
|
||||
void TextFormatter::print_param(const struct ppm_param_info* param) {
|
||||
printf("%s **%s**", param_type_to_string(param->type), param->name);
|
||||
|
||||
if(is_flag_type(param->type) && param->info) {
|
||||
auto flag_info = static_cast<const ppm_name_value*>(param->info);
|
||||
|
||||
printf(": ");
|
||||
for(size_t i = 0; flag_info[i].name != NULL; i++) {
|
||||
if(i != 0) {
|
||||
printf(", ");
|
||||
}
|
||||
printf("%s", flag_info[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// MarkdownFormatter implementation
|
||||
// ============================================================================
|
||||
|
||||
void MarkdownFormatter::begin(const std::string& schema_version) {
|
||||
printf("The events below are valid for Falco *Schema Version*: %s\n", schema_version.c_str());
|
||||
}
|
||||
|
||||
void MarkdownFormatter::begin_category(const std::string& category) {
|
||||
printf("## %s\n\n", category.c_str());
|
||||
printf("Default | Dir | Name | Params \n");
|
||||
printf(":-------|:----|:-----|:-----\n");
|
||||
}
|
||||
|
||||
void MarkdownFormatter::print_event(const event_entry& e) {
|
||||
char dir = e.is_enter ? '>' : '<';
|
||||
|
||||
printf(e.available ? "Yes" : "No");
|
||||
printf(" | `%c` | `%s` | ", dir, e.name.c_str());
|
||||
|
||||
for(uint32_t k = 0; k < e.info->nparams; k++) {
|
||||
if(k != 0) {
|
||||
printf(", ");
|
||||
}
|
||||
print_param(&e.info->params[k]);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void MarkdownFormatter::end_category() {
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void MarkdownFormatter::end() {
|
||||
// Nothing to do for markdown format
|
||||
}
|
||||
|
||||
void MarkdownFormatter::print_param(const struct ppm_param_info* param) {
|
||||
printf("%s **%s**", param_type_to_string(param->type), param->name);
|
||||
|
||||
if(is_flag_type(param->type) && param->info) {
|
||||
auto flag_info = static_cast<const ppm_name_value*>(param->info);
|
||||
|
||||
printf(": ");
|
||||
for(size_t i = 0; flag_info[i].name != NULL; i++) {
|
||||
if(i != 0) {
|
||||
printf(", ");
|
||||
}
|
||||
printf("*%s*", flag_info[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// JsonFormatter implementation
|
||||
// ============================================================================
|
||||
|
||||
void JsonFormatter::begin(const std::string& schema_version) {
|
||||
m_root = nlohmann::json::object();
|
||||
m_root["schema_version"] = schema_version;
|
||||
}
|
||||
|
||||
void JsonFormatter::begin_category(const std::string& category) {
|
||||
m_current_category = nlohmann::json::array();
|
||||
m_current_category_name = category;
|
||||
}
|
||||
|
||||
void JsonFormatter::print_event(const event_entry& e) {
|
||||
m_current_category.push_back(event_to_json(e));
|
||||
}
|
||||
|
||||
void JsonFormatter::end_category() {
|
||||
m_root[m_current_category_name] = m_current_category;
|
||||
}
|
||||
|
||||
void JsonFormatter::end() {
|
||||
printf("%s\n", m_root.dump(2).c_str());
|
||||
}
|
||||
|
||||
nlohmann::json JsonFormatter::event_to_json(const event_entry& e) {
|
||||
nlohmann::json event;
|
||||
event["name"] = e.name;
|
||||
event["dir"] = e.is_enter ? ">" : "<";
|
||||
event["available"] = e.available;
|
||||
|
||||
nlohmann::json params = nlohmann::json::array();
|
||||
for(uint32_t k = 0; k < e.info->nparams; k++) {
|
||||
nlohmann::json param;
|
||||
param["type"] = param_type_to_string(e.info->params[k].type);
|
||||
param["name"] = e.info->params[k].name;
|
||||
|
||||
if(is_flag_type(e.info->params[k].type) && e.info->params[k].info) {
|
||||
auto flag_info = static_cast<const ppm_name_value*>(e.info->params[k].info);
|
||||
nlohmann::json flags = nlohmann::json::array();
|
||||
for(size_t i = 0; flag_info[i].name != NULL; i++) {
|
||||
flags.push_back(flag_info[i].name);
|
||||
}
|
||||
param["flags"] = flags;
|
||||
}
|
||||
|
||||
params.push_back(param);
|
||||
}
|
||||
event["params"] = params;
|
||||
|
||||
return event;
|
||||
}
|
||||
111
userspace/falco/app/actions/event_formatter.h
Normal file
111
userspace/falco/app/actions/event_formatter.h
Normal file
@@ -0,0 +1,111 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2026 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "../../../engine/output_format.h"
|
||||
|
||||
struct ppm_param_info;
|
||||
struct ppm_event_info;
|
||||
|
||||
namespace falco {
|
||||
namespace app {
|
||||
namespace actions {
|
||||
|
||||
struct event_entry {
|
||||
bool is_enter;
|
||||
bool available;
|
||||
std::string name;
|
||||
const ppm_event_info* info;
|
||||
};
|
||||
|
||||
// Abstract formatter interface
|
||||
class EventFormatter {
|
||||
public:
|
||||
virtual ~EventFormatter() = default;
|
||||
|
||||
// Initialize formatter with schema version
|
||||
virtual void begin(const std::string& schema_version) = 0;
|
||||
|
||||
// Print category header
|
||||
virtual void begin_category(const std::string& category) = 0;
|
||||
|
||||
// Print a single event
|
||||
virtual void print_event(const event_entry& e) = 0;
|
||||
|
||||
// End category
|
||||
virtual void end_category() = 0;
|
||||
|
||||
// Finalize and output
|
||||
virtual void end() = 0;
|
||||
|
||||
// Factory method
|
||||
static std::unique_ptr<EventFormatter> create(output_format format);
|
||||
};
|
||||
|
||||
// Text formatter (default)
|
||||
class TextFormatter : public EventFormatter {
|
||||
public:
|
||||
void begin(const std::string& schema_version) override;
|
||||
void begin_category(const std::string& category) override;
|
||||
void print_event(const event_entry& e) override;
|
||||
void end_category() override;
|
||||
void end() override;
|
||||
|
||||
private:
|
||||
void print_param(const struct ppm_param_info* param);
|
||||
};
|
||||
|
||||
// Markdown formatter
|
||||
class MarkdownFormatter : public EventFormatter {
|
||||
public:
|
||||
void begin(const std::string& schema_version) override;
|
||||
void begin_category(const std::string& category) override;
|
||||
void print_event(const event_entry& e) override;
|
||||
void end_category() override;
|
||||
void end() override;
|
||||
|
||||
private:
|
||||
void print_param(const struct ppm_param_info* param);
|
||||
};
|
||||
|
||||
// JSON formatter
|
||||
class JsonFormatter : public EventFormatter {
|
||||
public:
|
||||
void begin(const std::string& schema_version) override;
|
||||
void begin_category(const std::string& category) override;
|
||||
void print_event(const event_entry& e) override;
|
||||
void end_category() override;
|
||||
void end() override;
|
||||
|
||||
private:
|
||||
nlohmann::json m_root;
|
||||
nlohmann::json m_current_category;
|
||||
std::string m_current_category_name;
|
||||
|
||||
nlohmann::json event_to_json(const event_entry& e);
|
||||
};
|
||||
|
||||
} // namespace actions
|
||||
} // namespace app
|
||||
} // namespace falco
|
||||
@@ -97,12 +97,6 @@ falco::app::run_result falco::app::actions::open_live_inspector(falco::app::stat
|
||||
falco_logger::log(falco_logger::level::INFO,
|
||||
"Opening '" + source + "' source with no driver\n");
|
||||
inspector->open_nodriver();
|
||||
} else if(s.is_gvisor()) /* gvisor engine. */
|
||||
{
|
||||
falco_logger::log(falco_logger::level::INFO,
|
||||
"Opening '" + source + "' source with gVisor. Configuration path: " +
|
||||
s.config->m_gvisor.m_config);
|
||||
inspector->open_gvisor(s.config->m_gvisor.m_config, s.config->m_gvisor.m_root);
|
||||
} else if(s.is_modern_ebpf()) /* modern BPF engine. */
|
||||
{
|
||||
falco_logger::log(falco_logger::level::INFO,
|
||||
@@ -116,14 +110,6 @@ falco::app::run_result falco::app::actions::open_live_inspector(falco::app::stat
|
||||
s.config->m_modern_ebpf.m_cpus_for_each_buffer,
|
||||
true,
|
||||
s.selected_sc_set);
|
||||
} else if(s.is_ebpf()) /* BPF engine. */
|
||||
{
|
||||
falco_logger::log(falco_logger::level::INFO,
|
||||
"Opening '" + source + "' source with BPF probe. BPF probe path: " +
|
||||
s.config->m_ebpf.m_probe_path);
|
||||
inspector->open_bpf(s.config->m_ebpf.m_probe_path.c_str(),
|
||||
s.syscall_buffer_bytes_size,
|
||||
s.selected_sc_set);
|
||||
} else /* Kernel module (default). */
|
||||
{
|
||||
try {
|
||||
|
||||
@@ -88,9 +88,6 @@ void configure_output_format(falco::app::state& s) {
|
||||
}
|
||||
}
|
||||
|
||||
// See https://falco.org/docs/rules/style-guide/
|
||||
const std::string gvisor_info = "vpid=%proc.vpid vtid=%thread.vtid";
|
||||
|
||||
if(!s.options.print_additional.empty()) {
|
||||
falco_logger::log(falco_logger::level::WARNING,
|
||||
"The -p/--print option is deprecated and will be removed. Use -o "
|
||||
@@ -100,11 +97,6 @@ void configure_output_format(falco::app::state& s) {
|
||||
s.options.print_additional == "k" || s.options.print_additional == "kubernetes") {
|
||||
// Don't do anything, we don't need these anymore
|
||||
// since container plugin takes care of suggesting the output format fields itself.
|
||||
} else if(s.options.print_additional == "cg" ||
|
||||
s.options.print_additional == "container-gvisor" ||
|
||||
s.options.print_additional == "kg" ||
|
||||
s.options.print_additional == "kubernetes-gvisor") {
|
||||
s.engine->add_extra_output_format(gvisor_info, falco_common::syscall_source, {}, "");
|
||||
} else {
|
||||
s.engine->add_extra_output_format(s.options.print_additional, "", {}, "");
|
||||
}
|
||||
|
||||
@@ -37,8 +37,7 @@ falco::app::run_result falco::app::actions::init_outputs(falco::app::state& s) {
|
||||
// read hostname
|
||||
std::string hostname;
|
||||
char* env_hostname = getenv("FALCO_HOSTNAME");
|
||||
// todo(leogr): keep FALCO_GRPC_HOSTNAME for backward compatibility. Shall we deprecate it?
|
||||
if(env_hostname || (env_hostname = getenv("FALCO_GRPC_HOSTNAME"))) {
|
||||
if(env_hostname) {
|
||||
hostname = env_hostname;
|
||||
falco_logger::log(falco_logger::level::INFO,
|
||||
"Hostname value has been overridden via environment variable to: " +
|
||||
|
||||
@@ -33,6 +33,6 @@ falco::app::run_result falco::app::actions::list_fields(falco::app::state& s) {
|
||||
s.engine->list_fields(s.options.list_source_fields,
|
||||
s.options.verbose,
|
||||
s.options.names_only,
|
||||
s.options.markdown);
|
||||
s.options.output_fmt);
|
||||
return run_result::exit();
|
||||
}
|
||||
|
||||
@@ -78,14 +78,14 @@ falco::app::run_result falco::app::actions::load_config(const falco::app::state&
|
||||
falco::app::run_result falco::app::actions::require_config_file(const falco::app::state& s) {
|
||||
#ifndef __EMSCRIPTEN__
|
||||
if(s.options.conf_filename.empty()) {
|
||||
#ifndef BUILD_TYPE_RELEASE
|
||||
#ifdef BUILD_TYPE_DEBUG
|
||||
return run_result::fatal(std::string("You must create a config file at ") +
|
||||
FALCO_SOURCE_CONF_FILE + ", " + FALCO_INSTALL_CONF_FILE +
|
||||
" or by passing -c");
|
||||
#else // BUILD_TYPE_RELEASE
|
||||
#else
|
||||
return run_result::fatal(std::string("You must create a config file at ") +
|
||||
FALCO_INSTALL_CONF_FILE + " or by passing -c");
|
||||
#endif // BUILD_TYPE_RELEASE
|
||||
#endif
|
||||
}
|
||||
#endif // __EMSCRIPTEN__
|
||||
return run_result::ok();
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 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 "config_falco.h"
|
||||
#include "actions.h"
|
||||
|
||||
using namespace falco::app;
|
||||
using namespace falco::app::actions;
|
||||
|
||||
falco::app::run_result falco::app::actions::print_generated_gvisor_config(falco::app::state& s) {
|
||||
if(s.options.gvisor_generate_config_with_socket.empty()) {
|
||||
return run_result::ok();
|
||||
}
|
||||
|
||||
sinsp i;
|
||||
std::string gvisor_config =
|
||||
i.generate_gvisor_config(s.options.gvisor_generate_config_with_socket);
|
||||
printf("%s\n", gvisor_config.c_str());
|
||||
return run_result::exit();
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ using namespace falco::app::actions;
|
||||
falco::app::run_result falco::app::actions::print_kernel_version(const falco::app::state& s) {
|
||||
#ifdef __linux__
|
||||
// We print this info only when a kernel driver is injected
|
||||
bool const is_kernel_driver_injected = s.is_modern_ebpf() || s.is_ebpf() || s.is_kmod();
|
||||
bool const is_kernel_driver_injected = s.is_modern_ebpf() || s.is_kmod();
|
||||
if(!is_kernel_driver_injected) {
|
||||
return run_result::ok();
|
||||
}
|
||||
|
||||
@@ -17,19 +17,13 @@ limitations under the License.
|
||||
|
||||
#include "actions.h"
|
||||
#include "helpers.h"
|
||||
#include "event_formatter.h"
|
||||
#include "../app.h"
|
||||
#include "../../versions_info.h"
|
||||
|
||||
using namespace falco::app;
|
||||
using namespace falco::app::actions;
|
||||
|
||||
struct event_entry {
|
||||
bool is_enter;
|
||||
bool available;
|
||||
std::string name;
|
||||
const ppm_event_info* info;
|
||||
};
|
||||
|
||||
struct events_by_category {
|
||||
std::vector<event_entry> syscalls;
|
||||
std::vector<event_entry> tracepoints;
|
||||
@@ -69,6 +63,32 @@ struct events_by_category {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void print_all(EventFormatter& formatter) {
|
||||
formatter.begin_category("Syscall events");
|
||||
for(const auto& e : syscalls) {
|
||||
formatter.print_event(e);
|
||||
}
|
||||
formatter.end_category();
|
||||
|
||||
formatter.begin_category("Tracepoint events");
|
||||
for(const auto& e : tracepoints) {
|
||||
formatter.print_event(e);
|
||||
}
|
||||
formatter.end_category();
|
||||
|
||||
formatter.begin_category("Plugin events");
|
||||
for(const auto& e : pluginevents) {
|
||||
formatter.print_event(e);
|
||||
}
|
||||
formatter.end_category();
|
||||
|
||||
formatter.begin_category("Metaevents");
|
||||
for(const auto& e : metaevents) {
|
||||
formatter.print_event(e);
|
||||
}
|
||||
formatter.end_category();
|
||||
}
|
||||
};
|
||||
|
||||
static struct events_by_category get_event_entries_by_category(
|
||||
@@ -100,86 +120,21 @@ static struct events_by_category get_event_entries_by_category(
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool is_flag_type(ppm_param_type type) {
|
||||
return (type == PT_FLAGS8 || type == PT_FLAGS16 || type == PT_FLAGS32 ||
|
||||
type == PT_ENUMFLAGS8 || type == PT_ENUMFLAGS16 || type == PT_ENUMFLAGS32);
|
||||
}
|
||||
|
||||
static void print_param(const struct ppm_param_info* param, bool markdown) {
|
||||
printf("%s **%s**", param_type_to_string(param->type), param->name);
|
||||
|
||||
if(is_flag_type(param->type) && param->info) {
|
||||
auto flag_info = static_cast<const ppm_name_value*>(param->info);
|
||||
|
||||
printf(": ");
|
||||
for(size_t i = 0; flag_info[i].name != NULL; i++) {
|
||||
if(i != 0) {
|
||||
printf(", ");
|
||||
}
|
||||
|
||||
if(markdown) {
|
||||
printf("*%s*", flag_info[i].name);
|
||||
} else {
|
||||
printf("%s", flag_info[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void print_events(const std::vector<event_entry>& events, bool markdown) {
|
||||
if(markdown) {
|
||||
printf("Default | Dir | Name | Params \n");
|
||||
printf(":-------|:----|:-----|:-----\n");
|
||||
}
|
||||
|
||||
for(const auto& e : events) {
|
||||
char dir = e.is_enter ? '>' : '<';
|
||||
if(markdown) {
|
||||
printf(e.available ? "Yes" : "No");
|
||||
printf(" | `%c` | `%s` | ", dir, e.name.c_str());
|
||||
} else {
|
||||
printf("%c %s(", dir, e.name.c_str());
|
||||
}
|
||||
|
||||
for(uint32_t k = 0; k < e.info->nparams; k++) {
|
||||
if(k != 0) {
|
||||
printf(", ");
|
||||
}
|
||||
|
||||
print_param(&e.info->params[k], markdown);
|
||||
}
|
||||
if(markdown) {
|
||||
printf("\n");
|
||||
} else {
|
||||
printf(")\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
falco::app::run_result falco::app::actions::print_syscall_events(falco::app::state& s) {
|
||||
if(!s.options.list_syscall_events) {
|
||||
return run_result::ok();
|
||||
}
|
||||
|
||||
const falco::versions_info info(s.offline_inspector);
|
||||
printf("The events below are valid for Falco *Schema Version*: %s\n",
|
||||
info.driver_schema_version.c_str());
|
||||
|
||||
const libsinsp::events::set<ppm_event_code> available = libsinsp::events::all_event_set().diff(
|
||||
sc_set_to_event_set(falco::app::ignored_sc_set()));
|
||||
const struct events_by_category events_bc = get_event_entries_by_category(true, available);
|
||||
struct events_by_category events_bc = get_event_entries_by_category(true, available);
|
||||
|
||||
printf("## Syscall events\n\n");
|
||||
print_events(events_bc.syscalls, s.options.markdown);
|
||||
|
||||
printf("\n\n## Tracepoint events\n\n");
|
||||
print_events(events_bc.tracepoints, s.options.markdown);
|
||||
|
||||
printf("\n\n## Plugin events\n\n");
|
||||
print_events(events_bc.pluginevents, s.options.markdown);
|
||||
|
||||
printf("\n\n## Metaevents\n\n");
|
||||
print_events(events_bc.metaevents, s.options.markdown);
|
||||
// Create the appropriate formatter and use it
|
||||
auto formatter = EventFormatter::create(s.options.output_fmt);
|
||||
formatter->begin(info.driver_schema_version);
|
||||
events_bc.print_all(*formatter);
|
||||
formatter->end();
|
||||
|
||||
return run_result::exit();
|
||||
}
|
||||
|
||||
@@ -320,9 +320,16 @@ static falco::app::run_result do_inspect(
|
||||
if(capture_mode_t::RULES == s.config->m_capture_mode && rule_res.capture) {
|
||||
capture = true;
|
||||
}
|
||||
// Extend deadline if defined by the rule
|
||||
if((rule_res.capture_duration_ns + ev->get_ts()) > dump_deadline_ts) {
|
||||
dump_deadline_ts = ev->get_ts() + rule_res.capture_duration_ns;
|
||||
// Compute the capture deadline for this event,
|
||||
// based on the rule’s duration or the default one if unspecified
|
||||
auto evt_deadline_ts =
|
||||
ev->get_ts() + (rule_res.capture_duration_ns > 0
|
||||
? rule_res.capture_duration_ns
|
||||
: s.config->m_capture_default_duration_ns);
|
||||
// Update the capture deadline if this event needs to extend it beyond the
|
||||
// current deadline or if no deadline is currently set
|
||||
if(evt_deadline_ts > dump_deadline_ts) {
|
||||
dump_deadline_ts = evt_deadline_ts;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -336,10 +343,6 @@ static falco::app::run_result do_inspect(
|
||||
ev->get_num()),
|
||||
true); // Enable compression
|
||||
dump_started_ts = ev->get_ts();
|
||||
// If no rule has set a deadline, use the default one
|
||||
if(dump_deadline_ts == 0) {
|
||||
dump_deadline_ts = dump_started_ts + s.config->m_capture_default_duration_ns;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,8 +379,7 @@ static void process_inspector_events(
|
||||
uint64_t num_evts = 0;
|
||||
syscall_evt_drop_mgr sdropmgr;
|
||||
bool is_capture_mode = source.empty();
|
||||
bool check_drops_timeouts =
|
||||
is_capture_mode || (source == falco_common::syscall_source && !s.is_gvisor());
|
||||
bool check_drops_timeouts = is_capture_mode || source == falco_common::syscall_source;
|
||||
|
||||
duration = ((double)clock()) / CLOCKS_PER_SEC;
|
||||
|
||||
@@ -644,13 +646,5 @@ falco::app::run_result falco::app::actions::process_events(falco::app::state& s)
|
||||
}
|
||||
}
|
||||
|
||||
// By deleting s.outputs, we make sure that the engine will wait until
|
||||
// regular output has been completely sent before printing stats, avoiding
|
||||
// intermixed stats with output.
|
||||
// Note that this will only work if this is the last reference held by the
|
||||
// shared pointer.
|
||||
s.outputs.reset();
|
||||
s.engine->print_stats();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 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 "actions.h"
|
||||
|
||||
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
#include "grpc_server.h"
|
||||
#endif
|
||||
|
||||
using namespace falco::app;
|
||||
using namespace falco::app::actions;
|
||||
|
||||
falco::app::run_result falco::app::actions::start_grpc_server(falco::app::state& s) {
|
||||
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
// gRPC server
|
||||
if(!s.config->m_grpc_enabled) {
|
||||
return run_result::ok();
|
||||
}
|
||||
|
||||
if(s.options.dry_run) {
|
||||
falco_logger::log(falco_logger::level::DEBUG, "Skipping starting gRPC server in dry-run\n");
|
||||
return run_result::ok();
|
||||
}
|
||||
|
||||
falco_logger::log(falco_logger::level::INFO,
|
||||
"gRPC server threadiness equals to " +
|
||||
std::to_string(s.config->m_grpc_threadiness) + "\n");
|
||||
// TODO(fntlnz,leodido): when we want to spawn multiple threads we need to have a queue per
|
||||
// thread, or implement different queuing mechanisms, round robin, fanout? What we want to
|
||||
// achieve?
|
||||
s.grpc_server.init(s.config->m_grpc_bind_address,
|
||||
s.config->m_grpc_threadiness,
|
||||
s.config->m_grpc_private_key,
|
||||
s.config->m_grpc_cert_chain,
|
||||
s.config->m_grpc_root_certs,
|
||||
s.config->m_log_level);
|
||||
s.grpc_server_thread = std::thread([&s] { s.grpc_server.run(); });
|
||||
#endif
|
||||
return run_result::ok();
|
||||
}
|
||||
|
||||
falco::app::run_result falco::app::actions::stop_grpc_server(falco::app::state& s) {
|
||||
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
if(!s.config->m_grpc_enabled) {
|
||||
return run_result::ok();
|
||||
}
|
||||
|
||||
if(s.options.dry_run) {
|
||||
falco_logger::log(falco_logger::level::DEBUG, "Skipping stopping gRPC server in dry-run\n");
|
||||
return run_result::ok();
|
||||
}
|
||||
|
||||
if(s.grpc_server_thread.joinable()) {
|
||||
s.grpc_server.shutdown();
|
||||
s.grpc_server_thread.join();
|
||||
}
|
||||
#endif
|
||||
return run_result::ok();
|
||||
}
|
||||
@@ -17,7 +17,7 @@ limitations under the License.
|
||||
|
||||
#include "actions.h"
|
||||
|
||||
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
#if defined(__linux__) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
#include "webserver.h"
|
||||
#endif
|
||||
|
||||
@@ -25,7 +25,7 @@ using namespace falco::app;
|
||||
using namespace falco::app::actions;
|
||||
|
||||
falco::app::run_result falco::app::actions::start_webserver(falco::app::state& state) {
|
||||
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
#if defined(__linux__) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
if(state.is_capture_mode() || !state.config->m_webserver_enabled) {
|
||||
return run_result::ok();
|
||||
}
|
||||
@@ -50,7 +50,7 @@ falco::app::run_result falco::app::actions::start_webserver(falco::app::state& s
|
||||
}
|
||||
|
||||
falco::app::run_result falco::app::actions::stop_webserver(falco::app::state& state) {
|
||||
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
#if defined(__linux__) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
if(state.is_capture_mode() || !state.config->m_webserver_enabled) {
|
||||
return run_result::ok();
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@ bool falco::app::run(falco::app::state& s, bool& restart, std::string& errstr) {
|
||||
falco::app::actions::print_help,
|
||||
falco::app::actions::print_config_schema,
|
||||
falco::app::actions::print_rule_schema,
|
||||
falco::app::actions::print_generated_gvisor_config,
|
||||
falco::app::actions::print_ignored_events,
|
||||
falco::app::actions::print_syscall_events,
|
||||
falco::app::actions::load_config,
|
||||
@@ -77,20 +76,19 @@ bool falco::app::run(falco::app::state& s, bool& restart, std::string& errstr) {
|
||||
falco::app::actions::print_support,
|
||||
falco::app::actions::init_outputs,
|
||||
falco::app::actions::create_signal_handlers,
|
||||
falco::app::actions::create_requested_paths,
|
||||
falco::app::actions::pidfile,
|
||||
falco::app::actions::configure_interesting_sets,
|
||||
falco::app::actions::configure_syscall_buffer_size,
|
||||
falco::app::actions::configure_syscall_buffer_num,
|
||||
falco::app::actions::start_grpc_server,
|
||||
falco::app::actions::start_webserver,
|
||||
falco::app::actions::process_events,
|
||||
};
|
||||
|
||||
std::list<app_action> const teardown_steps = {
|
||||
falco::app::actions::unregister_signal_handlers,
|
||||
falco::app::actions::stop_grpc_server,
|
||||
falco::app::actions::stop_webserver,
|
||||
// Note: calls print_stats internally after resetting outputs.
|
||||
falco::app::actions::cleanup_outputs,
|
||||
falco::app::actions::close_inspectors,
|
||||
};
|
||||
|
||||
|
||||
@@ -25,10 +25,35 @@ limitations under the License.
|
||||
#include <cxxopts.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
|
||||
namespace falco {
|
||||
namespace app {
|
||||
|
||||
static bool parse_output_format(const std::string &format_str,
|
||||
output_format &out,
|
||||
std::string &errstr) {
|
||||
if(format_str.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string lower_format = format_str;
|
||||
std::transform(lower_format.begin(), lower_format.end(), lower_format.begin(), ::tolower);
|
||||
|
||||
if(lower_format == "text") {
|
||||
out = output_format::TEXT;
|
||||
} else if(lower_format == "markdown") {
|
||||
out = output_format::MARKDOWN;
|
||||
} else if(lower_format == "json") {
|
||||
out = output_format::JSON;
|
||||
} else {
|
||||
errstr = "Invalid format '" + format_str + "'. Valid values are: text, markdown, json";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool options::parse(int argc, char **argv, std::string &errstr) {
|
||||
cxxopts::Options opts("falco", "Falco - Cloud Native Runtime Security");
|
||||
define(opts);
|
||||
@@ -51,7 +76,7 @@ bool options::parse(int argc, char **argv, std::string &errstr) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
#ifndef BUILD_TYPE_RELEASE
|
||||
#ifdef BUILD_TYPE_DEBUG
|
||||
conf_stream.open(FALCO_SOURCE_CONF_FILE);
|
||||
if(conf_stream.is_open()) {
|
||||
conf_filename = FALCO_SOURCE_CONF_FILE;
|
||||
@@ -81,6 +106,23 @@ bool options::parse(int argc, char **argv, std::string &errstr) {
|
||||
|
||||
list_fields = m_cmdline_parsed.count("list") > 0;
|
||||
|
||||
// Validate that both markdown and format are not specified together
|
||||
if(m_cmdline_parsed.count("markdown") > 0 && m_cmdline_parsed.count("format") > 0) {
|
||||
errstr = "Cannot specify both --markdown and --format options together";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse and validate the format option
|
||||
if(!format.empty()) {
|
||||
if(!parse_output_format(format, output_fmt, errstr)) {
|
||||
return false;
|
||||
}
|
||||
} else if(markdown) {
|
||||
// If markdown flag is set and format is not specified, use MARKDOWN format
|
||||
fprintf(stderr, "WARNING: --markdown is deprecated, use --format markdown instead.\n");
|
||||
output_fmt = output_format::MARKDOWN;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -93,7 +135,7 @@ void options::define(cxxopts::Options& opts)
|
||||
{
|
||||
opts.add_options()
|
||||
("h,help", "Print this help list and exit.", cxxopts::value(help)->default_value("false"))
|
||||
#ifdef BUILD_TYPE_RELEASE
|
||||
#ifndef BUILD_TYPE_DEBUG
|
||||
("c", "Configuration file. If not specified uses " FALCO_INSTALL_CONF_FILE ".", cxxopts::value(conf_filename), "<path>")
|
||||
#else
|
||||
("c", "Configuration file. If not specified tries " FALCO_SOURCE_CONF_FILE ", " FALCO_INSTALL_CONF_FILE ".", cxxopts::value(conf_filename), "<path>")
|
||||
@@ -103,9 +145,6 @@ void options::define(cxxopts::Options& opts)
|
||||
("disable-source", "Turn off a specific <event_source>. By default, all loaded sources get enabled. Available sources are 'syscall' plus all sources defined by loaded plugins supporting the event sourcing capability. This option can be passed multiple times, but turning off all event sources simultaneously is not permitted. This option can not be mixed with --enable-source. This option has no effect when reproducing events from a capture file.", cxxopts::value(disable_sources), "<event_source>")
|
||||
("dry-run", "Run Falco without processing events. It can help check that the configuration and rules do not have any errors.", cxxopts::value(dry_run)->default_value("false"))
|
||||
("enable-source", "Enable a specific <event_source>. By default, all loaded sources get enabled. Available sources are 'syscall' plus all sources defined by loaded plugins supporting the event sourcing capability. This option can be passed multiple times. When using this option, only the event sources specified by it will be enabled. This option can not be mixed with --disable-source. This option has no effect when reproducing events from a capture file.", cxxopts::value(enable_sources), "<event_source>")
|
||||
#ifdef HAS_GVISOR
|
||||
("gvisor-generate-config", "Generate a configuration file that can be used for gVisor and exit. See --gvisor-config for more details.", cxxopts::value<std::string>(gvisor_generate_config_with_socket)->implicit_value("/run/falco/gvisor.sock"), "<socket_path>")
|
||||
#endif
|
||||
("i", "Print those events that are ignored by default for performance reasons and exit.", cxxopts::value(print_ignored_events)->default_value("false"))
|
||||
("L", "Show the name and description of all rules and exit. If json_output is set to true, it prints details about all rules, macros, and lists in JSON format.", cxxopts::value(describe_all_rules)->default_value("false"))
|
||||
("l", "Show the name and description of the rule specified <rule> and exit. If json_output is set to true, it prints details about the rule in JSON format.", cxxopts::value(describe_rule), "<rule>")
|
||||
@@ -113,11 +152,12 @@ void options::define(cxxopts::Options& opts)
|
||||
("list-events", "List all defined syscall events, metaevents, tracepoint events and exit.", cxxopts::value<bool>(list_syscall_events))
|
||||
("list-plugins", "Print info on all loaded plugins and exit.", cxxopts::value(list_plugins)->default_value("false"))
|
||||
("M", "Stop Falco execution after <num_seconds> are passed.", cxxopts::value(duration_to_tot)->default_value("0"), "<num_seconds>")
|
||||
("markdown", "Print output in Markdown format when used in conjunction with --list or --list-events options. It has no effect when used with other options.", cxxopts::value<bool>(markdown))
|
||||
("markdown", "DEPRECATED: use --format markdown instead. Print output in Markdown format when used in conjunction with --list or --list-events options. It has no effect when used with other options.", cxxopts::value<bool>(markdown))
|
||||
("format", "Print output in the specified <format> when used in conjunction with --list or --list-events options. Valid values are 'text', 'markdown', or 'json'. It has no effect when used with other options. Cannot be used together with --markdown.", cxxopts::value(format), "<format>")
|
||||
("N", "Only print field names when used in conjunction with the --list option. It has no effect when used with other options.", cxxopts::value(names_only)->default_value("false"))
|
||||
("o,option", "Set the value of option <opt> to <val>. Overrides values in the configuration file. <opt> can be identified using its location in the configuration file using dot notation. Elements of list entries can be accessed via square brackets [].\n E.g. base.id = val\n base.subvalue.subvalue2 = val\n base.list[1]=val", cxxopts::value(cmdline_config_options), "<opt>=<val>")
|
||||
("plugin-info", "Print info for the plugin specified by <plugin_name> and exit.\nThis includes all descriptive information like name and author, along with the\nschema format for the init configuration and a list of suggested open parameters.\n<plugin_name> can be the plugin's name or its configured 'library_path'.", cxxopts::value(print_plugin_info), "<plugin_name>")
|
||||
("p,print", "DEPRECATED: use -o append_output... instead. Print additional information in the rule's output.\nUse -pc or -pcontainer to append container details to syscall events.\nUse -pk or -pkubernetes to add both container and Kubernetes details to syscall events.\nIf using gVisor, choose -pcg or -pkg variants (or -pcontainer-gvisor and -pkubernetes-gvisor, respectively).\nThe details will be directly appended to the rule's output.\nAlternatively, use -p <output_format> for a custom format. In this case, the given <output_format> will be appended to the rule's output without any replacement to all events, including plugin events.", cxxopts::value(print_additional), "<output_format>")
|
||||
("p,print", "DEPRECATED: use -o append_output... instead. Print additional information in the rule's output.\nUse -pc or -pcontainer to append container details to syscall events.\nUse -pk or -pkubernetes to add both container and Kubernetes details to syscall events.\nThe details will be directly appended to the rule's output.\nAlternatively, use -p <output_format> for a custom format. In this case, the given <output_format> will be appended to the rule's output without any replacement to all events, including plugin events.", cxxopts::value(print_additional), "<output_format>")
|
||||
("P,pidfile", "Write PID to specified <pid_file> path. By default, no PID file is created.", cxxopts::value(pidfilename)->default_value(""), "<pid_file>")
|
||||
("r", "Rules file or directory to be loaded. This option can be passed multiple times. Falco defaults to the values in the configuration file when this option is not specified. Only files with .yml or .yaml extension are considered.", cxxopts::value<std::vector<std::string>>(), "<rules_file>")
|
||||
("support", "Print support information, including version, rules files used, loaded configuration, etc., and exit. The output is in JSON format.", cxxopts::value(print_support)->default_value("false"))
|
||||
|
||||
@@ -18,6 +18,7 @@ limitations under the License.
|
||||
#pragma once
|
||||
|
||||
#include <libsinsp/event.h>
|
||||
#include "../../engine/output_format.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -48,7 +49,6 @@ public:
|
||||
sinsp_evt::param_fmt event_buffer_format = sinsp_evt::PF_NORMAL;
|
||||
std::vector<std::string> disable_sources;
|
||||
std::vector<std::string> enable_sources;
|
||||
std::string gvisor_generate_config_with_socket;
|
||||
bool describe_all_rules = false;
|
||||
std::string describe_rule;
|
||||
bool print_ignored_events = false;
|
||||
@@ -58,6 +58,8 @@ public:
|
||||
std::string print_plugin_info;
|
||||
bool list_syscall_events = false;
|
||||
bool markdown = false;
|
||||
std::string format;
|
||||
output_format output_fmt = output_format::TEXT;
|
||||
int duration_to_tot = 0;
|
||||
bool names_only = false;
|
||||
std::vector<std::string> cmdline_config_options;
|
||||
|
||||
@@ -23,8 +23,7 @@ limitations under the License.
|
||||
#include "restart_handler.h"
|
||||
#include "../configuration.h"
|
||||
#include "../stats_writer.h"
|
||||
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
#include "../grpc_server.h"
|
||||
#if defined(__linux__) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
#include "../webserver.h"
|
||||
#endif
|
||||
|
||||
@@ -110,10 +109,7 @@ struct state {
|
||||
// Helper responsible for watching of handling hot application restarts
|
||||
std::shared_ptr<restart_handler> restarter;
|
||||
|
||||
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
falco::grpc::server grpc_server;
|
||||
std::thread grpc_server_thread;
|
||||
|
||||
#if defined(__linux__) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
falco_webserver webserver;
|
||||
#endif
|
||||
// Set by start_webserver to start prometheus metrics
|
||||
@@ -122,12 +118,8 @@ struct state {
|
||||
|
||||
inline bool is_capture_mode() const { return config->m_engine_mode == engine_kind_t::REPLAY; }
|
||||
|
||||
inline bool is_gvisor() const { return config->m_engine_mode == engine_kind_t::GVISOR; }
|
||||
|
||||
inline bool is_kmod() const { return config->m_engine_mode == engine_kind_t::KMOD; }
|
||||
|
||||
inline bool is_ebpf() const { return config->m_engine_mode == engine_kind_t::EBPF; }
|
||||
|
||||
inline bool is_modern_ebpf() const {
|
||||
return config->m_engine_mode == engine_kind_t::MODERN_EBPF;
|
||||
}
|
||||
@@ -144,9 +136,6 @@ struct state {
|
||||
case engine_kind_t::KMOD:
|
||||
drop_failed = config->m_kmod.m_drop_failed_exit;
|
||||
break;
|
||||
case engine_kind_t::EBPF:
|
||||
drop_failed = config->m_ebpf.m_drop_failed_exit;
|
||||
break;
|
||||
case engine_kind_t::MODERN_EBPF:
|
||||
drop_failed = config->m_modern_ebpf.m_drop_failed_exit;
|
||||
break;
|
||||
@@ -163,9 +152,6 @@ struct state {
|
||||
case engine_kind_t::KMOD:
|
||||
index = config->m_kmod.m_buf_size_preset;
|
||||
break;
|
||||
case engine_kind_t::EBPF:
|
||||
index = config->m_ebpf.m_buf_size_preset;
|
||||
break;
|
||||
case engine_kind_t::MODERN_EBPF:
|
||||
index = config->m_modern_ebpf.m_buf_size_preset;
|
||||
break;
|
||||
|
||||
@@ -157,12 +157,6 @@ const char config_schema_string[] = LONG_STRING_CONST(
|
||||
"program_output": {
|
||||
"$ref": "#/definitions/ProgramOutput"
|
||||
},
|
||||
"grpc_output": {
|
||||
"$ref": "#/definitions/Output"
|
||||
},
|
||||
"grpc": {
|
||||
"$ref": "#/definitions/Grpc"
|
||||
},
|
||||
"webserver": {
|
||||
"$ref": "#/definitions/Webserver"
|
||||
},
|
||||
@@ -367,17 +361,11 @@ const char config_schema_string[] = LONG_STRING_CONST(
|
||||
"kmod": {
|
||||
"$ref": "#/definitions/Kmod"
|
||||
},
|
||||
"ebpf": {
|
||||
"$ref": "#/definitions/Ebpf"
|
||||
},
|
||||
"modern_ebpf": {
|
||||
"$ref": "#/definitions/ModernEbpf"
|
||||
},
|
||||
"replay": {
|
||||
"$ref": "#/definitions/Replay"
|
||||
},
|
||||
"gvisor": {
|
||||
"$ref": "#/definitions/Gvisor"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -385,42 +373,6 @@ const char config_schema_string[] = LONG_STRING_CONST(
|
||||
],
|
||||
"title": "Engine"
|
||||
},
|
||||
"Ebpf": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"probe": {
|
||||
"type": "string"
|
||||
},
|
||||
"buf_size_preset": {
|
||||
"type": "integer"
|
||||
},
|
||||
"drop_failed_exit": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"probe"
|
||||
],
|
||||
"title": "Ebpf"
|
||||
},
|
||||
"Gvisor": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"config": {
|
||||
"type": "string"
|
||||
},
|
||||
"root": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"config",
|
||||
"root"
|
||||
],
|
||||
"title": "Gvisor"
|
||||
},
|
||||
"Kmod": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
@@ -501,23 +453,6 @@ const char config_schema_string[] = LONG_STRING_CONST(
|
||||
"minProperties": 1,
|
||||
"title": "FileOutput"
|
||||
},
|
||||
"Grpc": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"bind_address": {
|
||||
"type": "string"
|
||||
},
|
||||
"threadiness": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"minProperties": 1,
|
||||
"title": "Grpc"
|
||||
},
|
||||
"Output": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
|
||||
@@ -27,9 +27,6 @@ limitations under the License.
|
||||
#include <sys/stat.h>
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
// Used in the ebpf probe path.
|
||||
#define PATH_MAX 260
|
||||
#endif
|
||||
#include "falco_utils.h"
|
||||
|
||||
@@ -77,8 +74,6 @@ falco_configuration::falco_configuration():
|
||||
m_time_format_iso_8601(false),
|
||||
m_buffer_format_base64(false),
|
||||
m_output_timeout(2000),
|
||||
m_grpc_enabled(false),
|
||||
m_grpc_threadiness(0),
|
||||
m_webserver_enabled(false),
|
||||
m_syscall_evt_drop_threshold(.1),
|
||||
m_syscall_evt_drop_rate(.03333),
|
||||
@@ -239,10 +234,8 @@ void falco_configuration::load_engine_config(const std::string &config_name) {
|
||||
// Set driver mode if not already set.
|
||||
const std::unordered_map<std::string, engine_kind_t> engine_mode_lut = {
|
||||
{"kmod", engine_kind_t::KMOD},
|
||||
{"ebpf", engine_kind_t::EBPF},
|
||||
{"modern_ebpf", engine_kind_t::MODERN_EBPF},
|
||||
{"replay", engine_kind_t::REPLAY},
|
||||
{"gvisor", engine_kind_t::GVISOR},
|
||||
{"nodriver", engine_kind_t::NODRIVER},
|
||||
};
|
||||
|
||||
@@ -261,21 +254,6 @@ void falco_configuration::load_engine_config(const std::string &config_name) {
|
||||
m_kmod.m_drop_failed_exit =
|
||||
m_config.get_scalar<bool>("engine.kmod.drop_failed_exit", DEFAULT_DROP_FAILED_EXIT);
|
||||
break;
|
||||
case engine_kind_t::EBPF: {
|
||||
// default value for `m_probe_path` should be `$HOME/FALCO_PROBE_BPF_FILEPATH`
|
||||
char full_path[PATH_MAX];
|
||||
const char *home = std::getenv("HOME");
|
||||
if(!home) {
|
||||
throw std::logic_error("Cannot get the env variable 'HOME'");
|
||||
}
|
||||
snprintf(full_path, PATH_MAX, "%s/%s", home, FALCO_PROBE_BPF_FILEPATH);
|
||||
m_ebpf.m_probe_path =
|
||||
m_config.get_scalar<std::string>("engine.ebpf.probe", std::string(full_path));
|
||||
m_ebpf.m_buf_size_preset = m_config.get_scalar<int16_t>("engine.ebpf.buf_size_preset",
|
||||
DEFAULT_BUF_SIZE_PRESET);
|
||||
m_ebpf.m_drop_failed_exit =
|
||||
m_config.get_scalar<bool>("engine.ebpf.drop_failed_exit", DEFAULT_DROP_FAILED_EXIT);
|
||||
} break;
|
||||
case engine_kind_t::MODERN_EBPF:
|
||||
m_modern_ebpf.m_cpus_for_each_buffer =
|
||||
m_config.get_scalar<uint16_t>("engine.modern_ebpf.cpus_for_each_buffer",
|
||||
@@ -296,15 +274,6 @@ void falco_configuration::load_engine_config(const std::string &config_name) {
|
||||
"): engine.kind is 'replay' but no engine.replay.capture_file specified.");
|
||||
}
|
||||
break;
|
||||
case engine_kind_t::GVISOR:
|
||||
m_gvisor.m_config = m_config.get_scalar<std::string>("engine.gvisor.config", "");
|
||||
if(m_gvisor.m_config.empty()) {
|
||||
throw std::logic_error(
|
||||
"Error reading config file (" + config_name +
|
||||
"): engine.kind is 'gvisor' but no engine.gvisor.config specified.");
|
||||
}
|
||||
m_gvisor.m_root = m_config.get_scalar<std::string>("engine.gvisor.root", "");
|
||||
break;
|
||||
case engine_kind_t::NODRIVER:
|
||||
default:
|
||||
break;
|
||||
@@ -472,27 +441,6 @@ void falco_configuration::load_yaml(const std::string &config_name) {
|
||||
m_outputs.push_back(http_output);
|
||||
}
|
||||
|
||||
m_grpc_enabled = m_config.get_scalar<bool>("grpc.enabled", false);
|
||||
m_grpc_bind_address = m_config.get_scalar<std::string>("grpc.bind_address", "0.0.0.0:5060");
|
||||
m_grpc_threadiness = m_config.get_scalar<uint32_t>("grpc.threadiness", 0);
|
||||
if(m_grpc_threadiness == 0) {
|
||||
m_grpc_threadiness = falco::utils::hardware_concurrency();
|
||||
}
|
||||
// todo > else limit threadiness to avoid oversubscription?
|
||||
m_grpc_private_key =
|
||||
m_config.get_scalar<std::string>("grpc.private_key", "/etc/falco/certs/server.key");
|
||||
m_grpc_cert_chain =
|
||||
m_config.get_scalar<std::string>("grpc.cert_chain", "/etc/falco/certs/server.crt");
|
||||
m_grpc_root_certs =
|
||||
m_config.get_scalar<std::string>("grpc.root_certs", "/etc/falco/certs/ca.crt");
|
||||
|
||||
falco::outputs::config grpc_output;
|
||||
grpc_output.name = "grpc";
|
||||
// gRPC output is enabled only if gRPC server is enabled too
|
||||
if(m_config.get_scalar<bool>("grpc_output.enabled", true) && m_grpc_enabled) {
|
||||
m_outputs.push_back(grpc_output);
|
||||
}
|
||||
|
||||
m_output_timeout = m_config.get_scalar<uint32_t>("output_timeout", 2000);
|
||||
|
||||
std::string rule_matching = m_config.get_scalar<std::string>("rule_matching", "first");
|
||||
|
||||
@@ -40,7 +40,7 @@ limitations under the License.
|
||||
// Falco only metric
|
||||
#define METRICS_V2_JEMALLOC_STATS 1 << 31
|
||||
|
||||
enum class engine_kind_t : uint8_t { KMOD, EBPF, MODERN_EBPF, REPLAY, GVISOR, NODRIVER };
|
||||
enum class engine_kind_t : uint8_t { KMOD, MODERN_EBPF, REPLAY, NODRIVER };
|
||||
|
||||
enum class capture_mode_t : uint8_t { RULES, ALL_RULES };
|
||||
|
||||
@@ -66,12 +66,6 @@ public:
|
||||
bool m_drop_failed_exit;
|
||||
};
|
||||
|
||||
struct ebpf_config {
|
||||
std::string m_probe_path;
|
||||
int16_t m_buf_size_preset;
|
||||
bool m_drop_failed_exit;
|
||||
};
|
||||
|
||||
struct modern_ebpf_config {
|
||||
uint16_t m_cpus_for_each_buffer;
|
||||
int16_t m_buf_size_preset;
|
||||
@@ -82,11 +76,6 @@ public:
|
||||
std::string m_capture_file;
|
||||
};
|
||||
|
||||
struct gvisor_config {
|
||||
std::string m_config;
|
||||
std::string m_root;
|
||||
};
|
||||
|
||||
struct webserver_config {
|
||||
uint32_t m_threadiness = 0;
|
||||
uint32_t m_listen_port = 8765;
|
||||
@@ -170,13 +159,6 @@ public:
|
||||
bool m_buffer_format_base64;
|
||||
uint32_t m_output_timeout;
|
||||
|
||||
bool m_grpc_enabled;
|
||||
uint32_t m_grpc_threadiness;
|
||||
std::string m_grpc_bind_address;
|
||||
std::string m_grpc_private_key;
|
||||
std::string m_grpc_cert_chain;
|
||||
std::string m_grpc_root_certs;
|
||||
|
||||
bool m_webserver_enabled;
|
||||
webserver_config m_webserver_config;
|
||||
|
||||
@@ -220,10 +202,8 @@ public:
|
||||
// Falco engine
|
||||
engine_kind_t m_engine_mode = engine_kind_t::KMOD;
|
||||
kmod_config m_kmod = {};
|
||||
ebpf_config m_ebpf = {};
|
||||
modern_ebpf_config m_modern_ebpf = {};
|
||||
replay_config m_replay = {};
|
||||
gvisor_config m_gvisor = {};
|
||||
|
||||
yaml_helper m_config;
|
||||
|
||||
|
||||
@@ -109,11 +109,9 @@ bool syscall_evt_drop_mgr::process_event(std::shared_ptr<sinsp> inspector, sinsp
|
||||
if(m_bucket.claim(1, evt->get_ts())) {
|
||||
m_num_actions++;
|
||||
|
||||
return perform_actions(
|
||||
evt->get_ts(),
|
||||
delta,
|
||||
inspector->check_current_engine(BPF_ENGINE) ||
|
||||
inspector->check_current_engine(MODERN_BPF_ENGINE));
|
||||
return perform_actions(evt->get_ts(),
|
||||
delta,
|
||||
inspector->check_current_engine(MODERN_BPF_ENGINE));
|
||||
} else {
|
||||
falco_logger::log(
|
||||
falco_logger::level::DEBUG,
|
||||
|
||||
@@ -150,13 +150,15 @@ std::string falco_metrics::falco_to_text_prometheus(
|
||||
// # HELP falcosecurity_falco_outputs_queue_num_drops_total https://falco.org/docs/metrics/
|
||||
// # TYPE falcosecurity_falco_outputs_queue_num_drops_total counter
|
||||
// falcosecurity_falco_outputs_queue_num_drops_total 0
|
||||
additional_wrapper_metrics.emplace_back(libs::metrics::libsinsp_metrics::new_metric(
|
||||
"outputs_queue_num_drops",
|
||||
METRICS_V2_MISC,
|
||||
METRIC_VALUE_TYPE_U64,
|
||||
METRIC_VALUE_UNIT_COUNT,
|
||||
METRIC_VALUE_METRIC_TYPE_MONOTONIC,
|
||||
state.outputs->get_outputs_queue_num_drops()));
|
||||
if(state.outputs != nullptr) {
|
||||
additional_wrapper_metrics.emplace_back(libs::metrics::libsinsp_metrics::new_metric(
|
||||
"outputs_queue_num_drops",
|
||||
METRICS_V2_MISC,
|
||||
METRIC_VALUE_TYPE_U64,
|
||||
METRIC_VALUE_UNIT_COUNT,
|
||||
METRIC_VALUE_METRIC_TYPE_MONOTONIC,
|
||||
state.outputs->get_outputs_queue_num_drops()));
|
||||
}
|
||||
|
||||
// # HELP falcosecurity_falco_reload_timestamp_nanoseconds https://falco.org/docs/metrics/
|
||||
// # TYPE falcosecurity_falco_reload_timestamp_nanoseconds gauge
|
||||
@@ -256,12 +258,10 @@ std::string falco_metrics::sources_to_text_prometheus(
|
||||
const falco::app::state& state,
|
||||
libs::metrics::prometheus_metrics_converter& prometheus_metrics_converter,
|
||||
std::vector<metrics_v2>& additional_wrapper_metrics) {
|
||||
static const char* all_driver_engines[] = {BPF_ENGINE,
|
||||
KMOD_ENGINE,
|
||||
static const char* all_driver_engines[] = {KMOD_ENGINE,
|
||||
MODERN_BPF_ENGINE,
|
||||
SOURCE_PLUGIN_ENGINE,
|
||||
NODRIVER_ENGINE,
|
||||
GVISOR_ENGINE};
|
||||
NODRIVER_ENGINE};
|
||||
static re2::RE2 drops_buffer_pattern("n_drops_buffer_([^_]+(?:_[^_]+)*)_exit$");
|
||||
static re2::RE2 cpu_pattern("(\\d+)");
|
||||
|
||||
|
||||
@@ -15,10 +15,6 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
#include <google/protobuf/util/time_util.h>
|
||||
#endif
|
||||
|
||||
#include "falco_outputs.h"
|
||||
#include "config_falco.h"
|
||||
|
||||
@@ -32,9 +28,8 @@ limitations under the License.
|
||||
#include "outputs_program.h"
|
||||
#include "outputs_syslog.h"
|
||||
#endif
|
||||
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
#if defined(__linux__) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
#include "outputs_http.h"
|
||||
#include "outputs_grpc.h"
|
||||
#endif
|
||||
|
||||
static const char *s_internal_source = "internal";
|
||||
@@ -98,11 +93,9 @@ void falco_outputs::add_output(const falco::outputs::config &oc) {
|
||||
oo = std::make_unique<falco::outputs::output_syslog>();
|
||||
}
|
||||
#endif
|
||||
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
#if defined(__linux__) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
else if(oc.name == "http") {
|
||||
oo = std::make_unique<falco::outputs::output_http>();
|
||||
} else if(oc.name == "grpc") {
|
||||
oo = std::make_unique<falco::outputs::output_grpc>();
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 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 <sstream>
|
||||
|
||||
#include "grpc_context.h"
|
||||
|
||||
falco::grpc::context::context(::grpc::ServerContext* ctx): m_ctx(ctx) {
|
||||
std::string session_id;
|
||||
std::string request_id;
|
||||
|
||||
get_metadata(meta_session, session_id);
|
||||
get_metadata(meta_request, request_id);
|
||||
|
||||
bool has_meta = false;
|
||||
std::stringstream meta;
|
||||
if(!session_id.empty()) {
|
||||
meta << "[sid=" << session_id << "]";
|
||||
has_meta = true;
|
||||
}
|
||||
if(!request_id.empty()) {
|
||||
meta << "[rid=" << request_id << "]";
|
||||
has_meta = true;
|
||||
}
|
||||
if(has_meta) {
|
||||
meta << " ";
|
||||
}
|
||||
m_prefix = meta.str();
|
||||
}
|
||||
|
||||
void falco::grpc::context::context::get_metadata(std::string key, std::string& val) {
|
||||
const std::multimap<::grpc::string_ref, ::grpc::string_ref>& client_metadata =
|
||||
m_ctx->client_metadata();
|
||||
auto it = client_metadata.find(key);
|
||||
if(it != client_metadata.end()) {
|
||||
val.assign(it->second.data(), it->second.size());
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef GRPC_INCLUDE_IS_GRPCPP
|
||||
#include <grpcpp/grpcpp.h>
|
||||
#else
|
||||
#include <grpc++/grpc++.h>
|
||||
#endif
|
||||
|
||||
namespace falco {
|
||||
namespace grpc {
|
||||
|
||||
const std::string meta_session = "session_id";
|
||||
const std::string meta_request = "request_id";
|
||||
|
||||
class context {
|
||||
public:
|
||||
explicit context(::grpc::ServerContext* ctx);
|
||||
virtual ~context() = default;
|
||||
|
||||
void get_metadata(std::string key, std::string& val);
|
||||
|
||||
private:
|
||||
::grpc::ServerContext* m_ctx = nullptr;
|
||||
std::string m_prefix;
|
||||
};
|
||||
|
||||
class stream_context : public context {
|
||||
public:
|
||||
explicit stream_context(::grpc::ServerContext* ctx): context(ctx) {};
|
||||
virtual ~stream_context() override = default;
|
||||
|
||||
enum : char { STREAMING = 1, SUCCESS, ERROR } m_status = STREAMING;
|
||||
|
||||
mutable void* m_stream = nullptr; // todo(fntlnz, leodido) > useful in the future
|
||||
mutable bool m_has_more = false;
|
||||
mutable bool m_is_running = true;
|
||||
};
|
||||
|
||||
class bidi_context : public stream_context {
|
||||
public:
|
||||
explicit bidi_context(::grpc::ServerContext* ctx): stream_context(ctx) {};
|
||||
virtual ~bidi_context() override = default;
|
||||
};
|
||||
|
||||
} // namespace grpc
|
||||
} // namespace falco
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user