mirror of
https://github.com/falcosecurity/falco.git
synced 2026-03-20 11:42:06 +00:00
Compare commits
28 Commits
master
...
release/0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0d3bef3e5 | ||
|
|
89a024bfdf | ||
|
|
3bc95a290a | ||
|
|
c20907332d | ||
|
|
2804d60bd2 | ||
|
|
7c8209ed8e | ||
|
|
3c4b315ff2 | ||
|
|
92d6c4bab6 | ||
|
|
51a19ea6cb | ||
|
|
88d73505b0 | ||
|
|
f2d23af415 | ||
|
|
10f87e515e | ||
|
|
82016080d0 | ||
|
|
bbb4d6e9b6 | ||
|
|
e34507c739 | ||
|
|
ff32882a7f | ||
|
|
f1b208f8fb | ||
|
|
ff65dc75ae | ||
|
|
a1ff7c7384 | ||
|
|
fb47e816ae | ||
|
|
39dfd6765a | ||
|
|
f4477f1ac2 | ||
|
|
92fa3b5347 | ||
|
|
fad91ea080 | ||
|
|
5e9a8fd665 | ||
|
|
241f620956 | ||
|
|
80816e67d6 | ||
|
|
5874dc1f95 |
@@ -1 +1,3 @@
|
||||
# Add here new files to ignore
|
||||
# These files contain some JSON schema definitions that are not C++ code
|
||||
userspace/falco/config_json_schema.h
|
||||
userspace/engine/rule_json_schema.h
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
# Add here new files to ignore
|
||||
# This commit formatted the Falco code for the first time.
|
||||
50b98b30e588eadce641136da85bc94a60eb6a3d
|
||||
2
.github/workflows/reusable_build_dev.yaml
vendored
2
.github/workflows/reusable_build_dev.yaml
vendored
@@ -39,7 +39,7 @@ permissions:
|
||||
jobs:
|
||||
build-and-test:
|
||||
# See https://github.com/actions/runner/issues/409#issuecomment-1158849936
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'actuated-arm64-8cpu-16gb') || 'ubuntu-22.04' }}
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'oracle-aarch64-4cpu-16gb') || 'ubuntu-22.04' }}
|
||||
outputs:
|
||||
cmdout: ${{ steps.run_cmd.outputs.out }}
|
||||
steps:
|
||||
|
||||
2
.github/workflows/reusable_build_docker.yaml
vendored
2
.github/workflows/reusable_build_docker.yaml
vendored
@@ -31,7 +31,7 @@ permissions:
|
||||
jobs:
|
||||
build-docker:
|
||||
# See https://github.com/actions/runner/issues/409#issuecomment-1158849936
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'actuated-arm64-8cpu-16gb') || 'ubuntu-latest' }}
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'oracle-aarch64-4cpu-16gb') || 'ubuntu-latest' }}
|
||||
env:
|
||||
TARGETARCH: ${{ (inputs.arch == 'aarch64' && 'arm64') || 'amd64' }}
|
||||
steps:
|
||||
|
||||
@@ -27,7 +27,7 @@ permissions:
|
||||
jobs:
|
||||
build-modern-bpf-skeleton:
|
||||
# See https://github.com/actions/runner/issues/409#issuecomment-1158849936
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'actuated-arm64-8cpu-16gb') || 'ubuntu-latest' }}
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'oracle-aarch64-4cpu-16gb') || 'ubuntu-latest' }}
|
||||
container: fedora:latest
|
||||
steps:
|
||||
# Always install deps before invoking checkout action, to properly perform a full clone.
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
# See https://github.com/actions/runner/issues/409#issuecomment-1158849936
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'actuated-arm64-8cpu-16gb') || 'ubuntu-latest' }}
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'oracle-aarch64-4cpu-16gb') || 'ubuntu-latest' }}
|
||||
needs: [build-modern-bpf-skeleton]
|
||||
container: centos:7
|
||||
steps:
|
||||
|
||||
@@ -27,7 +27,7 @@ permissions:
|
||||
jobs:
|
||||
test-packages:
|
||||
# See https://github.com/actions/runner/issues/409#issuecomment-1158849936
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'actuated-arm64-8cpu-16gb') || 'ubuntu-latest' }}
|
||||
runs-on: ${{ (inputs.arch == 'aarch64' && 'oracle-aarch64-4cpu-16gb') || 'ubuntu-latest' }}
|
||||
steps:
|
||||
- name: Download binary
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
|
||||
131
CHANGELOG.md
131
CHANGELOG.md
@@ -1,5 +1,136 @@
|
||||
# Change Log
|
||||
|
||||
## v0.39.2
|
||||
|
||||
Released on 2024-11-21
|
||||
|
||||
### Minor Changes
|
||||
|
||||
* update(cmake): bumped falcoctl to v0.10.1. [[#3408](https://github.com/falcosecurity/falco/pull/3408)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* update(cmake): bump yaml-cpp to latest master. [[#3394](https://github.com/falcosecurity/falco/pull/3394)] - [@FedeDP](https://github.com/FedeDP)
|
||||
|
||||
### Non user-facing changes
|
||||
|
||||
* update(ci): use arm64 CNCF runners for GH actions [[#3386](https://github.com/falcosecurity/falco/pull/3386)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
|
||||
### Statistics
|
||||
|
||||
| MERGED PRS | NUMBER |
|
||||
|-----------------|--------|
|
||||
| Not user-facing | 1 |
|
||||
| Release note | 2 |
|
||||
| Total | 3 |
|
||||
|
||||
|
||||
## v0.39.1
|
||||
|
||||
Released on 2024-10-09
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix(engine): allow null init_config for plugin info [[#3372](https://github.com/falcosecurity/falco/pull/3372)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* fix(engine): fix parsing issues in -o key={object} when the object definition contains a comma [[#3363](https://github.com/falcosecurity/falco/pull/3363)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* fix(userspace/falco): fix event set selection for plugin with parsing capability [[#3368](https://github.com/falcosecurity/falco/pull/3368)] - [@FedeDP](https://github.com/FedeDP)
|
||||
|
||||
### Statistics
|
||||
|
||||
| MERGED PRS | NUMBER |
|
||||
|-----------------|--------|
|
||||
| Not user-facing | 0 |
|
||||
| Release note | 3 |
|
||||
| Total | 3 |
|
||||
|
||||
|
||||
## v0.39.0
|
||||
|
||||
Released on 2024-10-01
|
||||
|
||||
### Breaking Changes :warning:
|
||||
|
||||
* fix(falco_metrics)!: split tags label into multiple `tag_`-prefixed labels [[#3337](https://github.com/falcosecurity/falco/pull/3337)] - [@ekoops](https://github.com/ekoops)
|
||||
* fix(falco_metrics)!: use full name for configs and rules files [[#3337](https://github.com/falcosecurity/falco/pull/3337)] - [@ekoops](https://github.com/ekoops)
|
||||
* update(falco_metrics)!: rearrange `n_evts_cpu` and `n_drops_cpu` Prometheus metrics to follow best practices [[#3319](https://github.com/falcosecurity/falco/pull/3319)] - [@incertum](https://github.com/incertum)
|
||||
* cleanup(userspace/falco)!: drop deprecated -t,-T,-D options. [[#3311](https://github.com/falcosecurity/falco/pull/3311)] - [@FedeDP](https://github.com/FedeDP)
|
||||
|
||||
|
||||
### Major Changes
|
||||
|
||||
* feat(stats): add host_netinfo networking information stats family [[#3344](https://github.com/falcosecurity/falco/pull/3344)] - [@ekoops](https://github.com/ekoops)
|
||||
* new(falco): add json_include_message_property to have a message field without date and priority [[#3314](https://github.com/falcosecurity/falco/pull/3314)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* new(userspace/falco,userspace/engine): rule json schema validation [[#3313](https://github.com/falcosecurity/falco/pull/3313)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* new(falco): introduce append_output configuration [[#3308](https://github.com/falcosecurity/falco/pull/3308)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* new(userspace/falco): added --config-schema action to print config schema [[#3312](https://github.com/falcosecurity/falco/pull/3312)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* new(falco): enable CLI options with -o key={object} [[#3310](https://github.com/falcosecurity/falco/pull/3310)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* new(config): add `container_engines` config to falco.yaml [[#3266](https://github.com/falcosecurity/falco/pull/3266)] - [@incertum](https://github.com/incertum)
|
||||
* new(metrics): add host_ifinfo metric [[#3253](https://github.com/falcosecurity/falco/pull/3253)] - [@incertum](https://github.com/incertum)
|
||||
* new(userspace,unit_tests): validate configs against schema [[#3302](https://github.com/falcosecurity/falco/pull/3302)] - [@FedeDP](https://github.com/FedeDP)
|
||||
|
||||
|
||||
### Minor Changes
|
||||
|
||||
* update(falco): upgrade libs to 0.18.1 [[#3349](https://github.com/falcosecurity/falco/pull/3349)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* update(systemd): users can refer to systemd falco services with a consistent unique alias falco.service [[#3332](https://github.com/falcosecurity/falco/pull/3332)] - [@ekoops](https://github.com/ekoops)
|
||||
* update(cmake): bump libs to 0.18.0 and driver to 7.3.0+driver. [[#3330](https://github.com/falcosecurity/falco/pull/3330)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* chore(userspace/falco): deprecate `cri` related CLI options. [[#3329](https://github.com/falcosecurity/falco/pull/3329)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* update(cmake): bumped falcoctl to v0.10.0 and rules to 3.2.0 [[#3327](https://github.com/falcosecurity/falco/pull/3327)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* update(falco_metrics): change prometheus rules metric naming [[#3324](https://github.com/falcosecurity/falco/pull/3324)] - [@incertum](https://github.com/incertum)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix(falco): allow disable_cri_async from both CLI and config [[#3353](https://github.com/falcosecurity/falco/pull/3353)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* fix(engine): sync outputs before printing stats at shutdown [[#3338](https://github.com/falcosecurity/falco/pull/3338)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* fix(falco): allow plugin init_config map in json schema [[#3335](https://github.com/falcosecurity/falco/pull/3335)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* fix(userspace/falco): properly account for plugin with CAP_PARSING when computing interesting sc set [[#3334](https://github.com/falcosecurity/falco/pull/3334)] - [@FedeDP](https://github.com/FedeDP)
|
||||
|
||||
|
||||
|
||||
### Non user-facing changes
|
||||
|
||||
* feat(cmake): add conditional builds for falcoctl and rules paths [[#3305](https://github.com/falcosecurity/falco/pull/3305)] - [@tembleking](https://github.com/tembleking)
|
||||
* cleanup(falco): ignore lint commit [[#3354](https://github.com/falcosecurity/falco/pull/3354)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* chore(falco): apply code formatting [[#3350](https://github.com/falcosecurity/falco/pull/3350)] - [@poiana](https://github.com/poiana)
|
||||
* chore: ignore_some_files for clang format [[#3351](https://github.com/falcosecurity/falco/pull/3351)] - [@Andreagit97](https://github.com/Andreagit97)
|
||||
* sync: release 0.39.x [[#3340](https://github.com/falcosecurity/falco/pull/3340)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* fix(userspace/engine): improve rule json schema to account for `source` and `required_plugin_versions` [[#3328](https://github.com/falcosecurity/falco/pull/3328)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* cleanup(falco): use header file for json schema [[#3325](https://github.com/falcosecurity/falco/pull/3325)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* update(engine): modify append_output format [[#3322](https://github.com/falcosecurity/falco/pull/3322)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
* chore: scaffolding for enabling code formatting [[#3321](https://github.com/falcosecurity/falco/pull/3321)] - [@Andreagit97](https://github.com/Andreagit97)
|
||||
* update(cmake): bump libs and driver to 0.18.0-rc1. [[#3320](https://github.com/falcosecurity/falco/pull/3320)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* fix(ci): restore master and release CI workflow permissions. [[#3317](https://github.com/falcosecurity/falco/pull/3317)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* fixed the token-permission and pinned-dependencies issue [[#3299](https://github.com/falcosecurity/falco/pull/3299)] - [@harshitasao](https://github.com/harshitasao)
|
||||
* update(cmake): bump falcoctl to v0.10.0-rc1 [[#3316](https://github.com/falcosecurity/falco/pull/3316)] - [@alacuku](https://github.com/alacuku)
|
||||
* ci(insecure-api): update semgrep docker image [[#3315](https://github.com/falcosecurity/falco/pull/3315)] - [@francesco-furlan](https://github.com/francesco-furlan)
|
||||
* Add demo environment instructions and docker-config files [[#3295](https://github.com/falcosecurity/falco/pull/3295)] - [@bbl232](https://github.com/bbl232)
|
||||
* chore(deps): Bump submodules/falcosecurity-rules from `baecf18` to `b6ad373` [[#3301](https://github.com/falcosecurity/falco/pull/3301)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* update(cmake): bump libs and driver to latest master [[#3283](https://github.com/falcosecurity/falco/pull/3283)] - [@jasondellaluce](https://github.com/jasondellaluce)
|
||||
* chore(deps): Bump submodules/falcosecurity-rules from `342b20d` to `baecf18` [[#3298](https://github.com/falcosecurity/falco/pull/3298)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* chore(deps): Bump submodules/falcosecurity-rules from `068f0f2` to `342b20d` [[#3288](https://github.com/falcosecurity/falco/pull/3288)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* vote: add sgaist to OWNERS [[#3264](https://github.com/falcosecurity/falco/pull/3264)] - [@sgaist](https://github.com/sgaist)
|
||||
* Add Tulip Retail to adopters list [[#3291](https://github.com/falcosecurity/falco/pull/3291)] - [@bbl232](https://github.com/bbl232)
|
||||
* chore(deps): Bump submodules/falcosecurity-rules from `28b98b6` to `068f0f2` [[#3282](https://github.com/falcosecurity/falco/pull/3282)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* chore(deps): Bump submodules/falcosecurity-rules from `c0a9bf1` to `28b98b6` [[#3267](https://github.com/falcosecurity/falco/pull/3267)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* Added the OpenSSF Scorecard Badge [[#3250](https://github.com/falcosecurity/falco/pull/3250)] - [@harshitasao](https://github.com/harshitasao)
|
||||
* chore(deps): Bump submodules/falcosecurity-rules from `ea57e78` to `c0a9bf1` [[#3247](https://github.com/falcosecurity/falco/pull/3247)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* update(cmake,userspace): bump libs and driver to latest master. [[#3263](https://github.com/falcosecurity/falco/pull/3263)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* If rule compilation fails, return immediately [[#3260](https://github.com/falcosecurity/falco/pull/3260)] - [@mstemm](https://github.com/mstemm)
|
||||
* new(userspace/engine): generalize indexable ruleset [[#3251](https://github.com/falcosecurity/falco/pull/3251)] - [@mstemm](https://github.com/mstemm)
|
||||
* update(cmake): bump libs to master. [[#3249](https://github.com/falcosecurity/falco/pull/3249)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* chore(deps): Bump submodules/falcosecurity-rules from `df963b6` to `ea57e78` [[#3240](https://github.com/falcosecurity/falco/pull/3240)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* chore(ci): enable dummy tests on the testing framework. [[#3233](https://github.com/falcosecurity/falco/pull/3233)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* chore(deps): Bump submodules/falcosecurity-rules from `679a50a` to `df963b6` [[#3231](https://github.com/falcosecurity/falco/pull/3231)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* update(cmake): bump libs and driver to master. [[#3225](https://github.com/falcosecurity/falco/pull/3225)] - [@FedeDP](https://github.com/FedeDP)
|
||||
* chore(deps): Bump submodules/falcosecurity-rules from `9e56293` to `679a50a` [[#3222](https://github.com/falcosecurity/falco/pull/3222)] - [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* update(docs): update CHANGELOG for 0.38.0 (master branch) [[#3224](https://github.com/falcosecurity/falco/pull/3224)] - [@LucaGuerra](https://github.com/LucaGuerra)
|
||||
|
||||
### Statistics
|
||||
|
||||
| MERGED PRS | NUMBER |
|
||||
|-----------------|--------|
|
||||
| Not user-facing | 35 |
|
||||
| Release note | 22 |
|
||||
| Total | 57 |
|
||||
|
||||
## v0.38.2
|
||||
|
||||
Released on 2024-08-19
|
||||
|
||||
208
CMakeLists.txt
208
CMakeLists.txt
@@ -2,14 +2,15 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# 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.
|
||||
#
|
||||
cmake_minimum_required(VERSION 3.5.1)
|
||||
|
||||
@@ -18,7 +19,11 @@ project(falco)
|
||||
option(USE_BUNDLED_DEPS "Bundle hard to find dependencies into the Falco binary" ON)
|
||||
option(USE_DYNAMIC_LIBELF "Dynamically link libelf" ON)
|
||||
option(BUILD_WARNINGS_AS_ERRORS "Enable building with -Wextra -Werror flags" OFF)
|
||||
option(MINIMAL_BUILD "Build a minimal version of Falco, containing only the engine and basic input/output (EXPERIMENTAL)" OFF)
|
||||
option(
|
||||
MINIMAL_BUILD
|
||||
"Build a minimal version of Falco, containing only the engine and basic input/output (EXPERIMENTAL)"
|
||||
OFF
|
||||
)
|
||||
option(MUSL_OPTIMIZED_BUILD "Enable if you want a musl optimized build" OFF)
|
||||
option(BUILD_FALCO_UNIT_TESTS "Build falco unit tests" OFF)
|
||||
option(USE_ASAN "Build with AddressSanitizer" OFF)
|
||||
@@ -26,54 +31,70 @@ option(USE_UBSAN "Build with UndefinedBehaviorSanitizer" OFF)
|
||||
option(UBSAN_HALT_ON_ERROR "Halt on error when building with UBSan" ON)
|
||||
|
||||
if(WIN32)
|
||||
if(POLICY CMP0091)
|
||||
# Needed for CMAKE_MSVC_RUNTIME_LIBRARY
|
||||
# https://cmake.org/cmake/help/latest/policy/CMP0091.html
|
||||
cmake_policy(SET CMP0091 NEW)
|
||||
endif()
|
||||
if(POLICY CMP0091)
|
||||
# Needed for CMAKE_MSVC_RUNTIME_LIBRARY
|
||||
# https://cmake.org/cmake/help/latest/policy/CMP0091.html
|
||||
cmake_policy(SET CMP0091 NEW)
|
||||
endif()
|
||||
set(CPACK_GENERATOR "NSIS") # this needs NSIS installed, and available
|
||||
elseif (APPLE)
|
||||
elseif(APPLE)
|
||||
set(CPACK_GENERATOR "DragNDrop")
|
||||
elseif(EMSCRIPTEN)
|
||||
set(USE_BUNDLED_DEPS ON CACHE BOOL "" FORCE)
|
||||
set(BUILD_DRIVER OFF CACHE BOOL "" FORCE)
|
||||
set(ENABLE_DKMS OFF CACHE BOOL "" FORCE)
|
||||
set(BUILD_BPF OFF CACHE BOOL "" FORCE)
|
||||
set(CPACK_GENERATOR TGZ CACHE BOOL "" FORCE)
|
||||
set(USE_BUNDLED_DEPS
|
||||
ON
|
||||
CACHE BOOL "" FORCE
|
||||
)
|
||||
set(BUILD_DRIVER
|
||||
OFF
|
||||
CACHE BOOL "" FORCE
|
||||
)
|
||||
set(ENABLE_DKMS
|
||||
OFF
|
||||
CACHE BOOL "" FORCE
|
||||
)
|
||||
set(BUILD_BPF
|
||||
OFF
|
||||
CACHE BOOL "" FORCE
|
||||
)
|
||||
set(CPACK_GENERATOR
|
||||
TGZ
|
||||
CACHE BOOL "" FORCE
|
||||
)
|
||||
endif()
|
||||
|
||||
# gVisor is currently only supported on Linux x86_64
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT MINIMAL_BUILD)
|
||||
option(BUILD_FALCO_GVISOR "Build gVisor support for Falco" ON)
|
||||
if (BUILD_FALCO_GVISOR)
|
||||
add_definitions(-DHAS_GVISOR)
|
||||
endif()
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64"
|
||||
AND CMAKE_SYSTEM_NAME MATCHES "Linux"
|
||||
AND NOT MINIMAL_BUILD
|
||||
)
|
||||
option(BUILD_FALCO_GVISOR "Build gVisor support for Falco" ON)
|
||||
if(BUILD_FALCO_GVISOR)
|
||||
add_definitions(-DHAS_GVISOR)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Modern BPF is not supported on not Linux systems and in MINIMAL_BUILD
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT MINIMAL_BUILD)
|
||||
option(BUILD_FALCO_MODERN_BPF "Build modern BPF support for Falco" ON)
|
||||
if(BUILD_FALCO_MODERN_BPF)
|
||||
add_definitions(-DHAS_MODERN_BPF)
|
||||
endif()
|
||||
option(BUILD_FALCO_MODERN_BPF "Build modern BPF support for Falco" ON)
|
||||
if(BUILD_FALCO_MODERN_BPF)
|
||||
add_definitions(-DHAS_MODERN_BPF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# We shouldn't need to set this, see https://gitlab.kitware.com/cmake/cmake/-/issues/16419
|
||||
option(EP_UPDATE_DISCONNECTED "ExternalProject update disconnected" OFF)
|
||||
if (${EP_UPDATE_DISCONNECTED})
|
||||
set_property(
|
||||
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
PROPERTY EP_UPDATE_DISCONNECTED TRUE)
|
||||
if(${EP_UPDATE_DISCONNECTED})
|
||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY EP_UPDATE_DISCONNECTED TRUE)
|
||||
endif()
|
||||
|
||||
# Elapsed time
|
||||
# set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time") # TODO(fntlnz, leodido): add a flag to enable this
|
||||
# Elapsed time set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time") #
|
||||
# TODO(fntlnz, leodido): add a flag to enable this
|
||||
|
||||
# Make flag for parallel processing
|
||||
include(ProcessorCount)
|
||||
processorcount(PROCESSOR_COUNT)
|
||||
ProcessorCount(PROCESSOR_COUNT)
|
||||
if(NOT PROCESSOR_COUNT EQUAL 0)
|
||||
set(PROCESSOUR_COUNT_MAKE_FLAG -j${PROCESSOR_COUNT})
|
||||
set(PROCESSOUR_COUNT_MAKE_FLAG -j${PROCESSOR_COUNT})
|
||||
endif()
|
||||
|
||||
# Custom CMake modules
|
||||
@@ -83,14 +104,14 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
|
||||
include(GNUInstallDirs)
|
||||
|
||||
if(NOT DEFINED FALCO_ETC_DIR)
|
||||
set(FALCO_ETC_DIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}/falco")
|
||||
set(FALCO_ETC_DIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}/falco")
|
||||
endif()
|
||||
|
||||
# This will be used to print the architecture for which Falco is compiled.
|
||||
if (EMSCRIPTEN)
|
||||
set(FALCO_TARGET_ARCH "wasm")
|
||||
if(EMSCRIPTEN)
|
||||
set(FALCO_TARGET_ARCH "wasm")
|
||||
else()
|
||||
set(FALCO_TARGET_ARCH ${CMAKE_SYSTEM_PROCESSOR})
|
||||
set(FALCO_TARGET_ARCH ${CMAKE_SYSTEM_PROCESSOR})
|
||||
endif()
|
||||
|
||||
include(CompilerFlags)
|
||||
@@ -100,19 +121,20 @@ set(DRIVER_NAME "falco")
|
||||
set(DRIVER_DEVICE_NAME "falco")
|
||||
set(DRIVERS_REPO "https://download.falco.org/driver")
|
||||
|
||||
# If no path is provided, try to search the BPF probe in: `home/.falco/falco-bpf.o`
|
||||
# This is the same fallback that we had in the libraries: `SCAP_PROBE_BPF_FILEPATH`.
|
||||
# If no path is provided, try to search the BPF probe in: `home/.falco/falco-bpf.o` This is the same
|
||||
# fallback that we had in the libraries: `SCAP_PROBE_BPF_FILEPATH`.
|
||||
set(FALCO_PROBE_BPF_FILEPATH ".${DRIVER_NAME}/${DRIVER_NAME}-bpf.o")
|
||||
add_definitions(-DFALCO_PROBE_BPF_FILEPATH="${FALCO_PROBE_BPF_FILEPATH}")
|
||||
|
||||
if(NOT DEFINED FALCO_COMPONENT_NAME)
|
||||
set(FALCO_COMPONENT_NAME "${CMAKE_PROJECT_NAME}")
|
||||
set(FALCO_COMPONENT_NAME "${CMAKE_PROJECT_NAME}")
|
||||
endif()
|
||||
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX
|
||||
/usr
|
||||
CACHE PATH "Default install path" FORCE)
|
||||
set(CMAKE_INSTALL_PREFIX
|
||||
/usr
|
||||
CACHE PATH "Default install path" FORCE
|
||||
)
|
||||
endif()
|
||||
|
||||
set(CMD_MAKE make)
|
||||
@@ -131,61 +153,93 @@ include(njson)
|
||||
# yaml-cpp
|
||||
include(yaml-cpp)
|
||||
|
||||
if(NOT WIN32 AND NOT APPLE AND NOT MINIMAL_BUILD AND NOT EMSCRIPTEN)
|
||||
# OpenSSL
|
||||
include(openssl)
|
||||
if(NOT WIN32
|
||||
AND NOT APPLE
|
||||
AND NOT MINIMAL_BUILD
|
||||
AND NOT EMSCRIPTEN
|
||||
)
|
||||
# OpenSSL
|
||||
include(openssl)
|
||||
|
||||
# libcurl
|
||||
include(curl)
|
||||
# libcurl
|
||||
include(curl)
|
||||
|
||||
# todo(jasondellaluce,rohith-raju): support webserver for non-linux builds too
|
||||
# cpp-httlib
|
||||
include(cpp-httplib)
|
||||
# todo(jasondellaluce,rohith-raju): support webserver for non-linux builds too cpp-httlib
|
||||
include(cpp-httplib)
|
||||
endif()
|
||||
|
||||
include(cxxopts)
|
||||
|
||||
# One TBB
|
||||
if (NOT EMSCRIPTEN)
|
||||
include(tbb)
|
||||
if(NOT EMSCRIPTEN)
|
||||
include(tbb)
|
||||
endif()
|
||||
|
||||
include(zlib)
|
||||
include(valijson)
|
||||
if (NOT MINIMAL_BUILD)
|
||||
if (NOT WIN32 AND NOT APPLE AND NOT EMSCRIPTEN)
|
||||
include(cares)
|
||||
include(protobuf)
|
||||
# gRPC
|
||||
include(grpc)
|
||||
endif()
|
||||
if(NOT MINIMAL_BUILD)
|
||||
if(NOT WIN32
|
||||
AND NOT APPLE
|
||||
AND NOT EMSCRIPTEN
|
||||
)
|
||||
include(cares)
|
||||
include(protobuf)
|
||||
# gRPC
|
||||
include(grpc)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Installation
|
||||
if(WIN32)
|
||||
set(FALCO_INSTALL_CONF_FILE "%PROGRAMFILES%/${PACKAGE_NAME}-${FALCO_VERSION}/etc/falco/falco.yaml")
|
||||
install(FILES falco.yaml DESTINATION etc/falco/ COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
install(DIRECTORY DESTINATION etc/falco/config.d COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
set(FALCO_INSTALL_CONF_FILE
|
||||
"%PROGRAMFILES%/${PACKAGE_NAME}-${FALCO_VERSION}/etc/falco/falco.yaml"
|
||||
)
|
||||
install(
|
||||
FILES falco.yaml
|
||||
DESTINATION etc/falco/
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}"
|
||||
)
|
||||
install(
|
||||
DIRECTORY
|
||||
DESTINATION etc/falco/config.d
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}"
|
||||
)
|
||||
elseif(APPLE)
|
||||
set(FALCO_INSTALL_CONF_FILE "/etc/falco/falco.yaml")
|
||||
install(FILES falco.yaml DESTINATION etc/falco/ COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
install(DIRECTORY DESTINATION etc/falco/config.d COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
install(
|
||||
FILES falco.yaml
|
||||
DESTINATION etc/falco/
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}"
|
||||
)
|
||||
install(
|
||||
DIRECTORY
|
||||
DESTINATION etc/falco/config.d
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}"
|
||||
)
|
||||
else()
|
||||
set(FALCO_INSTALL_CONF_FILE "/etc/falco/falco.yaml")
|
||||
install(FILES falco.yaml DESTINATION "${FALCO_ETC_DIR}" COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
install(DIRECTORY DESTINATION "${FALCO_ETC_DIR}/config.d" COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
install(
|
||||
FILES falco.yaml
|
||||
DESTINATION "${FALCO_ETC_DIR}"
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}"
|
||||
)
|
||||
install(
|
||||
DIRECTORY
|
||||
DESTINATION "${FALCO_ETC_DIR}/config.d"
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT MINIMAL_BUILD)
|
||||
# Coverage
|
||||
include(Coverage)
|
||||
# Coverage
|
||||
include(Coverage)
|
||||
endif()
|
||||
|
||||
# Rules
|
||||
include(rules)
|
||||
|
||||
# Clang format
|
||||
# add_custom_target(format COMMAND clang-format --style=file -i $<TARGET_PROPERTY:falco,SOURCES> COMMENT "Formatting ..." VERBATIM)
|
||||
# Clang format add_custom_target(format COMMAND clang-format --style=file -i
|
||||
# $<TARGET_PROPERTY:falco,SOURCES> COMMENT "Formatting ..." VERBATIM)
|
||||
|
||||
# Static analysis
|
||||
include(static-analysis)
|
||||
@@ -199,13 +253,17 @@ add_subdirectory(scripts)
|
||||
add_subdirectory(userspace/engine)
|
||||
add_subdirectory(userspace/falco)
|
||||
|
||||
if(NOT WIN32 AND NOT APPLE AND NOT EMSCRIPTEN AND NOT MUSL_OPTIMIZED_BUILD)
|
||||
include(falcoctl)
|
||||
if(NOT WIN32
|
||||
AND NOT APPLE
|
||||
AND NOT EMSCRIPTEN
|
||||
AND NOT MUSL_OPTIMIZED_BUILD
|
||||
)
|
||||
include(falcoctl)
|
||||
endif()
|
||||
|
||||
# Packages configuration
|
||||
include(CPackConfig)
|
||||
|
||||
if(BUILD_FALCO_UNIT_TESTS)
|
||||
add_subdirectory(unit_tests)
|
||||
add_subdirectory(unit_tests)
|
||||
endif()
|
||||
|
||||
@@ -2,24 +2,53 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
# or implied. See the License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
#
|
||||
|
||||
if(CPACK_GENERATOR MATCHES "DEB" OR CPACK_GENERATOR MATCHES "RPM")
|
||||
list(APPEND CPACK_INSTALL_COMMANDS "mkdir -p _CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}/usr/lib/systemd/system")
|
||||
list(APPEND CPACK_INSTALL_COMMANDS "cp scripts/systemd/falco-kmod-inject.service _CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}/usr/lib/systemd/system")
|
||||
list(APPEND CPACK_INSTALL_COMMANDS "cp scripts/systemd/falco-kmod.service _CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}/usr/lib/systemd/system")
|
||||
list(APPEND CPACK_INSTALL_COMMANDS "cp scripts/systemd/falco-bpf.service _CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}/usr/lib/systemd/system")
|
||||
list(APPEND CPACK_INSTALL_COMMANDS "cp scripts/systemd/falco-modern-bpf.service _CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}/usr/lib/systemd/system")
|
||||
list(APPEND CPACK_INSTALL_COMMANDS "cp scripts/systemd/falco-custom.service _CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}/usr/lib/systemd/system")
|
||||
list(APPEND CPACK_INSTALL_COMMANDS "cp scripts/systemd/falcoctl-artifact-follow.service _CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}/usr/lib/systemd/system")
|
||||
list(
|
||||
APPEND
|
||||
CPACK_INSTALL_COMMANDS
|
||||
"mkdir -p _CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}/usr/lib/systemd/system"
|
||||
)
|
||||
list(
|
||||
APPEND
|
||||
CPACK_INSTALL_COMMANDS
|
||||
"cp scripts/systemd/falco-kmod-inject.service _CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}/usr/lib/systemd/system"
|
||||
)
|
||||
list(
|
||||
APPEND
|
||||
CPACK_INSTALL_COMMANDS
|
||||
"cp scripts/systemd/falco-kmod.service _CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}/usr/lib/systemd/system"
|
||||
)
|
||||
list(
|
||||
APPEND
|
||||
CPACK_INSTALL_COMMANDS
|
||||
"cp scripts/systemd/falco-bpf.service _CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}/usr/lib/systemd/system"
|
||||
)
|
||||
list(
|
||||
APPEND
|
||||
CPACK_INSTALL_COMMANDS
|
||||
"cp scripts/systemd/falco-modern-bpf.service _CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}/usr/lib/systemd/system"
|
||||
)
|
||||
list(
|
||||
APPEND
|
||||
CPACK_INSTALL_COMMANDS
|
||||
"cp scripts/systemd/falco-custom.service _CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}/usr/lib/systemd/system"
|
||||
)
|
||||
list(
|
||||
APPEND
|
||||
CPACK_INSTALL_COMMANDS
|
||||
"cp scripts/systemd/falcoctl-artifact-follow.service _CPack_Packages/${CPACK_TOPLEVEL_TAG}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}/usr/lib/systemd/system"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CPACK_GENERATOR MATCHES "TGZ")
|
||||
|
||||
@@ -2,19 +2,21 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
# or implied. See the License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
#
|
||||
|
||||
set(CPACK_PACKAGE_NAME "${PACKAGE_NAME}")
|
||||
set(CPACK_PACKAGE_VENDOR "Cloud Native Computing Foundation (CNCF) cncf.io.")
|
||||
set(CPACK_PACKAGE_CONTACT "cncf-falco-dev@lists.cncf.io") # todo: change this once we've got @falco.org addresses
|
||||
set(CPACK_PACKAGE_CONTACT "cncf-falco-dev@lists.cncf.io") # todo: change this once we've got
|
||||
# @falco.org addresses
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Falco - Container Native Runtime Security")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/scripts/description.txt")
|
||||
set(CPACK_PACKAGE_VERSION "${FALCO_VERSION}")
|
||||
@@ -24,32 +26,35 @@ set(CPACK_PACKAGE_VERSION_PATCH "${FALCO_VERSION_PATCH}")
|
||||
set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_SOURCE_DIR}/cmake/cpack/CMakeCPackOptions.cmake")
|
||||
set(CPACK_STRIP_FILES "ON")
|
||||
set(CPACK_PACKAGE_RELOCATABLE "OFF")
|
||||
if (EMSCRIPTEN)
|
||||
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-wasm")
|
||||
if(EMSCRIPTEN)
|
||||
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-wasm")
|
||||
else()
|
||||
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_PROCESSOR}")
|
||||
set(CPACK_PACKAGE_FILE_NAME
|
||||
"${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_PROCESSOR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||
endif()
|
||||
|
||||
# Built packages will include only the following components
|
||||
set(CPACK_INSTALL_CMAKE_PROJECTS
|
||||
"${CMAKE_CURRENT_BINARY_DIR};${FALCO_COMPONENT_NAME};${FALCO_COMPONENT_NAME};/"
|
||||
"${CMAKE_CURRENT_BINARY_DIR};${FALCO_COMPONENT_NAME};${FALCO_COMPONENT_NAME};/"
|
||||
)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux") # only Linux has drivers
|
||||
list(APPEND CPACK_INSTALL_CMAKE_PROJECTS
|
||||
"${CMAKE_CURRENT_BINARY_DIR};${DRIVER_COMPONENT_NAME};${DRIVER_COMPONENT_NAME};/")
|
||||
list(APPEND CPACK_INSTALL_CMAKE_PROJECTS
|
||||
"${CMAKE_CURRENT_BINARY_DIR};${DRIVER_COMPONENT_NAME};${DRIVER_COMPONENT_NAME};/"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT CPACK_GENERATOR)
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
set(CPACK_GENERATOR DEB RPM TGZ)
|
||||
else()
|
||||
set(CPACK_GENERATOR TGZ)
|
||||
endif()
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
set(CPACK_GENERATOR DEB RPM TGZ)
|
||||
else()
|
||||
set(CPACK_GENERATOR TGZ)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message(STATUS "Using package generators: ${CPACK_GENERATOR}")
|
||||
@@ -57,15 +62,15 @@ message(STATUS "Package architecture: ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
set(CPACK_DEBIAN_PACKAGE_SECTION "utils")
|
||||
|
||||
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
|
||||
endif()
|
||||
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
|
||||
endif()
|
||||
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://www.falco.org")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "dkms (>= 2.1.0.0)")
|
||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
|
||||
"${CMAKE_BINARY_DIR}/scripts/debian/postinst;${CMAKE_BINARY_DIR}/scripts/debian/prerm;${CMAKE_BINARY_DIR}/scripts/debian/postrm;${PROJECT_SOURCE_DIR}/cmake/cpack/debian/conffiles"
|
||||
"${CMAKE_BINARY_DIR}/scripts/debian/postinst;${CMAKE_BINARY_DIR}/scripts/debian/prerm;${CMAKE_BINARY_DIR}/scripts/debian/postrm;${PROJECT_SOURCE_DIR}/cmake/cpack/debian/conffiles"
|
||||
)
|
||||
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "Apache v2.0")
|
||||
@@ -77,13 +82,14 @@ set(CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE "${CMAKE_BINARY_DIR}/scripts/rpm/preunin
|
||||
set(CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE "${CMAKE_BINARY_DIR}/scripts/rpm/postuninstall")
|
||||
set(CPACK_RPM_PACKAGE_VERSION "${FALCO_VERSION}")
|
||||
set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION
|
||||
/usr/src
|
||||
/usr/share/man
|
||||
/usr/share/man/man8
|
||||
/etc
|
||||
/usr
|
||||
/usr/bin
|
||||
/usr/share)
|
||||
/usr/src
|
||||
/usr/share/man
|
||||
/usr/share/man/man8
|
||||
/etc
|
||||
/usr
|
||||
/usr/bin
|
||||
/usr/share
|
||||
)
|
||||
set(CPACK_RPM_PACKAGE_RELOCATABLE "OFF")
|
||||
|
||||
include(CPack)
|
||||
|
||||
@@ -2,51 +2,51 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
# or implied. See the License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
#
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
if(NOT FALCO_EXTRA_DEBUG_FLAGS)
|
||||
set(FALCO_EXTRA_DEBUG_FLAGS "-D_DEBUG")
|
||||
set(FALCO_EXTRA_DEBUG_FLAGS "-D_DEBUG")
|
||||
endif()
|
||||
|
||||
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "debug")
|
||||
set(KBUILD_FLAGS "${FALCO_EXTRA_DEBUG_FLAGS} ${FALCO_EXTRA_FEATURE_FLAGS}")
|
||||
set(KBUILD_FLAGS "${FALCO_EXTRA_DEBUG_FLAGS} ${FALCO_EXTRA_FEATURE_FLAGS}")
|
||||
else()
|
||||
set(CMAKE_BUILD_TYPE "release")
|
||||
set(KBUILD_FLAGS "${FALCO_EXTRA_FEATURE_FLAGS}")
|
||||
add_definitions(-DBUILD_TYPE_RELEASE)
|
||||
set(CMAKE_BUILD_TYPE "release")
|
||||
set(KBUILD_FLAGS "${FALCO_EXTRA_FEATURE_FLAGS}")
|
||||
add_definitions(-DBUILD_TYPE_RELEASE)
|
||||
endif()
|
||||
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
||||
|
||||
if(MINIMAL_BUILD)
|
||||
set(MINIMAL_BUILD_FLAGS "-DMINIMAL_BUILD")
|
||||
set(MINIMAL_BUILD_FLAGS "-DMINIMAL_BUILD")
|
||||
endif()
|
||||
|
||||
if(MUSL_OPTIMIZED_BUILD)
|
||||
set(MUSL_FLAGS "-static -Os -fPIE -pie")
|
||||
add_definitions(-DMUSL_OPTIMIZED)
|
||||
set(MUSL_FLAGS "-static -Os -fPIE -pie")
|
||||
add_definitions(-DMUSL_OPTIMIZED)
|
||||
endif()
|
||||
|
||||
# explicitly set hardening flags
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
set(FALCO_SECURITY_FLAGS "")
|
||||
if(LINUX)
|
||||
set(FALCO_SECURITY_FLAGS "${FALCO_SECURITY_FLAGS} -fstack-protector-strong")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,relro,-z,now")
|
||||
set(FALCO_SECURITY_FLAGS "${FALCO_SECURITY_FLAGS} -fstack-protector-strong")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,relro,-z,now")
|
||||
endif()
|
||||
|
||||
|
||||
if(NOT MSVC)
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "release")
|
||||
@@ -64,7 +64,9 @@ if(NOT MSVC)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_COMMON_FLAGS "${FALCO_SECURITY_FLAGS} -Wall -ggdb ${FALCO_EXTRA_FEATURE_FLAGS} ${MINIMAL_BUILD_FLAGS} ${MUSL_FLAGS}")
|
||||
set(CMAKE_COMMON_FLAGS
|
||||
"${FALCO_SECURITY_FLAGS} -Wall -ggdb ${FALCO_EXTRA_FEATURE_FLAGS} ${MINIMAL_BUILD_FLAGS} ${MUSL_FLAGS}"
|
||||
)
|
||||
|
||||
if(BUILD_WARNINGS_AS_ERRORS)
|
||||
set(CMAKE_SUPPRESSED_WARNINGS
|
||||
@@ -87,18 +89,11 @@ else() # MSVC
|
||||
set(MINIMAL_BUILD ON)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
|
||||
# The WIN32_LEAN_AND_MEAN define avoids possible macro pollution
|
||||
# when a libsinsp consumer includes the windows.h header:
|
||||
# https://stackoverflow.com/a/28380820
|
||||
# Same goes for NOMINMAX:
|
||||
# The WIN32_LEAN_AND_MEAN define avoids possible macro pollution when a libsinsp consumer
|
||||
# includes the windows.h header: https://stackoverflow.com/a/28380820 Same goes for NOMINMAX:
|
||||
# https://stackoverflow.com/questions/5004858/why-is-stdmin-failing-when-windows-h-is-included
|
||||
add_compile_definitions(
|
||||
_HAS_STD_BYTE=0
|
||||
_CRT_SECURE_NO_WARNINGS
|
||||
WIN32
|
||||
MINIMAL_BUILD
|
||||
WIN32_LEAN_AND_MEAN
|
||||
NOMINMAX
|
||||
_HAS_STD_BYTE=0 _CRT_SECURE_NO_WARNINGS WIN32 MINIMAL_BUILD WIN32_LEAN_AND_MEAN NOMINMAX
|
||||
)
|
||||
|
||||
set(FALCOSECURITY_LIBS_COMMON_FLAGS "/EHsc /W3 /Zi /std:c++17")
|
||||
|
||||
@@ -2,25 +2,28 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# 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.
|
||||
#
|
||||
|
||||
# Tests coverage
|
||||
option(FALCO_COVERAGE "Build test suite with coverage information" OFF)
|
||||
if(FALCO_COVERAGE)
|
||||
if(NOT (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")))
|
||||
message(FATAL_ERROR "FALCO_COVERAGE requires GCC or Clang.")
|
||||
endif()
|
||||
if(NOT (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES
|
||||
"Clang"))
|
||||
)
|
||||
message(FATAL_ERROR "FALCO_COVERAGE requires GCC or Clang.")
|
||||
endif()
|
||||
|
||||
message(STATUS "Building with coverage information")
|
||||
add_compile_options(-g --coverage)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "--coverage ${CMAKE_SHARED_LINKER_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "--coverage ${CMAKE_EXE_LINKER_FLAGS}")
|
||||
message(STATUS "Building with coverage information")
|
||||
add_compile_options(-g --coverage)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "--coverage ${CMAKE_SHARED_LINKER_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "--coverage ${CMAKE_EXE_LINKER_FLAGS}")
|
||||
endif()
|
||||
|
||||
@@ -2,30 +2,32 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
# or implied. See the License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
#
|
||||
|
||||
function(copy_files_to_build_dir source_files targetsuffix)
|
||||
|
||||
set(build_files)
|
||||
set(build_files)
|
||||
|
||||
foreach(file_path ${source_files})
|
||||
get_filename_component(trace_file ${file_path} NAME)
|
||||
list(APPEND build_files ${CMAKE_CURRENT_BINARY_DIR}/${trace_file})
|
||||
endforeach()
|
||||
foreach(file_path ${source_files})
|
||||
get_filename_component(trace_file ${file_path} NAME)
|
||||
list(APPEND build_files ${CMAKE_CURRENT_BINARY_DIR}/${trace_file})
|
||||
endforeach()
|
||||
|
||||
add_custom_target(copy-files-${targetsuffix} ALL
|
||||
DEPENDS ${build_files})
|
||||
add_custom_target(copy-files-${targetsuffix} ALL DEPENDS ${build_files})
|
||||
|
||||
add_custom_command(OUTPUT ${build_files}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${source_files} ${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS ${source_files})
|
||||
add_custom_command(
|
||||
OUTPUT ${build_files}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${source_files} ${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS ${source_files}
|
||||
)
|
||||
|
||||
endfunction()
|
||||
|
||||
@@ -2,25 +2,27 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
# or implied. See the License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
#
|
||||
|
||||
option(USE_BUNDLED_CPPHTTPLIB "Enable building of the bundled cpp-httplib" ${USE_BUNDLED_DEPS})
|
||||
|
||||
if(USE_BUNDLED_CPPHTTPLIB)
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(cpp-httplib
|
||||
URL https://github.com/yhirose/cpp-httplib/archive/refs/tags/v0.15.3.tar.gz
|
||||
URL_HASH SHA256=2121bbf38871bb2aafb5f7f2b9b94705366170909f434428352187cb0216124e
|
||||
)
|
||||
FetchContent_MakeAvailable(cpp-httplib)
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
cpp-httplib
|
||||
URL https://github.com/yhirose/cpp-httplib/archive/refs/tags/v0.15.3.tar.gz
|
||||
URL_HASH SHA256=2121bbf38871bb2aafb5f7f2b9b94705366170909f434428352187cb0216124e
|
||||
)
|
||||
FetchContent_MakeAvailable(cpp-httplib)
|
||||
else()
|
||||
find_package(httplib CONFIG REQUIRED)
|
||||
find_package(httplib CONFIG REQUIRED)
|
||||
endif()
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
@@ -19,25 +20,26 @@
|
||||
option(USE_BUNDLED_CXXOPTS "Enable building of the bundled cxxopts" ${USE_BUNDLED_DEPS})
|
||||
|
||||
if(CXXOPTS_INCLUDE_DIR)
|
||||
# we already have cxxopts
|
||||
# we already have cxxopts
|
||||
elseif(NOT USE_BUNDLED_CXXOPTS)
|
||||
find_package(cxxopts CONFIG REQUIRED)
|
||||
get_target_property(CXXOPTS_INCLUDE_DIR cxxopts::cxxopts INTERFACE_INCLUDE_DIRECTORIES)
|
||||
find_package(cxxopts CONFIG REQUIRED)
|
||||
get_target_property(CXXOPTS_INCLUDE_DIR cxxopts::cxxopts INTERFACE_INCLUDE_DIRECTORIES)
|
||||
else()
|
||||
set(CXXOPTS_SRC "${PROJECT_BINARY_DIR}/cxxopts-prefix/src/cxxopts/")
|
||||
set(CXXOPTS_INCLUDE_DIR "${CXXOPTS_SRC}/include")
|
||||
set(CXXOPTS_SRC "${PROJECT_BINARY_DIR}/cxxopts-prefix/src/cxxopts/")
|
||||
set(CXXOPTS_INCLUDE_DIR "${CXXOPTS_SRC}/include")
|
||||
|
||||
message(STATUS "Using bundled cxxopts in ${CXXOPTS_SRC}")
|
||||
message(STATUS "Using bundled cxxopts in ${CXXOPTS_SRC}")
|
||||
|
||||
ExternalProject_Add(
|
||||
cxxopts
|
||||
URL "https://github.com/jarro2783/cxxopts/archive/refs/tags/v3.0.0.tar.gz"
|
||||
URL_HASH "SHA256=36f41fa2a46b3c1466613b63f3fa73dc24d912bc90d667147f1e43215a8c6d00"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
ExternalProject_Add(
|
||||
cxxopts
|
||||
URL "https://github.com/jarro2783/cxxopts/archive/refs/tags/v3.0.0.tar.gz"
|
||||
URL_HASH "SHA256=36f41fa2a46b3c1466613b63f3fa73dc24d912bc90d667147f1e43215a8c6d00"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT TARGET cxxopts)
|
||||
add_custom_target(cxxopts)
|
||||
add_custom_target(cxxopts)
|
||||
endif()
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# 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.
|
||||
#
|
||||
cmake_minimum_required(VERSION 3.5.1)
|
||||
|
||||
@@ -20,12 +21,12 @@ message(STATUS "Driver repository: ${DRIVER_REPO}")
|
||||
message(STATUS "Driver version: ${DRIVER_VERSION}")
|
||||
|
||||
ExternalProject_Add(
|
||||
driver
|
||||
URL "https://github.com/${DRIVER_REPO}/archive/${DRIVER_VERSION}.tar.gz"
|
||||
URL_HASH "${DRIVER_CHECKSUM}"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
PATCH_COMMAND sh -c "mv ./driver ../driver.tmp && rm -rf ./* && mv ../driver.tmp/* ."
|
||||
driver
|
||||
URL "https://github.com/${DRIVER_REPO}/archive/${DRIVER_VERSION}.tar.gz"
|
||||
URL_HASH "${DRIVER_CHECKSUM}"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
PATCH_COMMAND sh -c "mv ./driver ../driver.tmp && rm -rf ./* && mv ../driver.tmp/* ."
|
||||
)
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
# or implied. See the License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
#
|
||||
|
||||
set(DRIVER_CMAKE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/driver-repo")
|
||||
@@ -18,37 +19,42 @@ set(DRIVER_CMAKE_WORKING_DIR "${CMAKE_BINARY_DIR}/driver-repo")
|
||||
file(MAKE_DIRECTORY ${DRIVER_CMAKE_WORKING_DIR})
|
||||
|
||||
if(DRIVER_SOURCE_DIR)
|
||||
set(DRIVER_VERSION "0.0.0-local")
|
||||
message(STATUS "Using local version for driver: '${DRIVER_SOURCE_DIR}'")
|
||||
set(DRIVER_VERSION "0.0.0-local")
|
||||
message(STATUS "Using local version for driver: '${DRIVER_SOURCE_DIR}'")
|
||||
else()
|
||||
# DRIVER_REPO accepts a repository name (<org name>/<repo name>) alternative to the falcosecurity/libs repository.
|
||||
# In case you want to test against a fork of falcosecurity/libs just pass the variable -
|
||||
# ie., `cmake -DDRIVER_REPO=<your-gh-handle>/libs ..`
|
||||
if (NOT DRIVER_REPO)
|
||||
set(DRIVER_REPO "falcosecurity/libs")
|
||||
endif()
|
||||
# DRIVER_REPO accepts a repository name (<org name>/<repo name>) alternative to the
|
||||
# falcosecurity/libs repository. In case you want to test against a fork of falcosecurity/libs
|
||||
# just pass the variable - ie., `cmake -DDRIVER_REPO=<your-gh-handle>/libs ..`
|
||||
if(NOT DRIVER_REPO)
|
||||
set(DRIVER_REPO "falcosecurity/libs")
|
||||
endif()
|
||||
|
||||
# DRIVER_VERSION accepts a git reference (branch name, commit hash, or tag) to the falcosecurity/libs repository
|
||||
# which contains the driver source code under the `/driver` directory.
|
||||
# The chosen driver version must be compatible with the given FALCOSECURITY_LIBS_VERSION.
|
||||
# In case you want to test against another driver version (or branch, or commit) just pass the variable -
|
||||
# ie., `cmake -DDRIVER_VERSION=dev ..`
|
||||
if(NOT DRIVER_VERSION)
|
||||
set(DRIVER_VERSION "0.18.0-rc2")
|
||||
set(DRIVER_CHECKSUM "SHA256=e016ee1113eb5a14c85d9c4828244f5fba37cd663ecd38f5b58fbc4142348782")
|
||||
endif()
|
||||
# DRIVER_VERSION accepts a git reference (branch name, commit hash, or tag) to the
|
||||
# falcosecurity/libs repository which contains the driver source code under the `/driver`
|
||||
# directory. The chosen driver version must be compatible with the given
|
||||
# FALCOSECURITY_LIBS_VERSION. In case you want to test against another driver version (or
|
||||
# branch, or commit) just pass the variable - ie., `cmake -DDRIVER_VERSION=dev ..`
|
||||
if(NOT DRIVER_VERSION)
|
||||
set(DRIVER_VERSION "7.3.0+driver")
|
||||
set(DRIVER_CHECKSUM
|
||||
"SHA256=8f572d9a83feda635a3fa53b859d61e37af127c241e35068aadee3bc50d212c0"
|
||||
)
|
||||
endif()
|
||||
|
||||
# cd /path/to/build && cmake /path/to/source
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}"
|
||||
-DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}"
|
||||
-DDRIVER_REPO=${DRIVER_REPO}
|
||||
-DDRIVER_VERSION=${DRIVER_VERSION}
|
||||
-DDRIVER_CHECKSUM=${DRIVER_CHECKSUM}
|
||||
${DRIVER_CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${DRIVER_CMAKE_WORKING_DIR})
|
||||
# cd /path/to/build && cmake /path/to/source
|
||||
execute_process(
|
||||
COMMAND
|
||||
"${CMAKE_COMMAND}" -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" -DDRIVER_REPO=${DRIVER_REPO}
|
||||
-DDRIVER_VERSION=${DRIVER_VERSION} -DDRIVER_CHECKSUM=${DRIVER_CHECKSUM}
|
||||
${DRIVER_CMAKE_SOURCE_DIR}
|
||||
WORKING_DIRECTORY ${DRIVER_CMAKE_WORKING_DIR}
|
||||
)
|
||||
|
||||
# cmake --build .
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${DRIVER_CMAKE_WORKING_DIR}")
|
||||
set(DRIVER_SOURCE_DIR "${DRIVER_CMAKE_WORKING_DIR}/driver-prefix/src/driver")
|
||||
# cmake --build .
|
||||
execute_process(
|
||||
COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${DRIVER_CMAKE_WORKING_DIR}"
|
||||
)
|
||||
set(DRIVER_SOURCE_DIR "${DRIVER_CMAKE_WORKING_DIR}/driver-prefix/src/driver")
|
||||
endif()
|
||||
|
||||
add_definitions(-D_GNU_SOURCE)
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# 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.
|
||||
#
|
||||
|
||||
# Retrieve git ref and commit hash
|
||||
@@ -17,33 +18,39 @@ include(GetVersionFromGit)
|
||||
|
||||
# Get Falco version variable according to git index
|
||||
if(NOT FALCO_VERSION)
|
||||
set(FALCO_VERSION "0.0.0")
|
||||
get_version_from_git(FALCO_VERSION "" "")
|
||||
set(FALCO_VERSION "0.0.0")
|
||||
get_version_from_git(FALCO_VERSION "" "")
|
||||
endif()
|
||||
|
||||
# Remove the starting "v" in case there is one
|
||||
string(REGEX REPLACE "^v(.*)" "\\1" FALCO_VERSION "${FALCO_VERSION}")
|
||||
|
||||
string(REGEX MATCH "^(0|[1-9][0-9]*)" FALCO_VERSION_MAJOR "${FALCO_VERSION}")
|
||||
string(REGEX REPLACE "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\..*" "\\2" FALCO_VERSION_MINOR "${FALCO_VERSION}")
|
||||
string(REGEX REPLACE "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*).*" "\\3" FALCO_VERSION_PATCH
|
||||
"${FALCO_VERSION}")
|
||||
string(REGEX REPLACE "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\..*" "\\2" FALCO_VERSION_MINOR
|
||||
"${FALCO_VERSION}"
|
||||
)
|
||||
string(REGEX REPLACE "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*).*" "\\3"
|
||||
FALCO_VERSION_PATCH "${FALCO_VERSION}"
|
||||
)
|
||||
string(
|
||||
REGEX
|
||||
REPLACE
|
||||
"^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)-((0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*).*"
|
||||
"\\5"
|
||||
FALCO_VERSION_PRERELEASE
|
||||
"${FALCO_VERSION}")
|
||||
REGEX
|
||||
REPLACE
|
||||
"^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)-((0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*).*"
|
||||
"\\5"
|
||||
FALCO_VERSION_PRERELEASE
|
||||
"${FALCO_VERSION}"
|
||||
)
|
||||
|
||||
if(FALCO_VERSION_PRERELEASE STREQUAL "${FALCO_VERSION}")
|
||||
set(FALCO_VERSION_PRERELEASE "")
|
||||
set(FALCO_VERSION_PRERELEASE "")
|
||||
endif()
|
||||
if(NOT FALCO_VERSION_BUILD)
|
||||
string(REGEX REPLACE ".*\\+([0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*)" "\\1" FALCO_VERSION_BUILD "${FALCO_VERSION}")
|
||||
string(REGEX REPLACE ".*\\+([0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*)" "\\1" FALCO_VERSION_BUILD
|
||||
"${FALCO_VERSION}"
|
||||
)
|
||||
endif()
|
||||
if(FALCO_VERSION_BUILD STREQUAL "${FALCO_VERSION}")
|
||||
set(FALCO_VERSION_BUILD "")
|
||||
set(FALCO_VERSION_BUILD "")
|
||||
endif()
|
||||
|
||||
message(STATUS "Falco version: ${FALCO_VERSION}")
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# 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)
|
||||
@@ -17,30 +18,39 @@ include(ExternalProject)
|
||||
option(ADD_FALCOCTL_DEPENDENCY "Add falcoctl dependency while building falco" ON)
|
||||
|
||||
if(ADD_FALCOCTL_DEPENDENCY)
|
||||
string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} FALCOCTL_SYSTEM_NAME)
|
||||
string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} FALCOCTL_SYSTEM_NAME)
|
||||
|
||||
set(FALCOCTL_VERSION "0.10.0")
|
||||
set(FALCOCTL_VERSION "0.10.1")
|
||||
|
||||
message(STATUS "Building with falcoctl: ${FALCOCTL_VERSION}")
|
||||
message(STATUS "Building with falcoctl: ${FALCOCTL_VERSION}")
|
||||
|
||||
if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
set(FALCOCTL_SYSTEM_PROC_GO "amd64")
|
||||
set(FALCOCTL_HASH "32d1be4ab2335d9c3fc8ae8900341bcc26d3166094fc553ddb7bb783aa6c7b68")
|
||||
else() # aarch64
|
||||
set(FALCOCTL_SYSTEM_PROC_GO "arm64")
|
||||
set(FALCOCTL_HASH "9186fd948c1230c338a7fa36d6569ce85d3c4aa8153b30e8d86d2e887eb76756")
|
||||
endif()
|
||||
if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
set(FALCOCTL_SYSTEM_PROC_GO "amd64")
|
||||
set(FALCOCTL_HASH "039961004a72d27409ab6ba82542134bd5df8a69ad341c897f3d26b6596b9e6a")
|
||||
else() # aarch64
|
||||
set(FALCOCTL_SYSTEM_PROC_GO "arm64")
|
||||
set(FALCOCTL_HASH "fbaf83512cc73e99f14f90cb14ed4eee83f40efde3d398c7b7ef02163116f2fc")
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(
|
||||
falcoctl
|
||||
URL "https://github.com/falcosecurity/falcoctl/releases/download/v${FALCOCTL_VERSION}/falcoctl_${FALCOCTL_VERSION}_${FALCOCTL_SYSTEM_NAME}_${FALCOCTL_SYSTEM_PROC_GO}.tar.gz"
|
||||
URL_HASH "SHA256=${FALCOCTL_HASH}"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
ExternalProject_Add(
|
||||
falcoctl
|
||||
URL "https://github.com/falcosecurity/falcoctl/releases/download/v${FALCOCTL_VERSION}/falcoctl_${FALCOCTL_VERSION}_${FALCOCTL_SYSTEM_NAME}_${FALCOCTL_SYSTEM_PROC_GO}.tar.gz"
|
||||
URL_HASH "SHA256=${FALCOCTL_HASH}"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
)
|
||||
|
||||
install(PROGRAMS "${PROJECT_BINARY_DIR}/falcoctl-prefix/src/falcoctl/falcoctl" DESTINATION "${FALCO_BIN_DIR}" COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
install(DIRECTORY DESTINATION "${FALCO_ABSOLUTE_SHARE_DIR}/plugins" COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
install(
|
||||
PROGRAMS "${PROJECT_BINARY_DIR}/falcoctl-prefix/src/falcoctl/falcoctl"
|
||||
DESTINATION "${FALCO_BIN_DIR}"
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}"
|
||||
)
|
||||
install(
|
||||
DIRECTORY
|
||||
DESTINATION "${FALCO_ABSOLUTE_SHARE_DIR}/plugins"
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}"
|
||||
)
|
||||
else()
|
||||
message(STATUS "Won't build with falcoctl")
|
||||
message(STATUS "Won't build with falcoctl")
|
||||
endif()
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# 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.
|
||||
#
|
||||
cmake_minimum_required(VERSION 3.5.1)
|
||||
|
||||
@@ -20,11 +21,11 @@ message(STATUS "Libs repository: ${FALCOSECURITY_LIBS_REPO}")
|
||||
message(STATUS "Libs version: ${FALCOSECURITY_LIBS_VERSION}")
|
||||
|
||||
ExternalProject_Add(
|
||||
falcosecurity-libs
|
||||
URL "https://github.com/${FALCOSECURITY_LIBS_REPO}/archive/${FALCOSECURITY_LIBS_VERSION}.tar.gz"
|
||||
URL_HASH "${FALCOSECURITY_LIBS_CHECKSUM}"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
falcosecurity-libs
|
||||
URL "https://github.com/${FALCOSECURITY_LIBS_REPO}/archive/${FALCOSECURITY_LIBS_VERSION}.tar.gz"
|
||||
URL_HASH "${FALCOSECURITY_LIBS_CHECKSUM}"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
)
|
||||
|
||||
@@ -2,65 +2,82 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
# or implied. See the License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
#
|
||||
|
||||
set(FALCOSECURITY_LIBS_CMAKE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/falcosecurity-libs-repo")
|
||||
set(FALCOSECURITY_LIBS_CMAKE_SOURCE_DIR
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/falcosecurity-libs-repo"
|
||||
)
|
||||
set(FALCOSECURITY_LIBS_CMAKE_WORKING_DIR "${CMAKE_BINARY_DIR}/falcosecurity-libs-repo")
|
||||
|
||||
file(MAKE_DIRECTORY ${FALCOSECURITY_LIBS_CMAKE_WORKING_DIR})
|
||||
|
||||
# explicitly disable the bundled driver, since we pull it separately
|
||||
set(USE_BUNDLED_DRIVER OFF CACHE BOOL "")
|
||||
set(USE_BUNDLED_DRIVER
|
||||
OFF
|
||||
CACHE BOOL ""
|
||||
)
|
||||
|
||||
if(FALCOSECURITY_LIBS_SOURCE_DIR)
|
||||
set(FALCOSECURITY_LIBS_VERSION "0.0.0-local")
|
||||
message(STATUS "Using local version of falcosecurity/libs: '${FALCOSECURITY_LIBS_SOURCE_DIR}'")
|
||||
set(FALCOSECURITY_LIBS_VERSION "0.0.0-local")
|
||||
message(STATUS "Using local version of falcosecurity/libs: '${FALCOSECURITY_LIBS_SOURCE_DIR}'")
|
||||
else()
|
||||
# FALCOSECURITY_LIBS_REPO accepts a repository name (<org name>/<repo name>) alternative to the falcosecurity/libs repository.
|
||||
# In case you want to test against a fork of falcosecurity/libs just pass the variable -
|
||||
# ie., `cmake -DFALCOSECURITY_LIBS_REPO=<your-gh-handle>/libs ..`
|
||||
if (NOT FALCOSECURITY_LIBS_REPO)
|
||||
set(FALCOSECURITY_LIBS_REPO "falcosecurity/libs")
|
||||
endif()
|
||||
# FALCOSECURITY_LIBS_REPO accepts a repository name (<org name>/<repo name>) alternative to the
|
||||
# falcosecurity/libs repository. In case you want to test against a fork of falcosecurity/libs
|
||||
# just pass the variable - ie., `cmake -DFALCOSECURITY_LIBS_REPO=<your-gh-handle>/libs ..`
|
||||
if(NOT FALCOSECURITY_LIBS_REPO)
|
||||
set(FALCOSECURITY_LIBS_REPO "falcosecurity/libs")
|
||||
endif()
|
||||
|
||||
# FALCOSECURITY_LIBS_VERSION accepts a git reference (branch name, commit hash, or tag) to the falcosecurity/libs repository.
|
||||
# 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 "0.18.0-rc2")
|
||||
set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=e016ee1113eb5a14c85d9c4828244f5fba37cd663ecd38f5b58fbc4142348782")
|
||||
endif()
|
||||
# FALCOSECURITY_LIBS_VERSION accepts a git reference (branch name, commit hash, or tag) to the
|
||||
# falcosecurity/libs repository. 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 "0.18.2")
|
||||
set(FALCOSECURITY_LIBS_CHECKSUM
|
||||
"SHA256=b2e3e42c3255a6d41960afe086e8189d73e27f1dbc23abefaf6b05cf118eb6f4"
|
||||
)
|
||||
endif()
|
||||
|
||||
# cd /path/to/build && cmake /path/to/source
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}"
|
||||
-DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}"
|
||||
-DFALCOSECURITY_LIBS_REPO=${FALCOSECURITY_LIBS_REPO}
|
||||
-DFALCOSECURITY_LIBS_VERSION=${FALCOSECURITY_LIBS_VERSION}
|
||||
-DFALCOSECURITY_LIBS_CHECKSUM=${FALCOSECURITY_LIBS_CHECKSUM}
|
||||
${FALCOSECURITY_LIBS_CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${FALCOSECURITY_LIBS_CMAKE_WORKING_DIR})
|
||||
# cd /path/to/build && cmake /path/to/source
|
||||
execute_process(
|
||||
COMMAND
|
||||
"${CMAKE_COMMAND}" -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}"
|
||||
-DFALCOSECURITY_LIBS_REPO=${FALCOSECURITY_LIBS_REPO}
|
||||
-DFALCOSECURITY_LIBS_VERSION=${FALCOSECURITY_LIBS_VERSION}
|
||||
-DFALCOSECURITY_LIBS_CHECKSUM=${FALCOSECURITY_LIBS_CHECKSUM}
|
||||
${FALCOSECURITY_LIBS_CMAKE_SOURCE_DIR}
|
||||
WORKING_DIRECTORY ${FALCOSECURITY_LIBS_CMAKE_WORKING_DIR}
|
||||
)
|
||||
|
||||
# cmake --build .
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${FALCOSECURITY_LIBS_CMAKE_WORKING_DIR}")
|
||||
set(FALCOSECURITY_LIBS_SOURCE_DIR "${FALCOSECURITY_LIBS_CMAKE_WORKING_DIR}/falcosecurity-libs-prefix/src/falcosecurity-libs")
|
||||
# cmake --build .
|
||||
execute_process(
|
||||
COMMAND "${CMAKE_COMMAND}" --build .
|
||||
WORKING_DIRECTORY "${FALCOSECURITY_LIBS_CMAKE_WORKING_DIR}"
|
||||
)
|
||||
set(FALCOSECURITY_LIBS_SOURCE_DIR
|
||||
"${FALCOSECURITY_LIBS_CMAKE_WORKING_DIR}/falcosecurity-libs-prefix/src/falcosecurity-libs"
|
||||
)
|
||||
endif()
|
||||
|
||||
set(LIBS_PACKAGE_NAME "falcosecurity")
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
add_definitions(-D_GNU_SOURCE)
|
||||
add_definitions(-DHAS_CAPTURE)
|
||||
add_definitions(-D_GNU_SOURCE)
|
||||
add_definitions(-DHAS_CAPTURE)
|
||||
endif()
|
||||
|
||||
if(MUSL_OPTIMIZED_BUILD)
|
||||
add_definitions(-DMUSL_OPTIMIZED)
|
||||
add_definitions(-DMUSL_OPTIMIZED)
|
||||
endif()
|
||||
|
||||
set(SCAP_HOST_ROOT_ENV_VAR_NAME "HOST_ROOT")
|
||||
@@ -68,27 +85,60 @@ set(SCAP_HOSTNAME_ENV_VAR "FALCO_HOSTNAME")
|
||||
set(SINSP_AGENT_CGROUP_MEM_PATH_ENV_VAR "FALCO_CGROUP_MEM_PATH")
|
||||
|
||||
if(NOT LIBS_DIR)
|
||||
set(LIBS_DIR "${FALCOSECURITY_LIBS_SOURCE_DIR}")
|
||||
set(LIBS_DIR "${FALCOSECURITY_LIBS_SOURCE_DIR}")
|
||||
endif()
|
||||
|
||||
# configure gVisor support
|
||||
set(BUILD_LIBSCAP_GVISOR ${BUILD_FALCO_GVISOR} CACHE BOOL "")
|
||||
set(BUILD_LIBSCAP_GVISOR
|
||||
${BUILD_FALCO_GVISOR}
|
||||
CACHE BOOL ""
|
||||
)
|
||||
|
||||
# configure modern BPF support
|
||||
set(BUILD_LIBSCAP_MODERN_BPF ${BUILD_FALCO_MODERN_BPF} CACHE BOOL "")
|
||||
set(BUILD_LIBSCAP_MODERN_BPF
|
||||
${BUILD_FALCO_MODERN_BPF}
|
||||
CACHE BOOL ""
|
||||
)
|
||||
|
||||
# explicitly disable the tests/examples of this dependency
|
||||
set(CREATE_TEST_TARGETS OFF CACHE BOOL "")
|
||||
set(BUILD_LIBSCAP_EXAMPLES OFF CACHE BOOL "")
|
||||
set(CREATE_TEST_TARGETS
|
||||
OFF
|
||||
CACHE BOOL ""
|
||||
)
|
||||
set(BUILD_LIBSCAP_EXAMPLES
|
||||
OFF
|
||||
CACHE BOOL ""
|
||||
)
|
||||
|
||||
set(USE_BUNDLED_TBB ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_JSONCPP ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_VALIJSON ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_RE2 ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_UTHASH ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_TBB
|
||||
ON
|
||||
CACHE BOOL ""
|
||||
)
|
||||
set(USE_BUNDLED_JSONCPP
|
||||
ON
|
||||
CACHE BOOL ""
|
||||
)
|
||||
set(USE_BUNDLED_VALIJSON
|
||||
ON
|
||||
CACHE BOOL ""
|
||||
)
|
||||
set(USE_BUNDLED_RE2
|
||||
ON
|
||||
CACHE BOOL ""
|
||||
)
|
||||
set(USE_BUNDLED_UTHASH
|
||||
ON
|
||||
CACHE BOOL ""
|
||||
)
|
||||
if(USE_DYNAMIC_LIBELF)
|
||||
set(USE_BUNDLED_LIBELF OFF CACHE BOOL "")
|
||||
set(USE_SHARED_LIBELF ON CACHE BOOL "")
|
||||
set(USE_BUNDLED_LIBELF
|
||||
OFF
|
||||
CACHE BOOL ""
|
||||
)
|
||||
set(USE_SHARED_LIBELF
|
||||
ON
|
||||
CACHE BOOL ""
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${FALCOSECURITY_LIBS_SOURCE_DIR}/cmake/modules")
|
||||
@@ -97,15 +147,18 @@ include(CheckSymbolExists)
|
||||
check_symbol_exists(strlcpy "string.h" HAVE_STRLCPY)
|
||||
|
||||
if(HAVE_STRLCPY)
|
||||
message(STATUS "Existing strlcpy and strlcat found, will *not* use local definition by setting -DHAVE_STRLCPY and -DHAVE_STRLCAT.")
|
||||
add_definitions(-DHAVE_STRLCPY)
|
||||
add_definitions(-DHAVE_STRLCAT)
|
||||
message(
|
||||
STATUS
|
||||
"Existing strlcpy and strlcat found, will *not* use local definition by setting -DHAVE_STRLCPY and -DHAVE_STRLCAT."
|
||||
)
|
||||
add_definitions(-DHAVE_STRLCPY)
|
||||
add_definitions(-DHAVE_STRLCAT)
|
||||
else()
|
||||
message(STATUS "No strlcpy and strlcat found, will use local definition")
|
||||
message(STATUS "No strlcpy and strlcat found, will use local definition")
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
include(driver)
|
||||
include(driver)
|
||||
endif()
|
||||
include(libscap)
|
||||
include(libsinsp)
|
||||
|
||||
@@ -2,25 +2,27 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
# or implied. See the License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
#
|
||||
|
||||
option(USE_BUNDLED_NLOHMANN_JSON "Enable building of the bundled nlohmann-json" ${USE_BUNDLED_DEPS})
|
||||
|
||||
if(USE_BUNDLED_NLOHMANN_JSON)
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(nlohmann_json
|
||||
URL https://github.com/nlohmann/json/archive/v3.11.3.tar.gz
|
||||
URL_HASH SHA256=0d8ef5af7f9794e3263480193c491549b2ba6cc74bb018906202ada498a79406
|
||||
)
|
||||
FetchContent_MakeAvailable(nlohmann_json)
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
nlohmann_json
|
||||
URL https://github.com/nlohmann/json/archive/v3.11.3.tar.gz
|
||||
URL_HASH SHA256=0d8ef5af7f9794e3263480193c491549b2ba6cc74bb018906202ada498a79406
|
||||
)
|
||||
FetchContent_MakeAvailable(nlohmann_json)
|
||||
else()
|
||||
find_package(nlohmann_json CONFIG REQUIRED)
|
||||
find_package(nlohmann_json CONFIG REQUIRED)
|
||||
endif()
|
||||
|
||||
@@ -2,39 +2,46 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# 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(GNUInstallDirs)
|
||||
include(ExternalProject)
|
||||
|
||||
if(NOT DEFINED FALCOSECURITY_RULES_FALCO_PATH)
|
||||
# falco_rules.yaml
|
||||
set(FALCOSECURITY_RULES_FALCO_VERSION "falco-rules-3.2.0")
|
||||
set(FALCOSECURITY_RULES_FALCO_CHECKSUM "SHA256=b3990bf0209cfbf6a903b361e458a1f5851a9a5aeee808ad26a5ddbe1377157d")
|
||||
set(FALCOSECURITY_RULES_FALCO_PATH "${PROJECT_BINARY_DIR}/falcosecurity-rules-falco-prefix/src/falcosecurity-rules-falco/falco_rules.yaml")
|
||||
ExternalProject_Add(
|
||||
falcosecurity-rules-falco
|
||||
URL "https://download.falco.org/rules/${FALCOSECURITY_RULES_FALCO_VERSION}.tar.gz"
|
||||
URL_HASH "${FALCOSECURITY_RULES_FALCO_CHECKSUM}"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
)
|
||||
# falco_rules.yaml
|
||||
set(FALCOSECURITY_RULES_FALCO_VERSION "falco-rules-3.2.0")
|
||||
set(FALCOSECURITY_RULES_FALCO_CHECKSUM
|
||||
"SHA256=b3990bf0209cfbf6a903b361e458a1f5851a9a5aeee808ad26a5ddbe1377157d"
|
||||
)
|
||||
set(FALCOSECURITY_RULES_FALCO_PATH
|
||||
"${PROJECT_BINARY_DIR}/falcosecurity-rules-falco-prefix/src/falcosecurity-rules-falco/falco_rules.yaml"
|
||||
)
|
||||
ExternalProject_Add(
|
||||
falcosecurity-rules-falco
|
||||
URL "https://download.falco.org/rules/${FALCOSECURITY_RULES_FALCO_VERSION}.tar.gz"
|
||||
URL_HASH "${FALCOSECURITY_RULES_FALCO_CHECKSUM}"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED FALCOSECURITY_RULES_LOCAL_PATH)
|
||||
# falco_rules.local.yaml
|
||||
set(FALCOSECURITY_RULES_LOCAL_PATH "${PROJECT_BINARY_DIR}/falcosecurity-rules-local-prefix/falco_rules.local.yaml")
|
||||
file(WRITE "${FALCOSECURITY_RULES_LOCAL_PATH}" "# Your custom rules!\n")
|
||||
# falco_rules.local.yaml
|
||||
set(FALCOSECURITY_RULES_LOCAL_PATH
|
||||
"${PROJECT_BINARY_DIR}/falcosecurity-rules-local-prefix/falco_rules.local.yaml"
|
||||
)
|
||||
file(WRITE "${FALCOSECURITY_RULES_LOCAL_PATH}" "# Your custom rules!\n")
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED FALCO_ETC_DIR)
|
||||
@@ -46,34 +53,43 @@ if(WIN32 OR APPLE)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED FALCO_RULES_DEST_FILENAME)
|
||||
set(FALCO_RULES_DEST_FILENAME "falco_rules.yaml")
|
||||
set(FALCO_LOCAL_RULES_DEST_FILENAME "falco_rules.local.yaml")
|
||||
set(FALCO_RULES_DEST_FILENAME "falco_rules.yaml")
|
||||
set(FALCO_LOCAL_RULES_DEST_FILENAME "falco_rules.local.yaml")
|
||||
endif()
|
||||
|
||||
if(DEFINED FALCO_COMPONENT) # Allow a slim version of Falco to be embedded in other projects, intentionally *not* installing all rulesets.
|
||||
install(
|
||||
FILES "${FALCOSECURITY_RULES_FALCO_PATH}"
|
||||
COMPONENT "${FALCO_COMPONENT}"
|
||||
DESTINATION "${FALCO_ETC_DIR}"
|
||||
RENAME "${FALCO_RULES_DEST_FILENAME}")
|
||||
if(DEFINED FALCO_COMPONENT) # Allow a slim version of Falco to be embedded in other projects,
|
||||
# intentionally *not* installing all rulesets.
|
||||
install(
|
||||
FILES "${FALCOSECURITY_RULES_FALCO_PATH}"
|
||||
COMPONENT "${FALCO_COMPONENT}"
|
||||
DESTINATION "${FALCO_ETC_DIR}"
|
||||
RENAME "${FALCO_RULES_DEST_FILENAME}"
|
||||
)
|
||||
|
||||
install(
|
||||
FILES "${FALCOSECURITY_RULES_LOCAL_PATH}"
|
||||
COMPONENT "${FALCO_COMPONENT}"
|
||||
DESTINATION "${FALCO_ETC_DIR}"
|
||||
RENAME "${FALCO_LOCAL_RULES_DEST_FILENAME}")
|
||||
install(
|
||||
FILES "${FALCOSECURITY_RULES_LOCAL_PATH}"
|
||||
COMPONENT "${FALCO_COMPONENT}"
|
||||
DESTINATION "${FALCO_ETC_DIR}"
|
||||
RENAME "${FALCO_LOCAL_RULES_DEST_FILENAME}"
|
||||
)
|
||||
else() # Default Falco installation
|
||||
install(
|
||||
FILES "${FALCOSECURITY_RULES_FALCO_PATH}"
|
||||
DESTINATION "${FALCO_ETC_DIR}"
|
||||
RENAME "${FALCO_RULES_DEST_FILENAME}"
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
install(
|
||||
FILES "${FALCOSECURITY_RULES_FALCO_PATH}"
|
||||
DESTINATION "${FALCO_ETC_DIR}"
|
||||
RENAME "${FALCO_RULES_DEST_FILENAME}"
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}"
|
||||
)
|
||||
|
||||
install(
|
||||
FILES "${FALCOSECURITY_RULES_LOCAL_PATH}"
|
||||
DESTINATION "${FALCO_ETC_DIR}"
|
||||
RENAME "${FALCO_LOCAL_RULES_DEST_FILENAME}"
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
install(
|
||||
FILES "${FALCOSECURITY_RULES_LOCAL_PATH}"
|
||||
DESTINATION "${FALCO_ETC_DIR}"
|
||||
RENAME "${FALCO_LOCAL_RULES_DEST_FILENAME}"
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}"
|
||||
)
|
||||
|
||||
install(DIRECTORY DESTINATION "${FALCO_ETC_DIR}/rules.d" COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
install(
|
||||
DIRECTORY
|
||||
DESTINATION "${FALCO_ETC_DIR}/rules.d"
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}"
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# 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.
|
||||
#
|
||||
|
||||
# create the reports folder
|
||||
@@ -22,35 +23,42 @@ find_program(CPPCHECK cppcheck)
|
||||
find_program(CPPCHECK_HTMLREPORT cppcheck-htmlreport)
|
||||
|
||||
if(NOT CPPCHECK)
|
||||
message(STATUS "cppcheck command not found, static code analysis using cppcheck will not be available.")
|
||||
message(
|
||||
STATUS
|
||||
"cppcheck command not found, static code analysis using cppcheck will not be available."
|
||||
)
|
||||
else()
|
||||
message(STATUS "cppcheck found at: ${CPPCHECK}")
|
||||
# we are aware that cppcheck can be run
|
||||
# along with the software compilation in a single step
|
||||
# using the CMAKE_CXX_CPPCHECK variables.
|
||||
# However, for practical needs we want to keep the
|
||||
# two things separated and have a specific target for it.
|
||||
# Our cppcheck target reads the compilation database produced by CMake
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS On)
|
||||
add_custom_target(
|
||||
cppcheck
|
||||
COMMAND ${CPPCHECK}
|
||||
"--enable=all"
|
||||
"--force"
|
||||
"--inconclusive"
|
||||
"--inline-suppr" # allows to specify suppressions directly in source code
|
||||
"--xml" # we want to generate a report
|
||||
"--output-file=${CMAKE_CURRENT_BINARY_DIR}/static-analysis-reports/cppcheck/cppcheck.xml" # generate the report under the reports folder in the build folder
|
||||
"-i${CMAKE_CURRENT_BINARY_DIR}"# exclude the build folder
|
||||
"${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
message(STATUS "cppcheck found at: ${CPPCHECK}")
|
||||
# we are aware that cppcheck can be run along with the software compilation in a single step
|
||||
# using the CMAKE_CXX_CPPCHECK variables. However, for practical needs we want to keep the two
|
||||
# things separated and have a specific target for it. Our cppcheck target reads the compilation
|
||||
# database produced by CMake
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS On)
|
||||
add_custom_target(
|
||||
cppcheck
|
||||
COMMAND
|
||||
${CPPCHECK} "--enable=all" "--force" "--inconclusive" "--inline-suppr" # allows to
|
||||
# specify suppressions directly in source code
|
||||
"--xml" # we want to generate a report
|
||||
"--output-file=${CMAKE_CURRENT_BINARY_DIR}/static-analysis-reports/cppcheck/cppcheck.xml" # generate
|
||||
# the report under the reports folder in the build folder
|
||||
"-i${CMAKE_CURRENT_BINARY_DIR}" # exclude the build folder
|
||||
"${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
endif() # CPPCHECK
|
||||
|
||||
if(NOT CPPCHECK_HTMLREPORT)
|
||||
message(STATUS "cppcheck-htmlreport command not found, will not be able to produce html reports for cppcheck results")
|
||||
message(
|
||||
STATUS
|
||||
"cppcheck-htmlreport command not found, will not be able to produce html reports for cppcheck results"
|
||||
)
|
||||
else()
|
||||
message(STATUS "cppcheck-htmlreport found at: ${CPPCHECK_HTMLREPORT}")
|
||||
add_custom_target(
|
||||
cppcheck_htmlreport
|
||||
COMMAND ${CPPCHECK_HTMLREPORT} --title=${CMAKE_PROJECT_NAME} --report-dir=${CMAKE_CURRENT_BINARY_DIR}/static-analysis-reports/cppcheck --file=static-analysis-reports/cppcheck/cppcheck.xml)
|
||||
message(STATUS "cppcheck-htmlreport found at: ${CPPCHECK_HTMLREPORT}")
|
||||
add_custom_target(
|
||||
cppcheck_htmlreport
|
||||
COMMAND
|
||||
${CPPCHECK_HTMLREPORT} --title=${CMAKE_PROJECT_NAME}
|
||||
--report-dir=${CMAKE_CURRENT_BINARY_DIR}/static-analysis-reports/cppcheck
|
||||
--file=static-analysis-reports/cppcheck/cppcheck.xml
|
||||
)
|
||||
endif() # CPPCHECK_HTMLREPORT
|
||||
|
||||
@@ -2,25 +2,27 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
# or implied. See the License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
#
|
||||
|
||||
option(USE_BUNDLED_YAMLCPP "Enable building of the bundled yamlcpp" ${USE_BUNDLED_DEPS})
|
||||
|
||||
if(USE_BUNDLED_YAMLCPP)
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(yamlcpp
|
||||
URL https://github.com/jbeder/yaml-cpp/archive/refs/tags/0.8.0.tar.gz
|
||||
URL_HASH SHA256=fbe74bbdcee21d656715688706da3c8becfd946d92cd44705cc6098bb23b3a16
|
||||
)
|
||||
FetchContent_MakeAvailable(yamlcpp)
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
yamlcpp
|
||||
URL https://github.com/jbeder/yaml-cpp/archive/refs/tags/0.8.0.tar.gz
|
||||
URL_HASH SHA256=fbe74bbdcee21d656715688706da3c8becfd946d92cd44705cc6098bb23b3a16
|
||||
)
|
||||
FetchContent_MakeAvailable(yamlcpp)
|
||||
else()
|
||||
find_package(yaml-cpp CONFIG REQUIRED)
|
||||
find_package(yaml-cpp CONFIG REQUIRED)
|
||||
endif()
|
||||
|
||||
@@ -2,35 +2,44 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
# 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
|
||||
#
|
||||
# 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.
|
||||
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
# or implied. See the License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
#
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
# Systemd
|
||||
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/scripts/systemd)
|
||||
configure_file("${PROJECT_SOURCE_DIR}/scripts/systemd/falco-kmod-inject.service"
|
||||
"${PROJECT_BINARY_DIR}/scripts/systemd" COPYONLY)
|
||||
configure_file("${PROJECT_SOURCE_DIR}/scripts/systemd/falco-kmod.service"
|
||||
"${PROJECT_BINARY_DIR}/scripts/systemd" COPYONLY)
|
||||
configure_file("${PROJECT_SOURCE_DIR}/scripts/systemd/falco-bpf.service"
|
||||
"${PROJECT_BINARY_DIR}/scripts/systemd" COPYONLY)
|
||||
configure_file("${PROJECT_SOURCE_DIR}/scripts/systemd/falco-modern-bpf.service"
|
||||
"${PROJECT_BINARY_DIR}/scripts/systemd" COPYONLY)
|
||||
configure_file("${PROJECT_SOURCE_DIR}/scripts/systemd/falco-custom.service"
|
||||
"${PROJECT_BINARY_DIR}/scripts/systemd" COPYONLY)
|
||||
configure_file("${PROJECT_SOURCE_DIR}/scripts/systemd/falcoctl-artifact-follow.service"
|
||||
"${PROJECT_BINARY_DIR}/scripts/systemd" COPYONLY)
|
||||
configure_file(
|
||||
"${PROJECT_SOURCE_DIR}/scripts/systemd/falco-kmod-inject.service"
|
||||
"${PROJECT_BINARY_DIR}/scripts/systemd" COPYONLY
|
||||
)
|
||||
configure_file(
|
||||
"${PROJECT_SOURCE_DIR}/scripts/systemd/falco-kmod.service"
|
||||
"${PROJECT_BINARY_DIR}/scripts/systemd" COPYONLY
|
||||
)
|
||||
configure_file(
|
||||
"${PROJECT_SOURCE_DIR}/scripts/systemd/falco-bpf.service"
|
||||
"${PROJECT_BINARY_DIR}/scripts/systemd" COPYONLY
|
||||
)
|
||||
configure_file(
|
||||
"${PROJECT_SOURCE_DIR}/scripts/systemd/falco-modern-bpf.service"
|
||||
"${PROJECT_BINARY_DIR}/scripts/systemd" COPYONLY
|
||||
)
|
||||
configure_file(
|
||||
"${PROJECT_SOURCE_DIR}/scripts/systemd/falco-custom.service"
|
||||
"${PROJECT_BINARY_DIR}/scripts/systemd" COPYONLY
|
||||
)
|
||||
configure_file(
|
||||
"${PROJECT_SOURCE_DIR}/scripts/systemd/falcoctl-artifact-follow.service"
|
||||
"${PROJECT_BINARY_DIR}/scripts/systemd" COPYONLY
|
||||
)
|
||||
|
||||
# Debian
|
||||
configure_file(debian/postinst.in debian/postinst COPYONLY)
|
||||
@@ -44,21 +53,32 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
endif()
|
||||
|
||||
# Install Falcoctl config file
|
||||
if (NOT WIN32 AND NOT APPLE AND NOT EMSCRIPTEN AND NOT MUSL_OPTIMIZED_BUILD)
|
||||
if(NOT WIN32
|
||||
AND NOT APPLE
|
||||
AND NOT EMSCRIPTEN
|
||||
AND NOT MUSL_OPTIMIZED_BUILD
|
||||
)
|
||||
if(NOT DEFINED FALCOCTL_ETC_DIR)
|
||||
set(FALCOCTL_ETC_DIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}/falcoctl")
|
||||
endif()
|
||||
set(FALCOCTL_DRIVER_TYPES_LIST "")
|
||||
if (BUILD_FALCO_MODERN_BPF)
|
||||
endif()
|
||||
set(FALCOCTL_DRIVER_TYPES_LIST "")
|
||||
if(BUILD_FALCO_MODERN_BPF)
|
||||
list(APPEND FALCOCTL_DRIVER_TYPES_LIST "modern_ebpf")
|
||||
endif()
|
||||
if (BUILD_DRIVER)
|
||||
if(BUILD_DRIVER)
|
||||
list(APPEND FALCOCTL_DRIVER_TYPES_LIST "kmod")
|
||||
endif()
|
||||
if (BUILD_BPF)
|
||||
if(BUILD_BPF)
|
||||
list(APPEND FALCOCTL_DRIVER_TYPES_LIST "ebpf")
|
||||
endif()
|
||||
string(REPLACE ";" ", " FALCOCTL_DRIVER_TYPES "${FALCOCTL_DRIVER_TYPES_LIST}")
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/falcoctl/falcoctl.yaml.in ${PROJECT_BINARY_DIR}/scripts/falcoctl/falcoctl.yaml)
|
||||
install(FILES ${PROJECT_BINARY_DIR}/scripts/falcoctl/falcoctl.yaml DESTINATION "${FALCOCTL_ETC_DIR}" COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/falcoctl/falcoctl.yaml.in
|
||||
${PROJECT_BINARY_DIR}/scripts/falcoctl/falcoctl.yaml
|
||||
)
|
||||
install(
|
||||
FILES ${PROJECT_BINARY_DIR}/scripts/falcoctl/falcoctl.yaml
|
||||
DESTINATION "${FALCOCTL_ETC_DIR}"
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}"
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -24,3 +24,4 @@ StandardOutput=null
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Alias=falco.service
|
||||
@@ -24,3 +24,4 @@ StandardOutput=null
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Alias=falco.service
|
||||
|
||||
@@ -24,3 +24,4 @@ StandardOutput=null
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Alias=falco.service
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# 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.
|
||||
#
|
||||
|
||||
message(STATUS "Falco unit tests build enabled")
|
||||
@@ -17,72 +18,72 @@ message(STATUS "Falco unit tests build enabled")
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG v1.14.0
|
||||
googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG v1.14.0
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
# Create a libscap_test_var.h file with some variables used by our tests
|
||||
# for example the kmod path or the bpf path.
|
||||
configure_file (
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/falco_test_var.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/falco_test_var.h
|
||||
# Create a libscap_test_var.h file with some variables used by our tests for example the kmod path
|
||||
# or the bpf path.
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/falco_test_var.h.in ${CMAKE_CURRENT_BINARY_DIR}/falco_test_var.h
|
||||
)
|
||||
|
||||
add_executable(falco_unit_tests
|
||||
test_falco_engine.cpp
|
||||
engine/test_add_source.cpp
|
||||
engine/test_alt_rule_loader.cpp
|
||||
engine/test_enable_rule.cpp
|
||||
engine/test_extra_output.cpp
|
||||
engine/test_falco_utils.cpp
|
||||
engine/test_filter_details_resolver.cpp
|
||||
engine/test_filter_macro_resolver.cpp
|
||||
engine/test_filter_warning_resolver.cpp
|
||||
engine/test_plugin_requirements.cpp
|
||||
engine/test_rule_loader.cpp
|
||||
engine/test_rulesets.cpp
|
||||
falco/test_configuration.cpp
|
||||
falco/test_configuration_rule_selection.cpp
|
||||
falco/test_configuration_config_files.cpp
|
||||
falco/test_configuration_env_vars.cpp
|
||||
falco/test_configuration_output_options.cpp
|
||||
falco/test_configuration_schema.cpp
|
||||
falco/app/actions/test_select_event_sources.cpp
|
||||
falco/app/actions/test_load_config.cpp
|
||||
add_executable(
|
||||
falco_unit_tests
|
||||
test_falco_engine.cpp
|
||||
engine/test_add_source.cpp
|
||||
engine/test_alt_rule_loader.cpp
|
||||
engine/test_enable_rule.cpp
|
||||
engine/test_extra_output.cpp
|
||||
engine/test_falco_utils.cpp
|
||||
engine/test_filter_details_resolver.cpp
|
||||
engine/test_filter_macro_resolver.cpp
|
||||
engine/test_filter_warning_resolver.cpp
|
||||
engine/test_plugin_requirements.cpp
|
||||
engine/test_rule_loader.cpp
|
||||
engine/test_rulesets.cpp
|
||||
falco/test_configuration.cpp
|
||||
falco/test_configuration_rule_selection.cpp
|
||||
falco/test_configuration_config_files.cpp
|
||||
falco/test_configuration_env_vars.cpp
|
||||
falco/test_configuration_output_options.cpp
|
||||
falco/test_configuration_schema.cpp
|
||||
falco/app/actions/test_select_event_sources.cpp
|
||||
falco/app/actions/test_load_config.cpp
|
||||
)
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
target_sources(falco_unit_tests
|
||||
PRIVATE
|
||||
falco/test_atomic_signal_handler.cpp
|
||||
falco/app/actions/test_configure_interesting_sets.cpp
|
||||
falco/app/actions/test_configure_syscall_buffer_num.cpp
|
||||
)
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
target_sources(
|
||||
falco_unit_tests
|
||||
PRIVATE falco/test_atomic_signal_handler.cpp
|
||||
falco/app/actions/test_configure_interesting_sets.cpp
|
||||
falco/app/actions/test_configure_syscall_buffer_num.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
target_include_directories(falco_unit_tests
|
||||
PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/userspace
|
||||
${CMAKE_BINARY_DIR}/userspace/falco # we need it to include indirectly `config_falco.h` file
|
||||
${CMAKE_SOURCE_DIR}/userspace/engine # we need it to include indirectly `falco_common.h` file
|
||||
${CMAKE_CURRENT_BINARY_DIR} # we need it to include `falco_test_var.h`
|
||||
target_include_directories(
|
||||
falco_unit_tests
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/userspace
|
||||
${CMAKE_BINARY_DIR}/userspace/falco # we need it to include indirectly `config_falco.h`
|
||||
# file
|
||||
${CMAKE_SOURCE_DIR}/userspace/engine # we need it to include indirectly `falco_common.h`
|
||||
# file
|
||||
${CMAKE_CURRENT_BINARY_DIR} # we need it to include `falco_test_var.h`
|
||||
)
|
||||
|
||||
get_target_property(FALCO_APPLICATION_LIBRARIES falco_application LINK_LIBRARIES)
|
||||
|
||||
target_link_libraries(falco_unit_tests
|
||||
falco_application
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
${FALCO_APPLICATION_LIBRARIES}
|
||||
target_link_libraries(
|
||||
falco_unit_tests falco_application GTest::gtest GTest::gtest_main
|
||||
${FALCO_APPLICATION_LIBRARIES}
|
||||
)
|
||||
|
||||
if (EMSCRIPTEN)
|
||||
if(EMSCRIPTEN)
|
||||
target_compile_options(falco_unit_tests PRIVATE "-sDISABLE_EXCEPTION_CATCHING=0")
|
||||
target_link_options(falco_unit_tests PRIVATE "-sDISABLE_EXCEPTION_CATCHING=0")
|
||||
target_link_options(falco_unit_tests PRIVATE "-sALLOW_MEMORY_GROWTH=1")
|
||||
target_link_options(falco_unit_tests PRIVATE "-sALLOW_MEMORY_GROWTH=1")
|
||||
target_link_options(falco_unit_tests PRIVATE "-sEXPORTED_FUNCTIONS=['_main','_htons','_ntohs']")
|
||||
endif()
|
||||
|
||||
@@ -26,36 +26,30 @@ static std::string syscall_source_name = "syscall";
|
||||
// for the underlying ruleset. This allows testing of
|
||||
// ruleset_for_source
|
||||
|
||||
namespace
|
||||
{
|
||||
class test_ruleset_factory : public evttype_index_ruleset_factory
|
||||
{
|
||||
namespace {
|
||||
class test_ruleset_factory : public evttype_index_ruleset_factory {
|
||||
public:
|
||||
explicit test_ruleset_factory(std::shared_ptr<sinsp_filter_factory> factory):
|
||||
evttype_index_ruleset_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;
|
||||
}
|
||||
inline std::shared_ptr<filter_ruleset> new_ruleset() override { return ruleset; }
|
||||
|
||||
std::shared_ptr<filter_ruleset> ruleset;
|
||||
};
|
||||
}; // namespace
|
||||
}; // namespace
|
||||
|
||||
TEST(AddSource, basic)
|
||||
{
|
||||
TEST(AddSource, basic) {
|
||||
falco_engine engine;
|
||||
sinsp inspector;
|
||||
sinsp_filter_check_list filterchecks;
|
||||
|
||||
auto filter_factory = std::make_shared<sinsp_filter_factory>(&inspector, filterchecks);
|
||||
auto formatter_factory = std::make_shared<sinsp_evt_formatter_factory>(&inspector, filterchecks);
|
||||
auto formatter_factory =
|
||||
std::make_shared<sinsp_evt_formatter_factory>(&inspector, filterchecks);
|
||||
auto ruleset_factory = std::make_shared<test_ruleset_factory>(filter_factory);
|
||||
|
||||
falco_source syscall_source;
|
||||
@@ -66,9 +60,9 @@ TEST(AddSource, basic)
|
||||
syscall_source.formatter_factory = formatter_factory;
|
||||
|
||||
size_t source_idx = engine.add_source(syscall_source_name,
|
||||
filter_factory,
|
||||
formatter_factory,
|
||||
ruleset_factory);
|
||||
filter_factory,
|
||||
formatter_factory,
|
||||
ruleset_factory);
|
||||
|
||||
ASSERT_TRUE(engine.is_source_valid(syscall_source_name));
|
||||
|
||||
|
||||
@@ -32,42 +32,35 @@ limitations under the License.
|
||||
#include "rule_loader_collector.h"
|
||||
#include "rule_loader_compiler.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
|
||||
struct test_object_info
|
||||
{
|
||||
struct test_object_info {
|
||||
std::string name;
|
||||
std::string property;
|
||||
};
|
||||
|
||||
struct test_compile_output : public rule_loader::compile_output
|
||||
{
|
||||
struct test_compile_output : public rule_loader::compile_output {
|
||||
test_compile_output() = default;
|
||||
~test_compile_output() = default;
|
||||
|
||||
std::set<std::string> defined_test_properties;
|
||||
};
|
||||
|
||||
class test_compiler : public rule_loader::compiler
|
||||
{
|
||||
class test_compiler : public rule_loader::compiler {
|
||||
public:
|
||||
test_compiler() = default;
|
||||
virtual ~test_compiler() = default;
|
||||
|
||||
std::unique_ptr<rule_loader::compile_output> new_compile_output() override
|
||||
{
|
||||
std::unique_ptr<rule_loader::compile_output> new_compile_output() override {
|
||||
return std::make_unique<test_compile_output>();
|
||||
}
|
||||
|
||||
void compile(
|
||||
rule_loader::configuration& cfg,
|
||||
const rule_loader::collector& col,
|
||||
rule_loader::compile_output& out) const override;
|
||||
void compile(rule_loader::configuration& cfg,
|
||||
const rule_loader::collector& col,
|
||||
rule_loader::compile_output& out) const override;
|
||||
};
|
||||
|
||||
class test_collector : public rule_loader::collector
|
||||
{
|
||||
class test_collector : public rule_loader::collector {
|
||||
public:
|
||||
test_collector() = default;
|
||||
virtual ~test_collector() = default;
|
||||
@@ -75,32 +68,27 @@ public:
|
||||
indexed_vector<test_object_info> test_object_infos;
|
||||
};
|
||||
|
||||
class test_reader : public rule_loader::reader
|
||||
{
|
||||
class test_reader : public rule_loader::reader {
|
||||
public:
|
||||
test_reader() = default;
|
||||
virtual ~test_reader() = default;
|
||||
|
||||
protected:
|
||||
rule_loader::context create_context(const YAML::Node& item,
|
||||
const rule_loader::context& parent)
|
||||
{
|
||||
const rule_loader::context& parent) {
|
||||
return rule_loader::context(item,
|
||||
rule_loader::context::EXTENSION_ITEM,
|
||||
"test object",
|
||||
parent);
|
||||
rule_loader::context::EXTENSION_ITEM,
|
||||
"test object",
|
||||
parent);
|
||||
};
|
||||
|
||||
void read_item(rule_loader::configuration& cfg,
|
||||
rule_loader::collector& collector,
|
||||
const YAML::Node& item,
|
||||
const rule_loader::context& parent) override
|
||||
{
|
||||
test_collector& test_col =
|
||||
dynamic_cast<test_collector&>(collector);
|
||||
rule_loader::collector& collector,
|
||||
const YAML::Node& item,
|
||||
const rule_loader::context& parent) override {
|
||||
test_collector& test_col = dynamic_cast<test_collector&>(collector);
|
||||
|
||||
if(item["test_object"].IsDefined())
|
||||
{
|
||||
if(item["test_object"].IsDefined()) {
|
||||
rule_loader::context tmp = create_context(item, parent);
|
||||
test_object_info obj;
|
||||
std::string name;
|
||||
@@ -113,37 +101,29 @@ protected:
|
||||
obj.property = property;
|
||||
|
||||
test_col.test_object_infos.insert(obj, obj.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
rule_loader::reader::read_item(cfg, collector, item, parent);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class test_ruleset : public evttype_index_ruleset
|
||||
{
|
||||
class test_ruleset : public evttype_index_ruleset {
|
||||
public:
|
||||
explicit test_ruleset(std::shared_ptr<sinsp_filter_factory> factory):
|
||||
evttype_index_ruleset(factory){};
|
||||
evttype_index_ruleset(factory) {};
|
||||
virtual ~test_ruleset() = default;
|
||||
|
||||
void add_compile_output(
|
||||
const rule_loader::compile_output& compile_output,
|
||||
falco_common::priority_type min_priority,
|
||||
const std::string& source)
|
||||
{
|
||||
|
||||
evttype_index_ruleset::add_compile_output(compile_output,
|
||||
min_priority,
|
||||
source);
|
||||
void add_compile_output(const rule_loader::compile_output& compile_output,
|
||||
falco_common::priority_type min_priority,
|
||||
const std::string& source) {
|
||||
evttype_index_ruleset::add_compile_output(compile_output, min_priority, source);
|
||||
|
||||
std::shared_ptr<filter_ruleset> ruleset;
|
||||
get_engine_state().get_ruleset(source, ruleset);
|
||||
EXPECT_EQ(this, ruleset.get());
|
||||
|
||||
const test_compile_output& test_output =
|
||||
dynamic_cast<const test_compile_output&>(compile_output);
|
||||
dynamic_cast<const test_compile_output&>(compile_output);
|
||||
|
||||
defined_properties = test_output.defined_test_properties;
|
||||
};
|
||||
@@ -151,40 +131,31 @@ public:
|
||||
std::set<std::string> defined_properties;
|
||||
};
|
||||
|
||||
class test_ruleset_factory : public filter_ruleset_factory
|
||||
{
|
||||
class test_ruleset_factory : public filter_ruleset_factory {
|
||||
public:
|
||||
explicit test_ruleset_factory(std::shared_ptr<sinsp_filter_factory> factory):
|
||||
m_filter_factory(factory)
|
||||
{
|
||||
}
|
||||
m_filter_factory(factory) {}
|
||||
|
||||
virtual ~test_ruleset_factory() = default;
|
||||
|
||||
inline std::shared_ptr<filter_ruleset> new_ruleset() override
|
||||
{
|
||||
inline std::shared_ptr<filter_ruleset> new_ruleset() override {
|
||||
return std::make_shared<test_ruleset>(m_filter_factory);
|
||||
}
|
||||
|
||||
std::shared_ptr<sinsp_filter_factory> m_filter_factory;
|
||||
};
|
||||
}; // namespace
|
||||
}; // namespace
|
||||
|
||||
void test_compiler::compile(
|
||||
rule_loader::configuration& cfg,
|
||||
const rule_loader::collector& col,
|
||||
rule_loader::compile_output& out) const
|
||||
{
|
||||
void test_compiler::compile(rule_loader::configuration& cfg,
|
||||
const rule_loader::collector& col,
|
||||
rule_loader::compile_output& out) const {
|
||||
rule_loader::compiler::compile(cfg, col, out);
|
||||
|
||||
const test_collector& test_col =
|
||||
dynamic_cast<const test_collector&>(col);
|
||||
const test_collector& test_col = dynamic_cast<const test_collector&>(col);
|
||||
|
||||
test_compile_output& test_output =
|
||||
dynamic_cast<test_compile_output&>(out);
|
||||
test_compile_output& test_output = dynamic_cast<test_compile_output&>(out);
|
||||
|
||||
for(auto& test_obj : test_col.test_object_infos)
|
||||
{
|
||||
for(auto& test_obj : test_col.test_object_infos) {
|
||||
test_output.defined_test_properties.insert(test_obj.property);
|
||||
}
|
||||
}
|
||||
@@ -230,12 +201,13 @@ static std::string content = R"END(
|
||||
|
||||
static std::string syscall_source_name = "syscall";
|
||||
|
||||
static std::shared_ptr<rule_loader::configuration> create_configuration(sinsp& inspector,
|
||||
sinsp_filter_check_list& filterchecks,
|
||||
indexed_vector<falco_source>& sources)
|
||||
{
|
||||
static std::shared_ptr<rule_loader::configuration> create_configuration(
|
||||
sinsp& inspector,
|
||||
sinsp_filter_check_list& filterchecks,
|
||||
indexed_vector<falco_source>& sources) {
|
||||
auto filter_factory = std::make_shared<sinsp_filter_factory>(&inspector, filterchecks);
|
||||
auto formatter_factory = std::make_shared<sinsp_evt_formatter_factory>(&inspector, filterchecks);
|
||||
auto formatter_factory =
|
||||
std::make_shared<sinsp_evt_formatter_factory>(&inspector, filterchecks);
|
||||
auto ruleset_factory = std::make_shared<evttype_index_ruleset_factory>(filter_factory);
|
||||
|
||||
falco_source syscall_source;
|
||||
@@ -247,17 +219,15 @@ static std::shared_ptr<rule_loader::configuration> create_configuration(sinsp& i
|
||||
|
||||
sources.insert(syscall_source, syscall_source_name);
|
||||
|
||||
return std::make_shared<rule_loader::configuration>(content,
|
||||
sources,
|
||||
"test configuration");
|
||||
return std::make_shared<rule_loader::configuration>(content, sources, "test configuration");
|
||||
}
|
||||
|
||||
static void load_rules(sinsp& inspector,
|
||||
sinsp_filter_check_list& filterchecks,
|
||||
std::unique_ptr<rule_loader::compile_output>& compile_output,
|
||||
indexed_vector<falco_source>& sources)
|
||||
{
|
||||
std::shared_ptr<rule_loader::configuration> cfg = create_configuration(inspector, filterchecks, sources);
|
||||
sinsp_filter_check_list& filterchecks,
|
||||
std::unique_ptr<rule_loader::compile_output>& compile_output,
|
||||
indexed_vector<falco_source>& sources) {
|
||||
std::shared_ptr<rule_loader::configuration> cfg =
|
||||
create_configuration(inspector, filterchecks, sources);
|
||||
|
||||
rule_loader::reader reader;
|
||||
rule_loader::collector collector;
|
||||
@@ -270,8 +240,7 @@ static void load_rules(sinsp& inspector,
|
||||
compiler.compile(*cfg, collector, *compile_output);
|
||||
}
|
||||
|
||||
TEST(engine_loader_alt_loader, load_rules)
|
||||
{
|
||||
TEST(engine_loader_alt_loader, load_rules) {
|
||||
sinsp inspector;
|
||||
sinsp_filter_check_list filterchecks;
|
||||
std::unique_ptr<rule_loader::compile_output> compile_output;
|
||||
@@ -292,8 +261,7 @@ TEST(engine_loader_alt_loader, load_rules)
|
||||
EXPECT_TRUE(compile_output->rules.at("test debug rule") != nullptr);
|
||||
}
|
||||
|
||||
TEST(engine_loader_alt_loader, pass_compile_output_to_ruleset)
|
||||
{
|
||||
TEST(engine_loader_alt_loader, pass_compile_output_to_ruleset) {
|
||||
sinsp inspector;
|
||||
sinsp_filter_check_list filterchecks;
|
||||
std::unique_ptr<rule_loader::compile_output> compile_output;
|
||||
@@ -304,8 +272,8 @@ TEST(engine_loader_alt_loader, pass_compile_output_to_ruleset)
|
||||
std::shared_ptr<filter_ruleset> ruleset = sources.at(syscall_source_name)->ruleset;
|
||||
|
||||
ruleset->add_compile_output(*compile_output,
|
||||
falco_common::PRIORITY_INFORMATIONAL,
|
||||
syscall_source_name);
|
||||
falco_common::PRIORITY_INFORMATIONAL,
|
||||
syscall_source_name);
|
||||
|
||||
// Enable all rules for a ruleset id. Because the compile
|
||||
// output contained one rule with priority >= INFO, that rule
|
||||
@@ -316,14 +284,14 @@ TEST(engine_loader_alt_loader, pass_compile_output_to_ruleset)
|
||||
EXPECT_EQ(ruleset->enabled_count(ruleset_id), 1);
|
||||
}
|
||||
|
||||
TEST(engine_loader_alt_loader, falco_engine_alternate_loader)
|
||||
{
|
||||
TEST(engine_loader_alt_loader, falco_engine_alternate_loader) {
|
||||
falco_engine engine;
|
||||
sinsp inspector;
|
||||
sinsp_filter_check_list filterchecks;
|
||||
|
||||
auto filter_factory = std::make_shared<sinsp_filter_factory>(&inspector, filterchecks);
|
||||
auto formatter_factory = std::make_shared<sinsp_evt_formatter_factory>(&inspector, filterchecks);
|
||||
auto formatter_factory =
|
||||
std::make_shared<sinsp_evt_formatter_factory>(&inspector, filterchecks);
|
||||
auto ruleset_factory = std::make_shared<test_ruleset_factory>(filter_factory);
|
||||
|
||||
engine.add_source(syscall_source_name, filter_factory, formatter_factory, ruleset_factory);
|
||||
@@ -345,7 +313,8 @@ TEST(engine_loader_alt_loader, falco_engine_alternate_loader)
|
||||
EXPECT_EQ(collector->test_object_infos.size(), 2);
|
||||
|
||||
std::shared_ptr<filter_ruleset> ruleset = engine.ruleset_for_source(syscall_source_name);
|
||||
std::set<std::string>& defined_properties = std::dynamic_pointer_cast<test_ruleset>(ruleset)->defined_properties;
|
||||
std::set<std::string>& defined_properties =
|
||||
std::dynamic_pointer_cast<test_ruleset>(ruleset)->defined_properties;
|
||||
|
||||
EXPECT_TRUE(defined_properties.find("my-value") != defined_properties.end());
|
||||
EXPECT_TRUE(defined_properties.find("other-value") != defined_properties.end());
|
||||
|
||||
@@ -72,8 +72,6 @@ static std::string multi_rule = R"END(
|
||||
tags: [exec]
|
||||
)END";
|
||||
|
||||
|
||||
|
||||
// This must be kept in line with the (private) falco_engine::s_default_ruleset
|
||||
static const std::string default_ruleset = "falco-default-ruleset";
|
||||
|
||||
@@ -82,8 +80,7 @@ static const std::string ruleset_2 = "ruleset-2";
|
||||
static const std::string ruleset_3 = "ruleset-3";
|
||||
static const std::string ruleset_4 = "ruleset-4";
|
||||
|
||||
TEST_F(test_falco_engine, enable_rule_name)
|
||||
{
|
||||
TEST_F(test_falco_engine, enable_rule_name) {
|
||||
load_rules(single_rule, "single_rule.yaml");
|
||||
|
||||
// No rules should be enabled yet for any custom rulesets
|
||||
@@ -119,8 +116,7 @@ TEST_F(test_falco_engine, enable_rule_name)
|
||||
EXPECT_EQ(2, m_engine->num_rules_for_ruleset(ruleset_3));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, enable_rule_tags)
|
||||
{
|
||||
TEST_F(test_falco_engine, enable_rule_tags) {
|
||||
std::set<std::string> process_tags = {"process"};
|
||||
|
||||
load_rules(single_rule, "single_rule.yaml");
|
||||
@@ -147,8 +143,7 @@ TEST_F(test_falco_engine, enable_rule_tags)
|
||||
EXPECT_EQ(0, m_engine->num_rules_for_ruleset(ruleset_2));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, enable_disabled_rule_by_tag)
|
||||
{
|
||||
TEST_F(test_falco_engine, enable_disabled_rule_by_tag) {
|
||||
std::set<std::string> exec_process_tags = {"exec process"};
|
||||
|
||||
load_rules(single_rule, "single_rule.yaml");
|
||||
@@ -163,8 +158,7 @@ TEST_F(test_falco_engine, enable_disabled_rule_by_tag)
|
||||
EXPECT_EQ(2, m_engine->num_rules_for_ruleset(default_ruleset));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, enable_rule_id)
|
||||
{
|
||||
TEST_F(test_falco_engine, enable_rule_id) {
|
||||
uint16_t ruleset_1_id;
|
||||
uint16_t ruleset_2_id;
|
||||
uint16_t ruleset_3_id;
|
||||
@@ -204,8 +198,7 @@ TEST_F(test_falco_engine, enable_rule_id)
|
||||
EXPECT_EQ(2, m_engine->num_rules_for_ruleset(ruleset_3));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, enable_rule_name_exact)
|
||||
{
|
||||
TEST_F(test_falco_engine, enable_rule_name_exact) {
|
||||
load_rules(single_rule, "single_rule.yaml");
|
||||
|
||||
EXPECT_EQ(1, m_engine->num_rules_for_ruleset(default_ruleset));
|
||||
@@ -247,8 +240,7 @@ TEST_F(test_falco_engine, enable_rule_name_exact)
|
||||
EXPECT_EQ(2, m_engine->num_rules_for_ruleset(ruleset_4));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, enable_rule_name_wildcard)
|
||||
{
|
||||
TEST_F(test_falco_engine, enable_rule_name_wildcard) {
|
||||
load_rules(multi_rule, "multi_rule.yaml");
|
||||
|
||||
EXPECT_EQ(1, m_engine->num_rules_for_ruleset(default_ruleset));
|
||||
@@ -283,4 +275,3 @@ TEST_F(test_falco_engine, enable_rule_name_wildcard)
|
||||
EXPECT_EQ(1, m_engine->num_rules_for_ruleset(ruleset_3));
|
||||
EXPECT_EQ(3, m_engine->num_rules_for_ruleset(ruleset_4));
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,7 @@ limitations under the License.
|
||||
|
||||
#include "../test_falco_engine.h"
|
||||
|
||||
TEST_F(test_falco_engine, extra_format_all)
|
||||
{
|
||||
TEST_F(test_falco_engine, extra_format_all) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: legit_rule
|
||||
desc: legit rule description
|
||||
@@ -32,11 +31,11 @@ TEST_F(test_falco_engine, extra_format_all)
|
||||
m_engine->add_extra_output_format("evt.type=%evt.type", "", {}, "", false);
|
||||
ASSERT_TRUE(load_rules(rules_content, "legit_rules.yaml")) << m_load_result_string;
|
||||
|
||||
EXPECT_EQ(get_compiled_rule_output("legit_rule"),"user=%user.name command=%proc.cmdline file=%fd.name evt.type=%evt.type");
|
||||
EXPECT_EQ(get_compiled_rule_output("legit_rule"),
|
||||
"user=%user.name command=%proc.cmdline file=%fd.name evt.type=%evt.type");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, extra_format_by_rule)
|
||||
{
|
||||
TEST_F(test_falco_engine, extra_format_by_rule) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: legit_rule
|
||||
desc: legit rule description
|
||||
@@ -54,12 +53,11 @@ TEST_F(test_falco_engine, extra_format_by_rule)
|
||||
m_engine->add_extra_output_format("evt.type=%evt.type", "", {}, "legit_rule", false);
|
||||
ASSERT_TRUE(load_rules(rules_content, "legit_rules.yaml")) << m_load_result_string;
|
||||
|
||||
EXPECT_EQ(get_compiled_rule_output("legit_rule"),"out 1 evt.type=%evt.type");
|
||||
EXPECT_EQ(get_compiled_rule_output("another_rule"),"out 2");
|
||||
EXPECT_EQ(get_compiled_rule_output("legit_rule"), "out 1 evt.type=%evt.type");
|
||||
EXPECT_EQ(get_compiled_rule_output("another_rule"), "out 2");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, extra_format_by_tag_rule)
|
||||
{
|
||||
TEST_F(test_falco_engine, extra_format_by_tag_rule) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: legit_rule
|
||||
desc: legit rule description
|
||||
@@ -89,13 +87,12 @@ TEST_F(test_falco_engine, extra_format_by_tag_rule)
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "legit_rules.yaml")) << m_load_result_string;
|
||||
|
||||
EXPECT_EQ(get_compiled_rule_output("legit_rule"),"out 1 extra 1");
|
||||
EXPECT_EQ(get_compiled_rule_output("another_rule"),"out 2 extra 1 extra 2");
|
||||
EXPECT_EQ(get_compiled_rule_output("a_third_rule"),"out 3 extra 1 extra 3");
|
||||
EXPECT_EQ(get_compiled_rule_output("legit_rule"), "out 1 extra 1");
|
||||
EXPECT_EQ(get_compiled_rule_output("another_rule"), "out 2 extra 1 extra 2");
|
||||
EXPECT_EQ(get_compiled_rule_output("a_third_rule"), "out 3 extra 1 extra 3");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, extra_format_replace_container_info)
|
||||
{
|
||||
TEST_F(test_falco_engine, extra_format_replace_container_info) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: legit_rule
|
||||
desc: legit rule description
|
||||
@@ -120,8 +117,7 @@ TEST_F(test_falco_engine, extra_format_replace_container_info)
|
||||
EXPECT_EQ(get_compiled_rule_output("another_rule"), "out 2 extra 1");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, extra_format_do_not_replace_container_info)
|
||||
{
|
||||
TEST_F(test_falco_engine, extra_format_do_not_replace_container_info) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: legit_rule
|
||||
desc: legit rule description
|
||||
@@ -130,15 +126,14 @@ TEST_F(test_falco_engine, extra_format_do_not_replace_container_info)
|
||||
priority: INFO
|
||||
tags: [tag1]
|
||||
)END";
|
||||
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "legit_rules.yaml")) << m_load_result_string;
|
||||
|
||||
auto output = get_compiled_rule_output("legit_rule");
|
||||
EXPECT_TRUE(output.find("%container.info") == output.npos);
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, extra_fields_all)
|
||||
{
|
||||
TEST_F(test_falco_engine, extra_fields_all) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: legit_rule
|
||||
desc: legit rule description
|
||||
@@ -147,11 +142,11 @@ TEST_F(test_falco_engine, extra_fields_all)
|
||||
priority: INFO
|
||||
)END";
|
||||
|
||||
std::unordered_map<std::string, std::string> extra_formatted_fields = {{"my_field", "hello %evt.num"}};
|
||||
for (auto const& f : extra_formatted_fields)
|
||||
{
|
||||
m_engine->add_extra_output_formatted_field(f.first, f.second, "", {}, "");
|
||||
}
|
||||
std::unordered_map<std::string, std::string> extra_formatted_fields = {
|
||||
{"my_field", "hello %evt.num"}};
|
||||
for(auto const& f : extra_formatted_fields) {
|
||||
m_engine->add_extra_output_formatted_field(f.first, f.second, "", {}, "");
|
||||
}
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "legit_rules.yaml")) << m_load_result_string;
|
||||
|
||||
|
||||
@@ -18,8 +18,7 @@ limitations under the License.
|
||||
#include <gtest/gtest.h>
|
||||
#include <engine/falco_utils.h>
|
||||
|
||||
TEST(FalcoUtils, is_unix_scheme)
|
||||
{
|
||||
TEST(FalcoUtils, is_unix_scheme) {
|
||||
/* Wrong prefix */
|
||||
ASSERT_EQ(falco::utils::network::is_unix_scheme("something:///run/falco/falco.sock"), false);
|
||||
|
||||
@@ -38,15 +37,14 @@ TEST(FalcoUtils, is_unix_scheme)
|
||||
ASSERT_EQ(falco::utils::network::is_unix_scheme(url_char), true);
|
||||
}
|
||||
|
||||
TEST(FalcoUtils, parse_prometheus_interval)
|
||||
{
|
||||
TEST(FalcoUtils, parse_prometheus_interval) {
|
||||
/* Test matrix around correct time conversions. */
|
||||
ASSERT_EQ(falco::utils::parse_prometheus_interval("1ms"), 1UL);
|
||||
ASSERT_EQ(falco::utils::parse_prometheus_interval("1s"), 1000UL);
|
||||
ASSERT_EQ(falco::utils::parse_prometheus_interval("1m"), 60000UL);
|
||||
ASSERT_EQ(falco::utils::parse_prometheus_interval("1h"), 3600000UL);
|
||||
ASSERT_EQ(falco::utils::parse_prometheus_interval("1d"), 86400000UL);
|
||||
ASSERT_EQ(falco::utils::parse_prometheus_interval("1w"), 604800000UL);
|
||||
ASSERT_EQ(falco::utils::parse_prometheus_interval("1w"), 604800000UL);
|
||||
ASSERT_EQ(falco::utils::parse_prometheus_interval("1y"), (unsigned long)31536000000UL);
|
||||
|
||||
ASSERT_EQ(falco::utils::parse_prometheus_interval("300ms"), 300UL);
|
||||
@@ -57,8 +55,11 @@ TEST(FalcoUtils, parse_prometheus_interval)
|
||||
ASSERT_EQ(falco::utils::parse_prometheus_interval("60m"), 3600000UL);
|
||||
|
||||
/* Test matrix for concatenated time interval examples. */
|
||||
ASSERT_EQ(falco::utils::parse_prometheus_interval("1h3m2s1ms"), 3600000UL + 3 * 60000UL + 2 * 1000UL + 1UL);
|
||||
ASSERT_EQ(falco::utils::parse_prometheus_interval("1y1w1d1h1m1s1ms"),(unsigned long) 31536000000UL + 604800000UL + 86400000UL + 3600000UL + 60000UL + 1000UL + 1UL);
|
||||
ASSERT_EQ(falco::utils::parse_prometheus_interval("1h3m2s1ms"),
|
||||
3600000UL + 3 * 60000UL + 2 * 1000UL + 1UL);
|
||||
ASSERT_EQ(falco::utils::parse_prometheus_interval("1y1w1d1h1m1s1ms"),
|
||||
(unsigned long)31536000000UL + 604800000UL + 86400000UL + 3600000UL + 60000UL +
|
||||
1000UL + 1UL);
|
||||
ASSERT_EQ(falco::utils::parse_prometheus_interval("2h5m"), 2 * 3600000UL + 5 * 60000UL);
|
||||
ASSERT_EQ(falco::utils::parse_prometheus_interval("2h 5m"), 2 * 3600000UL + 5 * 60000UL);
|
||||
|
||||
@@ -73,16 +74,16 @@ TEST(FalcoUtils, parse_prometheus_interval)
|
||||
ASSERT_EQ(falco::utils::parse_prometheus_interval("200"), 0UL);
|
||||
}
|
||||
|
||||
TEST(FalcoUtils, sanitize_rule_name)
|
||||
{
|
||||
ASSERT_EQ(falco::utils::sanitize_rule_name("Testing rule 2 (CVE-2244)"), "Testing_rule_2_CVE_2244");
|
||||
TEST(FalcoUtils, sanitize_rule_name) {
|
||||
ASSERT_EQ(falco::utils::sanitize_rule_name("Testing rule 2 (CVE-2244)"),
|
||||
"Testing_rule_2_CVE_2244");
|
||||
ASSERT_EQ(falco::utils::sanitize_rule_name("Testing rule__:2)"), "Testing_rule_:2");
|
||||
ASSERT_EQ(falco::utils::sanitize_rule_name("This@is_a$test rule123"), "This_is_a_test_rule123");
|
||||
ASSERT_EQ(falco::utils::sanitize_rule_name("RULEwith:special#characters"), "RULEwith:special_characters");
|
||||
ASSERT_EQ(falco::utils::sanitize_rule_name("RULEwith:special#characters"),
|
||||
"RULEwith:special_characters");
|
||||
}
|
||||
|
||||
TEST(FalcoUtils, matches_wildcard)
|
||||
{
|
||||
TEST(FalcoUtils, matches_wildcard) {
|
||||
ASSERT_TRUE(falco::utils::matches_wildcard("*", "anything"));
|
||||
ASSERT_TRUE(falco::utils::matches_wildcard("**", "anything"));
|
||||
ASSERT_TRUE(falco::utils::matches_wildcard("*", ""));
|
||||
|
||||
@@ -18,33 +18,33 @@ limitations under the License.
|
||||
#include <gtest/gtest.h>
|
||||
#include <engine/filter_details_resolver.h>
|
||||
|
||||
TEST(DetailsResolver, resolve_ast) {
|
||||
std::string cond =
|
||||
"(spawned_process or evt.type = open) and (proc.name icontains cat or proc.name in "
|
||||
"(known_procs, ps))";
|
||||
auto ast = libsinsp::filter::parser(cond).parse();
|
||||
filter_details details;
|
||||
details.known_macros.insert("spawned_process");
|
||||
details.known_lists.insert("known_procs");
|
||||
filter_details_resolver resolver;
|
||||
resolver.run(ast.get(), details);
|
||||
|
||||
TEST(DetailsResolver, resolve_ast)
|
||||
{
|
||||
std::string cond = "(spawned_process or evt.type = open) and (proc.name icontains cat or proc.name in (known_procs, ps))";
|
||||
auto ast = libsinsp::filter::parser(cond).parse();
|
||||
filter_details details;
|
||||
details.known_macros.insert("spawned_process");
|
||||
details.known_lists.insert("known_procs");
|
||||
filter_details_resolver resolver;
|
||||
resolver.run(ast.get(), details);
|
||||
// Assert fields
|
||||
ASSERT_EQ(details.fields.size(), 2);
|
||||
ASSERT_NE(details.fields.find("evt.type"), details.fields.end());
|
||||
ASSERT_NE(details.fields.find("proc.name"), details.fields.end());
|
||||
|
||||
// Assert fields
|
||||
ASSERT_EQ(details.fields.size(), 2);
|
||||
ASSERT_NE(details.fields.find("evt.type"), details.fields.end());
|
||||
ASSERT_NE(details.fields.find("proc.name"), details.fields.end());
|
||||
// Assert macros
|
||||
ASSERT_EQ(details.macros.size(), 1);
|
||||
ASSERT_NE(details.macros.find("spawned_process"), details.macros.end());
|
||||
|
||||
// Assert macros
|
||||
ASSERT_EQ(details.macros.size(), 1);
|
||||
ASSERT_NE(details.macros.find("spawned_process"), details.macros.end());
|
||||
|
||||
// Assert operators
|
||||
ASSERT_EQ(details.operators.size(), 3);
|
||||
ASSERT_NE(details.operators.find("="), details.operators.end());
|
||||
ASSERT_NE(details.operators.find("icontains"), details.operators.end());
|
||||
ASSERT_NE(details.operators.find("in"), details.operators.end());
|
||||
// Assert operators
|
||||
ASSERT_EQ(details.operators.size(), 3);
|
||||
ASSERT_NE(details.operators.find("="), details.operators.end());
|
||||
ASSERT_NE(details.operators.find("icontains"), details.operators.end());
|
||||
ASSERT_NE(details.operators.find("in"), details.operators.end());
|
||||
|
||||
// Assert lists
|
||||
ASSERT_EQ(details.lists.size(), 1);
|
||||
ASSERT_NE(details.lists.find("known_procs"), details.lists.end());
|
||||
// Assert lists
|
||||
ASSERT_EQ(details.lists.size(), 1);
|
||||
ASSERT_NE(details.lists.find("known_procs"), details.lists.end());
|
||||
}
|
||||
|
||||
@@ -21,33 +21,37 @@ limitations under the License.
|
||||
namespace filter_ast = libsinsp::filter::ast;
|
||||
|
||||
static std::vector<filter_macro_resolver::value_info>::const_iterator find_value(
|
||||
const std::vector<filter_macro_resolver::value_info>& values,
|
||||
const std::string& ref)
|
||||
{
|
||||
const std::vector<filter_macro_resolver::value_info>& values,
|
||||
const std::string& ref) {
|
||||
return std::find_if(
|
||||
values.begin(),
|
||||
values.end(),
|
||||
[&ref](const filter_macro_resolver::value_info& v)
|
||||
{ return v.first == ref; });
|
||||
values.begin(),
|
||||
values.end(),
|
||||
[&ref](const filter_macro_resolver::value_info& v) { return v.first == ref; });
|
||||
}
|
||||
|
||||
#define MACRO_NAME "test_macro"
|
||||
#define MACRO_A_NAME "test_macro_1"
|
||||
#define MACRO_B_NAME "test_macro_2"
|
||||
|
||||
TEST(MacroResolver, should_resolve_macros_on_a_filter_AST)
|
||||
{
|
||||
TEST(MacroResolver, should_resolve_macros_on_a_filter_AST) {
|
||||
filter_ast::pos_info macro_pos(12, 85, 27);
|
||||
|
||||
std::shared_ptr<filter_ast::expr> macro = filter_ast::unary_check_expr::create(filter_ast::field_expr::create("test.field", ""), "exists");
|
||||
std::shared_ptr<filter_ast::expr> macro =
|
||||
filter_ast::unary_check_expr::create(filter_ast::field_expr::create("test.field", ""),
|
||||
"exists");
|
||||
|
||||
std::vector<std::unique_ptr<filter_ast::expr>> filter_and;
|
||||
filter_and.push_back(filter_ast::unary_check_expr::create(filter_ast::field_expr::create("evt.name", ""), "exists"));
|
||||
filter_and.push_back(filter_ast::not_expr::create(filter_ast::identifier_expr::create(MACRO_NAME, macro_pos)));
|
||||
filter_and.push_back(
|
||||
filter_ast::unary_check_expr::create(filter_ast::field_expr::create("evt.name", ""),
|
||||
"exists"));
|
||||
filter_and.push_back(filter_ast::not_expr::create(
|
||||
filter_ast::identifier_expr::create(MACRO_NAME, macro_pos)));
|
||||
std::shared_ptr<filter_ast::expr> filter = filter_ast::and_expr::create(filter_and);
|
||||
|
||||
std::vector<std::unique_ptr<filter_ast::expr>> expected_and;
|
||||
expected_and.push_back(filter_ast::unary_check_expr::create(filter_ast::field_expr::create("evt.name", ""), "exists"));
|
||||
expected_and.push_back(
|
||||
filter_ast::unary_check_expr::create(filter_ast::field_expr::create("evt.name", ""),
|
||||
"exists"));
|
||||
expected_and.push_back(filter_ast::not_expr::create(clone(macro.get())));
|
||||
std::shared_ptr<filter_ast::expr> expected = filter_ast::and_expr::create(expected_and);
|
||||
|
||||
@@ -69,13 +73,15 @@ TEST(MacroResolver, should_resolve_macros_on_a_filter_AST)
|
||||
ASSERT_TRUE(filter->is_equal(expected.get()));
|
||||
}
|
||||
|
||||
TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_single_node)
|
||||
{
|
||||
TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_single_node) {
|
||||
filter_ast::pos_info macro_pos(12, 85, 27);
|
||||
|
||||
std::shared_ptr<filter_ast::expr> macro = filter_ast::unary_check_expr::create(filter_ast::field_expr::create("test.field", ""), "exists");
|
||||
std::shared_ptr<filter_ast::expr> macro =
|
||||
filter_ast::unary_check_expr::create(filter_ast::field_expr::create("test.field", ""),
|
||||
"exists");
|
||||
|
||||
std::shared_ptr<filter_ast::expr> filter = filter_ast::identifier_expr::create(MACRO_NAME, macro_pos);
|
||||
std::shared_ptr<filter_ast::expr> filter =
|
||||
filter_ast::identifier_expr::create(MACRO_NAME, macro_pos);
|
||||
|
||||
filter_macro_resolver resolver;
|
||||
resolver.set_macro(MACRO_NAME, macro);
|
||||
@@ -99,13 +105,16 @@ TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_single_node)
|
||||
ASSERT_TRUE(filter->is_equal(macro.get()));
|
||||
}
|
||||
|
||||
TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_multiple_macros)
|
||||
{
|
||||
TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_multiple_macros) {
|
||||
filter_ast::pos_info a_macro_pos(11, 75, 43);
|
||||
filter_ast::pos_info b_macro_pos(91, 21, 9);
|
||||
|
||||
std::shared_ptr<filter_ast::expr> a_macro = filter_ast::unary_check_expr::create(filter_ast::field_expr::create("one.field", ""), "exists");
|
||||
std::shared_ptr<filter_ast::expr> b_macro = filter_ast::unary_check_expr::create(filter_ast::field_expr::create("another.field", ""), "exists");
|
||||
std::shared_ptr<filter_ast::expr> a_macro =
|
||||
filter_ast::unary_check_expr::create(filter_ast::field_expr::create("one.field", ""),
|
||||
"exists");
|
||||
std::shared_ptr<filter_ast::expr> b_macro = filter_ast::unary_check_expr::create(
|
||||
filter_ast::field_expr::create("another.field", ""),
|
||||
"exists");
|
||||
|
||||
std::vector<std::unique_ptr<filter_ast::expr>> filter_or;
|
||||
filter_or.push_back(filter_ast::identifier_expr::create(MACRO_A_NAME, a_macro_pos));
|
||||
@@ -143,24 +152,31 @@ TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_multiple_macros)
|
||||
ASSERT_TRUE(filter->is_equal(expected_filter.get()));
|
||||
}
|
||||
|
||||
TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_nested_macros)
|
||||
{
|
||||
TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_nested_macros) {
|
||||
filter_ast::pos_info a_macro_pos(47, 1, 76);
|
||||
filter_ast::pos_info b_macro_pos(111, 65, 2);
|
||||
|
||||
std::vector<std::unique_ptr<filter_ast::expr>> a_macro_and;
|
||||
a_macro_and.push_back(filter_ast::unary_check_expr::create(filter_ast::field_expr::create("one.field", ""), "exists"));
|
||||
a_macro_and.push_back(
|
||||
filter_ast::unary_check_expr::create(filter_ast::field_expr::create("one.field", ""),
|
||||
"exists"));
|
||||
a_macro_and.push_back(filter_ast::identifier_expr::create(MACRO_B_NAME, b_macro_pos));
|
||||
std::shared_ptr<filter_ast::expr> a_macro = filter_ast::and_expr::create(a_macro_and);
|
||||
|
||||
std::shared_ptr<filter_ast::expr> b_macro =
|
||||
filter_ast::unary_check_expr::create(filter_ast::field_expr::create("another.field", ""), "exists");
|
||||
std::shared_ptr<filter_ast::expr> b_macro = filter_ast::unary_check_expr::create(
|
||||
filter_ast::field_expr::create("another.field", ""),
|
||||
"exists");
|
||||
|
||||
std::shared_ptr<filter_ast::expr> filter = filter_ast::identifier_expr::create(MACRO_A_NAME, a_macro_pos);
|
||||
std::shared_ptr<filter_ast::expr> filter =
|
||||
filter_ast::identifier_expr::create(MACRO_A_NAME, a_macro_pos);
|
||||
|
||||
std::vector<std::unique_ptr<filter_ast::expr>> expected_and;
|
||||
expected_and.push_back(filter_ast::unary_check_expr::create(filter_ast::field_expr::create("one.field", ""), "exists"));
|
||||
expected_and.push_back(filter_ast::unary_check_expr::create(filter_ast::field_expr::create("another.field", ""), "exists"));
|
||||
expected_and.push_back(
|
||||
filter_ast::unary_check_expr::create(filter_ast::field_expr::create("one.field", ""),
|
||||
"exists"));
|
||||
expected_and.push_back(filter_ast::unary_check_expr::create(
|
||||
filter_ast::field_expr::create("another.field", ""),
|
||||
"exists"));
|
||||
std::shared_ptr<filter_ast::expr> expected_filter = filter_ast::and_expr::create(expected_and);
|
||||
|
||||
filter_macro_resolver resolver;
|
||||
@@ -191,13 +207,15 @@ TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_nested_macros)
|
||||
ASSERT_TRUE(filter->is_equal(expected_filter.get()));
|
||||
}
|
||||
|
||||
TEST(MacroResolver, should_find_unknown_macros)
|
||||
{
|
||||
TEST(MacroResolver, should_find_unknown_macros) {
|
||||
filter_ast::pos_info macro_pos(9, 4, 2);
|
||||
|
||||
std::vector<std::unique_ptr<filter_ast::expr>> filter_and;
|
||||
filter_and.push_back(filter_ast::unary_check_expr::create(filter_ast::field_expr::create("evt.name", ""), "exists"));
|
||||
filter_and.push_back(filter_ast::not_expr::create(filter_ast::identifier_expr::create(MACRO_NAME, macro_pos)));
|
||||
filter_and.push_back(
|
||||
filter_ast::unary_check_expr::create(filter_ast::field_expr::create("evt.name", ""),
|
||||
"exists"));
|
||||
filter_and.push_back(filter_ast::not_expr::create(
|
||||
filter_ast::identifier_expr::create(MACRO_NAME, macro_pos)));
|
||||
std::shared_ptr<filter_ast::expr> filter = filter_ast::and_expr::create(filter_and);
|
||||
|
||||
filter_macro_resolver resolver;
|
||||
@@ -208,17 +226,19 @@ TEST(MacroResolver, should_find_unknown_macros)
|
||||
ASSERT_TRUE(resolver.get_resolved_macros().empty());
|
||||
}
|
||||
|
||||
TEST(MacroResolver, should_find_unknown_nested_macros)
|
||||
{
|
||||
TEST(MacroResolver, should_find_unknown_nested_macros) {
|
||||
filter_ast::pos_info a_macro_pos(32, 84, 9);
|
||||
filter_ast::pos_info b_macro_pos(1, 0, 5);
|
||||
|
||||
std::vector<std::unique_ptr<filter_ast::expr>> a_macro_and;
|
||||
a_macro_and.push_back(filter_ast::unary_check_expr::create(filter_ast::field_expr::create("one.field", ""), "exists"));
|
||||
a_macro_and.push_back(
|
||||
filter_ast::unary_check_expr::create(filter_ast::field_expr::create("one.field", ""),
|
||||
"exists"));
|
||||
a_macro_and.push_back(filter_ast::identifier_expr::create(MACRO_B_NAME, b_macro_pos));
|
||||
std::shared_ptr<filter_ast::expr> a_macro = filter_ast::and_expr::create(a_macro_and);
|
||||
|
||||
std::shared_ptr<filter_ast::expr> filter = filter_ast::identifier_expr::create(MACRO_A_NAME, a_macro_pos);
|
||||
std::shared_ptr<filter_ast::expr> filter =
|
||||
filter_ast::identifier_expr::create(MACRO_A_NAME, a_macro_pos);
|
||||
auto expected_filter = clone(a_macro.get());
|
||||
|
||||
filter_macro_resolver resolver;
|
||||
@@ -234,14 +254,17 @@ TEST(MacroResolver, should_find_unknown_nested_macros)
|
||||
ASSERT_TRUE(filter->is_equal(expected_filter.get()));
|
||||
}
|
||||
|
||||
TEST(MacroResolver, should_undefine_macro)
|
||||
{
|
||||
TEST(MacroResolver, should_undefine_macro) {
|
||||
filter_ast::pos_info macro_pos_1(12, 9, 3);
|
||||
filter_ast::pos_info macro_pos_2(9, 6, 3);
|
||||
|
||||
std::shared_ptr<filter_ast::expr> macro = filter_ast::unary_check_expr::create(filter_ast::field_expr::create("test.field", ""), "exists");
|
||||
std::shared_ptr<filter_ast::expr> a_filter = filter_ast::identifier_expr::create(MACRO_NAME, macro_pos_1);
|
||||
std::shared_ptr<filter_ast::expr> b_filter = filter_ast::identifier_expr::create(MACRO_NAME, macro_pos_2);
|
||||
std::shared_ptr<filter_ast::expr> macro =
|
||||
filter_ast::unary_check_expr::create(filter_ast::field_expr::create("test.field", ""),
|
||||
"exists");
|
||||
std::shared_ptr<filter_ast::expr> a_filter =
|
||||
filter_ast::identifier_expr::create(MACRO_NAME, macro_pos_1);
|
||||
std::shared_ptr<filter_ast::expr> b_filter =
|
||||
filter_ast::identifier_expr::create(MACRO_NAME, macro_pos_2);
|
||||
filter_macro_resolver resolver;
|
||||
|
||||
resolver.set_macro(MACRO_NAME, macro);
|
||||
@@ -261,11 +284,13 @@ TEST(MacroResolver, should_undefine_macro)
|
||||
}
|
||||
|
||||
/* checks that the macro AST is cloned and not shared across resolved filters */
|
||||
TEST(MacroResolver, should_clone_macro_AST)
|
||||
{
|
||||
TEST(MacroResolver, should_clone_macro_AST) {
|
||||
filter_ast::pos_info macro_pos(5, 2, 8888);
|
||||
std::shared_ptr<filter_ast::unary_check_expr> macro = filter_ast::unary_check_expr::create(filter_ast::field_expr::create("test.field", ""), "exists");
|
||||
std::shared_ptr<filter_ast::expr> filter = filter_ast::identifier_expr::create(MACRO_NAME, macro_pos);
|
||||
std::shared_ptr<filter_ast::unary_check_expr> macro =
|
||||
filter_ast::unary_check_expr::create(filter_ast::field_expr::create("test.field", ""),
|
||||
"exists");
|
||||
std::shared_ptr<filter_ast::expr> filter =
|
||||
filter_ast::identifier_expr::create(MACRO_NAME, macro_pos);
|
||||
filter_macro_resolver resolver;
|
||||
|
||||
resolver.set_macro(MACRO_NAME, macro);
|
||||
|
||||
@@ -18,16 +18,14 @@ limitations under the License.
|
||||
#include <gtest/gtest.h>
|
||||
#include <engine/filter_warning_resolver.h>
|
||||
|
||||
static bool warns(const std::string& condition)
|
||||
{
|
||||
static bool warns(const std::string& condition) {
|
||||
std::set<falco::load_result::warning_code> w;
|
||||
auto ast = libsinsp::filter::parser(condition).parse();
|
||||
filter_warning_resolver().run(ast.get(), w);
|
||||
return !w.empty();
|
||||
}
|
||||
|
||||
TEST(WarningResolver, warnings_in_filtering_conditions)
|
||||
{
|
||||
TEST(WarningResolver, warnings_in_filtering_conditions) {
|
||||
ASSERT_FALSE(warns("ka.field exists"));
|
||||
ASSERT_FALSE(warns("some.field = <NA>"));
|
||||
ASSERT_TRUE(warns("jevt.field = <NA>"));
|
||||
|
||||
@@ -20,22 +20,19 @@ limitations under the License.
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
static bool check_requirements(std::string& err,
|
||||
const std::vector<falco_engine::plugin_version_requirement>& plugins,
|
||||
const std::string& ruleset_content)
|
||||
{
|
||||
const std::vector<falco_engine::plugin_version_requirement>& plugins,
|
||||
const std::string& ruleset_content) {
|
||||
falco_engine e;
|
||||
falco::load_result::rules_contents_t c = {{"test", ruleset_content}};
|
||||
|
||||
auto res = e.load_rules(c.begin()->second, c.begin()->first);
|
||||
if(!res->successful())
|
||||
{
|
||||
if(!res->successful()) {
|
||||
return false;
|
||||
}
|
||||
return e.check_plugin_requirements(plugins, err);
|
||||
}
|
||||
|
||||
TEST(PluginRequirements, check_plugin_requirements_success)
|
||||
{
|
||||
TEST(PluginRequirements, check_plugin_requirements_success) {
|
||||
std::string error;
|
||||
|
||||
/* No requirement */
|
||||
@@ -47,7 +44,7 @@ TEST(PluginRequirements, check_plugin_requirements_success)
|
||||
- name: k8saudit
|
||||
version: 0.1.0
|
||||
)")) << error
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
|
||||
/* Single plugin newer version */
|
||||
ASSERT_TRUE(check_requirements(error, {{"k8saudit", "0.2.0"}}, R"(
|
||||
@@ -55,7 +52,7 @@ TEST(PluginRequirements, check_plugin_requirements_success)
|
||||
- name: k8saudit
|
||||
version: 0.1.0
|
||||
)")) << error
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
|
||||
/* Multiple plugins */
|
||||
ASSERT_TRUE(check_requirements(error, {{"k8saudit", "0.1.0"}, {"json", "0.3.0"}}, R"(
|
||||
@@ -65,7 +62,7 @@ TEST(PluginRequirements, check_plugin_requirements_success)
|
||||
- name: json
|
||||
version: 0.3.0
|
||||
)")) << error
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
|
||||
/* Single plugin multiple versions */
|
||||
ASSERT_TRUE(check_requirements(error, {{"k8saudit", "0.2.0"}}, R"(
|
||||
@@ -76,7 +73,7 @@ TEST(PluginRequirements, check_plugin_requirements_success)
|
||||
- name: k8saudit
|
||||
version: 0.2.0
|
||||
)")) << error
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
|
||||
/* Single plugin with alternatives */
|
||||
ASSERT_TRUE(check_requirements(error, {{"k8saudit-other", "0.5.0"}}, R"(
|
||||
@@ -87,7 +84,7 @@ TEST(PluginRequirements, check_plugin_requirements_success)
|
||||
- name: k8saudit-other
|
||||
version: 0.4.0
|
||||
)")) << error
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
|
||||
/* Multiple plugins with alternatives */
|
||||
ASSERT_TRUE(check_requirements(error, {{"k8saudit-other", "0.5.0"}, {"json2", "0.5.0"}}, R"(
|
||||
@@ -103,7 +100,7 @@ TEST(PluginRequirements, check_plugin_requirements_success)
|
||||
- name: json2
|
||||
version: 0.1.0
|
||||
)")) << error
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
|
||||
/* Multiple plugins with alternatives with multiple versions */
|
||||
ASSERT_TRUE(check_requirements(error, {{"k8saudit-other", "0.7.0"}, {"json2", "0.5.0"}}, R"(
|
||||
@@ -125,11 +122,10 @@ TEST(PluginRequirements, check_plugin_requirements_success)
|
||||
- name: k8saudit-other
|
||||
version: 0.7.0
|
||||
)")) << error
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
TEST(PluginRequirements, check_plugin_requirements_reject)
|
||||
{
|
||||
TEST(PluginRequirements, check_plugin_requirements_reject) {
|
||||
std::string error;
|
||||
|
||||
/* No plugin loaded */
|
||||
@@ -138,7 +134,7 @@ TEST(PluginRequirements, check_plugin_requirements_reject)
|
||||
- name: k8saudit
|
||||
version: 0.1.0
|
||||
)")) << error
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
|
||||
/* Single plugin wrong name */
|
||||
ASSERT_FALSE(check_requirements(error, {{"k8saudit", "0.1.0"}}, R"(
|
||||
@@ -146,7 +142,7 @@ TEST(PluginRequirements, check_plugin_requirements_reject)
|
||||
- name: k8saudit2
|
||||
version: 0.1.0
|
||||
)")) << error
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
|
||||
/* Single plugin wrong version */
|
||||
ASSERT_FALSE(check_requirements(error, {{"k8saudit", "0.1.0"}}, R"(
|
||||
@@ -154,7 +150,7 @@ TEST(PluginRequirements, check_plugin_requirements_reject)
|
||||
- name: k8saudit
|
||||
version: 0.2.0
|
||||
)")) << error
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
|
||||
/* Multiple plugins */
|
||||
ASSERT_FALSE(check_requirements(error, {{"k8saudit", "0.1.0"}}, R"(
|
||||
@@ -164,7 +160,7 @@ TEST(PluginRequirements, check_plugin_requirements_reject)
|
||||
- name: json
|
||||
version: 0.3.0
|
||||
)")) << error
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
|
||||
/* Single plugin multiple versions */
|
||||
ASSERT_FALSE(check_requirements(error, {{"k8saudit", "0.1.0"}}, R"(
|
||||
@@ -175,7 +171,7 @@ TEST(PluginRequirements, check_plugin_requirements_reject)
|
||||
- name: k8saudit
|
||||
version: 0.2.0
|
||||
)")) << error
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
|
||||
/* Single plugin with alternatives */
|
||||
ASSERT_FALSE(check_requirements(error, {{"k8saudit2", "0.5.0"}}, R"(
|
||||
@@ -186,7 +182,7 @@ TEST(PluginRequirements, check_plugin_requirements_reject)
|
||||
- name: k8saudit-other
|
||||
version: 0.4.0
|
||||
)")) << error
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
|
||||
/* Single plugin with overlapping alternatives */
|
||||
ASSERT_FALSE(check_requirements(error, {{"k8saudit", "0.5.0"}}, R"(
|
||||
@@ -197,7 +193,7 @@ TEST(PluginRequirements, check_plugin_requirements_reject)
|
||||
- name: k8saudit
|
||||
version: 0.4.0
|
||||
)")) << error
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
|
||||
/* Multiple plugins with alternatives */
|
||||
ASSERT_FALSE(check_requirements(error, {{"k8saudit-other", "0.5.0"}, {"json3", "0.5.0"}}, R"(
|
||||
@@ -213,7 +209,7 @@ TEST(PluginRequirements, check_plugin_requirements_reject)
|
||||
- name: json2
|
||||
version: 0.1.0
|
||||
)")) << error
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
|
||||
/* Multiple plugins with alternatives with multiple versions */
|
||||
ASSERT_FALSE(check_requirements(error, {{"k8saudit", "0.7.0"}, {"json2", "0.5.0"}}, R"(
|
||||
@@ -235,5 +231,5 @@ TEST(PluginRequirements, check_plugin_requirements_reject)
|
||||
- name: k8saudit-other
|
||||
version: 0.7.0
|
||||
)")) << error
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
#include "../test_falco_engine.h"
|
||||
#include "yaml_helper.h"
|
||||
|
||||
#define ASSERT_VALIDATION_STATUS(status) ASSERT_TRUE(sinsp_utils::startswith(m_load_result->schema_validation(), status))
|
||||
#define ASSERT_VALIDATION_STATUS(status) \
|
||||
ASSERT_TRUE(sinsp_utils::startswith(m_load_result->schema_validation(), status))
|
||||
|
||||
std::string s_sample_ruleset = "sample-ruleset";
|
||||
std::string s_sample_source = falco_common::syscall_source;
|
||||
|
||||
TEST_F(test_falco_engine, list_append)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, list_append) {
|
||||
std::string rules_content = R"END(
|
||||
- list: shell_binaries
|
||||
items: [ash, bash, csh, ksh, sh, tcsh, zsh, dash]
|
||||
|
||||
@@ -28,12 +28,13 @@ TEST_F(test_falco_engine, list_append)
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "legit_rules.yaml")) << m_load_result_string;
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_EQ(get_compiled_rule_condition("legit_rule"),"(evt.type = open and proc.name in (ash, bash, csh, ksh, sh, tcsh, zsh, dash, pwsh))");
|
||||
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(test_falco_engine, condition_append)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, condition_append) {
|
||||
std::string rules_content = R"END(
|
||||
- macro: interactive
|
||||
condition: >
|
||||
((proc.aname=sshd and proc.name != sshd) or
|
||||
@@ -53,12 +54,13 @@ TEST_F(test_falco_engine, condition_append)
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "legit_rules.yaml")) << m_load_result_string;
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
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))");
|
||||
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(test_falco_engine, rule_override_append)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, rule_override_append) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: legit_rule
|
||||
desc: legit rule description
|
||||
condition: evt.type=open
|
||||
@@ -84,18 +86,17 @@ TEST_F(test_falco_engine, rule_override_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");
|
||||
"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");
|
||||
"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");
|
||||
"legit rule description with append");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_append)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, rule_append) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: legit_rule
|
||||
desc: legit rule description
|
||||
condition: evt.type=open
|
||||
@@ -113,12 +114,11 @@ TEST_F(test_falco_engine, rule_append)
|
||||
// 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)");
|
||||
ASSERT_EQ(get_compiled_rule_condition("legit_rule"), "(evt.type = open and proc.name = cat)");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_override_replace)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, rule_override_replace) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: legit_rule
|
||||
desc: legit rule description
|
||||
condition: evt.type=open
|
||||
@@ -139,18 +139,17 @@ TEST_F(test_falco_engine, rule_override_replace)
|
||||
|
||||
auto rule_description = m_engine->describe_rule(&rule_name, {});
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["condition"].template get<std::string>(),
|
||||
"evt.type = close");
|
||||
"evt.type = close");
|
||||
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["output"].template get<std::string>(),
|
||||
"user=%user.name command=%proc.cmdline file=%fd.name");
|
||||
"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");
|
||||
"a replaced legit description");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_override_append_replace)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, rule_override_append_replace) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: legit_rule
|
||||
desc: legit rule description
|
||||
condition: evt.type = close
|
||||
@@ -173,21 +172,20 @@ TEST_F(test_falco_engine, rule_override_append_replace)
|
||||
|
||||
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");
|
||||
"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");
|
||||
"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");
|
||||
"a replaced legit description");
|
||||
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["priority"].template get<std::string>(),
|
||||
"Warning");
|
||||
"Warning");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_incorrect_override_type)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, rule_incorrect_override_type) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: failing_rule
|
||||
desc: legit rule description
|
||||
condition: evt.type = close
|
||||
@@ -207,12 +205,12 @@ TEST_F(test_falco_engine, rule_incorrect_override_type)
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
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);
|
||||
ASSERT_TRUE(std::string(m_load_result_json["errors"][0]["context"]["snippet"])
|
||||
.find("priority: append") != std::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_incorrect_append_override)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, rule_incorrect_append_override) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: failing_rule
|
||||
desc: legit rule description
|
||||
condition: evt.type = close
|
||||
@@ -230,16 +228,15 @@ TEST_F(test_falco_engine, rule_incorrect_append_override)
|
||||
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
|
||||
|
||||
// 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(test_falco_engine, macro_override_append_before_macro_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, macro_override_append_before_macro_definition) {
|
||||
std::string rules_content = R"END(
|
||||
|
||||
- macro: open_simple
|
||||
condition: or evt.type = openat2
|
||||
@@ -263,9 +260,8 @@ TEST_F(test_falco_engine, macro_override_append_before_macro_definition)
|
||||
ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_MACRO));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, macro_override_replace_before_macro_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, macro_override_replace_before_macro_definition) {
|
||||
std::string rules_content = R"END(
|
||||
|
||||
- macro: open_simple
|
||||
condition: or evt.type = openat2
|
||||
@@ -286,12 +282,11 @@ TEST_F(test_falco_engine, macro_override_replace_before_macro_definition)
|
||||
// The first override defines a macro that is overridden by the second macro definition
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"evt.type in (open, openat)");
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"), "evt.type in (open, openat)");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, macro_append_before_macro_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, macro_append_before_macro_definition) {
|
||||
std::string rules_content = R"END(
|
||||
|
||||
- macro: open_simple
|
||||
condition: or evt.type = openat2
|
||||
@@ -314,9 +309,8 @@ TEST_F(test_falco_engine, macro_append_before_macro_definition)
|
||||
ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_MACRO));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, macro_override_append_after_macro_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, macro_override_append_after_macro_definition) {
|
||||
std::string rules_content = R"END(
|
||||
|
||||
- macro: open_simple
|
||||
condition: evt.type in (open,openat)
|
||||
@@ -337,12 +331,12 @@ TEST_F(test_falco_engine, macro_override_append_after_macro_definition)
|
||||
// We cannot define a macro override before the macro definition.
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type in (open, openat) or evt.type = openat2)");
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),
|
||||
"(evt.type in (open, openat) or evt.type = openat2)");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, macro_append_after_macro_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, macro_append_after_macro_definition) {
|
||||
std::string rules_content = R"END(
|
||||
|
||||
- macro: open_simple
|
||||
condition: evt.type in (open,openat)
|
||||
@@ -362,12 +356,12 @@ TEST_F(test_falco_engine, macro_append_after_macro_definition)
|
||||
// We cannot define a macro override before the macro definition.
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type in (open, openat) or evt.type = openat2)");
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),
|
||||
"(evt.type in (open, openat) or evt.type = openat2)");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_override_append_before_rule_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, rule_override_append_before_rule_definition) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
condition: and proc.name = cat
|
||||
override:
|
||||
@@ -386,9 +380,8 @@ TEST_F(test_falco_engine, rule_override_append_before_rule_definition)
|
||||
ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_RULE_APPEND));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_override_replace_before_rule_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, rule_override_replace_before_rule_definition) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
condition: and proc.name = cat
|
||||
override:
|
||||
@@ -407,9 +400,8 @@ TEST_F(test_falco_engine, rule_override_replace_before_rule_definition)
|
||||
ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_RULE_REPLACE));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_append_before_rule_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, rule_append_before_rule_definition) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
condition: and proc.name = cat
|
||||
append: true
|
||||
@@ -427,9 +419,8 @@ TEST_F(test_falco_engine, rule_append_before_rule_definition)
|
||||
ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_RULE_APPEND));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_override_append_after_rule_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, rule_override_append_after_rule_definition) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: simple rule
|
||||
condition: evt.type in (open,openat)
|
||||
@@ -444,12 +435,12 @@ TEST_F(test_falco_engine, rule_override_append_after_rule_definition)
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type in (open, openat) and proc.name = cat)");
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),
|
||||
"(evt.type in (open, openat) and proc.name = cat)");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_append_after_rule_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, rule_append_after_rule_definition) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: simple rule
|
||||
condition: evt.type in (open,openat)
|
||||
@@ -463,14 +454,14 @@ TEST_F(test_falco_engine, rule_append_after_rule_definition)
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type in (open, openat) and proc.name = cat)");
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),
|
||||
"(evt.type in (open, openat) and proc.name = cat)");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, list_override_append_wrong_key)
|
||||
{
|
||||
TEST_F(test_falco_engine, 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(
|
||||
std::string rules_content = R"END(
|
||||
- list: dev_creation_binaries
|
||||
items: ["csi-provisioner", "csi-attacher"]
|
||||
override_written_wrong:
|
||||
@@ -488,16 +479,16 @@ TEST_F(test_falco_engine, list_override_append_wrong_key)
|
||||
)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
|
||||
// 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_VALIDATION_STATUS(yaml_helper::validation_failed) << m_load_result->schema_validation();
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type = execve and proc.name in (blkid))");
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),
|
||||
"(evt.type = execve and proc.name in (blkid))");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, list_override_append_before_list_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, list_override_append_before_list_definition) {
|
||||
std::string rules_content = R"END(
|
||||
- list: dev_creation_binaries
|
||||
items: ["csi-provisioner", "csi-attacher"]
|
||||
override:
|
||||
@@ -520,9 +511,8 @@ TEST_F(test_falco_engine, list_override_append_before_list_definition)
|
||||
ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_LIST));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, list_override_replace_before_list_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, list_override_replace_before_list_definition) {
|
||||
std::string rules_content = R"END(
|
||||
- list: dev_creation_binaries
|
||||
items: ["csi-provisioner", "csi-attacher"]
|
||||
override:
|
||||
@@ -542,12 +532,12 @@ TEST_F(test_falco_engine, list_override_replace_before_list_definition)
|
||||
// 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_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type = execve and proc.name in (blkid))");
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),
|
||||
"(evt.type = execve and proc.name in (blkid))");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, list_append_before_list_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, list_append_before_list_definition) {
|
||||
std::string rules_content = R"END(
|
||||
- list: dev_creation_binaries
|
||||
items: ["csi-provisioner", "csi-attacher"]
|
||||
append: true
|
||||
@@ -569,9 +559,8 @@ TEST_F(test_falco_engine, list_append_before_list_definition)
|
||||
ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_LIST));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, list_override_append_after_list_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, list_override_append_after_list_definition) {
|
||||
std::string rules_content = R"END(
|
||||
- list: dev_creation_binaries
|
||||
items: [blkid]
|
||||
|
||||
@@ -590,12 +579,12 @@ TEST_F(test_falco_engine, list_override_append_after_list_definition)
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type = execve and proc.name in (blkid, csi-provisioner, csi-attacher))");
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),
|
||||
"(evt.type = execve and proc.name in (blkid, csi-provisioner, csi-attacher))");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, list_append_after_list_definition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, list_append_after_list_definition) {
|
||||
std::string rules_content = R"END(
|
||||
- list: dev_creation_binaries
|
||||
items: [blkid]
|
||||
|
||||
@@ -612,12 +601,12 @@ TEST_F(test_falco_engine, list_append_after_list_definition)
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type = execve and proc.name in (blkid, csi-provisioner, csi-attacher))");
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),
|
||||
"(evt.type = execve and proc.name in (blkid, csi-provisioner, csi-attacher))");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_override_without_field)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, rule_override_without_field) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: failing_rule
|
||||
desc: legit rule description
|
||||
condition: evt.type = close
|
||||
@@ -633,12 +622,12 @@ TEST_F(test_falco_engine, rule_override_without_field)
|
||||
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_TRUE(check_error_message("An append override for 'condition' was specified but 'condition' is not defined"));
|
||||
ASSERT_TRUE(check_error_message(
|
||||
"An append override for 'condition' was specified but 'condition' is not defined"));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_override_extra_field)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, rule_override_extra_field) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: failing_rule
|
||||
desc: legit rule description
|
||||
condition: evt.type = close
|
||||
@@ -659,9 +648,8 @@ TEST_F(test_falco_engine, rule_override_extra_field)
|
||||
ASSERT_TRUE(check_error_message("Unexpected key 'priority'"));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, missing_enabled_key_with_override)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, missing_enabled_key_with_override) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule description
|
||||
condition: evt.type = close
|
||||
@@ -684,9 +672,8 @@ TEST_F(test_falco_engine, missing_enabled_key_with_override)
|
||||
ASSERT_TRUE(check_error_message("'enabled' was specified but 'enabled' is not defined"));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_override_with_enabled)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, rule_override_with_enabled) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule description
|
||||
condition: evt.type = close
|
||||
@@ -711,9 +698,8 @@ TEST_F(test_falco_engine, rule_override_with_enabled)
|
||||
EXPECT_EQ(num_rules_for_ruleset(), 1);
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_override_exceptions_required_fields)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, rule_override_exceptions_required_fields) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule description
|
||||
condition: evt.type = close
|
||||
@@ -745,12 +731,12 @@ TEST_F(test_falco_engine, rule_override_exceptions_required_fields)
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_FALSE(has_warnings());
|
||||
ASSERT_TRUE(check_error_message("Item has no mapping for key 'fields'")) << m_load_result_json.dump();
|
||||
ASSERT_TRUE(check_error_message("Item has no mapping for key 'fields'"))
|
||||
<< m_load_result_json.dump();
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_not_enabled)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, rule_not_enabled) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: rule not enabled
|
||||
condition: evt.type = close
|
||||
@@ -765,9 +751,8 @@ TEST_F(test_falco_engine, rule_not_enabled)
|
||||
EXPECT_EQ(num_rules_for_ruleset(), 0);
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_enabled_warning)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, rule_enabled_warning) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule description
|
||||
condition: evt.type = close
|
||||
@@ -787,9 +772,8 @@ TEST_F(test_falco_engine, rule_enabled_warning)
|
||||
}
|
||||
|
||||
// todo!: Probably we shouldn't allow this syntax
|
||||
TEST_F(test_falco_engine, rule_enabled_is_ignored_by_append)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, rule_enabled_is_ignored_by_append) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule description
|
||||
condition: evt.type = close
|
||||
@@ -811,9 +795,8 @@ TEST_F(test_falco_engine, rule_enabled_is_ignored_by_append)
|
||||
}
|
||||
|
||||
// todo!: Probably we shouldn't allow this syntax
|
||||
TEST_F(test_falco_engine, rewrite_rule)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, rewrite_rule) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule description
|
||||
condition: evt.type = close
|
||||
@@ -835,12 +818,11 @@ TEST_F(test_falco_engine, rewrite_rule)
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
// 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");
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"), "proc.name = cat");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, required_engine_version_semver)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, required_engine_version_semver) {
|
||||
std::string rules_content = R"END(
|
||||
- required_engine_version: 0.26.0
|
||||
|
||||
- rule: test_rule
|
||||
@@ -857,9 +839,8 @@ TEST_F(test_falco_engine, required_engine_version_semver)
|
||||
ASSERT_FALSE(has_warnings());
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, required_engine_version_not_semver)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, required_engine_version_not_semver) {
|
||||
std::string rules_content = R"END(
|
||||
- required_engine_version: 26
|
||||
|
||||
- rule: test_rule
|
||||
@@ -876,9 +857,8 @@ TEST_F(test_falco_engine, required_engine_version_not_semver)
|
||||
ASSERT_FALSE(has_warnings());
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, required_engine_version_invalid)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, required_engine_version_invalid) {
|
||||
std::string rules_content = R"END(
|
||||
- required_engine_version: seven
|
||||
|
||||
- rule: test_rule
|
||||
@@ -896,9 +876,8 @@ TEST_F(test_falco_engine, required_engine_version_invalid)
|
||||
}
|
||||
|
||||
// checks for issue described in https://github.com/falcosecurity/falco/pull/3028
|
||||
TEST_F(test_falco_engine, list_value_with_escaping)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, list_value_with_escaping) {
|
||||
std::string rules_content = R"END(
|
||||
- list: my_list
|
||||
items: [non_escaped_val, "escaped val"]
|
||||
)END";
|
||||
@@ -906,7 +885,7 @@ TEST_F(test_falco_engine, list_value_with_escaping)
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_TRUE(m_load_result->successful());
|
||||
ASSERT_TRUE(m_load_result->has_warnings()); // a warning for the unused list
|
||||
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());
|
||||
@@ -919,13 +898,16 @@ TEST_F(test_falco_engine, list_value_with_escaping)
|
||||
|
||||
// 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");
|
||||
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");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, exceptions_condition)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, exceptions_condition) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule
|
||||
condition: proc.cmdline contains curl or proc.cmdline contains wget
|
||||
@@ -939,26 +921,27 @@ TEST_F(test_falco_engine, exceptions_condition)
|
||||
- [curl 127.0.0.1]
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),"((proc.cmdline contains curl or proc.cmdline contains wget) and not proc.cmdline contains \"curl 127.0.0.1\")");
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_EQ(get_compiled_rule_condition("test_rule"),
|
||||
"((proc.cmdline contains curl or proc.cmdline contains wget) and not proc.cmdline "
|
||||
"contains \"curl 127.0.0.1\")");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, macro_name_invalid)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, macro_name_invalid) {
|
||||
std::string rules_content = R"END(
|
||||
- macro: test-macro
|
||||
condition: evt.type = close
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_TRUE(check_warning_message("Macro has an invalid name. Macro names should match a regular expression"));
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_TRUE(check_warning_message(
|
||||
"Macro has an invalid name. Macro names should match a regular expression"));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, list_name_invalid)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, list_name_invalid) {
|
||||
std::string rules_content = R"END(
|
||||
- list: test list
|
||||
items: [open, openat, openat2]
|
||||
|
||||
@@ -971,16 +954,16 @@ TEST_F(test_falco_engine, list_name_invalid)
|
||||
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_TRUE(check_warning_message("List has an invalid name. List names should match a regular expression"));
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_TRUE(check_warning_message(
|
||||
"List has an invalid name. List names should match a regular expression"));
|
||||
}
|
||||
|
||||
// The appended exception has a purposely miswritten field (value),
|
||||
// simulating a typo or an incorrect usage.
|
||||
TEST_F(test_falco_engine, exceptions_append_no_values)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, exceptions_append_no_values) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule
|
||||
condition: proc.cmdline contains curl
|
||||
@@ -1000,14 +983,13 @@ TEST_F(test_falco_engine, exceptions_append_no_values)
|
||||
append: true
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_failed) << m_load_result->schema_validation();
|
||||
ASSERT_TRUE(check_warning_message("Overriding/appending exception with no values"));
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_failed) << m_load_result->schema_validation();
|
||||
ASSERT_TRUE(check_warning_message("Overriding/appending exception with no values"));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, exceptions_override_no_values)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, exceptions_override_no_values) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule
|
||||
condition: proc.cmdline contains curl
|
||||
@@ -1028,14 +1010,13 @@ TEST_F(test_falco_engine, exceptions_override_no_values)
|
||||
exceptions: append
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_failed) << m_load_result->schema_validation();
|
||||
ASSERT_TRUE(check_warning_message("Overriding/appending exception with no values"));
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_failed) << m_load_result->schema_validation();
|
||||
ASSERT_TRUE(check_warning_message("Overriding/appending exception with no values"));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, exceptions_names_not_unique)
|
||||
{
|
||||
std::string rules_content = R"END(
|
||||
TEST_F(test_falco_engine, exceptions_names_not_unique) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule
|
||||
condition: proc.cmdline contains curl
|
||||
@@ -1054,9 +1035,9 @@ TEST_F(test_falco_engine, exceptions_names_not_unique)
|
||||
- [curl 127.0.0.1]
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_TRUE(check_warning_message("Multiple definitions of exception"));
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_TRUE(check_warning_message("Multiple definitions of exception"));
|
||||
}
|
||||
|
||||
static std::string s_exception_values_rule_base = R"END(
|
||||
@@ -1067,9 +1048,8 @@ static std::string s_exception_values_rule_base = R"END(
|
||||
priority: INFO
|
||||
)END";
|
||||
|
||||
TEST_F(test_falco_engine, exceptions_values_rhs_field_ambiguous)
|
||||
{
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
TEST_F(test_falco_engine, exceptions_values_rhs_field_ambiguous) {
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
exceptions:
|
||||
- name: test_exception
|
||||
fields: [proc.name]
|
||||
@@ -1078,15 +1058,16 @@ TEST_F(test_falco_engine, exceptions_values_rhs_field_ambiguous)
|
||||
- [proc.pname]
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not proc.name = proc.pname)");
|
||||
EXPECT_TRUE(check_warning_message("'proc.pname' may be a valid field misused as a const string value"));
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"),
|
||||
"(evt.type = open and not proc.name = proc.pname)");
|
||||
EXPECT_TRUE(check_warning_message(
|
||||
"'proc.pname' may be a valid field misused as a const string value"));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, exceptions_values_rhs_field_ambiguous_quoted)
|
||||
{
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
TEST_F(test_falco_engine, exceptions_values_rhs_field_ambiguous_quoted) {
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
exceptions:
|
||||
- name: test_exception
|
||||
fields: [proc.name]
|
||||
@@ -1095,15 +1076,16 @@ TEST_F(test_falco_engine, exceptions_values_rhs_field_ambiguous_quoted)
|
||||
- ["proc.pname"]
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not proc.name = proc.pname)");
|
||||
EXPECT_TRUE(check_warning_message("'proc.pname' may be a valid field misused as a const string value"));
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"),
|
||||
"(evt.type = open and not proc.name = proc.pname)");
|
||||
EXPECT_TRUE(check_warning_message(
|
||||
"'proc.pname' may be a valid field misused as a const string value"));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, exceptions_values_rhs_field_ambiguous_space_quoted)
|
||||
{
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
TEST_F(test_falco_engine, exceptions_values_rhs_field_ambiguous_space_quoted) {
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
exceptions:
|
||||
- name: test_exception
|
||||
fields: [proc.name]
|
||||
@@ -1112,15 +1094,16 @@ TEST_F(test_falco_engine, exceptions_values_rhs_field_ambiguous_space_quoted)
|
||||
- ["proc.pname "]
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not proc.name = \"proc.pname \")");
|
||||
EXPECT_TRUE(check_warning_message("'proc.pname ' may be a valid field misused as a const string value"));
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"),
|
||||
"(evt.type = open and not proc.name = \"proc.pname \")");
|
||||
EXPECT_TRUE(check_warning_message(
|
||||
"'proc.pname ' may be a valid field misused as a const string value"));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, exceptions_values_rhs_transformer)
|
||||
{
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
TEST_F(test_falco_engine, exceptions_values_rhs_transformer) {
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
exceptions:
|
||||
- name: test_exception
|
||||
fields: [proc.name]
|
||||
@@ -1129,14 +1112,14 @@ TEST_F(test_falco_engine, exceptions_values_rhs_transformer)
|
||||
- [toupper(proc.pname)]
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not proc.name = toupper(proc.pname))");
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"),
|
||||
"(evt.type = open and not proc.name = toupper(proc.pname))");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, exceptions_values_transformer_value_quoted)
|
||||
{
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
TEST_F(test_falco_engine, exceptions_values_transformer_value_quoted) {
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
exceptions:
|
||||
- name: test_exception
|
||||
fields: [proc.name]
|
||||
@@ -1145,14 +1128,14 @@ TEST_F(test_falco_engine, exceptions_values_transformer_value_quoted)
|
||||
- ["toupper(proc.pname)"]
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not proc.name = toupper(proc.pname))");
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"),
|
||||
"(evt.type = open and not proc.name = toupper(proc.pname))");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, exceptions_values_transformer_space)
|
||||
{
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
TEST_F(test_falco_engine, exceptions_values_transformer_space) {
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
exceptions:
|
||||
- name: test_exception
|
||||
fields: [proc.name]
|
||||
@@ -1161,15 +1144,17 @@ TEST_F(test_falco_engine, exceptions_values_transformer_space)
|
||||
- [toupper( proc.pname)]
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not proc.name = \"toupper( proc.pname)\")");
|
||||
EXPECT_TRUE(check_warning_message("'toupper( proc.pname)' may be a valid field transformer misused as a const string value"));
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"),
|
||||
"(evt.type = open and not proc.name = \"toupper( proc.pname)\")");
|
||||
EXPECT_TRUE(
|
||||
check_warning_message("'toupper( proc.pname)' may be a valid field transformer misused "
|
||||
"as a const string value"));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, exceptions_values_transformer_space_quoted)
|
||||
{
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
TEST_F(test_falco_engine, exceptions_values_transformer_space_quoted) {
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
exceptions:
|
||||
- name: test_exception
|
||||
fields: [proc.name]
|
||||
@@ -1178,15 +1163,17 @@ TEST_F(test_falco_engine, exceptions_values_transformer_space_quoted)
|
||||
- ["toupper( proc.pname)"]
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not proc.name = \"toupper( proc.pname)\")");
|
||||
EXPECT_TRUE(check_warning_message("'toupper( proc.pname)' may be a valid field transformer misused as a const string value"));
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"),
|
||||
"(evt.type = open and not proc.name = \"toupper( proc.pname)\")");
|
||||
EXPECT_TRUE(
|
||||
check_warning_message("'toupper( proc.pname)' may be a valid field transformer misused "
|
||||
"as a const string value"));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, exceptions_fields_transformer)
|
||||
{
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
TEST_F(test_falco_engine, exceptions_fields_transformer) {
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
exceptions:
|
||||
- name: test_exception
|
||||
fields: [tolower(proc.name)]
|
||||
@@ -1195,15 +1182,15 @@ TEST_F(test_falco_engine, exceptions_fields_transformer)
|
||||
- [test]
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
EXPECT_FALSE(has_warnings());
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not tolower(proc.name) = test)");
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
EXPECT_FALSE(has_warnings());
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"),
|
||||
"(evt.type = open and not tolower(proc.name) = test)");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, exceptions_fields_transformer_quoted)
|
||||
{
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
TEST_F(test_falco_engine, exceptions_fields_transformer_quoted) {
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
exceptions:
|
||||
- name: test_exception
|
||||
fields: ["tolower(proc.name)"]
|
||||
@@ -1212,15 +1199,15 @@ TEST_F(test_falco_engine, exceptions_fields_transformer_quoted)
|
||||
- [test]
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_FALSE(has_warnings());
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not tolower(proc.name) = test)");
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_FALSE(has_warnings());
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"),
|
||||
"(evt.type = open and not tolower(proc.name) = test)");
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, exceptions_fields_transformer_space_quoted)
|
||||
{
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
TEST_F(test_falco_engine, exceptions_fields_transformer_space_quoted) {
|
||||
auto rules_content = s_exception_values_rule_base + R"END(
|
||||
exceptions:
|
||||
- name: test_exception
|
||||
fields: ["tolower( proc.name)"]
|
||||
@@ -1229,8 +1216,9 @@ TEST_F(test_falco_engine, exceptions_fields_transformer_space_quoted)
|
||||
- [test]
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_FALSE(has_warnings());
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not tolower(proc.name) = test)");
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
ASSERT_FALSE(has_warnings());
|
||||
EXPECT_EQ(get_compiled_rule_condition("test_rule"),
|
||||
"(evt.type = open and not tolower(proc.name) = test)");
|
||||
}
|
||||
|
||||
@@ -23,32 +23,28 @@ limitations under the License.
|
||||
#define RULESET_2 2
|
||||
|
||||
/* Helpers methods */
|
||||
static std::shared_ptr<sinsp_filter_factory> create_factory(sinsp* inspector, filter_check_list& list)
|
||||
{
|
||||
static std::shared_ptr<sinsp_filter_factory> create_factory(sinsp* inspector,
|
||||
filter_check_list& list) {
|
||||
return std::make_shared<sinsp_filter_factory>(inspector, list);
|
||||
}
|
||||
|
||||
static std::shared_ptr<filter_ruleset> create_ruleset(std::shared_ptr<sinsp_filter_factory> f)
|
||||
{
|
||||
static std::shared_ptr<filter_ruleset> create_ruleset(std::shared_ptr<sinsp_filter_factory> f) {
|
||||
return std::make_shared<evttype_index_ruleset>(f);
|
||||
}
|
||||
|
||||
static std::shared_ptr<libsinsp::filter::ast::expr> create_ast(std::shared_ptr<sinsp_filter_factory> f)
|
||||
{
|
||||
static std::shared_ptr<libsinsp::filter::ast::expr> create_ast(
|
||||
std::shared_ptr<sinsp_filter_factory> f) {
|
||||
libsinsp::filter::parser parser("evt.type=open");
|
||||
return parser.parse();
|
||||
}
|
||||
|
||||
static std::shared_ptr<sinsp_filter> create_filter(
|
||||
std::shared_ptr<sinsp_filter_factory> f,
|
||||
libsinsp::filter::ast::expr* ast)
|
||||
{
|
||||
static std::shared_ptr<sinsp_filter> create_filter(std::shared_ptr<sinsp_filter_factory> f,
|
||||
libsinsp::filter::ast::expr* ast) {
|
||||
sinsp_filter_compiler compiler(f, ast);
|
||||
return std::shared_ptr<sinsp_filter>(compiler.compile());
|
||||
}
|
||||
|
||||
TEST(Ruleset, enable_disable_rules_using_names)
|
||||
{
|
||||
TEST(Ruleset, enable_disable_rules_using_names) {
|
||||
sinsp inspector;
|
||||
|
||||
sinsp_filter_check_list filterlist;
|
||||
@@ -140,8 +136,7 @@ TEST(Ruleset, enable_disable_rules_using_names)
|
||||
ASSERT_EQ(r->enabled_count(RULESET_2), 0);
|
||||
}
|
||||
|
||||
TEST(Ruleset, enable_disable_rules_using_tags)
|
||||
{
|
||||
TEST(Ruleset, enable_disable_rules_using_tags) {
|
||||
sinsp inspector;
|
||||
|
||||
sinsp_filter_check_list filterlist;
|
||||
|
||||
@@ -19,5 +19,17 @@ limitations under the License.
|
||||
#include <falco/app/state.h>
|
||||
#include <falco/app/actions/actions.h>
|
||||
|
||||
#define EXPECT_ACTION_OK(r) { auto result = r; EXPECT_TRUE(result.success); EXPECT_TRUE(result.proceed); EXPECT_EQ(result.errstr, ""); }
|
||||
#define EXPECT_ACTION_FAIL(r) { auto result = r; EXPECT_FALSE(result.success); EXPECT_FALSE(result.proceed); EXPECT_NE(result.errstr, ""); }
|
||||
#define EXPECT_ACTION_OK(r) \
|
||||
{ \
|
||||
auto result = r; \
|
||||
EXPECT_TRUE(result.success); \
|
||||
EXPECT_TRUE(result.proceed); \
|
||||
EXPECT_EQ(result.errstr, ""); \
|
||||
}
|
||||
#define EXPECT_ACTION_FAIL(r) \
|
||||
{ \
|
||||
auto result = r; \
|
||||
EXPECT_FALSE(result.success); \
|
||||
EXPECT_FALSE(result.proceed); \
|
||||
EXPECT_NE(result.errstr, ""); \
|
||||
}
|
||||
|
||||
@@ -23,23 +23,21 @@ limitations under the License.
|
||||
#include <falco/app/app.h>
|
||||
#include "app_action_helpers.h"
|
||||
|
||||
#define ASSERT_NAMES_EQ(a, b) { \
|
||||
EXPECT_EQ(_order(a).size(), _order(b).size()); \
|
||||
ASSERT_EQ(_order(a), _order(b)); \
|
||||
}
|
||||
#define ASSERT_NAMES_EQ(a, b) \
|
||||
{ \
|
||||
EXPECT_EQ(_order(a).size(), _order(b).size()); \
|
||||
ASSERT_EQ(_order(a), _order(b)); \
|
||||
}
|
||||
|
||||
#define ASSERT_NAMES_CONTAIN(a, b) { \
|
||||
ASSERT_NAMES_EQ(unordered_set_intersection(a, b), b); \
|
||||
}
|
||||
#define ASSERT_NAMES_CONTAIN(a, b) \
|
||||
{ ASSERT_NAMES_EQ(unordered_set_intersection(a, b), b); }
|
||||
|
||||
#define ASSERT_NAMES_NOCONTAIN(a, b) { \
|
||||
ASSERT_NAMES_EQ(unordered_set_intersection(a, b), strset_t({})); \
|
||||
}
|
||||
#define ASSERT_NAMES_NOCONTAIN(a, b) \
|
||||
{ ASSERT_NAMES_EQ(unordered_set_intersection(a, b), strset_t({})); }
|
||||
|
||||
using strset_t = std::unordered_set<std::string>;
|
||||
|
||||
static std::set<std::string> _order(const strset_t& s)
|
||||
{
|
||||
static std::set<std::string> _order(const strset_t& s) {
|
||||
return std::set<std::string>(s.begin(), s.end());
|
||||
}
|
||||
|
||||
@@ -48,38 +46,31 @@ static std::string s_sample_ruleset = "sample-ruleset";
|
||||
static std::string s_sample_source = falco_common::syscall_source;
|
||||
|
||||
static strset_t s_sample_filters = {
|
||||
"evt.type=connect or evt.type=accept or evt.type=accept4 or evt.type=umount2",
|
||||
"evt.type in (open, ptrace, mmap, execve, read, container)",
|
||||
"evt.type in (open, execve, mprotect) and not evt.type=mprotect"};
|
||||
"evt.type=connect or evt.type=accept or evt.type=accept4 or evt.type=umount2",
|
||||
"evt.type in (open, ptrace, mmap, execve, read, container)",
|
||||
"evt.type in (open, execve, mprotect) and not evt.type=mprotect"};
|
||||
|
||||
static strset_t s_sample_generic_filters = {
|
||||
"evt.type=syncfs or evt.type=fanotify_init"};
|
||||
static strset_t s_sample_generic_filters = {"evt.type=syncfs or evt.type=fanotify_init"};
|
||||
|
||||
static strset_t s_sample_nonsyscall_filters = {
|
||||
"evt.type in (procexit, switch, pluginevent, container)"};
|
||||
"evt.type in (procexit, switch, pluginevent, container)"};
|
||||
|
||||
|
||||
static std::string ruleset_from_filters(const strset_t& filters)
|
||||
{
|
||||
static std::string ruleset_from_filters(const strset_t& filters) {
|
||||
std::string dummy_rules;
|
||||
falco::load_result::rules_contents_t content = {{"dummy_rules.yaml", dummy_rules}};
|
||||
int n_rules = 0;
|
||||
for (const auto& f : filters)
|
||||
{
|
||||
for(const auto& f : filters) {
|
||||
n_rules++;
|
||||
dummy_rules +=
|
||||
"- rule: Dummy Rule " + std::to_string(n_rules) + "\n"
|
||||
+ " output: Dummy Output " + std::to_string(n_rules) + "\n"
|
||||
+ " condition: " + f + "\n"
|
||||
+ " desc: Dummy Desc " + std::to_string(n_rules) + "\n"
|
||||
+ " priority: CRITICAL\n\n";
|
||||
dummy_rules += "- rule: Dummy Rule " + std::to_string(n_rules) + "\n" +
|
||||
" output: Dummy Output " + std::to_string(n_rules) + "\n" +
|
||||
" condition: " + f + "\n" + " desc: Dummy Desc " +
|
||||
std::to_string(n_rules) + "\n" + " priority: CRITICAL\n\n";
|
||||
}
|
||||
|
||||
return dummy_rules;
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, engine_codes_syscalls_set)
|
||||
{
|
||||
TEST_F(test_falco_engine, engine_codes_syscalls_set) {
|
||||
load_rules(ruleset_from_filters(s_sample_filters), "dummy_ruleset.yaml");
|
||||
|
||||
auto enabled_count = m_engine->num_rules_for_ruleset(s_sample_ruleset);
|
||||
@@ -88,20 +79,37 @@ TEST_F(test_falco_engine, engine_codes_syscalls_set)
|
||||
// test if event code names were extracted from each rule in test ruleset.
|
||||
auto rules_event_set = m_engine->event_codes_for_ruleset(s_sample_source);
|
||||
auto rules_event_names = libsinsp::events::event_set_to_names(rules_event_set);
|
||||
ASSERT_NAMES_EQ(rules_event_names, strset_t({
|
||||
"connect", "accept", "accept4", "umount2", "open", "ptrace", "mmap", "execve", "read", "container", "asyncevent"}));
|
||||
ASSERT_NAMES_EQ(rules_event_names,
|
||||
strset_t({"connect",
|
||||
"accept",
|
||||
"accept4",
|
||||
"umount2",
|
||||
"open",
|
||||
"ptrace",
|
||||
"mmap",
|
||||
"execve",
|
||||
"read",
|
||||
"container",
|
||||
"asyncevent"}));
|
||||
|
||||
// test if sc code names were extracted from each rule in test ruleset.
|
||||
// note, this is not supposed to contain "container", as that's an event
|
||||
// not mapped through the ppm_sc_code enumerative.
|
||||
auto rules_sc_set = m_engine->sc_codes_for_ruleset(s_sample_source);
|
||||
auto rules_sc_names = libsinsp::events::sc_set_to_event_names(rules_sc_set);
|
||||
ASSERT_NAMES_EQ(rules_sc_names, strset_t({
|
||||
"connect", "accept", "accept4", "umount2", "open", "ptrace", "mmap", "execve", "read"}));
|
||||
ASSERT_NAMES_EQ(rules_sc_names,
|
||||
strset_t({"connect",
|
||||
"accept",
|
||||
"accept4",
|
||||
"umount2",
|
||||
"open",
|
||||
"ptrace",
|
||||
"mmap",
|
||||
"execve",
|
||||
"read"}));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, preconditions_postconditions)
|
||||
{
|
||||
TEST_F(test_falco_engine, preconditions_postconditions) {
|
||||
load_rules(ruleset_from_filters(s_sample_filters), "dummy_ruleset.yaml");
|
||||
|
||||
falco::app::state s1;
|
||||
@@ -131,8 +139,7 @@ TEST_F(test_falco_engine, preconditions_postconditions)
|
||||
ASSERT_EQ(prev_selection_size, s1.selected_sc_set.size());
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, engine_codes_nonsyscalls_set)
|
||||
{
|
||||
TEST_F(test_falco_engine, engine_codes_nonsyscalls_set) {
|
||||
auto filters = s_sample_filters;
|
||||
filters.insert(s_sample_generic_filters.begin(), s_sample_generic_filters.end());
|
||||
filters.insert(s_sample_nonsyscall_filters.begin(), s_sample_nonsyscall_filters.end());
|
||||
@@ -149,22 +156,44 @@ TEST_F(test_falco_engine, engine_codes_nonsyscalls_set)
|
||||
// PPME_GENERIC_E will cause all names of generic events to be added!
|
||||
// This is a good example of information loss from ppm_event_code <-> ppm_sc_code.
|
||||
auto generic_names = libsinsp::events::event_set_to_names({ppm_event_code::PPME_GENERIC_E});
|
||||
auto expected_names = strset_t({
|
||||
"connect", "accept", "accept4", "umount2", "open", "ptrace", "mmap", "execve", "read", "container", // ruleset
|
||||
"procexit", "switch", "pluginevent", "asyncevent"}); // from non-syscall event filters
|
||||
auto expected_names = strset_t({"connect",
|
||||
"accept",
|
||||
"accept4",
|
||||
"umount2",
|
||||
"open",
|
||||
"ptrace",
|
||||
"mmap",
|
||||
"execve",
|
||||
"read",
|
||||
"container", // ruleset
|
||||
"procexit",
|
||||
"switch",
|
||||
"pluginevent",
|
||||
"asyncevent"}); // from non-syscall event filters
|
||||
expected_names.insert(generic_names.begin(), generic_names.end());
|
||||
ASSERT_NAMES_EQ(rules_event_names, expected_names);
|
||||
|
||||
auto rules_sc_set = m_engine->sc_codes_for_ruleset(s_sample_source);
|
||||
auto rules_sc_names = libsinsp::events::sc_set_to_event_names(rules_sc_set);
|
||||
ASSERT_NAMES_EQ(rules_sc_names, strset_t({
|
||||
"connect", "accept", "accept4", "umount2", "open", "ptrace", "mmap", "execve", "read",
|
||||
"procexit", "switch", "syncfs", "fanotify_init", // from generic event filters
|
||||
}));
|
||||
ASSERT_NAMES_EQ(rules_sc_names,
|
||||
strset_t({
|
||||
"connect",
|
||||
"accept",
|
||||
"accept4",
|
||||
"umount2",
|
||||
"open",
|
||||
"ptrace",
|
||||
"mmap",
|
||||
"execve",
|
||||
"read",
|
||||
"procexit",
|
||||
"switch",
|
||||
"syncfs",
|
||||
"fanotify_init", // from generic event filters
|
||||
}));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, selection_not_allevents)
|
||||
{
|
||||
TEST_F(test_falco_engine, selection_not_allevents) {
|
||||
load_rules(ruleset_from_filters(s_sample_filters), "dummy_ruleset.yaml");
|
||||
|
||||
falco::app::state s2;
|
||||
@@ -184,10 +213,22 @@ TEST_F(test_falco_engine, selection_not_allevents)
|
||||
ASSERT_GT(s2.selected_sc_set.size(), 1);
|
||||
auto selected_sc_names = libsinsp::events::sc_set_to_event_names(s2.selected_sc_set);
|
||||
auto expected_sc_names = strset_t({
|
||||
// note: we expect the "read" syscall to have been erased
|
||||
"connect", "accept", "accept4", "umount2", "open", "ptrace", "mmap", "execve", // from ruleset
|
||||
"clone", "clone3", "fork", "vfork", // from sinsp state set (spawned_process)
|
||||
"socket", "bind", "close" // from sinsp state set (network, files)
|
||||
// note: we expect the "read" syscall to have been erased
|
||||
"connect",
|
||||
"accept",
|
||||
"accept4",
|
||||
"umount2",
|
||||
"open",
|
||||
"ptrace",
|
||||
"mmap",
|
||||
"execve", // from ruleset
|
||||
"clone",
|
||||
"clone3",
|
||||
"fork",
|
||||
"vfork", // from sinsp state set (spawned_process)
|
||||
"socket",
|
||||
"bind",
|
||||
"close" // from sinsp state set (network, files)
|
||||
});
|
||||
ASSERT_NAMES_CONTAIN(selected_sc_names, expected_sc_names);
|
||||
|
||||
@@ -199,8 +240,7 @@ TEST_F(test_falco_engine, selection_not_allevents)
|
||||
// check that final selected set is exactly sinsp state + ruleset
|
||||
auto rule_set = s2.engine->sc_codes_for_ruleset(s_sample_source, s_sample_ruleset);
|
||||
auto state_set = libsinsp::events::sinsp_state_sc_set();
|
||||
for (const auto &erased : ignored_set)
|
||||
{
|
||||
for(const auto& erased : ignored_set) {
|
||||
rule_set.remove(erased);
|
||||
state_set.remove(erased);
|
||||
}
|
||||
@@ -210,8 +250,7 @@ TEST_F(test_falco_engine, selection_not_allevents)
|
||||
ASSERT_EQ(s2.selected_sc_set, union_set);
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, selection_allevents)
|
||||
{
|
||||
TEST_F(test_falco_engine, selection_allevents) {
|
||||
load_rules(ruleset_from_filters(s_sample_filters), "dummy_ruleset.yaml");
|
||||
|
||||
falco::app::state s3;
|
||||
@@ -229,10 +268,23 @@ TEST_F(test_falco_engine, selection_allevents)
|
||||
ASSERT_GT(s3.selected_sc_set.size(), 1);
|
||||
auto selected_sc_names = libsinsp::events::sc_set_to_event_names(s3.selected_sc_set);
|
||||
auto expected_sc_names = strset_t({
|
||||
// note: we expect the "read" syscall to not be erased
|
||||
"connect", "accept", "accept4", "umount2", "open", "ptrace", "mmap", "execve", "read", // from ruleset
|
||||
"clone", "clone3", "fork", "vfork", // from sinsp state set (spawned_process)
|
||||
"socket", "bind", "close" // from sinsp state set (network, files)
|
||||
// note: we expect the "read" syscall to not be erased
|
||||
"connect",
|
||||
"accept",
|
||||
"accept4",
|
||||
"umount2",
|
||||
"open",
|
||||
"ptrace",
|
||||
"mmap",
|
||||
"execve",
|
||||
"read", // from ruleset
|
||||
"clone",
|
||||
"clone3",
|
||||
"fork",
|
||||
"vfork", // from sinsp state set (spawned_process)
|
||||
"socket",
|
||||
"bind",
|
||||
"close" // from sinsp state set (network, files)
|
||||
});
|
||||
ASSERT_NAMES_CONTAIN(selected_sc_names, expected_sc_names);
|
||||
|
||||
@@ -245,8 +297,7 @@ TEST_F(test_falco_engine, selection_allevents)
|
||||
ASSERT_EQ(s3.selected_sc_set, union_set);
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, selection_generic_evts)
|
||||
{
|
||||
TEST_F(test_falco_engine, selection_generic_evts) {
|
||||
falco::app::state s4;
|
||||
// run app action with fake engine and without the `-A` option
|
||||
s4.options.all_events = false;
|
||||
@@ -262,14 +313,28 @@ TEST_F(test_falco_engine, selection_generic_evts)
|
||||
ASSERT_GT(s4.selected_sc_set.size(), 1);
|
||||
auto selected_sc_names = libsinsp::events::sc_set_to_event_names(s4.selected_sc_set);
|
||||
auto expected_sc_names = strset_t({
|
||||
// note: we expect the "read" syscall to not be erased
|
||||
"connect", "accept", "accept4", "umount2", "open", "ptrace", "mmap", "execve", // from ruleset
|
||||
"syncfs", "fanotify_init", // from ruleset (generic events)
|
||||
"clone", "clone3", "fork", "vfork", // from sinsp state set (spawned_process)
|
||||
"socket", "bind", "close" // from sinsp state set (network, files)
|
||||
// note: we expect the "read" syscall to not be erased
|
||||
"connect",
|
||||
"accept",
|
||||
"accept4",
|
||||
"umount2",
|
||||
"open",
|
||||
"ptrace",
|
||||
"mmap",
|
||||
"execve", // from ruleset
|
||||
"syncfs",
|
||||
"fanotify_init", // from ruleset (generic events)
|
||||
"clone",
|
||||
"clone3",
|
||||
"fork",
|
||||
"vfork", // from sinsp state set (spawned_process)
|
||||
"socket",
|
||||
"bind",
|
||||
"close" // from sinsp state set (network, files)
|
||||
});
|
||||
ASSERT_NAMES_CONTAIN(selected_sc_names, expected_sc_names);
|
||||
auto unexpected_sc_names = libsinsp::events::sc_set_to_event_names(falco::app::ignored_sc_set());
|
||||
auto unexpected_sc_names =
|
||||
libsinsp::events::sc_set_to_event_names(falco::app::ignored_sc_set());
|
||||
ASSERT_NAMES_NOCONTAIN(selected_sc_names, unexpected_sc_names);
|
||||
}
|
||||
|
||||
@@ -278,8 +343,7 @@ TEST_F(test_falco_engine, selection_generic_evts)
|
||||
// (either default or custom positive set)
|
||||
// - events in the custom negative set are removed from the selected set
|
||||
// - if `-A` is not set, events from the IO set are removed from the selected set
|
||||
TEST_F(test_falco_engine, selection_custom_base_set)
|
||||
{
|
||||
TEST_F(test_falco_engine, selection_custom_base_set) {
|
||||
load_rules(ruleset_from_filters(s_sample_filters), "dummy_ruleset.yaml");
|
||||
|
||||
falco::app::state s5;
|
||||
@@ -295,17 +359,24 @@ TEST_F(test_falco_engine, selection_custom_base_set)
|
||||
ASSERT_TRUE(result.success);
|
||||
ASSERT_EQ(result.errstr, "");
|
||||
auto selected_sc_names = libsinsp::events::sc_set_to_event_names(s5.selected_sc_set);
|
||||
auto expected_sc_names = strset_t({
|
||||
// note: `syncfs` has been added due to the custom base set, and `accept`
|
||||
// has been remove due to the negative base set.
|
||||
// note: `read` is not ignored due to the "-A" option being set.
|
||||
// note: `accept` is not included even though it is matched by the rules,
|
||||
// which means that the custom negation base set has precedence over the
|
||||
// final selection set as a whole
|
||||
// note(jasondellaluce): "accept4" should be added, however old versions
|
||||
// of the ACCEPT4 event are actually named "accept" in the event table
|
||||
"connect", "umount2", "open", "ptrace", "mmap", "execve", "read", "syncfs", "procexit"
|
||||
});
|
||||
auto expected_sc_names =
|
||||
strset_t({// note: `syncfs` has been added due to the custom base set, and `accept`
|
||||
// has been remove due to the negative base set.
|
||||
// note: `read` is not ignored due to the "-A" option being set.
|
||||
// note: `accept` is not included even though it is matched by the rules,
|
||||
// which means that the custom negation base set has precedence over the
|
||||
// final selection set as a whole
|
||||
// note(jasondellaluce): "accept4" should be added, however old versions
|
||||
// of the ACCEPT4 event are actually named "accept" in the event table
|
||||
"connect",
|
||||
"umount2",
|
||||
"open",
|
||||
"ptrace",
|
||||
"mmap",
|
||||
"execve",
|
||||
"read",
|
||||
"syncfs",
|
||||
"procexit"});
|
||||
ASSERT_NAMES_EQ(selected_sc_names, expected_sc_names);
|
||||
|
||||
// non-empty custom base set (both positive and negative with collision)
|
||||
@@ -325,10 +396,18 @@ TEST_F(test_falco_engine, selection_custom_base_set)
|
||||
ASSERT_TRUE(result.success);
|
||||
ASSERT_EQ(result.errstr, "");
|
||||
selected_sc_names = libsinsp::events::sc_set_to_event_names(s5.selected_sc_set);
|
||||
expected_sc_names = strset_t({
|
||||
// note: accept is not negated anymore
|
||||
"connect", "accept", "accept4", "umount2", "open", "ptrace", "mmap", "execve", "read", "syncfs", "procexit"
|
||||
});
|
||||
expected_sc_names = strset_t({// note: accept is not negated anymore
|
||||
"connect",
|
||||
"accept",
|
||||
"accept4",
|
||||
"umount2",
|
||||
"open",
|
||||
"ptrace",
|
||||
"mmap",
|
||||
"execve",
|
||||
"read",
|
||||
"syncfs",
|
||||
"procexit"});
|
||||
ASSERT_NAMES_EQ(selected_sc_names, expected_sc_names);
|
||||
|
||||
// non-empty custom base set (only negative)
|
||||
@@ -338,8 +417,8 @@ TEST_F(test_falco_engine, selection_custom_base_set)
|
||||
ASSERT_EQ(result.errstr, "");
|
||||
selected_sc_names = libsinsp::events::sc_set_to_event_names(s5.selected_sc_set);
|
||||
expected_sc_names = unordered_set_union(
|
||||
libsinsp::events::sc_set_to_event_names(default_base_set),
|
||||
strset_t({ "connect", "umount2", "open", "ptrace", "mmap", "execve", "read"}));
|
||||
libsinsp::events::sc_set_to_event_names(default_base_set),
|
||||
strset_t({"connect", "umount2", "open", "ptrace", "mmap", "execve", "read"}));
|
||||
expected_sc_names.erase("accept");
|
||||
// note(jasondellaluce): "accept4" should be included, however old versions
|
||||
// of the ACCEPT4 event are actually named "accept" in the event table
|
||||
@@ -353,18 +432,24 @@ TEST_F(test_falco_engine, selection_custom_base_set)
|
||||
ASSERT_TRUE(result.success);
|
||||
ASSERT_EQ(result.errstr, "");
|
||||
selected_sc_names = libsinsp::events::sc_set_to_event_names(s5.selected_sc_set);
|
||||
expected_sc_names = strset_t({
|
||||
// note: read is both part of the custom base set and the rules set,
|
||||
// but we expect the unset -A option to take precedence
|
||||
"connect", "accept", "accept4", "umount2", "open", "ptrace", "mmap", "execve", "procexit"
|
||||
});
|
||||
expected_sc_names = strset_t({// note: read is both part of the custom base set and the rules
|
||||
// set, but we expect the unset -A option to take precedence
|
||||
"connect",
|
||||
"accept",
|
||||
"accept4",
|
||||
"umount2",
|
||||
"open",
|
||||
"ptrace",
|
||||
"mmap",
|
||||
"execve",
|
||||
"procexit"});
|
||||
ASSERT_NAMES_EQ(selected_sc_names, expected_sc_names);
|
||||
auto unexpected_sc_names = libsinsp::events::sc_set_to_event_names(falco::app::ignored_sc_set());
|
||||
auto unexpected_sc_names =
|
||||
libsinsp::events::sc_set_to_event_names(falco::app::ignored_sc_set());
|
||||
ASSERT_NAMES_NOCONTAIN(selected_sc_names, unexpected_sc_names);
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, selection_custom_base_set_repair)
|
||||
{
|
||||
TEST_F(test_falco_engine, selection_custom_base_set_repair) {
|
||||
load_rules(ruleset_from_filters(s_sample_filters), "dummy_ruleset.yaml");
|
||||
|
||||
falco::app::state s6;
|
||||
@@ -383,18 +468,29 @@ TEST_F(test_falco_engine, selection_custom_base_set_repair)
|
||||
ASSERT_TRUE(result.success);
|
||||
ASSERT_EQ(result.errstr, "");
|
||||
auto selected_sc_names = libsinsp::events::sc_set_to_event_names(s6.selected_sc_set);
|
||||
auto expected_sc_names = strset_t({
|
||||
// note: expecting syscalls from mock rules and `sinsp_repair_state_sc_set` enforced syscalls
|
||||
"connect", "accept", "accept4", "umount2", "open", "ptrace", "mmap", "execve", "procexit", \
|
||||
"bind", "socket", "clone3", "close", "setuid"
|
||||
});
|
||||
auto expected_sc_names = strset_t({// note: expecting syscalls from mock rules and
|
||||
// `sinsp_repair_state_sc_set` enforced syscalls
|
||||
"connect",
|
||||
"accept",
|
||||
"accept4",
|
||||
"umount2",
|
||||
"open",
|
||||
"ptrace",
|
||||
"mmap",
|
||||
"execve",
|
||||
"procexit",
|
||||
"bind",
|
||||
"socket",
|
||||
"clone3",
|
||||
"close",
|
||||
"setuid"});
|
||||
ASSERT_NAMES_CONTAIN(selected_sc_names, expected_sc_names);
|
||||
auto unexpected_sc_names = libsinsp::events::sc_set_to_event_names(falco::app::ignored_sc_set());
|
||||
auto unexpected_sc_names =
|
||||
libsinsp::events::sc_set_to_event_names(falco::app::ignored_sc_set());
|
||||
ASSERT_NAMES_NOCONTAIN(selected_sc_names, unexpected_sc_names);
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, selection_empty_custom_base_set_repair)
|
||||
{
|
||||
TEST_F(test_falco_engine, selection_empty_custom_base_set_repair) {
|
||||
load_rules(ruleset_from_filters(s_sample_filters), "dummy_ruleset.yaml");
|
||||
|
||||
falco::app::state s7;
|
||||
@@ -410,23 +506,34 @@ TEST_F(test_falco_engine, selection_empty_custom_base_set_repair)
|
||||
ASSERT_TRUE(result.success);
|
||||
ASSERT_EQ(result.errstr, "");
|
||||
auto selected_sc_names = libsinsp::events::sc_set_to_event_names(s7.selected_sc_set);
|
||||
auto expected_sc_names = strset_t({
|
||||
// note: expecting syscalls from mock rules and `sinsp_repair_state_sc_set` enforced syscalls
|
||||
"connect", "accept", "accept4", "umount2", "open", "ptrace", "mmap", "execve", "procexit", \
|
||||
"bind", "socket", "clone3", "close", "setuid"
|
||||
});
|
||||
auto expected_sc_names = strset_t({// note: expecting syscalls from mock rules and
|
||||
// `sinsp_repair_state_sc_set` enforced syscalls
|
||||
"connect",
|
||||
"accept",
|
||||
"accept4",
|
||||
"umount2",
|
||||
"open",
|
||||
"ptrace",
|
||||
"mmap",
|
||||
"execve",
|
||||
"procexit",
|
||||
"bind",
|
||||
"socket",
|
||||
"clone3",
|
||||
"close",
|
||||
"setuid"});
|
||||
ASSERT_NAMES_CONTAIN(selected_sc_names, expected_sc_names);
|
||||
auto s7_state_set = libsinsp::events::sinsp_repair_state_sc_set(s7_rules_set);
|
||||
ASSERT_EQ(s7.selected_sc_set, s7_state_set);
|
||||
ASSERT_EQ(s7.selected_sc_set.size(), s7_state_set.size());
|
||||
}
|
||||
|
||||
TEST(ConfigureInterestingSets, ignored_set_expected_size)
|
||||
{
|
||||
TEST(ConfigureInterestingSets, ignored_set_expected_size) {
|
||||
// unit test fence to make sure we don't have unexpected regressions
|
||||
// in the ignored set, to be updated in the future
|
||||
ASSERT_EQ(falco::app::ignored_sc_set().size(), 14);
|
||||
|
||||
// we don't expect to ignore any syscall in the default base set
|
||||
ASSERT_EQ(falco::app::ignored_sc_set().intersect(libsinsp::events::sinsp_state_sc_set()).size(), 0);
|
||||
ASSERT_EQ(falco::app::ignored_sc_set().intersect(libsinsp::events::sinsp_state_sc_set()).size(),
|
||||
0);
|
||||
}
|
||||
|
||||
@@ -17,13 +17,11 @@ limitations under the License.
|
||||
|
||||
#include "app_action_helpers.h"
|
||||
|
||||
TEST(ActionConfigureSyscallBufferNum, variable_number_of_CPUs)
|
||||
{
|
||||
TEST(ActionConfigureSyscallBufferNum, variable_number_of_CPUs) {
|
||||
auto action = falco::app::actions::configure_syscall_buffer_num;
|
||||
|
||||
ssize_t online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
if(online_cpus <= 0)
|
||||
{
|
||||
if(online_cpus <= 0) {
|
||||
FAIL() << "cannot get the number of online CPUs from the system\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,7 @@ limitations under the License.
|
||||
#include "falco_test_var.h"
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
TEST(ActionLoadConfig, check_kmod_engine_config)
|
||||
{
|
||||
TEST(ActionLoadConfig, check_kmod_engine_config) {
|
||||
falco::app::state s = {};
|
||||
s.options.conf_filename = TEST_ENGINE_KMOD_CONFIG;
|
||||
EXPECT_ACTION_OK(falco::app::actions::load_config(s));
|
||||
@@ -47,8 +46,7 @@ TEST(ActionLoadConfig, check_kmod_engine_config)
|
||||
EXPECT_TRUE(s.config->m_gvisor.m_root.empty());
|
||||
}
|
||||
|
||||
TEST(ActionLoadConfig, check_modern_engine_config)
|
||||
{
|
||||
TEST(ActionLoadConfig, check_modern_engine_config) {
|
||||
falco::app::state s = {};
|
||||
s.options.conf_filename = TEST_ENGINE_MODERN_CONFIG;
|
||||
EXPECT_ACTION_OK(falco::app::actions::load_config(s));
|
||||
|
||||
@@ -17,85 +17,82 @@ limitations under the License.
|
||||
|
||||
#include "app_action_helpers.h"
|
||||
|
||||
TEST(ActionSelectEventSources, pre_post_conditions)
|
||||
{
|
||||
auto action = falco::app::actions::select_event_sources;
|
||||
TEST(ActionSelectEventSources, pre_post_conditions) {
|
||||
auto action = falco::app::actions::select_event_sources;
|
||||
|
||||
// requires sources to be already loaded
|
||||
{
|
||||
falco::app::state s;
|
||||
EXPECT_ACTION_FAIL(action(s));
|
||||
}
|
||||
// requires sources to be already loaded
|
||||
{
|
||||
falco::app::state s;
|
||||
EXPECT_ACTION_FAIL(action(s));
|
||||
}
|
||||
|
||||
// ignore source selection in capture mode
|
||||
{
|
||||
falco::app::state s;
|
||||
s.config->m_engine_mode = engine_kind_t::REPLAY;
|
||||
EXPECT_TRUE(s.is_capture_mode());
|
||||
EXPECT_ACTION_OK(action(s));
|
||||
}
|
||||
// ignore source selection in capture mode
|
||||
{
|
||||
falco::app::state s;
|
||||
s.config->m_engine_mode = engine_kind_t::REPLAY;
|
||||
EXPECT_TRUE(s.is_capture_mode());
|
||||
EXPECT_ACTION_OK(action(s));
|
||||
}
|
||||
|
||||
// enable all loaded sources by default, even with multiple calls
|
||||
{
|
||||
falco::app::state s;
|
||||
s.loaded_sources = {"syscall", "some_source"};
|
||||
EXPECT_ACTION_OK(action(s));
|
||||
EXPECT_EQ(s.loaded_sources.size(), s.enabled_sources.size());
|
||||
for (const auto& v : s.loaded_sources)
|
||||
{
|
||||
ASSERT_TRUE(s.enabled_sources.find(v) != s.enabled_sources.end());
|
||||
}
|
||||
s.loaded_sources.push_back("another_source");
|
||||
EXPECT_ACTION_OK(action(s));
|
||||
EXPECT_EQ(s.loaded_sources.size(), s.enabled_sources.size());
|
||||
for (const auto& v : s.loaded_sources)
|
||||
{
|
||||
ASSERT_TRUE(s.enabled_sources.find(v) != s.enabled_sources.end());
|
||||
}
|
||||
}
|
||||
// enable all loaded sources by default, even with multiple calls
|
||||
{
|
||||
falco::app::state s;
|
||||
s.loaded_sources = {"syscall", "some_source"};
|
||||
EXPECT_ACTION_OK(action(s));
|
||||
EXPECT_EQ(s.loaded_sources.size(), s.enabled_sources.size());
|
||||
for(const auto& v : s.loaded_sources) {
|
||||
ASSERT_TRUE(s.enabled_sources.find(v) != s.enabled_sources.end());
|
||||
}
|
||||
s.loaded_sources.push_back("another_source");
|
||||
EXPECT_ACTION_OK(action(s));
|
||||
EXPECT_EQ(s.loaded_sources.size(), s.enabled_sources.size());
|
||||
for(const auto& v : s.loaded_sources) {
|
||||
ASSERT_TRUE(s.enabled_sources.find(v) != s.enabled_sources.end());
|
||||
}
|
||||
}
|
||||
|
||||
// enable only selected sources
|
||||
{
|
||||
falco::app::state s;
|
||||
s.loaded_sources = {"syscall", "some_source"};
|
||||
s.options.enable_sources = {"syscall"};
|
||||
EXPECT_ACTION_OK(action(s));
|
||||
EXPECT_EQ(s.enabled_sources.size(), 1);
|
||||
EXPECT_EQ(*s.enabled_sources.begin(), "syscall");
|
||||
}
|
||||
// enable only selected sources
|
||||
{
|
||||
falco::app::state s;
|
||||
s.loaded_sources = {"syscall", "some_source"};
|
||||
s.options.enable_sources = {"syscall"};
|
||||
EXPECT_ACTION_OK(action(s));
|
||||
EXPECT_EQ(s.enabled_sources.size(), 1);
|
||||
EXPECT_EQ(*s.enabled_sources.begin(), "syscall");
|
||||
}
|
||||
|
||||
// enable all loaded sources expect the disabled ones
|
||||
{
|
||||
falco::app::state s;
|
||||
s.loaded_sources = {"syscall", "some_source"};
|
||||
s.options.disable_sources = {"syscall"};
|
||||
EXPECT_ACTION_OK(action(s));
|
||||
EXPECT_EQ(s.enabled_sources.size(), 1);
|
||||
EXPECT_EQ(*s.enabled_sources.begin(), "some_source");
|
||||
}
|
||||
// enable all loaded sources expect the disabled ones
|
||||
{
|
||||
falco::app::state s;
|
||||
s.loaded_sources = {"syscall", "some_source"};
|
||||
s.options.disable_sources = {"syscall"};
|
||||
EXPECT_ACTION_OK(action(s));
|
||||
EXPECT_EQ(s.enabled_sources.size(), 1);
|
||||
EXPECT_EQ(*s.enabled_sources.begin(), "some_source");
|
||||
}
|
||||
|
||||
// enable unknown sources
|
||||
{
|
||||
falco::app::state s;
|
||||
s.loaded_sources = {"syscall", "some_source"};
|
||||
s.options.enable_sources = {"some_other_source"};
|
||||
EXPECT_ACTION_FAIL(action(s));
|
||||
}
|
||||
// enable unknown sources
|
||||
{
|
||||
falco::app::state s;
|
||||
s.loaded_sources = {"syscall", "some_source"};
|
||||
s.options.enable_sources = {"some_other_source"};
|
||||
EXPECT_ACTION_FAIL(action(s));
|
||||
}
|
||||
|
||||
// disable unknown sources
|
||||
{
|
||||
falco::app::state s;
|
||||
s.loaded_sources = {"syscall", "some_source"};
|
||||
s.options.disable_sources = {"some_other_source"};
|
||||
EXPECT_ACTION_FAIL(action(s));
|
||||
}
|
||||
// disable unknown sources
|
||||
{
|
||||
falco::app::state s;
|
||||
s.loaded_sources = {"syscall", "some_source"};
|
||||
s.options.disable_sources = {"some_other_source"};
|
||||
EXPECT_ACTION_FAIL(action(s));
|
||||
}
|
||||
|
||||
// mix enable and disable sources options
|
||||
{
|
||||
falco::app::state s;
|
||||
s.loaded_sources = {"syscall", "some_source"};
|
||||
s.options.disable_sources = {"syscall"};
|
||||
s.options.enable_sources = {"syscall"};
|
||||
EXPECT_ACTION_FAIL(action(s));
|
||||
}
|
||||
// mix enable and disable sources options
|
||||
{
|
||||
falco::app::state s;
|
||||
s.loaded_sources = {"syscall", "some_source"};
|
||||
s.options.disable_sources = {"syscall"};
|
||||
s.options.enable_sources = {"syscall"};
|
||||
EXPECT_ACTION_FAIL(action(s));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,13 +25,11 @@ limitations under the License.
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
TEST(AtomicSignalHandler, lock_free_implementation)
|
||||
{
|
||||
TEST(AtomicSignalHandler, lock_free_implementation) {
|
||||
ASSERT_TRUE(falco::atomic_signal_handler().is_lock_free());
|
||||
}
|
||||
|
||||
TEST(AtomicSignalHandler, handle_once_wait_consistency)
|
||||
{
|
||||
TEST(AtomicSignalHandler, handle_once_wait_consistency) {
|
||||
constexpr const auto thread_num = 10;
|
||||
constexpr const std::chrono::seconds thread_wait_sec{2};
|
||||
constexpr const std::chrono::seconds handler_wait_sec{1};
|
||||
@@ -40,33 +38,27 @@ TEST(AtomicSignalHandler, handle_once_wait_consistency)
|
||||
falco::atomic_signal_handler handler;
|
||||
|
||||
// launch a bunch of threads all syncing on the same handler
|
||||
struct task_result_t
|
||||
{
|
||||
struct task_result_t {
|
||||
bool handled;
|
||||
std::chrono::seconds duration_secs;
|
||||
};
|
||||
|
||||
std::vector<std::future<task_result_t>> futures;
|
||||
for (int i = 0; i < thread_num; i++)
|
||||
{
|
||||
futures.emplace_back(std::async(std::launch::async,
|
||||
[&handler, thread_wait_sec]() {
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
task_result_t res;
|
||||
res.handled = false;
|
||||
while (!handler.handled())
|
||||
{
|
||||
if (handler.triggered())
|
||||
{
|
||||
res.handled = handler.handle([thread_wait_sec]() {
|
||||
std::this_thread::sleep_for(thread_wait_sec);
|
||||
});
|
||||
}
|
||||
for(int i = 0; i < thread_num; i++) {
|
||||
futures.emplace_back(std::async(std::launch::async, [&handler, thread_wait_sec]() {
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
task_result_t res;
|
||||
res.handled = false;
|
||||
while(!handler.handled()) {
|
||||
if(handler.triggered()) {
|
||||
res.handled = handler.handle(
|
||||
[thread_wait_sec]() { std::this_thread::sleep_for(thread_wait_sec); });
|
||||
}
|
||||
auto diff = std::chrono::high_resolution_clock::now() - start;
|
||||
res.duration_secs = std::chrono::duration_cast<std::chrono::seconds>(diff);
|
||||
return res;
|
||||
}));
|
||||
}
|
||||
auto diff = std::chrono::high_resolution_clock::now() - start;
|
||||
res.duration_secs = std::chrono::duration_cast<std::chrono::seconds>(diff);
|
||||
return res;
|
||||
}));
|
||||
}
|
||||
|
||||
// wait a bit, then trigger the signal handler from the main thread
|
||||
@@ -74,12 +66,10 @@ TEST(AtomicSignalHandler, handle_once_wait_consistency)
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
std::this_thread::sleep_for(handler_wait_sec);
|
||||
handler.trigger();
|
||||
for (int i = 0; i < thread_num; i++)
|
||||
{
|
||||
for(int i = 0; i < thread_num; i++) {
|
||||
// wait for all threads to finish and get the results from the futures
|
||||
auto res = futures[i].get();
|
||||
if (res.handled)
|
||||
{
|
||||
if(res.handled) {
|
||||
total_handled++;
|
||||
}
|
||||
ASSERT_GE(res.duration_secs, thread_wait_sec);
|
||||
@@ -94,9 +84,8 @@ TEST(AtomicSignalHandler, handle_once_wait_consistency)
|
||||
ASSERT_EQ(total_handled, 1);
|
||||
}
|
||||
|
||||
TEST(AtomicSignalHandler, handle_and_reset)
|
||||
{
|
||||
auto do_nothing = []{};
|
||||
TEST(AtomicSignalHandler, handle_and_reset) {
|
||||
auto do_nothing = [] {};
|
||||
falco::atomic_signal_handler handler;
|
||||
|
||||
ASSERT_FALSE(handler.triggered());
|
||||
|
||||
@@ -19,20 +19,19 @@ limitations under the License.
|
||||
#include <falco/configuration.h>
|
||||
|
||||
static std::string sample_yaml =
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: 'sample_name'\n"
|
||||
" subvalue:\n"
|
||||
" subvalue2:\n"
|
||||
" boolean: true\n"
|
||||
"base_value_2:\n"
|
||||
" sample_list:\n"
|
||||
" - elem1\n"
|
||||
" - elem2\n"
|
||||
" - elem3\n";
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: 'sample_name'\n"
|
||||
" subvalue:\n"
|
||||
" subvalue2:\n"
|
||||
" boolean: true\n"
|
||||
"base_value_2:\n"
|
||||
" sample_list:\n"
|
||||
" - elem1\n"
|
||||
" - elem2\n"
|
||||
" - elem3\n";
|
||||
|
||||
TEST(Configuration, configuration_exceptions)
|
||||
{
|
||||
TEST(Configuration, configuration_exceptions) {
|
||||
yaml_helper conf;
|
||||
|
||||
/* Broken YAML */
|
||||
@@ -43,8 +42,7 @@ TEST(Configuration, configuration_exceptions)
|
||||
EXPECT_NO_THROW(conf.load_from_string(sample_yaml));
|
||||
}
|
||||
|
||||
TEST(Configuration, configuration_reload)
|
||||
{
|
||||
TEST(Configuration, configuration_reload) {
|
||||
yaml_helper conf;
|
||||
|
||||
/* Clear and reload config */
|
||||
@@ -56,8 +54,7 @@ TEST(Configuration, configuration_reload)
|
||||
ASSERT_TRUE(conf.is_defined("base_value"));
|
||||
}
|
||||
|
||||
TEST(Configuration, read_yaml_fields)
|
||||
{
|
||||
TEST(Configuration, read_yaml_fields) {
|
||||
yaml_helper conf;
|
||||
conf.load_from_string(sample_yaml);
|
||||
|
||||
@@ -72,9 +69,12 @@ TEST(Configuration, read_yaml_fields)
|
||||
ASSERT_EQ(conf.get_scalar<bool>("base_value.subvalue.subvalue2.boolean", false), true);
|
||||
|
||||
/* get list field elements */
|
||||
ASSERT_STREQ(conf.get_scalar<std::string>("base_value_2.sample_list[0]", "none").c_str(), "elem1");
|
||||
ASSERT_STREQ(conf.get_scalar<std::string>("base_value_2.sample_list[1]", "none").c_str(), "elem2");
|
||||
ASSERT_STREQ(conf.get_scalar<std::string>("base_value_2.sample_list[2]", "none").c_str(), "elem3");
|
||||
ASSERT_STREQ(conf.get_scalar<std::string>("base_value_2.sample_list[0]", "none").c_str(),
|
||||
"elem1");
|
||||
ASSERT_STREQ(conf.get_scalar<std::string>("base_value_2.sample_list[1]", "none").c_str(),
|
||||
"elem2");
|
||||
ASSERT_STREQ(conf.get_scalar<std::string>("base_value_2.sample_list[2]", "none").c_str(),
|
||||
"elem3");
|
||||
|
||||
/* get sequence */
|
||||
std::vector<std::string> seq;
|
||||
@@ -85,100 +85,100 @@ TEST(Configuration, read_yaml_fields)
|
||||
ASSERT_STREQ(seq[2].c_str(), "elem3");
|
||||
}
|
||||
|
||||
TEST(Configuration, modify_yaml_fields)
|
||||
{
|
||||
TEST(Configuration, modify_yaml_fields) {
|
||||
std::string key = "base_value.subvalue.subvalue2.boolean";
|
||||
yaml_helper conf;
|
||||
|
||||
/* Get original value */
|
||||
conf.load_from_string(sample_yaml);
|
||||
/* Get original value */
|
||||
conf.load_from_string(sample_yaml);
|
||||
ASSERT_EQ(conf.get_scalar<bool>(key, false), true);
|
||||
|
||||
/* Modify the original value */
|
||||
conf.set_scalar<bool>(key, false);
|
||||
/* Modify the original value */
|
||||
conf.set_scalar<bool>(key, false);
|
||||
ASSERT_EQ(conf.get_scalar<bool>(key, true), false);
|
||||
|
||||
/* Modify it again */
|
||||
conf.set_scalar<bool>(key, true);
|
||||
/* Modify it again */
|
||||
conf.set_scalar<bool>(key, true);
|
||||
ASSERT_EQ(conf.get_scalar<bool>(key, false), true);
|
||||
}
|
||||
|
||||
TEST(Configuration, configuration_webserver_ip)
|
||||
{
|
||||
falco_configuration falco_config;
|
||||
TEST(Configuration, configuration_webserver_ip) {
|
||||
falco_configuration falco_config;
|
||||
|
||||
std::vector<std::string> valid_addresses = {"127.0.0.1",
|
||||
"1.127.0.1",
|
||||
"1.1.127.1",
|
||||
"1.1.1.127",
|
||||
"::",
|
||||
"::1",
|
||||
"1200:0000:AB00:1234:0000:2552:7777:1313",
|
||||
"1200::AB00:1234:0000:2552:7777:1313",
|
||||
"1200:0000:AB00:1234::2552:7777:1313",
|
||||
"21DA:D3:0:2F3B:2AA:FF:FE28:9C5A",
|
||||
"FE80:0000:0000:0000:0202:B3FF:FE1E:8329",
|
||||
"0.0.0.0",
|
||||
"9.255.255.255",
|
||||
"11.0.0.0",
|
||||
"126.255.255.255",
|
||||
"129.0.0.0",
|
||||
"169.253.255.255",
|
||||
"169.255.0.0",
|
||||
"172.15.255.255",
|
||||
"172.32.0.0",
|
||||
"191.0.1.255",
|
||||
"192.88.98.255",
|
||||
"192.88.100.0",
|
||||
"192.167.255.255",
|
||||
"192.169.0.0",
|
||||
"198.17.255.255",
|
||||
"223.255.255.255"};
|
||||
std::vector<std::string> valid_addresses = {"127.0.0.1",
|
||||
"1.127.0.1",
|
||||
"1.1.127.1",
|
||||
"1.1.1.127",
|
||||
"::",
|
||||
"::1",
|
||||
"1200:0000:AB00:1234:0000:2552:7777:1313",
|
||||
"1200::AB00:1234:0000:2552:7777:1313",
|
||||
"1200:0000:AB00:1234::2552:7777:1313",
|
||||
"21DA:D3:0:2F3B:2AA:FF:FE28:9C5A",
|
||||
"FE80:0000:0000:0000:0202:B3FF:FE1E:8329",
|
||||
"0.0.0.0",
|
||||
"9.255.255.255",
|
||||
"11.0.0.0",
|
||||
"126.255.255.255",
|
||||
"129.0.0.0",
|
||||
"169.253.255.255",
|
||||
"169.255.0.0",
|
||||
"172.15.255.255",
|
||||
"172.32.0.0",
|
||||
"191.0.1.255",
|
||||
"192.88.98.255",
|
||||
"192.88.100.0",
|
||||
"192.167.255.255",
|
||||
"192.169.0.0",
|
||||
"198.17.255.255",
|
||||
"223.255.255.255"};
|
||||
|
||||
for (const std::string &address: valid_addresses) {
|
||||
std::string option = "webserver.listen_address=";
|
||||
option.append(address);
|
||||
for(const std::string &address : valid_addresses) {
|
||||
std::string option = "webserver.listen_address=";
|
||||
option.append(address);
|
||||
|
||||
std::vector<std::string> cmdline_config_options;
|
||||
cmdline_config_options.push_back(option);
|
||||
std::vector<std::string> cmdline_config_options;
|
||||
cmdline_config_options.push_back(option);
|
||||
|
||||
EXPECT_NO_THROW(falco_config.init_from_content("", cmdline_config_options));
|
||||
EXPECT_NO_THROW(falco_config.init_from_content("", cmdline_config_options));
|
||||
|
||||
ASSERT_EQ(falco_config.m_webserver_config.m_listen_address, address);
|
||||
}
|
||||
ASSERT_EQ(falco_config.m_webserver_config.m_listen_address, address);
|
||||
}
|
||||
|
||||
std::vector<std::string> invalid_addresses = {"327.0.0.1",
|
||||
"1.327.0.1",
|
||||
"1.1.327.1",
|
||||
"1.1.1.327",
|
||||
"12 7.0.0.1",
|
||||
"127. 0.0.1",
|
||||
"127.0. 0.1",
|
||||
"127.0.0. 1",
|
||||
"!27.0.0.1",
|
||||
"1200: 0000:AB00:1234:0000:2552:7777:1313",
|
||||
"1200:0000: AB00:1234:0000:2552:7777:1313",
|
||||
"1200:0000:AB00: 1234:0000:2552:7777:1313",
|
||||
"1200:0000:AB00:1234: 0000:2552:7777:1313",
|
||||
"1200:0000:AB00:1234:0000: 2552:7777:1313",
|
||||
"1200:0000:AB00:1234:0000:2552: 7777:1313",
|
||||
"1200:0000:AB00:1234:0000:2552:7777: 1313",
|
||||
"1200:0000:AB00:1234:0000:2552:7777:131G",
|
||||
"1200:0000:AB00:1234:0000:2552:77Z7:1313",
|
||||
"1200:0000:AB00:1234:0000:2G52:7777:1313",
|
||||
"1200:0000:AB00:1234:0O00:2552:7777:1313",
|
||||
"1200:0000:AB00:H234:0000:2552:7777:1313",
|
||||
"1200:0000:IB00:1234:0000:2552:7777:1313",
|
||||
"1200:0O00:AB00:1234:0000:2552:7777:1313",
|
||||
"12O0:0000:AB00:1234:0000:2552:7777:1313",};
|
||||
std::vector<std::string> invalid_addresses = {
|
||||
"327.0.0.1",
|
||||
"1.327.0.1",
|
||||
"1.1.327.1",
|
||||
"1.1.1.327",
|
||||
"12 7.0.0.1",
|
||||
"127. 0.0.1",
|
||||
"127.0. 0.1",
|
||||
"127.0.0. 1",
|
||||
"!27.0.0.1",
|
||||
"1200: 0000:AB00:1234:0000:2552:7777:1313",
|
||||
"1200:0000: AB00:1234:0000:2552:7777:1313",
|
||||
"1200:0000:AB00: 1234:0000:2552:7777:1313",
|
||||
"1200:0000:AB00:1234: 0000:2552:7777:1313",
|
||||
"1200:0000:AB00:1234:0000: 2552:7777:1313",
|
||||
"1200:0000:AB00:1234:0000:2552: 7777:1313",
|
||||
"1200:0000:AB00:1234:0000:2552:7777: 1313",
|
||||
"1200:0000:AB00:1234:0000:2552:7777:131G",
|
||||
"1200:0000:AB00:1234:0000:2552:77Z7:1313",
|
||||
"1200:0000:AB00:1234:0000:2G52:7777:1313",
|
||||
"1200:0000:AB00:1234:0O00:2552:7777:1313",
|
||||
"1200:0000:AB00:H234:0000:2552:7777:1313",
|
||||
"1200:0000:IB00:1234:0000:2552:7777:1313",
|
||||
"1200:0O00:AB00:1234:0000:2552:7777:1313",
|
||||
"12O0:0000:AB00:1234:0000:2552:7777:1313",
|
||||
};
|
||||
|
||||
for (const std::string &address: invalid_addresses) {
|
||||
std::string option = "webserver.listen_address=";
|
||||
option.append(address);
|
||||
for(const std::string &address : invalid_addresses) {
|
||||
std::string option = "webserver.listen_address=";
|
||||
option.append(address);
|
||||
|
||||
std::vector<std::string> cmdline_config_options;
|
||||
cmdline_config_options.push_back(option);
|
||||
std::vector<std::string> cmdline_config_options;
|
||||
cmdline_config_options.push_back(option);
|
||||
|
||||
EXPECT_ANY_THROW(falco_config.init_from_content("", cmdline_config_options));
|
||||
}
|
||||
EXPECT_ANY_THROW(falco_config.init_from_content("", cmdline_config_options));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,23 +18,23 @@ limitations under the License.
|
||||
#include <gtest/gtest.h>
|
||||
#include <falco/configuration.h>
|
||||
|
||||
TEST(Configuration, configuration_config_files_secondary_fail)
|
||||
{
|
||||
/* Test that a secondary config file is not able to include anything, triggering an exception. */
|
||||
const std::string main_conf_yaml =
|
||||
yaml_helper::configs_key + ":\n"
|
||||
" - conf_2.yaml\n"
|
||||
" - conf_3.yaml\n"
|
||||
"foo: bar\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
const std::string conf_yaml_2 =
|
||||
yaml_helper::configs_key + ":\n"
|
||||
" - conf_4.yaml\n"
|
||||
"foo2: bar2\n"
|
||||
"base_value_2:\n"
|
||||
" id: 2\n";
|
||||
TEST(Configuration, configuration_config_files_secondary_fail) {
|
||||
/* Test that a secondary config file is not able to include anything, triggering an exception.
|
||||
*/
|
||||
const std::string main_conf_yaml = yaml_helper::configs_key +
|
||||
":\n"
|
||||
" - conf_2.yaml\n"
|
||||
" - conf_3.yaml\n"
|
||||
"foo: bar\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
const std::string conf_yaml_2 = yaml_helper::configs_key +
|
||||
":\n"
|
||||
" - conf_4.yaml\n"
|
||||
"foo2: bar2\n"
|
||||
"base_value_2:\n"
|
||||
" id: 2\n";
|
||||
|
||||
std::ofstream outfile("main.yaml");
|
||||
outfile << main_conf_yaml;
|
||||
@@ -52,29 +52,28 @@ TEST(Configuration, configuration_config_files_secondary_fail)
|
||||
std::filesystem::remove("conf_2.yaml");
|
||||
}
|
||||
|
||||
TEST(Configuration, configuration_config_files_ok)
|
||||
{
|
||||
TEST(Configuration, configuration_config_files_ok) {
|
||||
/* Test that every included config file was correctly parsed */
|
||||
const std::string main_conf_yaml =
|
||||
yaml_helper::configs_key + ":\n"
|
||||
" - conf_2.yaml\n"
|
||||
" - conf_3.yaml\n"
|
||||
"foo: bar\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
const std::string main_conf_yaml = yaml_helper::configs_key +
|
||||
":\n"
|
||||
" - conf_2.yaml\n"
|
||||
" - conf_3.yaml\n"
|
||||
"foo: bar\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
const std::string conf_yaml_2 =
|
||||
"foo2: bar2\n"
|
||||
"base_value_2:\n"
|
||||
" id: 2\n";
|
||||
"foo2: bar2\n"
|
||||
"base_value_2:\n"
|
||||
" id: 2\n";
|
||||
const std::string conf_yaml_3 =
|
||||
"foo3: bar3\n"
|
||||
"base_value_3:\n"
|
||||
" id: 3\n"
|
||||
" name: foo3\n";
|
||||
"foo3: bar3\n"
|
||||
"base_value_3:\n"
|
||||
" id: 3\n"
|
||||
" name: foo3\n";
|
||||
const std::string conf_yaml_4 =
|
||||
"base_value_4:\n"
|
||||
" id: 4\n";
|
||||
"base_value_4:\n"
|
||||
" id: 4\n";
|
||||
|
||||
std::ofstream outfile("main.yaml");
|
||||
outfile << main_conf_yaml;
|
||||
@@ -117,7 +116,7 @@ TEST(Configuration, configuration_config_files_ok)
|
||||
ASSERT_EQ(falco_config.m_config.get_scalar<int>("base_value_3.id", 0), 3);
|
||||
ASSERT_TRUE(falco_config.m_config.is_defined("base_value_3.name"));
|
||||
ASSERT_EQ(falco_config.m_config.get_scalar<std::string>("base_value_3.name", ""), "foo3");
|
||||
ASSERT_FALSE(falco_config.m_config.is_defined("base_value_4.id")); // conf_4 is not included
|
||||
ASSERT_FALSE(falco_config.m_config.is_defined("base_value_4.id")); // conf_4 is not included
|
||||
|
||||
std::filesystem::remove("main.yaml");
|
||||
std::filesystem::remove("conf_2.yaml");
|
||||
@@ -125,9 +124,7 @@ TEST(Configuration, configuration_config_files_ok)
|
||||
std::filesystem::remove("conf_4.yaml");
|
||||
}
|
||||
|
||||
|
||||
TEST(Configuration, configuration_config_files_relative_main)
|
||||
{
|
||||
TEST(Configuration, configuration_config_files_relative_main) {
|
||||
/*
|
||||
* Test that relative path are treated as relative to cwd and not to main config folder,
|
||||
* and that absolute includes are ok too.
|
||||
@@ -135,24 +132,25 @@ TEST(Configuration, configuration_config_files_relative_main)
|
||||
const auto temp_main = std::filesystem::temp_directory_path() / "main.yaml";
|
||||
// So, conf_2 will be looked up in the same folder as main config file,
|
||||
// while conf_3, since is absolute, will be looked up in the absolute path (and found!).
|
||||
const std::string main_conf_yaml =
|
||||
yaml_helper::configs_key + ":\n"
|
||||
" - conf_2.yaml\n"
|
||||
" - " +
|
||||
std::filesystem::current_path().string() + "/conf_3.yaml\n"
|
||||
"foo: bar\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
const std::string main_conf_yaml = yaml_helper::configs_key +
|
||||
":\n"
|
||||
" - conf_2.yaml\n"
|
||||
" - " +
|
||||
std::filesystem::current_path().string() +
|
||||
"/conf_3.yaml\n"
|
||||
"foo: bar\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
const std::string conf_yaml_2 =
|
||||
"foo2: bar2\n"
|
||||
"base_value_2:\n"
|
||||
" id: 2\n";
|
||||
"foo2: bar2\n"
|
||||
"base_value_2:\n"
|
||||
" id: 2\n";
|
||||
const std::string conf_yaml_3 =
|
||||
"foo3: bar3\n"
|
||||
"base_value_3:\n"
|
||||
" id: 3\n"
|
||||
" name: foo3\n";
|
||||
"foo3: bar3\n"
|
||||
"base_value_3:\n"
|
||||
" id: 3\n"
|
||||
" name: foo3\n";
|
||||
|
||||
std::ofstream outfile(temp_main.string());
|
||||
outfile << main_conf_yaml;
|
||||
@@ -192,24 +190,23 @@ TEST(Configuration, configuration_config_files_relative_main)
|
||||
std::filesystem::remove("conf_3.yaml");
|
||||
}
|
||||
|
||||
TEST(Configuration, configuration_config_files_override)
|
||||
{
|
||||
TEST(Configuration, configuration_config_files_override) {
|
||||
/* Test that included config files are able to override configs from main file */
|
||||
const std::string main_conf_yaml =
|
||||
yaml_helper::configs_key + ":\n"
|
||||
" - conf_2.yaml\n"
|
||||
" - conf_3.yaml\n"
|
||||
"foo: bar\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
const std::string main_conf_yaml = yaml_helper::configs_key +
|
||||
":\n"
|
||||
" - conf_2.yaml\n"
|
||||
" - conf_3.yaml\n"
|
||||
"foo: bar\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
const std::string conf_yaml_2 =
|
||||
"foo2: bar2\n"
|
||||
"base_value_2:\n"
|
||||
" id: 2\n";
|
||||
"foo2: bar2\n"
|
||||
"base_value_2:\n"
|
||||
" id: 2\n";
|
||||
const std::string conf_yaml_3 =
|
||||
"base_value:\n"
|
||||
" id: 3\n";
|
||||
"base_value:\n"
|
||||
" id: 3\n";
|
||||
|
||||
std::ofstream outfile("main.yaml");
|
||||
outfile << main_conf_yaml;
|
||||
@@ -234,28 +231,28 @@ TEST(Configuration, configuration_config_files_override)
|
||||
ASSERT_TRUE(falco_config.m_config.is_defined("foo"));
|
||||
ASSERT_EQ(falco_config.m_config.get_scalar<std::string>("foo", ""), "bar");
|
||||
ASSERT_TRUE(falco_config.m_config.is_defined("base_value.id"));
|
||||
ASSERT_EQ(falco_config.m_config.get_scalar<int>("base_value.id", 0), 3); // overridden!
|
||||
ASSERT_FALSE(falco_config.m_config.is_defined("base_value.name")); // no more present since entire `base_value` block was overridden
|
||||
ASSERT_EQ(falco_config.m_config.get_scalar<int>("base_value.id", 0), 3); // overridden!
|
||||
ASSERT_FALSE(falco_config.m_config.is_defined(
|
||||
"base_value.name")); // no more present since entire `base_value` block was overridden
|
||||
ASSERT_TRUE(falco_config.m_config.is_defined("foo2"));
|
||||
ASSERT_EQ(falco_config.m_config.get_scalar<std::string>("foo2", ""), "bar2");
|
||||
ASSERT_TRUE(falco_config.m_config.is_defined("base_value_2.id"));
|
||||
ASSERT_EQ(falco_config.m_config.get_scalar<int>("base_value_2.id", 0), 2);
|
||||
ASSERT_FALSE(falco_config.m_config.is_defined("base_value_3.id")); // not defined
|
||||
ASSERT_FALSE(falco_config.m_config.is_defined("base_value_3.id")); // not defined
|
||||
|
||||
std::filesystem::remove("main.yaml");
|
||||
std::filesystem::remove("conf_2.yaml");
|
||||
std::filesystem::remove("conf_3.yaml");
|
||||
}
|
||||
|
||||
TEST(Configuration, configuration_config_files_unexistent)
|
||||
{
|
||||
TEST(Configuration, configuration_config_files_unexistent) {
|
||||
/* Test that including an unexistent file just skips it */
|
||||
const std::string main_conf_yaml =
|
||||
yaml_helper::configs_key + ":\n"
|
||||
" - conf_5.yaml\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
const std::string main_conf_yaml = yaml_helper::configs_key +
|
||||
":\n"
|
||||
" - conf_5.yaml\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
|
||||
std::ofstream outfile("main.yaml");
|
||||
outfile << main_conf_yaml;
|
||||
@@ -277,19 +274,19 @@ TEST(Configuration, configuration_config_files_unexistent)
|
||||
std::filesystem::remove("main.yaml");
|
||||
}
|
||||
|
||||
TEST(Configuration, configuration_config_files_scalar_config_files)
|
||||
{
|
||||
/* Test that a single file can be included as a scalar (thanks to get_sequence_from_node magic) */
|
||||
const std::string main_conf_yaml =
|
||||
yaml_helper::configs_key + ": conf_2.yaml\n"
|
||||
"foo: bar\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
TEST(Configuration, configuration_config_files_scalar_config_files) {
|
||||
/* Test that a single file can be included as a scalar (thanks to get_sequence_from_node magic)
|
||||
*/
|
||||
const std::string main_conf_yaml = yaml_helper::configs_key +
|
||||
": conf_2.yaml\n"
|
||||
"foo: bar\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
const std::string conf_yaml_2 =
|
||||
"foo2: bar2\n"
|
||||
"base_value_2:\n"
|
||||
" id: 2\n";
|
||||
"foo2: bar2\n"
|
||||
"base_value_2:\n"
|
||||
" id: 2\n";
|
||||
|
||||
std::ofstream outfile("main.yaml");
|
||||
outfile << main_conf_yaml;
|
||||
@@ -322,15 +319,14 @@ TEST(Configuration, configuration_config_files_scalar_config_files)
|
||||
std::filesystem::remove("conf_2.yaml");
|
||||
}
|
||||
|
||||
TEST(Configuration, configuration_config_files_empty_config_files)
|
||||
{
|
||||
TEST(Configuration, configuration_config_files_empty_config_files) {
|
||||
/* Test that empty includes list is accepted */
|
||||
const std::string main_conf_yaml =
|
||||
yaml_helper::configs_key + ":\n"
|
||||
"foo: bar\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
const std::string main_conf_yaml = yaml_helper::configs_key +
|
||||
":\n"
|
||||
"foo: bar\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
|
||||
std::ofstream outfile("main.yaml");
|
||||
outfile << main_conf_yaml;
|
||||
@@ -354,15 +350,14 @@ TEST(Configuration, configuration_config_files_empty_config_files)
|
||||
std::filesystem::remove("main.yaml");
|
||||
}
|
||||
|
||||
TEST(Configuration, configuration_config_files_self)
|
||||
{
|
||||
TEST(Configuration, configuration_config_files_self) {
|
||||
/* Test that main config file cannot include itself */
|
||||
const std::string main_conf_yaml =
|
||||
yaml_helper::configs_key + ": main.yaml\n"
|
||||
"foo: bar\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
const std::string main_conf_yaml = yaml_helper::configs_key +
|
||||
": main.yaml\n"
|
||||
"foo: bar\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
|
||||
std::ofstream outfile("main.yaml");
|
||||
outfile << main_conf_yaml;
|
||||
@@ -375,31 +370,30 @@ TEST(Configuration, configuration_config_files_self)
|
||||
std::filesystem::remove("main.yaml");
|
||||
}
|
||||
|
||||
TEST(Configuration, configuration_config_files_directory)
|
||||
{
|
||||
TEST(Configuration, configuration_config_files_directory) {
|
||||
/*
|
||||
* Test that when main config file includes a config directory,
|
||||
* the config directory is parsed in lexicographic order,
|
||||
* and only regular files are parsed.
|
||||
*/
|
||||
// Main config includes whole temp directory
|
||||
const std::string main_conf_yaml =
|
||||
yaml_helper::configs_key + ": " + std::filesystem::temp_directory_path().string() + "/test\n"
|
||||
"foo: bar\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
const std::string main_conf_yaml = yaml_helper::configs_key + ": " +
|
||||
std::filesystem::temp_directory_path().string() +
|
||||
"/test\n"
|
||||
"foo: bar\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
const std::string conf_yaml_2 =
|
||||
"foo2: bar2\n"
|
||||
"base_value_2:\n"
|
||||
" id: 2\n";
|
||||
"foo2: bar2\n"
|
||||
"base_value_2:\n"
|
||||
" id: 2\n";
|
||||
const std::string conf_yaml_3 =
|
||||
"foo2: bar3\n"
|
||||
"base_value_3:\n"
|
||||
" id: 3\n"
|
||||
" name: foo3\n";
|
||||
const std::string conf_yaml_4 =
|
||||
"foo4: bar4\n";
|
||||
"foo2: bar3\n"
|
||||
"base_value_3:\n"
|
||||
" id: 3\n"
|
||||
" name: foo3\n";
|
||||
const std::string conf_yaml_4 = "foo4: bar4\n";
|
||||
|
||||
std::filesystem::create_directory(std::filesystem::temp_directory_path() / "test");
|
||||
|
||||
@@ -407,17 +401,17 @@ TEST(Configuration, configuration_config_files_directory)
|
||||
outfile << main_conf_yaml;
|
||||
outfile.close();
|
||||
|
||||
outfile.open(std::filesystem::temp_directory_path()/"test/conf_2.yaml");
|
||||
outfile.open(std::filesystem::temp_directory_path() / "test/conf_2.yaml");
|
||||
outfile << conf_yaml_2;
|
||||
outfile.close();
|
||||
|
||||
outfile.open(std::filesystem::temp_directory_path()/"test/conf_3.yaml");
|
||||
outfile.open(std::filesystem::temp_directory_path() / "test/conf_3.yaml");
|
||||
outfile << conf_yaml_3;
|
||||
outfile.close();
|
||||
|
||||
// Create a directory and create a config inside it. We will later check that it was not parsed
|
||||
std::filesystem::create_directory(std::filesystem::temp_directory_path() / "test" / "foo");
|
||||
outfile.open(std::filesystem::temp_directory_path()/"test/foo/conf_4.yaml");
|
||||
outfile.open(std::filesystem::temp_directory_path() / "test/foo/conf_4.yaml");
|
||||
outfile << conf_yaml_4;
|
||||
outfile.close();
|
||||
|
||||
@@ -445,21 +439,20 @@ TEST(Configuration, configuration_config_files_directory)
|
||||
ASSERT_FALSE(falco_config.m_config.is_defined("foo4"));
|
||||
|
||||
std::filesystem::remove("main");
|
||||
std::filesystem::remove_all(std::filesystem::temp_directory_path()/"test");
|
||||
std::filesystem::remove_all(std::filesystem::temp_directory_path() / "test");
|
||||
}
|
||||
|
||||
TEST(Configuration, configuration_config_files_cmdline)
|
||||
{
|
||||
TEST(Configuration, configuration_config_files_cmdline) {
|
||||
/* Test that we support including configs files from cmdline option */
|
||||
const std::string main_conf_yaml =
|
||||
"foo: bar\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
"foo: bar\n"
|
||||
"base_value:\n"
|
||||
" id: 1\n"
|
||||
" name: foo\n";
|
||||
const std::string conf_yaml_2 =
|
||||
"foo2: bar2\n"
|
||||
"base_value_2:\n"
|
||||
" id: 2\n";
|
||||
"foo2: bar2\n"
|
||||
"base_value_2:\n"
|
||||
" id: 2\n";
|
||||
|
||||
std::ofstream outfile("main.yaml");
|
||||
outfile << main_conf_yaml;
|
||||
@@ -471,7 +464,7 @@ TEST(Configuration, configuration_config_files_cmdline)
|
||||
|
||||
// Pass "config_files=..." cmdline option
|
||||
std::vector<std::string> cmdline_config_options;
|
||||
cmdline_config_options.push_back((yaml_helper::configs_key+"=conf_2.yaml"));
|
||||
cmdline_config_options.push_back((yaml_helper::configs_key + "=conf_2.yaml"));
|
||||
|
||||
falco_configuration falco_config;
|
||||
config_loaded_res res;
|
||||
@@ -493,4 +486,4 @@ TEST(Configuration, configuration_config_files_cmdline)
|
||||
|
||||
std::filesystem::remove("main.yaml");
|
||||
std::filesystem::remove("conf_2.yaml");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,7 @@ limitations under the License.
|
||||
#define SET_ENV_VAR(env_var_name, env_var_value) setenv(env_var_name, env_var_value, 1)
|
||||
#endif
|
||||
|
||||
TEST(Configuration, configuration_environment_variables)
|
||||
{
|
||||
TEST(Configuration, configuration_environment_variables) {
|
||||
// Set an environment variable for testing purposes
|
||||
std::string env_var_value = "envVarValue";
|
||||
std::string env_var_name = "ENV_VAR";
|
||||
@@ -49,38 +48,38 @@ TEST(Configuration, configuration_environment_variables)
|
||||
|
||||
std::string default_value = "default";
|
||||
std::string env_var_sample_yaml =
|
||||
"base_value:\n"
|
||||
" id: $ENV_VAR\n"
|
||||
" name: '${ENV_VAR}'\n"
|
||||
" string: my_string\n"
|
||||
" invalid: $${ENV_VAR}\n"
|
||||
" invalid_env: $$ENV_VAR\n"
|
||||
" invalid_double_env: $${ENV_VAR}$${ENV_VAR}\n"
|
||||
" invalid_embedded_env: $${${ENV_VAR}}\n"
|
||||
" invalid_valid_env: $${ENV_VAR}${ENV_VAR}\n"
|
||||
" escaped: \"${ENV_VAR}\"\n"
|
||||
" subvalue:\n"
|
||||
" subvalue2:\n"
|
||||
" boolean: ${UNSED_XX_X_X_VAR}\n"
|
||||
"base_value_2:\n"
|
||||
" sample_list:\n"
|
||||
" - ${ENV_VAR}\n"
|
||||
" - ' ${ENV_VAR}'\n"
|
||||
" - '${ENV_VAR} '\n"
|
||||
" - $UNSED_XX_X_X_VAR\n"
|
||||
"paths:\n"
|
||||
" - ${ENV_VAR}/foo\n"
|
||||
" - $ENV_VAR/foo\n"
|
||||
" - /foo/${ENV_VAR}/\n"
|
||||
" - /${ENV_VAR}/${ENV_VAR}${ENV_VAR}/foo\n"
|
||||
" - ${ENV_VAR_EMBEDDED}/foo\n"
|
||||
"is_test: ${ENV_VAR_BOOL}\n"
|
||||
"num_test: ${ENV_VAR_INT}\n"
|
||||
"empty_test: ${ENV_VAR_EMPTY}\n"
|
||||
"plugins:\n"
|
||||
" - name: k8saudit\n"
|
||||
" library_path: /foo/${ENV_VAR}/libk8saudit.so\n"
|
||||
" open_params: ${ENV_VAR_INT}\n";
|
||||
"base_value:\n"
|
||||
" id: $ENV_VAR\n"
|
||||
" name: '${ENV_VAR}'\n"
|
||||
" string: my_string\n"
|
||||
" invalid: $${ENV_VAR}\n"
|
||||
" invalid_env: $$ENV_VAR\n"
|
||||
" invalid_double_env: $${ENV_VAR}$${ENV_VAR}\n"
|
||||
" invalid_embedded_env: $${${ENV_VAR}}\n"
|
||||
" invalid_valid_env: $${ENV_VAR}${ENV_VAR}\n"
|
||||
" escaped: \"${ENV_VAR}\"\n"
|
||||
" subvalue:\n"
|
||||
" subvalue2:\n"
|
||||
" boolean: ${UNSED_XX_X_X_VAR}\n"
|
||||
"base_value_2:\n"
|
||||
" sample_list:\n"
|
||||
" - ${ENV_VAR}\n"
|
||||
" - ' ${ENV_VAR}'\n"
|
||||
" - '${ENV_VAR} '\n"
|
||||
" - $UNSED_XX_X_X_VAR\n"
|
||||
"paths:\n"
|
||||
" - ${ENV_VAR}/foo\n"
|
||||
" - $ENV_VAR/foo\n"
|
||||
" - /foo/${ENV_VAR}/\n"
|
||||
" - /${ENV_VAR}/${ENV_VAR}${ENV_VAR}/foo\n"
|
||||
" - ${ENV_VAR_EMBEDDED}/foo\n"
|
||||
"is_test: ${ENV_VAR_BOOL}\n"
|
||||
"num_test: ${ENV_VAR_INT}\n"
|
||||
"empty_test: ${ENV_VAR_EMPTY}\n"
|
||||
"plugins:\n"
|
||||
" - name: k8saudit\n"
|
||||
" library_path: /foo/${ENV_VAR}/libk8saudit.so\n"
|
||||
" open_params: ${ENV_VAR_INT}\n";
|
||||
|
||||
yaml_helper conf;
|
||||
conf.load_from_string(env_var_sample_yaml);
|
||||
@@ -95,84 +94,112 @@ TEST(Configuration, configuration_environment_variables)
|
||||
auto base_value_string = conf.get_scalar<std::string>("base_value.string", default_value);
|
||||
ASSERT_EQ(base_value_string, "my_string");
|
||||
|
||||
/* Test fetching of escaped environment variable format. Should return the string as-is after stripping the leading `$` */
|
||||
/* Test fetching of escaped environment variable format. Should return the string as-is after
|
||||
* stripping the leading `$` */
|
||||
auto base_value_invalid = conf.get_scalar<std::string>("base_value.invalid", default_value);
|
||||
ASSERT_EQ(base_value_invalid, "${ENV_VAR}");
|
||||
|
||||
/* Test fetching of invalid escaped environment variable format. Should return the string as-is */
|
||||
auto base_value_invalid_env = conf.get_scalar<std::string>("base_value.invalid_env", default_value);
|
||||
/* Test fetching of invalid escaped environment variable format. Should return the string as-is
|
||||
*/
|
||||
auto base_value_invalid_env =
|
||||
conf.get_scalar<std::string>("base_value.invalid_env", default_value);
|
||||
ASSERT_EQ(base_value_invalid_env, "$$ENV_VAR");
|
||||
|
||||
/* Test fetching of 2 escaped environment variables side by side. Should return the string as-is after stripping the leading `$` */
|
||||
auto base_value_double_invalid = conf.get_scalar<std::string>("base_value.invalid_double_env", default_value);
|
||||
/* Test fetching of 2 escaped environment variables side by side. Should return the string as-is
|
||||
* after stripping the leading `$` */
|
||||
auto base_value_double_invalid =
|
||||
conf.get_scalar<std::string>("base_value.invalid_double_env", default_value);
|
||||
ASSERT_EQ(base_value_double_invalid, "${ENV_VAR}${ENV_VAR}");
|
||||
|
||||
/*
|
||||
* Test fetching of escaped environment variable format with inside an env variable.
|
||||
* Should return the string as-is after stripping the leading `$` with the resolved env variable within
|
||||
* Test fetching of escaped environment variable format with inside an env variable.
|
||||
* Should return the string as-is after stripping the leading `$` with the resolved env variable
|
||||
* within
|
||||
*/
|
||||
auto base_value_embedded_invalid = conf.get_scalar<std::string>("base_value.invalid_embedded_env", default_value);
|
||||
auto base_value_embedded_invalid =
|
||||
conf.get_scalar<std::string>("base_value.invalid_embedded_env", default_value);
|
||||
ASSERT_EQ(base_value_embedded_invalid, "${" + env_var_value + "}");
|
||||
|
||||
/*
|
||||
* Test fetching of an escaped env variable plus an env variable side by side.
|
||||
* Should return the escaped one trimming the leading `$` plus the second one resolved.
|
||||
* Test fetching of an escaped env variable plus an env variable side by side.
|
||||
* Should return the escaped one trimming the leading `$` plus the second one resolved.
|
||||
*/
|
||||
auto base_value_valid_invalid = conf.get_scalar<std::string>("base_value.invalid_valid_env", default_value);
|
||||
auto base_value_valid_invalid =
|
||||
conf.get_scalar<std::string>("base_value.invalid_valid_env", default_value);
|
||||
ASSERT_EQ(base_value_valid_invalid, "${ENV_VAR}" + env_var_value);
|
||||
|
||||
/* Test fetching of strings that contain environment variables */
|
||||
auto base_value_id = conf.get_scalar<std::string>("base_value.id", default_value);
|
||||
ASSERT_EQ(base_value_id, "$ENV_VAR"); // Does not follow the `${VAR}` format, so it should be treated as a regular string
|
||||
ASSERT_EQ(base_value_id, "$ENV_VAR"); // Does not follow the `${VAR}` format, so it should be
|
||||
// treated as a regular string
|
||||
|
||||
auto base_value_name = conf.get_scalar<std::string>("base_value.name", default_value);
|
||||
ASSERT_EQ(base_value_name, env_var_value); // Proper environment variable format
|
||||
ASSERT_EQ(base_value_name, env_var_value); // Proper environment variable format
|
||||
|
||||
auto base_value_escaped = conf.get_scalar<std::string>("base_value.escaped", default_value);
|
||||
ASSERT_EQ(base_value_escaped, env_var_value); // Environment variable within quotes
|
||||
ASSERT_EQ(base_value_escaped, env_var_value); // Environment variable within quotes
|
||||
|
||||
/* Test fetching of an undefined environment variable. Resolves to empty string. */
|
||||
auto unknown_boolean = conf.get_scalar<std::string>("base_value.subvalue.subvalue2.boolean", default_value);
|
||||
auto unknown_boolean =
|
||||
conf.get_scalar<std::string>("base_value.subvalue.subvalue2.boolean", default_value);
|
||||
ASSERT_EQ(unknown_boolean, "");
|
||||
|
||||
/* Test fetching of environment variables from a list */
|
||||
auto base_value_2_list_0 = conf.get_scalar<std::string>("base_value_2.sample_list[0]", default_value);
|
||||
ASSERT_EQ(base_value_2_list_0, env_var_value); // Proper environment variable format
|
||||
auto base_value_2_list_0 =
|
||||
conf.get_scalar<std::string>("base_value_2.sample_list[0]", default_value);
|
||||
ASSERT_EQ(base_value_2_list_0, env_var_value); // Proper environment variable format
|
||||
|
||||
auto base_value_2_list_1 = conf.get_scalar<std::string>("base_value_2.sample_list[1]", default_value);
|
||||
ASSERT_EQ(base_value_2_list_1, " " + env_var_value); // Environment variable preceded by a space, still extracted env var with leading space
|
||||
auto base_value_2_list_1 =
|
||||
conf.get_scalar<std::string>("base_value_2.sample_list[1]", default_value);
|
||||
ASSERT_EQ(base_value_2_list_1,
|
||||
" " + env_var_value); // Environment variable preceded by a space, still extracted
|
||||
// env var with leading space
|
||||
|
||||
auto base_value_2_list_2 = conf.get_scalar<std::string>("base_value_2.sample_list[2]", default_value);
|
||||
ASSERT_EQ(base_value_2_list_2, env_var_value + " "); // Environment variable followed by a space, still extracted env var with trailing space
|
||||
auto base_value_2_list_2 =
|
||||
conf.get_scalar<std::string>("base_value_2.sample_list[2]", default_value);
|
||||
ASSERT_EQ(base_value_2_list_2,
|
||||
env_var_value + " "); // Environment variable followed by a space, still extracted
|
||||
// env var with trailing space
|
||||
|
||||
auto base_value_2_list_3 = conf.get_scalar<std::string>("base_value_2.sample_list[3]", default_value);
|
||||
ASSERT_EQ(base_value_2_list_3, "$UNSED_XX_X_X_VAR"); // Does not follow the `${VAR}` format, so should be treated as a regular string
|
||||
auto base_value_2_list_3 =
|
||||
conf.get_scalar<std::string>("base_value_2.sample_list[3]", default_value);
|
||||
ASSERT_EQ(base_value_2_list_3, "$UNSED_XX_X_X_VAR"); // Does not follow the `${VAR}` format, so
|
||||
// should be treated as a regular string
|
||||
|
||||
/* Test expansion of environment variables within strings */
|
||||
auto path_list_0 = conf.get_scalar<std::string>("paths[0]", default_value);
|
||||
ASSERT_EQ(path_list_0, env_var_value + "/foo"); // Even if env var is part of bigger string, it gets expanded
|
||||
ASSERT_EQ(
|
||||
path_list_0,
|
||||
env_var_value + "/foo"); // Even if env var is part of bigger string, it gets expanded
|
||||
|
||||
auto path_list_1 = conf.get_scalar<std::string>("paths[1]", default_value);
|
||||
ASSERT_EQ(path_list_1, "$ENV_VAR/foo"); // Does not follow the `${VAR}` format, so should be treated as a regular string
|
||||
ASSERT_EQ(path_list_1, "$ENV_VAR/foo"); // Does not follow the `${VAR}` format, so should be
|
||||
// treated as a regular string
|
||||
|
||||
auto path_list_2 = conf.get_scalar<std::string>("paths[2]", default_value);
|
||||
ASSERT_EQ(path_list_2, "/foo/" + env_var_value + "/"); // Even when env var is in the middle of a string. it gets expanded
|
||||
ASSERT_EQ(path_list_2,
|
||||
"/foo/" + env_var_value +
|
||||
"/"); // Even when env var is in the middle of a string. it gets expanded
|
||||
|
||||
auto path_list_3 = conf.get_scalar<std::string>("paths[3]", default_value);
|
||||
ASSERT_EQ(path_list_3, "/" + env_var_value + "/" + env_var_value + env_var_value + "/foo"); // Even when the string contains multiple env vars they are correctly expanded
|
||||
ASSERT_EQ(path_list_3,
|
||||
"/" + env_var_value + "/" + env_var_value + env_var_value +
|
||||
"/foo"); // Even when the string contains multiple env vars they are
|
||||
// correctly expanded
|
||||
|
||||
auto path_list_4 = conf.get_scalar<std::string>("paths[4]", default_value);
|
||||
ASSERT_EQ(path_list_4, env_var_value + "/foo"); // Even when the env var contains another env var, it gets correctly double-expanded
|
||||
ASSERT_EQ(path_list_4, env_var_value + "/foo"); // Even when the env var contains another env
|
||||
// var, it gets correctly double-expanded
|
||||
|
||||
/* Check that variable expansion is type-aware */
|
||||
auto boolean = conf.get_scalar<bool>("is_test", false);
|
||||
ASSERT_EQ(boolean, true); // `true` can be parsed to bool.
|
||||
ASSERT_EQ(boolean, true); // `true` can be parsed to bool.
|
||||
|
||||
auto boolean_as_str = conf.get_scalar<std::string>("is_test", "false");
|
||||
ASSERT_EQ(boolean_as_str, "true"); // `true` can be parsed to string.
|
||||
ASSERT_EQ(boolean_as_str, "true"); // `true` can be parsed to string.
|
||||
|
||||
auto boolean_as_int = conf.get_scalar<int32_t>("is_test", 0);
|
||||
ASSERT_EQ(boolean_as_int, 0); // `true` cannot be parsed to integer.
|
||||
ASSERT_EQ(boolean_as_int, 0); // `true` cannot be parsed to integer.
|
||||
|
||||
auto integer = conf.get_scalar<int32_t>("num_test", -1);
|
||||
ASSERT_EQ(integer, 12);
|
||||
@@ -182,9 +209,11 @@ TEST(Configuration, configuration_environment_variables)
|
||||
ASSERT_EQ(empty_default_str, "");
|
||||
|
||||
std::list<falco_configuration::plugin_config> plugins;
|
||||
conf.get_sequence<std::list<falco_configuration::plugin_config>>(plugins, std::string("plugins"));
|
||||
std::vector<falco_configuration::plugin_config> m_plugins{ std::make_move_iterator(std::begin(plugins)),
|
||||
std::make_move_iterator(std::end(plugins)) };
|
||||
conf.get_sequence<std::list<falco_configuration::plugin_config>>(plugins,
|
||||
std::string("plugins"));
|
||||
std::vector<falco_configuration::plugin_config> m_plugins{
|
||||
std::make_move_iterator(std::begin(plugins)),
|
||||
std::make_move_iterator(std::end(plugins))};
|
||||
ASSERT_EQ(m_plugins[0].m_name, "k8saudit");
|
||||
ASSERT_EQ(m_plugins[0].m_library_path, "/foo/" + env_var_value + "/libk8saudit.so");
|
||||
ASSERT_EQ(m_plugins[0].m_open_params, "12");
|
||||
|
||||
@@ -18,8 +18,7 @@ limitations under the License.
|
||||
#include <gtest/gtest.h>
|
||||
#include <falco/configuration.h>
|
||||
|
||||
TEST(ConfigurationRuleOutputOptions, parse_yaml)
|
||||
{
|
||||
TEST(ConfigurationRuleOutputOptions, parse_yaml) {
|
||||
falco_configuration falco_config;
|
||||
ASSERT_NO_THROW(falco_config.init_from_content(R"(
|
||||
append_output:
|
||||
@@ -44,7 +43,8 @@ append_output:
|
||||
- ka.verb
|
||||
- static_field: "static content"
|
||||
|
||||
)", {}));
|
||||
)",
|
||||
{}));
|
||||
|
||||
EXPECT_EQ(falco_config.m_append_output.size(), 3);
|
||||
|
||||
@@ -53,17 +53,22 @@ append_output:
|
||||
EXPECT_EQ(falco_config.m_append_output[0].m_tags.count("persistence"), 1);
|
||||
EXPECT_EQ(falco_config.m_append_output[0].m_rule, "some rule name");
|
||||
EXPECT_EQ(falco_config.m_append_output[0].m_formatted_fields.size(), 0);
|
||||
EXPECT_EQ(falco_config.m_append_output[0].m_format, "gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4]");
|
||||
EXPECT_EQ(falco_config.m_append_output[0].m_format,
|
||||
"gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4]");
|
||||
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_tags.size(), 2);
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_tags.count("persistence"), 1);
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_tags.count("execution"), 1);
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_format, "gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4]");
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_format,
|
||||
"gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4]");
|
||||
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_formatted_fields.size(), 3);
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_formatted_fields["proc.aname[2]"], "%proc.aname[2]");
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_formatted_fields["proc.aname[3]"], "%proc.aname[3]");
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_formatted_fields["proc.aname[4]"], "%proc.aname[4]");
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_formatted_fields["proc.aname[2]"],
|
||||
"%proc.aname[2]");
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_formatted_fields["proc.aname[3]"],
|
||||
"%proc.aname[3]");
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_formatted_fields["proc.aname[4]"],
|
||||
"%proc.aname[4]");
|
||||
|
||||
EXPECT_EQ(falco_config.m_append_output[2].m_source, "k8s_audit");
|
||||
|
||||
@@ -74,15 +79,15 @@ append_output:
|
||||
EXPECT_EQ(falco_config.m_append_output[2].m_raw_fields.count("ka.verb"), 1);
|
||||
}
|
||||
|
||||
TEST(ConfigurationRuleOutputOptions, cli_options)
|
||||
{
|
||||
TEST(ConfigurationRuleOutputOptions, cli_options) {
|
||||
falco_configuration falco_config;
|
||||
|
||||
ASSERT_NO_THROW(falco_config.init_from_content("",
|
||||
std::vector<std::string>{
|
||||
R"(append_output[]={"match": {"source": "syscall", "tags": ["persistence"], "rule": "some rule name"}, "extra_output": "gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4]"})",
|
||||
R"(append_output[]={"match": {"tags": ["persistence", "execution"]}, "extra_fields": [{"proc.aname[2]": "%proc.aname[2]"}, {"proc.aname[3]": "%proc.aname[3]"}, {"proc.aname[4]": "%proc.aname[4]"}], "extra_output": "gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4]"})",
|
||||
R"(append_output[]={"match": {"source": "k8s_audit"}, "extra_fields": ["ka.verb", {"static_field": "static content"}]})"}));
|
||||
ASSERT_NO_THROW(falco_config.init_from_content(
|
||||
"",
|
||||
std::vector<std::string>{
|
||||
R"(append_output[]={"match": {"source": "syscall", "tags": ["persistence"], "rule": "some rule name"}, "extra_output": "gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4]"})",
|
||||
R"(append_output[]={"match": {"tags": ["persistence", "execution"]}, "extra_fields": [{"proc.aname[2]": "%proc.aname[2]"}, {"proc.aname[3]": "%proc.aname[3]"}, {"proc.aname[4]": "%proc.aname[4]"}], "extra_output": "gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4]"})",
|
||||
R"(append_output[]={"match": {"source": "k8s_audit"}, "extra_fields": ["ka.verb", {"static_field": "static content"}]})"}));
|
||||
|
||||
EXPECT_EQ(falco_config.m_append_output.size(), 3);
|
||||
|
||||
@@ -91,17 +96,22 @@ TEST(ConfigurationRuleOutputOptions, cli_options)
|
||||
EXPECT_EQ(falco_config.m_append_output[0].m_tags.count("persistence"), 1);
|
||||
EXPECT_EQ(falco_config.m_append_output[0].m_rule, "some rule name");
|
||||
EXPECT_EQ(falco_config.m_append_output[0].m_formatted_fields.size(), 0);
|
||||
EXPECT_EQ(falco_config.m_append_output[0].m_format, "gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4]");
|
||||
EXPECT_EQ(falco_config.m_append_output[0].m_format,
|
||||
"gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4]");
|
||||
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_tags.size(), 2);
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_tags.count("persistence"), 1);
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_tags.count("execution"), 1);
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_format, "gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4]");
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_format,
|
||||
"gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4]");
|
||||
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_formatted_fields.size(), 3);
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_formatted_fields["proc.aname[2]"], "%proc.aname[2]");
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_formatted_fields["proc.aname[3]"], "%proc.aname[3]");
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_formatted_fields["proc.aname[4]"], "%proc.aname[4]");
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_formatted_fields["proc.aname[2]"],
|
||||
"%proc.aname[2]");
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_formatted_fields["proc.aname[3]"],
|
||||
"%proc.aname[3]");
|
||||
EXPECT_EQ(falco_config.m_append_output[1].m_formatted_fields["proc.aname[4]"],
|
||||
"%proc.aname[4]");
|
||||
|
||||
EXPECT_EQ(falco_config.m_append_output[2].m_source, "k8s_audit");
|
||||
|
||||
|
||||
@@ -18,8 +18,7 @@ limitations under the License.
|
||||
#include <gtest/gtest.h>
|
||||
#include <falco/configuration.h>
|
||||
|
||||
TEST(ConfigurationRuleSelection, parse_yaml)
|
||||
{
|
||||
TEST(ConfigurationRuleSelection, parse_yaml) {
|
||||
falco_configuration falco_config;
|
||||
ASSERT_NO_THROW(falco_config.init_from_content(R"(
|
||||
rules:
|
||||
@@ -31,44 +30,57 @@ rules:
|
||||
|
||||
- enable:
|
||||
rule: 'hello*'
|
||||
)", {}));
|
||||
)",
|
||||
{}));
|
||||
|
||||
EXPECT_EQ(falco_config.m_rules_selection.size(), 3);
|
||||
|
||||
EXPECT_EQ(falco_config.m_rules_selection[0].m_op, falco_configuration::rule_selection_operation::enable);
|
||||
EXPECT_EQ(falco_config.m_rules_selection[0].m_op,
|
||||
falco_configuration::rule_selection_operation::enable);
|
||||
EXPECT_EQ(falco_config.m_rules_selection[0].m_rule, "Terminal Shell in Container");
|
||||
|
||||
EXPECT_EQ(falco_config.m_rules_selection[1].m_op, falco_configuration::rule_selection_operation::disable);
|
||||
EXPECT_EQ(falco_config.m_rules_selection[1].m_op,
|
||||
falco_configuration::rule_selection_operation::disable);
|
||||
EXPECT_EQ(falco_config.m_rules_selection[1].m_tag, "experimental");
|
||||
|
||||
EXPECT_EQ(falco_config.m_rules_selection[2].m_op, falco_configuration::rule_selection_operation::enable);
|
||||
EXPECT_EQ(falco_config.m_rules_selection[2].m_op,
|
||||
falco_configuration::rule_selection_operation::enable);
|
||||
EXPECT_EQ(falco_config.m_rules_selection[2].m_rule, "hello*");
|
||||
}
|
||||
|
||||
TEST(ConfigurationRuleSelection, cli_options)
|
||||
{
|
||||
TEST(ConfigurationRuleSelection, cli_options) {
|
||||
falco_configuration falco_config;
|
||||
ASSERT_NO_THROW(falco_config.init_from_content("", std::vector<std::string>{"rules[].disable.tag=maturity_incubating", "rules[].enable.rule=Adding ssh keys to authorized_keys"}));
|
||||
ASSERT_NO_THROW(falco_config.init_from_content(
|
||||
"",
|
||||
std::vector<std::string>{"rules[].disable.tag=maturity_incubating",
|
||||
"rules[].enable.rule=Adding ssh keys to authorized_keys"}));
|
||||
|
||||
EXPECT_EQ(falco_config.m_rules_selection.size(), 2);
|
||||
|
||||
EXPECT_EQ(falco_config.m_rules_selection[0].m_op, falco_configuration::rule_selection_operation::disable);
|
||||
EXPECT_EQ(falco_config.m_rules_selection[0].m_op,
|
||||
falco_configuration::rule_selection_operation::disable);
|
||||
EXPECT_EQ(falco_config.m_rules_selection[0].m_tag, "maturity_incubating");
|
||||
|
||||
EXPECT_EQ(falco_config.m_rules_selection[1].m_op, falco_configuration::rule_selection_operation::enable);
|
||||
EXPECT_EQ(falco_config.m_rules_selection[1].m_op,
|
||||
falco_configuration::rule_selection_operation::enable);
|
||||
EXPECT_EQ(falco_config.m_rules_selection[1].m_rule, "Adding ssh keys to authorized_keys");
|
||||
}
|
||||
|
||||
TEST(ConfigurationRuleSelection, cli_options_object)
|
||||
{
|
||||
TEST(ConfigurationRuleSelection, cli_options_object) {
|
||||
falco_configuration falco_config;
|
||||
ASSERT_NO_THROW(falco_config.init_from_content("", std::vector<std::string>{R"(rules[]={"disable": {"tag": "maturity_incubating"}})", R"(rules[]={"enable": {"rule": "Adding ssh keys to authorized_keys"}})"}));
|
||||
ASSERT_NO_THROW(falco_config.init_from_content(
|
||||
"",
|
||||
std::vector<std::string>{
|
||||
R"(rules[]={"disable": {"tag": "maturity_incubating"}})",
|
||||
R"(rules[]={"enable": {"rule": "Adding ssh keys to authorized_keys"}})"}));
|
||||
|
||||
EXPECT_EQ(falco_config.m_rules_selection.size(), 2);
|
||||
|
||||
EXPECT_EQ(falco_config.m_rules_selection[0].m_op, falco_configuration::rule_selection_operation::disable);
|
||||
EXPECT_EQ(falco_config.m_rules_selection[0].m_op,
|
||||
falco_configuration::rule_selection_operation::disable);
|
||||
EXPECT_EQ(falco_config.m_rules_selection[0].m_tag, "maturity_incubating");
|
||||
|
||||
EXPECT_EQ(falco_config.m_rules_selection[1].m_op, falco_configuration::rule_selection_operation::enable);
|
||||
EXPECT_EQ(falco_config.m_rules_selection[1].m_op,
|
||||
falco_configuration::rule_selection_operation::enable);
|
||||
EXPECT_EQ(falco_config.m_rules_selection[1].m_rule, "Adding ssh keys to authorized_keys");
|
||||
}
|
||||
|
||||
@@ -18,94 +18,142 @@ limitations under the License.
|
||||
#include <gtest/gtest.h>
|
||||
#include <falco/configuration.h>
|
||||
#include <falco_test_var.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#define EXPECT_VALIDATION_STATUS(res, status) \
|
||||
do { \
|
||||
for(const auto& pair : res) { \
|
||||
auto validation_status = pair.second; \
|
||||
#define EXPECT_VALIDATION_STATUS(res, status) \
|
||||
do { \
|
||||
for(const auto& pair : res) { \
|
||||
auto validation_status = pair.second; \
|
||||
EXPECT_TRUE(sinsp_utils::startswith(validation_status, status)) << validation_status; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
// Read Falco config from current repo-path
|
||||
TEST(Configuration, schema_validate_config)
|
||||
{
|
||||
TEST(Configuration, schema_validate_config) {
|
||||
falco_configuration falco_config;
|
||||
config_loaded_res res;
|
||||
|
||||
if (!std::filesystem::exists(TEST_FALCO_CONFIG))
|
||||
{
|
||||
if(!std::filesystem::exists(TEST_FALCO_CONFIG)) {
|
||||
GTEST_SKIP() << "Falco config not present under " << TEST_FALCO_CONFIG;
|
||||
}
|
||||
EXPECT_NO_THROW(res = falco_config.init_from_file(TEST_FALCO_CONFIG, {}));
|
||||
EXPECT_VALIDATION_STATUS(res, yaml_helper::validation_ok);
|
||||
}
|
||||
|
||||
TEST(Configuration, schema_ok)
|
||||
{
|
||||
TEST(Configuration, schema_ok) {
|
||||
falco_configuration falco_config;
|
||||
config_loaded_res res;
|
||||
|
||||
/* OK YAML */
|
||||
std::string config =
|
||||
"falco_libs:\n"
|
||||
" thread_table_size: 50\n";
|
||||
"falco_libs:\n"
|
||||
" thread_table_size: 50\n";
|
||||
|
||||
EXPECT_NO_THROW(res = falco_config.init_from_content(config, {}));
|
||||
EXPECT_VALIDATION_STATUS(res, yaml_helper::validation_ok);
|
||||
}
|
||||
|
||||
TEST(Configuration, schema_wrong_key)
|
||||
{
|
||||
TEST(Configuration, schema_wrong_key) {
|
||||
falco_configuration falco_config;
|
||||
config_loaded_res res;
|
||||
|
||||
/* Miss-typed key YAML */
|
||||
std::string config =
|
||||
"falco_libss:\n"
|
||||
" thread_table_size: 50\n";
|
||||
"falco_libss:\n"
|
||||
" thread_table_size: 50\n";
|
||||
|
||||
EXPECT_NO_THROW(res = falco_config.init_from_content(config, {}));
|
||||
EXPECT_VALIDATION_STATUS(res, yaml_helper::validation_failed);
|
||||
}
|
||||
|
||||
TEST(Configuration, schema_wrong_type)
|
||||
{
|
||||
TEST(Configuration, schema_wrong_type) {
|
||||
falco_configuration falco_config;
|
||||
|
||||
/* Wrong value type YAML */
|
||||
std::string config =
|
||||
"falco_libs: 512\n";
|
||||
std::string config = "falco_libs: 512\n";
|
||||
|
||||
// We expect an exception since `falco_configuration::load_yaml()`
|
||||
// will fail to parse `falco_libs` node.
|
||||
ASSERT_ANY_THROW(falco_config.init_from_content(config, {}));
|
||||
}
|
||||
|
||||
TEST(Configuration, schema_wrong_embedded_key)
|
||||
{
|
||||
TEST(Configuration, schema_wrong_embedded_key) {
|
||||
falco_configuration falco_config;
|
||||
config_loaded_res res;
|
||||
|
||||
/* Miss-typed sub-key YAML */
|
||||
std::string config =
|
||||
"falco_libs:\n"
|
||||
" thread_table_sizeee: 50\n";
|
||||
"falco_libs:\n"
|
||||
" thread_table_sizeee: 50\n";
|
||||
|
||||
EXPECT_NO_THROW(res = falco_config.init_from_content(config, {}));
|
||||
EXPECT_VALIDATION_STATUS(res, yaml_helper::validation_failed);
|
||||
}
|
||||
|
||||
TEST(Configuration, schema_yaml_helper_validator)
|
||||
{
|
||||
TEST(Configuration, plugin_init_config) {
|
||||
falco_configuration falco_config;
|
||||
config_loaded_res res;
|
||||
|
||||
std::string config = R"(
|
||||
plugins:
|
||||
- name: k8saudit
|
||||
library_path: libk8saudit.so
|
||||
init_config:
|
||||
maxEventSize: 262144
|
||||
sslCertificate: /etc/falco/falco.pem
|
||||
)";
|
||||
|
||||
auto plugin_config_json = nlohmann::json::parse(
|
||||
R"({"maxEventSize": 262144, "sslCertificate": "/etc/falco/falco.pem"})");
|
||||
|
||||
EXPECT_NO_THROW(res = falco_config.init_from_content(config, {}));
|
||||
EXPECT_VALIDATION_STATUS(res, yaml_helper::validation_ok);
|
||||
auto parsed_init_config = nlohmann::json::parse(falco_config.m_plugins[0].m_init_config);
|
||||
EXPECT_EQ(parsed_init_config, plugin_config_json);
|
||||
|
||||
config = R"(
|
||||
plugins:
|
||||
- name: k8saudit
|
||||
library_path: libk8saudit.so
|
||||
init_config: '{"maxEventSize": 262144, "sslCertificate": "/etc/falco/falco.pem"}'
|
||||
)";
|
||||
|
||||
EXPECT_NO_THROW(res = falco_config.init_from_content(config, {}));
|
||||
EXPECT_VALIDATION_STATUS(res, yaml_helper::validation_ok);
|
||||
parsed_init_config = nlohmann::json::parse(falco_config.m_plugins[0].m_init_config);
|
||||
EXPECT_EQ(parsed_init_config, plugin_config_json);
|
||||
|
||||
config = R"(
|
||||
plugins:
|
||||
- name: k8saudit
|
||||
library_path: libk8saudit.so
|
||||
init_config: ""
|
||||
)";
|
||||
|
||||
EXPECT_NO_THROW(res = falco_config.init_from_content(config, {}));
|
||||
EXPECT_VALIDATION_STATUS(res, yaml_helper::validation_ok);
|
||||
EXPECT_EQ(falco_config.m_plugins[0].m_init_config, "");
|
||||
|
||||
config = R"(
|
||||
plugins:
|
||||
- name: k8saudit
|
||||
library_path: libk8saudit.so
|
||||
init_config: null
|
||||
)";
|
||||
|
||||
EXPECT_NO_THROW(res = falco_config.init_from_content(config, {}));
|
||||
EXPECT_VALIDATION_STATUS(res, yaml_helper::validation_ok);
|
||||
EXPECT_EQ(falco_config.m_plugins[0].m_init_config, "");
|
||||
}
|
||||
|
||||
TEST(Configuration, schema_yaml_helper_validator) {
|
||||
yaml_helper conf;
|
||||
falco_configuration falco_config;
|
||||
|
||||
/* Broken YAML */
|
||||
std::string sample_yaml =
|
||||
"falco_libs:\n"
|
||||
" thread_table_size: 50\n";
|
||||
"falco_libs:\n"
|
||||
" thread_table_size: 50\n";
|
||||
|
||||
// Ok, we don't ask for any validation
|
||||
EXPECT_NO_THROW(conf.load_from_string(sample_yaml));
|
||||
@@ -121,4 +169,4 @@ TEST(Configuration, schema_yaml_helper_validator)
|
||||
// We pass everything
|
||||
EXPECT_NO_THROW(conf.load_from_string(sample_yaml, falco_config.m_config_schema, &validation));
|
||||
EXPECT_EQ(validation[0], yaml_helper::validation_ok);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "test_falco_engine.h"
|
||||
|
||||
test_falco_engine::test_falco_engine()
|
||||
{
|
||||
test_falco_engine::test_falco_engine() {
|
||||
// create a falco engine ready to load the ruleset
|
||||
m_filter_factory = std::make_shared<sinsp_filter_factory>(&m_inspector, m_filterlist);
|
||||
m_formatter_factory = std::make_shared<sinsp_evt_formatter_factory>(&m_inspector, m_filterlist);
|
||||
@@ -9,8 +8,8 @@ test_falco_engine::test_falco_engine()
|
||||
m_engine->add_source(m_sample_source, m_filter_factory, m_formatter_factory);
|
||||
}
|
||||
|
||||
bool test_falco_engine::load_rules(const std::string& rules_content, const std::string& rules_filename)
|
||||
{
|
||||
bool test_falco_engine::load_rules(const std::string& rules_content,
|
||||
const 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);
|
||||
@@ -18,8 +17,7 @@ bool test_falco_engine::load_rules(const std::string& rules_content, const std::
|
||||
m_load_result_json = m_load_result->as_json(rc);
|
||||
ret = m_load_result->successful();
|
||||
|
||||
if (ret)
|
||||
{
|
||||
if(ret) {
|
||||
m_engine->enable_rule("", true, m_sample_ruleset);
|
||||
}
|
||||
|
||||
@@ -27,30 +25,24 @@ bool test_falco_engine::load_rules(const std::string& rules_content, const std::
|
||||
}
|
||||
|
||||
// This must be kept in line with the (private) falco_engine::s_default_ruleset
|
||||
uint64_t test_falco_engine::num_rules_for_ruleset(const std::string& ruleset)
|
||||
{
|
||||
uint64_t test_falco_engine::num_rules_for_ruleset(const std::string& ruleset) {
|
||||
return m_engine->num_rules_for_ruleset(ruleset);
|
||||
}
|
||||
|
||||
bool test_falco_engine::has_warnings() const
|
||||
{
|
||||
bool test_falco_engine::has_warnings() const {
|
||||
return m_load_result->has_warnings();
|
||||
}
|
||||
|
||||
bool test_falco_engine::check_warning_message(const std::string& warning_msg) const
|
||||
{
|
||||
if(!m_load_result->has_warnings())
|
||||
{
|
||||
bool test_falco_engine::check_warning_message(const std::string& warning_msg) const {
|
||||
if(!m_load_result->has_warnings()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(const auto &warn : m_load_result_json["warnings"])
|
||||
{
|
||||
for(const 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)
|
||||
{
|
||||
if(msg.find(warning_msg) != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -58,21 +50,17 @@ bool test_falco_engine::check_warning_message(const std::string& warning_msg) co
|
||||
return false;
|
||||
}
|
||||
|
||||
bool test_falco_engine::check_error_message(const std::string& error_msg) const
|
||||
{
|
||||
bool test_falco_engine::check_error_message(const std::string& error_msg) const {
|
||||
// if the loading is successful there are no errors
|
||||
if(m_load_result->successful())
|
||||
{
|
||||
if(m_load_result->successful()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(const auto &err : m_load_result_json["errors"])
|
||||
{
|
||||
for(const 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)
|
||||
{
|
||||
if(msg.find(error_msg) != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -80,20 +68,20 @@ bool test_falco_engine::check_error_message(const std::string& error_msg) const
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string test_falco_engine::get_compiled_rule_condition(std::string rule_name) const
|
||||
{
|
||||
std::string test_falco_engine::get_compiled_rule_condition(std::string rule_name) const {
|
||||
auto rule_description = m_engine->describe_rule(&rule_name, {});
|
||||
return rule_description["rules"][0]["details"]["condition_compiled"].template get<std::string>();
|
||||
return rule_description["rules"][0]["details"]["condition_compiled"]
|
||||
.template get<std::string>();
|
||||
}
|
||||
|
||||
std::string test_falco_engine::get_compiled_rule_output(std::string rule_name) const
|
||||
{
|
||||
std::string test_falco_engine::get_compiled_rule_output(std::string rule_name) const {
|
||||
auto rule_description = m_engine->describe_rule(&rule_name, {});
|
||||
return rule_description["rules"][0]["details"]["output_compiled"].template get<std::string>();
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::string> test_falco_engine::get_compiled_rule_formatted_fields(std::string rule_name) const
|
||||
{
|
||||
std::unordered_map<std::string, std::string> test_falco_engine::get_compiled_rule_formatted_fields(
|
||||
std::string rule_name) const {
|
||||
auto rule_description = m_engine->describe_rule(&rule_name, {});
|
||||
return rule_description["rules"][0]["details"]["extra_output_formatted_fields"].template get<std::unordered_map<std::string, std::string>>();
|
||||
return rule_description["rules"][0]["details"]["extra_output_formatted_fields"]
|
||||
.template get<std::unordered_map<std::string, std::string>>();
|
||||
}
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <unordered_map>
|
||||
|
||||
class test_falco_engine : public testing::Test
|
||||
{
|
||||
class test_falco_engine : public testing::Test {
|
||||
protected:
|
||||
test_falco_engine();
|
||||
|
||||
@@ -21,7 +20,8 @@ protected:
|
||||
bool check_error_message(const std::string& error_msg) const;
|
||||
std::string get_compiled_rule_condition(std::string rule_name = "") const;
|
||||
std::string get_compiled_rule_output(std::string rule_name = "") const;
|
||||
std::unordered_map<std::string, std::string> get_compiled_rule_formatted_fields(std::string rule_name) const;
|
||||
std::unordered_map<std::string, std::string> get_compiled_rule_formatted_fields(
|
||||
std::string rule_name) const;
|
||||
|
||||
std::string m_sample_ruleset = "sample-ruleset";
|
||||
std::string m_sample_source = falco_common::syscall_source;
|
||||
|
||||
@@ -2,47 +2,40 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# 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.
|
||||
|
||||
add_library(falco_engine STATIC
|
||||
falco_common.cpp
|
||||
falco_engine.cpp
|
||||
falco_load_result.cpp
|
||||
falco_utils.cpp
|
||||
filter_ruleset.cpp
|
||||
evttype_index_ruleset.cpp
|
||||
formats.cpp
|
||||
filter_details_resolver.cpp
|
||||
filter_macro_resolver.cpp
|
||||
filter_warning_resolver.cpp
|
||||
logger.cpp
|
||||
stats_manager.cpp
|
||||
rule_loader.cpp
|
||||
rule_loader_reader.cpp
|
||||
rule_loader_collector.cpp
|
||||
rule_loader_compiler.cpp
|
||||
add_library(
|
||||
falco_engine STATIC
|
||||
falco_common.cpp
|
||||
falco_engine.cpp
|
||||
falco_load_result.cpp
|
||||
falco_utils.cpp
|
||||
filter_ruleset.cpp
|
||||
evttype_index_ruleset.cpp
|
||||
formats.cpp
|
||||
filter_details_resolver.cpp
|
||||
filter_macro_resolver.cpp
|
||||
filter_warning_resolver.cpp
|
||||
logger.cpp
|
||||
stats_manager.cpp
|
||||
rule_loader.cpp
|
||||
rule_loader_reader.cpp
|
||||
rule_loader_collector.cpp
|
||||
rule_loader_compiler.cpp
|
||||
)
|
||||
|
||||
if (EMSCRIPTEN)
|
||||
if(EMSCRIPTEN)
|
||||
target_compile_options(falco_engine PRIVATE "-sDISABLE_EXCEPTION_CATCHING=0")
|
||||
endif()
|
||||
|
||||
target_include_directories(falco_engine
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${TBB_INCLUDE_DIR}
|
||||
)
|
||||
target_include_directories(falco_engine PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${TBB_INCLUDE_DIR})
|
||||
|
||||
target_link_libraries(falco_engine
|
||||
PUBLIC
|
||||
sinsp
|
||||
nlohmann_json::nlohmann_json
|
||||
yaml-cpp
|
||||
)
|
||||
target_link_libraries(falco_engine PUBLIC sinsp nlohmann_json::nlohmann_json yaml-cpp)
|
||||
|
||||
@@ -21,57 +21,43 @@ limitations under the License.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
evttype_index_ruleset::evttype_index_ruleset(
|
||||
std::shared_ptr<sinsp_filter_factory> f):
|
||||
m_filter_factory(f)
|
||||
{
|
||||
}
|
||||
evttype_index_ruleset::evttype_index_ruleset(std::shared_ptr<sinsp_filter_factory> f):
|
||||
m_filter_factory(f) {}
|
||||
|
||||
evttype_index_ruleset::~evttype_index_ruleset()
|
||||
{
|
||||
}
|
||||
evttype_index_ruleset::~evttype_index_ruleset() {}
|
||||
|
||||
void evttype_index_ruleset::add(
|
||||
const falco_rule& rule,
|
||||
std::shared_ptr<sinsp_filter> filter,
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> condition)
|
||||
{
|
||||
try
|
||||
{
|
||||
void evttype_index_ruleset::add(const falco_rule &rule,
|
||||
std::shared_ptr<sinsp_filter> filter,
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> condition) {
|
||||
try {
|
||||
auto wrap = std::make_shared<evttype_index_wrapper>();
|
||||
wrap->m_rule = rule;
|
||||
wrap->m_filter = filter;
|
||||
if(rule.source == falco_common::syscall_source)
|
||||
{
|
||||
if(rule.source == falco_common::syscall_source) {
|
||||
wrap->m_sc_codes = libsinsp::filter::ast::ppm_sc_codes(condition.get());
|
||||
wrap->m_event_codes = libsinsp::filter::ast::ppm_event_codes(condition.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
wrap->m_sc_codes = {};
|
||||
wrap->m_event_codes = {ppm_event_code::PPME_PLUGINEVENT_E};
|
||||
}
|
||||
wrap->m_event_codes.insert(ppm_event_code::PPME_ASYNCEVENT_E);
|
||||
|
||||
add_wrapper(wrap);
|
||||
}
|
||||
catch (const sinsp_exception& e)
|
||||
{
|
||||
} catch(const sinsp_exception &e) {
|
||||
throw falco_exception(std::string(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
void evttype_index_ruleset::on_loading_complete()
|
||||
{
|
||||
void evttype_index_ruleset::on_loading_complete() {
|
||||
print_enabled_rules_falco_logger();
|
||||
}
|
||||
|
||||
bool evttype_index_ruleset::run_wrappers(sinsp_evt *evt, filter_wrapper_list &wrappers, uint16_t ruleset_id, falco_rule &match)
|
||||
{
|
||||
for(auto &wrap : wrappers)
|
||||
{
|
||||
if(wrap->m_filter->run(evt))
|
||||
{
|
||||
bool evttype_index_ruleset::run_wrappers(sinsp_evt *evt,
|
||||
filter_wrapper_list &wrappers,
|
||||
uint16_t ruleset_id,
|
||||
falco_rule &match) {
|
||||
for(auto &wrap : wrappers) {
|
||||
if(wrap->m_filter->run(evt)) {
|
||||
match = wrap->m_rule;
|
||||
return true;
|
||||
}
|
||||
@@ -80,14 +66,14 @@ bool evttype_index_ruleset::run_wrappers(sinsp_evt *evt, filter_wrapper_list &wr
|
||||
return false;
|
||||
}
|
||||
|
||||
bool evttype_index_ruleset::run_wrappers(sinsp_evt *evt, filter_wrapper_list &wrappers, uint16_t ruleset_id, std::vector<falco_rule> &matches)
|
||||
{
|
||||
bool evttype_index_ruleset::run_wrappers(sinsp_evt *evt,
|
||||
filter_wrapper_list &wrappers,
|
||||
uint16_t ruleset_id,
|
||||
std::vector<falco_rule> &matches) {
|
||||
bool match_found = false;
|
||||
|
||||
for(auto &wrap : wrappers)
|
||||
{
|
||||
if(wrap->m_filter->run(evt))
|
||||
{
|
||||
for(auto &wrap : wrappers) {
|
||||
if(wrap->m_filter->run(evt)) {
|
||||
matches.push_back(wrap->m_rule);
|
||||
match_found = true;
|
||||
}
|
||||
@@ -96,16 +82,15 @@ bool evttype_index_ruleset::run_wrappers(sinsp_evt *evt, filter_wrapper_list &wr
|
||||
return match_found;
|
||||
}
|
||||
|
||||
void evttype_index_ruleset::print_enabled_rules_falco_logger()
|
||||
{
|
||||
void evttype_index_ruleset::print_enabled_rules_falco_logger() {
|
||||
falco_logger::log(falco_logger::level::DEBUG, "Enabled rules:\n");
|
||||
|
||||
auto logger = [](std::shared_ptr<evttype_index_wrapper> wrap)
|
||||
{
|
||||
auto logger = [](std::shared_ptr<evttype_index_wrapper> wrap) {
|
||||
falco_logger::log(falco_logger::level::DEBUG, std::string(" ") + wrap->name() + "\n");
|
||||
};
|
||||
|
||||
uint64_t num_filters = iterate(logger);
|
||||
|
||||
falco_logger::log(falco_logger::level::DEBUG, "(" + std::to_string(num_filters) + ") enabled rules in total\n");
|
||||
falco_logger::log(falco_logger::level::DEBUG,
|
||||
"(" + std::to_string(num_filters) + ") enabled rules in total\n");
|
||||
}
|
||||
|
||||
@@ -24,12 +24,11 @@ limitations under the License.
|
||||
#include <vector>
|
||||
|
||||
/*!
|
||||
\brief A filter_ruleset that indexes enabled rules by event type,
|
||||
and performs linear search on each event type bucket
|
||||
\brief A filter_ruleset that indexes enabled rules by event type,
|
||||
and performs linear search on each event type bucket
|
||||
*/
|
||||
|
||||
struct evttype_index_wrapper
|
||||
{
|
||||
struct evttype_index_wrapper {
|
||||
const std::string &name() { return m_rule.name; }
|
||||
const std::set<std::string> &tags() { return m_rule.tags; }
|
||||
const libsinsp::events::set<ppm_sc_code> &sc_codes() { return m_sc_codes; }
|
||||
@@ -41,23 +40,27 @@ struct evttype_index_wrapper
|
||||
std::shared_ptr<sinsp_filter> m_filter;
|
||||
};
|
||||
|
||||
class evttype_index_ruleset : public indexable_ruleset<evttype_index_wrapper>
|
||||
{
|
||||
class evttype_index_ruleset : public indexable_ruleset<evttype_index_wrapper> {
|
||||
public:
|
||||
explicit evttype_index_ruleset(std::shared_ptr<sinsp_filter_factory> factory);
|
||||
virtual ~evttype_index_ruleset();
|
||||
|
||||
// From filter_ruleset
|
||||
void add(
|
||||
const falco_rule& rule,
|
||||
std::shared_ptr<sinsp_filter> filter,
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> condition) override;
|
||||
void add(const falco_rule &rule,
|
||||
std::shared_ptr<sinsp_filter> filter,
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> condition) override;
|
||||
|
||||
void on_loading_complete() override;
|
||||
|
||||
// From indexable_ruleset
|
||||
bool run_wrappers(sinsp_evt *evt, filter_wrapper_list &wrappers, uint16_t ruleset_id, falco_rule &match) override;
|
||||
bool run_wrappers(sinsp_evt *evt, filter_wrapper_list &wrappers, uint16_t ruleset_id, std::vector<falco_rule> &matches) override;
|
||||
bool run_wrappers(sinsp_evt *evt,
|
||||
filter_wrapper_list &wrappers,
|
||||
uint16_t ruleset_id,
|
||||
falco_rule &match) override;
|
||||
bool run_wrappers(sinsp_evt *evt,
|
||||
filter_wrapper_list &wrappers,
|
||||
uint16_t ruleset_id,
|
||||
std::vector<falco_rule> &matches) override;
|
||||
|
||||
// Print each enabled rule when running Falco with falco logger
|
||||
// log_level=debug; invoked within on_loading_complete()
|
||||
@@ -67,15 +70,12 @@ private:
|
||||
std::shared_ptr<sinsp_filter_factory> m_filter_factory;
|
||||
};
|
||||
|
||||
class evttype_index_ruleset_factory: public filter_ruleset_factory
|
||||
{
|
||||
class evttype_index_ruleset_factory : public filter_ruleset_factory {
|
||||
public:
|
||||
inline explicit evttype_index_ruleset_factory(
|
||||
std::shared_ptr<sinsp_filter_factory> factory
|
||||
): m_filter_factory(factory) { }
|
||||
inline explicit evttype_index_ruleset_factory(std::shared_ptr<sinsp_filter_factory> factory):
|
||||
m_filter_factory(factory) {}
|
||||
|
||||
inline std::shared_ptr<filter_ruleset> new_ruleset() override
|
||||
{
|
||||
inline std::shared_ptr<filter_ruleset> new_ruleset() override {
|
||||
return std::make_shared<evttype_index_ruleset>(m_filter_factory);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,83 +17,57 @@ limitations under the License.
|
||||
|
||||
#include "falco_common.h"
|
||||
|
||||
static std::vector<std::string> priority_names = {
|
||||
"Emergency",
|
||||
"Alert",
|
||||
"Critical",
|
||||
"Error",
|
||||
"Warning",
|
||||
"Notice",
|
||||
"Informational",
|
||||
"Debug"
|
||||
};
|
||||
static std::vector<std::string> priority_names =
|
||||
{"Emergency", "Alert", "Critical", "Error", "Warning", "Notice", "Informational", "Debug"};
|
||||
|
||||
static std::vector<std::string> rule_matching_names = {
|
||||
"first",
|
||||
"all"
|
||||
};
|
||||
static std::vector<std::string> rule_matching_names = {"first", "all"};
|
||||
|
||||
bool falco_common::parse_priority(const std::string& v, priority_type& out)
|
||||
{
|
||||
for (size_t i = 0; i < priority_names.size(); i++)
|
||||
{
|
||||
bool falco_common::parse_priority(const std::string& v, priority_type& out) {
|
||||
for(size_t i = 0; i < priority_names.size(); i++) {
|
||||
// note: for legacy reasons, "Info" and "Informational" has been used
|
||||
// interchangeably and ambiguously, so this is the only edge case for
|
||||
// which we can't apply strict equality check
|
||||
if (!strcasecmp(v.c_str(), priority_names[i].c_str())
|
||||
|| (i == PRIORITY_INFORMATIONAL && !strcasecmp(v.c_str(), "info")))
|
||||
{
|
||||
out = (priority_type) i;
|
||||
if(!strcasecmp(v.c_str(), priority_names[i].c_str()) ||
|
||||
(i == PRIORITY_INFORMATIONAL && !strcasecmp(v.c_str(), "info"))) {
|
||||
out = (priority_type)i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
falco_common::priority_type falco_common::parse_priority(const std::string& v)
|
||||
{
|
||||
falco_common::priority_type falco_common::parse_priority(const std::string& v) {
|
||||
falco_common::priority_type out;
|
||||
if (!parse_priority(v, out))
|
||||
{
|
||||
if(!parse_priority(v, out)) {
|
||||
throw falco_exception("Unknown priority value: " + v);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
bool falco_common::format_priority(priority_type v, std::string& out, bool shortfmt)
|
||||
{
|
||||
if ((size_t) v < priority_names.size())
|
||||
{
|
||||
if (v == PRIORITY_INFORMATIONAL && shortfmt)
|
||||
{
|
||||
bool falco_common::format_priority(priority_type v, std::string& out, bool shortfmt) {
|
||||
if((size_t)v < priority_names.size()) {
|
||||
if(v == PRIORITY_INFORMATIONAL && shortfmt) {
|
||||
out = "Info";
|
||||
}
|
||||
else
|
||||
{
|
||||
out = priority_names[(size_t) v];
|
||||
} else {
|
||||
out = priority_names[(size_t)v];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string falco_common::format_priority(priority_type v, bool shortfmt)
|
||||
{
|
||||
std::string falco_common::format_priority(priority_type v, bool shortfmt) {
|
||||
std::string out;
|
||||
if(!format_priority(v, out, shortfmt))
|
||||
{
|
||||
if(!format_priority(v, out, shortfmt)) {
|
||||
throw falco_exception("Unknown priority enum value: " + std::to_string(v));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
bool falco_common::parse_rule_matching(const std::string& v, rule_matching& out)
|
||||
{
|
||||
for (size_t i = 0; i < rule_matching_names.size(); i++)
|
||||
{
|
||||
if (!strcasecmp(v.c_str(), rule_matching_names[i].c_str()))
|
||||
{
|
||||
out = (rule_matching) i;
|
||||
bool falco_common::parse_rule_matching(const std::string& v, rule_matching& out) {
|
||||
for(size_t i = 0; i < rule_matching_names.size(); i++) {
|
||||
if(!strcasecmp(v.c_str(), rule_matching_names[i].c_str())) {
|
||||
out = (rule_matching)i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,41 +36,34 @@ limitations under the License.
|
||||
// be of this type.
|
||||
//
|
||||
|
||||
struct falco_exception : std::runtime_error
|
||||
{
|
||||
struct falco_exception : std::runtime_error {
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
namespace falco_common
|
||||
{
|
||||
namespace falco_common {
|
||||
|
||||
const std::string syscall_source = sinsp_syscall_event_source_name;
|
||||
const std::string syscall_source = sinsp_syscall_event_source_name;
|
||||
|
||||
// Same as numbers/indices into the above vector
|
||||
enum priority_type
|
||||
{
|
||||
PRIORITY_EMERGENCY = 0,
|
||||
PRIORITY_ALERT = 1,
|
||||
PRIORITY_CRITICAL = 2,
|
||||
PRIORITY_ERROR = 3,
|
||||
PRIORITY_WARNING = 4,
|
||||
PRIORITY_NOTICE = 5,
|
||||
PRIORITY_INFORMATIONAL = 6,
|
||||
PRIORITY_DEBUG = 7
|
||||
};
|
||||
|
||||
bool parse_priority(const std::string& v, priority_type& out);
|
||||
priority_type parse_priority(const std::string& v);
|
||||
bool format_priority(priority_type v, std::string& out, bool shortfmt=false);
|
||||
std::string format_priority(priority_type v, bool shortfmt=false);
|
||||
|
||||
enum rule_matching
|
||||
{
|
||||
FIRST = 0,
|
||||
ALL = 1
|
||||
};
|
||||
|
||||
bool parse_rule_matching(const std::string& v, rule_matching& out);
|
||||
// Same as numbers/indices into the above vector
|
||||
enum priority_type {
|
||||
PRIORITY_EMERGENCY = 0,
|
||||
PRIORITY_ALERT = 1,
|
||||
PRIORITY_CRITICAL = 2,
|
||||
PRIORITY_ERROR = 3,
|
||||
PRIORITY_WARNING = 4,
|
||||
PRIORITY_NOTICE = 5,
|
||||
PRIORITY_INFORMATIONAL = 6,
|
||||
PRIORITY_DEBUG = 7
|
||||
};
|
||||
|
||||
bool parse_priority(const std::string& v, priority_type& out);
|
||||
priority_type parse_priority(const std::string& v);
|
||||
bool format_priority(priority_type v, std::string& out, bool shortfmt = false);
|
||||
std::string format_priority(priority_type v, bool shortfmt = false);
|
||||
|
||||
enum rule_matching { FIRST = 0, ALL = 1 };
|
||||
|
||||
bool parse_rule_matching(const std::string& v, rule_matching& out);
|
||||
}; // namespace falco_common
|
||||
|
||||
typedef std::unordered_map<std::string, std::pair<std::string, bool>> extra_output_field_t;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -41,10 +41,9 @@ limitations under the License.
|
||||
// handled in a separate class falco_outputs.
|
||||
//
|
||||
|
||||
class falco_engine
|
||||
{
|
||||
class falco_engine {
|
||||
public:
|
||||
explicit falco_engine(bool seed_rng=true);
|
||||
explicit falco_engine(bool seed_rng = true);
|
||||
virtual ~falco_engine();
|
||||
|
||||
// A given engine has a version which identifies the fields
|
||||
@@ -55,10 +54,9 @@ public:
|
||||
|
||||
// Engine version used to be represented as a simple progressive
|
||||
// number. With the new semver schema, the number now represents
|
||||
// the semver minor number. This function converts the legacy version
|
||||
// the semver minor number. This function converts the legacy version
|
||||
// number to the new semver schema.
|
||||
static inline sinsp_version get_implicit_version(uint32_t minor)
|
||||
{
|
||||
static inline sinsp_version get_implicit_version(uint32_t minor) {
|
||||
return rule_loader::reader::get_implicit_engine_version(minor);
|
||||
}
|
||||
|
||||
@@ -80,7 +78,8 @@ public:
|
||||
//
|
||||
// Load rules and returns a result object.
|
||||
//
|
||||
std::unique_ptr<falco::load_result> load_rules(const std::string &rules_content, const std::string &name);
|
||||
std::unique_ptr<falco::load_result> load_rules(const std::string &rules_content,
|
||||
const std::string &name);
|
||||
|
||||
//
|
||||
// Enable/Disable any rules matching the provided substring.
|
||||
@@ -91,30 +90,42 @@ public:
|
||||
// for different sets of rules being active at once.
|
||||
// The rules are matched against the rulesets of all the defined sources.
|
||||
//
|
||||
void enable_rule(const std::string &substring, bool enabled, const std::string &ruleset = s_default_ruleset);
|
||||
void enable_rule(const std::string &substring,
|
||||
bool enabled,
|
||||
const std::string &ruleset = s_default_ruleset);
|
||||
|
||||
// Same as above but providing a ruleset id instead
|
||||
void enable_rule(const std::string &substring, bool enabled, const uint16_t ruleset_id);
|
||||
|
||||
// Like enable_rule, but the rule name must be an exact match.
|
||||
void enable_rule_exact(const std::string &rule_name, bool enabled, const std::string &ruleset = s_default_ruleset);
|
||||
void enable_rule_exact(const std::string &rule_name,
|
||||
bool enabled,
|
||||
const std::string &ruleset = s_default_ruleset);
|
||||
|
||||
// Same as above but providing a ruleset id instead
|
||||
void enable_rule_exact(const std::string &rule_name, bool enabled, const uint16_t ruleset_id);
|
||||
|
||||
// Like enable_rule, but wildcards are supported and substrings are not matched
|
||||
void enable_rule_wildcard(const std::string &rule_name, bool enabled, const std::string &ruleset = s_default_ruleset);
|
||||
void enable_rule_wildcard(const std::string &rule_name,
|
||||
bool enabled,
|
||||
const std::string &ruleset = s_default_ruleset);
|
||||
|
||||
// Same as above but providing a ruleset id instead
|
||||
void enable_rule_wildcard(const std::string &rule_name, bool enabled, const uint16_t ruleset_id);
|
||||
void enable_rule_wildcard(const std::string &rule_name,
|
||||
bool enabled,
|
||||
const uint16_t ruleset_id);
|
||||
|
||||
//
|
||||
// Enable/Disable any rules with any of the provided tags (set, exact matches only)
|
||||
//
|
||||
void enable_rule_by_tag(const std::set<std::string> &tags, bool enabled, const std::string &ruleset = s_default_ruleset);
|
||||
void enable_rule_by_tag(const std::set<std::string> &tags,
|
||||
bool enabled,
|
||||
const std::string &ruleset = s_default_ruleset);
|
||||
|
||||
// Same as above but providing a ruleset id instead
|
||||
void enable_rule_by_tag(const std::set<std::string> &tags, bool enabled, const uint16_t ruleset_id);
|
||||
void enable_rule_by_tag(const std::set<std::string> &tags,
|
||||
bool enabled,
|
||||
const uint16_t ruleset_id);
|
||||
|
||||
//
|
||||
// Must be called after the engine has been configured and all rulesets
|
||||
@@ -147,12 +158,13 @@ public:
|
||||
// Print details on the given rule. If rule is NULL, print
|
||||
// details on all rules.
|
||||
//
|
||||
nlohmann::json describe_rule(std::string *rule_name, const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
|
||||
nlohmann::json describe_rule(std::string *rule_name,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>> &plugins) const;
|
||||
|
||||
//
|
||||
// Return const /ref to rules stored in the Falco engine.
|
||||
//
|
||||
inline const indexed_vector<falco_rule>& get_rules() const { return m_rules; }
|
||||
inline const indexed_vector<falco_rule> &get_rules() const { return m_rules; }
|
||||
|
||||
//
|
||||
// Print statistics on how many events matched each rule.
|
||||
@@ -160,9 +172,10 @@ public:
|
||||
void print_stats() const;
|
||||
|
||||
//
|
||||
// Return const /ref to stats_manager to access current rules stats (how many events matched each rule so far).
|
||||
// Return const /ref to stats_manager to access current rules stats (how many events matched
|
||||
// each rule so far).
|
||||
//
|
||||
const stats_manager& get_rule_stats_manager() const;
|
||||
const stats_manager &get_rule_stats_manager() const;
|
||||
|
||||
//
|
||||
// Set the sampling ratio, which can affect which events are
|
||||
@@ -183,33 +196,27 @@ public:
|
||||
// add k8s/container information to outputs when
|
||||
// available.
|
||||
//
|
||||
void add_extra_output_format(
|
||||
const std::string &format,
|
||||
const std::string &source,
|
||||
const std::set<std::string> &tags,
|
||||
const std::string &rule,
|
||||
bool replace_container_info
|
||||
);
|
||||
void add_extra_output_format(const std::string &format,
|
||||
const std::string &source,
|
||||
const std::set<std::string> &tags,
|
||||
const std::string &rule,
|
||||
bool replace_container_info);
|
||||
|
||||
// You can optionally add fields that will only show up in the object
|
||||
// output (e.g. json, gRPC) alongside other output_fields
|
||||
// and not in the text message output.
|
||||
// You can add two types of fields: formatted which will act like
|
||||
// an additional output format that appears in the output field
|
||||
void add_extra_output_formatted_field(
|
||||
const std::string &key,
|
||||
const std::string &format,
|
||||
const std::string &source,
|
||||
const std::set<std::string> &tags,
|
||||
const std::string &rule
|
||||
);
|
||||
void add_extra_output_formatted_field(const std::string &key,
|
||||
const std::string &format,
|
||||
const std::string &source,
|
||||
const std::set<std::string> &tags,
|
||||
const std::string &rule);
|
||||
|
||||
void add_extra_output_raw_field(
|
||||
const std::string &key,
|
||||
const std::string &source,
|
||||
const std::set<std::string> &tags,
|
||||
const std::string &rule
|
||||
);
|
||||
void add_extra_output_raw_field(const std::string &key,
|
||||
const std::string &source,
|
||||
const std::set<std::string> &tags,
|
||||
const std::string &rule);
|
||||
|
||||
// Represents the result of matching an event against a set of
|
||||
// rules.
|
||||
@@ -249,7 +256,9 @@ public:
|
||||
// concurrently with the same source_idx would inherently cause data races
|
||||
// and lead to undefined behavior.
|
||||
std::unique_ptr<std::vector<rule_result>> process_event(std::size_t source_idx,
|
||||
sinsp_evt *ev, uint16_t ruleset_id, falco_common::rule_matching strategy);
|
||||
sinsp_evt *ev,
|
||||
uint16_t ruleset_id,
|
||||
falco_common::rule_matching strategy);
|
||||
|
||||
//
|
||||
// Wrapper assuming the default ruleset.
|
||||
@@ -257,7 +266,8 @@ public:
|
||||
// This inherits the same thread-safety guarantees.
|
||||
//
|
||||
std::unique_ptr<std::vector<rule_result>> process_event(std::size_t source_idx,
|
||||
sinsp_evt *ev, falco_common::rule_matching strategy);
|
||||
sinsp_evt *ev,
|
||||
falco_common::rule_matching strategy);
|
||||
|
||||
//
|
||||
// Configure the engine to support events with the provided
|
||||
@@ -265,17 +275,17 @@ public:
|
||||
// Return source index for fast lookup.
|
||||
//
|
||||
std::size_t add_source(const std::string &source,
|
||||
std::shared_ptr<sinsp_filter_factory> filter_factory,
|
||||
std::shared_ptr<sinsp_evt_formatter_factory> formatter_factory);
|
||||
std::shared_ptr<sinsp_filter_factory> filter_factory,
|
||||
std::shared_ptr<sinsp_evt_formatter_factory> formatter_factory);
|
||||
|
||||
//
|
||||
// Equivalent to above, but allows specifying a ruleset factory
|
||||
// for the newly added source.
|
||||
//
|
||||
std::size_t add_source(const std::string &source,
|
||||
std::shared_ptr<sinsp_filter_factory> filter_factory,
|
||||
std::shared_ptr<sinsp_evt_formatter_factory> formatter_factory,
|
||||
std::shared_ptr<filter_ruleset_factory> ruleset_factory);
|
||||
std::shared_ptr<sinsp_filter_factory> filter_factory,
|
||||
std::shared_ptr<sinsp_evt_formatter_factory> formatter_factory,
|
||||
std::shared_ptr<filter_ruleset_factory> ruleset_factory);
|
||||
|
||||
// Return whether or not there is a valid filter/formatter
|
||||
// factory for this source.
|
||||
@@ -285,25 +295,27 @@ public:
|
||||
// Given a source, return a formatter factory that can create
|
||||
// filters for events of that source.
|
||||
//
|
||||
std::shared_ptr<sinsp_filter_factory> filter_factory_for_source(const std::string& source);
|
||||
std::shared_ptr<sinsp_filter_factory> filter_factory_for_source(const std::string &source);
|
||||
std::shared_ptr<sinsp_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<sinsp_evt_formatter_factory> formatter_factory_for_source(const std::string& source);
|
||||
std::shared_ptr<sinsp_evt_formatter_factory> formatter_factory_for_source(std::size_t source_idx);
|
||||
std::shared_ptr<sinsp_evt_formatter_factory> formatter_factory_for_source(
|
||||
const std::string &source);
|
||||
std::shared_ptr<sinsp_evt_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(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(const std::string &source);
|
||||
std::shared_ptr<filter_ruleset> ruleset_for_source(std::size_t source_idx);
|
||||
|
||||
//
|
||||
@@ -314,24 +326,24 @@ public:
|
||||
// todo(jasondellaluce): remove this in future code refactors
|
||||
//
|
||||
void evttypes_for_ruleset(const std::string &source,
|
||||
std::set<uint16_t> &evttypes,
|
||||
const std::string &ruleset = s_default_ruleset);
|
||||
std::set<uint16_t> &evttypes,
|
||||
const std::string &ruleset = s_default_ruleset);
|
||||
|
||||
//
|
||||
// Given an event source and ruleset, return the set of ppm_sc_codes
|
||||
// for which this ruleset can run and match events.
|
||||
//
|
||||
libsinsp::events::set<ppm_sc_code> sc_codes_for_ruleset(
|
||||
const std::string &source,
|
||||
const std::string &ruleset = s_default_ruleset);
|
||||
|
||||
const std::string &source,
|
||||
const std::string &ruleset = s_default_ruleset);
|
||||
|
||||
//
|
||||
// Given an event source and ruleset, return the set of ppm_event_codes
|
||||
// for which this ruleset can run and match events.
|
||||
//
|
||||
libsinsp::events::set<ppm_event_code> event_codes_for_ruleset(
|
||||
const std::string &source,
|
||||
const std::string &ruleset = s_default_ruleset);
|
||||
const std::string &source,
|
||||
const std::string &ruleset = s_default_ruleset);
|
||||
|
||||
//
|
||||
// Given a source and output string, return an
|
||||
@@ -339,7 +351,7 @@ public:
|
||||
// event.
|
||||
//
|
||||
std::shared_ptr<sinsp_evt_formatter> create_formatter(const std::string &source,
|
||||
const std::string &output) const;
|
||||
const std::string &output) const;
|
||||
|
||||
// The rule loader definition is aliased as it is exactly what we need
|
||||
typedef rule_loader::plugin_version_info::requirement plugin_version_requirement;
|
||||
@@ -351,49 +363,42 @@ public:
|
||||
// the name of the plugin and the second element is its version.
|
||||
// If false is returned, err is filled with error causing the check failure.
|
||||
//
|
||||
bool check_plugin_requirements(
|
||||
const std::vector<plugin_version_requirement>& plugins,
|
||||
std::string& err) const;
|
||||
bool check_plugin_requirements(const std::vector<plugin_version_requirement> &plugins,
|
||||
std::string &err) const;
|
||||
|
||||
nlohmann::json m_rule_schema;
|
||||
|
||||
private:
|
||||
// Create a ruleset using the provided factory and set the
|
||||
// engine state funcs for it.
|
||||
std::shared_ptr<filter_ruleset> create_ruleset(std::shared_ptr<filter_ruleset_factory>& ruleset_factory);
|
||||
std::shared_ptr<filter_ruleset> create_ruleset(
|
||||
std::shared_ptr<filter_ruleset_factory> &ruleset_factory);
|
||||
|
||||
// Functions to retrieve state from this engine
|
||||
void fill_engine_state_funcs(filter_ruleset::engine_state_funcs& engine_state);
|
||||
void fill_engine_state_funcs(filter_ruleset::engine_state_funcs &engine_state);
|
||||
|
||||
filter_ruleset::engine_state_funcs m_engine_state;
|
||||
|
||||
// Throws falco_exception if the file can not be read
|
||||
void read_file(const std::string& filename, std::string& contents);
|
||||
void read_file(const std::string &filename, std::string &contents);
|
||||
|
||||
indexed_vector<falco_source> m_sources;
|
||||
|
||||
inline const falco_source* find_source(std::size_t index)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if(!m_syscall_source) {
|
||||
throw falco_exception("Unknown event source index " + std::to_string(index));
|
||||
}
|
||||
}
|
||||
|
||||
source = m_syscall_source;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
source = m_sources.at(index);
|
||||
if(!source)
|
||||
{
|
||||
if(!source) {
|
||||
throw falco_exception("Unknown event source index " + std::to_string(index));
|
||||
}
|
||||
}
|
||||
@@ -401,11 +406,9 @@ private:
|
||||
return source;
|
||||
}
|
||||
|
||||
inline const falco_source* find_source(const std::string& name) const
|
||||
{
|
||||
inline const falco_source *find_source(const std::string &name) const {
|
||||
auto ret = m_sources.at(name);
|
||||
if(!ret)
|
||||
{
|
||||
if(!ret) {
|
||||
throw falco_exception("Unknown event source " + name);
|
||||
}
|
||||
return ret;
|
||||
@@ -414,7 +417,7 @@ private:
|
||||
// To allow the engine to be extremely fast for syscalls (can
|
||||
// be > 1M events/sec), we save the syscall source/source_idx
|
||||
// separately and check it explicitly in process_event()
|
||||
const falco_source* m_syscall_source;
|
||||
const falco_source *m_syscall_source;
|
||||
std::atomic<size_t> m_syscall_source_idx;
|
||||
|
||||
//
|
||||
@@ -425,31 +428,26 @@ private:
|
||||
inline bool should_drop_evt() const;
|
||||
|
||||
// Retrieve json details from rules, macros, lists
|
||||
void get_json_details(
|
||||
nlohmann::json& out,
|
||||
const falco_rule& r,
|
||||
const rule_loader::rule_info& info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
|
||||
void get_json_details(
|
||||
nlohmann::json& out,
|
||||
const falco_macro& m,
|
||||
const rule_loader::macro_info& info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
|
||||
void get_json_details(
|
||||
nlohmann::json& out,
|
||||
const falco_list& l,
|
||||
const rule_loader::list_info& info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
|
||||
void get_json_evt_types(
|
||||
nlohmann::json& out,
|
||||
const std::string& source,
|
||||
libsinsp::filter::ast::expr* ast) const;
|
||||
void get_json_used_plugins(
|
||||
nlohmann::json& out,
|
||||
const std::string& source,
|
||||
const std::unordered_set<std::string>& evttypes,
|
||||
const std::unordered_set<std::string>& fields,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
|
||||
void get_json_details(nlohmann::json &out,
|
||||
const falco_rule &r,
|
||||
const rule_loader::rule_info &info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>> &plugins) const;
|
||||
void get_json_details(nlohmann::json &out,
|
||||
const falco_macro &m,
|
||||
const rule_loader::macro_info &info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>> &plugins) const;
|
||||
void get_json_details(nlohmann::json &out,
|
||||
const falco_list &l,
|
||||
const rule_loader::list_info &info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>> &plugins) const;
|
||||
void get_json_evt_types(nlohmann::json &out,
|
||||
const std::string &source,
|
||||
libsinsp::filter::ast::expr *ast) const;
|
||||
void get_json_used_plugins(nlohmann::json &out,
|
||||
const std::string &source,
|
||||
const std::unordered_set<std::string> &evttypes,
|
||||
const std::unordered_set<std::string> &fields,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>> &plugins) const;
|
||||
|
||||
indexed_vector<falco_rule> m_rules;
|
||||
std::shared_ptr<rule_loader::reader> m_rule_reader;
|
||||
|
||||
@@ -23,14 +23,16 @@ limitations under the License.
|
||||
#define FALCO_ENGINE_VERSION_MINOR 43
|
||||
#define FALCO_ENGINE_VERSION_PATCH 0
|
||||
|
||||
#define FALCO_ENGINE_VERSION \
|
||||
__FALCO_ENGINE_STRINGIFY(FALCO_ENGINE_VERSION_MAJOR) "." \
|
||||
__FALCO_ENGINE_STRINGIFY(FALCO_ENGINE_VERSION_MINOR) "." \
|
||||
__FALCO_ENGINE_STRINGIFY(FALCO_ENGINE_VERSION_PATCH)
|
||||
#define FALCO_ENGINE_VERSION \
|
||||
__FALCO_ENGINE_STRINGIFY(FALCO_ENGINE_VERSION_MAJOR) \
|
||||
"." __FALCO_ENGINE_STRINGIFY(FALCO_ENGINE_VERSION_MINOR) "." __FALCO_ENGINE_STRINGIFY( \
|
||||
FALCO_ENGINE_VERSION_PATCH)
|
||||
|
||||
// This is the result of running the following command:
|
||||
// FALCO="falco -c ./falco.yaml"
|
||||
// echo $($FALCO --version | grep 'Engine:' | awk '{print $2}') $(echo $($FALCO --version | grep 'Schema version:' | awk '{print $3}') $($FALCO --list --markdown | grep '^`' | sort) $($FALCO --list-events | sort) | sha256sum)
|
||||
// echo $($FALCO --version | grep 'Engine:' | awk '{print $2}') $(echo $($FALCO --version | grep
|
||||
// 'Schema version:' | awk '{print $3}') $($FALCO --list --markdown | grep '^`' | sort) $($FALCO
|
||||
// --list-events | sort) | sha256sum)
|
||||
// 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.
|
||||
|
||||
@@ -17,113 +17,110 @@ limitations under the License.
|
||||
|
||||
#include "falco_load_result.h"
|
||||
|
||||
static const std::string error_codes[] = {
|
||||
"LOAD_ERR_FILE_READ",
|
||||
"LOAD_ERR_YAML_PARSE",
|
||||
"LOAD_ERR_YAML_VALIDATE",
|
||||
"LOAD_ERR_COMPILE_CONDITION",
|
||||
"LOAD_ERR_COMPILE_OUTPUT",
|
||||
"LOAD_ERR_VALIDATE",
|
||||
"LOAD_ERR_EXTENSION"
|
||||
};
|
||||
static const std::string error_codes[] = {"LOAD_ERR_FILE_READ",
|
||||
"LOAD_ERR_YAML_PARSE",
|
||||
"LOAD_ERR_YAML_VALIDATE",
|
||||
"LOAD_ERR_COMPILE_CONDITION",
|
||||
"LOAD_ERR_COMPILE_OUTPUT",
|
||||
"LOAD_ERR_VALIDATE",
|
||||
"LOAD_ERR_EXTENSION"};
|
||||
|
||||
const std::string& falco::load_result::error_code_str(error_code ec)
|
||||
{
|
||||
const std::string& falco::load_result::error_code_str(error_code ec) {
|
||||
return error_codes[ec];
|
||||
}
|
||||
|
||||
static const std::string error_strings[] = {
|
||||
"File read error",
|
||||
"YAML parse error",
|
||||
"Error validating internal structure of YAML file",
|
||||
"Error compiling condition",
|
||||
"Error compiling output",
|
||||
"Error validating rule/macro/list/exception objects",
|
||||
"Error in extension item"
|
||||
};
|
||||
static const std::string error_strings[] = {"File read error",
|
||||
"YAML parse error",
|
||||
"Error validating internal structure of YAML file",
|
||||
"Error compiling condition",
|
||||
"Error compiling output",
|
||||
"Error validating rule/macro/list/exception objects",
|
||||
"Error in extension item"};
|
||||
|
||||
const std::string& falco::load_result::error_str(error_code ec)
|
||||
{
|
||||
const std::string& falco::load_result::error_str(error_code ec) {
|
||||
return error_strings[ec];
|
||||
}
|
||||
|
||||
static const std::string error_descs[] = {
|
||||
"This occurs when falco can not read a given file. Check permissions and whether the file exists.",
|
||||
"This occurs when the rules content is not valid YAML.",
|
||||
"This occurs when the internal structure of the YAML file is incorrect. Examples include not consisting of a sequence of maps, a given rule/macro/list item not having required keys, values not having the right type (e.g. the items property of a list not being a sequence), etc.",
|
||||
"This occurs when a condition string can not be compiled to a filter object.",
|
||||
"This occurs when an output string can not be compiled to an output object.",
|
||||
"This occurs when a rule/macro/list item is incorrect. Examples include a condition field referring to an undefined macro, falco engine/plugin version mismatches, items with append without any existing item, exception fields/comps having different lengths, etc.",
|
||||
"This occurs when there is an error in an extension item"
|
||||
};
|
||||
"This occurs when falco can not read a given file. Check permissions and whether the file "
|
||||
"exists.",
|
||||
"This occurs when the rules content is not valid YAML.",
|
||||
"This occurs when the internal structure of the YAML file is incorrect. Examples include "
|
||||
"not consisting of a sequence of maps, a given rule/macro/list item not having required "
|
||||
"keys, values not having the right type (e.g. the items property of a list not being a "
|
||||
"sequence), etc.",
|
||||
"This occurs when a condition string can not be compiled to a filter object.",
|
||||
"This occurs when an output string can not be compiled to an output object.",
|
||||
"This occurs when a rule/macro/list item is incorrect. Examples include a condition field "
|
||||
"referring to an undefined macro, falco engine/plugin version mismatches, items with "
|
||||
"append without any existing item, exception fields/comps having different lengths, etc.",
|
||||
"This occurs when there is an error in an extension item"};
|
||||
|
||||
const std::string& falco::load_result::error_desc(error_code ec)
|
||||
{
|
||||
const std::string& falco::load_result::error_desc(error_code ec) {
|
||||
return error_strings[ec];
|
||||
}
|
||||
|
||||
static const std::string warning_codes[] = {
|
||||
"LOAD_UNKNOWN_SOURCE",
|
||||
"LOAD_UNSAFE_NA_CHECK",
|
||||
"LOAD_NO_EVTTYPE",
|
||||
"LOAD_UNKNOWN_FILTER",
|
||||
"LOAD_UNUSED_MACRO",
|
||||
"LOAD_UNUSED_LIST",
|
||||
"LOAD_UNKNOWN_ITEM",
|
||||
"LOAD_DEPRECATED_ITEM",
|
||||
"LOAD_WARNING_EXTENSION",
|
||||
"LOAD_APPEND_NO_VALUES",
|
||||
"LOAD_EXCEPTION_NAME_NOT_UNIQUE",
|
||||
"LOAD_INVALID_MACRO_NAME",
|
||||
"LOAD_INVALID_LIST_NAME",
|
||||
"LOAD_COMPILE_CONDITION"
|
||||
};
|
||||
static const std::string warning_codes[] = {"LOAD_UNKNOWN_SOURCE",
|
||||
"LOAD_UNSAFE_NA_CHECK",
|
||||
"LOAD_NO_EVTTYPE",
|
||||
"LOAD_UNKNOWN_FILTER",
|
||||
"LOAD_UNUSED_MACRO",
|
||||
"LOAD_UNUSED_LIST",
|
||||
"LOAD_UNKNOWN_ITEM",
|
||||
"LOAD_DEPRECATED_ITEM",
|
||||
"LOAD_WARNING_EXTENSION",
|
||||
"LOAD_APPEND_NO_VALUES",
|
||||
"LOAD_EXCEPTION_NAME_NOT_UNIQUE",
|
||||
"LOAD_INVALID_MACRO_NAME",
|
||||
"LOAD_INVALID_LIST_NAME",
|
||||
"LOAD_COMPILE_CONDITION"};
|
||||
|
||||
const std::string& falco::load_result::warning_code_str(warning_code wc)
|
||||
{
|
||||
const std::string& falco::load_result::warning_code_str(warning_code wc) {
|
||||
return warning_codes[wc];
|
||||
}
|
||||
|
||||
static const std::string warning_strings[] = {
|
||||
"Unknown event source",
|
||||
"Unsafe <NA> comparison in condition",
|
||||
"Condition has no event-type restriction",
|
||||
"Unknown field or event-type in condition or output",
|
||||
"Unused macro",
|
||||
"Unused list",
|
||||
"Unknown rules file item",
|
||||
"Used deprecated item",
|
||||
"Warning in extension item",
|
||||
"Overriding/appending with no values",
|
||||
"Multiple exceptions defined with the same name",
|
||||
"Invalid macro name",
|
||||
"Invalid list name",
|
||||
"Warning in rule condition"
|
||||
};
|
||||
static const std::string warning_strings[] = {"Unknown event source",
|
||||
"Unsafe <NA> comparison in condition",
|
||||
"Condition has no event-type restriction",
|
||||
"Unknown field or event-type in condition or output",
|
||||
"Unused macro",
|
||||
"Unused list",
|
||||
"Unknown rules file item",
|
||||
"Used deprecated item",
|
||||
"Warning in extension item",
|
||||
"Overriding/appending with no values",
|
||||
"Multiple exceptions defined with the same name",
|
||||
"Invalid macro name",
|
||||
"Invalid list name",
|
||||
"Warning in rule condition"};
|
||||
|
||||
const std::string& falco::load_result::warning_str(warning_code wc)
|
||||
{
|
||||
const std::string& falco::load_result::warning_str(warning_code wc) {
|
||||
return warning_strings[wc];
|
||||
}
|
||||
|
||||
static const std::string warning_descs[] = {
|
||||
"A rule has a unknown event source. This can occur when reading rules content without having a corresponding plugin loaded, etc. The rule will be silently ignored.",
|
||||
"Comparing a field value with <NA> is unsafe and can lead to unpredictable behavior of the rule condition. If you need to check for the existence of a field, consider using the 'exists' operator instead.",
|
||||
"A rule condition matches too many evt.type values. This has a significant performance penalty. Make the condition more specific by adding an evt.type field or further restricting the number of evt.type values in the condition.",
|
||||
"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.",
|
||||
"A deprecated item is employed by lists, macros, or rules.",
|
||||
"An extension item has a warning",
|
||||
"A rule exception is overriding/appending with no values",
|
||||
"A rule is defining multiple exceptions with the same name",
|
||||
"A macro is defined with an invalid name",
|
||||
"A list is defined with an invalid name",
|
||||
"A rule condition or output have been parsed with a warning"
|
||||
};
|
||||
"A rule has a unknown event source. This can occur when reading rules content without "
|
||||
"having a corresponding plugin loaded, etc. The rule will be silently ignored.",
|
||||
"Comparing a field value with <NA> is unsafe and can lead to unpredictable behavior of the "
|
||||
"rule condition. If you need to check for the existence of a field, consider using the "
|
||||
"'exists' operator instead.",
|
||||
"A rule condition matches too many evt.type values. This has a significant performance "
|
||||
"penalty. Make the condition more specific by adding an evt.type field or further "
|
||||
"restricting the number of evt.type values in the condition.",
|
||||
"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.",
|
||||
"A deprecated item is employed by lists, macros, or rules.",
|
||||
"An extension item has a warning",
|
||||
"A rule exception is overriding/appending with no values",
|
||||
"A rule is defining multiple exceptions with the same name",
|
||||
"A macro is defined with an invalid name",
|
||||
"A list is defined with an invalid name",
|
||||
"A rule condition or output have been parsed with a warning"};
|
||||
|
||||
const std::string& falco::load_result::warning_desc(warning_code wc)
|
||||
{
|
||||
const std::string& falco::load_result::warning_desc(warning_code wc) {
|
||||
return warning_descs[wc];
|
||||
}
|
||||
|
||||
@@ -21,13 +21,11 @@ limitations under the License.
|
||||
#include <string>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace falco
|
||||
{
|
||||
namespace falco {
|
||||
|
||||
// Represents the result of loading a rules file.
|
||||
class load_result {
|
||||
public:
|
||||
|
||||
enum error_code {
|
||||
LOAD_ERR_FILE_READ = 0,
|
||||
LOAD_ERR_YAML_PARSE,
|
||||
@@ -121,4 +119,4 @@ public:
|
||||
virtual const nlohmann::json& as_json(const rules_contents_t& contents) = 0;
|
||||
};
|
||||
|
||||
} // namespace falco
|
||||
} // namespace falco
|
||||
|
||||
@@ -24,16 +24,15 @@ limitations under the License.
|
||||
#include <libsinsp/filter/ast.h>
|
||||
|
||||
/*!
|
||||
\brief Represents a list in the Falco Engine.
|
||||
The rule ID must be unique across all the lists loaded in the engine.
|
||||
\brief Represents a list in the Falco Engine.
|
||||
The rule ID must be unique across all the lists loaded in the engine.
|
||||
*/
|
||||
struct falco_list
|
||||
{
|
||||
falco_list(): used(false), id(0) { }
|
||||
struct falco_list {
|
||||
falco_list(): used(false), id(0) {}
|
||||
falco_list(falco_list&&) = default;
|
||||
falco_list& operator = (falco_list&&) = default;
|
||||
falco_list& operator=(falco_list&&) = default;
|
||||
falco_list(const falco_list&) = default;
|
||||
falco_list& operator = (const falco_list&) = default;
|
||||
falco_list& operator=(const falco_list&) = default;
|
||||
~falco_list() = default;
|
||||
|
||||
bool used;
|
||||
@@ -43,16 +42,15 @@ struct falco_list
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Represents a macro in the Falco Engine.
|
||||
The rule ID must be unique across all the macros loaded in the engine.
|
||||
\brief Represents a macro in the Falco Engine.
|
||||
The rule ID must be unique across all the macros loaded in the engine.
|
||||
*/
|
||||
struct falco_macro
|
||||
{
|
||||
falco_macro(): used(false), id(0) { }
|
||||
struct falco_macro {
|
||||
falco_macro(): used(false), id(0) {}
|
||||
falco_macro(falco_macro&&) = default;
|
||||
falco_macro& operator = (falco_macro&&) = default;
|
||||
falco_macro& operator=(falco_macro&&) = default;
|
||||
falco_macro(const falco_macro&) = default;
|
||||
falco_macro& operator = (const falco_macro&) = default;
|
||||
falco_macro& operator=(const falco_macro&) = default;
|
||||
~falco_macro() = default;
|
||||
|
||||
bool used;
|
||||
@@ -62,16 +60,15 @@ struct falco_macro
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Represents a rule in the Falco Engine.
|
||||
The rule ID must be unique across all the rules loaded in the engine.
|
||||
\brief Represents a rule in the Falco Engine.
|
||||
The rule ID must be unique across all the rules loaded in the engine.
|
||||
*/
|
||||
struct falco_rule
|
||||
{
|
||||
struct falco_rule {
|
||||
falco_rule(): id(0), priority(falco_common::PRIORITY_DEBUG) {}
|
||||
falco_rule(falco_rule&&) = default;
|
||||
falco_rule& operator = (falco_rule&&) = default;
|
||||
falco_rule& operator=(falco_rule&&) = default;
|
||||
falco_rule(const falco_rule&) = default;
|
||||
falco_rule& operator = (const falco_rule&) = default;
|
||||
falco_rule& operator=(const falco_rule&) = default;
|
||||
~falco_rule() = default;
|
||||
|
||||
std::size_t id;
|
||||
|
||||
@@ -21,23 +21,21 @@ limitations under the License.
|
||||
#include "filter_ruleset.h"
|
||||
|
||||
/*!
|
||||
\brief Represents a given data source used by the engine.
|
||||
The ruleset of a source should be created through the ruleset factory
|
||||
of the same data source.
|
||||
\brief Represents a given data source used by the engine.
|
||||
The ruleset of a source should be created through the ruleset factory
|
||||
of the same data source.
|
||||
*/
|
||||
struct falco_source
|
||||
{
|
||||
struct falco_source {
|
||||
falco_source() = default;
|
||||
falco_source(falco_source&&) = default;
|
||||
falco_source& operator = (falco_source&&) = default;
|
||||
falco_source& operator=(falco_source&&) = default;
|
||||
falco_source(const falco_source& s):
|
||||
name(s.name),
|
||||
ruleset(s.ruleset),
|
||||
ruleset_factory(s.ruleset_factory),
|
||||
filter_factory(s.filter_factory),
|
||||
formatter_factory(s.formatter_factory) { };
|
||||
falco_source& operator = (const falco_source& s)
|
||||
{
|
||||
name(s.name),
|
||||
ruleset(s.ruleset),
|
||||
ruleset_factory(s.ruleset_factory),
|
||||
filter_factory(s.filter_factory),
|
||||
formatter_factory(s.formatter_factory) {};
|
||||
falco_source& operator=(const falco_source& s) {
|
||||
name = s.name;
|
||||
ruleset = s.ruleset;
|
||||
ruleset_factory = s.ruleset_factory;
|
||||
@@ -56,24 +54,19 @@ struct falco_source
|
||||
// matches an event.
|
||||
mutable std::vector<falco_rule> m_rules;
|
||||
|
||||
inline bool is_valid_lhs_field(const std::string& field) const
|
||||
{
|
||||
inline bool is_valid_lhs_field(const std::string& field) const {
|
||||
// if there's at least one parenthesis we may be parsing a field
|
||||
// wrapped inside one or more transformers. In those cases, the most
|
||||
// rigorous analysis we can do is compiling a simple filter using
|
||||
// the field as left-hand side of a comparison, and see if any error
|
||||
// occurs.
|
||||
if (field.find('(') != std::string::npos)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(field.find('(') != std::string::npos) {
|
||||
try {
|
||||
auto filter = field;
|
||||
filter.append(" exists");
|
||||
sinsp_filter_compiler(filter_factory, filter).compile();
|
||||
return true;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
} catch(...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,19 +30,22 @@ limitations under the License.
|
||||
#include <iomanip>
|
||||
#include <thread>
|
||||
|
||||
#define RGX_PROMETHEUS_TIME_DURATION "^((?P<y>[0-9]+)y)?((?P<w>[0-9]+)w)?((?P<d>[0-9]+)d)?((?P<h>[0-9]+)h)?((?P<m>[0-9]+)m)?((?P<s>[0-9]+)s)?((?P<ms>[0-9]+)ms)?$"
|
||||
#define RGX_PROMETHEUS_TIME_DURATION \
|
||||
"^((?P<y>[0-9]+)y)?((?P<w>[0-9]+)w)?((?P<d>[0-9]+)d)?((?P<h>[0-9]+)h)?((?P<m>[0-9]+)m)?((?P<" \
|
||||
"s>[0-9]+)s)?((?P<ms>[0-9]+)ms)?$"
|
||||
|
||||
// using pre-compiled regex
|
||||
static re2::RE2 s_rgx_prometheus_time_duration(RGX_PROMETHEUS_TIME_DURATION);
|
||||
|
||||
// Prometheus time durations: https://prometheus.io/docs/prometheus/latest/querying/basics/#time-durations
|
||||
#define PROMETHEUS_UNIT_Y "y" ///> assuming a year has always 365d
|
||||
#define PROMETHEUS_UNIT_W "w" ///> assuming a week has always 7d
|
||||
#define PROMETHEUS_UNIT_D "d" ///> assuming a day has always 24h
|
||||
#define PROMETHEUS_UNIT_H "h" ///> hour
|
||||
#define PROMETHEUS_UNIT_M "m" ///> minute
|
||||
#define PROMETHEUS_UNIT_S "s" ///> second
|
||||
#define PROMETHEUS_UNIT_MS "ms" ///> millisecond
|
||||
// Prometheus time durations:
|
||||
// https://prometheus.io/docs/prometheus/latest/querying/basics/#time-durations
|
||||
#define PROMETHEUS_UNIT_Y "y" ///> assuming a year has always 365d
|
||||
#define PROMETHEUS_UNIT_W "w" ///> assuming a week has always 7d
|
||||
#define PROMETHEUS_UNIT_D "d" ///> assuming a day has always 24h
|
||||
#define PROMETHEUS_UNIT_H "h" ///> hour
|
||||
#define PROMETHEUS_UNIT_M "m" ///> minute
|
||||
#define PROMETHEUS_UNIT_S "s" ///> second
|
||||
#define PROMETHEUS_UNIT_MS "ms" ///> millisecond
|
||||
|
||||
// standard time unit conversions to milliseconds
|
||||
#define ONE_MS_TO_MS 1UL
|
||||
@@ -53,20 +56,17 @@ static re2::RE2 s_rgx_prometheus_time_duration(RGX_PROMETHEUS_TIME_DURATION);
|
||||
#define ONE_WEEK_TO_MS ONE_DAY_TO_MS * 7UL
|
||||
#define ONE_YEAR_TO_MS ONE_DAY_TO_MS * 365UL
|
||||
|
||||
namespace falco
|
||||
{
|
||||
namespace falco {
|
||||
|
||||
namespace utils
|
||||
{
|
||||
namespace utils {
|
||||
|
||||
uint64_t parse_prometheus_interval(std::string interval_str)
|
||||
{
|
||||
uint64_t parse_prometheus_interval(std::string interval_str) {
|
||||
uint64_t interval = 0;
|
||||
/* Sanitize user input, remove possible whitespaces. */
|
||||
interval_str.erase(remove_if(interval_str.begin(), interval_str.end(), isspace), interval_str.end());
|
||||
interval_str.erase(remove_if(interval_str.begin(), interval_str.end(), isspace),
|
||||
interval_str.end());
|
||||
|
||||
if(!interval_str.empty())
|
||||
{
|
||||
if(!interval_str.empty()) {
|
||||
re2::StringPiece input(interval_str);
|
||||
std::string args[14];
|
||||
re2::RE2::Arg arg0(&args[0]);
|
||||
@@ -83,34 +83,52 @@ uint64_t parse_prometheus_interval(std::string interval_str)
|
||||
re2::RE2::Arg arg11(&args[11]);
|
||||
re2::RE2::Arg arg12(&args[12]);
|
||||
re2::RE2::Arg arg13(&args[13]);
|
||||
const re2::RE2::Arg* const matches[14] = {&arg0, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8, &arg9, &arg10, &arg11, &arg12, &arg13};
|
||||
const re2::RE2::Arg* const matches[14] = {&arg0,
|
||||
&arg1,
|
||||
&arg2,
|
||||
&arg3,
|
||||
&arg4,
|
||||
&arg5,
|
||||
&arg6,
|
||||
&arg7,
|
||||
&arg8,
|
||||
&arg9,
|
||||
&arg10,
|
||||
&arg11,
|
||||
&arg12,
|
||||
&arg13};
|
||||
|
||||
const std::map<std::string, int>& named_groups = s_rgx_prometheus_time_duration.NamedCapturingGroups();
|
||||
const std::map<std::string, int>& named_groups =
|
||||
s_rgx_prometheus_time_duration.NamedCapturingGroups();
|
||||
int num_groups = s_rgx_prometheus_time_duration.NumberOfCapturingGroups();
|
||||
re2::RE2::FullMatchN(input, s_rgx_prometheus_time_duration, matches, num_groups);
|
||||
|
||||
static const char* all_prometheus_units[7] = {
|
||||
PROMETHEUS_UNIT_Y, PROMETHEUS_UNIT_W, PROMETHEUS_UNIT_D, PROMETHEUS_UNIT_H,
|
||||
PROMETHEUS_UNIT_M, PROMETHEUS_UNIT_S, PROMETHEUS_UNIT_MS };
|
||||
static const char* all_prometheus_units[7] = {PROMETHEUS_UNIT_Y,
|
||||
PROMETHEUS_UNIT_W,
|
||||
PROMETHEUS_UNIT_D,
|
||||
PROMETHEUS_UNIT_H,
|
||||
PROMETHEUS_UNIT_M,
|
||||
PROMETHEUS_UNIT_S,
|
||||
PROMETHEUS_UNIT_MS};
|
||||
|
||||
static const uint64_t all_prometheus_time_conversions[7] = {
|
||||
ONE_YEAR_TO_MS, ONE_WEEK_TO_MS, ONE_DAY_TO_MS, ONE_HOUR_TO_MS,
|
||||
ONE_MINUTE_TO_MS, ONE_SECOND_TO_MS, ONE_MS_TO_MS };
|
||||
static const uint64_t all_prometheus_time_conversions[7] = {ONE_YEAR_TO_MS,
|
||||
ONE_WEEK_TO_MS,
|
||||
ONE_DAY_TO_MS,
|
||||
ONE_HOUR_TO_MS,
|
||||
ONE_MINUTE_TO_MS,
|
||||
ONE_SECOND_TO_MS,
|
||||
ONE_MS_TO_MS};
|
||||
|
||||
for(size_t i = 0; i < sizeof(all_prometheus_units) / sizeof(const char*); i++)
|
||||
{
|
||||
for(size_t i = 0; i < sizeof(all_prometheus_units) / sizeof(const char*); i++) {
|
||||
std::string cur_interval_str;
|
||||
uint64_t cur_interval = 0;
|
||||
const auto &group_it = named_groups.find(all_prometheus_units[i]);
|
||||
if(group_it != named_groups.end())
|
||||
{
|
||||
const auto& group_it = named_groups.find(all_prometheus_units[i]);
|
||||
if(group_it != named_groups.end()) {
|
||||
cur_interval_str = args[group_it->second - 1];
|
||||
if(!cur_interval_str.empty())
|
||||
{
|
||||
if(!cur_interval_str.empty()) {
|
||||
cur_interval = std::stoull(cur_interval_str, nullptr, 0);
|
||||
}
|
||||
if(cur_interval > 0)
|
||||
{
|
||||
if(cur_interval > 0) {
|
||||
interval += cur_interval * all_prometheus_time_conversions[i];
|
||||
}
|
||||
}
|
||||
@@ -120,11 +138,9 @@ uint64_t parse_prometheus_interval(std::string interval_str)
|
||||
}
|
||||
|
||||
#if defined(__linux__) and !defined(MINIMAL_BUILD) and !defined(__EMSCRIPTEN__)
|
||||
std::string calculate_file_sha256sum(const std::string& filename)
|
||||
{
|
||||
std::string calculate_file_sha256sum(const std::string& filename) {
|
||||
std::ifstream file(filename, std::ios::binary);
|
||||
if (!file.is_open())
|
||||
{
|
||||
if(!file.is_open()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -133,8 +149,7 @@ std::string calculate_file_sha256sum(const std::string& filename)
|
||||
|
||||
constexpr size_t buffer_size = 4096;
|
||||
char buffer[buffer_size];
|
||||
while (file.read(buffer, buffer_size))
|
||||
{
|
||||
while(file.read(buffer, buffer_size)) {
|
||||
SHA256_Update(&sha256_context, buffer, buffer_size);
|
||||
}
|
||||
SHA256_Update(&sha256_context, buffer, file.gcount());
|
||||
@@ -143,40 +158,32 @@ std::string calculate_file_sha256sum(const std::string& filename)
|
||||
SHA256_Final(digest, &sha256_context);
|
||||
|
||||
std::stringstream ss;
|
||||
for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i)
|
||||
{
|
||||
for(int i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
|
||||
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned>(digest[i]);
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string sanitize_rule_name(const std::string& name)
|
||||
{
|
||||
std::string sanitize_rule_name(const std::string& name) {
|
||||
std::string sanitized_name = name;
|
||||
RE2::GlobalReplace(&sanitized_name, "[^a-zA-Z0-9_:]", "_");
|
||||
RE2::GlobalReplace(&sanitized_name, "_+", "_");
|
||||
if (!sanitized_name.empty() && sanitized_name.back() == '_')
|
||||
{
|
||||
if(!sanitized_name.empty() && sanitized_name.back() == '_') {
|
||||
sanitized_name.pop_back();
|
||||
}
|
||||
return sanitized_name;
|
||||
}
|
||||
|
||||
std::string wrap_text(const std::string& in, uint32_t indent, uint32_t line_len)
|
||||
{
|
||||
std::string wrap_text(const std::string& in, uint32_t indent, uint32_t line_len) {
|
||||
std::istringstream is(in);
|
||||
std::ostringstream os;
|
||||
std::string word;
|
||||
uint32_t len = 0;
|
||||
while (is >> word)
|
||||
{
|
||||
if((len + word.length() + 1) <= (line_len-indent))
|
||||
{
|
||||
while(is >> word) {
|
||||
if((len + word.length() + 1) <= (line_len - indent)) {
|
||||
len += word.length() + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
os << std::endl;
|
||||
os << std::left << std::setw(indent) << " ";
|
||||
len = word.length() + 1;
|
||||
@@ -186,18 +193,15 @@ std::string wrap_text(const std::string& in, uint32_t indent, uint32_t line_len)
|
||||
return os.str();
|
||||
}
|
||||
|
||||
uint32_t hardware_concurrency()
|
||||
{
|
||||
uint32_t hardware_concurrency() {
|
||||
auto hc = std::thread::hardware_concurrency();
|
||||
return hc ? hc : 1;
|
||||
}
|
||||
|
||||
void readfile(const std::string& filename, std::string& data)
|
||||
{
|
||||
void readfile(const std::string& filename, std::string& data) {
|
||||
std::ifstream file(filename, std::ios::in);
|
||||
|
||||
if(file.is_open())
|
||||
{
|
||||
if(file.is_open()) {
|
||||
std::stringstream ss;
|
||||
ss << file.rdbuf();
|
||||
|
||||
@@ -209,22 +213,18 @@ void readfile(const std::string& filename, std::string& data)
|
||||
return;
|
||||
}
|
||||
|
||||
bool matches_wildcard(const std::string &pattern, const std::string &s)
|
||||
{
|
||||
bool matches_wildcard(const std::string& pattern, const std::string& s) {
|
||||
std::string::size_type star_pos = pattern.find("*");
|
||||
if(star_pos == std::string::npos)
|
||||
{
|
||||
if(star_pos == std::string::npos) {
|
||||
// regular match (no wildcards)
|
||||
return pattern == s;
|
||||
}
|
||||
|
||||
if(star_pos == 0)
|
||||
{
|
||||
if(star_pos == 0) {
|
||||
// wildcard at the beginning "*something*..."
|
||||
|
||||
std::string::size_type next_pattern_start = pattern.find_first_not_of("*");
|
||||
if(next_pattern_start == std::string::npos)
|
||||
{
|
||||
if(next_pattern_start == std::string::npos) {
|
||||
// pattern was just a sequence of stars *, **, ***, ... . This always matches.
|
||||
return true;
|
||||
}
|
||||
@@ -232,18 +232,16 @@ bool matches_wildcard(const std::string &pattern, const std::string &s)
|
||||
std::string next_pattern = pattern.substr(next_pattern_start);
|
||||
std::string to_find = next_pattern.substr(0, next_pattern.find("*"));
|
||||
std::string::size_type lit_pos = s.find(to_find);
|
||||
if(lit_pos == std::string::npos)
|
||||
{
|
||||
if(lit_pos == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return matches_wildcard(next_pattern.substr(to_find.size()), s.substr(lit_pos + to_find.size()));
|
||||
} else
|
||||
{
|
||||
return matches_wildcard(next_pattern.substr(to_find.size()),
|
||||
s.substr(lit_pos + to_find.size()));
|
||||
} else {
|
||||
// wildcard at the end or in the middle "something*else*..."
|
||||
|
||||
if(pattern.substr(0, star_pos) != s.substr(0, star_pos))
|
||||
{
|
||||
|
||||
if(pattern.substr(0, star_pos) != s.substr(0, star_pos)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -251,12 +249,10 @@ bool matches_wildcard(const std::string &pattern, const std::string &s)
|
||||
}
|
||||
}
|
||||
|
||||
namespace network
|
||||
{
|
||||
bool is_unix_scheme(const std::string& url)
|
||||
{
|
||||
namespace network {
|
||||
bool is_unix_scheme(const std::string& url) {
|
||||
return sinsp_utils::startswith(url, UNIX_SCHEME);
|
||||
}
|
||||
} // namespace network
|
||||
} // namespace utils
|
||||
} // namespace falco
|
||||
} // namespace network
|
||||
} // namespace utils
|
||||
} // namespace falco
|
||||
|
||||
@@ -23,8 +23,7 @@ limitations under the License.
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace falco::utils
|
||||
{
|
||||
namespace falco::utils {
|
||||
uint64_t parse_prometheus_interval(std::string interval_str);
|
||||
|
||||
#if defined(__linux__) and !defined(MINIMAL_BUILD) and !defined(__EMSCRIPTEN__)
|
||||
@@ -39,11 +38,10 @@ void readfile(const std::string& filename, std::string& data);
|
||||
|
||||
uint32_t hardware_concurrency();
|
||||
|
||||
bool matches_wildcard(const std::string &pattern, const std::string &s);
|
||||
bool matches_wildcard(const std::string& pattern, const std::string& s);
|
||||
|
||||
namespace network
|
||||
{
|
||||
namespace network {
|
||||
static const std::string UNIX_SCHEME("unix://");
|
||||
bool is_unix_scheme(const std::string& url);
|
||||
} // namespace network
|
||||
} // namespace falco::utils
|
||||
} // namespace network
|
||||
} // namespace falco::utils
|
||||
|
||||
@@ -21,18 +21,15 @@ limitations under the License.
|
||||
|
||||
using namespace libsinsp::filter;
|
||||
|
||||
static inline std::string get_field_name(const std::string& name, const std::string& arg)
|
||||
{
|
||||
static inline std::string get_field_name(const std::string& name, const std::string& arg) {
|
||||
std::string fld = name;
|
||||
if (!arg.empty())
|
||||
{
|
||||
if(!arg.empty()) {
|
||||
fld += "[" + arg + "]";
|
||||
}
|
||||
return fld;
|
||||
}
|
||||
|
||||
void filter_details::reset()
|
||||
{
|
||||
void filter_details::reset() {
|
||||
fields.clear();
|
||||
macros.clear();
|
||||
operators.clear();
|
||||
@@ -41,114 +38,92 @@ void filter_details::reset()
|
||||
transformers.clear();
|
||||
}
|
||||
|
||||
void filter_details_resolver::run(ast::expr* filter, filter_details& details)
|
||||
{
|
||||
void filter_details_resolver::run(ast::expr* filter, filter_details& details) {
|
||||
visitor v(details);
|
||||
filter->accept(&v);
|
||||
}
|
||||
|
||||
void filter_details_resolver::visitor::visit(ast::and_expr* e)
|
||||
{
|
||||
for(size_t i = 0; i < e->children.size(); i++)
|
||||
{
|
||||
void filter_details_resolver::visitor::visit(ast::and_expr* e) {
|
||||
for(size_t i = 0; i < e->children.size(); i++) {
|
||||
e->children[i]->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
void filter_details_resolver::visitor::visit(ast::or_expr* e)
|
||||
{
|
||||
for(size_t i = 0; i < e->children.size(); i++)
|
||||
{
|
||||
void filter_details_resolver::visitor::visit(ast::or_expr* e) {
|
||||
for(size_t i = 0; i < e->children.size(); i++) {
|
||||
e->children[i]->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
void filter_details_resolver::visitor::visit(ast::not_expr* e)
|
||||
{
|
||||
void filter_details_resolver::visitor::visit(ast::not_expr* e) {
|
||||
e->child->accept(this);
|
||||
}
|
||||
|
||||
void filter_details_resolver::visitor::visit(ast::list_expr* e)
|
||||
{
|
||||
if(m_expect_list)
|
||||
{
|
||||
for(const auto& item : e->values)
|
||||
{
|
||||
if(m_details.known_lists.find(item) != m_details.known_lists.end())
|
||||
{
|
||||
void filter_details_resolver::visitor::visit(ast::list_expr* e) {
|
||||
if(m_expect_list) {
|
||||
for(const auto& item : e->values) {
|
||||
if(m_details.known_lists.find(item) != m_details.known_lists.end()) {
|
||||
m_details.lists.insert(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_expect_evtname)
|
||||
{
|
||||
for(const auto& item : e->values)
|
||||
{
|
||||
if(m_details.known_lists.find(item) == m_details.known_lists.end())
|
||||
{
|
||||
if(m_expect_evtname) {
|
||||
for(const auto& item : e->values) {
|
||||
if(m_details.known_lists.find(item) == m_details.known_lists.end()) {
|
||||
m_details.evtnames.insert(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void filter_details_resolver::visitor::visit(ast::binary_check_expr* e)
|
||||
{
|
||||
void filter_details_resolver::visitor::visit(ast::binary_check_expr* e) {
|
||||
m_last_node_field_name.clear();
|
||||
m_expect_evtname = false;
|
||||
m_expect_list = false;
|
||||
e->left->accept(this);
|
||||
if (m_last_node_field_name.empty())
|
||||
{
|
||||
if(m_last_node_field_name.empty()) {
|
||||
throw std::runtime_error("can't find field info in binary check expression");
|
||||
}
|
||||
|
||||
|
||||
m_details.operators.insert(e->op);
|
||||
|
||||
m_expect_list = true;
|
||||
m_expect_evtname = m_last_node_field_name == "evt.type" || m_last_node_field_name == "evt.asynctype";
|
||||
m_expect_evtname =
|
||||
m_last_node_field_name == "evt.type" || m_last_node_field_name == "evt.asynctype";
|
||||
e->right->accept(this);
|
||||
m_expect_evtname = false;
|
||||
m_expect_list = false;
|
||||
}
|
||||
|
||||
void filter_details_resolver::visitor::visit(ast::unary_check_expr* e)
|
||||
{
|
||||
void filter_details_resolver::visitor::visit(ast::unary_check_expr* e) {
|
||||
m_last_node_field_name.clear();
|
||||
e->left->accept(this);
|
||||
if (m_last_node_field_name.empty())
|
||||
{
|
||||
if(m_last_node_field_name.empty()) {
|
||||
throw std::runtime_error("can't find field info in unary check expression");
|
||||
}
|
||||
m_details.fields.insert(m_last_node_field_name);
|
||||
m_details.operators.insert(e->op);
|
||||
}
|
||||
|
||||
void filter_details_resolver::visitor::visit(ast::identifier_expr* e)
|
||||
{
|
||||
void filter_details_resolver::visitor::visit(ast::identifier_expr* e) {
|
||||
// todo(jasondellaluce): maybe throw an error if we encounter an unknown macro?
|
||||
if(m_details.known_macros.find(e->identifier) != m_details.known_macros.end())
|
||||
{
|
||||
if(m_details.known_macros.find(e->identifier) != m_details.known_macros.end()) {
|
||||
m_details.macros.insert(e->identifier);
|
||||
}
|
||||
}
|
||||
|
||||
void filter_details_resolver::visitor::visit(ast::value_expr* e)
|
||||
{
|
||||
if (m_expect_evtname)
|
||||
{
|
||||
void filter_details_resolver::visitor::visit(ast::value_expr* e) {
|
||||
if(m_expect_evtname) {
|
||||
m_details.evtnames.insert(e->value);
|
||||
}
|
||||
}
|
||||
|
||||
void filter_details_resolver::visitor::visit(ast::field_expr* e)
|
||||
{
|
||||
void filter_details_resolver::visitor::visit(ast::field_expr* e) {
|
||||
m_last_node_field_name = get_field_name(e->field, e->arg);
|
||||
m_details.fields.insert(m_last_node_field_name);
|
||||
}
|
||||
|
||||
void filter_details_resolver::visitor::visit(ast::field_transformer_expr* e)
|
||||
{
|
||||
void filter_details_resolver::visitor::visit(ast::field_transformer_expr* e) {
|
||||
m_details.transformers.insert(e->transformer);
|
||||
e->value->accept(this);
|
||||
}
|
||||
|
||||
@@ -22,8 +22,7 @@ limitations under the License.
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
|
||||
struct filter_details
|
||||
{
|
||||
struct filter_details {
|
||||
// input macros and lists
|
||||
std::unordered_set<std::string> known_macros;
|
||||
std::unordered_set<std::string> known_lists;
|
||||
@@ -40,29 +39,26 @@ struct filter_details
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Helper class for getting details about rules' filters.
|
||||
\brief Helper class for getting details about rules' filters.
|
||||
*/
|
||||
class filter_details_resolver
|
||||
{
|
||||
class filter_details_resolver {
|
||||
public:
|
||||
/*!
|
||||
\brief Visits a filter AST and stores details about macros, lists,
|
||||
fields and operators used.
|
||||
\param filter The filter AST to be processed.
|
||||
\param details Helper structure used to state known macros and
|
||||
lists on input, and to store all the retrieved details as output.
|
||||
\brief Visits a filter AST and stores details about macros, lists,
|
||||
fields and operators used.
|
||||
\param filter The filter AST to be processed.
|
||||
\param details Helper structure used to state known macros and
|
||||
lists on input, and to store all the retrieved details as output.
|
||||
*/
|
||||
void run(libsinsp::filter::ast::expr* filter,
|
||||
filter_details& details);
|
||||
void run(libsinsp::filter::ast::expr* filter, filter_details& details);
|
||||
|
||||
private:
|
||||
struct visitor : public libsinsp::filter::ast::expr_visitor
|
||||
{
|
||||
explicit visitor(filter_details& details) :
|
||||
m_details(details),
|
||||
m_expect_list(false),
|
||||
m_expect_evtname(false),
|
||||
m_last_node_field_name() {}
|
||||
struct visitor : public libsinsp::filter::ast::expr_visitor {
|
||||
explicit visitor(filter_details& details):
|
||||
m_details(details),
|
||||
m_expect_list(false),
|
||||
m_expect_evtname(false),
|
||||
m_last_node_field_name() {}
|
||||
visitor(visitor&&) = default;
|
||||
visitor(const visitor&) = delete;
|
||||
|
||||
|
||||
@@ -20,8 +20,7 @@ limitations under the License.
|
||||
|
||||
using namespace libsinsp::filter;
|
||||
|
||||
bool filter_macro_resolver::run(std::shared_ptr<libsinsp::filter::ast::expr>& filter)
|
||||
{
|
||||
bool filter_macro_resolver::run(std::shared_ptr<libsinsp::filter::ast::expr>& filter) {
|
||||
m_unknown_macros.clear();
|
||||
m_resolved_macros.clear();
|
||||
m_errors.clear();
|
||||
@@ -29,110 +28,90 @@ bool filter_macro_resolver::run(std::shared_ptr<libsinsp::filter::ast::expr>& fi
|
||||
visitor v(m_errors, m_unknown_macros, m_resolved_macros, m_macros);
|
||||
v.m_node_substitute = nullptr;
|
||||
filter->accept(&v);
|
||||
if (v.m_node_substitute)
|
||||
{
|
||||
if(v.m_node_substitute) {
|
||||
filter = std::move(v.m_node_substitute);
|
||||
}
|
||||
return !m_resolved_macros.empty();
|
||||
}
|
||||
|
||||
void filter_macro_resolver::set_macro(
|
||||
const std::string& name,
|
||||
const std::shared_ptr<libsinsp::filter::ast::expr>& macro)
|
||||
{
|
||||
void filter_macro_resolver::set_macro(const std::string& name,
|
||||
const std::shared_ptr<libsinsp::filter::ast::expr>& macro) {
|
||||
m_macros[name] = macro;
|
||||
}
|
||||
|
||||
const std::vector<filter_macro_resolver::value_info>& filter_macro_resolver::get_unknown_macros() const
|
||||
{
|
||||
const std::vector<filter_macro_resolver::value_info>& filter_macro_resolver::get_unknown_macros()
|
||||
const {
|
||||
return m_unknown_macros;
|
||||
}
|
||||
|
||||
const std::vector<filter_macro_resolver::value_info>& filter_macro_resolver::get_errors() const
|
||||
{
|
||||
const std::vector<filter_macro_resolver::value_info>& filter_macro_resolver::get_errors() const {
|
||||
return m_errors;
|
||||
}
|
||||
|
||||
const std::vector<filter_macro_resolver::value_info>& filter_macro_resolver::get_resolved_macros() const
|
||||
{
|
||||
const std::vector<filter_macro_resolver::value_info>& filter_macro_resolver::get_resolved_macros()
|
||||
const {
|
||||
return m_resolved_macros;
|
||||
}
|
||||
|
||||
void filter_macro_resolver::visitor::visit(ast::and_expr* e)
|
||||
{
|
||||
for (size_t i = 0; i < e->children.size(); i++)
|
||||
{
|
||||
void filter_macro_resolver::visitor::visit(ast::and_expr* e) {
|
||||
for(size_t i = 0; i < e->children.size(); i++) {
|
||||
e->children[i]->accept(this);
|
||||
if (m_node_substitute)
|
||||
{
|
||||
if(m_node_substitute) {
|
||||
e->children[i] = std::move(m_node_substitute);
|
||||
}
|
||||
}
|
||||
m_node_substitute = nullptr;
|
||||
}
|
||||
|
||||
void filter_macro_resolver::visitor::visit(ast::or_expr* e)
|
||||
{
|
||||
for (size_t i = 0; i < e->children.size(); i++)
|
||||
{
|
||||
void filter_macro_resolver::visitor::visit(ast::or_expr* e) {
|
||||
for(size_t i = 0; i < e->children.size(); i++) {
|
||||
e->children[i]->accept(this);
|
||||
if (m_node_substitute)
|
||||
{
|
||||
if(m_node_substitute) {
|
||||
e->children[i] = std::move(m_node_substitute);
|
||||
}
|
||||
}
|
||||
m_node_substitute = nullptr;
|
||||
}
|
||||
|
||||
void filter_macro_resolver::visitor::visit(ast::not_expr* e)
|
||||
{
|
||||
void filter_macro_resolver::visitor::visit(ast::not_expr* e) {
|
||||
e->child->accept(this);
|
||||
if (m_node_substitute)
|
||||
{
|
||||
if(m_node_substitute) {
|
||||
e->child = std::move(m_node_substitute);
|
||||
}
|
||||
m_node_substitute = nullptr;
|
||||
}
|
||||
|
||||
void filter_macro_resolver::visitor::visit(ast::list_expr* e)
|
||||
{
|
||||
void filter_macro_resolver::visitor::visit(ast::list_expr* e) {
|
||||
m_node_substitute = nullptr;
|
||||
}
|
||||
|
||||
void filter_macro_resolver::visitor::visit(ast::binary_check_expr* e)
|
||||
{
|
||||
void filter_macro_resolver::visitor::visit(ast::binary_check_expr* e) {
|
||||
m_node_substitute = nullptr;
|
||||
}
|
||||
|
||||
void filter_macro_resolver::visitor::visit(ast::unary_check_expr* e)
|
||||
{
|
||||
void filter_macro_resolver::visitor::visit(ast::unary_check_expr* e) {
|
||||
m_node_substitute = nullptr;
|
||||
}
|
||||
|
||||
void filter_macro_resolver::visitor::visit(ast::value_expr* e)
|
||||
{
|
||||
void filter_macro_resolver::visitor::visit(ast::value_expr* e) {
|
||||
m_node_substitute = nullptr;
|
||||
}
|
||||
|
||||
void filter_macro_resolver::visitor::visit(ast::field_expr* e)
|
||||
{
|
||||
void filter_macro_resolver::visitor::visit(ast::field_expr* e) {
|
||||
m_node_substitute = nullptr;
|
||||
}
|
||||
|
||||
void filter_macro_resolver::visitor::visit(ast::field_transformer_expr* e)
|
||||
{
|
||||
void filter_macro_resolver::visitor::visit(ast::field_transformer_expr* e) {
|
||||
m_node_substitute = nullptr;
|
||||
}
|
||||
|
||||
void filter_macro_resolver::visitor::visit(ast::identifier_expr* e)
|
||||
{
|
||||
void filter_macro_resolver::visitor::visit(ast::identifier_expr* e) {
|
||||
const auto& macro = m_macros.find(e->identifier);
|
||||
if (macro != m_macros.end() && macro->second) // skip null-ptr macros
|
||||
if(macro != m_macros.end() && macro->second) // skip null-ptr macros
|
||||
{
|
||||
// note: checks for loop detection
|
||||
const auto& prevref = std::find(m_macros_path.begin(), m_macros_path.end(), macro->first);
|
||||
if (prevref != m_macros_path.end())
|
||||
{
|
||||
if(prevref != m_macros_path.end()) {
|
||||
auto msg = "reference loop in macro '" + macro->first + "'";
|
||||
m_errors.push_back({msg, e->get_pos()});
|
||||
m_node_substitute = nullptr;
|
||||
@@ -146,15 +125,12 @@ void filter_macro_resolver::visitor::visit(ast::identifier_expr* e)
|
||||
new_node->accept(this);
|
||||
// new_node might already have set a non-NULL m_node_substitute.
|
||||
// if not, the right substituted is the newly-cloned node.
|
||||
if (!m_node_substitute)
|
||||
{
|
||||
if(!m_node_substitute) {
|
||||
m_node_substitute = std::move(new_node);
|
||||
}
|
||||
m_resolved_macros.push_back({e->identifier, e->get_pos()});
|
||||
m_macros_path.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
m_node_substitute = nullptr;
|
||||
m_unknown_macros.push_back({e->identifier, e->get_pos()});
|
||||
}
|
||||
|
||||
@@ -24,114 +24,107 @@ limitations under the License.
|
||||
#include <memory>
|
||||
|
||||
/*!
|
||||
\brief Helper class for substituting and resolving macro
|
||||
references in parsed filters.
|
||||
\brief Helper class for substituting and resolving macro
|
||||
references in parsed filters.
|
||||
*/
|
||||
class filter_macro_resolver
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
\brief Visits a filter AST and substitutes macro references
|
||||
according with all the definitions added through set_macro(),
|
||||
by replacing the reference with a clone of the macro AST.
|
||||
\param filter The filter AST to be processed. Note that the pointer
|
||||
is passed by reference and be transformed in order to apply
|
||||
the substutions. In that case, the old pointer is owned by this
|
||||
class and is deleted automatically.
|
||||
\return true if at least one of the defined macros is resolved
|
||||
*/
|
||||
bool run(std::shared_ptr<libsinsp::filter::ast::expr>& filter);
|
||||
class filter_macro_resolver {
|
||||
public:
|
||||
/*!
|
||||
\brief Visits a filter AST and substitutes macro references
|
||||
according with all the definitions added through set_macro(),
|
||||
by replacing the reference with a clone of the macro AST.
|
||||
\param filter The filter AST to be processed. Note that the pointer
|
||||
is passed by reference and be transformed in order to apply
|
||||
the substutions. In that case, the old pointer is owned by this
|
||||
class and is deleted automatically.
|
||||
\return true if at least one of the defined macros is resolved
|
||||
*/
|
||||
bool run(std::shared_ptr<libsinsp::filter::ast::expr>& filter);
|
||||
|
||||
/*!
|
||||
\brief Defines a new macro to be substituted in filters. If called
|
||||
multiple times for the same macro name, the previous definition
|
||||
gets overridden. A macro can be undefined by setting a null
|
||||
AST pointer.
|
||||
\param name The name of the macro.
|
||||
\param macro The AST of the macro.
|
||||
*/
|
||||
void set_macro(
|
||||
const std::string& name,
|
||||
const std::shared_ptr<libsinsp::filter::ast::expr>& macro);
|
||||
/*!
|
||||
\brief Defines a new macro to be substituted in filters. If called
|
||||
multiple times for the same macro name, the previous definition
|
||||
gets overridden. A macro can be undefined by setting a null
|
||||
AST pointer.
|
||||
\param name The name of the macro.
|
||||
\param macro The AST of the macro.
|
||||
*/
|
||||
void set_macro(const std::string& name,
|
||||
const std::shared_ptr<libsinsp::filter::ast::expr>& macro);
|
||||
|
||||
/*!
|
||||
\brief used in get_{resolved,unknown}_macros and get_errors
|
||||
to represent an identifier/string value along with an AST position.
|
||||
*/
|
||||
typedef std::pair<std::string,libsinsp::filter::ast::pos_info> value_info;
|
||||
/*!
|
||||
\brief used in get_{resolved,unknown}_macros and get_errors
|
||||
to represent an identifier/string value along with an AST position.
|
||||
*/
|
||||
typedef std::pair<std::string, libsinsp::filter::ast::pos_info> value_info;
|
||||
|
||||
/*!
|
||||
\brief Returns a set containing the names of all the macros
|
||||
substituted during the last invocation of run(). Should be
|
||||
non-empty if the last invocation of run() returned true.
|
||||
*/
|
||||
const std::vector<value_info>& get_resolved_macros() const;
|
||||
/*!
|
||||
\brief Returns a set containing the names of all the macros
|
||||
substituted during the last invocation of run(). Should be
|
||||
non-empty if the last invocation of run() returned true.
|
||||
*/
|
||||
const std::vector<value_info>& get_resolved_macros() const;
|
||||
|
||||
/*!
|
||||
\brief Returns a set containing the names of all the macros
|
||||
that remained unresolved during the last invocation of run().
|
||||
A macro remains unresolved if it is found inside the processed
|
||||
filter but it was not defined with set_macro();
|
||||
*/
|
||||
const std::vector<value_info>& get_unknown_macros() const;
|
||||
/*!
|
||||
\brief Returns a set containing the names of all the macros
|
||||
that remained unresolved during the last invocation of run().
|
||||
A macro remains unresolved if it is found inside the processed
|
||||
filter but it was not defined with set_macro();
|
||||
*/
|
||||
const std::vector<value_info>& get_unknown_macros() const;
|
||||
|
||||
/*!
|
||||
\brief Returns a list of errors occurred during
|
||||
the latest invocation of run().
|
||||
*/
|
||||
const std::vector<value_info>& get_errors() const;
|
||||
/*!
|
||||
\brief Returns a list of errors occurred during
|
||||
the latest invocation of run().
|
||||
*/
|
||||
const std::vector<value_info>& get_errors() const;
|
||||
|
||||
/*!
|
||||
\brief Clears the resolver by resetting all state related to
|
||||
known macros and everything related to the previous resolution run.
|
||||
*/
|
||||
inline void clear()
|
||||
{
|
||||
m_errors.clear();
|
||||
m_unknown_macros.clear();
|
||||
m_resolved_macros.clear();
|
||||
m_macros.clear();
|
||||
}
|
||||
/*!
|
||||
\brief Clears the resolver by resetting all state related to
|
||||
known macros and everything related to the previous resolution run.
|
||||
*/
|
||||
inline void clear() {
|
||||
m_errors.clear();
|
||||
m_unknown_macros.clear();
|
||||
m_resolved_macros.clear();
|
||||
m_macros.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::unordered_map<
|
||||
std::string,
|
||||
std::shared_ptr<libsinsp::filter::ast::expr>
|
||||
> macro_defs;
|
||||
private:
|
||||
typedef std::unordered_map<std::string, std::shared_ptr<libsinsp::filter::ast::expr> >
|
||||
macro_defs;
|
||||
|
||||
struct visitor : public libsinsp::filter::ast::expr_visitor
|
||||
{
|
||||
visitor(
|
||||
std::vector<value_info>& errors,
|
||||
std::vector<value_info>& unknown_macros,
|
||||
std::vector<value_info>& resolved_macros,
|
||||
macro_defs& macros):
|
||||
m_errors(errors),
|
||||
m_unknown_macros(unknown_macros),
|
||||
m_resolved_macros(resolved_macros),
|
||||
m_macros(macros) {}
|
||||
struct visitor : public libsinsp::filter::ast::expr_visitor {
|
||||
visitor(std::vector<value_info>& errors,
|
||||
std::vector<value_info>& unknown_macros,
|
||||
std::vector<value_info>& resolved_macros,
|
||||
macro_defs& macros):
|
||||
m_errors(errors),
|
||||
m_unknown_macros(unknown_macros),
|
||||
m_resolved_macros(resolved_macros),
|
||||
m_macros(macros) {}
|
||||
|
||||
std::vector<std::string> m_macros_path;
|
||||
std::unique_ptr<libsinsp::filter::ast::expr> m_node_substitute;
|
||||
std::vector<value_info>& m_errors;
|
||||
std::vector<value_info>& m_unknown_macros;
|
||||
std::vector<value_info>& m_resolved_macros;
|
||||
macro_defs& m_macros;
|
||||
std::vector<std::string> m_macros_path;
|
||||
std::unique_ptr<libsinsp::filter::ast::expr> m_node_substitute;
|
||||
std::vector<value_info>& m_errors;
|
||||
std::vector<value_info>& m_unknown_macros;
|
||||
std::vector<value_info>& m_resolved_macros;
|
||||
macro_defs& m_macros;
|
||||
|
||||
void visit(libsinsp::filter::ast::and_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::or_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::not_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::identifier_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::value_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::list_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::unary_check_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::binary_check_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::field_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::field_transformer_expr* e) override;
|
||||
};
|
||||
void visit(libsinsp::filter::ast::and_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::or_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::not_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::identifier_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::value_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::list_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::unary_check_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::binary_check_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::field_expr* e) override;
|
||||
void visit(libsinsp::filter::ast::field_transformer_expr* e) override;
|
||||
};
|
||||
|
||||
std::vector<value_info> m_errors;
|
||||
std::vector<value_info> m_unknown_macros;
|
||||
std::vector<value_info> m_resolved_macros;
|
||||
macro_defs m_macros;
|
||||
std::vector<value_info> m_errors;
|
||||
std::vector<value_info> m_unknown_macros;
|
||||
std::vector<value_info> m_resolved_macros;
|
||||
macro_defs m_macros;
|
||||
};
|
||||
|
||||
@@ -17,12 +17,10 @@ limitations under the License.
|
||||
|
||||
#include "filter_ruleset.h"
|
||||
|
||||
void filter_ruleset::set_engine_state(const filter_ruleset::engine_state_funcs& engine_state)
|
||||
{
|
||||
void filter_ruleset::set_engine_state(const filter_ruleset::engine_state_funcs& engine_state) {
|
||||
m_engine_state = engine_state;
|
||||
}
|
||||
|
||||
filter_ruleset::engine_state_funcs& filter_ruleset::get_engine_state()
|
||||
{
|
||||
filter_ruleset::engine_state_funcs& filter_ruleset::get_engine_state() {
|
||||
return m_engine_state;
|
||||
}
|
||||
|
||||
@@ -25,25 +25,22 @@ limitations under the License.
|
||||
#include <libsinsp/events/sinsp_events.h>
|
||||
|
||||
/*!
|
||||
\brief Manages a set of rulesets. A ruleset is a set of
|
||||
enabled rules that is able to process events and find matches for those rules.
|
||||
\brief Manages a set of rulesets. A ruleset is a set of
|
||||
enabled rules that is able to process events and find matches for those rules.
|
||||
*/
|
||||
|
||||
class filter_ruleset
|
||||
{
|
||||
class filter_ruleset {
|
||||
public:
|
||||
// A set of functions that can be used to retrieve state from
|
||||
// the falco engine that created this ruleset.
|
||||
struct engine_state_funcs
|
||||
{
|
||||
using ruleset_retriever_func_t = std::function<bool(const std::string &, std::shared_ptr<filter_ruleset> &ruleset)>;
|
||||
struct engine_state_funcs {
|
||||
using ruleset_retriever_func_t =
|
||||
std::function<bool(const std::string &, std::shared_ptr<filter_ruleset> &ruleset)>;
|
||||
|
||||
ruleset_retriever_func_t get_ruleset;
|
||||
};
|
||||
|
||||
enum class match_type {
|
||||
exact, substring, wildcard
|
||||
};
|
||||
enum class match_type { exact, substring, wildcard };
|
||||
|
||||
virtual ~filter_ruleset() = default;
|
||||
|
||||
@@ -51,198 +48,171 @@ public:
|
||||
engine_state_funcs &get_engine_state();
|
||||
|
||||
/*!
|
||||
\brief Adds a rule and its filtering filter + condition inside the manager.
|
||||
\brief Adds a rule and its filtering filter + condition inside the manager.
|
||||
This method only adds the rule inside the internal collection,
|
||||
but does not enable it for any ruleset. The rule must be enabled
|
||||
for one or more rulesets with the enable() or enable_tags() methods.
|
||||
The ast representation of the rule's condition is provided to allow
|
||||
the filter_ruleset object to parse the ast to obtain event types
|
||||
or do other analysis/indexing of the condition.
|
||||
\param rule The rule to be added
|
||||
\param the filter representing the rule's filtering condition.
|
||||
\param condition The AST representing the rule's filtering condition
|
||||
but does not enable it for any ruleset. The rule must be enabled
|
||||
for one or more rulesets with the enable() or enable_tags() methods.
|
||||
The ast representation of the rule's condition is provided to allow
|
||||
the filter_ruleset object to parse the ast to obtain event types
|
||||
or do other analysis/indexing of the condition.
|
||||
\param rule The rule to be added
|
||||
\param the filter representing the rule's filtering condition.
|
||||
\param condition The AST representing the rule's filtering condition
|
||||
*/
|
||||
virtual void add(
|
||||
const falco_rule& rule,
|
||||
std::shared_ptr<sinsp_filter> filter,
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> condition) = 0;
|
||||
virtual void add(const falco_rule &rule,
|
||||
std::shared_ptr<sinsp_filter> filter,
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> condition) = 0;
|
||||
|
||||
/*!
|
||||
\brief Adds all rules contained in the provided
|
||||
rule_loader::compile_output struct. Only
|
||||
those rules with the provided source and those rules
|
||||
with priority >= min_priority should be added. The
|
||||
intent is that this replaces add(). However, we retain
|
||||
add() for backwards compatibility. Any rules added via
|
||||
add() are also added to this ruleset. The default
|
||||
implementation iterates over rules and calls add(),
|
||||
but can be overridden.
|
||||
\param rule The compile output.
|
||||
\param min_priority Only add rules with priority above this priority.
|
||||
\param source Only add rules with source equal to this source.
|
||||
\brief Adds all rules contained in the provided
|
||||
rule_loader::compile_output struct. Only
|
||||
those rules with the provided source and those rules
|
||||
with priority >= min_priority should be added. The
|
||||
intent is that this replaces add(). However, we retain
|
||||
add() for backwards compatibility. Any rules added via
|
||||
add() are also added to this ruleset. The default
|
||||
implementation iterates over rules and calls add(),
|
||||
but can be overridden.
|
||||
\param rule The compile output.
|
||||
\param min_priority Only add rules with priority above this priority.
|
||||
\param source Only add rules with source equal to this source.
|
||||
*/
|
||||
virtual void add_compile_output(
|
||||
const rule_loader::compile_output& compile_output,
|
||||
falco_common::priority_type min_priority,
|
||||
const std::string& source)
|
||||
{
|
||||
for (const auto& rule : compile_output.rules)
|
||||
{
|
||||
if(rule.priority <= min_priority &&
|
||||
rule.source == source)
|
||||
{
|
||||
virtual void add_compile_output(const rule_loader::compile_output &compile_output,
|
||||
falco_common::priority_type min_priority,
|
||||
const std::string &source) {
|
||||
for(const auto &rule : compile_output.rules) {
|
||||
if(rule.priority <= min_priority && rule.source == source) {
|
||||
add(rule, rule.filter, rule.condition);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Erases the internal state. All rules are disabled in each
|
||||
ruleset, and all the rules defined with add() are removed.
|
||||
\brief Erases the internal state. All rules are disabled in each
|
||||
ruleset, and all the rules defined with add() are removed.
|
||||
*/
|
||||
virtual void clear() = 0;
|
||||
|
||||
/*!
|
||||
\brief This is meant to be called after all rules have been added
|
||||
with add() and enabled on the given ruleset with enable()/enable_tags().
|
||||
\brief This is meant to be called after all rules have been added
|
||||
with add() and enabled on the given ruleset with enable()/enable_tags().
|
||||
*/
|
||||
virtual void on_loading_complete() = 0;
|
||||
|
||||
/*!
|
||||
\brief Processes an event and tries to find a match in a given ruleset.
|
||||
\return true if a match is found, false otherwise
|
||||
\param evt The event to be processed
|
||||
\param match If true is returned, this is filled-out with the first rule
|
||||
that matched the event
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
\brief Processes an event and tries to find a match in a given ruleset.
|
||||
\return true if a match is found, false otherwise
|
||||
\param evt The event to be processed
|
||||
\param match If true is returned, this is filled-out with the first rule
|
||||
that matched the event
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
*/
|
||||
virtual bool run(
|
||||
sinsp_evt *evt,
|
||||
falco_rule& match,
|
||||
uint16_t ruleset_id) = 0;
|
||||
|
||||
/*!
|
||||
\brief Processes an event and tries to find a match in a given ruleset.
|
||||
\return true if a match is found, false otherwise
|
||||
\param evt The event to be processed
|
||||
\param matches If true is returned, this is filled-out with all the rules
|
||||
that matched the event
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
*/
|
||||
virtual bool run(
|
||||
sinsp_evt *evt,
|
||||
std::vector<falco_rule>& matches,
|
||||
uint16_t ruleset_id) = 0;
|
||||
virtual bool run(sinsp_evt *evt, falco_rule &match, uint16_t ruleset_id) = 0;
|
||||
|
||||
/*!
|
||||
\brief Returns the number of rules enabled in a given ruleset
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
\brief Processes an event and tries to find a match in a given ruleset.
|
||||
\return true if a match is found, false otherwise
|
||||
\param evt The event to be processed
|
||||
\param matches If true is returned, this is filled-out with all the rules
|
||||
that matched the event
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
*/
|
||||
virtual bool run(sinsp_evt *evt, std::vector<falco_rule> &matches, uint16_t ruleset_id) = 0;
|
||||
|
||||
/*!
|
||||
\brief Returns the number of rules enabled in a given ruleset
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
*/
|
||||
virtual uint64_t enabled_count(uint16_t ruleset_id) = 0;
|
||||
|
||||
/*!
|
||||
\brief Returns the union of the evttypes of all the rules enabled
|
||||
in a given ruleset
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
\deprecated Must use the new typing-improved `enabled_event_codes`
|
||||
and `enabled_sc_codes` instead
|
||||
\note todo(jasondellaluce): remove this in future refactors
|
||||
\brief Returns the union of the evttypes of all the rules enabled
|
||||
in a given ruleset
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
\deprecated Must use the new typing-improved `enabled_event_codes`
|
||||
and `enabled_sc_codes` instead
|
||||
\note todo(jasondellaluce): remove this in future refactors
|
||||
*/
|
||||
virtual void enabled_evttypes(
|
||||
std::set<uint16_t> &evttypes,
|
||||
uint16_t ruleset) = 0;
|
||||
|
||||
/*!
|
||||
\brief Returns the all the ppm_sc_codes matching the rules
|
||||
enabled in a given ruleset.
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
*/
|
||||
virtual libsinsp::events::set<ppm_sc_code> enabled_sc_codes(
|
||||
uint16_t ruleset) = 0;
|
||||
|
||||
/*!
|
||||
\brief Returns the all the ppm_event_codes matching the rules
|
||||
enabled in a given ruleset.
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
*/
|
||||
virtual libsinsp::events::set<ppm_event_code> enabled_event_codes(
|
||||
uint16_t ruleset) = 0;
|
||||
virtual void enabled_evttypes(std::set<uint16_t> &evttypes, uint16_t ruleset) = 0;
|
||||
|
||||
/*!
|
||||
\brief Find those rules matching the provided substring and enable
|
||||
them in the provided ruleset.
|
||||
\param pattern Pattern used to match rule names.
|
||||
\param match How to match the pattern against rules:
|
||||
- exact: rules that has the same exact name as the pattern are matched
|
||||
- substring: rules having the pattern as a substring in the rule are matched.
|
||||
An empty pattern matches all rules.
|
||||
- wildcard: rules with names that satisfies a wildcard (*) pattern are matched.
|
||||
A "*" pattern matches all rules.
|
||||
Wildcards can appear anywhere in the pattern (e.g. "*hello*world*")
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
\brief Returns the all the ppm_sc_codes matching the rules
|
||||
enabled in a given ruleset.
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
*/
|
||||
virtual void enable(
|
||||
const std::string &pattern,
|
||||
match_type match,
|
||||
uint16_t ruleset_id) = 0;
|
||||
virtual libsinsp::events::set<ppm_sc_code> enabled_sc_codes(uint16_t ruleset) = 0;
|
||||
|
||||
/*!
|
||||
\brief Find those rules matching the provided substring and disable
|
||||
them in the provided ruleset.
|
||||
\param pattern Pattern used to match rule names.
|
||||
\param match How to match the pattern against rules:
|
||||
- exact: rules that has the same exact name as the pattern are matched
|
||||
- substring: rules having the pattern as a substring in the rule are matched.
|
||||
An empty pattern matches all rules.
|
||||
- wildcard: rules with names that satisfies a wildcard (*) pattern are matched.
|
||||
A "*" pattern matches all rules.
|
||||
Wildcards can appear anywhere in the pattern (e.g. "*hello*world*")
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
\brief Returns the all the ppm_event_codes matching the rules
|
||||
enabled in a given ruleset.
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
*/
|
||||
virtual void disable(
|
||||
const std::string &pattern,
|
||||
match_type match,
|
||||
uint16_t ruleset_id) = 0;
|
||||
virtual libsinsp::events::set<ppm_event_code> enabled_event_codes(uint16_t ruleset) = 0;
|
||||
|
||||
/*!
|
||||
\brief Find those rules that have a tag in the set of tags and
|
||||
enable them for the provided ruleset. Note that the enabled
|
||||
status is on the rules, and not the tags--if a rule R has
|
||||
tags (a, b), and you call enable_tags([a]) and then
|
||||
disable_tags([b]), R will be disabled despite the
|
||||
fact it has tag a and was enabled by the first call to
|
||||
enable_tags.
|
||||
\param substring Tags used to match ruless
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
\brief Find those rules matching the provided substring and enable
|
||||
them in the provided ruleset.
|
||||
\param pattern Pattern used to match rule names.
|
||||
\param match How to match the pattern against rules:
|
||||
- exact: rules that has the same exact name as the pattern are matched
|
||||
- substring: rules having the pattern as a substring in the rule are matched.
|
||||
An empty pattern matches all rules.
|
||||
- wildcard: rules with names that satisfies a wildcard (*) pattern are matched.
|
||||
A "*" pattern matches all rules.
|
||||
Wildcards can appear anywhere in the pattern (e.g. "*hello*world*")
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
*/
|
||||
virtual void enable_tags(
|
||||
const std::set<std::string> &tags,
|
||||
uint16_t ruleset_id) = 0;
|
||||
virtual void enable(const std::string &pattern, match_type match, uint16_t ruleset_id) = 0;
|
||||
|
||||
/*!
|
||||
\brief Find those rules that have a tag in the set of tags and
|
||||
disable them for the provided ruleset. Note that the disabled
|
||||
status is on the rules, and not the tags--if a rule R has
|
||||
tags (a, b), and you call enable_tags([a]) and then
|
||||
disable_tags([b]), R will be disabled despite the
|
||||
fact it has tag a and was enabled by the first call to
|
||||
enable_tags.
|
||||
\param substring Tags used to match ruless
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
\brief Find those rules matching the provided substring and disable
|
||||
them in the provided ruleset.
|
||||
\param pattern Pattern used to match rule names.
|
||||
\param match How to match the pattern against rules:
|
||||
- exact: rules that has the same exact name as the pattern are matched
|
||||
- substring: rules having the pattern as a substring in the rule are matched.
|
||||
An empty pattern matches all rules.
|
||||
- wildcard: rules with names that satisfies a wildcard (*) pattern are matched.
|
||||
A "*" pattern matches all rules.
|
||||
Wildcards can appear anywhere in the pattern (e.g. "*hello*world*")
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
*/
|
||||
virtual void disable_tags(
|
||||
const std::set<std::string> &tags,
|
||||
uint16_t ruleset_id) = 0;
|
||||
virtual void disable(const std::string &pattern, match_type match, uint16_t ruleset_id) = 0;
|
||||
|
||||
/*!
|
||||
\brief Find those rules that have a tag in the set of tags and
|
||||
enable them for the provided ruleset. Note that the enabled
|
||||
status is on the rules, and not the tags--if a rule R has
|
||||
tags (a, b), and you call enable_tags([a]) and then
|
||||
disable_tags([b]), R will be disabled despite the
|
||||
fact it has tag a and was enabled by the first call to
|
||||
enable_tags.
|
||||
\param substring Tags used to match ruless
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
*/
|
||||
virtual void enable_tags(const std::set<std::string> &tags, uint16_t ruleset_id) = 0;
|
||||
|
||||
/*!
|
||||
\brief Find those rules that have a tag in the set of tags and
|
||||
disable them for the provided ruleset. Note that the disabled
|
||||
status is on the rules, and not the tags--if a rule R has
|
||||
tags (a, b), and you call enable_tags([a]) and then
|
||||
disable_tags([b]), R will be disabled despite the
|
||||
fact it has tag a and was enabled by the first call to
|
||||
enable_tags.
|
||||
\param substring Tags used to match ruless
|
||||
\param ruleset_id The id of the ruleset to be used
|
||||
*/
|
||||
virtual void disable_tags(const std::set<std::string> &tags, uint16_t ruleset_id) = 0;
|
||||
|
||||
private:
|
||||
engine_state_funcs m_engine_state;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Represents a factory that creates filter_ruleset objects
|
||||
\brief Represents a factory that creates filter_ruleset objects
|
||||
*/
|
||||
class filter_ruleset_factory
|
||||
{
|
||||
class filter_ruleset_factory {
|
||||
public:
|
||||
virtual ~filter_ruleset_factory() = default;
|
||||
|
||||
|
||||
@@ -22,22 +22,18 @@ using namespace falco;
|
||||
|
||||
static const char* no_value = "<NA>";
|
||||
|
||||
static inline bool is_unsafe_field(const std::string& f)
|
||||
{
|
||||
return !strncmp(f.c_str(), "ka.", strlen("ka."))
|
||||
|| !strncmp(f.c_str(), "jevt.", strlen("jevt."));
|
||||
static inline bool is_unsafe_field(const std::string& f) {
|
||||
return !strncmp(f.c_str(), "ka.", strlen("ka.")) ||
|
||||
!strncmp(f.c_str(), "jevt.", strlen("jevt."));
|
||||
}
|
||||
|
||||
static inline bool is_equality_operator(const std::string& op)
|
||||
{
|
||||
return op == "==" || op == "=" || op == "!="
|
||||
|| op == "in" || op == "intersects" || op == "pmatch";
|
||||
static inline bool is_equality_operator(const std::string& op) {
|
||||
return op == "==" || op == "=" || op == "!=" || op == "in" || op == "intersects" ||
|
||||
op == "pmatch";
|
||||
}
|
||||
|
||||
bool filter_warning_resolver::run(
|
||||
libsinsp::filter::ast::expr* filter,
|
||||
std::set<load_result::warning_code>& warnings) const
|
||||
{
|
||||
bool filter_warning_resolver::run(libsinsp::filter::ast::expr* filter,
|
||||
std::set<load_result::warning_code>& warnings) const {
|
||||
visitor v;
|
||||
auto size = warnings.size();
|
||||
v.m_is_equality_check = false;
|
||||
@@ -46,40 +42,29 @@ bool filter_warning_resolver::run(
|
||||
return warnings.size() > size;
|
||||
}
|
||||
|
||||
void filter_warning_resolver::visitor::visit(
|
||||
libsinsp::filter::ast::binary_check_expr* e)
|
||||
{
|
||||
void filter_warning_resolver::visitor::visit(libsinsp::filter::ast::binary_check_expr* e) {
|
||||
m_last_node_is_unsafe_field = false;
|
||||
e->left->accept(this);
|
||||
if (m_last_node_is_unsafe_field && is_equality_operator(e->op))
|
||||
{
|
||||
if(m_last_node_is_unsafe_field && is_equality_operator(e->op)) {
|
||||
m_is_equality_check = true;
|
||||
e->right->accept(this);
|
||||
m_is_equality_check = false;
|
||||
}
|
||||
}
|
||||
|
||||
void filter_warning_resolver::visitor::visit(
|
||||
libsinsp::filter::ast::field_expr* e)
|
||||
{
|
||||
void filter_warning_resolver::visitor::visit(libsinsp::filter::ast::field_expr* e) {
|
||||
m_last_node_is_unsafe_field = is_unsafe_field(e->field);
|
||||
}
|
||||
|
||||
void filter_warning_resolver::visitor::visit(
|
||||
libsinsp::filter::ast::value_expr* e)
|
||||
{
|
||||
if (m_is_equality_check && e->value == no_value)
|
||||
{
|
||||
void filter_warning_resolver::visitor::visit(libsinsp::filter::ast::value_expr* e) {
|
||||
if(m_is_equality_check && e->value == no_value) {
|
||||
m_warnings->insert(load_result::LOAD_UNSAFE_NA_CHECK);
|
||||
}
|
||||
}
|
||||
|
||||
void filter_warning_resolver::visitor::visit(
|
||||
libsinsp::filter::ast::list_expr* e)
|
||||
{
|
||||
if (m_is_equality_check
|
||||
&& std::find(e->values.begin(), e->values.end(), no_value) != e->values.end())
|
||||
{
|
||||
void filter_warning_resolver::visitor::visit(libsinsp::filter::ast::list_expr* e) {
|
||||
if(m_is_equality_check &&
|
||||
std::find(e->values.begin(), e->values.end(), no_value) != e->values.end()) {
|
||||
m_warnings->insert(load_result::LOAD_UNSAFE_NA_CHECK);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,38 +25,35 @@ limitations under the License.
|
||||
#include "falco_load_result.h"
|
||||
|
||||
/*!
|
||||
\brief Searches for bad practices in filter conditions and
|
||||
generates warning messages
|
||||
\brief Searches for bad practices in filter conditions and
|
||||
generates warning messages
|
||||
*/
|
||||
class filter_warning_resolver
|
||||
{
|
||||
class filter_warning_resolver {
|
||||
public:
|
||||
/*!
|
||||
\brief Visits a filter AST and substitutes macro references
|
||||
according with all the definitions added through set_macro(),
|
||||
by replacing the reference with a clone of the macro AST.
|
||||
\param filter The filter AST to be visited
|
||||
\param warnings Set of strings to be filled with warning codes. This
|
||||
is not cleared up before the visit
|
||||
\param blocking Filled-out with true if at least one warning is
|
||||
found and at least one warning prevents the filter from being loaded
|
||||
\return true if at least one warning is generated
|
||||
\brief Visits a filter AST and substitutes macro references
|
||||
according with all the definitions added through set_macro(),
|
||||
by replacing the reference with a clone of the macro AST.
|
||||
\param filter The filter AST to be visited
|
||||
\param warnings Set of strings to be filled with warning codes. This
|
||||
is not cleared up before the visit
|
||||
\param blocking Filled-out with true if at least one warning is
|
||||
found and at least one warning prevents the filter from being loaded
|
||||
\return true if at least one warning is generated
|
||||
*/
|
||||
bool run(
|
||||
libsinsp::filter::ast::expr* filter,
|
||||
std::set<falco::load_result::warning_code>& warnings) const;
|
||||
bool run(libsinsp::filter::ast::expr* filter,
|
||||
std::set<falco::load_result::warning_code>& warnings) const;
|
||||
|
||||
private:
|
||||
struct visitor : public libsinsp::filter::ast::base_expr_visitor
|
||||
{
|
||||
struct visitor : public libsinsp::filter::ast::base_expr_visitor {
|
||||
visitor():
|
||||
m_is_equality_check(false),
|
||||
m_last_node_is_unsafe_field(false),
|
||||
m_warnings(nullptr) {}
|
||||
m_is_equality_check(false),
|
||||
m_last_node_is_unsafe_field(false),
|
||||
m_warnings(nullptr) {}
|
||||
visitor(visitor&&) = default;
|
||||
visitor& operator = (visitor&&) = default;
|
||||
visitor& operator=(visitor&&) = default;
|
||||
visitor(const visitor&) = delete;
|
||||
visitor& operator = (const visitor&) = delete;
|
||||
visitor& operator=(const visitor&) = delete;
|
||||
|
||||
bool m_is_equality_check;
|
||||
bool m_last_node_is_unsafe_field;
|
||||
|
||||
@@ -21,41 +21,37 @@ limitations under the License.
|
||||
#include "falco_engine.h"
|
||||
|
||||
falco_formats::falco_formats(std::shared_ptr<const falco_engine> engine,
|
||||
bool json_include_output_property,
|
||||
bool json_include_tags_property,
|
||||
bool json_include_message_property,
|
||||
bool time_format_iso_8601)
|
||||
: m_falco_engine(engine),
|
||||
m_json_include_output_property(json_include_output_property),
|
||||
m_json_include_tags_property(json_include_tags_property),
|
||||
m_json_include_message_property(json_include_message_property),
|
||||
m_time_format_iso_8601(time_format_iso_8601)
|
||||
{
|
||||
}
|
||||
bool json_include_output_property,
|
||||
bool json_include_tags_property,
|
||||
bool json_include_message_property,
|
||||
bool time_format_iso_8601):
|
||||
m_falco_engine(engine),
|
||||
m_json_include_output_property(json_include_output_property),
|
||||
m_json_include_tags_property(json_include_tags_property),
|
||||
m_json_include_message_property(json_include_message_property),
|
||||
m_time_format_iso_8601(time_format_iso_8601) {}
|
||||
|
||||
falco_formats::~falco_formats()
|
||||
{
|
||||
}
|
||||
falco_formats::~falco_formats() {}
|
||||
|
||||
std::string falco_formats::format_event(sinsp_evt *evt, const std::string &rule, const std::string &source,
|
||||
const std::string &level, const std::string &format, const std::set<std::string> &tags,
|
||||
const std::string &hostname, const extra_output_field_t &extra_fields) const
|
||||
{
|
||||
std::string falco_formats::format_event(sinsp_evt *evt,
|
||||
const std::string &rule,
|
||||
const std::string &source,
|
||||
const std::string &level,
|
||||
const std::string &format,
|
||||
const std::set<std::string> &tags,
|
||||
const std::string &hostname,
|
||||
const extra_output_field_t &extra_fields) const {
|
||||
std::string prefix_format;
|
||||
std::string message_format = format;
|
||||
|
||||
if(m_time_format_iso_8601)
|
||||
{
|
||||
if(m_time_format_iso_8601) {
|
||||
prefix_format = "*%evt.time.iso8601: ";
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
prefix_format = "*%evt.time: ";
|
||||
}
|
||||
prefix_format += level;
|
||||
|
||||
if(message_format[0] != '*')
|
||||
{
|
||||
if(message_format[0] != '*') {
|
||||
message_format = "*" + message_format;
|
||||
}
|
||||
|
||||
@@ -72,15 +68,13 @@ std::string falco_formats::format_event(sinsp_evt *evt, const std::string &rule,
|
||||
std::string message;
|
||||
message_formatter->tostring_withformat(evt, message, sinsp_evt_formatter::OF_NORMAL);
|
||||
|
||||
// The complete Falco output, e.g. "13:53:31.726060287: Critical Some Event Description (proc_exe=bash)..."
|
||||
// The complete Falco output, e.g. "13:53:31.726060287: Critical Some Event Description
|
||||
// (proc_exe=bash)..."
|
||||
std::string output = prefix + " " + message;
|
||||
|
||||
if(message_formatter->get_output_format() == sinsp_evt_formatter::OF_NORMAL)
|
||||
{
|
||||
if(message_formatter->get_output_format() == sinsp_evt_formatter::OF_NORMAL) {
|
||||
return output;
|
||||
}
|
||||
else if(message_formatter->get_output_format() == sinsp_evt_formatter::OF_JSON)
|
||||
{
|
||||
} else if(message_formatter->get_output_format() == sinsp_evt_formatter::OF_JSON) {
|
||||
std::string json_fields_message;
|
||||
std::string json_fields_prefix;
|
||||
|
||||
@@ -98,8 +92,8 @@ std::string falco_formats::format_event(sinsp_evt *evt, const std::string &rule,
|
||||
|
||||
// Convert the time-as-nanoseconds to a more json-friendly ISO8601.
|
||||
time_t evttime = evt->get_ts() / 1000000000;
|
||||
char time_sec[20]; // sizeof "YYYY-MM-DDTHH:MM:SS"
|
||||
char time_ns[12]; // sizeof ".sssssssssZ"
|
||||
char time_sec[20]; // sizeof "YYYY-MM-DDTHH:MM:SS"
|
||||
char time_ns[12]; // sizeof ".sssssssssZ"
|
||||
std::string iso8601evttime;
|
||||
|
||||
strftime(time_sec, sizeof(time_sec), "%FT%T", gmtime(&evttime));
|
||||
@@ -112,52 +106,47 @@ std::string falco_formats::format_event(sinsp_evt *evt, const std::string &rule,
|
||||
event["source"] = source;
|
||||
event["hostname"] = hostname;
|
||||
|
||||
if(m_json_include_output_property)
|
||||
{
|
||||
if(m_json_include_output_property) {
|
||||
event["output"] = output;
|
||||
}
|
||||
|
||||
if(m_json_include_tags_property)
|
||||
{
|
||||
if(m_json_include_tags_property) {
|
||||
event["tags"] = tags;
|
||||
}
|
||||
|
||||
if(m_json_include_message_property)
|
||||
{
|
||||
if(m_json_include_message_property) {
|
||||
event["message"] = message;
|
||||
}
|
||||
|
||||
event["output_fields"] = nlohmann::json::parse(json_fields_message);
|
||||
|
||||
auto prefix_fields = nlohmann::json::parse(json_fields_prefix);
|
||||
if (prefix_fields.is_object()) {
|
||||
for (auto const& el : prefix_fields.items()) {
|
||||
if(prefix_fields.is_object()) {
|
||||
for(auto const &el : prefix_fields.items()) {
|
||||
event["output_fields"][el.key()] = el.value();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto const& ef : extra_fields)
|
||||
{
|
||||
for(auto const &ef : extra_fields) {
|
||||
std::string fformat = ef.second.first;
|
||||
if (fformat.size() == 0)
|
||||
{
|
||||
if(fformat.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(fformat[0] == '*'))
|
||||
{
|
||||
if(!(fformat[0] == '*')) {
|
||||
fformat = "*" + fformat;
|
||||
}
|
||||
|
||||
if(ef.second.second) // raw field
|
||||
if(ef.second.second) // raw field
|
||||
{
|
||||
std::string json_field_map;
|
||||
auto field_formatter = m_falco_engine->create_formatter(source, fformat);
|
||||
field_formatter->tostring_withformat(evt, json_field_map, sinsp_evt_formatter::OF_JSON);
|
||||
field_formatter->tostring_withformat(evt,
|
||||
json_field_map,
|
||||
sinsp_evt_formatter::OF_JSON);
|
||||
auto json_obj = nlohmann::json::parse(json_field_map);
|
||||
event["output_fields"][ef.first] = json_obj[ef.first];
|
||||
} else
|
||||
{
|
||||
} else {
|
||||
event["output_fields"][ef.first] = format_string(evt, fformat, source);
|
||||
}
|
||||
}
|
||||
@@ -169,8 +158,9 @@ std::string falco_formats::format_event(sinsp_evt *evt, const std::string &rule,
|
||||
return "INVALID_OUTPUT_FORMAT";
|
||||
}
|
||||
|
||||
std::string falco_formats::format_string(sinsp_evt *evt, const std::string &format, const std::string &source) const
|
||||
{
|
||||
std::string falco_formats::format_string(sinsp_evt *evt,
|
||||
const std::string &format,
|
||||
const std::string &source) const {
|
||||
std::string line;
|
||||
std::shared_ptr<sinsp_evt_formatter> formatter;
|
||||
|
||||
@@ -180,14 +170,14 @@ std::string falco_formats::format_string(sinsp_evt *evt, const std::string &form
|
||||
return line;
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> falco_formats::get_field_values(sinsp_evt *evt, const std::string &source,
|
||||
const std::string &format) const
|
||||
{
|
||||
std::map<std::string, std::string> falco_formats::get_field_values(
|
||||
sinsp_evt *evt,
|
||||
const std::string &source,
|
||||
const std::string &format) const {
|
||||
std::shared_ptr<sinsp_evt_formatter> formatter;
|
||||
|
||||
std::string fformat = format;
|
||||
if(fformat[0] != '*')
|
||||
{
|
||||
if(fformat[0] != '*') {
|
||||
fformat = "*" + fformat;
|
||||
}
|
||||
|
||||
@@ -195,8 +185,7 @@ std::map<std::string, std::string> falco_formats::get_field_values(sinsp_evt *ev
|
||||
|
||||
std::map<std::string, std::string> ret;
|
||||
|
||||
if (! formatter->get_field_values(evt, ret))
|
||||
{
|
||||
if(!formatter->get_field_values(evt, ret)) {
|
||||
throw falco_exception("Could not extract all field values from event");
|
||||
}
|
||||
|
||||
|
||||
@@ -21,24 +21,31 @@ limitations under the License.
|
||||
#include <map>
|
||||
#include "falco_engine.h"
|
||||
|
||||
class falco_formats
|
||||
{
|
||||
class falco_formats {
|
||||
public:
|
||||
falco_formats(std::shared_ptr<const falco_engine> engine,
|
||||
bool json_include_output_property,
|
||||
bool json_include_tags_property,
|
||||
bool json_include_message_property,
|
||||
bool time_format_iso_8601);
|
||||
bool json_include_output_property,
|
||||
bool json_include_tags_property,
|
||||
bool json_include_message_property,
|
||||
bool time_format_iso_8601);
|
||||
virtual ~falco_formats();
|
||||
|
||||
std::string format_event(sinsp_evt *evt, const std::string &rule, const std::string &source,
|
||||
const std::string &level, const std::string &format, const std::set<std::string> &tags,
|
||||
const std::string &hostname, const extra_output_field_t &extra_fields) const;
|
||||
std::string format_event(sinsp_evt *evt,
|
||||
const std::string &rule,
|
||||
const std::string &source,
|
||||
const std::string &level,
|
||||
const std::string &format,
|
||||
const std::set<std::string> &tags,
|
||||
const std::string &hostname,
|
||||
const extra_output_field_t &extra_fields) const;
|
||||
|
||||
std::string format_string(sinsp_evt *evt, const std::string &format, const std::string &source) const;
|
||||
std::string format_string(sinsp_evt *evt,
|
||||
const std::string &format,
|
||||
const std::string &source) const;
|
||||
|
||||
std::map<std::string, std::string> get_field_values(sinsp_evt *evt, const std::string &source,
|
||||
const std::string &format) const ;
|
||||
std::map<std::string, std::string> get_field_values(sinsp_evt *evt,
|
||||
const std::string &source,
|
||||
const std::string &format) const;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<const falco_engine> m_falco_engine;
|
||||
|
||||
@@ -43,139 +43,98 @@ limitations under the License.
|
||||
// const libsinsp::events::set<ppm_event_code> &filter_wrapper::event_codes();
|
||||
|
||||
template<class filter_wrapper>
|
||||
class indexable_ruleset : public filter_ruleset
|
||||
{
|
||||
class indexable_ruleset : public filter_ruleset {
|
||||
public:
|
||||
indexable_ruleset() = default;
|
||||
virtual ~indexable_ruleset() = default;
|
||||
|
||||
// Required to implement filter_ruleset
|
||||
void clear() override
|
||||
{
|
||||
for(size_t i = 0; i < m_rulesets.size(); i++)
|
||||
{
|
||||
void clear() override {
|
||||
for(size_t i = 0; i < m_rulesets.size(); i++) {
|
||||
m_rulesets[i] = std::make_shared<ruleset_filters>(i);
|
||||
}
|
||||
m_filters.clear();
|
||||
}
|
||||
|
||||
uint64_t enabled_count(uint16_t ruleset_id) override
|
||||
{
|
||||
while(m_rulesets.size() < (size_t)ruleset_id + 1)
|
||||
{
|
||||
uint64_t enabled_count(uint16_t ruleset_id) override {
|
||||
while(m_rulesets.size() < (size_t)ruleset_id + 1) {
|
||||
m_rulesets.emplace_back(std::make_shared<ruleset_filters>(m_rulesets.size()));
|
||||
}
|
||||
|
||||
return m_rulesets[ruleset_id]->num_filters();
|
||||
}
|
||||
|
||||
void enabled_evttypes(
|
||||
std::set<uint16_t> &evttypes,
|
||||
uint16_t ruleset_id) override
|
||||
{
|
||||
void enabled_evttypes(std::set<uint16_t> &evttypes, uint16_t ruleset_id) override {
|
||||
evttypes.clear();
|
||||
for(const auto &e : enabled_event_codes(ruleset_id))
|
||||
{
|
||||
for(const auto &e : enabled_event_codes(ruleset_id)) {
|
||||
evttypes.insert((uint16_t)e);
|
||||
}
|
||||
}
|
||||
|
||||
libsinsp::events::set<ppm_sc_code> enabled_sc_codes(
|
||||
uint16_t ruleset_id) override
|
||||
{
|
||||
if(m_rulesets.size() < (size_t)ruleset_id + 1)
|
||||
{
|
||||
libsinsp::events::set<ppm_sc_code> enabled_sc_codes(uint16_t ruleset_id) override {
|
||||
if(m_rulesets.size() < (size_t)ruleset_id + 1) {
|
||||
return {};
|
||||
}
|
||||
return m_rulesets[ruleset_id]->sc_codes();
|
||||
}
|
||||
|
||||
libsinsp::events::set<ppm_event_code> enabled_event_codes(
|
||||
uint16_t ruleset_id) override
|
||||
{
|
||||
if(m_rulesets.size() < (size_t)ruleset_id + 1)
|
||||
{
|
||||
libsinsp::events::set<ppm_event_code> enabled_event_codes(uint16_t ruleset_id) override {
|
||||
if(m_rulesets.size() < (size_t)ruleset_id + 1) {
|
||||
return {};
|
||||
}
|
||||
return m_rulesets[ruleset_id]->event_codes();
|
||||
}
|
||||
|
||||
void enable(
|
||||
const std::string &pattern,
|
||||
match_type match,
|
||||
uint16_t ruleset_id) override
|
||||
{
|
||||
void enable(const std::string &pattern, match_type match, uint16_t ruleset_id) override {
|
||||
enable_disable(pattern, match, true, ruleset_id);
|
||||
}
|
||||
|
||||
void disable(
|
||||
const std::string &pattern,
|
||||
match_type match,
|
||||
uint16_t ruleset_id) override
|
||||
{
|
||||
void disable(const std::string &pattern, match_type match, uint16_t ruleset_id) override {
|
||||
enable_disable(pattern, match, false, ruleset_id);
|
||||
}
|
||||
|
||||
void enable_tags(
|
||||
const std::set<std::string> &tags,
|
||||
uint16_t ruleset_id) override
|
||||
{
|
||||
void enable_tags(const std::set<std::string> &tags, uint16_t ruleset_id) override {
|
||||
enable_disable_tags(tags, true, ruleset_id);
|
||||
}
|
||||
|
||||
void disable_tags(
|
||||
const std::set<std::string> &tags,
|
||||
uint16_t ruleset_id) override
|
||||
{
|
||||
void disable_tags(const std::set<std::string> &tags, uint16_t ruleset_id) override {
|
||||
enable_disable_tags(tags, false, ruleset_id);
|
||||
}
|
||||
|
||||
// Note that subclasses do *not* implement run. Instead, they
|
||||
// implement run_wrappers.
|
||||
bool run(sinsp_evt *evt, falco_rule &match, uint16_t ruleset_id) override
|
||||
{
|
||||
if(m_rulesets.size() < (size_t)ruleset_id + 1)
|
||||
{
|
||||
bool run(sinsp_evt *evt, falco_rule &match, uint16_t ruleset_id) override {
|
||||
if(m_rulesets.size() < (size_t)ruleset_id + 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_rulesets[ruleset_id]->run(*this, evt, match);
|
||||
}
|
||||
|
||||
bool run(sinsp_evt *evt, std::vector<falco_rule> &matches, uint16_t ruleset_id) override
|
||||
{
|
||||
if(m_rulesets.size() < (size_t)ruleset_id + 1)
|
||||
{
|
||||
bool run(sinsp_evt *evt, std::vector<falco_rule> &matches, uint16_t ruleset_id) override {
|
||||
if(m_rulesets.size() < (size_t)ruleset_id + 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_rulesets[ruleset_id]->run(*this, evt, matches);
|
||||
}
|
||||
|
||||
typedef std::list<std::shared_ptr<filter_wrapper>>
|
||||
filter_wrapper_list;
|
||||
typedef std::list<std::shared_ptr<filter_wrapper>> filter_wrapper_list;
|
||||
|
||||
// Subclasses should call add_wrapper (most likely from
|
||||
// filter_ruleset::add or ::add_compile_output) to add filters.
|
||||
void add_wrapper(std::shared_ptr<filter_wrapper> wrap)
|
||||
{
|
||||
m_filters.insert(wrap);
|
||||
}
|
||||
void add_wrapper(std::shared_ptr<filter_wrapper> wrap) { m_filters.insert(wrap); }
|
||||
|
||||
// If a subclass needs to iterate over all filters, they can
|
||||
// call iterate with this function, which will be called for
|
||||
// all filters.
|
||||
typedef std::function<void(const std::shared_ptr<filter_wrapper> &wrap)> filter_wrapper_func;
|
||||
uint64_t iterate(filter_wrapper_func func)
|
||||
{
|
||||
uint64_t iterate(filter_wrapper_func func) {
|
||||
uint64_t num_filters = 0;
|
||||
|
||||
for(const auto &ruleset_ptr : m_rulesets)
|
||||
{
|
||||
if(ruleset_ptr)
|
||||
{
|
||||
for(const auto &wrap : ruleset_ptr->get_filters())
|
||||
{
|
||||
for(const auto &ruleset_ptr : m_rulesets) {
|
||||
if(ruleset_ptr) {
|
||||
for(const auto &wrap : ruleset_ptr->get_filters()) {
|
||||
num_filters++;
|
||||
func(wrap);
|
||||
}
|
||||
@@ -188,34 +147,34 @@ public:
|
||||
// A subclass must implement these methods. They are analogous
|
||||
// to run() but take care of selecting filters that match a
|
||||
// ruleset and possibly an event type.
|
||||
virtual bool run_wrappers(sinsp_evt *evt, filter_wrapper_list &wrappers, uint16_t ruleset_id, std::vector<falco_rule> &matches) = 0;
|
||||
virtual bool run_wrappers(sinsp_evt *evt, filter_wrapper_list &wrappers, uint16_t ruleset_id, falco_rule &match) = 0;
|
||||
virtual bool run_wrappers(sinsp_evt *evt,
|
||||
filter_wrapper_list &wrappers,
|
||||
uint16_t ruleset_id,
|
||||
std::vector<falco_rule> &matches) = 0;
|
||||
virtual bool run_wrappers(sinsp_evt *evt,
|
||||
filter_wrapper_list &wrappers,
|
||||
uint16_t ruleset_id,
|
||||
falco_rule &match) = 0;
|
||||
|
||||
private:
|
||||
// Helper used by enable()/disable()
|
||||
void enable_disable(
|
||||
const std::string &pattern,
|
||||
match_type match,
|
||||
bool enabled,
|
||||
uint16_t ruleset_id)
|
||||
{
|
||||
while(m_rulesets.size() < (size_t)ruleset_id + 1)
|
||||
{
|
||||
void enable_disable(const std::string &pattern,
|
||||
match_type match,
|
||||
bool enabled,
|
||||
uint16_t ruleset_id) {
|
||||
while(m_rulesets.size() < (size_t)ruleset_id + 1) {
|
||||
m_rulesets.emplace_back(std::make_shared<ruleset_filters>(m_rulesets.size()));
|
||||
}
|
||||
|
||||
for(const auto &wrap : m_filters)
|
||||
{
|
||||
for(const auto &wrap : m_filters) {
|
||||
bool matches;
|
||||
std::string::size_type pos;
|
||||
|
||||
switch(match)
|
||||
{
|
||||
switch(match) {
|
||||
case match_type::exact:
|
||||
pos = wrap->name().find(pattern);
|
||||
|
||||
matches = (pattern == "" || (pos == 0 &&
|
||||
pattern.size() == wrap->name().size()));
|
||||
matches = (pattern == "" || (pos == 0 && pattern.size() == wrap->name().size()));
|
||||
break;
|
||||
case match_type::substring:
|
||||
matches = (pattern == "" || (wrap->name().find(pattern) != std::string::npos));
|
||||
@@ -228,14 +187,10 @@ private:
|
||||
matches = false;
|
||||
}
|
||||
|
||||
if(matches)
|
||||
{
|
||||
if(enabled)
|
||||
{
|
||||
if(matches) {
|
||||
if(enabled) {
|
||||
m_rulesets[ruleset_id]->add_filter(wrap);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
m_rulesets[ruleset_id]->remove_filter(wrap);
|
||||
}
|
||||
}
|
||||
@@ -243,32 +198,24 @@ private:
|
||||
}
|
||||
|
||||
// Helper used by enable_tags()/disable_tags()
|
||||
void enable_disable_tags(
|
||||
const std::set<std::string> &tags,
|
||||
bool enabled,
|
||||
uint16_t ruleset_id)
|
||||
{
|
||||
while(m_rulesets.size() < (size_t)ruleset_id + 1)
|
||||
{
|
||||
void enable_disable_tags(const std::set<std::string> &tags, bool enabled, uint16_t ruleset_id) {
|
||||
while(m_rulesets.size() < (size_t)ruleset_id + 1) {
|
||||
m_rulesets.emplace_back(std::make_shared<ruleset_filters>(m_rulesets.size()));
|
||||
}
|
||||
|
||||
for(const auto &wrap : m_filters)
|
||||
{
|
||||
for(const auto &wrap : m_filters) {
|
||||
std::set<std::string> intersect;
|
||||
|
||||
set_intersection(tags.begin(), tags.end(),
|
||||
wrap->tags().begin(), wrap->tags().end(),
|
||||
inserter(intersect, intersect.begin()));
|
||||
set_intersection(tags.begin(),
|
||||
tags.end(),
|
||||
wrap->tags().begin(),
|
||||
wrap->tags().end(),
|
||||
inserter(intersect, intersect.begin()));
|
||||
|
||||
if(!intersect.empty())
|
||||
{
|
||||
if(enabled)
|
||||
{
|
||||
if(!intersect.empty()) {
|
||||
if(enabled) {
|
||||
m_rulesets[ruleset_id]->add_filter(wrap);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
m_rulesets[ruleset_id]->remove_filter(wrap);
|
||||
}
|
||||
}
|
||||
@@ -276,27 +223,19 @@ private:
|
||||
}
|
||||
|
||||
// A group of filters all having the same ruleset
|
||||
class ruleset_filters
|
||||
{
|
||||
class ruleset_filters {
|
||||
public:
|
||||
ruleset_filters(uint16_t ruleset_id):
|
||||
m_ruleset_id(ruleset_id) {}
|
||||
ruleset_filters(uint16_t ruleset_id): m_ruleset_id(ruleset_id) {}
|
||||
|
||||
virtual ~ruleset_filters(){};
|
||||
virtual ~ruleset_filters() {};
|
||||
|
||||
void add_filter(std::shared_ptr<filter_wrapper> wrap)
|
||||
{
|
||||
if(wrap->event_codes().empty())
|
||||
{
|
||||
void add_filter(std::shared_ptr<filter_wrapper> wrap) {
|
||||
if(wrap->event_codes().empty()) {
|
||||
// Should run for all event types
|
||||
add_wrapper_to_list(m_filter_all_event_types, wrap);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(auto &etype : wrap->event_codes())
|
||||
{
|
||||
if(m_filter_by_event_type.size() <= etype)
|
||||
{
|
||||
} else {
|
||||
for(auto &etype : wrap->event_codes()) {
|
||||
if(m_filter_by_event_type.size() <= etype) {
|
||||
m_filter_by_event_type.resize(etype + 1);
|
||||
}
|
||||
|
||||
@@ -307,18 +246,12 @@ private:
|
||||
m_filters.insert(wrap);
|
||||
}
|
||||
|
||||
void remove_filter(std::shared_ptr<filter_wrapper> wrap)
|
||||
{
|
||||
if(wrap->event_codes().empty())
|
||||
{
|
||||
void remove_filter(std::shared_ptr<filter_wrapper> wrap) {
|
||||
if(wrap->event_codes().empty()) {
|
||||
remove_wrapper_from_list(m_filter_all_event_types, wrap);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(auto &etype : wrap->event_codes())
|
||||
{
|
||||
if(etype < m_filter_by_event_type.size())
|
||||
{
|
||||
} else {
|
||||
for(auto &etype : wrap->event_codes()) {
|
||||
if(etype < m_filter_by_event_type.size()) {
|
||||
remove_wrapper_from_list(m_filter_by_event_type[etype], wrap);
|
||||
}
|
||||
}
|
||||
@@ -327,34 +260,28 @@ private:
|
||||
m_filters.erase(wrap);
|
||||
}
|
||||
|
||||
uint64_t num_filters()
|
||||
{
|
||||
return m_filters.size();
|
||||
}
|
||||
uint64_t num_filters() { return m_filters.size(); }
|
||||
|
||||
inline const std::set<std::shared_ptr<filter_wrapper>> &get_filters() const
|
||||
{
|
||||
inline const std::set<std::shared_ptr<filter_wrapper>> &get_filters() const {
|
||||
return m_filters;
|
||||
}
|
||||
|
||||
// Evaluate an event against the ruleset and return the first rule
|
||||
// that matched.
|
||||
bool run(indexable_ruleset &ruleset, sinsp_evt *evt, falco_rule &match)
|
||||
{
|
||||
bool run(indexable_ruleset &ruleset, sinsp_evt *evt, falco_rule &match) {
|
||||
if(evt->get_type() < m_filter_by_event_type.size() &&
|
||||
m_filter_by_event_type[evt->get_type()].size() > 0)
|
||||
{
|
||||
if(ruleset.run_wrappers(evt, m_filter_by_event_type[evt->get_type()], m_ruleset_id, match))
|
||||
{
|
||||
m_filter_by_event_type[evt->get_type()].size() > 0) {
|
||||
if(ruleset.run_wrappers(evt,
|
||||
m_filter_by_event_type[evt->get_type()],
|
||||
m_ruleset_id,
|
||||
match)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, try filters that are not specific to an event type.
|
||||
if(m_filter_all_event_types.size() > 0)
|
||||
{
|
||||
if(ruleset.run_wrappers(evt, m_filter_all_event_types, m_ruleset_id, match))
|
||||
{
|
||||
if(m_filter_all_event_types.size() > 0) {
|
||||
if(ruleset.run_wrappers(evt, m_filter_all_event_types, m_ruleset_id, match)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -364,22 +291,20 @@ private:
|
||||
|
||||
// Evaluate an event against the ruleset and return all the
|
||||
// matching rules.
|
||||
bool run(indexable_ruleset &ruleset, sinsp_evt *evt, std::vector<falco_rule> &matches)
|
||||
{
|
||||
bool run(indexable_ruleset &ruleset, sinsp_evt *evt, std::vector<falco_rule> &matches) {
|
||||
if(evt->get_type() < m_filter_by_event_type.size() &&
|
||||
m_filter_by_event_type[evt->get_type()].size() > 0)
|
||||
{
|
||||
if(ruleset.run_wrappers(evt, m_filter_by_event_type[evt->get_type()], m_ruleset_id, matches))
|
||||
{
|
||||
m_filter_by_event_type[evt->get_type()].size() > 0) {
|
||||
if(ruleset.run_wrappers(evt,
|
||||
m_filter_by_event_type[evt->get_type()],
|
||||
m_ruleset_id,
|
||||
matches)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, try filters that are not specific to an event type.
|
||||
if(m_filter_all_event_types.size() > 0)
|
||||
{
|
||||
if(ruleset.run_wrappers(evt, m_filter_all_event_types, m_ruleset_id, matches))
|
||||
{
|
||||
if(m_filter_all_event_types.size() > 0) {
|
||||
if(ruleset.run_wrappers(evt, m_filter_all_event_types, m_ruleset_id, matches)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -387,49 +312,39 @@ private:
|
||||
return false;
|
||||
}
|
||||
|
||||
libsinsp::events::set<ppm_sc_code> sc_codes()
|
||||
{
|
||||
libsinsp::events::set<ppm_sc_code> sc_codes() {
|
||||
libsinsp::events::set<ppm_sc_code> res;
|
||||
for(const auto &wrap : m_filters)
|
||||
{
|
||||
for(const auto &wrap : m_filters) {
|
||||
res.insert(wrap->sc_codes().begin(), wrap->sc_codes().end());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
libsinsp::events::set<ppm_event_code> event_codes()
|
||||
{
|
||||
libsinsp::events::set<ppm_event_code> event_codes() {
|
||||
libsinsp::events::set<ppm_event_code> res;
|
||||
for(const auto &wrap : m_filters)
|
||||
{
|
||||
for(const auto &wrap : m_filters) {
|
||||
res.insert(wrap->event_codes().begin(), wrap->event_codes().end());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
void add_wrapper_to_list(filter_wrapper_list &wrappers, std::shared_ptr<filter_wrapper> wrap)
|
||||
{
|
||||
void add_wrapper_to_list(filter_wrapper_list &wrappers,
|
||||
std::shared_ptr<filter_wrapper> wrap) {
|
||||
// This is O(n) but it's also uncommon
|
||||
// (when loading rules only).
|
||||
auto pos = std::find(wrappers.begin(),
|
||||
wrappers.end(),
|
||||
wrap);
|
||||
auto pos = std::find(wrappers.begin(), wrappers.end(), wrap);
|
||||
|
||||
if(pos == wrappers.end())
|
||||
{
|
||||
if(pos == wrappers.end()) {
|
||||
wrappers.push_back(wrap);
|
||||
}
|
||||
}
|
||||
|
||||
void remove_wrapper_from_list(filter_wrapper_list &wrappers, std::shared_ptr<filter_wrapper> wrap)
|
||||
{
|
||||
void remove_wrapper_from_list(filter_wrapper_list &wrappers,
|
||||
std::shared_ptr<filter_wrapper> wrap) {
|
||||
// This is O(n) but it's also uncommon
|
||||
// (when loading rules only).
|
||||
auto pos = std::find(wrappers.begin(),
|
||||
wrappers.end(),
|
||||
wrap);
|
||||
if(pos != wrappers.end())
|
||||
{
|
||||
auto pos = std::find(wrappers.begin(), wrappers.end(), wrap);
|
||||
if(pos != wrappers.end()) {
|
||||
wrappers.erase(pos);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,63 +22,54 @@ limitations under the License.
|
||||
#include <unordered_map>
|
||||
|
||||
/*!
|
||||
\brief Simple wrapper of std::vector that allows random access
|
||||
through both numeric and string indexes with O(1) complexity
|
||||
\brief Simple wrapper of std::vector that allows random access
|
||||
through both numeric and string indexes with O(1) complexity
|
||||
*/
|
||||
template <typename T>
|
||||
class indexed_vector
|
||||
{
|
||||
template<typename T>
|
||||
class indexed_vector {
|
||||
public:
|
||||
indexed_vector() = default;
|
||||
virtual ~indexed_vector() = default;
|
||||
indexed_vector(indexed_vector&&) = default;
|
||||
indexed_vector& operator = (indexed_vector&&) = default;
|
||||
indexed_vector& operator=(indexed_vector&&) = default;
|
||||
indexed_vector(const indexed_vector&) = default;
|
||||
indexed_vector& operator = (const indexed_vector&) = default;
|
||||
indexed_vector& operator=(const indexed_vector&) = default;
|
||||
|
||||
/*!
|
||||
\brief Returns the number of elements
|
||||
\brief Returns the number of elements
|
||||
*/
|
||||
virtual inline size_t size() const
|
||||
{
|
||||
return m_entries.size();
|
||||
}
|
||||
virtual inline size_t size() const { return m_entries.size(); }
|
||||
|
||||
/*!
|
||||
\brief Returns true if the vector is empty
|
||||
\brief Returns true if the vector is empty
|
||||
*/
|
||||
virtual inline bool empty() const
|
||||
{
|
||||
return m_entries.empty();
|
||||
}
|
||||
virtual inline bool empty() const { return m_entries.empty(); }
|
||||
|
||||
/*!
|
||||
\brief Removes all the elements
|
||||
\brief Removes all the elements
|
||||
*/
|
||||
virtual inline void clear()
|
||||
{
|
||||
virtual inline void clear() {
|
||||
m_entries.clear();
|
||||
m_index.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Inserts a new element in the vector with a given string index
|
||||
and returns its numeric index. String indexes are unique in
|
||||
the vector. If no element is already present with the given string
|
||||
index, then the provided element is added to the vector and its
|
||||
numeric index is assigned as the next free slot in the vector.
|
||||
Otherwise, the existing element gets overwritten with the contents
|
||||
of the provided one and the numeric index of the existing element
|
||||
is returned.
|
||||
\param entry Element to add in the vector
|
||||
\param index String index of the element to be added in the vector
|
||||
\return The numeric index assigned to the element
|
||||
\brief Inserts a new element in the vector with a given string index
|
||||
and returns its numeric index. String indexes are unique in
|
||||
the vector. If no element is already present with the given string
|
||||
index, then the provided element is added to the vector and its
|
||||
numeric index is assigned as the next free slot in the vector.
|
||||
Otherwise, the existing element gets overwritten with the contents
|
||||
of the provided one and the numeric index of the existing element
|
||||
is returned.
|
||||
\param entry Element to add in the vector
|
||||
\param index String index of the element to be added in the vector
|
||||
\return The numeric index assigned to the element
|
||||
*/
|
||||
virtual inline size_t insert(const T& entry, const std::string& index)
|
||||
{
|
||||
virtual inline size_t insert(const T& entry, const std::string& index) {
|
||||
size_t id;
|
||||
auto prev = m_index.find(index);
|
||||
if (prev != m_index.end()) {
|
||||
if(prev != m_index.end()) {
|
||||
id = prev->second;
|
||||
m_entries[id] = entry;
|
||||
return id;
|
||||
@@ -90,50 +81,37 @@ public:
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Returns a pointer to the element at the given numeric index,
|
||||
or nullptr if no element exists at the given index.
|
||||
\brief Returns a pointer to the element at the given numeric index,
|
||||
or nullptr if no element exists at the given index.
|
||||
*/
|
||||
virtual inline T* at(size_t id) const
|
||||
{
|
||||
if (id < m_entries.size())
|
||||
{
|
||||
return (T* const) &m_entries[id];
|
||||
virtual inline T* at(size_t id) const {
|
||||
if(id < m_entries.size()) {
|
||||
return (T* const)&m_entries[id];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Returns a pointer to the element at the given string index,
|
||||
or nullptr if no element exists at the given index.
|
||||
\brief Returns a pointer to the element at the given string index,
|
||||
or nullptr if no element exists at the given index.
|
||||
*/
|
||||
virtual inline T* at(const std::string& index) const
|
||||
{
|
||||
virtual inline T* at(const std::string& index) const {
|
||||
auto it = m_index.find(index);
|
||||
if (it != m_index.end()) {
|
||||
if(it != m_index.end()) {
|
||||
return at(it->second);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual inline typename std::vector<T>::iterator begin()
|
||||
{
|
||||
virtual inline typename std::vector<T>::iterator begin() { return m_entries.begin(); }
|
||||
|
||||
virtual inline typename std::vector<T>::iterator end() { return m_entries.end(); }
|
||||
|
||||
virtual inline typename std::vector<T>::const_iterator begin() const {
|
||||
return m_entries.begin();
|
||||
}
|
||||
|
||||
virtual inline typename std::vector<T>::iterator end()
|
||||
{
|
||||
return m_entries.end();
|
||||
}
|
||||
|
||||
virtual inline typename std::vector<T>::const_iterator begin() const
|
||||
{
|
||||
return m_entries.begin();
|
||||
}
|
||||
|
||||
virtual inline typename std::vector<T>::const_iterator end() const
|
||||
{
|
||||
return m_entries.end();
|
||||
}
|
||||
virtual inline typename std::vector<T>::const_iterator end() const { return m_entries.end(); }
|
||||
|
||||
private:
|
||||
std::vector<T> m_entries;
|
||||
|
||||
@@ -23,133 +23,89 @@ limitations under the License.
|
||||
falco_logger::level falco_logger::current_level = falco_logger::level::INFO;
|
||||
bool falco_logger::time_format_iso_8601 = false;
|
||||
|
||||
static sinsp_logger::severity decode_sinsp_severity(const std::string& s)
|
||||
{
|
||||
if(s == "trace")
|
||||
{
|
||||
static sinsp_logger::severity decode_sinsp_severity(const std::string& s) {
|
||||
if(s == "trace") {
|
||||
return sinsp_logger::SEV_TRACE;
|
||||
}
|
||||
else if(s == "debug")
|
||||
{
|
||||
} else if(s == "debug") {
|
||||
return sinsp_logger::SEV_DEBUG;
|
||||
}
|
||||
else if(s == "info")
|
||||
{
|
||||
} else if(s == "info") {
|
||||
return sinsp_logger::SEV_INFO;
|
||||
}
|
||||
else if(s == "notice")
|
||||
{
|
||||
} else if(s == "notice") {
|
||||
return sinsp_logger::SEV_NOTICE;
|
||||
}
|
||||
else if(s == "warning")
|
||||
{
|
||||
} else if(s == "warning") {
|
||||
return sinsp_logger::SEV_WARNING;
|
||||
}
|
||||
else if(s == "error")
|
||||
{
|
||||
} else if(s == "error") {
|
||||
return sinsp_logger::SEV_ERROR;
|
||||
}
|
||||
else if(s == "critical")
|
||||
{
|
||||
} else if(s == "critical") {
|
||||
return sinsp_logger::SEV_CRITICAL;
|
||||
}
|
||||
else if(s == "fatal")
|
||||
{
|
||||
} else if(s == "fatal") {
|
||||
return sinsp_logger::SEV_FATAL;
|
||||
}
|
||||
throw falco_exception("Unknown sinsp log severity " + s);
|
||||
}
|
||||
|
||||
void falco_logger::set_time_format_iso_8601(bool val)
|
||||
{
|
||||
void falco_logger::set_time_format_iso_8601(bool val) {
|
||||
falco_logger::time_format_iso_8601 = val;
|
||||
}
|
||||
|
||||
void falco_logger::set_level(const std::string &level)
|
||||
{
|
||||
if(level == "emergency")
|
||||
{
|
||||
void falco_logger::set_level(const std::string& level) {
|
||||
if(level == "emergency") {
|
||||
falco_logger::current_level = falco_logger::level::EMERG;
|
||||
}
|
||||
else if(level == "alert")
|
||||
{
|
||||
} else if(level == "alert") {
|
||||
falco_logger::current_level = falco_logger::level::ALERT;
|
||||
}
|
||||
else if(level == "critical")
|
||||
{
|
||||
} else if(level == "critical") {
|
||||
falco_logger::current_level = falco_logger::level::CRIT;
|
||||
}
|
||||
else if(level == "error")
|
||||
{
|
||||
} else if(level == "error") {
|
||||
falco_logger::current_level = falco_logger::level::ERR;
|
||||
}
|
||||
else if(level == "warning")
|
||||
{
|
||||
} else if(level == "warning") {
|
||||
falco_logger::current_level = falco_logger::level::WARNING;
|
||||
}
|
||||
else if(level == "notice")
|
||||
{
|
||||
} else if(level == "notice") {
|
||||
falco_logger::current_level = falco_logger::level::NOTICE;
|
||||
}
|
||||
else if(level == "info")
|
||||
{
|
||||
} else if(level == "info") {
|
||||
falco_logger::current_level = falco_logger::level::INFO;
|
||||
}
|
||||
else if(level == "debug")
|
||||
{
|
||||
} else if(level == "debug") {
|
||||
falco_logger::current_level = falco_logger::level::DEBUG;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
throw falco_exception("Unknown log level " + level);
|
||||
}
|
||||
}
|
||||
|
||||
static std::string s_sinsp_logger_prefix = "";
|
||||
|
||||
void falco_logger::set_sinsp_logging(bool enable, const std::string& severity, const std::string& prefix)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
void falco_logger::set_sinsp_logging(bool enable,
|
||||
const std::string& severity,
|
||||
const std::string& prefix) {
|
||||
if(enable) {
|
||||
s_sinsp_logger_prefix = prefix;
|
||||
libsinsp_logger()->set_severity(decode_sinsp_severity(severity));
|
||||
libsinsp_logger()->disable_timestamps();
|
||||
libsinsp_logger()->add_callback_log(
|
||||
[](std::string&& str, const sinsp_logger::severity sev)
|
||||
{
|
||||
// note: using falco_logger::level ensures that the sinsp
|
||||
// logs are always printed by the Falco logger. These
|
||||
// logs are pre-filtered at the sinsp level depending
|
||||
// on the configured severity
|
||||
falco_logger::log(falco_logger::current_level, s_sinsp_logger_prefix + str);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
[](std::string&& str, const sinsp_logger::severity sev) {
|
||||
// note: using falco_logger::level ensures that the sinsp
|
||||
// logs are always printed by the Falco logger. These
|
||||
// logs are pre-filtered at the sinsp level depending
|
||||
// on the configured severity
|
||||
falco_logger::log(falco_logger::current_level, s_sinsp_logger_prefix + str);
|
||||
});
|
||||
} else {
|
||||
libsinsp_logger()->remove_callback_log();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool falco_logger::log_stderr = true;
|
||||
bool falco_logger::log_syslog = true;
|
||||
|
||||
void falco_logger::log(falco_logger::level priority, const std::string&& msg)
|
||||
{
|
||||
|
||||
if(priority > falco_logger::current_level)
|
||||
{
|
||||
void falco_logger::log(falco_logger::level priority, const std::string&& msg) {
|
||||
if(priority > falco_logger::current_level) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string copy = msg;
|
||||
|
||||
#ifndef _WIN32
|
||||
if (falco_logger::log_syslog)
|
||||
{
|
||||
if(falco_logger::log_syslog) {
|
||||
// Syslog output should not have any trailing newline
|
||||
if(copy.back() == '\n')
|
||||
{
|
||||
if(copy.back() == '\n') {
|
||||
copy.pop_back();
|
||||
}
|
||||
|
||||
@@ -157,37 +113,27 @@ void falco_logger::log(falco_logger::level priority, const std::string&& msg)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (falco_logger::log_stderr)
|
||||
{
|
||||
if(falco_logger::log_stderr) {
|
||||
// log output should always have a trailing newline
|
||||
if(copy.back() != '\n')
|
||||
{
|
||||
if(copy.back() != '\n') {
|
||||
copy.push_back('\n');
|
||||
}
|
||||
|
||||
std::time_t result = std::time(nullptr);
|
||||
if(falco_logger::time_format_iso_8601)
|
||||
{
|
||||
if(falco_logger::time_format_iso_8601) {
|
||||
char buf[sizeof "YYYY-MM-DDTHH:MM:SS-0000"];
|
||||
const struct tm *gtm = std::gmtime(&result);
|
||||
if(gtm != NULL &&
|
||||
(strftime(buf, sizeof(buf), "%FT%T%z", gtm) != 0))
|
||||
{
|
||||
const struct tm* gtm = std::gmtime(&result);
|
||||
if(gtm != NULL && (strftime(buf, sizeof(buf), "%FT%T%z", gtm) != 0)) {
|
||||
fprintf(stderr, "%s: %s", buf, copy.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const struct tm *ltm = std::localtime(&result);
|
||||
char *atime = (ltm ? std::asctime(ltm) : NULL);
|
||||
} else {
|
||||
const struct tm* ltm = std::localtime(&result);
|
||||
char* atime = (ltm ? std::asctime(ltm) : NULL);
|
||||
std::string tstr;
|
||||
if(atime)
|
||||
{
|
||||
if(atime) {
|
||||
tstr = atime;
|
||||
tstr = tstr.substr(0, 24);// remove trailing newline
|
||||
}
|
||||
else
|
||||
{
|
||||
tstr = tstr.substr(0, 24); // remove trailing newline
|
||||
} else {
|
||||
tstr = "N/A";
|
||||
}
|
||||
fprintf(stderr, "%s: %s", tstr.c_str(), copy.c_str());
|
||||
|
||||
@@ -22,28 +22,18 @@ limitations under the License.
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
|
||||
class falco_logger
|
||||
{
|
||||
public:
|
||||
|
||||
enum class level : int
|
||||
{
|
||||
EMERG = 0,
|
||||
ALERT,
|
||||
CRIT,
|
||||
ERR,
|
||||
WARNING,
|
||||
NOTICE,
|
||||
INFO,
|
||||
DEBUG
|
||||
};
|
||||
class falco_logger {
|
||||
public:
|
||||
enum class level : int { EMERG = 0, ALERT, CRIT, ERR, WARNING, NOTICE, INFO, DEBUG };
|
||||
|
||||
static void set_time_format_iso_8601(bool val);
|
||||
|
||||
// Will throw exception if level is unknown.
|
||||
static void set_level(const std::string &level);
|
||||
static void set_level(const std::string& level);
|
||||
|
||||
static void set_sinsp_logging(bool enable, const std::string& severity, const std::string& prefix);
|
||||
static void set_sinsp_logging(bool enable,
|
||||
const std::string& severity,
|
||||
const std::string& prefix);
|
||||
|
||||
static void log(falco_logger::level priority, const std::string&& msg);
|
||||
|
||||
|
||||
@@ -35,6 +35,12 @@ const char rule_schema_string[] = LONG_STRING_CONST(
|
||||
"required_engine_version": {
|
||||
"type": "string"
|
||||
},
|
||||
"required_plugin_versions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/RequiredPluginVersion"
|
||||
}
|
||||
},
|
||||
"macro": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -68,6 +74,9 @@ const char rule_schema_string[] = LONG_STRING_CONST(
|
||||
"priority": {
|
||||
"$ref": "#/definitions/Priority"
|
||||
},
|
||||
"source": {
|
||||
"type": "string"
|
||||
},
|
||||
"exceptions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
@@ -166,6 +175,46 @@ const char rule_schema_string[] = LONG_STRING_CONST(
|
||||
},
|
||||
"minProperties": 1,
|
||||
"title": "Override"
|
||||
},
|
||||
"RequiredPluginVersion": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"alternatives": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Alternative"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"version"
|
||||
],
|
||||
"title": "RequiredPluginVersion"
|
||||
},
|
||||
"Alternative": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"version"
|
||||
],
|
||||
"title": "Alternative"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,72 +20,62 @@ limitations under the License.
|
||||
#include "rule_loader.h"
|
||||
#include "yaml_helper.h"
|
||||
|
||||
static const std::string item_type_strings[] = {"value for",
|
||||
"exceptions",
|
||||
"exception",
|
||||
"exception values",
|
||||
"exception value",
|
||||
"rules content",
|
||||
"rules content item",
|
||||
"required_engine_version",
|
||||
"required plugin versions",
|
||||
"required plugin versions entry",
|
||||
"required plugin versions alternative",
|
||||
"list",
|
||||
"list item",
|
||||
"macro",
|
||||
"macro condition",
|
||||
"rule",
|
||||
"rule condition",
|
||||
"condition expression",
|
||||
"rule output",
|
||||
"rule output expression",
|
||||
"rule priority",
|
||||
"overrides",
|
||||
"extension item"};
|
||||
|
||||
static const std::string item_type_strings[] = {
|
||||
"value for",
|
||||
"exceptions",
|
||||
"exception",
|
||||
"exception values",
|
||||
"exception value",
|
||||
"rules content",
|
||||
"rules content item",
|
||||
"required_engine_version",
|
||||
"required plugin versions",
|
||||
"required plugin versions entry",
|
||||
"required plugin versions alternative",
|
||||
"list",
|
||||
"list item",
|
||||
"macro",
|
||||
"macro condition",
|
||||
"rule",
|
||||
"rule condition",
|
||||
"condition expression",
|
||||
"rule output",
|
||||
"rule output expression",
|
||||
"rule priority",
|
||||
"overrides",
|
||||
"extension item"
|
||||
};
|
||||
|
||||
const std::string& rule_loader::context::item_type_as_string(enum item_type it)
|
||||
{
|
||||
const std::string& rule_loader::context::item_type_as_string(enum item_type it) {
|
||||
return item_type_strings[it];
|
||||
}
|
||||
|
||||
rule_loader::context::context(const std::string& name)
|
||||
{
|
||||
rule_loader::context::context(const std::string& name) {
|
||||
// This ensures that every context has one location, even if
|
||||
// that location is effectively the whole document.
|
||||
location loc = {name, position(), rule_loader::context::RULES_CONTENT, ""};
|
||||
m_locs.push_back(loc);
|
||||
}
|
||||
|
||||
rule_loader::context::context(const YAML::Node &item,
|
||||
const item_type item_type,
|
||||
const std::string& item_name,
|
||||
const context& parent)
|
||||
{
|
||||
rule_loader::context::context(const YAML::Node& item,
|
||||
const item_type item_type,
|
||||
const std::string& item_name,
|
||||
const context& parent) {
|
||||
init(parent.name(), position(item.Mark()), item_type, item_name, parent);
|
||||
}
|
||||
|
||||
rule_loader::context::context(const YAML::Mark &mark, const context& parent)
|
||||
{
|
||||
rule_loader::context::context(const YAML::Mark& mark, const context& parent) {
|
||||
init(parent.name(), position(mark), item_type::VALUE_FOR, "", parent);
|
||||
}
|
||||
|
||||
rule_loader::context::context(const libsinsp::filter::ast::pos_info& pos,
|
||||
const std::string& condition,
|
||||
const context& parent)
|
||||
: alt_content(condition)
|
||||
{
|
||||
|
||||
const std::string& condition,
|
||||
const context& parent):
|
||||
alt_content(condition) {
|
||||
// Contexts based on conditions don't use the
|
||||
// filename. Instead the "name" is just the condition, and
|
||||
// uses a short prefix of the condition.
|
||||
std::string condition_name = "\"" + (
|
||||
condition.length() > 20
|
||||
? condition.substr(0, 20 - 3) + "...\""
|
||||
: condition + "\"");
|
||||
std::string condition_name =
|
||||
"\"" +
|
||||
(condition.length() > 20 ? condition.substr(0, 20 - 3) + "...\"" : condition + "\"");
|
||||
std::replace(condition_name.begin(), condition_name.end(), '\n', ' ');
|
||||
std::replace(condition_name.begin(), condition_name.end(), '\r', ' ');
|
||||
|
||||
@@ -104,11 +94,9 @@ rule_loader::context::context(const libsinsp::filter::ast::pos_info& pos,
|
||||
init(condition_name, condpos, rule_loader::context::CONDITION_EXPRESSION, item_name, parent);
|
||||
}
|
||||
|
||||
const std::string& rule_loader::context::name() const
|
||||
{
|
||||
const std::string& rule_loader::context::name() const {
|
||||
// All valid contexts should have at least one location.
|
||||
if(m_locs.empty())
|
||||
{
|
||||
if(m_locs.empty()) {
|
||||
throw falco_exception("rule_loader::context without location?");
|
||||
}
|
||||
|
||||
@@ -116,11 +104,10 @@ const std::string& rule_loader::context::name() const
|
||||
}
|
||||
|
||||
void rule_loader::context::init(const std::string& name,
|
||||
const position& pos,
|
||||
const item_type item_type,
|
||||
const std::string& item_name,
|
||||
const context& parent)
|
||||
{
|
||||
const position& pos,
|
||||
const item_type item_type,
|
||||
const std::string& item_name,
|
||||
const context& parent) {
|
||||
// Copy parent locations
|
||||
m_locs = parent.m_locs;
|
||||
|
||||
@@ -129,54 +116,43 @@ void rule_loader::context::init(const std::string& name,
|
||||
m_locs.push_back(loc);
|
||||
}
|
||||
|
||||
std::string rule_loader::context::as_string()
|
||||
{
|
||||
std::string rule_loader::context::as_string() {
|
||||
std::ostringstream os;
|
||||
|
||||
// All valid contexts should have at least one location.
|
||||
if(m_locs.empty())
|
||||
{
|
||||
if(m_locs.empty()) {
|
||||
throw falco_exception("rule_loader::context without location?");
|
||||
}
|
||||
|
||||
bool first = true;
|
||||
|
||||
for(const auto& loc : m_locs)
|
||||
{
|
||||
for(const auto& loc : m_locs) {
|
||||
os << (first ? "In " : " ");
|
||||
first = false;
|
||||
|
||||
os << item_type_as_string(loc.item_type);
|
||||
if(!loc.item_name.empty())
|
||||
{
|
||||
if(!loc.item_name.empty()) {
|
||||
os << " '" << loc.item_name << "'";
|
||||
}
|
||||
os << ": ";
|
||||
|
||||
os << "("
|
||||
<< loc.name << ":"
|
||||
<< loc.pos.line << ":"
|
||||
<< loc.pos.column
|
||||
<< ")" << std::endl;
|
||||
os << "(" << loc.name << ":" << loc.pos.line << ":" << loc.pos.column << ")" << std::endl;
|
||||
}
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
nlohmann::json rule_loader::context::as_json()
|
||||
{
|
||||
nlohmann::json rule_loader::context::as_json() {
|
||||
nlohmann::json ret;
|
||||
|
||||
ret["locations"] = nlohmann::json::array();
|
||||
|
||||
// All valid contexts should have at least one location.
|
||||
if(m_locs.empty())
|
||||
{
|
||||
if(m_locs.empty()) {
|
||||
throw falco_exception("rule_loader::context without location?");
|
||||
}
|
||||
|
||||
for(const auto& loc : m_locs)
|
||||
{
|
||||
for(const auto& loc : m_locs) {
|
||||
nlohmann::json jloc, jpos;
|
||||
|
||||
jloc["item_type"] = item_type_as_string(loc.item_type);
|
||||
@@ -195,28 +171,25 @@ nlohmann::json rule_loader::context::as_json()
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string rule_loader::context::snippet(const falco::load_result::rules_contents_t& rules_contents,
|
||||
size_t snippet_width) const
|
||||
{
|
||||
std::string rule_loader::context::snippet(
|
||||
const falco::load_result::rules_contents_t& rules_contents,
|
||||
size_t snippet_width) const {
|
||||
// All valid contexts should have at least one location.
|
||||
if(m_locs.empty())
|
||||
{
|
||||
if(m_locs.empty()) {
|
||||
throw falco_exception("rule_loader::context without location?");
|
||||
}
|
||||
|
||||
rule_loader::context::location loc = m_locs.back();
|
||||
auto it = rules_contents.find(loc.name);
|
||||
|
||||
if(alt_content.empty() && it == rules_contents.end())
|
||||
{
|
||||
if(alt_content.empty() && it == rules_contents.end()) {
|
||||
return "<No context for file + " + loc.name + ">\n";
|
||||
}
|
||||
|
||||
// If not using alt content, the last location's name must be found in rules_contents
|
||||
const std::string& snip_content = (!alt_content.empty() ? alt_content : it->second.get());
|
||||
|
||||
if(snip_content.empty())
|
||||
{
|
||||
if(snip_content.empty()) {
|
||||
return "<No context available>\n";
|
||||
}
|
||||
|
||||
@@ -225,7 +198,8 @@ std::string rule_loader::context::snippet(const falco::load_result::rules_conten
|
||||
// tags:
|
||||
// The YAML::Mark position can be past the end of the file.
|
||||
size_t pos = loc.pos.pos;
|
||||
for(; pos > 0 && (pos >= snip_content.size() || snip_content.at(pos) == '\n'); pos--);
|
||||
for(; pos > 0 && (pos >= snip_content.size() || snip_content.at(pos) == '\n'); pos--)
|
||||
;
|
||||
|
||||
// The snippet is generally the line that contains the
|
||||
// position. So walk backwards from pos to the preceding
|
||||
@@ -236,151 +210,127 @@ std::string rule_loader::context::snippet(const falco::load_result::rules_conten
|
||||
// forwards/walk backwards is capped at a maximum of
|
||||
// snippet_width/2 characters in either direction.
|
||||
size_t from = pos;
|
||||
for(; from > 0 && snip_content.at(from) != '\n' && (pos - from) < (snippet_width/2); from--);
|
||||
for(; from > 0 && snip_content.at(from) != '\n' && (pos - from) < (snippet_width / 2); from--)
|
||||
;
|
||||
|
||||
size_t to = pos;
|
||||
for(; to < snip_content.size()-1 && snip_content.at(to) != '\n' && (to - pos) < (snippet_width/2); to++);
|
||||
for(; to < snip_content.size() - 1 && snip_content.at(to) != '\n' &&
|
||||
(to - pos) < (snippet_width / 2);
|
||||
to++)
|
||||
;
|
||||
|
||||
// Don't include the newlines
|
||||
if(from < snip_content.size() && snip_content.at(from) == '\n')
|
||||
{
|
||||
if(from < snip_content.size() && snip_content.at(from) == '\n') {
|
||||
from++;
|
||||
}
|
||||
if(to < snip_content.size() && snip_content.at(to) == '\n')
|
||||
{
|
||||
if(to < snip_content.size() && snip_content.at(to) == '\n') {
|
||||
to--;
|
||||
}
|
||||
|
||||
std::string ret = snip_content.substr(from, to-from+1);
|
||||
std::string ret = snip_content.substr(from, to - from + 1);
|
||||
|
||||
if(ret.empty())
|
||||
{
|
||||
if(ret.empty()) {
|
||||
return "<No context available>\n";
|
||||
}
|
||||
|
||||
// Replace the initial/end characters with '...' if the walk
|
||||
// forwards/backwards was incomplete
|
||||
if(pos - from >= (snippet_width/2))
|
||||
{
|
||||
if(pos - from >= (snippet_width / 2)) {
|
||||
ret.replace(0, 3, "...");
|
||||
}
|
||||
|
||||
if(to - pos >= (snippet_width/2))
|
||||
{
|
||||
ret.replace(ret.size()-3, 3, "...");
|
||||
if(to - pos >= (snippet_width / 2)) {
|
||||
ret.replace(ret.size() - 3, 3, "...");
|
||||
}
|
||||
|
||||
ret += "\n";
|
||||
|
||||
// Add a blank line with a marker at the position within the snippet
|
||||
if(pos-from <= ret.size() - 1)
|
||||
{
|
||||
ret += std::string(pos-from, ' ') + '^' + "\n";
|
||||
if(pos - from <= ret.size() - 1) {
|
||||
ret += std::string(pos - from, ' ') + '^' + "\n";
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
rule_loader::result::result(const std::string &name)
|
||||
: name(name),
|
||||
success(true)
|
||||
{
|
||||
}
|
||||
rule_loader::result::result(const std::string& name): name(name), success(true) {}
|
||||
|
||||
bool rule_loader::result::successful()
|
||||
{
|
||||
bool rule_loader::result::successful() {
|
||||
return success;
|
||||
}
|
||||
|
||||
bool rule_loader::result::has_warnings()
|
||||
{
|
||||
bool rule_loader::result::has_warnings() {
|
||||
return (warnings.size() > 0);
|
||||
}
|
||||
|
||||
std::string rule_loader::result::schema_validation()
|
||||
{
|
||||
if (schema_validation_status.empty())
|
||||
{
|
||||
std::string rule_loader::result::schema_validation() {
|
||||
if(schema_validation_status.empty()) {
|
||||
return yaml_helper::validation_none;
|
||||
}
|
||||
return schema_validation_status[0];
|
||||
}
|
||||
|
||||
void rule_loader::result::add_error(load_result::error_code ec, const std::string& msg, const context& ctx)
|
||||
{
|
||||
void rule_loader::result::add_error(load_result::error_code ec,
|
||||
const std::string& msg,
|
||||
const context& ctx) {
|
||||
error err = {ec, msg, ctx};
|
||||
success = false;
|
||||
|
||||
errors.push_back(err);
|
||||
}
|
||||
|
||||
void rule_loader::result::add_warning(load_result::warning_code wc, const std::string& msg, const context& ctx)
|
||||
{
|
||||
void rule_loader::result::add_warning(load_result::warning_code wc,
|
||||
const std::string& msg,
|
||||
const context& ctx) {
|
||||
warning warn = {wc, msg, ctx};
|
||||
|
||||
warnings.push_back(warn);
|
||||
}
|
||||
|
||||
void rule_loader::result::set_schema_validation_status(const std::vector<std::string>& status)
|
||||
{
|
||||
void rule_loader::result::set_schema_validation_status(const std::vector<std::string>& status) {
|
||||
schema_validation_status = status;
|
||||
}
|
||||
|
||||
const std::string& rule_loader::result::as_string(bool verbose, const rules_contents_t& contents)
|
||||
{
|
||||
if(verbose)
|
||||
{
|
||||
const std::string& rule_loader::result::as_string(bool verbose, const rules_contents_t& contents) {
|
||||
if(verbose) {
|
||||
return as_verbose_string(contents);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return as_summary_string();
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& rule_loader::result::as_summary_string()
|
||||
{
|
||||
const std::string& rule_loader::result::as_summary_string() {
|
||||
std::ostringstream os;
|
||||
|
||||
if(!res_summary_string.empty())
|
||||
{
|
||||
if(!res_summary_string.empty()) {
|
||||
return res_summary_string;
|
||||
}
|
||||
|
||||
if(!name.empty())
|
||||
{
|
||||
if(!name.empty()) {
|
||||
os << name << ": ";
|
||||
}
|
||||
|
||||
if(success)
|
||||
{
|
||||
if(success) {
|
||||
os << "Ok";
|
||||
|
||||
if (!warnings.empty())
|
||||
{
|
||||
if(!warnings.empty()) {
|
||||
os << ", with warnings";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
os << "Invalid";
|
||||
}
|
||||
|
||||
// Only print schema validation info if any validation was requested
|
||||
if (!schema_validation_status.empty())
|
||||
{
|
||||
if(!schema_validation_status.empty()) {
|
||||
bool schema_valid = schema_validation() == yaml_helper::validation_ok;
|
||||
// Only print info when there are validation warnings
|
||||
if (!schema_valid)
|
||||
{
|
||||
if(!schema_valid) {
|
||||
os << std::endl;
|
||||
|
||||
os << " " << schema_validation_status.size() << " schema warnings: [";
|
||||
bool first = true;
|
||||
for(auto& status : schema_validation_status)
|
||||
{
|
||||
if(!first)
|
||||
{
|
||||
for(auto& status : schema_validation_status) {
|
||||
if(!first) {
|
||||
os << " ";
|
||||
}
|
||||
first = false;
|
||||
@@ -391,42 +341,36 @@ const std::string& rule_loader::result::as_summary_string()
|
||||
}
|
||||
}
|
||||
|
||||
if(!errors.empty())
|
||||
{
|
||||
if(!errors.empty()) {
|
||||
os << std::endl;
|
||||
|
||||
os << " " << errors.size() << " errors: [";
|
||||
bool first = true;
|
||||
for(auto &err : errors)
|
||||
{
|
||||
if(!first)
|
||||
{
|
||||
for(auto& err : errors) {
|
||||
if(!first) {
|
||||
os << " ";
|
||||
}
|
||||
first = false;
|
||||
|
||||
os << load_result::error_code_str(err.ec)
|
||||
<< " (" << load_result::error_str(err.ec) << ")";
|
||||
os << load_result::error_code_str(err.ec) << " (" << load_result::error_str(err.ec)
|
||||
<< ")";
|
||||
}
|
||||
os << "]";
|
||||
}
|
||||
|
||||
if(!warnings.empty())
|
||||
{
|
||||
if(!warnings.empty()) {
|
||||
os << std::endl;
|
||||
|
||||
os << " " << warnings.size() << " warnings: [";
|
||||
bool first = true;
|
||||
for(auto &warn : warnings)
|
||||
{
|
||||
if(!first)
|
||||
{
|
||||
for(auto& warn : warnings) {
|
||||
if(!first) {
|
||||
os << " ";
|
||||
}
|
||||
first = false;
|
||||
|
||||
os << load_result::warning_code_str(warn.wc)
|
||||
<< " (" << load_result::warning_str(warn.wc) << ")";
|
||||
os << load_result::warning_code_str(warn.wc) << " ("
|
||||
<< load_result::warning_str(warn.wc) << ")";
|
||||
}
|
||||
os << "]";
|
||||
}
|
||||
@@ -435,93 +379,73 @@ const std::string& rule_loader::result::as_summary_string()
|
||||
return res_summary_string;
|
||||
}
|
||||
|
||||
const std::string& rule_loader::result::as_verbose_string(const rules_contents_t& contents)
|
||||
{
|
||||
const std::string& rule_loader::result::as_verbose_string(const rules_contents_t& contents) {
|
||||
std::ostringstream os;
|
||||
|
||||
if(!res_verbose_string.empty())
|
||||
{
|
||||
if(!res_verbose_string.empty()) {
|
||||
return res_verbose_string;
|
||||
}
|
||||
|
||||
if(!name.empty())
|
||||
{
|
||||
if(!name.empty()) {
|
||||
os << name << ": ";
|
||||
}
|
||||
|
||||
if(success)
|
||||
{
|
||||
if(success) {
|
||||
os << "Ok";
|
||||
|
||||
if (!warnings.empty())
|
||||
{
|
||||
if(!warnings.empty()) {
|
||||
os << ", with warnings";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
os << "Invalid";
|
||||
}
|
||||
|
||||
// Only print schema validation info if any validation was requested
|
||||
if (!schema_validation_status.empty())
|
||||
{
|
||||
if(!schema_validation_status.empty()) {
|
||||
bool schema_valid = schema_validation() == yaml_helper::validation_ok;
|
||||
// Only print info when there are validation warnings
|
||||
if (!schema_valid)
|
||||
{
|
||||
if(!schema_valid) {
|
||||
os << std::endl;
|
||||
|
||||
os << schema_validation_status.size()
|
||||
<< " Schema warnings:" << std::endl;
|
||||
os << schema_validation_status.size() << " Schema warnings:" << std::endl;
|
||||
|
||||
for(auto& status : schema_validation_status)
|
||||
{
|
||||
for(auto& status : schema_validation_status) {
|
||||
os << "------" << std::endl;
|
||||
os << status << std::endl;
|
||||
}
|
||||
os << "------" << std::endl;
|
||||
}
|
||||
}
|
||||
if (!errors.empty())
|
||||
{
|
||||
if(!errors.empty()) {
|
||||
os << std::endl;
|
||||
|
||||
os << errors.size()
|
||||
<< " Errors:" << std::endl;
|
||||
os << errors.size() << " Errors:" << std::endl;
|
||||
|
||||
for(auto &err : errors)
|
||||
{
|
||||
for(auto& err : errors) {
|
||||
os << err.ctx.as_string();
|
||||
|
||||
os << "------" << std::endl;
|
||||
os << err.ctx.snippet(contents);
|
||||
os << "------" << std::endl;
|
||||
|
||||
os << load_result::error_code_str(err.ec)
|
||||
<< " (" << load_result::error_str(err.ec) << "): "
|
||||
<< err.msg
|
||||
<< std::endl;
|
||||
os << load_result::error_code_str(err.ec) << " (" << load_result::error_str(err.ec)
|
||||
<< "): " << err.msg << std::endl;
|
||||
}
|
||||
}
|
||||
if (!warnings.empty())
|
||||
{
|
||||
if(!warnings.empty()) {
|
||||
os << std::endl;
|
||||
|
||||
os << warnings.size()
|
||||
<< " Warnings:" << std::endl;
|
||||
os << warnings.size() << " Warnings:" << std::endl;
|
||||
|
||||
for(auto &warn : warnings)
|
||||
{
|
||||
for(auto& warn : warnings) {
|
||||
os << warn.ctx.as_string();
|
||||
|
||||
os << "------" << std::endl;
|
||||
os << warn.ctx.snippet(contents);
|
||||
os << "------" << std::endl;
|
||||
|
||||
os << load_result::warning_code_str(warn.wc)
|
||||
<< " (" << load_result::warning_str(warn.wc) << "): "
|
||||
<< warn.msg;
|
||||
os << load_result::warning_code_str(warn.wc) << " ("
|
||||
<< load_result::warning_str(warn.wc) << "): " << warn.msg;
|
||||
os << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -530,12 +454,10 @@ const std::string& rule_loader::result::as_verbose_string(const rules_contents_t
|
||||
return res_verbose_string;
|
||||
}
|
||||
|
||||
const nlohmann::json& rule_loader::result::as_json(const rules_contents_t& contents)
|
||||
{
|
||||
const nlohmann::json& rule_loader::result::as_json(const rules_contents_t& contents) {
|
||||
nlohmann::json j;
|
||||
|
||||
if(!res_json.empty())
|
||||
{
|
||||
if(!res_json.empty()) {
|
||||
return res_json;
|
||||
}
|
||||
|
||||
@@ -543,23 +465,19 @@ const nlohmann::json& rule_loader::result::as_json(const rules_contents_t& conte
|
||||
j["successful"] = success;
|
||||
|
||||
// Only print schema validation info if any validation was requested
|
||||
if (!schema_validation_status.empty())
|
||||
{
|
||||
if(!schema_validation_status.empty()) {
|
||||
bool schema_valid = schema_validation() == yaml_helper::validation_ok;
|
||||
j["schema_valid"] = schema_valid;
|
||||
j["schema_warnings"] = nlohmann::json::array();
|
||||
if (!schema_valid)
|
||||
{
|
||||
for (const auto &schema_warning : schema_validation_status)
|
||||
{
|
||||
if(!schema_valid) {
|
||||
for(const auto& schema_warning : schema_validation_status) {
|
||||
j["schema_warnings"].push_back(schema_warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
j["errors"] = nlohmann::json::array();
|
||||
for(auto &err : errors)
|
||||
{
|
||||
for(auto& err : errors) {
|
||||
nlohmann::json jerr;
|
||||
|
||||
jerr["context"] = err.ctx.as_json();
|
||||
@@ -573,8 +491,7 @@ const nlohmann::json& rule_loader::result::as_json(const rules_contents_t& conte
|
||||
}
|
||||
|
||||
j["warnings"] = nlohmann::json::array();
|
||||
for(auto &warn : warnings)
|
||||
{
|
||||
for(auto& warn : warnings) {
|
||||
nlohmann::json jwarn;
|
||||
|
||||
jwarn["context"] = warn.ctx.as_json();
|
||||
@@ -591,59 +508,46 @@ const nlohmann::json& rule_loader::result::as_json(const rules_contents_t& conte
|
||||
return res_json;
|
||||
}
|
||||
|
||||
rule_loader::engine_version_info::engine_version_info(context &ctx)
|
||||
: ctx(ctx)
|
||||
{
|
||||
}
|
||||
rule_loader::engine_version_info::engine_version_info(context& ctx): ctx(ctx) {}
|
||||
|
||||
rule_loader::plugin_version_info::plugin_version_info()
|
||||
: ctx("no-filename-given")
|
||||
{
|
||||
}
|
||||
rule_loader::plugin_version_info::plugin_version_info(): ctx("no-filename-given") {}
|
||||
|
||||
rule_loader::plugin_version_info::plugin_version_info(context &ctx)
|
||||
: ctx(ctx)
|
||||
{
|
||||
}
|
||||
rule_loader::plugin_version_info::plugin_version_info(context& ctx): ctx(ctx) {}
|
||||
|
||||
rule_loader::list_info::list_info(context &ctx)
|
||||
: ctx(ctx), index(0), visibility(0)
|
||||
{
|
||||
}
|
||||
rule_loader::list_info::list_info(context& ctx): ctx(ctx), index(0), visibility(0) {}
|
||||
|
||||
rule_loader::macro_info::macro_info(context &ctx)
|
||||
: ctx(ctx), cond_ctx(ctx), index(0), visibility(0)
|
||||
{
|
||||
}
|
||||
rule_loader::macro_info::macro_info(context& ctx):
|
||||
ctx(ctx),
|
||||
cond_ctx(ctx),
|
||||
index(0),
|
||||
visibility(0) {}
|
||||
|
||||
rule_loader::rule_exception_info::rule_exception_info(context &ctx)
|
||||
: ctx(ctx)
|
||||
{
|
||||
}
|
||||
rule_loader::rule_exception_info::rule_exception_info(context& ctx): ctx(ctx) {}
|
||||
|
||||
rule_loader::rule_info::rule_info(context &ctx)
|
||||
: ctx(ctx), cond_ctx(ctx), output_ctx(ctx), index(0), visibility(0),
|
||||
unknown_source(false), priority(falco_common::PRIORITY_DEBUG),
|
||||
enabled(true), warn_evttypes(true), skip_if_unknown_filter(false)
|
||||
{
|
||||
}
|
||||
rule_loader::rule_info::rule_info(context& ctx):
|
||||
ctx(ctx),
|
||||
cond_ctx(ctx),
|
||||
output_ctx(ctx),
|
||||
index(0),
|
||||
visibility(0),
|
||||
unknown_source(false),
|
||||
priority(falco_common::PRIORITY_DEBUG),
|
||||
enabled(true),
|
||||
warn_evttypes(true),
|
||||
skip_if_unknown_filter(false) {}
|
||||
|
||||
rule_loader::rule_update_info::rule_update_info(context &ctx)
|
||||
: ctx(ctx), cond_ctx(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)
|
||||
{
|
||||
}
|
||||
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) {}
|
||||
|
||||
rule_loader::rule_load_exception::~rule_load_exception()
|
||||
{
|
||||
}
|
||||
rule_loader::rule_load_exception::~rule_load_exception() {}
|
||||
|
||||
const char* rule_loader::rule_load_exception::what() const noexcept
|
||||
{
|
||||
const char* rule_loader::rule_load_exception::what() const noexcept {
|
||||
// const + noexcept: can't use functions that change the object or throw
|
||||
return msg.c_str();
|
||||
}
|
||||
|
||||
@@ -28,487 +28,473 @@ limitations under the License.
|
||||
#include "indexed_vector.h"
|
||||
#include <libsinsp/version.h>
|
||||
|
||||
namespace rule_loader
|
||||
{
|
||||
class context
|
||||
{
|
||||
public:
|
||||
// The kinds of items that can be in rules
|
||||
// content. These generally map to yaml items but a
|
||||
// few are more specific (e.g. "within condition
|
||||
// expression", "value for yaml node", etc.)
|
||||
enum item_type {
|
||||
VALUE_FOR = 0,
|
||||
EXCEPTIONS,
|
||||
EXCEPTION,
|
||||
EXCEPTION_VALUES,
|
||||
EXCEPTION_VALUE,
|
||||
RULES_CONTENT,
|
||||
RULES_CONTENT_ITEM,
|
||||
REQUIRED_ENGINE_VERSION,
|
||||
REQUIRED_PLUGIN_VERSIONS,
|
||||
REQUIRED_PLUGIN_VERSIONS_ENTRY,
|
||||
REQUIRED_PLUGIN_VERSIONS_ALTERNATIVE,
|
||||
LIST,
|
||||
LIST_ITEM,
|
||||
MACRO,
|
||||
MACRO_CONDITION,
|
||||
RULE,
|
||||
RULE_CONDITION,
|
||||
CONDITION_EXPRESSION,
|
||||
RULE_OUTPUT,
|
||||
RULE_OUTPUT_EXPRESSION,
|
||||
RULE_PRIORITY,
|
||||
OVERRIDE,
|
||||
EXTENSION_ITEM
|
||||
};
|
||||
|
||||
static const std::string& item_type_as_string(enum item_type it);
|
||||
|
||||
static const size_t default_snippet_width = 160;
|
||||
|
||||
struct position
|
||||
{
|
||||
position() : pos(0), line(0), column(0) {};
|
||||
explicit position(const YAML::Mark& mark) : pos(mark.pos), line(mark.line), column(mark.column) {};
|
||||
~position() = default;
|
||||
position(position&&) = default;
|
||||
position& operator = (position&&) = default;
|
||||
position(const position&) = default;
|
||||
position& operator = (const position&) = default;
|
||||
|
||||
int pos;
|
||||
int line;
|
||||
int column;
|
||||
};
|
||||
|
||||
struct location
|
||||
{
|
||||
location(): item_type(context::item_type::VALUE_FOR) {}
|
||||
location(
|
||||
const std::string& n,
|
||||
const position& p,
|
||||
context::item_type i,
|
||||
const std::string& in):
|
||||
name(n), pos(p), item_type(i), item_name(in) {}
|
||||
location(location&&) = default;
|
||||
location& operator = (location&&) = default;
|
||||
location(const location&) = default;
|
||||
location& operator = (const location&) = default;
|
||||
|
||||
// A name for the content this location refers
|
||||
// to. Will generally be a filename, can also
|
||||
// refer to a rule/macro condition when the
|
||||
// location points into a condition string.
|
||||
std::string name;
|
||||
|
||||
// The original location in the document
|
||||
position pos;
|
||||
|
||||
// The kind of item at this location
|
||||
// (e.g. "list", "macro", "rule", "exception", etc)
|
||||
context::item_type item_type;
|
||||
|
||||
// The name of this item (e.g. "Write Below Etc",
|
||||
// etc).
|
||||
std::string item_name;
|
||||
};
|
||||
|
||||
explicit context(const std::string& name);
|
||||
context(const YAML::Node& item,
|
||||
item_type item_type,
|
||||
const std::string& item_name,
|
||||
const context& parent);
|
||||
context(
|
||||
const YAML::Mark &mark,
|
||||
const context& parent);
|
||||
|
||||
// Build a context from a condition expression +
|
||||
// parser position. This does not use the original
|
||||
// yaml content because:
|
||||
// - YAML block indicators will remove whitespace/newlines/wrapping
|
||||
// from the YAML node containing the condition expression.
|
||||
// - When compiling, the condition expression has expanded
|
||||
// macro and list references with their values.
|
||||
context(const libsinsp::filter::ast::pos_info& pos,
|
||||
const std::string& condition,
|
||||
const context& parent);
|
||||
|
||||
virtual ~context() = default;
|
||||
|
||||
context(context&&) = default;
|
||||
context& operator = (context&&) = default;
|
||||
context(const context&) = default;
|
||||
context& operator = (const context&) = default;
|
||||
|
||||
// Return the content name (generally filename) for
|
||||
// this context
|
||||
const std::string& name() const;
|
||||
|
||||
// Return a snippet of the provided rules content
|
||||
// corresponding to this context.
|
||||
// Uses the provided rules_contents to look up the original
|
||||
// rules content for a given location name.
|
||||
// (If this context has a non-empty alt_content, it
|
||||
// will be used to create the snippet, ignoring the
|
||||
// provided rules_contents).
|
||||
std::string snippet(const falco::load_result::rules_contents_t& rules_contents, size_t snippet_width = default_snippet_width) const;
|
||||
|
||||
std::string as_string();
|
||||
nlohmann::json as_json();
|
||||
|
||||
private:
|
||||
void init(const std::string& name,
|
||||
const position& pos,
|
||||
const item_type item_type,
|
||||
const std::string& item_name,
|
||||
const context& parent);
|
||||
|
||||
// A chain of locations from the current item, its
|
||||
// parent, possibly older ancestors.
|
||||
std::vector<location> m_locs;
|
||||
|
||||
// If non-empty, this content will be used when
|
||||
// creating snippets. Used for contexts involving
|
||||
// condition expressions.
|
||||
std::string alt_content;
|
||||
namespace rule_loader {
|
||||
class context {
|
||||
public:
|
||||
// The kinds of items that can be in rules
|
||||
// content. These generally map to yaml items but a
|
||||
// few are more specific (e.g. "within condition
|
||||
// expression", "value for yaml node", etc.)
|
||||
enum item_type {
|
||||
VALUE_FOR = 0,
|
||||
EXCEPTIONS,
|
||||
EXCEPTION,
|
||||
EXCEPTION_VALUES,
|
||||
EXCEPTION_VALUE,
|
||||
RULES_CONTENT,
|
||||
RULES_CONTENT_ITEM,
|
||||
REQUIRED_ENGINE_VERSION,
|
||||
REQUIRED_PLUGIN_VERSIONS,
|
||||
REQUIRED_PLUGIN_VERSIONS_ENTRY,
|
||||
REQUIRED_PLUGIN_VERSIONS_ALTERNATIVE,
|
||||
LIST,
|
||||
LIST_ITEM,
|
||||
MACRO,
|
||||
MACRO_CONDITION,
|
||||
RULE,
|
||||
RULE_CONDITION,
|
||||
CONDITION_EXPRESSION,
|
||||
RULE_OUTPUT,
|
||||
RULE_OUTPUT_EXPRESSION,
|
||||
RULE_PRIORITY,
|
||||
OVERRIDE,
|
||||
EXTENSION_ITEM
|
||||
};
|
||||
|
||||
struct warning
|
||||
{
|
||||
warning(): wc(falco::load_result::warning_code::LOAD_UNKNOWN_SOURCE), ctx("no-filename-given") {}
|
||||
warning(
|
||||
falco::load_result::warning_code w,
|
||||
const std::string& m,
|
||||
const context& c): wc(w), msg(m), ctx(c) {}
|
||||
warning(warning&&) = default;
|
||||
warning& operator = (warning&&) = default;
|
||||
warning(const warning&) = default;
|
||||
warning& operator = (const warning&) = default;
|
||||
static const std::string& item_type_as_string(enum item_type it);
|
||||
|
||||
falco::load_result::warning_code wc;
|
||||
std::string msg;
|
||||
context ctx;
|
||||
static const size_t default_snippet_width = 160;
|
||||
|
||||
struct position {
|
||||
position(): pos(0), line(0), column(0) {};
|
||||
explicit position(const YAML::Mark& mark):
|
||||
pos(mark.pos),
|
||||
line(mark.line),
|
||||
column(mark.column) {};
|
||||
~position() = default;
|
||||
position(position&&) = default;
|
||||
position& operator=(position&&) = default;
|
||||
position(const position&) = default;
|
||||
position& operator=(const position&) = default;
|
||||
|
||||
int pos;
|
||||
int line;
|
||||
int column;
|
||||
};
|
||||
|
||||
struct error
|
||||
{
|
||||
error(): ec(falco::load_result::error_code::LOAD_ERR_FILE_READ), ctx("no-filename-given") {}
|
||||
error(
|
||||
falco::load_result::error_code e,
|
||||
const std::string& m,
|
||||
const context& c): ec(e), msg(m), ctx(c) {}
|
||||
error(error&&) = default;
|
||||
error& operator = (error&&) = default;
|
||||
error(const error&) = default;
|
||||
error& operator = (const error&) = default;
|
||||
struct location {
|
||||
location(): item_type(context::item_type::VALUE_FOR) {}
|
||||
location(const std::string& n,
|
||||
const position& p,
|
||||
context::item_type i,
|
||||
const std::string& in):
|
||||
name(n),
|
||||
pos(p),
|
||||
item_type(i),
|
||||
item_name(in) {}
|
||||
location(location&&) = default;
|
||||
location& operator=(location&&) = default;
|
||||
location(const location&) = default;
|
||||
location& operator=(const location&) = default;
|
||||
|
||||
falco::load_result::error_code ec;
|
||||
std::string msg;
|
||||
context ctx;
|
||||
};
|
||||
|
||||
class rule_load_exception : public std::exception
|
||||
{
|
||||
public:
|
||||
rule_load_exception(falco::load_result::error_code ec, const std::string& msg, const context& ctx);
|
||||
virtual ~rule_load_exception();
|
||||
|
||||
const char* what() const noexcept override;
|
||||
|
||||
falco::load_result::error_code ec;
|
||||
std::string msg;
|
||||
context ctx;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Contains the result of loading rule definitions
|
||||
*/
|
||||
class result : public falco::load_result
|
||||
{
|
||||
public:
|
||||
explicit result(const std::string &name);
|
||||
virtual ~result() = default;
|
||||
result(result&&) = default;
|
||||
result& operator = (result&&) = default;
|
||||
result(const result&) = default;
|
||||
result& operator = (const result&) = default;
|
||||
|
||||
virtual bool successful() override;
|
||||
virtual bool has_warnings() override;
|
||||
|
||||
virtual const std::string& as_string(bool verbose, const falco::load_result::rules_contents_t& contents) override;
|
||||
virtual const nlohmann::json& as_json(const falco::load_result::rules_contents_t& contents) override;
|
||||
|
||||
void add_error(falco::load_result::error_code ec,
|
||||
const std::string& msg,
|
||||
const context& ctx);
|
||||
|
||||
void add_warning(falco::load_result::warning_code ec,
|
||||
const std::string& msg,
|
||||
const context& ctx);
|
||||
|
||||
void set_schema_validation_status(const std::vector<std::string>& status);
|
||||
std::string schema_validation();
|
||||
protected:
|
||||
|
||||
const std::string& as_summary_string();
|
||||
const std::string& as_verbose_string(const falco::load_result::rules_contents_t& contents);
|
||||
std::string name;
|
||||
bool success;
|
||||
std::vector<std::string> schema_validation_status;
|
||||
|
||||
std::vector<error> errors;
|
||||
std::vector<warning> warnings;
|
||||
|
||||
std::string res_summary_string;
|
||||
std::string res_verbose_string;
|
||||
nlohmann::json res_json;
|
||||
};
|
||||
|
||||
struct extra_output_format_conf
|
||||
{
|
||||
std::string m_format;
|
||||
std::string m_source;
|
||||
std::set<std::string> m_tags;
|
||||
std::string m_rule;
|
||||
bool m_replace_container_info;
|
||||
};
|
||||
|
||||
struct extra_output_field_conf
|
||||
{
|
||||
std::string m_key;
|
||||
std::string m_format;
|
||||
std::string m_source;
|
||||
std::set<std::string> m_tags;
|
||||
std::string m_rule;
|
||||
bool m_raw;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Contains the info required to load rule definitions
|
||||
*/
|
||||
struct configuration
|
||||
{
|
||||
explicit configuration(
|
||||
const std::string& cont,
|
||||
const indexed_vector<falco_source>& srcs,
|
||||
const std::string& name)
|
||||
: content(cont), sources(srcs), name(name), res(std::make_unique<result>(name))
|
||||
{
|
||||
}
|
||||
|
||||
// inputs
|
||||
const std::string& content;
|
||||
const indexed_vector<falco_source>& sources;
|
||||
// A name for the content this location refers
|
||||
// to. Will generally be a filename, can also
|
||||
// refer to a rule/macro condition when the
|
||||
// location points into a condition string.
|
||||
std::string name;
|
||||
|
||||
std::vector<extra_output_format_conf> extra_output_format;
|
||||
std::vector<extra_output_field_conf> extra_output_fields;
|
||||
// The original location in the document
|
||||
position pos;
|
||||
|
||||
// outputs
|
||||
std::unique_ptr<result> res;
|
||||
// The kind of item at this location
|
||||
// (e.g. "list", "macro", "rule", "exception", etc)
|
||||
context::item_type item_type;
|
||||
|
||||
// The name of this item (e.g. "Write Below Etc",
|
||||
// etc).
|
||||
std::string item_name;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Represents infos about an engine version requirement
|
||||
*/
|
||||
struct engine_version_info
|
||||
{
|
||||
engine_version_info() : ctx("no-filename-given"), version("0.0.0") { };
|
||||
explicit engine_version_info(context &ctx);
|
||||
~engine_version_info() = default;
|
||||
engine_version_info(engine_version_info&&) = default;
|
||||
engine_version_info& operator = (engine_version_info&&) = default;
|
||||
engine_version_info(const engine_version_info&) = default;
|
||||
engine_version_info& operator = (const engine_version_info&) = default;
|
||||
explicit context(const std::string& name);
|
||||
context(const YAML::Node& item,
|
||||
item_type item_type,
|
||||
const std::string& item_name,
|
||||
const context& parent);
|
||||
context(const YAML::Mark& mark, const context& parent);
|
||||
|
||||
context ctx;
|
||||
sinsp_version version;
|
||||
};
|
||||
// Build a context from a condition expression +
|
||||
// parser position. This does not use the original
|
||||
// yaml content because:
|
||||
// - YAML block indicators will remove whitespace/newlines/wrapping
|
||||
// from the YAML node containing the condition expression.
|
||||
// - When compiling, the condition expression has expanded
|
||||
// macro and list references with their values.
|
||||
context(const libsinsp::filter::ast::pos_info& pos,
|
||||
const std::string& condition,
|
||||
const context& parent);
|
||||
|
||||
/*!
|
||||
\brief Represents infos about a plugin version requirement
|
||||
*/
|
||||
struct plugin_version_info
|
||||
{
|
||||
struct requirement
|
||||
{
|
||||
requirement() = default;
|
||||
requirement(const std::string& n, const std::string& v):
|
||||
name(n), version(v) { }
|
||||
requirement(requirement&&) = default;
|
||||
requirement& operator = (requirement&&) = default;
|
||||
requirement(const requirement&) = default;
|
||||
requirement& operator = (const requirement&) = default;
|
||||
virtual ~context() = default;
|
||||
|
||||
std::string name;
|
||||
std::string version;
|
||||
};
|
||||
context(context&&) = default;
|
||||
context& operator=(context&&) = default;
|
||||
context(const context&) = default;
|
||||
context& operator=(const context&) = default;
|
||||
|
||||
typedef std::vector<requirement> requirement_alternatives;
|
||||
// Return the content name (generally filename) for
|
||||
// this context
|
||||
const std::string& name() const;
|
||||
|
||||
// This differs from the other _info structs by having
|
||||
// a default constructor. This allows it to be used
|
||||
// by falco_engine, which aliases the type.
|
||||
plugin_version_info();
|
||||
explicit plugin_version_info(context &ctx);
|
||||
~plugin_version_info() = default;
|
||||
plugin_version_info(plugin_version_info&&) = default;
|
||||
plugin_version_info& operator = (plugin_version_info&&) = default;
|
||||
plugin_version_info(const plugin_version_info&) = default;
|
||||
plugin_version_info& operator = (const plugin_version_info&) = default;
|
||||
// Return a snippet of the provided rules content
|
||||
// corresponding to this context.
|
||||
// Uses the provided rules_contents to look up the original
|
||||
// rules content for a given location name.
|
||||
// (If this context has a non-empty alt_content, it
|
||||
// will be used to create the snippet, ignoring the
|
||||
// provided rules_contents).
|
||||
std::string snippet(const falco::load_result::rules_contents_t& rules_contents,
|
||||
size_t snippet_width = default_snippet_width) const;
|
||||
|
||||
context ctx;
|
||||
requirement_alternatives alternatives;
|
||||
};
|
||||
std::string as_string();
|
||||
nlohmann::json as_json();
|
||||
|
||||
/*!
|
||||
\brief Represents infos about a list
|
||||
*/
|
||||
struct list_info
|
||||
{
|
||||
explicit list_info(context &ctx);
|
||||
~list_info() = default;
|
||||
list_info(list_info&&) = default;
|
||||
list_info& operator = (list_info&&) = default;
|
||||
list_info(const list_info&) = default;
|
||||
list_info& operator = (const list_info&) = default;
|
||||
private:
|
||||
void init(const std::string& name,
|
||||
const position& pos,
|
||||
const item_type item_type,
|
||||
const std::string& item_name,
|
||||
const context& parent);
|
||||
|
||||
context ctx;
|
||||
size_t index;
|
||||
size_t visibility;
|
||||
std::string name;
|
||||
std::vector<std::string> items;
|
||||
};
|
||||
// A chain of locations from the current item, its
|
||||
// parent, possibly older ancestors.
|
||||
std::vector<location> m_locs;
|
||||
|
||||
/*!
|
||||
\brief Represents infos about a macro
|
||||
*/
|
||||
struct macro_info
|
||||
{
|
||||
explicit macro_info(context &ctx);
|
||||
~macro_info() = default;
|
||||
macro_info(macro_info&&) = default;
|
||||
macro_info& operator = (macro_info&&) = default;
|
||||
macro_info(const macro_info&) = default;
|
||||
macro_info& operator = (const macro_info&) = default;
|
||||
|
||||
context ctx;
|
||||
context cond_ctx;
|
||||
size_t index;
|
||||
size_t visibility;
|
||||
std::string name;
|
||||
std::string cond;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Represents infos about a single rule exception
|
||||
*/
|
||||
struct rule_exception_info
|
||||
{
|
||||
explicit rule_exception_info(context &ctx);
|
||||
~rule_exception_info() = default;
|
||||
rule_exception_info(rule_exception_info&&) = default;
|
||||
rule_exception_info& operator = (rule_exception_info&&) = default;
|
||||
rule_exception_info(const rule_exception_info&) = default;
|
||||
rule_exception_info& operator = (const rule_exception_info&) = default;
|
||||
|
||||
/*!
|
||||
\brief This is necessary due to the dynamic-typed nature of
|
||||
exceptions. Each of fields, comps, and values, can either be a
|
||||
single value or a list of values. This is a simple hack to make
|
||||
this easier to implement in C++, that is not non-dynamic-typed.
|
||||
*/
|
||||
struct entry {
|
||||
entry(): is_list(false) {}
|
||||
explicit entry(const std::string& i): is_list(false), item(i) {}
|
||||
explicit entry(const std::vector<entry>& v): is_list(true), items(v) {}
|
||||
entry(entry&&) = default;
|
||||
entry& operator = (entry&&) = default;
|
||||
entry(const entry&) = default;
|
||||
entry& operator = (const entry&) = default;
|
||||
|
||||
bool is_list;
|
||||
std::string item;
|
||||
std::vector<entry> items;
|
||||
|
||||
inline bool is_valid() const
|
||||
{
|
||||
return (is_list && !items.empty())
|
||||
|| (!is_list && !item.empty());
|
||||
}
|
||||
};
|
||||
|
||||
context ctx;
|
||||
std::string name;
|
||||
entry fields;
|
||||
entry comps;
|
||||
std::vector<entry> values;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Represents infos about a rule
|
||||
*/
|
||||
struct rule_info
|
||||
{
|
||||
explicit rule_info(context &ctx);
|
||||
~rule_info() = default;
|
||||
rule_info(rule_info&&) = default;
|
||||
rule_info& operator = (rule_info&&) = default;
|
||||
rule_info(const rule_info&) = default;
|
||||
rule_info& operator = (const rule_info&) = default;
|
||||
|
||||
context ctx;
|
||||
context cond_ctx;
|
||||
context output_ctx;
|
||||
size_t index;
|
||||
size_t visibility;
|
||||
bool unknown_source;
|
||||
std::string name;
|
||||
std::string cond;
|
||||
std::string source;
|
||||
std::string desc;
|
||||
std::string output;
|
||||
std::set<std::string> tags;
|
||||
std::vector<rule_exception_info> exceptions;
|
||||
falco_common::priority_type priority;
|
||||
bool enabled;
|
||||
bool warn_evttypes;
|
||||
bool skip_if_unknown_filter;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Represents infos about a rule update (append or replace) request
|
||||
*/
|
||||
|
||||
struct rule_update_info
|
||||
{
|
||||
explicit 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;
|
||||
};
|
||||
// If non-empty, this content will be used when
|
||||
// creating snippets. Used for contexts involving
|
||||
// condition expressions.
|
||||
std::string alt_content;
|
||||
};
|
||||
|
||||
struct warning {
|
||||
warning():
|
||||
wc(falco::load_result::warning_code::LOAD_UNKNOWN_SOURCE),
|
||||
ctx("no-filename-given") {}
|
||||
warning(falco::load_result::warning_code w, const std::string& m, const context& c):
|
||||
wc(w),
|
||||
msg(m),
|
||||
ctx(c) {}
|
||||
warning(warning&&) = default;
|
||||
warning& operator=(warning&&) = default;
|
||||
warning(const warning&) = default;
|
||||
warning& operator=(const warning&) = default;
|
||||
|
||||
falco::load_result::warning_code wc;
|
||||
std::string msg;
|
||||
context ctx;
|
||||
};
|
||||
|
||||
struct error {
|
||||
error(): ec(falco::load_result::error_code::LOAD_ERR_FILE_READ), ctx("no-filename-given") {}
|
||||
error(falco::load_result::error_code e, const std::string& m, const context& c):
|
||||
ec(e),
|
||||
msg(m),
|
||||
ctx(c) {}
|
||||
error(error&&) = default;
|
||||
error& operator=(error&&) = default;
|
||||
error(const error&) = default;
|
||||
error& operator=(const error&) = default;
|
||||
|
||||
falco::load_result::error_code ec;
|
||||
std::string msg;
|
||||
context ctx;
|
||||
};
|
||||
|
||||
class rule_load_exception : public std::exception {
|
||||
public:
|
||||
rule_load_exception(falco::load_result::error_code ec,
|
||||
const std::string& msg,
|
||||
const context& ctx);
|
||||
virtual ~rule_load_exception();
|
||||
|
||||
const char* what() const noexcept override;
|
||||
|
||||
falco::load_result::error_code ec;
|
||||
std::string msg;
|
||||
context ctx;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Contains the result of loading rule definitions
|
||||
*/
|
||||
class result : public falco::load_result {
|
||||
public:
|
||||
explicit result(const std::string& name);
|
||||
virtual ~result() = default;
|
||||
result(result&&) = default;
|
||||
result& operator=(result&&) = default;
|
||||
result(const result&) = default;
|
||||
result& operator=(const result&) = default;
|
||||
|
||||
virtual bool successful() override;
|
||||
virtual bool has_warnings() override;
|
||||
|
||||
virtual const std::string& as_string(
|
||||
bool verbose,
|
||||
const falco::load_result::rules_contents_t& contents) override;
|
||||
virtual const nlohmann::json& as_json(
|
||||
const falco::load_result::rules_contents_t& contents) override;
|
||||
|
||||
void add_error(falco::load_result::error_code ec, const std::string& msg, const context& ctx);
|
||||
|
||||
void add_warning(falco::load_result::warning_code ec,
|
||||
const std::string& msg,
|
||||
const context& ctx);
|
||||
|
||||
void set_schema_validation_status(const std::vector<std::string>& status);
|
||||
std::string schema_validation();
|
||||
|
||||
protected:
|
||||
const std::string& as_summary_string();
|
||||
const std::string& as_verbose_string(const falco::load_result::rules_contents_t& contents);
|
||||
std::string name;
|
||||
bool success;
|
||||
std::vector<std::string> schema_validation_status;
|
||||
|
||||
std::vector<error> errors;
|
||||
std::vector<warning> warnings;
|
||||
|
||||
std::string res_summary_string;
|
||||
std::string res_verbose_string;
|
||||
nlohmann::json res_json;
|
||||
};
|
||||
|
||||
struct extra_output_format_conf {
|
||||
std::string m_format;
|
||||
std::string m_source;
|
||||
std::set<std::string> m_tags;
|
||||
std::string m_rule;
|
||||
bool m_replace_container_info;
|
||||
};
|
||||
|
||||
struct extra_output_field_conf {
|
||||
std::string m_key;
|
||||
std::string m_format;
|
||||
std::string m_source;
|
||||
std::set<std::string> m_tags;
|
||||
std::string m_rule;
|
||||
bool m_raw;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Contains the info required to load rule definitions
|
||||
*/
|
||||
struct configuration {
|
||||
explicit configuration(const std::string& cont,
|
||||
const indexed_vector<falco_source>& srcs,
|
||||
const std::string& name):
|
||||
content(cont),
|
||||
sources(srcs),
|
||||
name(name),
|
||||
res(std::make_unique<result>(name)) {}
|
||||
|
||||
// inputs
|
||||
const std::string& content;
|
||||
const indexed_vector<falco_source>& sources;
|
||||
std::string name;
|
||||
|
||||
std::vector<extra_output_format_conf> extra_output_format;
|
||||
std::vector<extra_output_field_conf> extra_output_fields;
|
||||
|
||||
// outputs
|
||||
std::unique_ptr<result> res;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Represents infos about an engine version requirement
|
||||
*/
|
||||
struct engine_version_info {
|
||||
engine_version_info(): ctx("no-filename-given"), version("0.0.0") {};
|
||||
explicit engine_version_info(context& ctx);
|
||||
~engine_version_info() = default;
|
||||
engine_version_info(engine_version_info&&) = default;
|
||||
engine_version_info& operator=(engine_version_info&&) = default;
|
||||
engine_version_info(const engine_version_info&) = default;
|
||||
engine_version_info& operator=(const engine_version_info&) = default;
|
||||
|
||||
context ctx;
|
||||
sinsp_version version;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Represents infos about a plugin version requirement
|
||||
*/
|
||||
struct plugin_version_info {
|
||||
struct requirement {
|
||||
requirement() = default;
|
||||
requirement(const std::string& n, const std::string& v): name(n), version(v) {}
|
||||
requirement(requirement&&) = default;
|
||||
requirement& operator=(requirement&&) = default;
|
||||
requirement(const requirement&) = default;
|
||||
requirement& operator=(const requirement&) = default;
|
||||
|
||||
std::string name;
|
||||
std::string version;
|
||||
};
|
||||
|
||||
typedef std::vector<requirement> requirement_alternatives;
|
||||
|
||||
// This differs from the other _info structs by having
|
||||
// a default constructor. This allows it to be used
|
||||
// by falco_engine, which aliases the type.
|
||||
plugin_version_info();
|
||||
explicit plugin_version_info(context& ctx);
|
||||
~plugin_version_info() = default;
|
||||
plugin_version_info(plugin_version_info&&) = default;
|
||||
plugin_version_info& operator=(plugin_version_info&&) = default;
|
||||
plugin_version_info(const plugin_version_info&) = default;
|
||||
plugin_version_info& operator=(const plugin_version_info&) = default;
|
||||
|
||||
context ctx;
|
||||
requirement_alternatives alternatives;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Represents infos about a list
|
||||
*/
|
||||
struct list_info {
|
||||
explicit list_info(context& ctx);
|
||||
~list_info() = default;
|
||||
list_info(list_info&&) = default;
|
||||
list_info& operator=(list_info&&) = default;
|
||||
list_info(const list_info&) = default;
|
||||
list_info& operator=(const list_info&) = default;
|
||||
|
||||
context ctx;
|
||||
size_t index;
|
||||
size_t visibility;
|
||||
std::string name;
|
||||
std::vector<std::string> items;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Represents infos about a macro
|
||||
*/
|
||||
struct macro_info {
|
||||
explicit macro_info(context& ctx);
|
||||
~macro_info() = default;
|
||||
macro_info(macro_info&&) = default;
|
||||
macro_info& operator=(macro_info&&) = default;
|
||||
macro_info(const macro_info&) = default;
|
||||
macro_info& operator=(const macro_info&) = default;
|
||||
|
||||
context ctx;
|
||||
context cond_ctx;
|
||||
size_t index;
|
||||
size_t visibility;
|
||||
std::string name;
|
||||
std::string cond;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Represents infos about a single rule exception
|
||||
*/
|
||||
struct rule_exception_info {
|
||||
explicit rule_exception_info(context& ctx);
|
||||
~rule_exception_info() = default;
|
||||
rule_exception_info(rule_exception_info&&) = default;
|
||||
rule_exception_info& operator=(rule_exception_info&&) = default;
|
||||
rule_exception_info(const rule_exception_info&) = default;
|
||||
rule_exception_info& operator=(const rule_exception_info&) = default;
|
||||
|
||||
/*!
|
||||
\brief This is necessary due to the dynamic-typed nature of
|
||||
exceptions. Each of fields, comps, and values, can either be a
|
||||
single value or a list of values. This is a simple hack to make
|
||||
this easier to implement in C++, that is not non-dynamic-typed.
|
||||
*/
|
||||
struct entry {
|
||||
entry(): is_list(false) {}
|
||||
explicit entry(const std::string& i): is_list(false), item(i) {}
|
||||
explicit entry(const std::vector<entry>& v): is_list(true), items(v) {}
|
||||
entry(entry&&) = default;
|
||||
entry& operator=(entry&&) = default;
|
||||
entry(const entry&) = default;
|
||||
entry& operator=(const entry&) = default;
|
||||
|
||||
bool is_list;
|
||||
std::string item;
|
||||
std::vector<entry> items;
|
||||
|
||||
inline bool is_valid() const {
|
||||
return (is_list && !items.empty()) || (!is_list && !item.empty());
|
||||
}
|
||||
};
|
||||
|
||||
context ctx;
|
||||
std::string name;
|
||||
entry fields;
|
||||
entry comps;
|
||||
std::vector<entry> values;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Represents infos about a rule
|
||||
*/
|
||||
struct rule_info {
|
||||
explicit rule_info(context& ctx);
|
||||
~rule_info() = default;
|
||||
rule_info(rule_info&&) = default;
|
||||
rule_info& operator=(rule_info&&) = default;
|
||||
rule_info(const rule_info&) = default;
|
||||
rule_info& operator=(const rule_info&) = default;
|
||||
|
||||
context ctx;
|
||||
context cond_ctx;
|
||||
context output_ctx;
|
||||
size_t index;
|
||||
size_t visibility;
|
||||
bool unknown_source;
|
||||
std::string name;
|
||||
std::string cond;
|
||||
std::string source;
|
||||
std::string desc;
|
||||
std::string output;
|
||||
std::set<std::string> tags;
|
||||
std::vector<rule_exception_info> exceptions;
|
||||
falco_common::priority_type priority;
|
||||
bool enabled;
|
||||
bool warn_evttypes;
|
||||
bool skip_if_unknown_filter;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Represents infos about a rule update (append or replace) request
|
||||
*/
|
||||
|
||||
struct rule_update_info {
|
||||
explicit 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;
|
||||
};
|
||||
}; // namespace rule_loader
|
||||
|
||||
@@ -22,102 +22,86 @@ limitations under the License.
|
||||
#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)); } }
|
||||
#define THROW(cond, err, ctx) \
|
||||
{ \
|
||||
if((cond)) { \
|
||||
throw rule_loader::rule_load_exception(falco::load_result::LOAD_ERR_VALIDATE, \
|
||||
(err), \
|
||||
(ctx)); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
static inline bool is_operator_defined(const std::string& op)
|
||||
{
|
||||
static inline bool is_operator_defined(const std::string& op) {
|
||||
auto ops = libsinsp::filter::parser::supported_operators();
|
||||
return find(ops.begin(), ops.end(), op) != ops.end();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline void define_info(indexed_vector<T>& infos, T& info, uint32_t id)
|
||||
{
|
||||
template<typename T>
|
||||
static inline void define_info(indexed_vector<T>& infos, T& info, uint32_t id) {
|
||||
auto prev = infos.at(info.name);
|
||||
if (prev)
|
||||
{
|
||||
if(prev) {
|
||||
info.index = prev->index;
|
||||
info.visibility = id;
|
||||
*prev = info;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
info.index = id;
|
||||
info.visibility = id;
|
||||
infos.insert(info, info.name);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
static inline void append_info(T* prev, U& 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)
|
||||
{
|
||||
template<typename T, typename U>
|
||||
static inline void replace_info(T* prev, U& info, uint32_t id) {
|
||||
prev->visibility = id;
|
||||
}
|
||||
|
||||
static void validate_exception_info(
|
||||
const falco_source* source,
|
||||
rule_loader::rule_exception_info &ex)
|
||||
{
|
||||
if (ex.fields.is_list)
|
||||
{
|
||||
if (!ex.comps.is_valid())
|
||||
{
|
||||
static void validate_exception_info(const falco_source* source,
|
||||
rule_loader::rule_exception_info& ex) {
|
||||
if(ex.fields.is_list) {
|
||||
if(!ex.comps.is_valid()) {
|
||||
ex.comps.is_list = true;
|
||||
for (size_t i = 0; i < ex.fields.items.size(); i++)
|
||||
{
|
||||
for(size_t i = 0; i < ex.fields.items.size(); i++) {
|
||||
ex.comps.items.push_back(rule_loader::rule_exception_info::entry("="));
|
||||
}
|
||||
}
|
||||
THROW(ex.fields.items.size() != ex.comps.items.size(),
|
||||
"Fields and comps lists must have equal length",
|
||||
ex.ctx);
|
||||
for (const auto &v : ex.comps.items)
|
||||
{
|
||||
"Fields and comps lists must have equal length",
|
||||
ex.ctx);
|
||||
for(const auto& v : ex.comps.items) {
|
||||
THROW(!is_operator_defined(v.item),
|
||||
std::string("'") + v.item + "' is not a supported comparison operator",
|
||||
ex.ctx);
|
||||
}
|
||||
if (source)
|
||||
{
|
||||
for (const auto &v : ex.fields.items)
|
||||
{
|
||||
if(source) {
|
||||
for(const auto& v : ex.fields.items) {
|
||||
THROW(!source->is_valid_lhs_field(v.item),
|
||||
std::string("'") + v.item + "' is not a supported filter field",
|
||||
ex.ctx);
|
||||
std::string("'") + v.item + "' is not a supported filter field",
|
||||
ex.ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ex.comps.is_valid())
|
||||
{
|
||||
} else {
|
||||
if(!ex.comps.is_valid()) {
|
||||
ex.comps.is_list = false;
|
||||
ex.comps.item = "in";
|
||||
}
|
||||
THROW(ex.comps.is_list,
|
||||
"Fields and comps must both be strings",
|
||||
ex.ctx);
|
||||
THROW(ex.comps.is_list, "Fields and comps must both be strings", ex.ctx);
|
||||
THROW((ex.comps.item != "in" && ex.comps.item != "pmatch" && ex.comps.item != "intersects"),
|
||||
"When fields is a single value, comps must be one of (in, pmatch, intersects)",
|
||||
ex.ctx);
|
||||
if (source)
|
||||
{
|
||||
if(source) {
|
||||
THROW(!source->is_valid_lhs_field(ex.fields.item),
|
||||
std::string("'") + ex.fields.item + "' is not a supported filter field",
|
||||
ex.ctx);
|
||||
std::string("'") + ex.fields.item + "' is not a supported filter field",
|
||||
ex.ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rule_loader::collector::clear()
|
||||
{
|
||||
void rule_loader::collector::clear() {
|
||||
m_cur_index = 0;
|
||||
m_rule_infos.clear();
|
||||
m_list_infos.clear();
|
||||
@@ -125,84 +109,71 @@ void rule_loader::collector::clear()
|
||||
m_required_plugin_versions.clear();
|
||||
}
|
||||
|
||||
const std::vector<rule_loader::plugin_version_info::requirement_alternatives>& rule_loader::collector::required_plugin_versions() const
|
||||
{
|
||||
const std::vector<rule_loader::plugin_version_info::requirement_alternatives>&
|
||||
rule_loader::collector::required_plugin_versions() const {
|
||||
return m_required_plugin_versions;
|
||||
}
|
||||
|
||||
const rule_loader::engine_version_info& rule_loader::collector::required_engine_version() const
|
||||
{
|
||||
const rule_loader::engine_version_info& rule_loader::collector::required_engine_version() const {
|
||||
return m_required_engine_version;
|
||||
}
|
||||
|
||||
const indexed_vector<rule_loader::list_info>& rule_loader::collector::lists() const
|
||||
{
|
||||
const indexed_vector<rule_loader::list_info>& rule_loader::collector::lists() const {
|
||||
return m_list_infos;
|
||||
}
|
||||
|
||||
const indexed_vector<rule_loader::macro_info>& rule_loader::collector::macros() const
|
||||
{
|
||||
const indexed_vector<rule_loader::macro_info>& rule_loader::collector::macros() const {
|
||||
return m_macro_infos;
|
||||
}
|
||||
|
||||
const indexed_vector<rule_loader::rule_info>& rule_loader::collector::rules() const
|
||||
{
|
||||
const indexed_vector<rule_loader::rule_info>& rule_loader::collector::rules() const {
|
||||
return m_rule_infos;
|
||||
}
|
||||
|
||||
void rule_loader::collector::define(configuration& cfg, engine_version_info& info)
|
||||
{
|
||||
void rule_loader::collector::define(configuration& cfg, engine_version_info& info) {
|
||||
auto v = falco_engine::engine_version();
|
||||
THROW(!v.compatible_with(info.version), "Rules require engine version "
|
||||
+ info.version.as_string() + ", but engine version is " + v.as_string(),
|
||||
THROW(!v.compatible_with(info.version),
|
||||
"Rules require engine version " + info.version.as_string() + ", but engine version is " +
|
||||
v.as_string(),
|
||||
info.ctx);
|
||||
|
||||
|
||||
// Store max required_engine_version
|
||||
if(m_required_engine_version.version < info.version)
|
||||
{
|
||||
if(m_required_engine_version.version < info.version) {
|
||||
m_required_engine_version = info;
|
||||
}
|
||||
}
|
||||
|
||||
void rule_loader::collector::define(configuration& cfg, plugin_version_info& info)
|
||||
{
|
||||
void rule_loader::collector::define(configuration& cfg, plugin_version_info& info) {
|
||||
std::unordered_set<std::string> plugin_names;
|
||||
for (const auto& req : info.alternatives)
|
||||
{
|
||||
for(const auto& req : info.alternatives) {
|
||||
sinsp_version plugin_version(req.version);
|
||||
THROW(!plugin_version.is_valid(),
|
||||
"Invalid required version '" + req.version
|
||||
+ "' for plugin '" + req.name + "'",
|
||||
info.ctx);
|
||||
"Invalid required version '" + req.version + "' for plugin '" + req.name + "'",
|
||||
info.ctx);
|
||||
THROW(plugin_names.find(req.name) != plugin_names.end(),
|
||||
"Defined multiple alternative version requirements for plugin '"
|
||||
+ req.name + "'",
|
||||
info.ctx);
|
||||
"Defined multiple alternative version requirements for plugin '" + req.name + "'",
|
||||
info.ctx);
|
||||
plugin_names.insert(req.name);
|
||||
}
|
||||
m_required_plugin_versions.push_back(info.alternatives);
|
||||
}
|
||||
|
||||
void rule_loader::collector::define(configuration& cfg, list_info& info)
|
||||
{
|
||||
void rule_loader::collector::define(configuration& cfg, list_info& info) {
|
||||
define_info(m_list_infos, info, m_cur_index++);
|
||||
}
|
||||
|
||||
void rule_loader::collector::append(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, 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++);
|
||||
}
|
||||
|
||||
void rule_loader::collector::define(configuration& cfg, macro_info& info)
|
||||
{
|
||||
void rule_loader::collector::define(configuration& cfg, macro_info& info) {
|
||||
define_info(m_macro_infos, info, m_cur_index++);
|
||||
}
|
||||
|
||||
void rule_loader::collector::append(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, ERROR_NO_PREVIOUS_MACRO, info.ctx);
|
||||
prev->cond += " ";
|
||||
@@ -210,108 +181,92 @@ void rule_loader::collector::append(configuration& cfg, macro_info& info)
|
||||
append_info(prev, info, m_cur_index++);
|
||||
}
|
||||
|
||||
void rule_loader::collector::define(configuration& cfg, rule_info& info)
|
||||
{
|
||||
void rule_loader::collector::define(configuration& cfg, rule_info& info) {
|
||||
const auto* prev = m_rule_infos.at(info.name);
|
||||
THROW(prev && prev->source != info.source,
|
||||
"Rule has been re-defined with a different source",
|
||||
info.ctx);
|
||||
"Rule has been re-defined with a different source",
|
||||
info.ctx);
|
||||
|
||||
const auto* source = cfg.sources.at(info.source);
|
||||
if (!source)
|
||||
{
|
||||
if(!source) {
|
||||
info.unknown_source = true;
|
||||
cfg.res->add_warning(falco::load_result::LOAD_UNKNOWN_SOURCE,
|
||||
"Unknown source " + info.source + ", skipping",
|
||||
info.ctx);
|
||||
"Unknown source " + info.source + ", skipping",
|
||||
info.ctx);
|
||||
}
|
||||
for (auto &ex : info.exceptions)
|
||||
{
|
||||
for(auto& ex : info.exceptions) {
|
||||
THROW(!ex.fields.is_valid(),
|
||||
"Rule exception item must have fields property with a list of fields",
|
||||
ex.ctx);
|
||||
"Rule exception item must have fields property with a list of fields",
|
||||
ex.ctx);
|
||||
validate_exception_info(source, ex);
|
||||
}
|
||||
|
||||
define_info(m_rule_infos, info, m_cur_index++);
|
||||
}
|
||||
|
||||
void rule_loader::collector::append(configuration& cfg, rule_update_info& info)
|
||||
{
|
||||
void rule_loader::collector::append(configuration& cfg, rule_update_info& info) {
|
||||
auto prev = m_rule_infos.at(info.name);
|
||||
|
||||
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);
|
||||
"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
|
||||
// rule for which the source is unknown
|
||||
const falco_source* source = nullptr;
|
||||
if (!prev->unknown_source)
|
||||
{
|
||||
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);
|
||||
THROW(!source, std::string("Unknown source ") + prev->source, info.ctx);
|
||||
}
|
||||
|
||||
if (info.cond.has_value() && !info.cond->empty())
|
||||
{
|
||||
if(info.cond.has_value() && !info.cond->empty()) {
|
||||
prev->cond += " ";
|
||||
prev->cond += *info.cond;
|
||||
}
|
||||
|
||||
if (info.output.has_value() && !info.output->empty())
|
||||
{
|
||||
if(info.output.has_value() && !info.output->empty()) {
|
||||
prev->output += " ";
|
||||
prev->output += *info.output;
|
||||
}
|
||||
|
||||
if (info.desc.has_value() && !info.desc->empty())
|
||||
{
|
||||
if(info.desc.has_value() && !info.desc->empty()) {
|
||||
prev->desc += " ";
|
||||
prev->desc += *info.desc;
|
||||
}
|
||||
|
||||
if (info.tags.has_value())
|
||||
{
|
||||
for (auto &tag: *info.tags)
|
||||
{
|
||||
if(info.tags.has_value()) {
|
||||
for(auto& tag : *info.tags) {
|
||||
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())
|
||||
{
|
||||
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);
|
||||
"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);
|
||||
"Rule exception must have values property with a list of values",
|
||||
ex.ctx);
|
||||
validate_exception_info(source, ex);
|
||||
prev->exceptions.push_back(ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
THROW(ex.fields.is_valid(),
|
||||
"Can not append exception fields to existing exception, only values",
|
||||
ex.ctx);
|
||||
"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());
|
||||
"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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -319,80 +274,64 @@ void rule_loader::collector::append(configuration& cfg, rule_update_info& info)
|
||||
append_info(prev, info, m_cur_index++);
|
||||
}
|
||||
|
||||
void rule_loader::collector::selective_replace(configuration& cfg, rule_update_info& info)
|
||||
{
|
||||
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);
|
||||
"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
|
||||
const falco_source* source = nullptr;
|
||||
if (!prev->unknown_source)
|
||||
{
|
||||
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);
|
||||
THROW(!source, std::string("Unknown source ") + prev->source, info.ctx);
|
||||
}
|
||||
|
||||
if (info.cond.has_value())
|
||||
{
|
||||
if(info.cond.has_value()) {
|
||||
prev->cond = *info.cond;
|
||||
}
|
||||
|
||||
if (info.output.has_value())
|
||||
{
|
||||
if(info.output.has_value()) {
|
||||
prev->output = *info.output;
|
||||
}
|
||||
|
||||
if (info.desc.has_value())
|
||||
{
|
||||
if(info.desc.has_value()) {
|
||||
prev->desc = *info.desc;
|
||||
}
|
||||
|
||||
if (info.tags.has_value())
|
||||
{
|
||||
if(info.tags.has_value()) {
|
||||
prev->tags = *info.tags;
|
||||
}
|
||||
|
||||
if (info.exceptions.has_value())
|
||||
{
|
||||
if(info.exceptions.has_value()) {
|
||||
prev->exceptions = *info.exceptions;
|
||||
}
|
||||
|
||||
if (info.priority.has_value())
|
||||
{
|
||||
if(info.priority.has_value()) {
|
||||
prev->priority = *info.priority;
|
||||
}
|
||||
|
||||
if (info.enabled.has_value())
|
||||
{
|
||||
if(info.enabled.has_value()) {
|
||||
prev->enabled = *info.enabled;
|
||||
}
|
||||
|
||||
if (info.warn_evttypes.has_value())
|
||||
{
|
||||
if(info.warn_evttypes.has_value()) {
|
||||
prev->warn_evttypes = *info.warn_evttypes;
|
||||
}
|
||||
|
||||
if (info.skip_if_unknown_filter.has_value())
|
||||
{
|
||||
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)
|
||||
{
|
||||
void rule_loader::collector::enable(configuration& cfg, rule_info& info) {
|
||||
auto prev = m_rule_infos.at(info.name);
|
||||
THROW(!prev,
|
||||
"Rule has 'enabled' key but no rule by that name already exists",
|
||||
info.ctx);
|
||||
THROW(!prev, "Rule has 'enabled' key but no rule by that name already exists", info.ctx);
|
||||
prev->enabled = info.enabled;
|
||||
}
|
||||
|
||||
@@ -21,56 +21,55 @@ limitations under the License.
|
||||
#include "rule_loader.h"
|
||||
#include "indexed_vector.h"
|
||||
|
||||
namespace rule_loader
|
||||
{
|
||||
namespace rule_loader {
|
||||
|
||||
/*!
|
||||
\brief Collector for the ruleset loader of the falco engine
|
||||
\brief Collector for the ruleset loader of the falco engine
|
||||
*/
|
||||
class collector
|
||||
{
|
||||
class collector {
|
||||
public:
|
||||
collector(): m_cur_index(0) { }
|
||||
collector(): m_cur_index(0) {}
|
||||
virtual ~collector() = default;
|
||||
collector(collector&&) = default;
|
||||
collector& operator = (collector&&) = default;
|
||||
collector& operator=(collector&&) = default;
|
||||
collector(const collector&) = delete;
|
||||
collector& operator = (const collector&) = delete;
|
||||
collector& operator=(const collector&) = delete;
|
||||
|
||||
/*!
|
||||
\brief Erases all the internal state and definitions
|
||||
\brief Erases all the internal state and definitions
|
||||
*/
|
||||
virtual void clear();
|
||||
|
||||
/*!
|
||||
\brief Returns the set of all defined required plugin versions
|
||||
\brief Returns the set of all defined required plugin versions
|
||||
*/
|
||||
virtual const std::vector<plugin_version_info::requirement_alternatives>& required_plugin_versions() const;
|
||||
virtual const std::vector<plugin_version_info::requirement_alternatives>&
|
||||
required_plugin_versions() const;
|
||||
|
||||
/*!
|
||||
\brief Returns the required engine versions
|
||||
\brief Returns the required engine versions
|
||||
*/
|
||||
virtual const engine_version_info& required_engine_version() const;
|
||||
|
||||
/*!
|
||||
\brief Returns the list of defined lists
|
||||
\brief Returns the list of defined lists
|
||||
*/
|
||||
virtual const indexed_vector<list_info>& lists() const;
|
||||
|
||||
/*!
|
||||
\brief Returns the list of defined macros
|
||||
\brief Returns the list of defined macros
|
||||
*/
|
||||
virtual const indexed_vector<macro_info>& macros() const;
|
||||
|
||||
/*!
|
||||
\brief Returns the list of defined rules
|
||||
\brief Returns the list of defined rules
|
||||
*/
|
||||
virtual const indexed_vector<rule_info>& rules() const;
|
||||
|
||||
/*!
|
||||
\brief Defines an info block. If a similar info block is found
|
||||
in the internal state (e.g. another rule with same name), then
|
||||
the previous definition gets overwritten
|
||||
\brief Defines an info block. If a similar info block is found
|
||||
in the internal state (e.g. another rule with same name), then
|
||||
the previous definition gets overwritten
|
||||
*/
|
||||
virtual void define(configuration& cfg, engine_version_info& info);
|
||||
virtual void define(configuration& cfg, plugin_version_info& info);
|
||||
@@ -79,21 +78,21 @@ public:
|
||||
virtual void define(configuration& cfg, rule_info& info);
|
||||
|
||||
/*!
|
||||
\brief Appends an info block to an existing one. An exception
|
||||
is thrown if no existing definition can be matched with the appended
|
||||
one
|
||||
\brief Appends an info block to an existing one. An exception
|
||||
is thrown if no existing definition can be matched with the appended
|
||||
one
|
||||
*/
|
||||
virtual void append(configuration& cfg, list_info& info);
|
||||
virtual void append(configuration& cfg, macro_info& info);
|
||||
virtual void append(configuration& cfg, rule_update_info& info);
|
||||
|
||||
/*!
|
||||
\brief Updates the 'enabled' flag of an existing definition
|
||||
\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
|
||||
\brief Selectively replaces some fields of an existing definition
|
||||
*/
|
||||
virtual void selective_replace(configuration& cfg, rule_update_info& info);
|
||||
|
||||
@@ -106,4 +105,4 @@ private:
|
||||
engine_version_info m_required_engine_version;
|
||||
};
|
||||
|
||||
}; // namespace rule_loader
|
||||
}; // namespace rule_loader
|
||||
|
||||
@@ -20,20 +20,17 @@ limitations under the License.
|
||||
#include "indexed_vector.h"
|
||||
#include "falco_rule.h"
|
||||
|
||||
namespace rule_loader
|
||||
{
|
||||
struct compile_output
|
||||
{
|
||||
compile_output() = default;
|
||||
virtual ~compile_output() = default;
|
||||
compile_output(compile_output&&) = default;
|
||||
compile_output& operator = (compile_output&&) = default;
|
||||
compile_output(const compile_output&) = default;
|
||||
compile_output& operator = (const compile_output&) = default;
|
||||
namespace rule_loader {
|
||||
struct compile_output {
|
||||
compile_output() = default;
|
||||
virtual ~compile_output() = default;
|
||||
compile_output(compile_output&&) = default;
|
||||
compile_output& operator=(compile_output&&) = default;
|
||||
compile_output(const compile_output&) = default;
|
||||
compile_output& operator=(const compile_output&) = default;
|
||||
|
||||
indexed_vector<falco_list> lists;
|
||||
indexed_vector<falco_macro> macros;
|
||||
indexed_vector<falco_rule> rules;
|
||||
};
|
||||
indexed_vector<falco_list> lists;
|
||||
indexed_vector<falco_macro> macros;
|
||||
indexed_vector<falco_rule> rules;
|
||||
};
|
||||
|
||||
}; // namespace rule_loader
|
||||
|
||||
@@ -24,117 +24,96 @@ limitations under the License.
|
||||
#include "rule_loader_compiler.h"
|
||||
#include "filter_warning_resolver.h"
|
||||
|
||||
#define MAX_VISIBILITY ((uint32_t) -1)
|
||||
#define MAX_VISIBILITY ((uint32_t) - 1)
|
||||
|
||||
#define THROW(cond, err, ctx) { if ((cond)) { throw rule_loader::rule_load_exception(falco::load_result::LOAD_ERR_VALIDATE, (err), (ctx)); } }
|
||||
#define THROW(cond, err, ctx) \
|
||||
{ \
|
||||
if((cond)) { \
|
||||
throw rule_loader::rule_load_exception(falco::load_result::LOAD_ERR_VALIDATE, \
|
||||
(err), \
|
||||
(ctx)); \
|
||||
} \
|
||||
}
|
||||
|
||||
static std::string s_container_info_fmt = "%container.info";
|
||||
static std::string s_default_extra_fmt = "container_id=%container.id container_name=%container.name";
|
||||
static std::string s_default_extra_fmt =
|
||||
"container_id=%container.id container_name=%container.name";
|
||||
|
||||
using namespace libsinsp::filter;
|
||||
|
||||
// todo(jasondellaluce): this breaks string escaping in lists and exceptions
|
||||
static void quote_item(std::string& e)
|
||||
{
|
||||
if (e.find(" ") != std::string::npos && e[0] != '"' && e[0] != '\'')
|
||||
{
|
||||
static void quote_item(std::string& e) {
|
||||
if(e.find(" ") != std::string::npos && e[0] != '"' && e[0] != '\'') {
|
||||
e = '"' + e + '"';
|
||||
}
|
||||
}
|
||||
|
||||
static void paren_item(std::string& e)
|
||||
{
|
||||
if(e[0] != '(')
|
||||
{
|
||||
static void paren_item(std::string& e) {
|
||||
if(e[0] != '(') {
|
||||
e = '(' + e + ')';
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool is_operator_for_list(const std::string& op)
|
||||
{
|
||||
static inline bool is_operator_for_list(const std::string& op) {
|
||||
auto ops = libsinsp::filter::parser::supported_operators(true);
|
||||
return find(ops.begin(), ops.end(), op) != ops.end();
|
||||
}
|
||||
|
||||
static bool is_format_valid(const falco_source& source, std::string fmt, std::string& err)
|
||||
{
|
||||
try
|
||||
{
|
||||
static bool is_format_valid(const falco_source& source, std::string fmt, std::string& err) {
|
||||
try {
|
||||
std::shared_ptr<sinsp_evt_formatter> formatter;
|
||||
formatter = source.formatter_factory->create_formatter(fmt);
|
||||
return true;
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
} catch(std::exception& e) {
|
||||
err = e.what();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void build_rule_exception_infos(
|
||||
const std::vector<rule_loader::rule_exception_info>& exceptions,
|
||||
std::set<std::string>& exception_fields,
|
||||
std::string& condition)
|
||||
{
|
||||
const std::vector<rule_loader::rule_exception_info>& exceptions,
|
||||
std::set<std::string>& exception_fields,
|
||||
std::string& condition) {
|
||||
std::string tmp;
|
||||
condition = "(" + condition + ")";
|
||||
for (const auto &ex : exceptions)
|
||||
{
|
||||
for(const auto& ex : exceptions) {
|
||||
std::string icond;
|
||||
if(!ex.fields.is_list)
|
||||
{
|
||||
for (const auto &val : ex.values)
|
||||
{
|
||||
THROW(val.is_list,
|
||||
"Expected values array to contain a list of strings",
|
||||
ex.ctx)
|
||||
icond += icond.empty()
|
||||
? ("(" + ex.fields.item + " "
|
||||
+ ex.comps.item + " (")
|
||||
: ", ";
|
||||
if(!ex.fields.is_list) {
|
||||
for(const auto& val : ex.values) {
|
||||
THROW(val.is_list, "Expected values array to contain a list of strings", ex.ctx)
|
||||
icond += icond.empty() ? ("(" + ex.fields.item + " " + ex.comps.item + " (") : ", ";
|
||||
exception_fields.insert(ex.fields.item);
|
||||
tmp = val.item;
|
||||
quote_item(tmp);
|
||||
icond += tmp;
|
||||
}
|
||||
icond += icond.empty() ? "" : "))";
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
icond = "(";
|
||||
for (const auto &values : ex.values)
|
||||
{
|
||||
for(const auto& values : ex.values) {
|
||||
THROW(ex.fields.items.size() != values.items.size(),
|
||||
"Fields and values lists must have equal length",
|
||||
ex.ctx);
|
||||
"Fields and values lists must have equal length",
|
||||
ex.ctx);
|
||||
icond += icond == "(" ? "" : " or ";
|
||||
icond += "(";
|
||||
uint32_t k = 0;
|
||||
std::string istr;
|
||||
for (const auto &field : ex.fields.items)
|
||||
{
|
||||
for(const auto& field : ex.fields.items) {
|
||||
icond += k == 0 ? "" : " and ";
|
||||
if (values.items[k].is_list)
|
||||
{
|
||||
if(values.items[k].is_list) {
|
||||
istr = "(";
|
||||
for (const auto &v : values.items[k].items)
|
||||
{
|
||||
for(const auto& v : values.items[k].items) {
|
||||
tmp = v.item;
|
||||
quote_item(tmp);
|
||||
istr += istr == "(" ? "" : ", ";
|
||||
istr += tmp;
|
||||
}
|
||||
istr += ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
istr = values.items[k].item;
|
||||
if(is_operator_for_list(ex.comps.items[k].item))
|
||||
{
|
||||
if(is_operator_for_list(ex.comps.items[k].item)) {
|
||||
paren_item(istr);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
quote_item(istr);
|
||||
}
|
||||
}
|
||||
@@ -146,8 +125,7 @@ static void build_rule_exception_infos(
|
||||
icond += ")";
|
||||
}
|
||||
icond += ")";
|
||||
if (icond == "()")
|
||||
{
|
||||
if(icond == "()") {
|
||||
icond = "";
|
||||
}
|
||||
}
|
||||
@@ -155,31 +133,26 @@ static void build_rule_exception_infos(
|
||||
}
|
||||
}
|
||||
|
||||
static inline rule_loader::list_info* list_info_from_name(
|
||||
const rule_loader::collector& c, const std::string& name)
|
||||
{
|
||||
static inline rule_loader::list_info* list_info_from_name(const rule_loader::collector& c,
|
||||
const std::string& name) {
|
||||
auto ret = c.lists().at(name);
|
||||
if (!ret)
|
||||
{
|
||||
if(!ret) {
|
||||
throw falco_exception("can't find internal list info at name: " + name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline rule_loader::macro_info* macro_info_from_name(
|
||||
const rule_loader::collector& c, const std::string& name)
|
||||
{
|
||||
static inline rule_loader::macro_info* macro_info_from_name(const rule_loader::collector& c,
|
||||
const std::string& name) {
|
||||
auto ret = c.macros().at(name);
|
||||
if (!ret)
|
||||
{
|
||||
if(!ret) {
|
||||
throw falco_exception("can't find internal macro info at name: " + name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// todo(jasondellaluce): this breaks string escaping in lists
|
||||
static bool resolve_list(std::string& cnd, const falco_list& list)
|
||||
{
|
||||
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;
|
||||
@@ -187,31 +160,23 @@ static bool resolve_list(std::string& cnd, const falco_list& list)
|
||||
size_t start, end;
|
||||
bool used = false;
|
||||
start = cnd.find(list.name);
|
||||
while (start != std::string::npos)
|
||||
{
|
||||
while(start != std::string::npos) {
|
||||
// the characters surrounding the name must
|
||||
// be delims of beginning/end of string
|
||||
end = start + list.name.length();
|
||||
if ((start == 0 || delims.find(cnd[start - 1]) != std::string::npos)
|
||||
&& (end >= cnd.length() || delims.find(cnd[end]) != std::string::npos))
|
||||
{
|
||||
if((start == 0 || delims.find(cnd[start - 1]) != std::string::npos) &&
|
||||
(end >= cnd.length() || delims.find(cnd[end]) != std::string::npos)) {
|
||||
// shift pointers to consume all whitespaces
|
||||
while (start > 0
|
||||
&& blanks.find(cnd[start - 1]) != std::string::npos)
|
||||
{
|
||||
while(start > 0 && blanks.find(cnd[start - 1]) != std::string::npos) {
|
||||
start--;
|
||||
}
|
||||
while (end < cnd.length()
|
||||
&& blanks.find(cnd[end]) != std::string::npos)
|
||||
{
|
||||
while(end < cnd.length() && blanks.find(cnd[end]) != std::string::npos) {
|
||||
end++;
|
||||
}
|
||||
// create substitution string by concatenating all values
|
||||
std::string sub = "";
|
||||
for (const auto &v : list.items)
|
||||
{
|
||||
if (!sub.empty())
|
||||
{
|
||||
for(const auto& v : list.items) {
|
||||
if(!sub.empty()) {
|
||||
sub += ", ";
|
||||
}
|
||||
tmp = v;
|
||||
@@ -220,26 +185,20 @@ static bool resolve_list(std::string& cnd, const falco_list& list)
|
||||
}
|
||||
// if substituted list is empty, we need to
|
||||
// remove a comma from the left or the right
|
||||
if (sub.empty())
|
||||
{
|
||||
if (start > 0 && cnd[start - 1] == ',')
|
||||
{
|
||||
if(sub.empty()) {
|
||||
if(start > 0 && cnd[start - 1] == ',') {
|
||||
start--;
|
||||
}
|
||||
else if (end < cnd.length() && cnd[end] == ',')
|
||||
{
|
||||
} else if(end < cnd.length() && cnd[end] == ',') {
|
||||
end++;
|
||||
}
|
||||
}
|
||||
// compose new string with substitution
|
||||
new_cnd = "";
|
||||
if (start > 0)
|
||||
{
|
||||
if(start > 0) {
|
||||
new_cnd += cnd.substr(0, start) + " ";
|
||||
}
|
||||
new_cnd += sub + " ";
|
||||
if (end <= cnd.length())
|
||||
{
|
||||
if(end <= cnd.length()) {
|
||||
new_cnd += cnd.substr(end);
|
||||
}
|
||||
cnd = new_cnd;
|
||||
@@ -251,20 +210,16 @@ static bool resolve_list(std::string& cnd, const falco_list& list)
|
||||
return used;
|
||||
}
|
||||
|
||||
static inline void resolve_macros(
|
||||
filter_macro_resolver& macro_resolver,
|
||||
const indexed_vector<rule_loader::macro_info>& infos,
|
||||
indexed_vector<falco_macro>& macros,
|
||||
std::shared_ptr<ast::expr>& ast,
|
||||
const std::string& condition,
|
||||
uint32_t visibility,
|
||||
const rule_loader::context &ctx)
|
||||
{
|
||||
static inline void resolve_macros(filter_macro_resolver& macro_resolver,
|
||||
const indexed_vector<rule_loader::macro_info>& infos,
|
||||
indexed_vector<falco_macro>& macros,
|
||||
std::shared_ptr<ast::expr>& ast,
|
||||
const std::string& condition,
|
||||
uint32_t visibility,
|
||||
const rule_loader::context& ctx) {
|
||||
macro_resolver.clear();
|
||||
for (const auto &m : infos)
|
||||
{
|
||||
if (m.index < visibility)
|
||||
{
|
||||
for(const auto& m : infos) {
|
||||
if(m.index < visibility) {
|
||||
auto macro = macros.at(m.name);
|
||||
macro_resolver.set_macro(m.name, macro->condition);
|
||||
}
|
||||
@@ -274,79 +229,61 @@ static inline void resolve_macros(
|
||||
// Note: only complaining about the first error or unknown macro
|
||||
const auto& errors_macros = macro_resolver.get_errors();
|
||||
const auto& unresolved_macros = macro_resolver.get_unknown_macros();
|
||||
if(!errors_macros.empty() || !unresolved_macros.empty())
|
||||
{
|
||||
auto errpos = !errors_macros.empty()
|
||||
? errors_macros.begin()->second
|
||||
: unresolved_macros.begin()->second;
|
||||
if(!errors_macros.empty() || !unresolved_macros.empty()) {
|
||||
auto errpos = !errors_macros.empty() ? errors_macros.begin()->second
|
||||
: unresolved_macros.begin()->second;
|
||||
std::string errmsg = !errors_macros.empty()
|
||||
? errors_macros.begin()->first
|
||||
: ("Undefined macro '" + unresolved_macros.begin()->first + "' used in filter.");
|
||||
? errors_macros.begin()->first
|
||||
: ("Undefined macro '" + unresolved_macros.begin()->first +
|
||||
"' used in filter.");
|
||||
const rule_loader::context cond_ctx(errpos, condition, ctx);
|
||||
THROW(true, errmsg, cond_ctx);
|
||||
}
|
||||
|
||||
for (const auto &it : macro_resolver.get_resolved_macros())
|
||||
{
|
||||
for(const auto& it : macro_resolver.get_resolved_macros()) {
|
||||
macros.at(it.first)->used = true;
|
||||
}
|
||||
}
|
||||
|
||||
// note: there is no visibility order between filter conditions and lists
|
||||
static std::shared_ptr<ast::expr> parse_condition(
|
||||
std::string condition,
|
||||
indexed_vector<falco_list>& lists,
|
||||
const rule_loader::context &ctx)
|
||||
{
|
||||
for (auto &l : lists)
|
||||
{
|
||||
if (resolve_list(condition, l))
|
||||
{
|
||||
static std::shared_ptr<ast::expr> parse_condition(std::string condition,
|
||||
indexed_vector<falco_list>& lists,
|
||||
const rule_loader::context& ctx) {
|
||||
for(auto& l : lists) {
|
||||
if(resolve_list(condition, l)) {
|
||||
l.used = true;
|
||||
}
|
||||
}
|
||||
libsinsp::filter::parser p(condition);
|
||||
p.set_max_depth(1000);
|
||||
try
|
||||
{
|
||||
try {
|
||||
std::shared_ptr<ast::expr> res_ptr(p.parse());
|
||||
return res_ptr;
|
||||
}
|
||||
catch (const sinsp_exception& e)
|
||||
{
|
||||
} catch(const sinsp_exception& e) {
|
||||
rule_loader::context parsectx(p.get_pos(), condition, ctx);
|
||||
|
||||
throw rule_loader::rule_load_exception(
|
||||
falco::load_result::LOAD_ERR_COMPILE_CONDITION,
|
||||
e.what(),
|
||||
parsectx);
|
||||
throw rule_loader::rule_load_exception(falco::load_result::LOAD_ERR_COMPILE_CONDITION,
|
||||
e.what(),
|
||||
parsectx);
|
||||
}
|
||||
}
|
||||
|
||||
void rule_loader::compiler::compile_list_infos(
|
||||
configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<falco_list>& out) const
|
||||
{
|
||||
void rule_loader::compiler::compile_list_infos(configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<falco_list>& out) const {
|
||||
std::list<std::string> used_names;
|
||||
falco_list infos;
|
||||
for (const auto &list : col.lists())
|
||||
{
|
||||
for(const auto& list : col.lists()) {
|
||||
infos.name = list.name;
|
||||
infos.items.clear();
|
||||
for (const auto &item : list.items)
|
||||
{
|
||||
for(const auto& item : list.items) {
|
||||
const auto ref = col.lists().at(item);
|
||||
if (ref && ref->index < list.visibility)
|
||||
{
|
||||
if(ref && ref->index < list.visibility) {
|
||||
used_names.push_back(ref->name);
|
||||
for (const auto &val : ref->items)
|
||||
{
|
||||
for(const auto& val : ref->items) {
|
||||
infos.items.push_back(val);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
infos.items.push_back(item);
|
||||
}
|
||||
}
|
||||
@@ -354,21 +291,17 @@ void rule_loader::compiler::compile_list_infos(
|
||||
auto list_id = out.insert(infos, infos.name);
|
||||
out.at(list_id)->id = list_id;
|
||||
}
|
||||
for (const auto &name : used_names)
|
||||
{
|
||||
for(const auto& name : used_names) {
|
||||
out.at(name)->used = true;
|
||||
}
|
||||
}
|
||||
|
||||
// note: there is a visibility ordering between macros
|
||||
void rule_loader::compiler::compile_macros_infos(
|
||||
configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<falco_list>& lists,
|
||||
indexed_vector<falco_macro>& out) const
|
||||
{
|
||||
for (const auto &m : col.macros())
|
||||
{
|
||||
void rule_loader::compiler::compile_macros_infos(configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<falco_list>& lists,
|
||||
indexed_vector<falco_macro>& out) const {
|
||||
for(const auto& m : col.macros()) {
|
||||
falco_macro entry;
|
||||
entry.name = m.name;
|
||||
entry.condition = parse_condition(m.cond, lists, m.cond_ctx);
|
||||
@@ -378,44 +311,50 @@ void rule_loader::compiler::compile_macros_infos(
|
||||
}
|
||||
|
||||
filter_macro_resolver macro_resolver;
|
||||
for (auto &m : out)
|
||||
{
|
||||
for(auto& m : out) {
|
||||
const auto* info = macro_info_from_name(col, m.name);
|
||||
resolve_macros(macro_resolver, col.macros(), out, m.condition, info->cond, info->visibility, info->ctx);
|
||||
resolve_macros(macro_resolver,
|
||||
col.macros(),
|
||||
out,
|
||||
m.condition,
|
||||
info->cond,
|
||||
info->visibility,
|
||||
info->ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static bool err_is_unknown_type_or_field(const std::string& err)
|
||||
{
|
||||
return err.find("nonexistent field") != std::string::npos
|
||||
|| err.find("invalid formatting token") != std::string::npos
|
||||
|| err.find("unknown event type") != std::string::npos;
|
||||
static bool err_is_unknown_type_or_field(const std::string& err) {
|
||||
return err.find("nonexistent field") != std::string::npos ||
|
||||
err.find("invalid formatting token") != std::string::npos ||
|
||||
err.find("unknown event type") != std::string::npos;
|
||||
}
|
||||
|
||||
bool rule_loader::compiler::compile_condition(
|
||||
configuration& cfg,
|
||||
filter_macro_resolver& macro_resolver,
|
||||
indexed_vector<falco_list>& lists,
|
||||
const indexed_vector<rule_loader::macro_info>& macros,
|
||||
const std::string& condition,
|
||||
std::shared_ptr<sinsp_filter_factory> filter_factory,
|
||||
const rule_loader::context& cond_ctx,
|
||||
const rule_loader::context& parent_ctx,
|
||||
bool allow_unknown_fields,
|
||||
indexed_vector<falco_macro>& macros_out,
|
||||
std::shared_ptr<libsinsp::filter::ast::expr>& ast_out,
|
||||
std::shared_ptr<sinsp_filter>& filter_out) const
|
||||
{
|
||||
bool rule_loader::compiler::compile_condition(configuration& cfg,
|
||||
filter_macro_resolver& macro_resolver,
|
||||
indexed_vector<falco_list>& lists,
|
||||
const indexed_vector<rule_loader::macro_info>& macros,
|
||||
const std::string& condition,
|
||||
std::shared_ptr<sinsp_filter_factory> filter_factory,
|
||||
const rule_loader::context& cond_ctx,
|
||||
const rule_loader::context& parent_ctx,
|
||||
bool allow_unknown_fields,
|
||||
indexed_vector<falco_macro>& macros_out,
|
||||
std::shared_ptr<libsinsp::filter::ast::expr>& ast_out,
|
||||
std::shared_ptr<sinsp_filter>& filter_out) const {
|
||||
std::set<falco::load_result::load_result::warning_code> warn_codes;
|
||||
filter_warning_resolver warn_resolver;
|
||||
ast_out = parse_condition(condition, lists, cond_ctx);
|
||||
resolve_macros(macro_resolver, macros, macros_out, ast_out, condition, MAX_VISIBILITY, parent_ctx);
|
||||
resolve_macros(macro_resolver,
|
||||
macros,
|
||||
macros_out,
|
||||
ast_out,
|
||||
condition,
|
||||
MAX_VISIBILITY,
|
||||
parent_ctx);
|
||||
|
||||
// check for warnings in the filtering condition
|
||||
if(warn_resolver.run(ast_out.get(), warn_codes))
|
||||
{
|
||||
for(const auto& w : warn_codes)
|
||||
{
|
||||
if(warn_resolver.run(ast_out.get(), warn_codes)) {
|
||||
for(const auto& w : warn_codes) {
|
||||
cfg.res->add_warning(w, "", parent_ctx);
|
||||
}
|
||||
}
|
||||
@@ -423,134 +362,105 @@ bool rule_loader::compiler::compile_condition(
|
||||
// validate the rule's condition: we compile it into a sinsp filter
|
||||
// on-the-fly and we throw an exception with details on failure
|
||||
sinsp_filter_compiler compiler(filter_factory, ast_out.get());
|
||||
try
|
||||
{
|
||||
try {
|
||||
filter_out = compiler.compile();
|
||||
}
|
||||
catch(const sinsp_exception& e)
|
||||
{
|
||||
} catch(const sinsp_exception& e) {
|
||||
// skip the rule silently if skip_if_unknown_filter is true and
|
||||
// we encountered some specific kind of errors
|
||||
std::string err = e.what();
|
||||
rule_loader::context ctx(compiler.get_pos(), condition, cond_ctx);
|
||||
if(err_is_unknown_type_or_field(err) && allow_unknown_fields)
|
||||
{
|
||||
cfg.res->add_warning(
|
||||
falco::load_result::load_result::LOAD_UNKNOWN_FILTER,
|
||||
err,
|
||||
ctx);
|
||||
if(err_is_unknown_type_or_field(err) && allow_unknown_fields) {
|
||||
cfg.res->add_warning(falco::load_result::load_result::LOAD_UNKNOWN_FILTER, err, ctx);
|
||||
return false;
|
||||
}
|
||||
throw rule_loader::rule_load_exception(
|
||||
falco::load_result::load_result::LOAD_ERR_COMPILE_CONDITION,
|
||||
err,
|
||||
ctx);
|
||||
falco::load_result::load_result::LOAD_ERR_COMPILE_CONDITION,
|
||||
err,
|
||||
ctx);
|
||||
}
|
||||
for (const auto &w : compiler.get_warnings())
|
||||
{
|
||||
for(const auto& w : compiler.get_warnings()) {
|
||||
rule_loader::context ctx(w.pos, condition, cond_ctx);
|
||||
cfg.res->add_warning(
|
||||
falco::load_result::load_result::LOAD_COMPILE_CONDITION,
|
||||
w.msg,
|
||||
ctx);
|
||||
cfg.res->add_warning(falco::load_result::load_result::LOAD_COMPILE_CONDITION, w.msg, ctx);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void rule_loader::compiler::compile_rule_infos(
|
||||
configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<falco_list>& lists,
|
||||
indexed_vector<falco_macro>& macros,
|
||||
indexed_vector<falco_rule>& out) const
|
||||
{
|
||||
void rule_loader::compiler::compile_rule_infos(configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<falco_list>& lists,
|
||||
indexed_vector<falco_macro>& macros,
|
||||
indexed_vector<falco_rule>& out) const {
|
||||
std::string err, condition;
|
||||
filter_macro_resolver macro_resolver;
|
||||
for(const auto& r : col.rules())
|
||||
{
|
||||
for(const auto& r : col.rules()) {
|
||||
// skip the rule if it has an unknown source
|
||||
if (r.unknown_source)
|
||||
{
|
||||
if(r.unknown_source) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// note: this should not be nullptr if the source is not unknown
|
||||
auto source = cfg.sources.at(r.source);
|
||||
THROW(!source,
|
||||
std::string("Unknown source at compile-time") + r.source,
|
||||
r.ctx);
|
||||
THROW(!source, std::string("Unknown source at compile-time") + r.source, r.ctx);
|
||||
|
||||
// build filter AST by parsing the condition, building exceptions,
|
||||
// and resolving lists and macros
|
||||
falco_rule rule;
|
||||
|
||||
condition = r.cond;
|
||||
if (!r.exceptions.empty())
|
||||
{
|
||||
build_rule_exception_infos(
|
||||
r.exceptions, rule.exception_fields, condition);
|
||||
if(!r.exceptions.empty()) {
|
||||
build_rule_exception_infos(r.exceptions, rule.exception_fields, condition);
|
||||
}
|
||||
|
||||
// build rule output message
|
||||
rule.output = r.output;
|
||||
|
||||
for (auto& extra : cfg.extra_output_format)
|
||||
{
|
||||
if (extra.m_source != "" && r.source != extra.m_source)
|
||||
{
|
||||
for(auto& extra : cfg.extra_output_format) {
|
||||
if(extra.m_source != "" && r.source != extra.m_source) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!std::includes(r.tags.begin(), r.tags.end(),
|
||||
extra.m_tags.begin(), extra.m_tags.end()))
|
||||
{
|
||||
if(!std::includes(r.tags.begin(),
|
||||
r.tags.end(),
|
||||
extra.m_tags.begin(),
|
||||
extra.m_tags.end())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (extra.m_rule != "" && r.name != extra.m_rule)
|
||||
{
|
||||
if(extra.m_rule != "" && r.name != extra.m_rule) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (extra.m_replace_container_info)
|
||||
{
|
||||
if (rule.output.find(s_container_info_fmt) != std::string::npos)
|
||||
{
|
||||
if(extra.m_replace_container_info) {
|
||||
if(rule.output.find(s_container_info_fmt) != std::string::npos) {
|
||||
rule.output = replace(rule.output, s_container_info_fmt, extra.m_format);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
rule.output = rule.output + " " + extra.m_format;
|
||||
}
|
||||
} else
|
||||
{
|
||||
} else {
|
||||
rule.output = rule.output + " " + extra.m_format;
|
||||
}
|
||||
}
|
||||
|
||||
if (rule.output.find(s_container_info_fmt) != std::string::npos)
|
||||
{
|
||||
if(rule.output.find(s_container_info_fmt) != std::string::npos) {
|
||||
rule.output = replace(rule.output, s_container_info_fmt, s_default_extra_fmt);
|
||||
}
|
||||
|
||||
// build extra output fields if required
|
||||
|
||||
for (auto const& extra : cfg.extra_output_fields)
|
||||
{
|
||||
if (extra.m_source != "" && r.source != extra.m_source)
|
||||
{
|
||||
for(auto const& extra : cfg.extra_output_fields) {
|
||||
if(extra.m_source != "" && r.source != extra.m_source) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!std::includes(r.tags.begin(), r.tags.end(),
|
||||
extra.m_tags.begin(), extra.m_tags.end()))
|
||||
{
|
||||
if(!std::includes(r.tags.begin(),
|
||||
r.tags.end(),
|
||||
extra.m_tags.begin(),
|
||||
extra.m_tags.end())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (extra.m_rule != "" && r.name != extra.m_rule)
|
||||
{
|
||||
if(extra.m_rule != "" && r.name != extra.m_rule) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -558,62 +468,52 @@ void rule_loader::compiler::compile_rule_infos(
|
||||
}
|
||||
|
||||
// validate the rule's output
|
||||
if(!is_format_valid(*cfg.sources.at(r.source), rule.output, err))
|
||||
{
|
||||
if(!is_format_valid(*cfg.sources.at(r.source), rule.output, err)) {
|
||||
// skip the rule silently if skip_if_unknown_filter is true and
|
||||
// we encountered some specific kind of errors
|
||||
if (err_is_unknown_type_or_field(err) && r.skip_if_unknown_filter)
|
||||
{
|
||||
cfg.res->add_warning(
|
||||
falco::load_result::load_result::LOAD_UNKNOWN_FILTER,
|
||||
err,
|
||||
r.output_ctx);
|
||||
if(err_is_unknown_type_or_field(err) && r.skip_if_unknown_filter) {
|
||||
cfg.res->add_warning(falco::load_result::load_result::LOAD_UNKNOWN_FILTER,
|
||||
err,
|
||||
r.output_ctx);
|
||||
continue;
|
||||
}
|
||||
throw rule_load_exception(
|
||||
falco::load_result::load_result::LOAD_ERR_COMPILE_OUTPUT,
|
||||
err,
|
||||
r.output_ctx);
|
||||
throw rule_load_exception(falco::load_result::load_result::LOAD_ERR_COMPILE_OUTPUT,
|
||||
err,
|
||||
r.output_ctx);
|
||||
}
|
||||
|
||||
// validate the rule's extra fields if any
|
||||
for (auto const& ef : rule.extra_output_fields)
|
||||
{
|
||||
if(!is_format_valid(*cfg.sources.at(r.source), ef.second.first, err))
|
||||
{
|
||||
throw rule_load_exception(
|
||||
falco::load_result::load_result::LOAD_ERR_COMPILE_OUTPUT,
|
||||
err,
|
||||
r.output_ctx);
|
||||
for(auto const& ef : rule.extra_output_fields) {
|
||||
if(!is_format_valid(*cfg.sources.at(r.source), ef.second.first, err)) {
|
||||
throw rule_load_exception(falco::load_result::load_result::LOAD_ERR_COMPILE_OUTPUT,
|
||||
err,
|
||||
r.output_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
if (!compile_condition(cfg,
|
||||
macro_resolver,
|
||||
lists,
|
||||
col.macros(),
|
||||
condition,
|
||||
cfg.sources.at(r.source)->filter_factory,
|
||||
r.cond_ctx,
|
||||
r.ctx,
|
||||
r.skip_if_unknown_filter,
|
||||
macros,
|
||||
rule.condition,
|
||||
rule.filter))
|
||||
{
|
||||
if(!compile_condition(cfg,
|
||||
macro_resolver,
|
||||
lists,
|
||||
col.macros(),
|
||||
condition,
|
||||
cfg.sources.at(r.source)->filter_factory,
|
||||
r.cond_ctx,
|
||||
r.ctx,
|
||||
r.skip_if_unknown_filter,
|
||||
macros,
|
||||
rule.condition,
|
||||
rule.filter)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// populate set of event types and emit an special warning
|
||||
if(r.source == falco_common::syscall_source)
|
||||
{
|
||||
if(r.source == falco_common::syscall_source) {
|
||||
auto evttypes = libsinsp::filter::ast::ppm_event_codes(rule.condition.get());
|
||||
if ((evttypes.empty() || evttypes.size() > 100) && r.warn_evttypes)
|
||||
{
|
||||
cfg.res->add_warning(
|
||||
falco::load_result::load_result::LOAD_NO_EVTTYPE,
|
||||
"Rule matches too many evt.type values. This has a significant performance penalty.",
|
||||
r.ctx);
|
||||
if((evttypes.empty() || evttypes.size() > 100) && r.warn_evttypes) {
|
||||
cfg.res->add_warning(falco::load_result::load_result::LOAD_NO_EVTTYPE,
|
||||
"Rule matches too many evt.type values. This has a "
|
||||
"significant performance penalty.",
|
||||
r.ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -628,48 +528,36 @@ void rule_loader::compiler::compile_rule_infos(
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<rule_loader::compile_output> rule_loader::compiler::new_compile_output()
|
||||
{
|
||||
std::unique_ptr<rule_loader::compile_output> rule_loader::compiler::new_compile_output() {
|
||||
return std::make_unique<compile_output>();
|
||||
}
|
||||
|
||||
void rule_loader::compiler::compile(
|
||||
configuration& cfg,
|
||||
const collector& col,
|
||||
compile_output& out) const
|
||||
{
|
||||
void rule_loader::compiler::compile(configuration& cfg,
|
||||
const collector& col,
|
||||
compile_output& out) const {
|
||||
// expand all lists, macros, and rules
|
||||
try
|
||||
{
|
||||
try {
|
||||
compile_list_infos(cfg, col, out.lists);
|
||||
compile_macros_infos(cfg, col, out.lists, out.macros);
|
||||
compile_rule_infos(cfg, col, out.lists, out.macros, out.rules);
|
||||
}
|
||||
catch(rule_load_exception &e)
|
||||
{
|
||||
} catch(rule_load_exception& e) {
|
||||
cfg.res->add_error(e.ec, e.msg, e.ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
// print info on any dangling lists or macros that were not used anywhere
|
||||
for (const auto &m : out.macros)
|
||||
{
|
||||
if (!m.used)
|
||||
{
|
||||
cfg.res->add_warning(
|
||||
falco::load_result::load_result::LOAD_UNUSED_MACRO,
|
||||
"Macro not referred to by any other rule/macro",
|
||||
macro_info_from_name(col, m.name)->ctx);
|
||||
for(const auto& m : out.macros) {
|
||||
if(!m.used) {
|
||||
cfg.res->add_warning(falco::load_result::load_result::LOAD_UNUSED_MACRO,
|
||||
"Macro not referred to by any other rule/macro",
|
||||
macro_info_from_name(col, m.name)->ctx);
|
||||
}
|
||||
}
|
||||
for (const auto &l : out.lists)
|
||||
{
|
||||
if (!l.used)
|
||||
{
|
||||
cfg.res->add_warning(
|
||||
falco::load_result::LOAD_UNUSED_LIST,
|
||||
"List not referred to by any other rule/macro",
|
||||
list_info_from_name(col, l.name)->ctx);
|
||||
for(const auto& l : out.lists) {
|
||||
if(!l.used) {
|
||||
cfg.res->add_warning(falco::load_result::LOAD_UNUSED_LIST,
|
||||
"List not referred to by any other rule/macro",
|
||||
list_info_from_name(col, l.name)->ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,75 +24,66 @@ limitations under the License.
|
||||
#include "indexed_vector.h"
|
||||
#include "falco_rule.h"
|
||||
|
||||
namespace rule_loader
|
||||
{
|
||||
namespace rule_loader {
|
||||
|
||||
/*!
|
||||
\brief Compiler for the ruleset loader of the falco engine
|
||||
\brief Compiler for the ruleset loader of the falco engine
|
||||
*/
|
||||
class compiler
|
||||
{
|
||||
class compiler {
|
||||
public:
|
||||
compiler() = default;
|
||||
virtual ~compiler() = default;
|
||||
compiler(compiler&&) = default;
|
||||
compiler& operator = (compiler&&) = default;
|
||||
compiler& operator=(compiler&&) = default;
|
||||
compiler(const compiler&) = default;
|
||||
compiler& operator = (const compiler&) = default;
|
||||
compiler& operator=(const compiler&) = default;
|
||||
|
||||
// Return a new result object, suitable for passing to
|
||||
// compile().
|
||||
virtual std::unique_ptr<compile_output> new_compile_output();
|
||||
virtual std::unique_ptr<compile_output> new_compile_output();
|
||||
|
||||
/*!
|
||||
\brief Compiles a list of falco rules
|
||||
\brief Compiles a list of falco rules
|
||||
*/
|
||||
virtual void compile(
|
||||
configuration& cfg,
|
||||
const collector& col,
|
||||
compile_output& out) const;
|
||||
protected:
|
||||
/*!
|
||||
\brief Compile a single condition expression,
|
||||
including expanding macro and list references.
|
||||
virtual void compile(configuration& cfg, const collector& col, compile_output& out) const;
|
||||
|
||||
returns true if the condition could be compiled, and sets
|
||||
ast_out/filter_out with the compiled filter + ast. Returns false if
|
||||
the condition could not be compiled and should be skipped.
|
||||
*/
|
||||
bool compile_condition(
|
||||
configuration& cfg,
|
||||
filter_macro_resolver& macro_resolver,
|
||||
indexed_vector<falco_list>& lists,
|
||||
const indexed_vector<rule_loader::macro_info>& macros,
|
||||
const std::string& condition,
|
||||
std::shared_ptr<sinsp_filter_factory> filter_factory,
|
||||
const rule_loader::context& cond_ctx,
|
||||
const rule_loader::context& parent_ctx,
|
||||
bool allow_unknown_fields,
|
||||
indexed_vector<falco_macro>& macros_out,
|
||||
std::shared_ptr<libsinsp::filter::ast::expr>& ast_out,
|
||||
std::shared_ptr<sinsp_filter>& filter_out) const;
|
||||
protected:
|
||||
/*!
|
||||
\brief Compile a single condition expression,
|
||||
including expanding macro and list references.
|
||||
|
||||
returns true if the condition could be compiled, and sets
|
||||
ast_out/filter_out with the compiled filter + ast. Returns false if
|
||||
the condition could not be compiled and should be skipped.
|
||||
*/
|
||||
bool compile_condition(configuration& cfg,
|
||||
filter_macro_resolver& macro_resolver,
|
||||
indexed_vector<falco_list>& lists,
|
||||
const indexed_vector<rule_loader::macro_info>& macros,
|
||||
const std::string& condition,
|
||||
std::shared_ptr<sinsp_filter_factory> filter_factory,
|
||||
const rule_loader::context& cond_ctx,
|
||||
const rule_loader::context& parent_ctx,
|
||||
bool allow_unknown_fields,
|
||||
indexed_vector<falco_macro>& macros_out,
|
||||
std::shared_ptr<libsinsp::filter::ast::expr>& ast_out,
|
||||
std::shared_ptr<sinsp_filter>& filter_out) const;
|
||||
|
||||
private:
|
||||
void compile_list_infos(
|
||||
configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<falco_list>& out) const;
|
||||
void compile_list_infos(configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<falco_list>& out) const;
|
||||
|
||||
void compile_macros_infos(
|
||||
configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<falco_list>& lists,
|
||||
indexed_vector<falco_macro>& out) const;
|
||||
void compile_macros_infos(configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<falco_list>& lists,
|
||||
indexed_vector<falco_macro>& out) const;
|
||||
|
||||
void compile_rule_infos(
|
||||
configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<falco_list>& lists,
|
||||
indexed_vector<falco_macro>& macros,
|
||||
indexed_vector<falco_rule>& out) const;
|
||||
void compile_rule_infos(configuration& cfg,
|
||||
const collector& col,
|
||||
indexed_vector<falco_list>& lists,
|
||||
indexed_vector<falco_macro>& macros,
|
||||
indexed_vector<falco_rule>& out) const;
|
||||
};
|
||||
|
||||
}; // namespace rule_loader
|
||||
|
||||
}; // namespace rule_loader
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,53 +23,55 @@ limitations under the License.
|
||||
#include <libsinsp/version.h>
|
||||
#include "falco_engine_version.h"
|
||||
|
||||
namespace rule_loader
|
||||
{
|
||||
namespace rule_loader {
|
||||
|
||||
/*!
|
||||
\brief Reads the contents of a ruleset
|
||||
*/
|
||||
class reader
|
||||
{
|
||||
class reader {
|
||||
public:
|
||||
reader() = default;
|
||||
virtual ~reader() = default;
|
||||
reader(reader&&) = default;
|
||||
reader& operator = (reader&&) = default;
|
||||
reader() = default;
|
||||
virtual ~reader() = default;
|
||||
reader(reader&&) = default;
|
||||
reader& operator=(reader&&) = default;
|
||||
reader(const reader&) = default;
|
||||
reader& operator = (const reader&) = default;
|
||||
reader& operator=(const reader&) = default;
|
||||
|
||||
/*!
|
||||
\brief Reads the contents of a ruleset and uses a collector to store
|
||||
thew new definitions
|
||||
/*!
|
||||
\brief Reads the contents of a ruleset and uses a collector to store
|
||||
thew new definitions
|
||||
*/
|
||||
virtual bool read(configuration& cfg, collector& loader, const nlohmann::json& schema={});
|
||||
|
||||
/*!
|
||||
\brief Engine version used to be represented as a simple progressive
|
||||
virtual bool read(configuration& cfg, collector& loader, const nlohmann::json& schema = {});
|
||||
|
||||
/*!
|
||||
\brief Engine version used to be represented as a simple progressive
|
||||
number. With the new semver schema, the number now represents
|
||||
the semver minor number. This function converts the legacy version
|
||||
the semver minor number. This function converts the legacy version
|
||||
number to the new semver schema.
|
||||
*/
|
||||
static inline sinsp_version get_implicit_engine_version(uint32_t minor)
|
||||
{
|
||||
return sinsp_version(std::to_string(FALCO_ENGINE_VERSION_MAJOR) + "."
|
||||
+ std::to_string(minor) + "."
|
||||
+ std::to_string(FALCO_ENGINE_VERSION_PATCH));
|
||||
*/
|
||||
static inline sinsp_version get_implicit_engine_version(uint32_t minor) {
|
||||
return sinsp_version(std::to_string(FALCO_ENGINE_VERSION_MAJOR) + "." +
|
||||
std::to_string(minor) + "." +
|
||||
std::to_string(FALCO_ENGINE_VERSION_PATCH));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void decode_val(const YAML::Node& item, const char *key, T& out, const rule_loader::context& ctx);
|
||||
template<typename T>
|
||||
static void decode_val(const YAML::Node& item,
|
||||
const char* key,
|
||||
T& out,
|
||||
const rule_loader::context& ctx);
|
||||
|
||||
template <typename T>
|
||||
static void decode_optional_val(const YAML::Node& item, const char *key, T& out, const rule_loader::context& ctx);
|
||||
template<typename T>
|
||||
static void decode_optional_val(const YAML::Node& item,
|
||||
const char* key,
|
||||
T& out,
|
||||
const rule_loader::context& ctx);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void read_item(rule_loader::configuration& cfg,
|
||||
rule_loader::collector& collector,
|
||||
const YAML::Node& item,
|
||||
const rule_loader::context& parent);
|
||||
rule_loader::collector& collector,
|
||||
const YAML::Node& item,
|
||||
const rule_loader::context& parent);
|
||||
};
|
||||
|
||||
}; // namespace rule_loader
|
||||
}; // namespace rule_loader
|
||||
|
||||
@@ -4,20 +4,30 @@
|
||||
// Warnings
|
||||
////////////////
|
||||
|
||||
#define WARNING_APPEND "'append' key is deprecated. Add an 'append' entry (e.g. 'condition: append') under 'override' instead."
|
||||
#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')."
|
||||
#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_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_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_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_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"
|
||||
#define ERROR_NO_PREVIOUS_RULE_REPLACE \
|
||||
"An 'override.<key>: replace' to a rule was requested but no rule by that name already exists"
|
||||
|
||||
@@ -18,72 +18,53 @@ limitations under the License.
|
||||
#include "stats_manager.h"
|
||||
#include "falco_common.h"
|
||||
|
||||
stats_manager::stats_manager()
|
||||
: m_total(0)
|
||||
{
|
||||
}
|
||||
stats_manager::stats_manager(): m_total(0) {}
|
||||
|
||||
stats_manager::~stats_manager()
|
||||
{
|
||||
stats_manager::~stats_manager() {
|
||||
clear();
|
||||
}
|
||||
|
||||
void stats_manager::clear()
|
||||
{
|
||||
void stats_manager::clear() {
|
||||
m_total = 0;
|
||||
m_by_rule_id.clear();
|
||||
m_by_priority.clear();
|
||||
}
|
||||
|
||||
void stats_manager::format(
|
||||
const indexed_vector<falco_rule>& rules,
|
||||
std::string& out) const
|
||||
{
|
||||
void stats_manager::format(const indexed_vector<falco_rule>& rules, std::string& out) const {
|
||||
std::string fmt;
|
||||
out = "Events detected: " + to_string(m_total) + "\n";
|
||||
out += "Rule counts by severity:\n";
|
||||
for (size_t i = 0; i < m_by_priority.size(); i++)
|
||||
{
|
||||
for(size_t i = 0; i < m_by_priority.size(); i++) {
|
||||
auto val = m_by_priority[i]->load();
|
||||
if (val > 0)
|
||||
{
|
||||
falco_common::format_priority(
|
||||
(falco_common::priority_type) i, fmt, true);
|
||||
if(val > 0) {
|
||||
falco_common::format_priority((falco_common::priority_type)i, fmt, true);
|
||||
transform(fmt.begin(), fmt.end(), fmt.begin(), ::toupper);
|
||||
out += " " + fmt + ": " + std::to_string(val) + "\n";
|
||||
}
|
||||
}
|
||||
out += "Triggered rules by rule name:\n";
|
||||
for (size_t i = 0; i < m_by_rule_id.size(); i++)
|
||||
{
|
||||
for(size_t i = 0; i < m_by_rule_id.size(); i++) {
|
||||
auto val = m_by_rule_id[i]->load();
|
||||
if (val > 0)
|
||||
{
|
||||
if(val > 0) {
|
||||
out += " " + rules.at(i)->name + ": " + std::to_string(val) + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void stats_manager::on_rule_loaded(const falco_rule& rule)
|
||||
{
|
||||
while (m_by_rule_id.size() <= rule.id)
|
||||
{
|
||||
void stats_manager::on_rule_loaded(const falco_rule& rule) {
|
||||
while(m_by_rule_id.size() <= rule.id) {
|
||||
m_by_rule_id.emplace_back(std::make_unique<std::atomic<uint64_t>>(0));
|
||||
}
|
||||
while (m_by_priority.size() <= (size_t) rule.priority)
|
||||
{
|
||||
while(m_by_priority.size() <= (size_t)rule.priority) {
|
||||
m_by_priority.emplace_back(std::make_unique<std::atomic<uint64_t>>(0));
|
||||
}
|
||||
}
|
||||
|
||||
void stats_manager::on_event(const falco_rule& rule)
|
||||
{
|
||||
if (m_by_rule_id.size() <= rule.id
|
||||
|| m_by_priority.size() <= (size_t) rule.priority)
|
||||
{
|
||||
void stats_manager::on_event(const falco_rule& rule) {
|
||||
if(m_by_rule_id.size() <= rule.id || m_by_priority.size() <= (size_t)rule.priority) {
|
||||
throw falco_exception("rule id or priority out of bounds");
|
||||
}
|
||||
m_total.fetch_add(1, std::memory_order_relaxed);
|
||||
m_by_rule_id[rule.id]->fetch_add(1, std::memory_order_relaxed);
|
||||
m_by_priority[(size_t) rule.priority]->fetch_add(1, std::memory_order_relaxed);
|
||||
m_by_priority[(size_t)rule.priority]->fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
@@ -25,61 +25,52 @@ limitations under the License.
|
||||
#include "indexed_vector.h"
|
||||
|
||||
/*!
|
||||
\brief Manager for the internal statistics of the rule engine.
|
||||
The on_event() is thread-safe and non-blocking, and it can be used
|
||||
concurrently across many callers in parallel.
|
||||
All the other methods are not thread safe.
|
||||
\brief Manager for the internal statistics of the rule engine.
|
||||
The on_event() is thread-safe and non-blocking, and it can be used
|
||||
concurrently across many callers in parallel.
|
||||
All the other methods are not thread safe.
|
||||
*/
|
||||
class stats_manager
|
||||
{
|
||||
class stats_manager {
|
||||
public:
|
||||
stats_manager();
|
||||
virtual ~stats_manager();
|
||||
|
||||
/*!
|
||||
\brief Erases the internal state and statistics data
|
||||
\brief Erases the internal state and statistics data
|
||||
*/
|
||||
virtual void clear();
|
||||
|
||||
/*!
|
||||
\brief Callback for when a new rule is loaded in the engine.
|
||||
Rules must be passed through this method before submitting them as
|
||||
an argument of on_event().
|
||||
\brief Callback for when a new rule is loaded in the engine.
|
||||
Rules must be passed through this method before submitting them as
|
||||
an argument of on_event().
|
||||
*/
|
||||
virtual void on_rule_loaded(const falco_rule& rule);
|
||||
|
||||
/*!
|
||||
\brief Callback for when a given rule matches an event.
|
||||
This method is thread-safe.
|
||||
\throws falco_exception if rule has not been passed to
|
||||
on_rule_loaded() first
|
||||
\brief Callback for when a given rule matches an event.
|
||||
This method is thread-safe.
|
||||
\throws falco_exception if rule has not been passed to
|
||||
on_rule_loaded() first
|
||||
*/
|
||||
virtual void on_event(const falco_rule& rule);
|
||||
|
||||
/*!
|
||||
\brief Formats the internal statistics into the out string.
|
||||
\brief Formats the internal statistics into the out string.
|
||||
*/
|
||||
virtual void format(
|
||||
const indexed_vector<falco_rule>& rules,
|
||||
std::string& out) const;
|
||||
virtual void format(const indexed_vector<falco_rule>& rules, std::string& out) const;
|
||||
|
||||
// Getter functions
|
||||
inline const std::atomic<uint64_t>& get_total() const
|
||||
{
|
||||
return m_total;
|
||||
}
|
||||
inline const std::atomic<uint64_t>& get_total() const { return m_total; }
|
||||
|
||||
inline const std::vector<std::unique_ptr<std::atomic<uint64_t>>>& get_by_priority() const
|
||||
{
|
||||
inline const std::vector<std::unique_ptr<std::atomic<uint64_t>>>& get_by_priority() const {
|
||||
return m_by_priority;
|
||||
}
|
||||
|
||||
inline const std::vector<std::unique_ptr<std::atomic<uint64_t>>>& get_by_rule_id() const
|
||||
{
|
||||
inline const std::vector<std::unique_ptr<std::atomic<uint64_t>>>& get_by_rule_id() const {
|
||||
return m_by_rule_id;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::atomic<uint64_t> m_total;
|
||||
std::vector<std::unique_ptr<std::atomic<uint64_t>>> m_by_priority;
|
||||
|
||||
@@ -48,23 +48,23 @@ private:
|
||||
using Callback = std::function<void(YAML::Node&)>;
|
||||
explicit yaml_visitor(Callback cb): seen(), cb(std::move(cb)) {}
|
||||
|
||||
void operator()(YAML::Node &cur) {
|
||||
void operator()(YAML::Node& cur) {
|
||||
seen.push_back(cur);
|
||||
if (cur.IsMap()) {
|
||||
for (YAML::detail::iterator_value pair : cur) {
|
||||
if(cur.IsMap()) {
|
||||
for(YAML::detail::iterator_value pair : cur) {
|
||||
descend(pair.second);
|
||||
}
|
||||
} else if (cur.IsSequence()) {
|
||||
for (YAML::detail::iterator_value child : cur) {
|
||||
} else if(cur.IsSequence()) {
|
||||
for(YAML::detail::iterator_value child : cur) {
|
||||
descend(child);
|
||||
}
|
||||
} else if (cur.IsScalar()) {
|
||||
} else if(cur.IsScalar()) {
|
||||
cb(cur);
|
||||
}
|
||||
}
|
||||
|
||||
void descend(YAML::Node &target) {
|
||||
if (std::find(seen.begin(), seen.end(), target) == seen.end()) {
|
||||
void descend(YAML::Node& target) {
|
||||
if(std::find(seen.begin(), seen.end(), target) == seen.end()) {
|
||||
(*this)(target);
|
||||
}
|
||||
}
|
||||
@@ -78,8 +78,7 @@ private:
|
||||
/**
|
||||
* @brief An helper class for reading and editing YAML documents
|
||||
*/
|
||||
class yaml_helper
|
||||
{
|
||||
class yaml_helper {
|
||||
public:
|
||||
inline static const std::string configs_key = "config_files";
|
||||
inline static const std::string validation_ok = "ok";
|
||||
@@ -87,25 +86,22 @@ public:
|
||||
inline static const std::string validation_none = "none";
|
||||
|
||||
/**
|
||||
* Load all the YAML document represented by the input string.
|
||||
* Since this is used by rule loader, does not process env vars.
|
||||
*/
|
||||
std::vector<YAML::Node> loadall_from_string(const std::string& input, const nlohmann::json& schema={}, std::vector<std::string> *schema_warnings=nullptr)
|
||||
{
|
||||
* Load all the YAML document represented by the input string.
|
||||
* Since this is used by rule loader, does not process env vars.
|
||||
*/
|
||||
std::vector<YAML::Node> loadall_from_string(
|
||||
const std::string& input,
|
||||
const nlohmann::json& schema = {},
|
||||
std::vector<std::string>* schema_warnings = nullptr) {
|
||||
auto nodes = YAML::LoadAll(input);
|
||||
if (schema_warnings)
|
||||
{
|
||||
if(schema_warnings) {
|
||||
schema_warnings->clear();
|
||||
if(!schema.empty())
|
||||
{
|
||||
if(!schema.empty()) {
|
||||
// Validate each node.
|
||||
for(const auto& node : nodes)
|
||||
{
|
||||
for(const auto& node : nodes) {
|
||||
validate_node(node, schema, schema_warnings);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
schema_warnings->push_back(validation_none);
|
||||
}
|
||||
}
|
||||
@@ -113,50 +109,48 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the YAML document represented by the input string.
|
||||
*/
|
||||
void load_from_string(const std::string& input, const nlohmann::json& schema={}, std::vector<std::string> *schema_warnings=nullptr)
|
||||
{
|
||||
* Load the YAML document represented by the input string.
|
||||
*/
|
||||
void load_from_string(const std::string& input,
|
||||
const nlohmann::json& schema = {},
|
||||
std::vector<std::string>* schema_warnings = nullptr) {
|
||||
m_root = YAML::Load(input);
|
||||
pre_process_env_vars(m_root);
|
||||
|
||||
if (schema_warnings)
|
||||
{
|
||||
if(schema_warnings) {
|
||||
schema_warnings->clear();
|
||||
if(!schema.empty())
|
||||
{
|
||||
if(!schema.empty()) {
|
||||
validate_node(m_root, schema, schema_warnings);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
schema_warnings->push_back(validation_none);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the YAML document from the given file path.
|
||||
*/
|
||||
void load_from_file(const std::string& path, const nlohmann::json& schema={}, std::vector<std::string> *schema_warnings=nullptr)
|
||||
{
|
||||
* Load the YAML document from the given file path.
|
||||
*/
|
||||
void load_from_file(const std::string& path,
|
||||
const nlohmann::json& schema = {},
|
||||
std::vector<std::string>* schema_warnings = nullptr) {
|
||||
m_root = load_from_file_int(path, schema, schema_warnings);
|
||||
}
|
||||
|
||||
void include_config_file(const std::string& include_file_path, const nlohmann::json& schema={}, std::vector<std::string> *schema_warnings=nullptr)
|
||||
{
|
||||
void include_config_file(const std::string& include_file_path,
|
||||
const nlohmann::json& schema = {},
|
||||
std::vector<std::string>* schema_warnings = nullptr) {
|
||||
auto loaded_nodes = load_from_file_int(include_file_path, schema, schema_warnings);
|
||||
for(auto n : loaded_nodes)
|
||||
{
|
||||
for(auto n : loaded_nodes) {
|
||||
/*
|
||||
* To avoid recursion hell,
|
||||
* we don't support `config_files` directives from included config files
|
||||
* (that use load_from_file_int recursively).
|
||||
*/
|
||||
const auto &key = n.first.Scalar();
|
||||
if (key == configs_key)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"Config error: '" + configs_key + "' directive in included config file " + include_file_path + ".");
|
||||
const auto& key = n.first.Scalar();
|
||||
if(key == configs_key) {
|
||||
throw std::runtime_error("Config error: '" + configs_key +
|
||||
"' directive in included config file " +
|
||||
include_file_path + ".");
|
||||
}
|
||||
// We allow to override keys.
|
||||
// We don't need to use `get_node()` here,
|
||||
@@ -168,21 +162,16 @@ public:
|
||||
/**
|
||||
* Clears the internal loaded document.
|
||||
*/
|
||||
void clear()
|
||||
{
|
||||
m_root = YAML::Node();
|
||||
}
|
||||
void clear() { m_root = YAML::Node(); }
|
||||
|
||||
/**
|
||||
* Get a scalar value from the node identified by key.
|
||||
*/
|
||||
* Get a scalar value from the node identified by key.
|
||||
*/
|
||||
template<typename T>
|
||||
const T get_scalar(const std::string& key, const T& default_value) const
|
||||
{
|
||||
const T get_scalar(const std::string& key, const T& default_value) const {
|
||||
YAML::Node node;
|
||||
get_node(node, key);
|
||||
if(node.IsDefined())
|
||||
{
|
||||
if(node.IsDefined()) {
|
||||
return node.as<T>(default_value);
|
||||
}
|
||||
return default_value;
|
||||
@@ -192,8 +181,7 @@ public:
|
||||
* Set the node identified by key to value.
|
||||
*/
|
||||
template<typename T>
|
||||
void set_scalar(const std::string& key, const T& value)
|
||||
{
|
||||
void set_scalar(const std::string& key, const T& value) {
|
||||
YAML::Node node;
|
||||
get_node(node, key, true);
|
||||
node = value;
|
||||
@@ -202,66 +190,60 @@ public:
|
||||
/**
|
||||
* Set the node identified by key to an object value
|
||||
*/
|
||||
void set_object(const std::string& key, const YAML::Node& value)
|
||||
{
|
||||
void set_object(const std::string& key, const YAML::Node& value) {
|
||||
YAML::Node node;
|
||||
get_node(node, key, true);
|
||||
node = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sequence value from the node identified by key.
|
||||
*/
|
||||
* Get the sequence value from the node identified by key.
|
||||
*/
|
||||
template<typename T>
|
||||
void get_sequence(T& ret, const std::string& key) const
|
||||
{
|
||||
void get_sequence(T& ret, const std::string& key) const {
|
||||
YAML::Node node;
|
||||
get_node(node, key);
|
||||
return get_sequence_from_node<T>(ret, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the node identified by key is defined.
|
||||
*/
|
||||
bool is_defined(const std::string& key) const
|
||||
{
|
||||
* Return true if the node identified by key is defined.
|
||||
*/
|
||||
bool is_defined(const std::string& key) const {
|
||||
YAML::Node node;
|
||||
get_node(node, key);
|
||||
return node.IsDefined();
|
||||
}
|
||||
|
||||
std::string dump() const
|
||||
{
|
||||
std::string dump() const {
|
||||
YAML::Emitter emitter;
|
||||
emitter << YAML::DoubleQuoted << YAML::Flow << YAML::LowerNull << YAML::BeginSeq << m_root;
|
||||
return emitter.c_str() + 1; // drop initial '[' char
|
||||
return emitter.c_str() + 1; // drop initial '[' char
|
||||
}
|
||||
|
||||
private:
|
||||
YAML::Node m_root;
|
||||
|
||||
YAML::Node load_from_file_int(const std::string& path, const nlohmann::json& schema, std::vector<std::string> *schema_warnings)
|
||||
{
|
||||
YAML::Node load_from_file_int(const std::string& path,
|
||||
const nlohmann::json& schema,
|
||||
std::vector<std::string>* schema_warnings) {
|
||||
auto root = YAML::LoadFile(path);
|
||||
pre_process_env_vars(root);
|
||||
|
||||
if (schema_warnings)
|
||||
{
|
||||
if(schema_warnings) {
|
||||
schema_warnings->clear();
|
||||
if(!schema.empty())
|
||||
{
|
||||
if(!schema.empty()) {
|
||||
validate_node(root, schema, schema_warnings);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
schema_warnings->push_back(validation_none);
|
||||
}
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
void validate_node(const YAML::Node &node, const nlohmann::json& schema, std::vector<std::string> *schema_warnings)
|
||||
{
|
||||
void validate_node(const YAML::Node& node,
|
||||
const nlohmann::json& schema,
|
||||
std::vector<std::string>* schema_warnings) {
|
||||
// Validate the yaml against our json schema
|
||||
valijson::Schema schemaDef;
|
||||
valijson::SchemaParser schemaParser;
|
||||
@@ -271,20 +253,17 @@ private:
|
||||
valijson::adapters::NlohmannJsonAdapter schemaAdapter(schema);
|
||||
schemaParser.populateSchema(schemaAdapter, schemaDef);
|
||||
|
||||
if (!validator.validate(schemaDef, configAdapter, &validationResults))
|
||||
{
|
||||
if(!validator.validate(schemaDef, configAdapter, &validationResults)) {
|
||||
valijson::ValidationResults::Error error;
|
||||
// report only the top-most error
|
||||
while (validationResults.popError(error))
|
||||
{
|
||||
schema_warnings->push_back(std::string(validation_failed + " for ")
|
||||
+ std::accumulate(error.context.begin(), error.context.end(), std::string(""))
|
||||
+ ": "
|
||||
+ error.description);
|
||||
while(validationResults.popError(error)) {
|
||||
schema_warnings->push_back(std::string(validation_failed + " for ") +
|
||||
std::accumulate(error.context.begin(),
|
||||
error.context.end(),
|
||||
std::string("")) +
|
||||
": " + error.description);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
schema_warnings->push_back(validation_ok);
|
||||
}
|
||||
}
|
||||
@@ -295,63 +274,51 @@ private:
|
||||
* and resolve any "${env_var}" to its value;
|
||||
* moreover, any "$${str}" is resolved to simply "${str}".
|
||||
*/
|
||||
void pre_process_env_vars(YAML::Node& root)
|
||||
{
|
||||
yaml_visitor([](YAML::Node &scalar) {
|
||||
auto value = scalar.as<std::string>();
|
||||
auto start_pos = value.find('$');
|
||||
while (start_pos != std::string::npos)
|
||||
{
|
||||
auto substr = value.substr(start_pos);
|
||||
// Case 1 -> ${}
|
||||
if (substr.rfind("${", 0) == 0)
|
||||
{
|
||||
auto end_pos = substr.find('}');
|
||||
if (end_pos != std::string::npos)
|
||||
{
|
||||
// Eat "${" and "}" when getting the env var name
|
||||
auto env_str = substr.substr(2, end_pos - 2);
|
||||
const char* env_value = std::getenv(env_str.c_str()); // Get the environment variable value
|
||||
if(env_value)
|
||||
{
|
||||
// env variable name + "${}"
|
||||
value.replace(start_pos, env_str.length() + 3, env_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
value.erase(start_pos, env_str.length() + 3);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// There are no "}" chars anymore; just break leaving rest of value untouched.
|
||||
break;
|
||||
void pre_process_env_vars(YAML::Node& root) {
|
||||
yaml_visitor([](YAML::Node& scalar) {
|
||||
auto value = scalar.as<std::string>();
|
||||
auto start_pos = value.find('$');
|
||||
while(start_pos != std::string::npos) {
|
||||
auto substr = value.substr(start_pos);
|
||||
// Case 1 -> ${}
|
||||
if(substr.rfind("${", 0) == 0) {
|
||||
auto end_pos = substr.find('}');
|
||||
if(end_pos != std::string::npos) {
|
||||
// Eat "${" and "}" when getting the env var name
|
||||
auto env_str = substr.substr(2, end_pos - 2);
|
||||
const char* env_value =
|
||||
std::getenv(env_str.c_str()); // Get the environment variable value
|
||||
if(env_value) {
|
||||
// env variable name + "${}"
|
||||
value.replace(start_pos, env_str.length() + 3, env_value);
|
||||
} else {
|
||||
value.erase(start_pos, env_str.length() + 3);
|
||||
}
|
||||
} else {
|
||||
// There are no "}" chars anymore; just break leaving rest of value
|
||||
// untouched.
|
||||
break;
|
||||
}
|
||||
// Case 2 -> $${}
|
||||
else if (substr.rfind("$${", 0) == 0)
|
||||
{
|
||||
auto end_pos = substr.find('}');
|
||||
if (end_pos != std::string::npos)
|
||||
{
|
||||
// Consume first "$" token
|
||||
value.erase(start_pos, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// There are no "}" chars anymore; just break leaving rest of value untouched.
|
||||
break;
|
||||
}
|
||||
start_pos++; // consume the second '$' token
|
||||
}
|
||||
else
|
||||
{
|
||||
start_pos += substr.length();
|
||||
}
|
||||
start_pos = value.find("$", start_pos);
|
||||
}
|
||||
scalar = value;
|
||||
})(root);
|
||||
// Case 2 -> $${}
|
||||
else if(substr.rfind("$${", 0) == 0) {
|
||||
auto end_pos = substr.find('}');
|
||||
if(end_pos != std::string::npos) {
|
||||
// Consume first "$" token
|
||||
value.erase(start_pos, 1);
|
||||
} else {
|
||||
// There are no "}" chars anymore; just break leaving rest of value
|
||||
// untouched.
|
||||
break;
|
||||
}
|
||||
start_pos++; // consume the second '$' token
|
||||
} else {
|
||||
start_pos += substr.length();
|
||||
}
|
||||
start_pos = value.find("$", start_pos);
|
||||
}
|
||||
scalar = value;
|
||||
})(root);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -365,101 +332,79 @@ private:
|
||||
*
|
||||
* If can_append is true, an empty NodeKey will append a new entry
|
||||
* to the sequence, it is rejected otherwise.
|
||||
*
|
||||
*
|
||||
* Some examples of accepted key strings:
|
||||
* - NodeName
|
||||
* - ListValue[3].subvalue
|
||||
* - MatrixValue[1][3]
|
||||
* - value1.subvalue2.subvalue3
|
||||
*/
|
||||
void get_node(YAML::Node &ret, const std::string &key, bool can_append=false) const
|
||||
{
|
||||
try
|
||||
{
|
||||
void get_node(YAML::Node& ret, const std::string& key, bool can_append = false) const {
|
||||
try {
|
||||
char c;
|
||||
bool should_shift;
|
||||
std::string nodeKey;
|
||||
ret.reset(m_root);
|
||||
for(std::string::size_type i = 0; i < key.size(); ++i)
|
||||
{
|
||||
for(std::string::size_type i = 0; i < key.size(); ++i) {
|
||||
c = key[i];
|
||||
should_shift = c == '.' || c == '[' || i == key.size() - 1;
|
||||
|
||||
if (c != '.' && c != '[')
|
||||
{
|
||||
if (i > 0 && nodeKey.empty() && key[i - 1] != '.')
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"Parsing error: expected '.' character at pos "
|
||||
+ std::to_string(i - 1));
|
||||
if(c != '.' && c != '[') {
|
||||
if(i > 0 && nodeKey.empty() && key[i - 1] != '.') {
|
||||
throw std::runtime_error("Parsing error: expected '.' character at pos " +
|
||||
std::to_string(i - 1));
|
||||
}
|
||||
nodeKey += c;
|
||||
}
|
||||
|
||||
if (should_shift)
|
||||
{
|
||||
if (nodeKey.empty())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"Parsing error: unexpected character at pos "
|
||||
+ std::to_string(i));
|
||||
if(should_shift) {
|
||||
if(nodeKey.empty()) {
|
||||
throw std::runtime_error("Parsing error: unexpected character at pos " +
|
||||
std::to_string(i));
|
||||
}
|
||||
ret.reset(ret[nodeKey]);
|
||||
nodeKey.clear();
|
||||
}
|
||||
if (c == '[')
|
||||
{
|
||||
if(c == '[') {
|
||||
auto close_param_idx = key.find(']', i);
|
||||
std::string idx_str = key.substr(i + 1, close_param_idx - i - 1);
|
||||
int nodeIdx;
|
||||
|
||||
bool ret_appendable = !ret.IsDefined() || ret.IsSequence();
|
||||
if (idx_str.empty() && ret_appendable && can_append)
|
||||
{
|
||||
if(idx_str.empty() && ret_appendable && can_append) {
|
||||
YAML::Node newNode;
|
||||
ret.push_back(newNode);
|
||||
nodeIdx = ret.size() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
} else {
|
||||
try {
|
||||
nodeIdx = std::stoi(idx_str);
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
throw std::runtime_error("Parsing error: expected a numeric index, found '" + idx_str + "'");
|
||||
} catch(const std::exception& e) {
|
||||
throw std::runtime_error(
|
||||
"Parsing error: expected a numeric index, found '" + idx_str +
|
||||
"'");
|
||||
}
|
||||
}
|
||||
ret.reset(ret[nodeIdx]);
|
||||
i = close_param_idx;
|
||||
if (i < key.size() - 1 && key[i + 1] == '.')
|
||||
{
|
||||
if(i < key.size() - 1 && key[i + 1] == '.') {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
throw std::runtime_error("Config error at key \"" + key + "\": " + std::string(e.what()));
|
||||
} catch(const std::exception& e) {
|
||||
throw std::runtime_error("Config error at key \"" + key +
|
||||
"\": " + std::string(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void get_sequence_from_node(T& ret, const YAML::Node& node) const
|
||||
{
|
||||
if(node.IsDefined())
|
||||
{
|
||||
if(node.IsSequence())
|
||||
{
|
||||
for(const YAML::Node& item : node)
|
||||
{
|
||||
void get_sequence_from_node(T& ret, const YAML::Node& node) const {
|
||||
if(node.IsDefined()) {
|
||||
if(node.IsSequence()) {
|
||||
for(const YAML::Node& item : node) {
|
||||
ret.insert(ret.end(), item.as<typename T::value_type>());
|
||||
}
|
||||
}
|
||||
else if(node.IsScalar())
|
||||
{
|
||||
} else if(node.IsScalar()) {
|
||||
ret.insert(ret.end(), node.as<typename T::value_type>());
|
||||
}
|
||||
}
|
||||
@@ -468,55 +413,45 @@ private:
|
||||
|
||||
// define a yaml-cpp conversion function for nlohmann json objects
|
||||
namespace YAML {
|
||||
template<>
|
||||
struct convert<nlohmann::json> {
|
||||
static bool decode(const Node& node, nlohmann::json& res)
|
||||
{
|
||||
int int_val;
|
||||
double double_val;
|
||||
bool bool_val;
|
||||
std::string str_val;
|
||||
template<>
|
||||
struct convert<nlohmann::json> {
|
||||
static bool decode(const Node& node, nlohmann::json& res) {
|
||||
int int_val;
|
||||
double double_val;
|
||||
bool bool_val;
|
||||
std::string str_val;
|
||||
|
||||
switch (node.Type()) {
|
||||
case YAML::NodeType::Map:
|
||||
for (auto &&it: node)
|
||||
{
|
||||
nlohmann::json sub{};
|
||||
YAML::convert<nlohmann::json>::decode(it.second, sub);
|
||||
res[it.first.as<std::string>()] = sub;
|
||||
}
|
||||
break;
|
||||
case YAML::NodeType::Sequence:
|
||||
for (auto &&it : node)
|
||||
{
|
||||
nlohmann::json sub{};
|
||||
YAML::convert<nlohmann::json>::decode(it, sub);
|
||||
res.emplace_back(sub);
|
||||
}
|
||||
break;
|
||||
case YAML::NodeType::Scalar:
|
||||
if (YAML::convert<int>::decode(node, int_val))
|
||||
{
|
||||
res = int_val;
|
||||
}
|
||||
else if (YAML::convert<double>::decode(node, double_val))
|
||||
{
|
||||
res = double_val;
|
||||
}
|
||||
else if (YAML::convert<bool>::decode(node, bool_val))
|
||||
{
|
||||
res = bool_val;
|
||||
}
|
||||
else if (YAML::convert<std::string>::decode(node, str_val))
|
||||
{
|
||||
res = str_val;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
switch(node.Type()) {
|
||||
case YAML::NodeType::Map:
|
||||
for(auto&& it : node) {
|
||||
nlohmann::json sub{};
|
||||
YAML::convert<nlohmann::json>::decode(it.second, sub);
|
||||
res[it.first.as<std::string>()] = sub;
|
||||
}
|
||||
|
||||
return true;
|
||||
break;
|
||||
case YAML::NodeType::Sequence:
|
||||
for(auto&& it : node) {
|
||||
nlohmann::json sub{};
|
||||
YAML::convert<nlohmann::json>::decode(it, sub);
|
||||
res.emplace_back(sub);
|
||||
}
|
||||
break;
|
||||
case YAML::NodeType::Scalar:
|
||||
if(YAML::convert<int>::decode(node, int_val)) {
|
||||
res = int_val;
|
||||
} else if(YAML::convert<double>::decode(node, double_val)) {
|
||||
res = double_val;
|
||||
} else if(YAML::convert<bool>::decode(node, bool_val)) {
|
||||
res = bool_val;
|
||||
} else if(YAML::convert<std::string>::decode(node, str_val)) {
|
||||
res = str_val;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// The "encode" function is not needed here, in fact you can simply YAML::load any json string.
|
||||
};
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
// The "encode" function is not needed here, in fact you can simply YAML::load any json string.
|
||||
};
|
||||
} // namespace YAML
|
||||
|
||||
@@ -2,138 +2,126 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# 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.
|
||||
#
|
||||
|
||||
configure_file(config_falco.h.in config_falco.h)
|
||||
|
||||
add_library(falco_application STATIC
|
||||
app/app.cpp
|
||||
app/options.cpp
|
||||
app/restart_handler.cpp
|
||||
app/actions/helpers_generic.cpp
|
||||
app/actions/helpers_inspector.cpp
|
||||
app/actions/configure_interesting_sets.cpp
|
||||
app/actions/create_signal_handlers.cpp
|
||||
app/actions/pidfile.cpp
|
||||
app/actions/init_falco_engine.cpp
|
||||
app/actions/init_inspectors.cpp
|
||||
app/actions/init_outputs.cpp
|
||||
app/actions/list_fields.cpp
|
||||
app/actions/list_plugins.cpp
|
||||
app/actions/load_config.cpp
|
||||
app/actions/load_plugins.cpp
|
||||
app/actions/load_rules_files.cpp
|
||||
app/actions/process_events.cpp
|
||||
app/actions/print_generated_gvisor_config.cpp
|
||||
app/actions/print_help.cpp
|
||||
app/actions/print_ignored_events.cpp
|
||||
app/actions/print_kernel_version.cpp
|
||||
app/actions/print_plugin_info.cpp
|
||||
app/actions/print_support.cpp
|
||||
app/actions/print_syscall_events.cpp
|
||||
app/actions/print_version.cpp
|
||||
app/actions/print_page_size.cpp
|
||||
app/actions/configure_syscall_buffer_size.cpp
|
||||
app/actions/configure_syscall_buffer_num.cpp
|
||||
app/actions/select_event_sources.cpp
|
||||
app/actions/start_grpc_server.cpp
|
||||
app/actions/start_webserver.cpp
|
||||
app/actions/validate_rules_files.cpp
|
||||
app/actions/create_requested_paths.cpp
|
||||
app/actions/close_inspectors.cpp
|
||||
app/actions/print_config_schema.cpp
|
||||
app/actions/print_rule_schema.cpp
|
||||
configuration.cpp
|
||||
falco_outputs.cpp
|
||||
outputs_file.cpp
|
||||
outputs_stdout.cpp
|
||||
event_drops.cpp
|
||||
stats_writer.cpp
|
||||
versions_info.cpp
|
||||
add_library(
|
||||
falco_application STATIC
|
||||
app/app.cpp
|
||||
app/options.cpp
|
||||
app/restart_handler.cpp
|
||||
app/actions/helpers_generic.cpp
|
||||
app/actions/helpers_inspector.cpp
|
||||
app/actions/configure_interesting_sets.cpp
|
||||
app/actions/create_signal_handlers.cpp
|
||||
app/actions/pidfile.cpp
|
||||
app/actions/init_falco_engine.cpp
|
||||
app/actions/init_inspectors.cpp
|
||||
app/actions/init_outputs.cpp
|
||||
app/actions/list_fields.cpp
|
||||
app/actions/list_plugins.cpp
|
||||
app/actions/load_config.cpp
|
||||
app/actions/load_plugins.cpp
|
||||
app/actions/load_rules_files.cpp
|
||||
app/actions/process_events.cpp
|
||||
app/actions/print_generated_gvisor_config.cpp
|
||||
app/actions/print_help.cpp
|
||||
app/actions/print_ignored_events.cpp
|
||||
app/actions/print_kernel_version.cpp
|
||||
app/actions/print_plugin_info.cpp
|
||||
app/actions/print_support.cpp
|
||||
app/actions/print_syscall_events.cpp
|
||||
app/actions/print_version.cpp
|
||||
app/actions/print_page_size.cpp
|
||||
app/actions/configure_syscall_buffer_size.cpp
|
||||
app/actions/configure_syscall_buffer_num.cpp
|
||||
app/actions/select_event_sources.cpp
|
||||
app/actions/start_grpc_server.cpp
|
||||
app/actions/start_webserver.cpp
|
||||
app/actions/validate_rules_files.cpp
|
||||
app/actions/create_requested_paths.cpp
|
||||
app/actions/close_inspectors.cpp
|
||||
app/actions/print_config_schema.cpp
|
||||
app/actions/print_rule_schema.cpp
|
||||
configuration.cpp
|
||||
falco_outputs.cpp
|
||||
outputs_file.cpp
|
||||
outputs_stdout.cpp
|
||||
event_drops.cpp
|
||||
stats_writer.cpp
|
||||
versions_info.cpp
|
||||
)
|
||||
|
||||
set(
|
||||
FALCO_INCLUDE_DIRECTORIES
|
||||
"${PROJECT_SOURCE_DIR}/userspace/engine"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
"${PROJECT_BINARY_DIR}/driver/src"
|
||||
"${CXXOPTS_INCLUDE_DIR}"
|
||||
set(FALCO_INCLUDE_DIRECTORIES
|
||||
"${PROJECT_SOURCE_DIR}/userspace/engine" "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}" "${PROJECT_BINARY_DIR}/driver/src" "${CXXOPTS_INCLUDE_DIR}"
|
||||
)
|
||||
|
||||
set(
|
||||
FALCO_DEPENDENCIES
|
||||
cxxopts
|
||||
)
|
||||
set(FALCO_DEPENDENCIES cxxopts)
|
||||
|
||||
set(
|
||||
FALCO_LIBRARIES
|
||||
falco_engine
|
||||
sinsp
|
||||
yaml-cpp
|
||||
)
|
||||
set(FALCO_LIBRARIES falco_engine sinsp yaml-cpp)
|
||||
|
||||
if(NOT WIN32)
|
||||
target_sources(falco_application
|
||||
PRIVATE
|
||||
outputs_program.cpp
|
||||
outputs_syslog.cpp
|
||||
)
|
||||
target_sources(falco_application PRIVATE outputs_program.cpp outputs_syslog.cpp)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT MINIMAL_BUILD)
|
||||
target_sources(falco_application
|
||||
PRIVATE
|
||||
outputs_grpc.cpp
|
||||
outputs_http.cpp
|
||||
falco_metrics.cpp
|
||||
webserver.cpp
|
||||
grpc_context.cpp
|
||||
grpc_request_context.cpp
|
||||
grpc_server.cpp
|
||||
grpc_context.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc
|
||||
)
|
||||
target_sources(
|
||||
falco_application
|
||||
PRIVATE outputs_grpc.cpp
|
||||
outputs_http.cpp
|
||||
falco_metrics.cpp
|
||||
webserver.cpp
|
||||
grpc_context.cpp
|
||||
grpc_request_context.cpp
|
||||
grpc_server.cpp
|
||||
grpc_context.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc
|
||||
)
|
||||
|
||||
list(
|
||||
APPEND FALCO_INCLUDE_DIRECTORIES
|
||||
"${OPENSSL_INCLUDE_DIR}"
|
||||
"${GRPC_INCLUDE}"
|
||||
"${GRPCPP_INCLUDE}"
|
||||
"${PROTOBUF_INCLUDE}"
|
||||
"${CARES_INCLUDE}"
|
||||
)
|
||||
list(
|
||||
APPEND
|
||||
FALCO_INCLUDE_DIRECTORIES
|
||||
"${OPENSSL_INCLUDE_DIR}"
|
||||
"${GRPC_INCLUDE}"
|
||||
"${GRPCPP_INCLUDE}"
|
||||
"${PROTOBUF_INCLUDE}"
|
||||
"${CARES_INCLUDE}"
|
||||
)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND USE_BUNDLED_GRPC)
|
||||
list(APPEND FALCO_DEPENDENCIES grpc)
|
||||
list(APPEND FALCO_LIBRARIES "${GRPC_LIBRARIES}")
|
||||
endif()
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND USE_BUNDLED_GRPC)
|
||||
list(APPEND FALCO_DEPENDENCIES grpc)
|
||||
list(APPEND FALCO_LIBRARIES "${GRPC_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
list(
|
||||
APPEND FALCO_LIBRARIES
|
||||
httplib::httplib
|
||||
"${GRPCPP_LIB}"
|
||||
"${GRPC_LIB}"
|
||||
"${GPR_LIB}"
|
||||
"${PROTOBUF_LIB}"
|
||||
"${CARES_LIB}"
|
||||
"${OPENSSL_LIBRARIES}"
|
||||
)
|
||||
list(
|
||||
APPEND
|
||||
FALCO_LIBRARIES
|
||||
httplib::httplib
|
||||
"${GRPCPP_LIB}"
|
||||
"${GRPC_LIB}"
|
||||
"${GPR_LIB}"
|
||||
"${PROTOBUF_LIB}"
|
||||
"${CARES_LIB}"
|
||||
"${OPENSSL_LIBRARIES}"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (EMSCRIPTEN)
|
||||
if(EMSCRIPTEN)
|
||||
target_compile_options(falco_application PRIVATE "-sDISABLE_EXCEPTION_CATCHING=0")
|
||||
endif()
|
||||
|
||||
@@ -141,81 +129,78 @@ target_compile_definitions(falco_application PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT)
|
||||
|
||||
add_dependencies(falco_application ${FALCO_DEPENDENCIES})
|
||||
|
||||
target_link_libraries(
|
||||
falco_application
|
||||
${FALCO_LIBRARIES}
|
||||
)
|
||||
target_link_libraries(falco_application ${FALCO_LIBRARIES})
|
||||
|
||||
target_include_directories(
|
||||
falco_application
|
||||
PUBLIC
|
||||
${FALCO_INCLUDE_DIRECTORIES}
|
||||
)
|
||||
target_include_directories(falco_application PUBLIC ${FALCO_INCLUDE_DIRECTORIES})
|
||||
|
||||
add_executable(falco falco.cpp)
|
||||
add_dependencies(falco falco_application ${FALCO_DEPENDENCIES})
|
||||
target_link_libraries(falco falco_application ${FALCO_LIBRARIES})
|
||||
target_include_directories(falco PUBLIC ${FALCO_INCLUDE_DIRECTORIES})
|
||||
|
||||
if (EMSCRIPTEN)
|
||||
target_compile_options(falco PRIVATE "-sDISABLE_EXCEPTION_CATCHING=0")
|
||||
target_link_options(falco PRIVATE "-sALLOW_MEMORY_GROWTH=1")
|
||||
target_link_options(falco PRIVATE "-sDISABLE_EXCEPTION_CATCHING=0")
|
||||
target_link_options(falco PRIVATE "-sMODULARIZE=1")
|
||||
target_link_options(falco PRIVATE "-sEXPORT_ES6=1")
|
||||
target_link_options(falco PRIVATE "-sEXPORTED_RUNTIME_METHODS=['FS', 'callMain']")
|
||||
target_link_options(falco PRIVATE "-sEXPORTED_FUNCTIONS=['_main','_htons','_ntohs']")
|
||||
if(EMSCRIPTEN)
|
||||
target_compile_options(falco PRIVATE "-sDISABLE_EXCEPTION_CATCHING=0")
|
||||
target_link_options(falco PRIVATE "-sALLOW_MEMORY_GROWTH=1")
|
||||
target_link_options(falco PRIVATE "-sDISABLE_EXCEPTION_CATCHING=0")
|
||||
target_link_options(falco PRIVATE "-sMODULARIZE=1")
|
||||
target_link_options(falco PRIVATE "-sEXPORT_ES6=1")
|
||||
target_link_options(falco PRIVATE "-sEXPORTED_RUNTIME_METHODS=['FS', 'callMain']")
|
||||
target_link_options(falco PRIVATE "-sEXPORTED_FUNCTIONS=['_main','_htons','_ntohs']")
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT MINIMAL_BUILD)
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.h
|
||||
COMMENT "Generate gRPC API"
|
||||
# Falco gRPC Version API
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/version.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/version.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=. --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/version.proto
|
||||
# Falco gRPC Outputs API
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=. ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/schema.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=. --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/outputs.pb.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.cc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/schema.pb.h
|
||||
COMMENT "Generate gRPC API"
|
||||
# Falco gRPC Version API
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/version.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=.
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/version.proto
|
||||
COMMAND
|
||||
${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=.
|
||||
--plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN} ${CMAKE_CURRENT_SOURCE_DIR}/version.proto
|
||||
# Falco gRPC Outputs API
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
|
||||
COMMAND ${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --cpp_out=.
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto ${CMAKE_CURRENT_SOURCE_DIR}/schema.proto
|
||||
COMMAND
|
||||
${PROTOC} -I ${CMAKE_CURRENT_SOURCE_DIR} --grpc_out=.
|
||||
--plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN} ${CMAKE_CURRENT_SOURCE_DIR}/outputs.proto
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
# strip the Falco binary when releasing using musl
|
||||
if(MUSL_OPTIMIZED_BUILD AND CMAKE_BUILD_TYPE STREQUAL "release")
|
||||
add_custom_command(
|
||||
TARGET falco
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_STRIP} --strip-unneeded falco
|
||||
COMMENT "Strip the Falco binary when releasing the musl build"
|
||||
)
|
||||
add_custom_command(
|
||||
TARGET falco
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_STRIP} --strip-unneeded falco
|
||||
COMMENT "Strip the Falco binary when releasing the musl build"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (EMSCRIPTEN)
|
||||
install(FILES
|
||||
"$<TARGET_FILE_DIR:falco>/falco.js"
|
||||
"$<TARGET_FILE_DIR:falco>/falco.wasm"
|
||||
if(EMSCRIPTEN)
|
||||
install(
|
||||
FILES "$<TARGET_FILE_DIR:falco>/falco.js" "$<TARGET_FILE_DIR:falco>/falco.wasm"
|
||||
DESTINATION ${FALCO_BIN_DIR}
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
elseif (WIN32)
|
||||
install(TARGETS falco
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}"
|
||||
)
|
||||
elseif(WIN32)
|
||||
install(
|
||||
TARGETS falco
|
||||
DESTINATION bin
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
COMPONENT "${FALCO_COMPONENT_NAME}"
|
||||
)
|
||||
else()
|
||||
install(TARGETS falco RUNTIME DESTINATION ${FALCO_BIN_DIR} COMPONENT "${FALCO_COMPONENT_NAME}")
|
||||
endif()
|
||||
|
||||
@@ -60,6 +60,6 @@ falco::app::run_result unregister_signal_handlers(falco::app::state& s);
|
||||
falco::app::run_result validate_rules_files(falco::app::state& s);
|
||||
falco::app::run_result close_inspectors(falco::app::state& s);
|
||||
|
||||
}; // namespace actions
|
||||
}; // namespace app
|
||||
}; // namespace falco
|
||||
}; // namespace actions
|
||||
}; // namespace app
|
||||
}; // namespace falco
|
||||
|
||||
@@ -21,21 +21,17 @@ limitations under the License.
|
||||
using namespace falco::app;
|
||||
using namespace falco::app::actions;
|
||||
|
||||
falco::app::run_result falco::app::actions::close_inspectors(falco::app::state& s)
|
||||
{
|
||||
falco::app::run_result falco::app::actions::close_inspectors(falco::app::state& s) {
|
||||
falco_logger::log(falco_logger::level::DEBUG, "closing inspectors");
|
||||
|
||||
if (s.offline_inspector != nullptr)
|
||||
{
|
||||
if(s.offline_inspector != nullptr) {
|
||||
s.offline_inspector->close();
|
||||
}
|
||||
|
||||
for (const auto &src : s.loaded_sources)
|
||||
{
|
||||
for(const auto& src : s.loaded_sources) {
|
||||
auto src_info = s.source_infos.at(src);
|
||||
|
||||
if (src_info->inspector != nullptr)
|
||||
{
|
||||
if(src_info->inspector != nullptr) {
|
||||
src_info->inspector->close();
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user