mirror of
https://github.com/falcosecurity/falco.git
synced 2026-03-21 04:02:14 +00:00
Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba229e5b54 | ||
|
|
b8a8c2d1bf | ||
|
|
a018132908 | ||
|
|
7f35ae723f | ||
|
|
285d69ec42 | ||
|
|
78ce4d1ecc | ||
|
|
a8ac367574 | ||
|
|
dc96fe2c87 | ||
|
|
102e49713d | ||
|
|
8b5aab9ee0 | ||
|
|
2f7582e2b6 | ||
|
|
f4aef006fe | ||
|
|
e1c07568b4 | ||
|
|
ded4bdde96 | ||
|
|
ae9ffe414f | ||
|
|
d8c368b5ce | ||
|
|
b718083fe7 | ||
|
|
3f4ed4ca4b | ||
|
|
a6a1a9769f | ||
|
|
e601ec2eab | ||
|
|
64bbffe5ef | ||
|
|
5ee05abc08 | ||
|
|
c308f5c7e2 | ||
|
|
ee78c862ad | ||
|
|
8ebdbe3e6f | ||
|
|
91d1511285 | ||
|
|
3f9ede86bb | ||
|
|
5192921732 | ||
|
|
56de6e6786 | ||
|
|
f5dea33b5e | ||
|
|
b318c165da | ||
|
|
5ac005bd4d | ||
|
|
2367d36867 | ||
|
|
95e4c58e7f | ||
|
|
4aebee684a | ||
|
|
63736563a2 | ||
|
|
7cac2833b2 | ||
|
|
447a251e16 | ||
|
|
b5e64c52f3 | ||
|
|
bbef26aad0 | ||
|
|
6bb68c0c43 | ||
|
|
a25b5c1045 | ||
|
|
f6ab7f2501 | ||
|
|
66df3dc417 | ||
|
|
14d1ca3c97 | ||
|
|
07d7b9a57a | ||
|
|
70ce7b936b | ||
|
|
728c8d7d0e | ||
|
|
04dd06b2c6 | ||
|
|
4c023b0d93 | ||
|
|
8a7ef687b1 | ||
|
|
21c629dc4d | ||
|
|
2db29af0e8 | ||
|
|
bc072502cc | ||
|
|
3976e777a5 | ||
|
|
9131261ff3 | ||
|
|
e5034323fd | ||
|
|
213fa392e8 | ||
|
|
a2c128e934 | ||
|
|
f2d0c42911 | ||
|
|
8ff1ef752d | ||
|
|
454882f518 | ||
|
|
3c31c05450 |
2
.github/workflows/release.yaml
vendored
2
.github/workflows/release.yaml
vendored
@@ -147,7 +147,7 @@ jobs:
|
||||
sed -i s/FALCOVER/${{ github.event.release.tag_name }}/g release-body.md
|
||||
|
||||
- name: Generate release notes
|
||||
uses: leodido/rn2md@0669e5f3b21492c11c2db43cd6e267566f5880f3
|
||||
uses: leodido/rn2md@1378404a058ecf86701f3ab533d487333fc675a7
|
||||
with:
|
||||
milestone: ${{ github.event.release.tag_name }}
|
||||
output: ./notes.md
|
||||
|
||||
33
.github/workflows/reusable_test_packages.yaml
vendored
33
.github/workflows/reusable_test_packages.yaml
vendored
@@ -43,26 +43,21 @@ jobs:
|
||||
tar -xvf $(ls falco-*.tar.gz)
|
||||
cd falco-${{ inputs.version }}-${{ inputs.arch }}
|
||||
sudo cp -r * /
|
||||
|
||||
|
||||
# Note: most probably the plugin related tests should be moved to the plugin repo sooner or later.
|
||||
- name: Install needed artifacts using falcoctl
|
||||
if: ${{ inputs.static == false }}
|
||||
run: |
|
||||
sudo mkdir -p /usr/share/falco/plugins
|
||||
sudo falcoctl artifact install k8saudit-rules
|
||||
sudo falcoctl artifact install cloudtrail-rules
|
||||
|
||||
# We only run driver loader tests on x86_64
|
||||
- name: Install dependencies for falco-driver-loader tests
|
||||
if: ${{ inputs.arch == 'x86_64' }}
|
||||
run: |
|
||||
sudo apt update -y
|
||||
sudo apt install -y --no-install-recommends build-essential clang make llvm gcc dkms
|
||||
|
||||
- name: Install kernel headers (workaround)
|
||||
if: inputs.arch == 'aarch64'
|
||||
run: |
|
||||
sudo mkdir -p /usr/src
|
||||
sudo git clone --depth 1 --branch v$(uname -r) git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git /usr/src/linux
|
||||
sudo rm /lib/modules/$(uname -r)/build
|
||||
sudo ln -s /usr/src/linux-headers-$(uname -r)/ /lib/modules/$(uname -r)/build
|
||||
sudo rm /lib/modules/$(uname -r)/source
|
||||
sudo ln -s /usr/src/linux-headers-$(uname -r)/ /lib/modules/$(uname -r)/source
|
||||
|
||||
- name: Install kernel headers
|
||||
if: inputs.arch == 'x86_64'
|
||||
run: |
|
||||
sudo apt install -y --no-install-recommends linux-headers-$(uname -r)
|
||||
sudo apt install -y --no-install-recommends build-essential clang make llvm gcc dkms linux-headers-$(uname -r)
|
||||
|
||||
- name: Install go-junit-report
|
||||
run: |
|
||||
@@ -86,7 +81,9 @@ jobs:
|
||||
if ${{ inputs.static && 'false' || 'true' }}; then
|
||||
./build/falcoctl.test -test.timeout=90s -test.v >> ./report.txt 2>&1 || true
|
||||
./build/k8saudit.test -test.timeout=90s -test.v >> ./report.txt 2>&1 || true
|
||||
sudo ./build/falco-driver-loader.test -test.timeout=90s -test.v >> ./report.txt 2>&1 || true
|
||||
if ${{ inputs.arch == 'x86_64' && 'true' || 'false' }}; then
|
||||
sudo ./build/falco-driver-loader.test -test.timeout=90s -test.v >> ./report.txt 2>&1 || true
|
||||
fi
|
||||
fi
|
||||
cat ./report.txt | go-junit-report -set-exit-code > report.xml
|
||||
popd
|
||||
|
||||
132
CHANGELOG.md
132
CHANGELOG.md
@@ -1,5 +1,137 @@
|
||||
# Change Log
|
||||
|
||||
## v0.37.0
|
||||
|
||||
Released on 2024-01-30
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- The deprecated `rate-limiter` mechanism is removed as it is no longer used.
|
||||
- the deprecated `outputs.rate` Falco config is removed.
|
||||
- the deprecated `outputs.max_burst` Falco config is removed.
|
||||
- The deprecated `--userspace` CLI option is removed as it is no longer used.
|
||||
- The `falco-driver-loader` script will be removed and embedded into falcoctl. The new falcoctl driven implementation will drop:
|
||||
- `--source-only` CLI option.
|
||||
- `BPF_USE_LOCAL_KERNEL_SOURCES` environment variable.
|
||||
- `DRIVER_CURL_OPTIONS` environment variable.
|
||||
- `FALCO_BPF_PROBE` environment variable is not used by the new falcoctl driver loader, since it is already deprecated and will be removed in the next major version.
|
||||
|
||||
Some env vars were renamed:
|
||||
- `DRIVERS_REPO` env variable has been replaced by `FALCOCTL_DRIVER_NAME` or `--name` command line argument for `falcoctl driver` command
|
||||
- `DRIVERS_NAME` env variable has been replaced by `FALCOCTL_DRIVER_REPOS`, or `--repo` command line argument for `falcoctl driver` command
|
||||
- `DRIVER_KERNEL_RELEASE` env variable has been replaced by `--kernelrelease` command line argument for `falcoctl driver install` command
|
||||
- `DRIVER_KERNEL_VERSION` env variable has been replaced by `--kernelversion` command line argument for `falcoctl driver install` command
|
||||
- `DRIVER_INSECURE_DOWNLOAD` env variable has been replaced by `--http-insecure` command line argument for `falcoctl driver install` command
|
||||
- Remove `-K/-k` options from Falco in favor of the new `k8smeta` plugin.
|
||||
- Drop plugins shipped with Falco since plugins are now be managed by falcoctl.
|
||||
- Falco 0.37.0 allows environment variables to be expanded even if they are part of a string. This introduces small breaking changes:
|
||||
- Previously, environment variables used in YAML that were empty or defined as `“”` would be expanded to the default value. This was not consistent with the way YAML was handled in other cases, where we only returned the default values if the node was not defined. Now expanded env vars retain the same behavior of all other variables.
|
||||
- Falco 0.37.0 will return default value for nodes that cannot be parsed to chosen type.
|
||||
- `program_output` command will be env-expanded at init time, instead of letting `popen` and thus the `sh` shell expand it. This is technically a breaking change even if no behavioral change is expected. Also, you can avoid env var expansion by using `${{FOO}}` instead of `${FOO}`. It will resolve to `${FOO}` and won't be resolved to the env var value.
|
||||
|
||||
### Major Changes
|
||||
|
||||
* new!: dropped falco-driver-loader script in favor of new falcoctl driver command [[#2905](https://github.com/falcosecurity/falco/pull/2905)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* update!: bump libs to latest and deprecation of k8s metadata options and configs [[#2914](https://github.com/falcosecurity/falco/pull/2914)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* cleanup(falco)!: remove `outputs.rate` and `outputs.max_burst` from Falco config [[#2841](https://github.com/falcosecurity/falco/pull/2841)] - [@Andreagit97](https://github.com/Andreagit97)
|
||||
* cleanup(falco)!: remove `--userspace` support [[#2839](https://github.com/falcosecurity/falco/pull/2839)] - [@Andreagit97](https://github.com/Andreagit97)
|
||||
* new(engine): add selective overrides for Falco rules [[#2981](https://github.com/falcosecurity/falco/pull/2981)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* feat(userspace/falco): falco administrators can now configure the http output to compress the data sent as well as enable keep alive for the connection. Two new fields (compress_uploads and keep_alive) in the http_output block of the `falco.yaml` file can be used for that purpose. Both are disabled by default. [[#2974](https://github.com/falcosecurity/falco/pull/2974)] - [@sgaist](https://github.com/sgaist)
|
||||
* new(userspace): support env variable expansion in all yaml, even inside strings. [[#2918](https://github.com/falcosecurity/falco/pull/2918)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* new(scripts): add a way to enforce driver kind and falcoctl enablement when installing Falco from packages and dialog is not present. [[#2773](https://github.com/falcosecurity/falco/pull/2773)] - [@vjjmiras](https://github.com/vjjmiras)
|
||||
* new(falco): print system info when Falco starts [[#2927](https://github.com/falcosecurity/falco/pull/2927)] - [@Andreagit97](https://github.com/Andreagit97)
|
||||
* new: driver selection in falco.yaml [[#2413](https://github.com/falcosecurity/falco/pull/2413)] - [@therealbobo](https://github.com/therealbobo)
|
||||
* new(build): enable compilation on win32 and macOS. [[#2889](https://github.com/falcosecurity/falco/pull/2889)] - [@therealbobo](https://github.com/therealbobo)
|
||||
* feat(userspace/falco): falco administrators can now configure the address on which the webserver listen using the new listen_address field in the webserver block of the `falco.yaml` file. [[#2890](https://github.com/falcosecurity/falco/pull/2890)] - [@sgaist](https://github.com/sgaist)
|
||||
|
||||
### Minor Changes
|
||||
|
||||
* update(userspace/falco): add `engine_version_semver` key in `/versions` endpoint [[#2899](https://github.com/falcosecurity/falco/pull/2899)] - [@loresuso](https://github.com/loresuso)
|
||||
* update: default ruleset upgrade to version 3.0 [[#3034](https://github.com/falcosecurity/falco/pull/3034)] - [@leogr](https://github.com/leogr)
|
||||
* update!(config): soft deprecation of drop stats counters in `syscall_event_drops` [[#3015](https://github.com/falcosecurity/falco/pull/3015)] - [@incertum](https://github.com/incertum)
|
||||
* update(cmake): bumped falcoctl tool to v0.7.1. [[#3030](https://github.com/falcosecurity/falco/pull/3030)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* update(rule_loader): deprecate the `append` flag in Falco rules [[#2992](https://github.com/falcosecurity/falco/pull/2992)] - [@Andreagit97](https://github.com/Andreagit97)
|
||||
* cleanup!(cmake): drop bundled plugins in Falco [[#2997](https://github.com/falcosecurity/falco/pull/2997)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* update(config): clarify deprecation notices + list all env vars [[#2988](https://github.com/falcosecurity/falco/pull/2988)] - [@incertum](https://github.com/incertum)
|
||||
* update: now the `watch_config_files` config option monitors file/directory moving and deletion, too [[#2965](https://github.com/falcosecurity/falco/pull/2965)] - [@NitroCao](https://github.com/NitroCao)
|
||||
* update(userspace): enhancements in rule description feature [[#2934](https://github.com/falcosecurity/falco/pull/2934)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* update(userspace/falco): add libsinsp state metrics option [[#2883](https://github.com/falcosecurity/falco/pull/2883)] - [@incertum](https://github.com/incertum)
|
||||
* update(doc): Add Thought Machine as adopters [[#2919](https://github.com/falcosecurity/falco/pull/2919)] - [@RichardoC](https://github.com/RichardoC)
|
||||
* update(docs): add Wireshark/Logray as adopter [[#2867](https://github.com/falcosecurity/falco/pull/2867)] - [@geraldcombs](https://github.com/geraldcombs)
|
||||
* update: engine_version in semver representation [[#2838](https://github.com/falcosecurity/falco/pull/2838)] - [@loresuso](https://github.com/loresuso)
|
||||
* update(userspace/engine): modularize rule compiler, fix and enrich rule descriptions [[#2817](https://github.com/falcosecurity/falco/pull/2817)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix(userspace/metric): minor fixes in new libsinsp state metrics handling [[#3033](https://github.com/falcosecurity/falco/pull/3033)] - [@incertum](https://github.com/incertum)
|
||||
* fix(userspace/engine): avoid storing escaped strings in engine defs [[#3028](https://github.com/falcosecurity/falco/pull/3028)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* fix(userspace/engine): cache latest rules compilation output [[#2900](https://github.com/falcosecurity/falco/pull/2900)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* fix(userspace/engine): solve description of macro-only rules [[#2898](https://github.com/falcosecurity/falco/pull/2898)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* fix(userspace/engine): fix memory leak [[#2877](https://github.com/falcosecurity/falco/pull/2877)] - [@therealbobo](https://github.com/therealbobo)
|
||||
|
||||
### Non user-facing changes
|
||||
|
||||
* fix: nlohmann_json lib include path [[#3032](https://github.com/falcosecurity/falco/pull/3032)] - [@federico-sysdig](https://github.com/federico-sysdig)
|
||||
* chore: bump falco rules [[#3021](https://github.com/falcosecurity/falco/pull/3021)] - [@Andreagit97](https://github.com/Andreagit97)
|
||||
* chore: bump Falco to libs 0.14.1 [[#3020](https://github.com/falcosecurity/falco/pull/3020)] - [@Andreagit97](https://github.com/Andreagit97)
|
||||
* chore(build): remove outdated development libs [[#2946](https://github.com/falcosecurity/falco/pull/2946)] - [@federico-sysdig](https://github.com/federico-sysdig)
|
||||
* chore(falco): bump Falco to `000d576` libs commit [[#2944](https://github.com/falcosecurity/falco/pull/2944)] - [@Andreagit97](https://github.com/Andreagit97)
|
||||
* fix(gha): update rpmsign [[#2856](https://github.com/falcosecurity/falco/pull/2856)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* build(deps): Bump submodules/falcosecurity-rules from `424b258` to `1221b9e` [[#3000](https://github.com/falcosecurity/falco/pull/3000)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* build(deps): Bump submodules/falcosecurity-rules from `2ac430b` to `c39d31a` [[#3019](https://github.com/falcosecurity/falco/pull/3019)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* cleanup(falco.yaml): rename `none` in `nodriver` [[#3012](https://github.com/falcosecurity/falco/pull/3012)] - [@Andreagit97](https://github.com/Andreagit97)
|
||||
* update(config): graduate outputs_queue to stable [[#3016](https://github.com/falcosecurity/falco/pull/3016)] - [@incertum](https://github.com/incertum)
|
||||
* update(cmake): bump falcoctl to v0.7.0. [[#3009](https://github.com/falcosecurity/falco/pull/3009)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* build(deps): Bump submodules/falcosecurity-rules from `1221b9e` to `2ac430b` [[#3007](https://github.com/falcosecurity/falco/pull/3007)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* chore(ci): bumped rn2md to latest master. [[#3006](https://github.com/falcosecurity/falco/pull/3006)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* chore: bump Falco to latest libs [[#3002](https://github.com/falcosecurity/falco/pull/3002)] - [@Andreagit97](https://github.com/Andreagit97)
|
||||
* chore: bump driver version [[#2998](https://github.com/falcosecurity/falco/pull/2998)] - [@Andreagit97](https://github.com/Andreagit97)
|
||||
* Add addl source related methods [[#2939](https://github.com/falcosecurity/falco/pull/2939)] - [@mstemm](https://github.com/mstemm)
|
||||
* build(deps): Bump submodules/falcosecurity-rules from `cd33bc3` to `424b258` [[#2993](https://github.com/falcosecurity/falco/pull/2993)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* cleanup(engine): clarify deprecation notice for engines [[#2987](https://github.com/falcosecurity/falco/pull/2987)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* update(cmake): bumped falcoctl to v0.7.0-rc1. [[#2983](https://github.com/falcosecurity/falco/pull/2983)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* chore(ci): revert #2961. [[#2984](https://github.com/falcosecurity/falco/pull/2984)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* build(deps): Bump submodules/falcosecurity-testing from `930170b` to `9b9630e` [[#2980](https://github.com/falcosecurity/falco/pull/2980)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* chore: bump Falco to latest libs [[#2977](https://github.com/falcosecurity/falco/pull/2977)] - [@Andreagit97](https://github.com/Andreagit97)
|
||||
* build(deps): Bump submodules/falcosecurity-rules from `262f569` to `cd33bc3` [[#2976](https://github.com/falcosecurity/falco/pull/2976)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* Allow enabling rules by ruleset id in addition to name [[#2920](https://github.com/falcosecurity/falco/pull/2920)] - [@mstemm](https://github.com/mstemm)
|
||||
* chore(ci): enable aarch64 falco driver loader tests. [[#2961](https://github.com/falcosecurity/falco/pull/2961)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* chore(unit_tests): added more tests for yaml env vars expansion. [[#2972](https://github.com/falcosecurity/falco/pull/2972)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* chore(falco.yaml): use HOME env var for ebpf probe path. [[#2971](https://github.com/falcosecurity/falco/pull/2971)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* chore: bump falco to latest libs [[#2970](https://github.com/falcosecurity/falco/pull/2970)] - [@Andreagit97](https://github.com/Andreagit97)
|
||||
* build(deps): Bump submodules/falcosecurity-rules from `dd38952` to `262f569` [[#2969](https://github.com/falcosecurity/falco/pull/2969)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* update(readme): add actuated.dev badge [[#2967](https://github.com/falcosecurity/falco/pull/2967)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* chore(cmake,docker): bumped falcoctl to v0.7.0-beta5. [[#2968](https://github.com/falcosecurity/falco/pull/2968)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* build(deps): Bump submodules/falcosecurity-rules from `64e2adb` to `dd38952` [[#2959](https://github.com/falcosecurity/falco/pull/2959)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* fix(docker): small fixes in docker entrypoints for new driver loader. [[#2966](https://github.com/falcosecurity/falco/pull/2966)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* chore(build): allow usage of non-bundled nlohmann-json [[#2947](https://github.com/falcosecurity/falco/pull/2947)] - [@federico-sysdig](https://github.com/federico-sysdig)
|
||||
* update(ci): enable actuated.dev [[#2945](https://github.com/falcosecurity/falco/pull/2945)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* cleanup: fix several warnings from a Clang build [[#2948](https://github.com/falcosecurity/falco/pull/2948)] - [@federico-sysdig](https://github.com/federico-sysdig)
|
||||
* chore(docker/falco): add back some deps to falco docker image. [[#2932](https://github.com/falcosecurity/falco/pull/2932)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* build(deps): Bump submodules/falcosecurity-testing from `92c313f` to `5248e6d` [[#2937](https://github.com/falcosecurity/falco/pull/2937)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* build(deps): Bump submodules/falcosecurity-rules from `e206c1a` to `8f0520f` [[#2904](https://github.com/falcosecurity/falco/pull/2904)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* cleanup(falco): remove decode_uri as it is no longer used [[#2933](https://github.com/falcosecurity/falco/pull/2933)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* update(engine): port decode_uri in falco engine [[#2912](https://github.com/falcosecurity/falco/pull/2912)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* chore(falco): update to libs on nov 28th [[#2929](https://github.com/falcosecurity/falco/pull/2929)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* cleanup(falco): remove `init` in the configuration constructor [[#2917](https://github.com/falcosecurity/falco/pull/2917)] - [@Andreagit97](https://github.com/Andreagit97)
|
||||
* build(deps): Bump submodules/falcosecurity-rules from `8f0520f` to `64e2adb` [[#2908](https://github.com/falcosecurity/falco/pull/2908)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* cleanup(userspace/engine): remove legacy k8saudit implementation [[#2913](https://github.com/falcosecurity/falco/pull/2913)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* fix(gha): disable branch protection rule trigger for scorecard [[#2911](https://github.com/falcosecurity/falco/pull/2911)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* chore(gha): set cosign-installer to v3.1.2 [[#2901](https://github.com/falcosecurity/falco/pull/2901)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* new(docs): sync changelog for 0.36.2. [[#2894](https://github.com/falcosecurity/falco/pull/2894)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* Run OpenSSF Scorecard in pipeline [[#2888](https://github.com/falcosecurity/falco/pull/2888)] - [@maxgio92](https://github.com/maxgio92)
|
||||
* cleanup: replace banned.h with semgrep [[#2881](https://github.com/falcosecurity/falco/pull/2881)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* chore(gha): upgrade GitHub actions [[#2876](https://github.com/falcosecurity/falco/pull/2876)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* build(deps): Bump submodules/falcosecurity-rules from `a22d0d7` to `e206c1a` [[#2865](https://github.com/falcosecurity/falco/pull/2865)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* build(deps): Bump submodules/falcosecurity-rules from `d119706` to `a22d0d7` [[#2860](https://github.com/falcosecurity/falco/pull/2860)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* fix(gha): use fedora instead of centos 7 for package publishing [[#2854](https://github.com/falcosecurity/falco/pull/2854)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* chore(gha): pin versions to hashes [[#2849](https://github.com/falcosecurity/falco/pull/2849)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* build(deps): Bump submodules/falcosecurity-rules from `c366d5b` to `d119706` [[#2847](https://github.com/falcosecurity/falco/pull/2847)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* new(ci): properly link libs and driver releases linked to a Falco release [[#2846](https://github.com/falcosecurity/falco/pull/2846)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* build(deps): Bump submodules/falcosecurity-rules from `7a7cf24` to `c366d5b` [[#2842](https://github.com/falcosecurity/falco/pull/2842)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* build(deps): Bump submodules/falcosecurity-rules from `77ba57a` to `7a7cf24` [[#2836](https://github.com/falcosecurity/falco/pull/2836)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* chore(ci): bumped rn2md to latest master. [[#2844](https://github.com/falcosecurity/falco/pull/2844)] - [@FedeDP](https://github.com/FedeDP)
|
||||
|
||||
## v0.36.2
|
||||
|
||||
Released on 2023-10-27
|
||||
|
||||
@@ -180,7 +180,6 @@ include(static-analysis)
|
||||
# Shared build variables
|
||||
set(FALCO_SINSP_LIBRARY sinsp)
|
||||
set(FALCO_SHARE_DIR share/falco)
|
||||
set(FALCO_PLUGINS_DIR ${FALCO_SHARE_DIR}/plugins)
|
||||
set(FALCO_ABSOLUTE_SHARE_DIR "${CMAKE_INSTALL_PREFIX}/${FALCO_SHARE_DIR}")
|
||||
set(FALCO_BIN_DIR bin)
|
||||
|
||||
@@ -189,7 +188,6 @@ add_subdirectory(userspace/engine)
|
||||
add_subdirectory(userspace/falco)
|
||||
|
||||
if(NOT WIN32 AND NOT APPLE AND NOT EMSCRIPTEN AND NOT MUSL_OPTIMIZED_BUILD)
|
||||
include(plugins)
|
||||
include(falcoctl)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -44,11 +44,6 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") # only Linux has drivers
|
||||
"${CMAKE_CURRENT_BINARY_DIR};${DRIVER_COMPONENT_NAME};${DRIVER_COMPONENT_NAME};/")
|
||||
endif()
|
||||
|
||||
if(NOT WIN32 AND NOT APPLE AND NOT EMSCRIPTEN AND NOT MUSL_OPTIMIZED_BUILD) # static builds do not have plugins
|
||||
list(APPEND CPACK_INSTALL_CMAKE_PROJECTS
|
||||
"${CMAKE_CURRENT_BINARY_DIR};${PLUGINS_COMPONENT_NAME};${PLUGINS_COMPONENT_NAME};/")
|
||||
endif()
|
||||
|
||||
if(NOT CPACK_GENERATOR)
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
set(CPACK_GENERATOR DEB RPM TGZ)
|
||||
|
||||
@@ -34,8 +34,8 @@ else()
|
||||
# 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 "ea23169c13df2ce5d8ba7d6faecdaa65f36140cb")
|
||||
set(DRIVER_CHECKSUM "SHA256=c84c80a9a2241667e1c0be7a611f071c9b0264ac81b98103d2272b939337d02f")
|
||||
set(DRIVER_VERSION "7.0.0+driver")
|
||||
set(DRIVER_CHECKSUM "SHA256=9f2a0f14827c0d9d1c3d1abe45b8f074dea531ebeca9859363a92f0d2475757e")
|
||||
endif()
|
||||
|
||||
# cd /path/to/build && cmake /path/to/source
|
||||
|
||||
@@ -16,14 +16,14 @@ include(ExternalProject)
|
||||
|
||||
string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} FALCOCTL_SYSTEM_NAME)
|
||||
|
||||
set(FALCOCTL_VERSION "0.7.0-beta5")
|
||||
set(FALCOCTL_VERSION "0.7.1")
|
||||
|
||||
if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
set(FALCOCTL_SYSTEM_PROC_GO "amd64")
|
||||
set(FALCOCTL_HASH "e08cdd3bed96bda2e45f54d86aec0f1ad986963ff30624578283b218829df225")
|
||||
set(FALCOCTL_HASH "f142507c0e2b1e7dc03fd0b1ec36b479eb171f1f58c17f90d2d8edeb00668ef5")
|
||||
else() # aarch64
|
||||
set(FALCOCTL_SYSTEM_PROC_GO "arm64")
|
||||
set(FALCOCTL_HASH "582b6b73f77cfdf66dbcddadaa1073fa1802f24bd1670c1cf578e524fd3e8486")
|
||||
set(FALCOCTL_HASH "93e4800b68e21057da82c8c7aafa0970598594d62cd9929ebb9b38a9c02159a6")
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(
|
||||
|
||||
@@ -35,8 +35,8 @@ else()
|
||||
# In case you want to test against another falcosecurity/libs version (or branch, or commit) just pass the variable -
|
||||
# ie., `cmake -DFALCOSECURITY_LIBS_VERSION=dev ..`
|
||||
if(NOT FALCOSECURITY_LIBS_VERSION)
|
||||
set(FALCOSECURITY_LIBS_VERSION "ea23169c13df2ce5d8ba7d6faecdaa65f36140cb")
|
||||
set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=c84c80a9a2241667e1c0be7a611f071c9b0264ac81b98103d2272b939337d02f")
|
||||
set(FALCOSECURITY_LIBS_VERSION "0.14.2")
|
||||
set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=b4ae7bbf3ad031deee4a808145f9fd64b71c537406cc5a92f512823b2e52cdd5")
|
||||
endif()
|
||||
|
||||
# cd /path/to/build && cmake /path/to/source
|
||||
|
||||
@@ -19,8 +19,9 @@ if(USE_BUNDLED_NLOHMANN_JSON)
|
||||
CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/njson-prefix -DJSON_BuildTests=OFF -DBUILD_TESTING=OFF
|
||||
)
|
||||
|
||||
set(nlohmann_json_DIR ${PROJECT_BINARY_DIR}/njson-prefix/include)
|
||||
set(nlohmann_json_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/njson-prefix/include)
|
||||
else()
|
||||
find_package(nlohmann_json CONFIG REQUIRED)
|
||||
get_target_property(nlohmann_json_INCLUDE_DIRS nlohmann_json::nlohmann_json INTERFACE_INCLUDE_DIRECTORIES)
|
||||
add_custom_target(njson)
|
||||
endif()
|
||||
|
||||
@@ -1,98 +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(ExternalProject)
|
||||
|
||||
# 'stable' or 'dev'
|
||||
set(PLUGINS_DOWNLOAD_BUCKET "stable")
|
||||
|
||||
string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} PLUGINS_SYSTEM_NAME)
|
||||
|
||||
if(NOT DEFINED PLUGINS_COMPONENT_NAME)
|
||||
set(PLUGINS_COMPONENT_NAME "${CMAKE_PROJECT_NAME}-plugins")
|
||||
endif()
|
||||
|
||||
# k8saudit
|
||||
set(PLUGIN_K8S_AUDIT_VERSION "0.6.1")
|
||||
if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
set(PLUGIN_K8S_AUDIT_HASH "e2908ebf2c03feecd26307ceab55aec9cae1cbc63d6aa05e147d8786e7670fb0")
|
||||
else() # aarch64
|
||||
set(PLUGIN_K8S_AUDIT_HASH "8987a995fa09518aebc488ba549448166d605596c2d6478c10415a9d9f5f05dd")
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(
|
||||
k8saudit-plugin
|
||||
URL "https://download.falco.org/plugins/${PLUGINS_DOWNLOAD_BUCKET}/k8saudit-${PLUGIN_K8S_AUDIT_VERSION}-${PLUGINS_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR}.tar.gz"
|
||||
URL_HASH "SHA256=${PLUGIN_K8S_AUDIT_HASH}"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
|
||||
install(FILES "${PROJECT_BINARY_DIR}/k8saudit-plugin-prefix/src/k8saudit-plugin/libk8saudit.so" DESTINATION "${FALCO_PLUGINS_DIR}" COMPONENT "${PLUGINS_COMPONENT_NAME}")
|
||||
|
||||
ExternalProject_Add(
|
||||
k8saudit-rules
|
||||
URL "https://download.falco.org/plugins/${PLUGINS_DOWNLOAD_BUCKET}/k8saudit-rules-${PLUGIN_K8S_AUDIT_VERSION}.tar.gz"
|
||||
URL_HASH "SHA256=36321b3f1d7969926073a4d40bbbb7b4b28805b038c067f140795210ab641161"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
|
||||
install(FILES "${PROJECT_BINARY_DIR}/k8saudit-rules-prefix/src/k8saudit-rules/k8s_audit_rules.yaml" DESTINATION "${FALCO_ETC_DIR}" COMPONENT "${PLUGINS_COMPONENT_NAME}")
|
||||
|
||||
# cloudtrail
|
||||
set(PLUGIN_CLOUDTRAIL_VERSION "0.9.0")
|
||||
if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
set(PLUGIN_CLOUDTRAIL_HASH "c8dc8ea5337aa9475042e6441320a5188bbf76977e3a69dd34a49a6251f8e9ad")
|
||||
else() # aarch64
|
||||
set(PLUGIN_CLOUDTRAIL_HASH "bea12e81409c3df5698f7ab6a740ee9698b9dd1275b5985810daf70ac505c810")
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(
|
||||
cloudtrail-plugin
|
||||
URL "https://download.falco.org/plugins/${PLUGINS_DOWNLOAD_BUCKET}/cloudtrail-${PLUGIN_CLOUDTRAIL_VERSION}-${PLUGINS_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR}.tar.gz"
|
||||
URL_HASH "SHA256=${PLUGIN_CLOUDTRAIL_HASH}"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
|
||||
install(FILES "${PROJECT_BINARY_DIR}/cloudtrail-plugin-prefix/src/cloudtrail-plugin/libcloudtrail.so" DESTINATION "${FALCO_PLUGINS_DIR}" COMPONENT "${PLUGINS_COMPONENT_NAME}")
|
||||
|
||||
ExternalProject_Add(
|
||||
cloudtrail-rules
|
||||
URL "https://download.falco.org/plugins/${PLUGINS_DOWNLOAD_BUCKET}/cloudtrail-rules-${PLUGIN_CLOUDTRAIL_VERSION}.tar.gz"
|
||||
URL_HASH "SHA256=b0c2b6c78d61cc3e7fb66445bcd8f763d15eb4a24f518385377e704aacec6b3f"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
|
||||
install(FILES "${PROJECT_BINARY_DIR}/cloudtrail-rules-prefix/src/cloudtrail-rules/aws_cloudtrail_rules.yaml" DESTINATION "${FALCO_ETC_DIR}" COMPONENT "${PLUGINS_COMPONENT_NAME}")
|
||||
|
||||
# json
|
||||
set(PLUGIN_JSON_VERSION "0.7.1")
|
||||
if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
set(PLUGIN_JSON_HASH "3177fd667b384df2ffd2ae3260bda867c407c09d3fbcae841af204b82c1341c1")
|
||||
else() # aarch64
|
||||
set(PLUGIN_JSON_HASH "3b5d0a9190bfd08e21915f997f88ca314f2027564a022eb88eef80ff4e2c77fa")
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(
|
||||
json-plugin
|
||||
URL "https://download.falco.org/plugins/${PLUGINS_DOWNLOAD_BUCKET}/json-${PLUGIN_JSON_VERSION}-${PLUGINS_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR}.tar.gz"
|
||||
URL_HASH "SHA256=${PLUGIN_JSON_HASH}"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
|
||||
install(FILES "${PROJECT_BINARY_DIR}/json-plugin-prefix/src/json-plugin/libjson.so" DESTINATION "${FALCO_PLUGINS_DIR}" COMPONENT "${PLUGINS_COMPONENT_NAME}")
|
||||
@@ -1,6 +1,6 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright (C) 2023 The Falco Authors.
|
||||
# Copyright (C) 2024 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
|
||||
@@ -16,8 +16,8 @@ include(GNUInstallDirs)
|
||||
include(ExternalProject)
|
||||
|
||||
# falco_rules.yaml
|
||||
set(FALCOSECURITY_RULES_FALCO_VERSION "falco-rules-2.0.0")
|
||||
set(FALCOSECURITY_RULES_FALCO_CHECKSUM "SHA256=48b6c5ae7a619a320eb51dbe036d1bc78622ab692956c9493390678874757b32")
|
||||
set(FALCOSECURITY_RULES_FALCO_VERSION "falco-rules-3.0.0")
|
||||
set(FALCOSECURITY_RULES_FALCO_CHECKSUM "SHA256=2e91799fee49c2daf58fb482e47410a21433eb116e02cde18206f7af87449ddb")
|
||||
set(FALCOSECURITY_RULES_FALCO_PATH "${PROJECT_BINARY_DIR}/falcosecurity-rules-falco-prefix/src/falcosecurity-rules-falco/falco_rules.yaml")
|
||||
ExternalProject_Add(
|
||||
falcosecurity-rules-falco
|
||||
|
||||
50
falco.yaml
50
falco.yaml
@@ -41,7 +41,6 @@
|
||||
# json_include_output_property
|
||||
# json_include_tags_property
|
||||
# buffered_outputs
|
||||
# outputs (throttling)
|
||||
# rule_matching
|
||||
# outputs_queue
|
||||
# Falco outputs channels
|
||||
@@ -62,13 +61,13 @@
|
||||
# Falco logging / alerting / metrics related to software functioning (advanced)
|
||||
# output_timeout
|
||||
# syscall_event_timeouts
|
||||
# syscall_event_drops
|
||||
# syscall_event_drops -> [CHANGE NOTICE] Automatic notifications will be simplified in Falco 0.38! If you depend on the detailed drop counters payload, use 'metrics.output_rule' along with 'metrics.kernel_event_counters_enabled' instead
|
||||
# metrics
|
||||
# Falco performance tuning (advanced)
|
||||
# syscall_buf_size_preset [DEPRECATED]
|
||||
# syscall_drop_failed_exit [DEPRECATED]
|
||||
# syscall_buf_size_preset [DEPRECATED] -> Replaced by `engine.<driver>.buf_size_preset` starting Falco 0.38!
|
||||
# syscall_drop_failed_exit [DEPRECATED] -> Replaced by `engine.<driver>.drop_failed_exit` starting Falco 0.38!
|
||||
# base_syscalls
|
||||
# modern_bpf.cpus_for_each_syscall_buffer [DEPRECATED]
|
||||
# modern_bpf.cpus_for_each_syscall_buffer [DEPRECATED] -> Replaced by `engine.modern_ebpf.cpus_for_each_buffer` starting Falco 0.38!
|
||||
|
||||
|
||||
################################
|
||||
@@ -80,9 +79,9 @@
|
||||
# configuration options from this config file as command-line arguments by using
|
||||
# the `-o` flag followed by the option name and value. In the following example,
|
||||
# three config options (`json_output`, `log_level`, and
|
||||
# `modern_bpf.cpus_for_each_syscall_buffer`) are passed as command-line
|
||||
# `engine.kind`) are passed as command-line
|
||||
# arguments with their corresponding values: falco -o "json_output=true"
|
||||
# -o "log_level=debug" -o "modern_bpf.cpus_for_each_syscall_buffer=4"
|
||||
# -o "log_level=debug" -o "engine.kind=kmod"
|
||||
# Please note that command-line arguments take precedence over the options
|
||||
# specified in this config file.
|
||||
|
||||
@@ -93,16 +92,32 @@
|
||||
|
||||
# Customize Falco settings using environment variables:
|
||||
#
|
||||
# - "HOST_ROOT": Specifies the prefix to the underlying host `/proc` filesystem
|
||||
# - HOST_ROOT: Specifies the prefix to the underlying host `/proc` filesystem
|
||||
# when deploying Falco over a container with read-only host mounts instead of
|
||||
# directly on the host. Defaults to "/host".
|
||||
# - "FALCO_BPF_PROBE": DEPRECATED. Specify a custom path to the BPF object code file (`bpf`
|
||||
#
|
||||
# - !!! [DEPRECATED] FALCO_BPF_PROBE: Specify a custom path to the BPF object code file (`bpf`
|
||||
# driver). This is not needed for the modern_bpf driver.
|
||||
# - "FALCO_HOSTNAME": Customize the hostname output field logged by Falco by
|
||||
# -> Replaced by `engine.kind: ebpf` and `engine.ebpf` starting Falco 0.38!
|
||||
#
|
||||
# - FALCO_HOSTNAME: Customize the hostname output field logged by Falco by
|
||||
# setting the "FALCO_HOSTNAME" environment variable.
|
||||
# - "FALCO_CGROUP_MEM_PATH": Specifies the file path holding the container
|
||||
#
|
||||
# - FALCO_CGROUP_MEM_PATH: Specifies the file path holding the container
|
||||
# memory usage metric for the `metrics` feature. Defaults to
|
||||
# "/sys/fs/cgroup/memory/memory.usage_in_bytes" (Kubernetes).
|
||||
#
|
||||
# - SKIP_DRIVER_LOADER is used by the Falco fat image to skip the driver loading part.
|
||||
#
|
||||
# - FALCO_FRONTEND is useful when set to noninteractive to skip the dialog choice during
|
||||
# the installation of Falco deb/rpm packages. This setting is somewhat similar to DEBIAN_FRONTEND.
|
||||
#
|
||||
# - FALCO_DRIVER_CHOICE is useful when set to kmod, ebpf, or modern_ebpf (matching the names
|
||||
# used in engine.kind in the Falco config) during the installation of Falco deb/rpm packages.
|
||||
# It skips the dialog choice but retains the driver configuration.
|
||||
#
|
||||
# - FALCOCTL_ENABLED is useful when set to 'no' during the installation of Falco deb/rpm packages,
|
||||
# disabling the automatic artifacts followed by falcoctl.
|
||||
|
||||
|
||||
#####################
|
||||
@@ -164,7 +179,8 @@ rules_file:
|
||||
# - `modern_ebpf`: Modern eBPF (CO-RE eBPF probe)
|
||||
# - `gvisor`: gVisor (gVisor sandbox)
|
||||
# - `replay`: Replay a scap trace file
|
||||
# - `none`: No event producer loaded, useful to run with plugins.
|
||||
# - `nodriver`: No driver is injected into the system.
|
||||
# This is useful to debug and to run plugins with 'syscall' source.
|
||||
#
|
||||
# Only one engine can be specified in the `kind` key.
|
||||
# Moreover, for each engine multiple options might be available,
|
||||
@@ -482,7 +498,7 @@ buffered_outputs: false
|
||||
# deploying it in production.
|
||||
rule_matching: first
|
||||
|
||||
# [Experimental] `outputs_queue`
|
||||
# [Stable] `outputs_queue`
|
||||
#
|
||||
# Falco utilizes tbb::concurrent_bounded_queue for handling outputs, and this parameter
|
||||
# allows you to customize the queue capacity. Please refer to the official documentation:
|
||||
@@ -777,7 +793,7 @@ output_timeout: 2000
|
||||
syscall_event_timeouts:
|
||||
max_consecutives: 1000
|
||||
|
||||
# [Stable] `syscall_event_drops`
|
||||
# [Stable] `syscall_event_drops` -> [CHANGE NOTICE] Automatic notifications will be simplified in Falco 0.38! If you depend on the detailed drop counters payload, use 'metrics.output_rule' along with 'metrics.kernel_event_counters_enabled' instead
|
||||
#
|
||||
# Generates "Falco internal: syscall event drop" rule output when `priority=debug` at minimum
|
||||
#
|
||||
@@ -977,7 +993,7 @@ metrics:
|
||||
# Falco performance tuning (advanced) #
|
||||
#######################################
|
||||
|
||||
# [DEPRECATED] `syscall_buf_size_preset`
|
||||
# [DEPRECATED] `syscall_buf_size_preset` -> Replaced by `engine.<driver>.buf_size_preset` starting Falco 0.38!
|
||||
#
|
||||
# Deprecated in favor of engine.{kmod,ebpf,modern_ebpf}.buf_size_preset.
|
||||
# This config is evaluated only if the default `engine` config block is not changed,
|
||||
@@ -1033,7 +1049,7 @@ metrics:
|
||||
# if the default size is not suitable for your use case.
|
||||
syscall_buf_size_preset: 4
|
||||
|
||||
# [DEPRECATED] `syscall_drop_failed_exit`
|
||||
# [DEPRECATED] `syscall_drop_failed_exit` -> Replaced by `engine.<driver>.drop_failed_exit` starting Falco 0.38!
|
||||
#
|
||||
# Deprecated in favor of engine.{kmod,ebpf,modern_ebpf}.drop_failed_exit.
|
||||
# This config is evaluated only if the default `engine` config block is not changed,
|
||||
@@ -1162,7 +1178,7 @@ base_syscalls:
|
||||
custom_set: []
|
||||
repair: false
|
||||
|
||||
# [DEPRECATED] `modern_bpf.cpus_for_each_syscall_buffer`, modern_bpf only
|
||||
# [DEPRECATED] `modern_bpf.cpus_for_each_syscall_buffer`, modern_bpf only -> Replaced by `engine.modern_ebpf.cpus_for_each_buffer` starting Falco 0.38!
|
||||
#
|
||||
# Deprecated in favor of engine.modern_ebpf.cpus_for_each_buffer.
|
||||
# This config is evaluated only if the default `engine` config block is not changed,
|
||||
|
||||
Submodule submodules/falcosecurity-rules updated: 262f56986e...c39d31a0bc
Submodule submodules/falcosecurity-testing updated: 930170bb0b...ae3950acf0
89
unit_tests/engine/test_add_source.cpp
Normal file
89
unit_tests/engine/test_add_source.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
|
||||
#include <falco_engine.h>
|
||||
#include <evttype_index_ruleset.h>
|
||||
|
||||
static std::string syscall_source_name = "syscall";
|
||||
|
||||
// A variant of evttype_index_ruleset_factory that uses a singleton
|
||||
// for the underlying ruleset. This allows testing of
|
||||
// ruleset_for_source
|
||||
|
||||
namespace
|
||||
{
|
||||
class test_ruleset_factory : public evttype_index_ruleset_factory
|
||||
{
|
||||
public:
|
||||
test_ruleset_factory(std::shared_ptr<gen_event_filter_factory> factory):
|
||||
evttype_index_ruleset_factory(factory)
|
||||
{
|
||||
ruleset = evttype_index_ruleset_factory::new_ruleset();
|
||||
}
|
||||
|
||||
virtual ~test_ruleset_factory() = default;
|
||||
|
||||
inline std::shared_ptr<filter_ruleset> new_ruleset() override
|
||||
{
|
||||
return ruleset;
|
||||
}
|
||||
|
||||
std::shared_ptr<filter_ruleset> ruleset;
|
||||
};
|
||||
}; // namespace
|
||||
|
||||
TEST(AddSource, basic)
|
||||
{
|
||||
falco_engine engine;
|
||||
sinsp inspector;
|
||||
sinsp_filter_check_list filterchecks;
|
||||
|
||||
auto filter_factory = std::shared_ptr<gen_event_filter_factory>(
|
||||
new sinsp_filter_factory(&inspector, filterchecks));
|
||||
auto formatter_factory = std::shared_ptr<gen_event_formatter_factory>(
|
||||
new sinsp_evt_formatter_factory(&inspector, filterchecks));
|
||||
test_ruleset_factory *test_factory = new test_ruleset_factory(filter_factory);
|
||||
auto ruleset_factory = std::shared_ptr<filter_ruleset_factory>(test_factory);
|
||||
|
||||
falco_source syscall_source;
|
||||
syscall_source.name = syscall_source_name;
|
||||
syscall_source.ruleset = ruleset_factory->new_ruleset();
|
||||
syscall_source.ruleset_factory = ruleset_factory;
|
||||
syscall_source.filter_factory = filter_factory;
|
||||
syscall_source.formatter_factory = formatter_factory;
|
||||
|
||||
size_t source_idx = engine.add_source(syscall_source_name,
|
||||
filter_factory,
|
||||
formatter_factory,
|
||||
ruleset_factory);
|
||||
|
||||
ASSERT_TRUE(engine.is_source_valid(syscall_source_name));
|
||||
|
||||
ASSERT_EQ(engine.filter_factory_for_source(syscall_source_name), filter_factory);
|
||||
ASSERT_EQ(engine.filter_factory_for_source(source_idx), filter_factory);
|
||||
|
||||
ASSERT_EQ(engine.formatter_factory_for_source(syscall_source_name), formatter_factory);
|
||||
ASSERT_EQ(engine.formatter_factory_for_source(source_idx), formatter_factory);
|
||||
|
||||
ASSERT_EQ(engine.ruleset_factory_for_source(syscall_source_name), ruleset_factory);
|
||||
ASSERT_EQ(engine.ruleset_factory_for_source(source_idx), ruleset_factory);
|
||||
|
||||
ASSERT_EQ(engine.ruleset_for_source(syscall_source_name), test_factory->ruleset);
|
||||
ASSERT_EQ(engine.ruleset_for_source(source_idx), test_factory->ruleset);
|
||||
}
|
||||
970
unit_tests/engine/test_rule_loader.cpp
Normal file
970
unit_tests/engine/test_rule_loader.cpp
Normal file
@@ -0,0 +1,970 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "falco_engine.h"
|
||||
#include "rule_loader_reader.h"
|
||||
#include "rule_loader_compiler.h"
|
||||
#include "rule_loading_messages.h"
|
||||
|
||||
class engine_loader_test : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
m_sample_ruleset = "sample-ruleset";
|
||||
m_sample_source = falco_common::syscall_source;
|
||||
|
||||
// create a falco engine ready to load the ruleset
|
||||
m_inspector.reset(new sinsp());
|
||||
m_engine.reset(new falco_engine());
|
||||
m_filter_factory = std::shared_ptr<gen_event_filter_factory>(
|
||||
new sinsp_filter_factory(m_inspector.get(), m_filterlist));
|
||||
m_formatter_factory = std::shared_ptr<gen_event_formatter_factory>(
|
||||
new sinsp_evt_formatter_factory(m_inspector.get(), m_filterlist));
|
||||
m_engine->add_source(m_sample_source, m_filter_factory, m_formatter_factory);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool load_rules(std::string rules_content, std::string rules_filename)
|
||||
{
|
||||
bool ret = false;
|
||||
falco::load_result::rules_contents_t rc = {{rules_filename, rules_content}};
|
||||
m_load_result = m_engine->load_rules(rules_content, rules_filename);
|
||||
m_load_result_string = m_load_result->as_string(true, rc);
|
||||
m_load_result_json = m_load_result->as_json(rc);
|
||||
ret = m_load_result->successful();
|
||||
|
||||
if (ret)
|
||||
{
|
||||
m_engine->enable_rule("", true, m_sample_ruleset);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// This must be kept in line with the (private) falco_engine::s_default_ruleset
|
||||
uint64_t num_rules_for_ruleset(std::string ruleset = "falco-default-ruleset")
|
||||
{
|
||||
return m_engine->num_rules_for_ruleset(ruleset);
|
||||
}
|
||||
|
||||
bool has_warnings()
|
||||
{
|
||||
return m_load_result->has_warnings();
|
||||
}
|
||||
|
||||
bool check_warning_message(std::string warning_msg)
|
||||
{
|
||||
if(!m_load_result->has_warnings())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for(auto &warn : m_load_result_json["warnings"])
|
||||
{
|
||||
std::string msg = warn["message"];
|
||||
// Debug:
|
||||
// printf("msg: %s\n", msg.c_str());
|
||||
if(msg.find(warning_msg) != std::string::npos)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool check_error_message(std::string error_msg)
|
||||
{
|
||||
// if the loading is successful there are no errors
|
||||
if(m_load_result->successful())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for(auto &err : m_load_result_json["errors"])
|
||||
{
|
||||
std::string msg = err["message"];
|
||||
// Debug:
|
||||
// printf("msg: %s\n", msg.c_str());
|
||||
if(msg.find(error_msg) != std::string::npos)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string get_compiled_rule_condition(std::string rule_name = "")
|
||||
{
|
||||
auto rule_description = m_engine->describe_rule(&rule_name, {});
|
||||
return rule_description["rules"][0]["details"]["condition_compiled"].template get<std::string>();
|
||||
}
|
||||
|
||||
std::string m_sample_ruleset;
|
||||
std::string m_sample_source;
|
||||
sinsp_filter_check_list m_filterlist;
|
||||
std::shared_ptr<gen_event_filter_factory> m_filter_factory;
|
||||
std::shared_ptr<gen_event_formatter_factory> m_formatter_factory;
|
||||
std::unique_ptr<falco_engine> m_engine;
|
||||
std::unique_ptr<falco::load_result> m_load_result;
|
||||
std::string m_load_result_string;
|
||||
nlohmann::json m_load_result_json;
|
||||
std::unique_ptr<sinsp> m_inspector;
|
||||
};
|
||||
|
||||
std::string s_sample_ruleset = "sample-ruleset";
|
||||
std::string s_sample_source = falco_common::syscall_source;
|
||||
|
||||
TEST_F(engine_loader_test, list_append)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- list: shell_binaries
|
||||
items: [ash, bash, csh, ksh, sh, tcsh, zsh, dash]
|
||||
|
||||
- rule: legit_rule
|
||||
desc: legit rule description
|
||||
condition: evt.type=open and proc.name in (shell_binaries)
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
|
||||
- list: shell_binaries
|
||||
items: [pwsh]
|
||||
override:
|
||||
items: append
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "legit_rules.yaml")) << m_load_result_string;
|
||||
ASSERT_EQ(get_compiled_rule_condition("legit_rule"),"(evt.type = open and proc.name in (ash, bash, csh, ksh, sh, tcsh, zsh, dash, pwsh))");
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, condition_append)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- macro: interactive
|
||||
condition: >
|
||||
((proc.aname=sshd and proc.name != sshd) or
|
||||
proc.name=systemd-logind or proc.name=login)
|
||||
|
||||
- rule: legit_rule
|
||||
desc: legit rule description
|
||||
condition: evt.type=open and interactive
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
|
||||
- macro: interactive
|
||||
condition: or proc.name = ssh
|
||||
override:
|
||||
condition: append
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "legit_rules.yaml")) << m_load_result_string;
|
||||
ASSERT_EQ(get_compiled_rule_condition("legit_rule"),"(evt.type = open and (((proc.aname = sshd and proc.name != sshd) or proc.name = systemd-logind or proc.name = login) or proc.name = ssh))");
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, rule_override_append)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- rule: legit_rule
|
||||
desc: legit rule description
|
||||
condition: evt.type=open
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
|
||||
- rule: legit_rule
|
||||
desc: with append
|
||||
condition: and proc.name = cat
|
||||
output: proc=%proc.name
|
||||
override:
|
||||
desc: append
|
||||
condition: append
|
||||
output: append
|
||||
)END";
|
||||
|
||||
std::string rule_name = "legit_rule";
|
||||
ASSERT_TRUE(load_rules(rules_content, "legit_rules.yaml")) << m_load_result_string;
|
||||
|
||||
// Here we don't use the deprecated `append` flag, so we don't expect the warning.
|
||||
ASSERT_FALSE(check_warning_message(WARNING_APPEND));
|
||||
|
||||
auto rule_description = m_engine->describe_rule(&rule_name, {});
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["condition"].template get<std::string>(),
|
||||
"evt.type=open and proc.name = cat");
|
||||
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["output"].template get<std::string>(),
|
||||
"user=%user.name command=%proc.cmdline file=%fd.name proc=%proc.name");
|
||||
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["description"].template get<std::string>(),
|
||||
"legit rule description with append");
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, rule_append)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- rule: legit_rule
|
||||
desc: legit rule description
|
||||
condition: evt.type=open
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
|
||||
- rule: legit_rule
|
||||
condition: and proc.name = cat
|
||||
append: true
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "legit_rules.yaml")) << m_load_result_string;
|
||||
|
||||
// We should have at least one warning because the 'append' flag is deprecated.
|
||||
ASSERT_TRUE(check_warning_message(WARNING_APPEND));
|
||||
|
||||
ASSERT_EQ(get_compiled_rule_condition("legit_rule"),"(evt.type = open and proc.name = cat)");
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, rule_override_replace)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- rule: legit_rule
|
||||
desc: legit rule description
|
||||
condition: evt.type=open
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
|
||||
- rule: legit_rule
|
||||
desc: a replaced legit description
|
||||
condition: evt.type = close
|
||||
override:
|
||||
desc: replace
|
||||
condition: replace
|
||||
)END";
|
||||
|
||||
std::string rule_name = "legit_rule";
|
||||
ASSERT_TRUE(load_rules(rules_content, "legit_rules.yaml")) << m_load_result_string;
|
||||
|
||||
auto rule_description = m_engine->describe_rule(&rule_name, {});
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["condition"].template get<std::string>(),
|
||||
"evt.type = close");
|
||||
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["output"].template get<std::string>(),
|
||||
"user=%user.name command=%proc.cmdline file=%fd.name");
|
||||
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["description"].template get<std::string>(),
|
||||
"a replaced legit description");
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, rule_override_append_replace)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- rule: legit_rule
|
||||
desc: legit rule description
|
||||
condition: evt.type = close
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
|
||||
- rule: legit_rule
|
||||
desc: a replaced legit description
|
||||
condition: and proc.name = cat
|
||||
priority: WARNING
|
||||
override:
|
||||
desc: replace
|
||||
condition: append
|
||||
priority: replace
|
||||
)END";
|
||||
|
||||
std::string rule_name = "legit_rule";
|
||||
ASSERT_TRUE(load_rules(rules_content, "legit_rules.yaml")) << m_load_result_string;
|
||||
|
||||
auto rule_description = m_engine->describe_rule(&rule_name, {});
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["condition"].template get<std::string>(),
|
||||
"evt.type = close and proc.name = cat");
|
||||
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["output"].template get<std::string>(),
|
||||
"user=%user.name command=%proc.cmdline file=%fd.name");
|
||||
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["description"].template get<std::string>(),
|
||||
"a replaced legit description");
|
||||
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["priority"].template get<std::string>(),
|
||||
"Warning");
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, rule_incorrect_override_type)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- rule: failing_rule
|
||||
desc: legit rule description
|
||||
condition: evt.type = close
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
|
||||
- rule: failing_rule
|
||||
desc: an appended incorrect field
|
||||
condition: and proc.name = cat
|
||||
priority: WARNING
|
||||
override:
|
||||
desc: replace
|
||||
condition: append
|
||||
priority: append
|
||||
)END";
|
||||
|
||||
std::string rule_name = "failing_rule";
|
||||
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_TRUE(check_error_message("Key 'priority' cannot be appended to, use 'replace' instead"));
|
||||
ASSERT_TRUE(std::string(m_load_result_json["errors"][0]["context"]["snippet"]).find("priority: append") != std::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, rule_incorrect_append_override)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- rule: failing_rule
|
||||
desc: legit rule description
|
||||
condition: evt.type = close
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
|
||||
- rule: failing_rule
|
||||
desc: an appended incorrect field
|
||||
condition: and proc.name = cat
|
||||
append: true
|
||||
override:
|
||||
desc: replace
|
||||
condition: append
|
||||
)END";
|
||||
|
||||
std::string rule_name = "failing_rule";
|
||||
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
|
||||
// We should have at least one warning because the 'append' flag is deprecated.
|
||||
ASSERT_TRUE(check_warning_message(WARNING_APPEND));
|
||||
|
||||
ASSERT_TRUE(check_error_message(ERROR_OVERRIDE_APPEND));
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, macro_override_append_before_macro_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
|
||||
- macro: open_simple
|
||||
condition: or evt.type = openat2
|
||||
override:
|
||||
condition: append
|
||||
|
||||
- macro: open_simple
|
||||
condition: evt.type in (open,openat)
|
||||
|
||||
- rule: test_rule
|
||||
desc: simple rule
|
||||
condition: open_simple
|
||||
output: command=%proc.cmdline
|
||||
priority: INFO
|
||||
|
||||
)END";
|
||||
|
||||
// We cannot define a macro override before the macro definition.
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_MACRO));
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, macro_override_replace_before_macro_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
|
||||
- macro: open_simple
|
||||
condition: or evt.type = openat2
|
||||
override:
|
||||
condition: replace
|
||||
|
||||
- macro: open_simple
|
||||
condition: evt.type in (open,openat)
|
||||
|
||||
- rule: test_rule
|
||||
desc: simple rule
|
||||
condition: open_simple
|
||||
output: command=%proc.cmdline
|
||||
priority: INFO
|
||||
|
||||
)END";
|
||||
|
||||
// The first override defines a macro that is overridden by the second macro definition
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"evt.type in (open, openat)");
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, macro_append_before_macro_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
|
||||
- macro: open_simple
|
||||
condition: or evt.type = openat2
|
||||
append: true
|
||||
|
||||
- macro: open_simple
|
||||
condition: evt.type in (open,openat)
|
||||
|
||||
- rule: test_rule
|
||||
desc: simple rule
|
||||
condition: open_simple
|
||||
output: command=%proc.cmdline
|
||||
priority: INFO
|
||||
|
||||
)END";
|
||||
|
||||
// We cannot define a macro override before the macro definition.
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_MACRO));
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, macro_override_append_after_macro_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
|
||||
- macro: open_simple
|
||||
condition: evt.type in (open,openat)
|
||||
|
||||
- macro: open_simple
|
||||
condition: or evt.type = openat2
|
||||
override:
|
||||
condition: append
|
||||
|
||||
- rule: test_rule
|
||||
desc: simple rule
|
||||
condition: open_simple
|
||||
output: command=%proc.cmdline
|
||||
priority: INFO
|
||||
|
||||
)END";
|
||||
|
||||
// We cannot define a macro override before the macro definition.
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type in (open, openat) or evt.type = openat2)");
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, macro_append_after_macro_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
|
||||
- macro: open_simple
|
||||
condition: evt.type in (open,openat)
|
||||
|
||||
- macro: open_simple
|
||||
condition: or evt.type = openat2
|
||||
append: true
|
||||
|
||||
- rule: test_rule
|
||||
desc: simple rule
|
||||
condition: open_simple
|
||||
output: command=%proc.cmdline
|
||||
priority: INFO
|
||||
|
||||
)END";
|
||||
|
||||
// We cannot define a macro override before the macro definition.
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type in (open, openat) or evt.type = openat2)");
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, rule_override_append_before_rule_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
condition: and proc.name = cat
|
||||
override:
|
||||
condition: append
|
||||
|
||||
- rule: test_rule
|
||||
desc: simple rule
|
||||
condition: evt.type in (open,openat)
|
||||
output: command=%proc.cmdline
|
||||
priority: INFO
|
||||
|
||||
)END";
|
||||
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_RULE_APPEND));
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, rule_override_replace_before_rule_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
condition: and proc.name = cat
|
||||
override:
|
||||
condition: replace
|
||||
|
||||
- rule: test_rule
|
||||
desc: simple rule
|
||||
condition: evt.type in (open,openat)
|
||||
output: command=%proc.cmdline
|
||||
priority: INFO
|
||||
|
||||
)END";
|
||||
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_RULE_REPLACE));
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, rule_append_before_rule_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
condition: and proc.name = cat
|
||||
append: true
|
||||
|
||||
- rule: test_rule
|
||||
desc: simple rule
|
||||
condition: evt.type in (open,openat)
|
||||
output: command=%proc.cmdline
|
||||
priority: INFO
|
||||
|
||||
)END";
|
||||
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_RULE_APPEND));
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, rule_override_append_after_rule_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: simple rule
|
||||
condition: evt.type in (open,openat)
|
||||
output: command=%proc.cmdline
|
||||
priority: INFO
|
||||
|
||||
- rule: test_rule
|
||||
condition: and proc.name = cat
|
||||
override:
|
||||
condition: append
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type in (open, openat) and proc.name = cat)");
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, rule_append_after_rule_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: simple rule
|
||||
condition: evt.type in (open,openat)
|
||||
output: command=%proc.cmdline
|
||||
priority: INFO
|
||||
|
||||
- rule: test_rule
|
||||
condition: and proc.name = cat
|
||||
append: true
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type in (open, openat) and proc.name = cat)");
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, list_override_append_wrong_key)
|
||||
{
|
||||
// todo: maybe we want to manage some non-existent keys
|
||||
// Please note how the non-existent key 'non-existent keys' is ignored.
|
||||
std::string rules_content = R"END(
|
||||
- list: dev_creation_binaries
|
||||
items: ["csi-provisioner", "csi-attacher"]
|
||||
override_written_wrong:
|
||||
items: append
|
||||
|
||||
- list: dev_creation_binaries
|
||||
items: [blkid]
|
||||
|
||||
- rule: test_rule
|
||||
desc: simple rule
|
||||
condition: evt.type = execve and proc.name in (dev_creation_binaries)
|
||||
output: command=%proc.cmdline
|
||||
priority: INFO
|
||||
|
||||
)END";
|
||||
|
||||
// Since there is a wrong key in the first list definition the `override` is not
|
||||
// considered. so in this situation, we are defining the list 2 times. The
|
||||
// second one overrides the first one.
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type = execve and proc.name in (blkid))");
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, list_override_append_before_list_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- list: dev_creation_binaries
|
||||
items: ["csi-provisioner", "csi-attacher"]
|
||||
override:
|
||||
items: append
|
||||
|
||||
- list: dev_creation_binaries
|
||||
items: [blkid]
|
||||
|
||||
- rule: test_rule
|
||||
desc: simple rule
|
||||
condition: evt.type = execve and proc.name in (dev_creation_binaries)
|
||||
output: command=%proc.cmdline
|
||||
priority: INFO
|
||||
|
||||
)END";
|
||||
|
||||
// We cannot define a list override before the list definition.
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_LIST));
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, list_override_replace_before_list_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- list: dev_creation_binaries
|
||||
items: ["csi-provisioner", "csi-attacher"]
|
||||
override:
|
||||
items: replace
|
||||
|
||||
- list: dev_creation_binaries
|
||||
items: [blkid]
|
||||
|
||||
- rule: test_rule
|
||||
desc: simple rule
|
||||
condition: evt.type = execve and proc.name in (dev_creation_binaries)
|
||||
output: command=%proc.cmdline
|
||||
priority: INFO
|
||||
|
||||
)END";
|
||||
|
||||
// With override replace we define a first list that then is overridden by the second one.
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type = execve and proc.name in (blkid))");
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, list_append_before_list_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- list: dev_creation_binaries
|
||||
items: ["csi-provisioner", "csi-attacher"]
|
||||
append: true
|
||||
|
||||
- list: dev_creation_binaries
|
||||
items: [blkid]
|
||||
|
||||
- rule: test_rule
|
||||
desc: simple rule
|
||||
condition: evt.type = execve and proc.name in (dev_creation_binaries)
|
||||
output: command=%proc.cmdline
|
||||
priority: INFO
|
||||
|
||||
)END";
|
||||
|
||||
// We cannot define a list append before the list definition.
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_LIST));
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, list_override_append_after_list_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- list: dev_creation_binaries
|
||||
items: [blkid]
|
||||
|
||||
- list: dev_creation_binaries
|
||||
items: ["csi-provisioner", "csi-attacher"]
|
||||
override:
|
||||
items: append
|
||||
|
||||
- rule: test_rule
|
||||
desc: simple rule
|
||||
condition: evt.type = execve and proc.name in (dev_creation_binaries)
|
||||
output: command=%proc.cmdline
|
||||
priority: INFO
|
||||
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type = execve and proc.name in (blkid, csi-provisioner, csi-attacher))");
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, list_append_after_list_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- list: dev_creation_binaries
|
||||
items: [blkid]
|
||||
|
||||
- list: dev_creation_binaries
|
||||
items: ["csi-provisioner", "csi-attacher"]
|
||||
append: true
|
||||
|
||||
- rule: test_rule
|
||||
desc: simple rule
|
||||
condition: evt.type = execve and proc.name in (dev_creation_binaries)
|
||||
output: command=%proc.cmdline
|
||||
priority: INFO
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type = execve and proc.name in (blkid, csi-provisioner, csi-attacher))");
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, rule_override_without_field)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- rule: failing_rule
|
||||
desc: legit rule description
|
||||
condition: evt.type = close
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
|
||||
- rule: failing_rule
|
||||
desc: an appended incorrect field
|
||||
override:
|
||||
desc: replace
|
||||
condition: append
|
||||
)END";
|
||||
|
||||
std::string rule_name = "failing_rule";
|
||||
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_TRUE(check_error_message("An append override for 'condition' was specified but 'condition' is not defined"));
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, rule_override_extra_field)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- rule: failing_rule
|
||||
desc: legit rule description
|
||||
condition: evt.type = close
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
|
||||
- rule: failing_rule
|
||||
desc: an appended incorrect field
|
||||
condition: and proc.name = cat
|
||||
priority: WARNING
|
||||
override:
|
||||
desc: replace
|
||||
condition: append
|
||||
)END";
|
||||
|
||||
std::string rule_name = "failing_rule";
|
||||
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_TRUE(check_error_message("Unexpected key 'priority'"));
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, missing_enabled_key_with_override)
|
||||
{
|
||||
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
|
||||
enabled: false
|
||||
|
||||
- rule: test_rule
|
||||
desc: missing enabled key
|
||||
condition: and proc.name = cat
|
||||
override:
|
||||
desc: replace
|
||||
condition: append
|
||||
enabled: replace
|
||||
)END";
|
||||
|
||||
// In the rule override we miss `enabled: true`
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_TRUE(check_error_message("'enabled' was specified but 'enabled' is not defined"));
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, rule_override_with_enabled)
|
||||
{
|
||||
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
|
||||
enabled: false
|
||||
|
||||
- rule: test_rule
|
||||
desc: correct override
|
||||
condition: and proc.name = cat
|
||||
enabled: true
|
||||
override:
|
||||
desc: replace
|
||||
condition: append
|
||||
enabled: replace
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_FALSE(has_warnings());
|
||||
// The rule should be enabled at the end.
|
||||
EXPECT_EQ(num_rules_for_ruleset(), 1);
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, rule_not_enabled)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: rule not enabled
|
||||
condition: evt.type = close
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
enabled: false
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_FALSE(has_warnings());
|
||||
EXPECT_EQ(num_rules_for_ruleset(), 0);
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, rule_enabled_warning)
|
||||
{
|
||||
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
|
||||
enabled: false
|
||||
|
||||
- rule: test_rule
|
||||
enabled: true
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_TRUE(check_warning_message(WARNING_ENABLED));
|
||||
// The rule should be enabled at the end.
|
||||
EXPECT_EQ(num_rules_for_ruleset(), 1);
|
||||
}
|
||||
|
||||
// todo!: Probably we shouldn't allow this syntax
|
||||
TEST_F(engine_loader_test, rule_enabled_is_ignored_by_append)
|
||||
{
|
||||
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
|
||||
enabled: false
|
||||
|
||||
- rule: test_rule
|
||||
condition: and proc.name = cat
|
||||
append: true
|
||||
enabled: true
|
||||
)END";
|
||||
|
||||
// 'enabled' is ignored by the append, this syntax is not supported
|
||||
// so the rule is not enabled.
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
EXPECT_EQ(num_rules_for_ruleset(), 0);
|
||||
}
|
||||
|
||||
// todo!: Probably we shouldn't allow this syntax
|
||||
TEST_F(engine_loader_test, rewrite_rule)
|
||||
{
|
||||
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
|
||||
enabled: false
|
||||
|
||||
- rule: test_rule
|
||||
desc: redefined rule syntax
|
||||
condition: proc.name = cat
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: WARNING
|
||||
enabled: true
|
||||
)END";
|
||||
|
||||
// The above syntax is not supported, we cannot override the content
|
||||
// of a rule in this way.
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
// In this case the rule is completely overridden but this syntax is not supported.
|
||||
EXPECT_EQ(num_rules_for_ruleset(), 1);
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"proc.name = cat");
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, required_engine_version_semver)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- required_engine_version: 0.26.0
|
||||
|
||||
- rule: test_rule
|
||||
desc: test rule description
|
||||
condition: evt.type = close
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
enabled: false
|
||||
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_FALSE(has_warnings());
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, required_engine_version_not_semver)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- required_engine_version: 26
|
||||
|
||||
- rule: test_rule
|
||||
desc: test rule description
|
||||
condition: evt.type = close
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
enabled: false
|
||||
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_FALSE(has_warnings());
|
||||
}
|
||||
|
||||
TEST_F(engine_loader_test, required_engine_version_invalid)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- required_engine_version: seven
|
||||
|
||||
- rule: test_rule
|
||||
desc: test rule description
|
||||
condition: evt.type = close
|
||||
output: user=%user.name command=%proc.cmdline file=%fd.name
|
||||
priority: INFO
|
||||
enabled: false
|
||||
|
||||
)END";
|
||||
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_TRUE(check_error_message("Unable to parse engine version"));
|
||||
}
|
||||
|
||||
// checks for issue described in https://github.com/falcosecurity/falco/pull/3028
|
||||
TEST_F(engine_loader_test, list_value_with_escaping)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
- list: my_list
|
||||
items: [non_escaped_val, "escaped val"]
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_TRUE(m_load_result->successful());
|
||||
ASSERT_TRUE(m_load_result->has_warnings()); // a warning for the unused list
|
||||
|
||||
auto rule_description = m_engine->describe_rule(nullptr, {});
|
||||
ASSERT_TRUE(m_load_result->successful());
|
||||
ASSERT_EQ(rule_description["rules"].size(), 0);
|
||||
ASSERT_EQ(rule_description["macros"].size(), 0);
|
||||
ASSERT_EQ(rule_description["lists"].size(), 1);
|
||||
|
||||
// escaped values must not be interpreted as list refs by mistake
|
||||
ASSERT_EQ(rule_description["lists"][0]["details"]["lists"].size(), 0);
|
||||
|
||||
// values should be escaped correctly
|
||||
ASSERT_EQ(rule_description["lists"][0]["details"]["items_compiled"].size(), 2);
|
||||
ASSERT_EQ(rule_description["lists"][0]["details"]["items_compiled"][0].template get<std::string>(), "non_escaped_val");
|
||||
ASSERT_EQ(rule_description["lists"][0]["details"]["items_compiled"][1].template get<std::string>(), "escaped val");
|
||||
}
|
||||
@@ -39,7 +39,7 @@ PUBLIC
|
||||
${LIBSCAP_INCLUDE_DIRS}
|
||||
${LIBSINSP_INCLUDE_DIRS}
|
||||
${PROJECT_BINARY_DIR}/userspace/engine
|
||||
${nlohmann_json_DIR}
|
||||
${nlohmann_json_INCLUDE_DIRS}
|
||||
${TBB_INCLUDE_DIR}
|
||||
${YAMLCPP_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
@@ -79,26 +79,6 @@ sinsp_version falco_engine::engine_version()
|
||||
return sinsp_version(FALCO_ENGINE_VERSION);
|
||||
}
|
||||
|
||||
const falco_source* falco_engine::find_source(const std::string& name) const
|
||||
{
|
||||
auto ret = m_sources.at(name);
|
||||
if(!ret)
|
||||
{
|
||||
throw falco_exception("Unknown event source " + name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const falco_source* falco_engine::find_source(std::size_t index) const
|
||||
{
|
||||
auto ret = m_sources.at(index);
|
||||
if(!ret)
|
||||
{
|
||||
throw falco_exception("Unknown event source index " + std::to_string(index));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Return a key that uniquely represents a field class.
|
||||
// For now, we assume name + shortdesc is unique.
|
||||
static std::string fieldclass_key(const gen_event_filter_factory::filter_fieldclass_info &fld_info)
|
||||
@@ -177,15 +157,6 @@ void falco_engine::list_fields(std::string &source, bool verbose, bool names_onl
|
||||
}
|
||||
}
|
||||
|
||||
void falco_engine::load_rules(const std::string &rules_content, bool verbose, bool all_events)
|
||||
{
|
||||
static const std::string no_name = "N/A";
|
||||
|
||||
std::unique_ptr<load_result> res = load_rules(rules_content, no_name);
|
||||
|
||||
interpret_load_result(res, no_name, rules_content, verbose);
|
||||
}
|
||||
|
||||
std::unique_ptr<load_result> falco_engine::load_rules(const std::string &rules_content, const std::string &name)
|
||||
{
|
||||
rule_loader::configuration cfg(rules_content, m_sources, name);
|
||||
@@ -257,44 +228,6 @@ std::unique_ptr<load_result> falco_engine::load_rules(const std::string &rules_c
|
||||
return std::move(cfg.res);
|
||||
}
|
||||
|
||||
void falco_engine::load_rules_file(const std::string &rules_filename, bool verbose, bool all_events)
|
||||
{
|
||||
std::string rules_content;
|
||||
|
||||
read_file(rules_filename, rules_content);
|
||||
|
||||
std::unique_ptr<load_result> res = load_rules(rules_content, rules_filename);
|
||||
|
||||
interpret_load_result(res, rules_filename, rules_content, verbose);
|
||||
}
|
||||
|
||||
std::unique_ptr<load_result> falco_engine::load_rules_file(const std::string &rules_filename)
|
||||
{
|
||||
std::string rules_content;
|
||||
|
||||
try {
|
||||
read_file(rules_filename, rules_content);
|
||||
}
|
||||
catch (falco_exception &e)
|
||||
{
|
||||
rule_loader::context ctx(rules_filename);
|
||||
|
||||
std::unique_ptr<rule_loader::result> res(new rule_loader::result(rules_filename));
|
||||
|
||||
res->add_error(load_result::LOAD_ERR_FILE_READ, e.what(), ctx);
|
||||
|
||||
// Old gcc versions (e.g. 4.8.3) won't allow move elision but newer versions
|
||||
// (e.g. 10.2.1) would complain about the redundant move.
|
||||
#if __GNUC__ > 4
|
||||
return res;
|
||||
#else
|
||||
return std::move(res);
|
||||
#endif
|
||||
}
|
||||
|
||||
return load_rules(rules_content, rules_filename);
|
||||
}
|
||||
|
||||
void falco_engine::enable_rule(const std::string &substring, bool enabled, const std::string &ruleset)
|
||||
{
|
||||
uint16_t ruleset_id = find_ruleset_id(ruleset);
|
||||
@@ -422,21 +355,7 @@ std::unique_ptr<std::vector<falco_engine::rule_result>> falco_engine::process_ev
|
||||
// source_idx, which means that at any time each filter_ruleset will only
|
||||
// be accessed by a single thread.
|
||||
|
||||
const falco_source *source;
|
||||
|
||||
if(source_idx == m_syscall_source_idx)
|
||||
{
|
||||
if(m_syscall_source == NULL)
|
||||
{
|
||||
m_syscall_source = find_source(m_syscall_source_idx);
|
||||
}
|
||||
|
||||
source = m_syscall_source;
|
||||
}
|
||||
else
|
||||
{
|
||||
source = find_source(source_idx);
|
||||
}
|
||||
const falco_source *source = find_source(source_idx);
|
||||
|
||||
if(should_drop_evt() || !source)
|
||||
{
|
||||
@@ -538,7 +457,7 @@ nlohmann::json falco_engine::describe_rule(std::string *rule, const std::vector<
|
||||
// output of rules, macros, and lists.
|
||||
if (m_last_compile_output == nullptr)
|
||||
{
|
||||
throw falco_exception("rules most be loaded before describing them");
|
||||
throw falco_exception("rules must be loaded before describing them");
|
||||
}
|
||||
|
||||
// use collected and compiled info to print a json output
|
||||
@@ -941,6 +860,50 @@ bool falco_engine::is_source_valid(const std::string &source) const
|
||||
return m_sources.at(source) != nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<gen_event_filter_factory> falco_engine::filter_factory_for_source(const std::string& source)
|
||||
{
|
||||
return find_source(source)->filter_factory;
|
||||
}
|
||||
|
||||
std::shared_ptr<gen_event_filter_factory> falco_engine::filter_factory_for_source(std::size_t source_idx)
|
||||
{
|
||||
return find_source(source_idx)->filter_factory;
|
||||
}
|
||||
|
||||
std::shared_ptr<gen_event_formatter_factory> falco_engine::formatter_factory_for_source(const std::string& source)
|
||||
{
|
||||
return find_source(source)->formatter_factory;
|
||||
}
|
||||
|
||||
std::shared_ptr<gen_event_formatter_factory> falco_engine::formatter_factory_for_source(std::size_t source_idx)
|
||||
{
|
||||
return find_source(source_idx)->formatter_factory;
|
||||
}
|
||||
|
||||
std::shared_ptr<filter_ruleset_factory> falco_engine::ruleset_factory_for_source(const std::string& source)
|
||||
{
|
||||
return find_source(source)->ruleset_factory;
|
||||
}
|
||||
|
||||
std::shared_ptr<filter_ruleset_factory> falco_engine::ruleset_factory_for_source(std::size_t source_idx)
|
||||
{
|
||||
return find_source(source_idx)->ruleset_factory;
|
||||
}
|
||||
|
||||
std::shared_ptr<filter_ruleset> falco_engine::ruleset_for_source(const std::string& source_name)
|
||||
{
|
||||
const falco_source *source = find_source(source_name);
|
||||
|
||||
return source->ruleset;
|
||||
}
|
||||
|
||||
std::shared_ptr<filter_ruleset> falco_engine::ruleset_for_source(std::size_t source_idx)
|
||||
{
|
||||
const falco_source *source = find_source(source_idx);
|
||||
|
||||
return source->ruleset;
|
||||
}
|
||||
|
||||
void falco_engine::read_file(const std::string& filename, std::string& contents)
|
||||
{
|
||||
std::ifstream is;
|
||||
@@ -955,29 +918,6 @@ void falco_engine::read_file(const std::string& filename, std::string& contents)
|
||||
std::istreambuf_iterator<char>());
|
||||
}
|
||||
|
||||
void falco_engine::interpret_load_result(std::unique_ptr<load_result>& res,
|
||||
const std::string& rules_filename,
|
||||
const std::string& rules_content,
|
||||
bool verbose)
|
||||
{
|
||||
falco::load_result::rules_contents_t rc = {{rules_filename, rules_content}};
|
||||
|
||||
if(!res->successful())
|
||||
{
|
||||
// The output here is always the full e.g. "verbose" output.
|
||||
throw falco_exception(res->as_string(true, rc).c_str());
|
||||
}
|
||||
|
||||
if(verbose && res->has_warnings())
|
||||
{
|
||||
// Here, verbose controls whether to additionally
|
||||
// "log" e.g. print to stderr. What's logged is always
|
||||
// non-verbose so it fits on a single line.
|
||||
// todo(jasondellaluce): introduce a logging callback in Falco
|
||||
fprintf(stderr, "%s\n", res->as_string(false, rc).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
static bool check_plugin_requirement_alternatives(
|
||||
const std::vector<falco_engine::plugin_version_requirement>& plugins,
|
||||
const rule_loader::plugin_version_info::requirement_alternatives& alternatives,
|
||||
|
||||
@@ -74,15 +74,8 @@ public:
|
||||
void list_fields(std::string &source, bool verbose, bool names_only, bool markdown) const;
|
||||
|
||||
//
|
||||
// Load rules either directly or from a filename.
|
||||
// Load rules and returns a result object.
|
||||
//
|
||||
void load_rules_file(const std::string &rules_filename, bool verbose, bool all_events);
|
||||
void load_rules(const std::string &rules_content, bool verbose, bool all_events);
|
||||
|
||||
//
|
||||
// Identical to above, but returns a result object instead of
|
||||
// throwing exceptions on error.
|
||||
std::unique_ptr<falco::load_result> load_rules_file(const std::string &rules_filename);
|
||||
std::unique_ptr<falco::load_result> load_rules(const std::string &rules_content, const std::string &name);
|
||||
|
||||
//
|
||||
@@ -242,6 +235,31 @@ public:
|
||||
// factory for this source.
|
||||
bool is_source_valid(const std::string &source) const;
|
||||
|
||||
//
|
||||
// Given a source, return a formatter factory that can create
|
||||
// filters for events of that source.
|
||||
//
|
||||
std::shared_ptr<gen_event_filter_factory> filter_factory_for_source(const std::string& source);
|
||||
std::shared_ptr<gen_event_filter_factory> filter_factory_for_source(std::size_t source_idx);
|
||||
|
||||
//
|
||||
// Given a source, return a formatter factory that can create
|
||||
// formatters for an event.
|
||||
//
|
||||
std::shared_ptr<gen_event_formatter_factory> formatter_factory_for_source(const std::string& source);
|
||||
std::shared_ptr<gen_event_formatter_factory> formatter_factory_for_source(std::size_t source_idx);
|
||||
|
||||
//
|
||||
// Given a source, return a ruleset factory that can create
|
||||
// rulesets for that source.
|
||||
//
|
||||
std::shared_ptr<filter_ruleset_factory> ruleset_factory_for_source(const std::string& source);
|
||||
std::shared_ptr<filter_ruleset_factory> ruleset_factory_for_source(std::size_t source_idx);
|
||||
|
||||
// Return the filter_ruleset used for a given source.
|
||||
std::shared_ptr<filter_ruleset> ruleset_for_source(const std::string& source);
|
||||
std::shared_ptr<filter_ruleset> ruleset_for_source(std::size_t source_idx);
|
||||
|
||||
//
|
||||
// Given an event source and ruleset, fill in a bitset
|
||||
// containing the event types for which this ruleset can run.
|
||||
@@ -296,17 +314,46 @@ private:
|
||||
// Throws falco_exception if the file can not be read
|
||||
void read_file(const std::string& filename, std::string& contents);
|
||||
|
||||
// For load_rules methods that throw exceptions on error,
|
||||
// interpret a load_result and throw an exception if needed.
|
||||
void interpret_load_result(std::unique_ptr<falco::load_result>& res,
|
||||
const std::string& rules_filename,
|
||||
const std::string& rules_content,
|
||||
bool verbose);
|
||||
|
||||
indexed_vector<falco_source> m_sources;
|
||||
|
||||
const falco_source* find_source(std::size_t index) const;
|
||||
const falco_source* find_source(const std::string& name) const;
|
||||
inline const falco_source* find_source(std::size_t index)
|
||||
{
|
||||
const falco_source *source;
|
||||
|
||||
if(index == m_syscall_source_idx)
|
||||
{
|
||||
if(m_syscall_source == NULL)
|
||||
{
|
||||
m_syscall_source = m_sources.at(m_syscall_source_idx);
|
||||
if(!m_syscall_source)
|
||||
{
|
||||
throw falco_exception("Unknown event source index " + std::to_string(index));
|
||||
}
|
||||
}
|
||||
|
||||
source = m_syscall_source;
|
||||
}
|
||||
else
|
||||
{
|
||||
source = m_sources.at(index);
|
||||
if(!source)
|
||||
{
|
||||
throw falco_exception("Unknown event source index " + std::to_string(index));
|
||||
}
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
inline const falco_source* find_source(const std::string& name) const
|
||||
{
|
||||
auto ret = m_sources.at(name);
|
||||
if(!ret)
|
||||
{
|
||||
throw falco_exception("Unknown event source " + name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// To allow the engine to be extremely fast for syscalls (can
|
||||
// be > 1M events/sec), we save the syscall source/source_idx
|
||||
@@ -387,4 +434,3 @@ private:
|
||||
std::string m_extra;
|
||||
bool m_replace_container_info;
|
||||
};
|
||||
|
||||
|
||||
@@ -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 29
|
||||
#define FALCO_ENGINE_VERSION_MINOR 31
|
||||
#define FALCO_ENGINE_VERSION_PATCH 0
|
||||
|
||||
#define FALCO_ENGINE_VERSION \
|
||||
@@ -34,4 +34,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 "30bd8b1c09eab71e14416f04b617d4d20bc7c7358bce91748ce9bd8007786c4d"
|
||||
#define FALCO_ENGINE_CHECKSUM "7c512927c89f594f024f2ff181077c780c4fe6e9dd4cee3f20a9ef208a356e4e"
|
||||
|
||||
@@ -66,7 +66,8 @@ static const std::string warning_codes[] = {
|
||||
"LOAD_UNKNOWN_FILTER",
|
||||
"LOAD_UNUSED_MACRO",
|
||||
"LOAD_UNUSED_LIST",
|
||||
"LOAD_UNKNOWN_ITEM"
|
||||
"LOAD_UNKNOWN_ITEM",
|
||||
"LOAD_DEPRECATED_ITEM"
|
||||
};
|
||||
|
||||
const std::string& falco::load_result::warning_code_str(warning_code wc)
|
||||
@@ -81,7 +82,8 @@ static const std::string warning_strings[] = {
|
||||
"Unknown field or event-type in condition or output",
|
||||
"Unused macro",
|
||||
"Unused list",
|
||||
"Unknown rules file item"
|
||||
"Unknown rules file item",
|
||||
"Used deprecated item"
|
||||
};
|
||||
|
||||
const std::string& falco::load_result::warning_str(warning_code wc)
|
||||
@@ -96,7 +98,8 @@ static const std::string warning_descs[] = {
|
||||
"A rule condition or output refers to a field or evt.type that does not exist. This is normally an error, but if a rule has a skip-if-unknown-filter property, the error is downgraded to a warning.",
|
||||
"A macro is defined in the rules content but is not used by any other macro or rule.",
|
||||
"A list is defined in the rules content but is not used by any other list, macro, or rule.",
|
||||
"An unknown top-level object is in the rules content. It will be ignored."
|
||||
"An unknown top-level object is in the rules content. It will be ignored.",
|
||||
"A deprecated item is employed by lists, macros, or rules."
|
||||
};
|
||||
|
||||
const std::string& falco::load_result::warning_desc(warning_code wc)
|
||||
|
||||
@@ -54,7 +54,8 @@ public:
|
||||
LOAD_UNKNOWN_FILTER,
|
||||
LOAD_UNUSED_MACRO,
|
||||
LOAD_UNUSED_LIST,
|
||||
LOAD_UNKNOWN_ITEM
|
||||
LOAD_UNKNOWN_ITEM,
|
||||
LOAD_DEPRECATED_ITEM
|
||||
};
|
||||
|
||||
virtual ~load_result() = default;
|
||||
|
||||
@@ -41,7 +41,8 @@ static const std::string item_type_strings[] = {
|
||||
"condition expression",
|
||||
"rule output",
|
||||
"rule output expression",
|
||||
"rule priority"
|
||||
"rule priority",
|
||||
"overrides"
|
||||
};
|
||||
|
||||
const std::string& rule_loader::context::item_type_as_string(enum item_type it)
|
||||
@@ -553,6 +554,11 @@ rule_loader::rule_info::rule_info(context &ctx)
|
||||
{
|
||||
}
|
||||
|
||||
rule_loader::rule_update_info::rule_update_info(context &ctx)
|
||||
: ctx(ctx), cond_ctx(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
rule_loader::rule_load_exception::rule_load_exception(falco::load_result::error_code ec, const std::string& msg, const context& ctx)
|
||||
: ec(ec), msg(msg), ctx(ctx)
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@ limitations under the License.
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <yaml-cpp/yaml.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include "falco_source.h"
|
||||
@@ -56,7 +57,8 @@ namespace rule_loader
|
||||
CONDITION_EXPRESSION,
|
||||
RULE_OUTPUT,
|
||||
RULE_OUTPUT_EXPRESSION,
|
||||
RULE_PRIORITY
|
||||
RULE_PRIORITY,
|
||||
OVERRIDE
|
||||
};
|
||||
|
||||
static const std::string& item_type_as_string(enum item_type it);
|
||||
@@ -451,4 +453,38 @@ namespace rule_loader
|
||||
bool warn_evttypes;
|
||||
bool skip_if_unknown_filter;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Represents infos about a rule update (append or replace) request
|
||||
*/
|
||||
|
||||
struct rule_update_info
|
||||
{
|
||||
rule_update_info(context &ctx);
|
||||
~rule_update_info() = default;
|
||||
rule_update_info(rule_update_info&&) = default;
|
||||
rule_update_info& operator = (rule_update_info&&) = default;
|
||||
rule_update_info(const rule_update_info&) = default;
|
||||
rule_update_info& operator = (const rule_update_info&) = default;
|
||||
|
||||
bool has_any_value()
|
||||
{
|
||||
return cond.has_value() || output.has_value() || desc.has_value() || tags.has_value() ||
|
||||
exceptions.has_value() || priority.has_value() || enabled.has_value() ||
|
||||
warn_evttypes.has_value() || skip_if_unknown_filter.has_value();
|
||||
}
|
||||
|
||||
context ctx;
|
||||
context cond_ctx;
|
||||
std::string name;
|
||||
std::optional<std::string> cond;
|
||||
std::optional<std::string> output;
|
||||
std::optional<std::string> desc;
|
||||
std::optional<std::set<std::string>> tags;
|
||||
std::optional<std::vector<rule_exception_info>> exceptions;
|
||||
std::optional<falco_common::priority_type> priority;
|
||||
std::optional<bool> enabled;
|
||||
std::optional<bool> warn_evttypes;
|
||||
std::optional<bool> skip_if_unknown_filter;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -20,6 +20,7 @@ limitations under the License.
|
||||
|
||||
#include "falco_engine.h"
|
||||
#include "rule_loader_collector.h"
|
||||
#include "rule_loading_messages.h"
|
||||
|
||||
#define THROW(cond, err, ctx) { if ((cond)) { throw rule_loader::rule_load_exception(falco::load_result::LOAD_ERR_VALIDATE, (err), (ctx)); } }
|
||||
|
||||
@@ -48,8 +49,14 @@ static inline void define_info(indexed_vector<T>& infos, T& info, uint32_t id)
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline void append_info(T* prev, T& info, uint32_t id)
|
||||
template <typename T, typename U>
|
||||
static inline void append_info(T* prev, U& info, uint32_t id)
|
||||
{
|
||||
prev->visibility = id;
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
static inline void replace_info(T* prev, U& info, uint32_t id)
|
||||
{
|
||||
prev->visibility = id;
|
||||
}
|
||||
@@ -184,9 +191,7 @@ void rule_loader::collector::define(configuration& cfg, list_info& info)
|
||||
void rule_loader::collector::append(configuration& cfg, list_info& info)
|
||||
{
|
||||
auto prev = m_list_infos.at(info.name);
|
||||
THROW(!prev,
|
||||
"List has 'append' key but no list by that name already exists",
|
||||
info.ctx);
|
||||
THROW(!prev, ERROR_NO_PREVIOUS_LIST, info.ctx);
|
||||
prev->items.insert(prev->items.end(), info.items.begin(), info.items.end());
|
||||
append_info(prev, info, m_cur_index++);
|
||||
}
|
||||
@@ -199,9 +204,7 @@ void rule_loader::collector::define(configuration& cfg, macro_info& info)
|
||||
void rule_loader::collector::append(configuration& cfg, macro_info& info)
|
||||
{
|
||||
auto prev = m_macro_infos.at(info.name);
|
||||
THROW(!prev,
|
||||
"Macro has 'append' key but no macro by that name already exists",
|
||||
info.ctx);
|
||||
THROW(!prev, ERROR_NO_PREVIOUS_MACRO, info.ctx);
|
||||
prev->cond += " ";
|
||||
prev->cond += info.cond;
|
||||
append_info(prev, info, m_cur_index++);
|
||||
@@ -233,15 +236,14 @@ void rule_loader::collector::define(configuration& cfg, rule_info& info)
|
||||
define_info(m_rule_infos, info, m_cur_index++);
|
||||
}
|
||||
|
||||
void rule_loader::collector::append(configuration& cfg, rule_info& info)
|
||||
void rule_loader::collector::append(configuration& cfg, rule_update_info& info)
|
||||
{
|
||||
auto prev = m_rule_infos.at(info.name);
|
||||
|
||||
THROW(!prev,
|
||||
"Rule has 'append' key but no rule by that name already exists",
|
||||
info.ctx);
|
||||
THROW(info.cond.empty() && info.exceptions.empty(),
|
||||
THROW(!prev, ERROR_NO_PREVIOUS_RULE_APPEND, info.ctx);
|
||||
THROW(!info.has_any_value(),
|
||||
"Appended rule must have exceptions or condition property",
|
||||
// "Appended rule must have at least one field that can be appended to", // TODO replace with this and update testing
|
||||
info.ctx);
|
||||
|
||||
// note: source can be nullptr in case we've collected a
|
||||
@@ -256,43 +258,136 @@ void rule_loader::collector::append(configuration& cfg, rule_info& info)
|
||||
info.ctx);
|
||||
}
|
||||
|
||||
if (!info.cond.empty())
|
||||
if (info.cond.has_value() && !info.cond->empty())
|
||||
{
|
||||
prev->cond += " ";
|
||||
prev->cond += info.cond;
|
||||
prev->cond += *info.cond;
|
||||
}
|
||||
|
||||
for (auto &ex : info.exceptions)
|
||||
if (info.output.has_value() && !info.output->empty())
|
||||
{
|
||||
auto prev_ex = find_if(prev->exceptions.begin(), prev->exceptions.end(),
|
||||
[&ex](const rule_loader::rule_exception_info& i)
|
||||
{ return i.name == ex.name; });
|
||||
if (prev_ex == prev->exceptions.end())
|
||||
prev->output += " ";
|
||||
prev->output += *info.output;
|
||||
}
|
||||
|
||||
if (info.desc.has_value() && !info.desc->empty())
|
||||
{
|
||||
prev->desc += " ";
|
||||
prev->desc += *info.desc;
|
||||
}
|
||||
|
||||
if (info.tags.has_value())
|
||||
{
|
||||
for (auto &tag: *info.tags)
|
||||
{
|
||||
THROW(!ex.fields.is_valid(),
|
||||
"Rule exception must have fields property with a list of fields",
|
||||
ex.ctx);
|
||||
THROW(ex.values.empty(),
|
||||
"Rule exception must have values property with a list of values",
|
||||
ex.ctx);
|
||||
validate_exception_info(source, ex);
|
||||
prev->exceptions.push_back(ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
THROW(ex.fields.is_valid(),
|
||||
"Can not append exception fields to existing exception, only values",
|
||||
ex.ctx);
|
||||
THROW(ex.comps.is_valid(),
|
||||
"Can not append exception comps to existing exception, only values",
|
||||
ex.ctx);
|
||||
prev_ex->values.insert(
|
||||
prev_ex->values.end(), ex.values.begin(), ex.values.end());
|
||||
prev->tags.insert(tag);
|
||||
}
|
||||
}
|
||||
|
||||
if (info.exceptions.has_value())
|
||||
{
|
||||
for (auto &ex : *info.exceptions)
|
||||
{
|
||||
auto prev_ex = find_if(prev->exceptions.begin(), prev->exceptions.end(),
|
||||
[&ex](const rule_loader::rule_exception_info& i)
|
||||
{ return i.name == ex.name; });
|
||||
if (prev_ex == prev->exceptions.end())
|
||||
{
|
||||
THROW(!ex.fields.is_valid(),
|
||||
"Rule exception must have fields property with a list of fields",
|
||||
ex.ctx);
|
||||
THROW(ex.values.empty(),
|
||||
"Rule exception must have values property with a list of values",
|
||||
ex.ctx);
|
||||
validate_exception_info(source, ex);
|
||||
prev->exceptions.push_back(ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
THROW(ex.fields.is_valid(),
|
||||
"Can not append exception fields to existing exception, only values",
|
||||
ex.ctx);
|
||||
THROW(ex.comps.is_valid(),
|
||||
"Can not append exception comps to existing exception, only values",
|
||||
ex.ctx);
|
||||
prev_ex->values.insert(
|
||||
prev_ex->values.end(), ex.values.begin(), ex.values.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
append_info(prev, info, m_cur_index++);
|
||||
}
|
||||
|
||||
void rule_loader::collector::selective_replace(configuration& cfg, rule_update_info& info)
|
||||
{
|
||||
auto prev = m_rule_infos.at(info.name);
|
||||
|
||||
THROW(!prev, ERROR_NO_PREVIOUS_RULE_REPLACE, info.ctx);
|
||||
THROW(!info.has_any_value(),
|
||||
"The rule must have at least one field that can be replaced",
|
||||
info.ctx);
|
||||
|
||||
// note: source can be nullptr in case we've collected a
|
||||
// rule for which the source is unknown
|
||||
falco_source* source = nullptr;
|
||||
if (!prev->unknown_source)
|
||||
{
|
||||
// note: if the source is not unknown, this should not return nullptr
|
||||
source = cfg.sources.at(prev->source);
|
||||
THROW(!source,
|
||||
std::string("Unknown source ") + prev->source,
|
||||
info.ctx);
|
||||
}
|
||||
|
||||
if (info.cond.has_value())
|
||||
{
|
||||
prev->cond = *info.cond;
|
||||
}
|
||||
|
||||
if (info.output.has_value())
|
||||
{
|
||||
prev->output = *info.output;
|
||||
}
|
||||
|
||||
if (info.desc.has_value())
|
||||
{
|
||||
prev->desc = *info.desc;
|
||||
}
|
||||
|
||||
if (info.tags.has_value())
|
||||
{
|
||||
prev->tags = *info.tags;
|
||||
}
|
||||
|
||||
if (info.exceptions.has_value())
|
||||
{
|
||||
prev->exceptions = *info.exceptions;
|
||||
}
|
||||
|
||||
if (info.priority.has_value())
|
||||
{
|
||||
prev->priority = *info.priority;
|
||||
}
|
||||
|
||||
if (info.enabled.has_value())
|
||||
{
|
||||
prev->enabled = *info.enabled;
|
||||
}
|
||||
|
||||
if (info.warn_evttypes.has_value())
|
||||
{
|
||||
prev->warn_evttypes = *info.warn_evttypes;
|
||||
}
|
||||
|
||||
if (info.skip_if_unknown_filter.has_value())
|
||||
{
|
||||
prev->skip_if_unknown_filter = *info.skip_if_unknown_filter;
|
||||
}
|
||||
|
||||
replace_info(prev, info, m_cur_index++);
|
||||
}
|
||||
|
||||
void rule_loader::collector::enable(configuration& cfg, rule_info& info)
|
||||
{
|
||||
auto prev = m_rule_infos.at(info.name);
|
||||
|
||||
@@ -85,13 +85,18 @@ public:
|
||||
*/
|
||||
virtual void append(configuration& cfg, list_info& info);
|
||||
virtual void append(configuration& cfg, macro_info& info);
|
||||
virtual void append(configuration& cfg, rule_info& info);
|
||||
virtual void append(configuration& cfg, rule_update_info& info);
|
||||
|
||||
/*!
|
||||
\brief Updates the 'enabled' flag of an existing definition
|
||||
*/
|
||||
virtual void enable(configuration& cfg, rule_info& info);
|
||||
|
||||
/*!
|
||||
\brief Selectively replaces some fields of an existing definition
|
||||
*/
|
||||
virtual void selective_replace(configuration& cfg, rule_update_info& info);
|
||||
|
||||
private:
|
||||
uint32_t m_cur_index;
|
||||
indexed_vector<rule_info> m_rule_infos;
|
||||
|
||||
@@ -181,6 +181,7 @@ static bool resolve_list(std::string& cnd, const falco_list& list)
|
||||
{
|
||||
static std::string blanks = " \t\n\r";
|
||||
static std::string delims = blanks + "(),=";
|
||||
std::string tmp;
|
||||
std::string new_cnd;
|
||||
size_t start, end;
|
||||
bool used = false;
|
||||
@@ -212,7 +213,9 @@ static bool resolve_list(std::string& cnd, const falco_list& list)
|
||||
{
|
||||
sub += ", ";
|
||||
}
|
||||
sub += v;
|
||||
tmp = v;
|
||||
quote_item(tmp);
|
||||
sub += tmp;
|
||||
}
|
||||
// if substituted list is empty, we need to
|
||||
// remove a comma from the left or the right
|
||||
@@ -339,7 +342,6 @@ void rule_loader::compiler::compile_list_infos(
|
||||
const collector& col,
|
||||
indexed_vector<falco_list>& out) const
|
||||
{
|
||||
std::string tmp;
|
||||
std::list<std::string> used;
|
||||
falco_list v;
|
||||
for (const auto &list : col.lists())
|
||||
@@ -352,17 +354,14 @@ void rule_loader::compiler::compile_list_infos(
|
||||
if (ref && ref->index < list.visibility)
|
||||
{
|
||||
used.push_back(ref->name);
|
||||
for (auto val : ref->items)
|
||||
for (const auto &val : ref->items)
|
||||
{
|
||||
quote_item(val);
|
||||
v.items.push_back(val);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = item;
|
||||
quote_item(tmp);
|
||||
v.items.push_back(tmp);
|
||||
v.items.push_back(item);
|
||||
}
|
||||
}
|
||||
v.used = false;
|
||||
|
||||
@@ -17,10 +17,12 @@ limitations under the License.
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
|
||||
#include "rule_loader_reader.h"
|
||||
#include "falco_engine_version.h"
|
||||
#include "logger.h"
|
||||
#include "rule_loading_messages.h"
|
||||
|
||||
#define THROW(cond, err, ctx) { if ((cond)) { throw rule_loader::rule_load_exception(falco::load_result::LOAD_ERR_YAML_VALIDATE, (err), (ctx)); } }
|
||||
|
||||
@@ -45,6 +47,14 @@ static void decode_val_generic(const YAML::Node& item, const char *key, T& out,
|
||||
THROW(!YAML::convert<T>::decode(val, out), "Can't decode YAML scalar value", valctx);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void decode_val_generic(const YAML::Node& item, const char *key, std::optional<T>& out, const rule_loader::context& ctx, bool optional)
|
||||
{
|
||||
T decoded;
|
||||
decode_val_generic(item, key, decoded, ctx, optional);
|
||||
out = decoded;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void decode_val(const YAML::Node& item, const char *key, T& out, const rule_loader::context& ctx)
|
||||
{
|
||||
@@ -115,6 +125,73 @@ static void decode_tags(const YAML::Node& item, std::set<T>& out,
|
||||
decode_seq(item, "tags", inserter, ctx, optional);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void decode_tags(const YAML::Node& item, std::optional<std::set<T>>& out,
|
||||
const rule_loader::context& ctx)
|
||||
{
|
||||
std::set<T> decoded;
|
||||
decode_tags(item, decoded, ctx);
|
||||
out = decoded;
|
||||
}
|
||||
|
||||
static void decode_overrides(const YAML::Node& item,
|
||||
std::set<std::string>& overridable_append,
|
||||
std::set<std::string>& overridable_replace,
|
||||
std::set<std::string>& out_append,
|
||||
std::set<std::string>& out_replace,
|
||||
const rule_loader::context& ctx)
|
||||
{
|
||||
const YAML::Node& val = item["override"];
|
||||
|
||||
if(!val.IsDefined())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rule_loader::context overridectx(item, rule_loader::context::OVERRIDE, "", ctx);
|
||||
|
||||
for(YAML::const_iterator it=val.begin();it!=val.end();++it)
|
||||
{
|
||||
std::string key = it->first.as<std::string>();
|
||||
std::string operation = it->second.as<std::string>();
|
||||
|
||||
bool is_overridable_append = overridable_append.find(it->first.as<std::string>()) != overridable_append.end();
|
||||
bool is_overridable_replace = overridable_replace.find(it->first.as<std::string>()) != overridable_replace.end();
|
||||
|
||||
if (operation == "append")
|
||||
{
|
||||
rule_loader::context keyctx(it->first, rule_loader::context::OVERRIDE, key, overridectx);
|
||||
THROW(!is_overridable_append, std::string("Key '") + key + std::string("' cannot be appended to, use 'replace' instead"), keyctx);
|
||||
|
||||
out_append.insert(key);
|
||||
}
|
||||
else if (operation == "replace")
|
||||
{
|
||||
rule_loader::context keyctx(it->first, rule_loader::context::OVERRIDE, key, overridectx);
|
||||
THROW(!is_overridable_replace, std::string("Key '") + key + std::string("' cannot be replaced"), keyctx);
|
||||
|
||||
out_replace.insert(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
rule_loader::context operationctx(it->second, rule_loader::context::VALUE_FOR, key, overridectx);
|
||||
std::stringstream err_ss;
|
||||
err_ss << "Invalid override operation for key '" << key << "': '" << operation << "'. "
|
||||
<< "Allowed values are: ";
|
||||
if (is_overridable_append)
|
||||
{
|
||||
err_ss << "append ";
|
||||
}
|
||||
if (is_overridable_replace)
|
||||
{
|
||||
err_ss << "replace ";
|
||||
}
|
||||
|
||||
THROW(true, err_ss.str(), operationctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Don't call this directly, call decode_exception_{fields,comps,values} instead
|
||||
static void decode_exception_info_entry(
|
||||
const YAML::Node& item,
|
||||
@@ -187,7 +264,7 @@ static void decode_exception_values(
|
||||
|
||||
static void read_rule_exceptions(
|
||||
const YAML::Node& item,
|
||||
rule_loader::rule_info& v,
|
||||
std::vector<rule_loader::rule_exception_info>& exceptions,
|
||||
const rule_loader::context& parent,
|
||||
bool append)
|
||||
{
|
||||
@@ -239,10 +316,36 @@ static void read_rule_exceptions(
|
||||
v_ex.values.push_back(v_ex_val);
|
||||
}
|
||||
}
|
||||
v.exceptions.push_back(v_ex);
|
||||
exceptions.push_back(v_ex);
|
||||
}
|
||||
}
|
||||
|
||||
static void read_rule_exceptions(
|
||||
const YAML::Node& item,
|
||||
std::optional<std::vector<rule_loader::rule_exception_info>>& exceptions,
|
||||
const rule_loader::context& parent,
|
||||
bool append)
|
||||
{
|
||||
std::vector<rule_loader::rule_exception_info> decoded;
|
||||
read_rule_exceptions(item, decoded, parent, append);
|
||||
exceptions = decoded;
|
||||
}
|
||||
|
||||
inline static bool check_update_expected(std::set<std::string>& expected_keys, const std::set<std::string>& overrides, const std::string& override_type, const std::string& key, const rule_loader::context& ctx)
|
||||
{
|
||||
if (overrides.find(key) == overrides.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
THROW(expected_keys.find(key) == expected_keys.end(),
|
||||
std::string("An ") + override_type + " override for '" + key + "' was specified but '" + key + "' is not defined", ctx);
|
||||
|
||||
expected_keys.erase(key);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void read_item(
|
||||
rule_loader::configuration& cfg,
|
||||
rule_loader::collector& collector,
|
||||
@@ -337,6 +440,21 @@ static void read_item(
|
||||
decode_items(item, v.items, ctx);
|
||||
|
||||
decode_optional_val(item, "append", append, ctx);
|
||||
if(append)
|
||||
{
|
||||
cfg.res->add_warning(falco::load_result::LOAD_DEPRECATED_ITEM, WARNING_APPEND, ctx);
|
||||
}
|
||||
|
||||
std::set<std::string> override_append, override_replace;
|
||||
std::set<std::string> overridable {"items"};
|
||||
decode_overrides(item, overridable, overridable, override_append, override_replace, ctx);
|
||||
bool has_overrides = !override_append.empty() || !override_replace.empty();
|
||||
|
||||
THROW(append && has_overrides, ERROR_OVERRIDE_APPEND, ctx);
|
||||
|
||||
// Since a list only has items, if we have chosen to append them we can append the entire object
|
||||
// otherwise we just want to redefine the list.
|
||||
append |= override_append.find("items") != override_append.end();
|
||||
|
||||
if(append)
|
||||
{
|
||||
@@ -365,6 +483,21 @@ static void read_item(
|
||||
v.cond_ctx = rule_loader::context(item["condition"], rule_loader::context::MACRO_CONDITION, "", ctx);
|
||||
|
||||
decode_optional_val(item, "append", append, ctx);
|
||||
if(append)
|
||||
{
|
||||
cfg.res->add_warning(falco::load_result::LOAD_DEPRECATED_ITEM, WARNING_APPEND, ctx);
|
||||
}
|
||||
|
||||
std::set<std::string> override_append, override_replace;
|
||||
std::set<std::string> overridable {"condition"};
|
||||
decode_overrides(item, overridable, overridable, override_append, override_replace, ctx);
|
||||
bool has_overrides = !override_append.empty() || !override_replace.empty();
|
||||
|
||||
THROW((append && has_overrides), ERROR_OVERRIDE_APPEND, ctx);
|
||||
|
||||
// Since a macro only has a condition, if we have chosen to append to it we can append the entire object
|
||||
// otherwise we just want to redefine the macro.
|
||||
append |= override_append.find("condition") != override_append.end();
|
||||
|
||||
if(append)
|
||||
{
|
||||
@@ -384,28 +517,172 @@ static void read_item(
|
||||
decode_val(item, "rule", name, tmp);
|
||||
|
||||
rule_loader::context ctx(item, rule_loader::context::RULE, name, parent);
|
||||
rule_loader::rule_info v(ctx);
|
||||
v.name = name;
|
||||
|
||||
bool append = false;
|
||||
v.enabled = true;
|
||||
v.warn_evttypes = true;
|
||||
v.skip_if_unknown_filter = false;
|
||||
|
||||
decode_optional_val(item, "append", append, ctx);
|
||||
|
||||
if(append)
|
||||
bool has_append_flag = false;
|
||||
decode_optional_val(item, "append", has_append_flag, ctx);
|
||||
if(has_append_flag)
|
||||
{
|
||||
decode_optional_val(item, "condition", v.cond, ctx);
|
||||
cfg.res->add_warning(falco::load_result::LOAD_DEPRECATED_ITEM, WARNING_APPEND, ctx);
|
||||
}
|
||||
|
||||
std::set<std::string> override_append, override_replace;
|
||||
std::set<std::string> overridable_append {"condition", "output", "desc", "tags", "exceptions"};
|
||||
std::set<std::string> overridable_replace {
|
||||
"condition", "output", "desc", "priority", "tags", "exceptions", "enabled", "warn_evttypes", "skip-if-unknown-filter"};
|
||||
decode_overrides(item, overridable_append, overridable_replace, override_append, override_replace, ctx);
|
||||
bool has_overrides_append = !override_append.empty();
|
||||
bool has_overrides_replace = !override_replace.empty();
|
||||
bool has_overrides = has_overrides_append || has_overrides_replace;
|
||||
|
||||
THROW((has_append_flag && has_overrides), ERROR_OVERRIDE_APPEND, ctx);
|
||||
|
||||
if(has_overrides)
|
||||
{
|
||||
std::set<std::string> expected_keys;
|
||||
for (auto& key : overridable_append)
|
||||
{
|
||||
if (item[key].IsDefined())
|
||||
{
|
||||
expected_keys.insert(key);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& key : overridable_replace)
|
||||
{
|
||||
if (item[key].IsDefined())
|
||||
{
|
||||
expected_keys.insert(key);
|
||||
}
|
||||
}
|
||||
|
||||
// expected_keys is (appendable U replaceable) ^ (defined)
|
||||
|
||||
if (has_overrides_append)
|
||||
{
|
||||
rule_loader::rule_update_info v(ctx);
|
||||
v.name = name;
|
||||
if (check_update_expected(expected_keys, override_append, "append", "condition", ctx))
|
||||
{
|
||||
decode_val(item, "condition", v.cond, ctx);
|
||||
}
|
||||
|
||||
if (check_update_expected(expected_keys, override_append, "append", "exceptions", ctx))
|
||||
{
|
||||
read_rule_exceptions(item, v.exceptions, ctx, true);
|
||||
}
|
||||
|
||||
if (check_update_expected(expected_keys, override_append, "append", "output", ctx))
|
||||
{
|
||||
decode_val(item, "output", v.output, ctx);
|
||||
}
|
||||
|
||||
if (check_update_expected(expected_keys, override_append, "append", "desc", ctx))
|
||||
{
|
||||
decode_val(item, "desc", v.desc, ctx);
|
||||
}
|
||||
|
||||
if (check_update_expected(expected_keys, override_append, "append", "tags", ctx))
|
||||
{
|
||||
decode_tags(item, v.tags, ctx);
|
||||
}
|
||||
|
||||
collector.append(cfg, v);
|
||||
}
|
||||
|
||||
if (has_overrides_replace)
|
||||
{
|
||||
rule_loader::rule_update_info v(ctx);
|
||||
v.name = name;
|
||||
if (check_update_expected(expected_keys, override_replace, "replace", "condition", ctx))
|
||||
{
|
||||
decode_val(item, "condition", v.cond, ctx);
|
||||
}
|
||||
|
||||
if (check_update_expected(expected_keys, override_replace, "replace", "exceptions", ctx))
|
||||
{
|
||||
read_rule_exceptions(item, v.exceptions, ctx, true);
|
||||
}
|
||||
|
||||
if (check_update_expected(expected_keys, override_replace, "replace", "output", ctx))
|
||||
{
|
||||
decode_val(item, "output", v.output, ctx);
|
||||
}
|
||||
|
||||
if (check_update_expected(expected_keys, override_replace, "replace", "desc", ctx))
|
||||
{
|
||||
decode_val(item, "desc", v.desc, ctx);
|
||||
}
|
||||
|
||||
if (check_update_expected(expected_keys, override_replace, "replace", "tags", ctx))
|
||||
{
|
||||
decode_tags(item, v.tags, ctx);
|
||||
}
|
||||
|
||||
if (check_update_expected(expected_keys, override_replace, "replace", "priority", ctx))
|
||||
{
|
||||
std::string priority;
|
||||
decode_val(item, "priority", priority, ctx);
|
||||
rule_loader::context prictx(item["priority"], rule_loader::context::RULE_PRIORITY, "", ctx);
|
||||
falco_common::priority_type parsed_priority;
|
||||
THROW(!falco_common::parse_priority(priority, parsed_priority), "Invalid priority", prictx);
|
||||
v.priority = parsed_priority;
|
||||
}
|
||||
|
||||
if (check_update_expected(expected_keys, override_replace, "replace", "enabled", ctx))
|
||||
{
|
||||
decode_val(item, "enabled", v.enabled, ctx);
|
||||
}
|
||||
|
||||
if (check_update_expected(expected_keys, override_replace, "replace", "warn_evttypes", ctx))
|
||||
{
|
||||
decode_val(item, "warn_evttypes", v.warn_evttypes, ctx);
|
||||
}
|
||||
|
||||
if (check_update_expected(expected_keys, override_replace, "replace", "skip-if-unknown-filter", ctx))
|
||||
{
|
||||
decode_val(item, "skip-if-unknown-filter", v.skip_if_unknown_filter, ctx);
|
||||
}
|
||||
|
||||
collector.selective_replace(cfg, v);
|
||||
}
|
||||
|
||||
// if any expected key has not been defined throw an error
|
||||
for (auto &key : expected_keys) {
|
||||
rule_loader::context keyctx(item[key], rule_loader::context::OVERRIDE, key, ctx);
|
||||
THROW(true, "Unexpected key '" + key + "': no corresponding entry under 'override' is defined.", keyctx);
|
||||
}
|
||||
}
|
||||
else if(has_append_flag)
|
||||
{
|
||||
rule_loader::rule_update_info v(ctx);
|
||||
v.name = name;
|
||||
|
||||
if(item["condition"].IsDefined())
|
||||
{
|
||||
v.cond_ctx = rule_loader::context(item["condition"], rule_loader::context::RULE_CONDITION, "", ctx);
|
||||
decode_val(item, "condition", v.cond, ctx);
|
||||
}
|
||||
read_rule_exceptions(item, v, ctx, append);
|
||||
|
||||
if(item["exceptions"].IsDefined())
|
||||
{
|
||||
read_rule_exceptions(item, v.exceptions, ctx, true);
|
||||
}
|
||||
|
||||
// TODO restore this error and update testing
|
||||
//THROW((!v.cond.has_value() && !v.exceptions.has_value()),
|
||||
// "Appended rule must have exceptions or condition property",
|
||||
// v.ctx);
|
||||
|
||||
collector.append(cfg, v);
|
||||
}
|
||||
else
|
||||
{
|
||||
rule_loader::rule_info v(ctx);
|
||||
v.name = name;
|
||||
v.enabled = true;
|
||||
v.warn_evttypes = true;
|
||||
v.skip_if_unknown_filter = false;
|
||||
|
||||
// If the rule does *not* have any of
|
||||
// condition/output/desc/priority, it *must*
|
||||
// have an enabled property. Use the enabled
|
||||
@@ -417,6 +694,7 @@ static void read_item(
|
||||
!item["priority"].IsDefined())
|
||||
{
|
||||
decode_val(item, "enabled", v.enabled, ctx);
|
||||
cfg.res->add_warning(falco::load_result::LOAD_DEPRECATED_ITEM, WARNING_ENABLED, ctx);
|
||||
collector.enable(cfg, v);
|
||||
}
|
||||
else
|
||||
@@ -443,7 +721,7 @@ static void read_item(
|
||||
decode_optional_val(item, "warn_evttypes", v.warn_evttypes, ctx);
|
||||
decode_optional_val(item, "skip-if-unknown-filter", v.skip_if_unknown_filter, ctx);
|
||||
decode_tags(item, v.tags, ctx);
|
||||
read_rule_exceptions(item, v, ctx, append);
|
||||
read_rule_exceptions(item, v.exceptions, ctx, has_append_flag);
|
||||
collector.define(cfg, v);
|
||||
}
|
||||
}
|
||||
|
||||
23
userspace/engine/rule_loading_messages.h
Normal file
23
userspace/engine/rule_loading_messages.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
////////////////
|
||||
// Warnings
|
||||
////////////////
|
||||
|
||||
#define WARNING_APPEND "'append' key is deprecated. Add an 'append' entry (e.g. 'condition: append') under 'override' instead."
|
||||
|
||||
#define WARNING_ENABLED "The standalone 'enabled' key usage is deprecated. The correct approach requires also a 'replace' entry under the 'override' key (i.e. 'enabled: replace')."
|
||||
|
||||
////////////////
|
||||
// Errors
|
||||
////////////////
|
||||
|
||||
#define ERROR_OVERRIDE_APPEND "Keys 'override' and 'append: true' cannot be used together. Add an 'append' entry (e.g. 'condition: append') under 'override' instead."
|
||||
|
||||
#define ERROR_NO_PREVIOUS_MACRO "Macro uses 'append' or 'override.condition: append' but no macro by that name already exists"
|
||||
|
||||
#define ERROR_NO_PREVIOUS_LIST "List uses 'append' or 'override.items: append' but no list by that name already exists"
|
||||
|
||||
#define ERROR_NO_PREVIOUS_RULE_APPEND "Rule uses 'append' or 'override.<key>: append' but no rule by that name already exists"
|
||||
|
||||
#define ERROR_NO_PREVIOUS_RULE_REPLACE "An 'override.<key>: replace' to a rule was requested but no rule by that name already exists"
|
||||
@@ -79,17 +79,17 @@ static falco::app::run_result apply_deprecated_options(falco::app::state& s)
|
||||
if(s.config->m_syscall_drop_failed_exit != DEFAULT_DROP_FAILED_EXIT)
|
||||
{
|
||||
falco_logger::log(falco_logger::level::WARNING,
|
||||
"DEPRECATION NOTICE: 'syscall_drop_failed_exit' config is deprecated and will be removed in Falco 0.38! Use `engine.<driver>.drop_failed_exit' config instead\n");
|
||||
"DEPRECATION NOTICE: 'syscall_drop_failed_exit' config is deprecated and will be removed in Falco 0.38! Use 'engine.<driver>.drop_failed_exit' config instead\n");
|
||||
}
|
||||
if(s.config->m_syscall_buf_size_preset != DEFAULT_BUF_SIZE_PRESET)
|
||||
{
|
||||
falco_logger::log(falco_logger::level::WARNING,
|
||||
"DEPRECATION NOTICE: 'syscall_buf_size_preset' config is deprecated and will be removed in Falco 0.38! Use `engine.<driver>.buf_size_preset' config instead\n");
|
||||
"DEPRECATION NOTICE: 'syscall_buf_size_preset' config is deprecated and will be removed in Falco 0.38! Use 'engine.<driver>.buf_size_preset' config instead\n");
|
||||
}
|
||||
if(s.config->m_cpus_for_each_syscall_buffer != DEFAULT_CPUS_FOR_EACH_SYSCALL_BUFFER)
|
||||
{
|
||||
falco_logger::log(falco_logger::level::WARNING,
|
||||
"DEPRECATION NOTICE: 'modern_bpf.cpus_for_each_syscall_buffer' config is deprecated and will be removed in Falco 0.38! Use `engine.modern_ebpf.cpus_for_each_buffer' config instead\n");
|
||||
"DEPRECATION NOTICE: 'modern_bpf.cpus_for_each_syscall_buffer' config is deprecated and will be removed in Falco 0.38! Use 'engine.modern_ebpf.cpus_for_each_buffer' config instead\n");
|
||||
}
|
||||
|
||||
// Replace the kmod default values in case the engine was open with the kmod.
|
||||
@@ -102,7 +102,7 @@ static falco::app::run_result apply_deprecated_options(falco::app::state& s)
|
||||
// use the requested driver.
|
||||
if (getenv(FALCO_BPF_ENV_VARIABLE))
|
||||
{
|
||||
falco_logger::log(falco_logger::level::WARNING, "DEPRECATION NOTICE: the 'FALCO_BPF_PROBE' environment variable is deprecated and will be removed in Falco 0.38!\n");
|
||||
falco_logger::log(falco_logger::level::WARNING, "DEPRECATION NOTICE: the 'FALCO_BPF_PROBE' environment variable is deprecated and will be removed in Falco 0.38! Set 'engine.kind: ebpf' and use 'engine.ebpf' config instead in falco.yaml\n");
|
||||
s.config->m_engine_mode = engine_kind_t::EBPF;
|
||||
s.config->m_ebpf.m_probe_path = getenv(FALCO_BPF_ENV_VARIABLE);
|
||||
s.config->m_ebpf.m_drop_failed_exit = s.config->m_syscall_drop_failed_exit;
|
||||
@@ -110,7 +110,7 @@ static falco::app::run_result apply_deprecated_options(falco::app::state& s)
|
||||
}
|
||||
else if (s.options.modern_bpf)
|
||||
{
|
||||
falco_logger::log(falco_logger::level::WARNING, "DEPRECATION NOTICE: the '--modern-bpf' command line option is deprecated and will be removed in Falco 0.38!\n");
|
||||
falco_logger::log(falco_logger::level::WARNING, "DEPRECATION NOTICE: the '--modern-bpf' command line option is deprecated and will be removed in Falco 0.38! Set 'engine.kind: modern_ebpf' and use 'engine.modern_ebpf' config instead in falco.yaml\n");
|
||||
s.config->m_engine_mode = engine_kind_t::MODERN_EBPF;
|
||||
s.config->m_modern_ebpf.m_drop_failed_exit = s.config->m_syscall_drop_failed_exit;
|
||||
s.config->m_modern_ebpf.m_buf_size_preset = s.config->m_syscall_buf_size_preset;
|
||||
@@ -118,19 +118,19 @@ static falco::app::run_result apply_deprecated_options(falco::app::state& s)
|
||||
}
|
||||
if (!s.options.gvisor_config.empty())
|
||||
{
|
||||
falco_logger::log(falco_logger::level::WARNING, "DEPRECATION NOTICE: the '-g,--gvisor-config' command line option is deprecated and will be removed in Falco 0.38!\n");
|
||||
falco_logger::log(falco_logger::level::WARNING, "DEPRECATION NOTICE: the '-g,--gvisor-config' command line option is deprecated and will be removed in Falco 0.38! Set 'engine.kind: gvisor' and use 'engine.gvisor' config instead in falco.yaml\n");
|
||||
s.config->m_engine_mode = engine_kind_t::GVISOR;
|
||||
s.config->m_gvisor.m_config = s.options.gvisor_config;
|
||||
s.config->m_gvisor.m_root = s.options.gvisor_root;
|
||||
}
|
||||
if (s.options.nodriver)
|
||||
{
|
||||
falco_logger::log(falco_logger::level::WARNING, "DEPRECATION NOTICE: the '--nodriver' command line option is deprecated and will be removed in Falco 0.38!\n");
|
||||
s.config->m_engine_mode = engine_kind_t::NONE;
|
||||
falco_logger::log(falco_logger::level::WARNING, "DEPRECATION NOTICE: the '--nodriver' command line option is deprecated and will be removed in Falco 0.38! Set 'engine.kind: nodriver' instead in falco.yaml\n");
|
||||
s.config->m_engine_mode = engine_kind_t::NODRIVER;
|
||||
}
|
||||
if (!s.options.capture_file.empty())
|
||||
{
|
||||
falco_logger::log(falco_logger::level::WARNING, "DEPRECATION NOTICE: the '-e' command line option is deprecated and will be removed in Falco 0.38!\n");
|
||||
falco_logger::log(falco_logger::level::WARNING, "DEPRECATION NOTICE: the '-e' command line option is deprecated and will be removed in Falco 0.38! Set 'engine.kind: replay' and use 'engine.replay' config instead in falco.yaml\n");
|
||||
s.config->m_engine_mode = engine_kind_t::REPLAY;
|
||||
s.config->m_replay.m_capture_file = s.options.capture_file;
|
||||
}
|
||||
|
||||
@@ -79,10 +79,9 @@ falco::app::run_result falco::app::actions::load_rules_files(falco::app::state&
|
||||
break;
|
||||
}
|
||||
|
||||
// If verbose is true, also print any warnings
|
||||
if(s.options.verbose && res->has_warnings())
|
||||
if(res->has_warnings())
|
||||
{
|
||||
fprintf(stderr, "%s\n", res->as_string(true, rc).c_str());
|
||||
falco_logger::log(falco_logger::level::WARNING,res->as_string(true, rc) + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,12 +114,7 @@ falco::app::run_result falco::app::actions::validate_rules_files(falco::app::sta
|
||||
// file was ok with warnings, without actually
|
||||
// printing the warnings.
|
||||
summary += filename + ": Ok, with warnings";
|
||||
|
||||
// If verbose is true, print the warnings now.
|
||||
if(s.options.verbose)
|
||||
{
|
||||
fprintf(stderr, "%s\n", res->as_string(true, rc).c_str());
|
||||
}
|
||||
falco_logger::log(falco_logger::level::WARNING, res->as_string(true, rc) + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ struct state
|
||||
|
||||
inline bool is_nodriver() const
|
||||
{
|
||||
return config->m_engine_mode == engine_kind_t::NONE;
|
||||
return config->m_engine_mode == engine_kind_t::NODRIVER;
|
||||
}
|
||||
|
||||
inline bool is_source_enabled(const std::string& src) const
|
||||
|
||||
@@ -109,7 +109,7 @@ void falco_configuration::load_engine_config(const std::string& config_name, con
|
||||
{"modern_ebpf",engine_kind_t::MODERN_EBPF},
|
||||
{"replay",engine_kind_t::REPLAY},
|
||||
{"gvisor",engine_kind_t::GVISOR},
|
||||
{"none",engine_kind_t::NONE},
|
||||
{"nodriver",engine_kind_t::NODRIVER},
|
||||
};
|
||||
|
||||
auto driver_mode_str = config.get_scalar<std::string>("engine.kind", "kmod");
|
||||
@@ -172,7 +172,7 @@ void falco_configuration::load_engine_config(const std::string& config_name, con
|
||||
}
|
||||
m_gvisor.m_root = config.get_scalar<std::string>("engine.gvisor.root", "");
|
||||
break;
|
||||
case engine_kind_t::NONE:
|
||||
case engine_kind_t::NODRIVER:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ enum class engine_kind_t : uint8_t
|
||||
MODERN_EBPF,
|
||||
REPLAY,
|
||||
GVISOR,
|
||||
NONE
|
||||
NODRIVER
|
||||
};
|
||||
|
||||
class falco_configuration
|
||||
|
||||
@@ -366,9 +366,16 @@ void stats_writer::collector::get_metrics_output_fields_additional(
|
||||
sinsp_thread_manager* thread_manager = inspector->m_thread_manager;
|
||||
const scap_stats_v2* sinsp_stats_v2_snapshot = libsinsp::stats::get_sinsp_stats_v2(flags, agent_info, thread_manager, sinsp_stats_v2, buffer, &nstats, &rc);
|
||||
|
||||
uint32_t base_stat = 0;
|
||||
// todo @incertum this needs to become better with the next proper stats refactor in libs 0.15.0
|
||||
if ((flags & PPM_SCAP_STATS_STATE_COUNTERS) && !(flags & PPM_SCAP_STATS_RESOURCE_UTILIZATION))
|
||||
{
|
||||
base_stat = SINSP_STATS_V2_N_THREADS;
|
||||
}
|
||||
|
||||
if (sinsp_stats_v2_snapshot && rc == 0 && nstats > 0)
|
||||
{
|
||||
for(uint32_t stat = 0; stat < nstats; stat++)
|
||||
for(uint32_t stat = base_stat; stat < nstats; stat++)
|
||||
{
|
||||
if (sinsp_stats_v2_snapshot[stat].name[0] == '\0')
|
||||
{
|
||||
@@ -376,6 +383,12 @@ void stats_writer::collector::get_metrics_output_fields_additional(
|
||||
}
|
||||
char metric_name[STATS_NAME_MAX] = "falco.";
|
||||
strlcat(metric_name, sinsp_stats_v2_snapshot[stat].name, sizeof(metric_name));
|
||||
// todo @incertum temporary fix for n_fds and n_threads, type assignment was missed in libs, will be fixed in libs 0.15.0
|
||||
if (strncmp(sinsp_stats_v2_snapshot[stat].name, "n_fds", 6) == 0 || strncmp(sinsp_stats_v2_snapshot[stat].name, "n_threads", 10) == 0)
|
||||
{
|
||||
output_fields[metric_name] = sinsp_stats_v2_snapshot[stat].value.u64;
|
||||
}
|
||||
|
||||
switch(sinsp_stats_v2_snapshot[stat].type)
|
||||
{
|
||||
case STATS_VALUE_TYPE_U64:
|
||||
|
||||
Reference in New Issue
Block a user