Compare commits

...

207 Commits

Author SHA1 Message Date
Luca Guerra
35ee18c435 new(docs): add changelog for 0.38.2
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-08-19 14:53:41 +02:00
Luca Guerra
876637839f update(build): libs 0.17.3
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-08-19 11:12:41 +02:00
Luca Guerra
76719bdc39 chore(build): bumpd falcoctl to 0.9.0 for 0.38.2
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-08-08 11:36:53 +02:00
Melissa Kilby
1347810eab fix(metrics/prometheus): adopt best prometheus practices for rules counters and sha256 file metrics
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-08-07 11:26:47 +02:00
Federico Di Pierro
2653b67342 chore(ci): add ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION:true env to enforce the usage of node16.
Centos:7 does not support node20 (glibc required mismatch).

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-08-07 11:26:47 +02:00
Federico Di Pierro
89e30841da chore(ci): use correct vault repo path for arm64.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-08-07 11:26:47 +02:00
Federico Di Pierro
4d6332765f fix(ci): use vault.centos.org for centos:7 CI build.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-08-07 11:26:47 +02:00
Luca Guerra
00e154870b chore(app): update stats interface to build
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-08-07 11:26:47 +02:00
Luca Guerra
62ab938973 update(engine): upgrade libs and driver to 0.17.3 / 7.2.1
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-08-07 11:26:47 +02:00
Federico Di Pierro
7efabb7243 update(docs): update CHANGELOG for 0.38.1
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-06-25 14:37:37 +02:00
Gianmatteo Palmieri
2820cd1d07 new(metrics): enable plugins metrics
Signed-off-by: Gianmatteo Palmieri <mail@gian.im>
Co-authored-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-06-17 11:54:00 +02:00
Luca Guerra
ee26667e89 update(engine): allow using -p to pass a format to plugin events
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-06-17 11:54:00 +02:00
Luca Guerra
f267404be9 cleanup(falco): clarify that --print variants only affect syscalls
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-06-17 11:54:00 +02:00
Gianmatteo Palmieri
160e35e801 Revert "fix(engine): apply output substitutions for all sources"
This reverts commit 4ef7c9553a.

Signed-off-by: Gianmatteo Palmieri <mail@gian.im>
2024-06-17 11:54:00 +02:00
Melissa Kilby
2117f3031d fix(metrics): fix sha256 metric names for prometheus
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-06-17 11:54:00 +02:00
Melissa Kilby
fa905e1356 fix(metrics): allow each metric output channel to be selected independently
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-06-17 11:54:00 +02:00
Federico Di Pierro
f265e18d96 chore(userspace/falco): more extra safety checks on stats collector too.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>

Co-authored-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-06-17 11:54:00 +02:00
Federico Di Pierro
6643c7491f fix(userspace/falco): fixed falco_metrics::to_text implementation when running with plugins.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-06-17 11:54:00 +02:00
Federico Di Pierro
cb5b075b0e update(cmake): bump libs to 0.17.2
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-06-17 11:54:00 +02:00
Luca Guerra
fc921d1bda update(docs): update CHANGELOG for 0.38.0
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-05-30 09:59:54 +02:00
Federico Di Pierro
576f3164d8 update(cmake): bump libs to 0.17.1.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-29 15:05:50 +02:00
Federico Di Pierro
11ad96bdd7 chore(proposals): fix typo.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-28 15:33:47 +02:00
Federico Di Pierro
718e3e8876 update(cmake): bump falcoctl to v0.8.0.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-28 15:33:47 +02:00
Luca Guerra
fdd093b817 chore(build): bump rules to 3.1.0
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-05-28 15:33:47 +02:00
dependabot[bot]
dbc3765aef ---
updated-dependencies:
- dependency-name: submodules/falcosecurity-rules
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-28 15:33:47 +02:00
Jason Dellaluce
d7cbf9c7c9 refactor(userspace): move falco logger under falco engine
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2024-05-28 15:33:47 +02:00
Federico Di Pierro
7fc186ac81 update(cmake): bumped libs to 0.17.0 and driver to 7.2.0+driver.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-27 10:09:43 +02:00
Federico Di Pierro
951310878c update(cmake): bump libs to 0.17.0-rc2.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-22 10:14:19 +02:00
Luca Guerra
7a4ee0d768 chore(gha): update cosign
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-05-21 12:14:13 +02:00
dependabot[bot]
6948b2f5c0 build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `29c41c4` to `59bf03b`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](29c41c4eed...59bf03bf74)

---
updated-dependencies:
- dependency-name: submodules/falcosecurity-rules
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-21 12:14:13 +02:00
Federico Di Pierro
0bf7458f3d chore(falco.yaml): rule -> rules.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-20 16:33:11 +02:00
Federico Di Pierro
d553662108 cleanup(falco.yaml): removed useless sentence.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-20 16:33:11 +02:00
Federico Di Pierro
a48965a00c chore(userspace,falco.yaml,unit_tests): configs_files -> config_files.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-20 16:33:11 +02:00
Federico Di Pierro
1b22c4566a chore(falco.yaml): added config maturity to index.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-20 16:33:11 +02:00
Federico Di Pierro
c03ce122e7 chore(docs): added falco.yaml section about config keys maturity.
Also, rename `Experimental` -> `Incubating` and move `prometheus_metrics_enabled` to `Incubating`.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-20 16:33:11 +02:00
Melissa Kilby
0668c54485 cleanup(metrics): use sha26_rules (plural form) as naming
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-05-20 10:25:10 +02:00
Melissa Kilby
27bab30017 cleanup(metrics): add original rule name as label
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-05-20 10:25:10 +02:00
Federico Di Pierro
dfbd1810f9 update(cmake): bumped libs to 0.17.0-rc1 and falcoctl to v0.8.0-rc6.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-17 17:11:58 +02:00
Melissa Kilby
b0f352e7b9 cleanup(test): add test cases for sanitize_metric_name
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-05-17 14:54:58 +02:00
Melissa Kilby
c15a309781 clenaup: add sanitize_metric_name helper
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-05-17 14:54:58 +02:00
Melissa Kilby
e9afe24e17 cleanup(metrics): simplify some logic
Co-authored-by: Samuel Gaist <samuel.gaist@idiap.ch>
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-05-17 14:54:58 +02:00
Melissa Kilby
aa021537d9 cleanup(metrics): improve comments
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-05-17 14:54:58 +02:00
Melissa Kilby
0195dba889 cleanup: add getter functions to stats_manager
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-05-17 14:54:58 +02:00
Melissa Kilby
b7adcd251d new(metrics): add rules_counters_enabled option
Intended to replace https://github.com/falcosecurity/falco-exporter
when used with Prometheus output

Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-05-17 14:54:58 +02:00
Jason Dellaluce
64039196ad chore(unit_tests): fix linting issue
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2024-05-17 14:38:57 +02:00
Jason Dellaluce
ec9f148e0b test(engine): cover case of replaced or appended exceptions
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2024-05-17 14:38:57 +02:00
Jason Dellaluce
e211e97e2a fix(userspace/engine): make sure exception fields are not optional in replace mode
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2024-05-17 14:38:57 +02:00
Federico Di Pierro
1bf6a83e31 new(docker): added zstd dep.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-17 13:38:57 +02:00
Luca Guerra
b5461e11a7 new(ci): sign .tar.gz packages
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-05-17 10:17:56 +02:00
Federico Di Pierro
c8072d2640 update(cmake): bumped falcoctl to v0.8.0-rc5.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-16 14:41:54 +02:00
Melissa Kilby
6057c1553e cleanup(engine): print total number of enabled rules
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-05-16 10:29:53 +02:00
Melissa Kilby
77341cbd2e new(engine): add print_enabled_rules_falco_logger when log_level debug
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-05-16 10:29:53 +02:00
dependabot[bot]
0869abc65e build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `4f153f5` to `29c41c4`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](4f153f53ae...29c41c4eed)

---
updated-dependencies:
- dependency-name: submodules/falcosecurity-rules
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-16 09:37:53 +02:00
Luca Guerra
eb3ee5d2b2 update(falco): add deprecation warning messages
Signed-off-by: Luca Guerra <luca@guerra.sh>
Co-authored-by: Federico Di Pierro <nierro92@gmail.com>
Co-authored-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-05-15 10:33:50 +02:00
Luca Guerra
f9a56d9c9d update(falco): add deprecation notice for -T, -t and -D
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-05-15 10:33:50 +02:00
Luca Guerra
abf82f6373 update(config): split init_from_content from init_from_file
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-05-14 12:47:46 +02:00
Luca Guerra
f6ae8c8470 update(config): experimental->incubating
Co-authored-by: Leonardo Grasso <me@leonardograsso.com>
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-05-14 12:47:46 +02:00
Luca Guerra
02afb39a85 new(engine): add 'rules' section description to falco.yaml
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-05-14 12:47:46 +02:00
Luca Guerra
35bd348e21 new(falco): implement rule selection configuration in falco.yaml
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-05-14 12:47:46 +02:00
Melissa Kilby
60e6798f9b cleanup(metrics): use map for config and rules filenames sha256 tracking
Co-authored-by: Federico Di Pierro <nierro92@gmail.com>
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-05-14 10:08:51 +02:00
Melissa Kilby
91b58c43f1 chore: fix non linux build metrics
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-05-14 10:08:51 +02:00
Melissa Kilby
67a5015be7 cleanup(metrics): use filesystem lib to derive file names + build fix
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-05-14 10:08:51 +02:00
Melissa Kilby
34ecd39113 new(metrics): add file sha256sum metrics for loaded config and rules files
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-05-14 10:08:51 +02:00
Melissa Kilby
2b80cf85ac new(utils): add new helper to calculate file sha256sum
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-05-14 10:08:51 +02:00
Federico Di Pierro
44c275dee8 update(cmake): bumped falcoctl to v0.8.0-rc4.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-13 18:32:43 +02:00
Federico Di Pierro
cf88a8cdf8 update(cmake): bump falcoctl to v0.8.0-rc3
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-13 18:32:43 +02:00
Federico Di Pierro
dd9163c6f4 fix(userspace/falco): fix state inizialization.
This fixes an ugly segfault happening during hot reload.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-09 10:43:58 +02:00
Jason Dellaluce
d17f2afe4f update(cmake): bump libs and driver to a8fdacdb
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2024-05-08 20:23:55 +02:00
Jason Dellaluce
b2e4cddcdf fix(userspace/falco): inizialize options variables
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2024-05-08 20:23:55 +02:00
Jason Dellaluce
c6e3cfd115 test(engine): cover transformers and field-to-field checks in exceptions
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2024-05-08 20:23:55 +02:00
Jason Dellaluce
f18ea1e8b7 update(userspace/engine): support tranformers in exception fields
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2024-05-08 20:23:55 +02:00
Jason Dellaluce
fa8e780b07 update(userspace/engine): propagate compiler warnings
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2024-05-08 20:23:55 +02:00
Jason Dellaluce
bc078f1f63 update(userspace/engine): support comparins with right-hand fields
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2024-05-08 20:23:55 +02:00
Jason Dellaluce
ed22e94292 refactor(userspace/libsinsp): support new filter ast structure in falco engine
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2024-05-08 20:23:55 +02:00
Federico Aponte
62d1c4fc4d refactor: smart pointer usage
Signed-off-by: Federico Aponte <federico.aponte@sysdig.com>
2024-05-06 11:10:44 +02:00
dependabot[bot]
96c47e5eeb build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `ec255e6` to `4f153f5`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](ec255e68f4...4f153f53ae)

---
updated-dependencies:
- dependency-name: submodules/falcosecurity-rules
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-06 10:33:44 +02:00
Federico Di Pierro
ec0f8077e1 update(cmake): bump libs and driver to latest master.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-03 12:12:02 +02:00
Andrea Terzolo
0999d45fbf bump ro rc4
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2024-05-03 12:12:02 +02:00
Federico Di Pierro
20c394ba34 chore(cmake): bumped libs to 0.16.0-rc2.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-03 12:12:02 +02:00
Andrea Terzolo
e2c2b50b3b chore: disable TLS sanitizer
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2024-05-03 12:12:02 +02:00
Andrea Terzolo
db1be96ad9 chore: tmp bump to libs master to test Falco CI
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2024-05-03 12:12:02 +02:00
Federico Di Pierro
6954a4028e chore(userspace/engine): bump version and checksum.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-03 12:12:02 +02:00
Federico Di Pierro
937637f668 update(cmake): bumped falcoctl to v0.8.0-rc2.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-03 12:12:02 +02:00
Federico Di Pierro
8b477bdc00 update(cmake): bumped libs and driver to latest RCs.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-05-03 12:12:02 +02:00
Samuel Gaist
cbfe77d1a0 fix(falco_metrics): remove falco_ prefix for version
The textual content was fixed but not the metrics name.

Co-authored-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
66d1970952 fix(falco_metrics): make duration_sec and outputs_queue_num_drops monotonic
Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
1316b0f448 chore(configuration): add reference to Prometheus endpoint in metrics documentation
The cross reference makes it easier to pair the web server and the
metrics configuration elements.

Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
82c914c11d fix(falco_metrics): make duration_sec a count and not a timestamp
The output will thus be a total which is what this metrics is.

Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
2ae6103ab6 fix(falco_metrics): remove redundant falco in version metrics
Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
65331c0f20 feat(falco_metrics): add event sources
Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
1ba35c911a feat(falco_metrics): add duration_sec
Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
5ef8f1c311 feat(falco_metrics): add outputs_queue_num_drops
Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
f90dbf9b77 refactor(metrics): use prometheus_metrics_enabled for configuration
As agreed upon during review, use this name to get started. If more
backends were to be added, the configuration structure will be updated.

Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
5c237a07dc refactor(metrics): make to_text get the application state
As falco may update its state at any time and thus its inspectors objects,
keeping pointers to them may end up in using dangling values.

Therefore, use the state of the application when requesting metrics.

Optimizations such as caching of mostly static values will be done in
a follow up patch.

Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
a0c109fcff refactor(falco_metrics): put content type in documented constant
This will keep things clearer and also allow for easir update in
the future.

Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
9cc44c0eb7 doc(falco_metrics): add basic documentation
Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
de7a70ea54 fix(metrics): correct hostname metrics name and namespace
Co-authored-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
53722a26bf fix(metrics): correct static metrics
Things to fix:
- type
- name
- unit

Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
59c290dc80 fix(metrics): correct metrics namespace
Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
daf7efde67 refactor(metrics): move metrics handling to its own class
This will keep the details out of the webserver itself and make
it easier to manage metrics.

Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
e50d647dc9 refactor(configuration): move webserver items in own struct
This makes things easier to pass around like when starting the
web server.

This has the added benefit of simplifying further extension such as
making the metrics endpoint name configurable without adding yet another
parameter to the start function.

Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
968a403cba refactor(webserver): move metrics endpoint activation under webserver
Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
cd073a033a fix(webserver): use falcosecurity as metric namespace
Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
4819877b9f fix(webserver): remove extra line return
The converter already provides properly formatted text.

Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
3a251beea7 fix(webserver): correct enabled check
It was checking twice for prometheus configuration rather than metrics and then prometheus.

Co-authored-by: Federico Di Pierro <nierro92@gmail.com>
Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Samuel Gaist
8f1b2dc909 feat(webserver): implement metrics endpoint
This endpoint currently returns only prometheus metrics.

Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-05-03 11:23:02 +02:00
Federico Di Pierro
61dab93eb3 chore(ci): fixed BUILD_FALCO_MODERN_BPF usages.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-24 16:49:26 +02:00
Federico Di Pierro
cc09811303 chore(cmake): enable modern bpf build by default.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-24 16:49:26 +02:00
Luca Guerra
d0945e5db5 cleanup(docs): fix typo in license blocks
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-04-19 16:52:58 +02:00
Federico Di Pierro
bdcfbba90b chore(docker,scripts): set old eBPF probe as lowest priority driver.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-18 11:18:54 +02:00
dependabot[bot]
b239246ff8 build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `869c9a7` to `ec255e6`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](869c9a7f4d...ec255e68f4)

---
updated-dependencies:
- dependency-name: submodules/falcosecurity-rules
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-18 09:44:54 +02:00
Luca Guerra
814c510d7e update(app): close inspectors at teardown time
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-04-17 18:39:54 +02:00
Gianmatteo Palmieri
eb04b1c66f fix(test): expect warning instead of error on invalid macro/list name
Signed-off-by: Gianmatteo Palmieri <mail@gian.im>
2024-04-17 11:27:52 +02:00
Gianmatteo Palmieri
dd59c48034 new(engine): raise warning instead of error on invalid macro/list name
Signed-off-by: Gianmatteo Palmieri <mail@gian.im>
2024-04-17 11:27:52 +02:00
Federico Di Pierro
e21a3a5e58 chore(userspace/falco): make it clear singular vs plural.
Co-authored-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-16 16:39:47 +02:00
Federico Di Pierro
92c1b24905 chore(falco.yaml): small improvements.
Co-authored-by: Leonardo Grasso <me@leonardograsso.com>
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-16 16:39:47 +02:00
Federico Di Pierro
a2a8c6c3d4 chore(userspace/falco): deprecate old 'rules_file' config key.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-16 16:39:47 +02:00
Federico Di Pierro
80a99b672f fix(docker): default to auto for driver to be configured.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-16 14:44:46 +02:00
Federico Di Pierro
fc7a451aed fix(docker): fixed docker entrypoints for driver loading.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-16 14:44:46 +02:00
Federico Di Pierro
ac61543276 fix(docker,scripts): do not load falcoctl driver loader when installing Falco deb package in docker image.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-15 17:22:44 +02:00
Federico Di Pierro
7cc57a9fa0 docs(scripts): leave a small comment.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-15 15:13:44 +02:00
Federico Di Pierro
cb414f1254 chore(docker): support new automatic driver selection in docker images entrypoints.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-15 15:13:44 +02:00
Federico Di Pierro
bb939959a7 update(falco.yaml): set modern_ebpf as default engine kind.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-15 15:13:44 +02:00
Federico Di Pierro
2ede48ccfc chore(scripts): updated debian and rpm post installation scripts to deal with new automatic driver selection as default behavior.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-15 15:13:44 +02:00
Federico Di Pierro
53d13f8bfc chore(scripts): dynamically set falcoctl allowed driver types based on cmake configuration.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-15 15:13:44 +02:00
Federico Di Pierro
2eb519380a update(cmake,scripts): bumped falcoctl to v0.8.0-rc1.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-15 15:13:44 +02:00
Gianmatteo Palmieri
c3d0579d9b fix(test): expect warning instead of error in exceptions names test
Signed-off-by: Gianmatteo Palmieri <mail@gian.im>
2024-04-11 17:22:28 +02:00
Gianmatteo Palmieri
83910be726 new(engine): raise warning instead of error on not-unique exceptions names
Signed-off-by: Gianmatteo Palmieri <mail@gian.im>
2024-04-11 17:22:28 +02:00
Luca Guerra
7ac5c36d5a update(ci): build both release and debug versions
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-04-10 16:10:20 +02:00
Federico Di Pierro
8b340d3903 chore(userspace/falco): watch all configs files.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-10 15:57:20 +02:00
Federico Di Pierro
e840a4ada0 new(unit_tests,userspace/falco): support loading and merging configs files when used from cmdline option.
Also, moved core logic from yaml_helper to falco_configuration class.
Finally, updated tests.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-10 14:44:20 +02:00
Federico Di Pierro
faabd41d9e chore(falco.yaml): add configs_files to falco yaml index.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-10 14:44:20 +02:00
Federico Di Pierro
a8345327d4 chore(unit_tests,userspace/falco): throw an exception when included config file is not present.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-10 14:44:20 +02:00
Federico Di Pierro
de9efcbec7 new(userspace/falco): allow --support to print expanded configuration file.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-10 14:44:20 +02:00
Federico Di Pierro
2a856f2cd3 chore(unit_tests): assert expected length of warnings.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-10 14:44:20 +02:00
Federico Di Pierro
74034213a2 chore(unit_test,userspace): better log management.
Also, warnings are now returned so that yaml_helper class does not need to log anything.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-10 14:44:20 +02:00
Federico Di Pierro
aac9b550d3 new(userspace,unit_tests): return loaded config filenames in config::load_from_file.
Add a debug log with the list of loaded config files.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-10 14:44:20 +02:00
Federico Di Pierro
df220e3c3b chore(userspace,unit_tests): support loading config files from directories.
The files inside the folder will be loaded in lexicographic order,
like we do for rules_file.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-10 14:44:20 +02:00
Federico Di Pierro
5e51828509 chore(build): install a config.d folder under the falco directory.
Also, include it in the config file.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-10 14:44:20 +02:00
Federico Di Pierro
d3bf3a7560 chore(userspace/falco,unit_tests): renamed includes to configs_files.
Moreover, split single huge test into multiple smaller ones.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-10 14:44:20 +02:00
Federico Di Pierro
1deafee5f7 chore(userspace/falco): print a warn message if -o includes= is passed to cmdline.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-10 14:44:20 +02:00
Federico Di Pierro
45754fda9f new(userspace,unit_tests): deny main config to include itself.
Moreover, added a couple more tests.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>

Co-authored-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-04-10 14:44:20 +02:00
Federico Di Pierro
8112f6210b chore(userspace,unit_tests): enable override of main config from secondary config files.
Moreover, do not trigger an exception when an included file is not present; just print a warning.
Finally, add more tests.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-10 14:44:20 +02:00
Federico Di Pierro
6e1f128851 chore(unit_tests): more tests.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-10 14:44:20 +02:00
Federico Di Pierro
b3ebf9f57e new(userspace,unit_tests): introduce the possibility to split main config file into multiple config files.
The PR introduces a `includes` keyword in the config file,
that points to a list of strings (paths to other config files).

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-04-10 14:44:20 +02:00
Luca Guerra
3cbc4aa29c chore(falco): update falco libs to latest master
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-04-08 17:18:13 +02:00
dependabot[bot]
39cb0a8a67 build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `88a40c8` to `869c9a7`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](88a40c8d9c...869c9a7f4d)

---
updated-dependencies:
- dependency-name: submodules/falcosecurity-rules
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-05 19:02:03 +02:00
Gianmatteo Palmieri
7234bc5bee chore(engine): bump engine version
Signed-off-by: Gianmatteo Palmieri <mail@gian.im>
2024-04-03 18:23:53 +02:00
Gianmatteo Palmieri
368463e295 new(tests): add unique exceptions names test
Signed-off-by: Gianmatteo Palmieri <mail@gian.im>
2024-04-03 18:23:53 +02:00
Gianmatteo Palmieri
05c434ed89 new(engine): enforce unique exceptions names
Signed-off-by: Gianmatteo Palmieri <mail@gian.im>
2024-04-03 18:23:53 +02:00
Luca Guerra
05e6e3038c chore(build): update scorecard-action to v2.3.1
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-04-02 16:53:45 +02:00
Luca Guerra
b01ef55f6b new(ci): build with sanitizers in CI
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-03-29 14:08:24 +01:00
Luca Guerra
f895f8fc78 fix(tests): fix uninitialized variable in test
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-03-29 14:08:24 +01:00
Luca Guerra
b82c73c66c new(build): add option to build with ASAN and UBSAN
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-03-29 14:08:24 +01:00
Luca Guerra
1aae10fe84 update(engine): bump engine checksum and version
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-03-29 10:16:23 +01:00
Luca Guerra
0d40a718c8 update(build): bump libs to latest master
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-03-29 10:16:23 +01:00
Luca Guerra
13c8e37a41 cleanup(falco): consolidate falco::grpc::server in one class
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-03-28 10:16:15 +01:00
Gianmatteo Palmieri
a8018a2894 new(tests): test override/append exception with no values
Signed-off-by: Gianmatteo Palmieri <mail@gian.im>
2024-03-27 09:15:13 +01:00
Gianmatteo Palmieri
7086f35eba new(engine): add warning when appending an exception with no values
Signed-off-by: Gianmatteo Palmieri <mail@gian.im>
2024-03-27 09:15:13 +01:00
Gianmatteo Palmieri
d1707bef63 fix(engine): apply output substitutions for all sources
Signed-off-by: Gianmatteo Palmieri <mail@gian.im>
2024-03-25 19:33:06 +01:00
dependabot[bot]
1882def2a6 build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `fbf0a4e` to `88a40c8`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](fbf0a4e8ce...88a40c8d9c)

---
updated-dependencies:
- dependency-name: submodules/falcosecurity-rules
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-25 19:06:06 +01:00
Luca Guerra
8421e4b122 fix(cmake): fix USE_BUNDLED_DEPS=ON and BUILD_FALCO_UNIT_TESTS=ON
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-03-25 16:47:06 +01:00
Paul Rey
12cd72a396 Remove --source-only option in driver loader docker-entrypoint.sh
The option is supported anymore in falcoctl

Signed-off-by: Paul Rey <contact@paulrey.io>
2024-03-22 13:45:53 +01:00
Paul Rey
858c82ffe0 Update driver-loader docker-entrypoint
Remove debug log
Set default option ENABLE_COMPILE and ENABLE_DOWNLOAD

Signed-off-by: Paul Rey <contact@paulrey.io>
2024-03-22 13:45:53 +01:00
Paul Rey
2f6fdfa972 Add kernelversion and kernelrelease options to falco driver loader entrypoint
Signed-off-by: Paul Rey <contact@paulrey.io>
2024-03-22 13:45:53 +01:00
dependabot[bot]
2dfac14cd1 build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `44addef` to `fbf0a4e`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](44addef4f7...fbf0a4e8ce)

---
updated-dependencies:
- dependency-name: submodules/falcosecurity-rules
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-15 09:41:27 +01:00
Federico Di Pierro
5fe9fc9d89 update(cmake): bumped libs and driver to 0.15.0-rc1.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-03-14 10:55:24 +01:00
Melissa Kilby
3b7b3439ec cleanup(metrics): fix build for non linux
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-03-14 10:55:24 +01:00
Melissa Kilby
7762d0cd84 chore: bump libs
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-03-14 10:55:24 +01:00
Melissa Kilby
09d813b22d feat(metrics): sync libs metrics collector refactor
Includes a handful of naming changes. A notice to
https://falco.org/docs/metrics/falco-metrics/ will be added well
in advance of Falco 0.38.0

falco.hostname -> evt.hostname to be consistent with the newer evt.hostname filtercheck
cpu_usage_perc_total_host -> host_cpu_usage_perc
memory_used_host -> host_memory_used_kb (or host_memory_used_mb)
procs_running_host -> host_procs_running
open_fds_host -> host_open_fds

memory_rss -> memory_rss_kb (or memory_rss_mb)
memory_pss -> memory_pss_kb (or memory_pss_mb)
memory_vsz -> memory_vsz_kb (or memory_vsz_mb)
container_memory_used -> container_memory_used_bytes (or container_memory_used_mb)

Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-03-14 10:55:24 +01:00
Andrea Terzolo
3395e604b6 ci: use ubuntu-22.04 with codeQL job
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2024-03-12 16:29:17 +01:00
Andrea Terzolo
0ce2b95b89 chore: bump falco engine version
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2024-03-12 16:29:17 +01:00
Andrea Terzolo
c5bb2b68e2 chore: bump to latest libs commit
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2024-03-12 16:29:17 +01:00
Federico Aponte
8dbec6c779 refactor: Use FetchContent for integrating bundled yaml-cpp lib
Signed-off-by: Federico Aponte <federico.aponte@sysdig.com>
2024-03-11 13:57:15 +01:00
Federico Aponte
c32b7c1246 refactor: Use FetchContent for integrating bundled cpp-httplib
Signed-off-by: Federico Aponte <federico.aponte@sysdig.com>
2024-03-11 13:57:15 +01:00
Federico Aponte
bc499e191d refactor: Use FetchContent for integrating bundled nlohman-json lib
Signed-off-by: Federico Aponte <federico.aponte@sysdig.com>
2024-03-11 13:57:15 +01:00
dependabot[bot]
ea187d3b45 build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `dc7970d` to `44addef`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](dc7970d175...44addef4f7)

---
updated-dependencies:
- dependency-name: submodules/falcosecurity-rules
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-11 09:38:14 +01:00
Gianmatteo Palmieri
517b79ee13 chore(engine): bump engine version
Signed-off-by: Gianmatteo Palmieri <mail@gian.im>
2024-03-08 00:02:01 +01:00
Gianmatteo Palmieri
3d4be156cc new(tests): add unit test for invalid macro/list name
Signed-off-by: Gianmatteo Palmieri <mail@gian.im>
2024-03-08 00:02:01 +01:00
Gianmatteo Palmieri
7265190e66 new(engine): don't expose details in error message
Signed-off-by: Gianmatteo Palmieri <mail@gian.im>
2024-03-08 00:02:01 +01:00
Gianmatteo Palmieri
f00926b8af new(engine): error on invalid macro/list name
Signed-off-by: Gianmatteo Palmieri <mail@gian.im>
2024-03-08 00:02:01 +01:00
dependabot[bot]
a473ae5eb8 build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `f88b991` to `dc7970d`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](f88b991a7f...dc7970d175)

---
updated-dependencies:
- dependency-name: submodules/falcosecurity-rules
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-07 11:39:58 +01:00
Federico Aponte
3954ff233b refactor(ci): Avoid using command make directly
Signed-off-by: Federico Aponte <federico.aponte@sysdig.com>
2024-03-07 11:37:58 +01:00
Leonardo Grasso
a5297c4f29 docs(proposals/20231220-features-adoption-and-deprecation): general revision
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2024-03-06 14:34:55 +01:00
Leonardo Grasso
eb35ea7dfe docs(proposals/20231220-features-adoption-and-deprecation): add Platform support area
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2024-03-06 14:34:55 +01:00
Leonardo Grasso
63ccf872fd Update proposals/20231220-features-adoption-and-deprecation.md
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2024-03-06 14:34:55 +01:00
Leonardo Grasso
3bdb98a46b Update proposals/20231220-features-adoption-and-deprecation.md
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2024-03-06 14:34:55 +01:00
Leonardo Grasso
c68ef54bb2 docs(proposals/20231220-features-adoption-and-deprecation): remove feature gates, simplify policies and transition phases
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2024-03-06 14:34:55 +01:00
Leonardo Grasso
865553dbe3 docs(proposals/20231220-features-adoption-and-deprecation): only stable features deprecation require a major bump
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2024-03-06 14:34:55 +01:00
Leonardo Grasso
10a9c1d774 docs(proposal): 20231220-features-adoption-and-deprecation.md
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2024-03-06 14:34:55 +01:00
Aldo Lacuku
185075bfd8 update(scrips/falcoctl): bump falco-rules version to 3
Signed-off-by: Aldo Lacuku <aldo@lacuku.eu>
2024-03-06 07:35:54 +01:00
Melissa Kilby
5185f152c5 new(config): add falco_libs.thread_table_size
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-03-05 11:36:51 +01:00
Samuel Gaist
8f87b117c4 fix(userspace): correct directory iteration options
The original code was using follow_directory_symlink twice, this patch
fixes that.

Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-03-05 10:29:51 +01:00
dependabot[bot]
5084a62dd1 build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `b499a1d` to `f88b991`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](b499a1d0d0...f88b991a7f)

---
updated-dependencies:
- dependency-name: submodules/falcosecurity-rules
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-01 12:05:36 +01:00
Leonardo Grasso
ca4db17e05 docs(README.md): Falco Graduates within the CNCF
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2024-02-29 16:41:33 +01:00
Samuel Gaist
f9b17b67f8 refactor(engine): fix variable / function shadowing
Improve variable names in the code surrounding the changes.

Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-02-29 16:20:34 +01:00
Samuel Gaist
8a7361c8ab refactor(app): fix variable / function shadowing
Improve variable names in the code surrounding the changes.

Signed-off-by: Samuel Gaist <samuel.gaist@idiap.ch>
2024-02-29 16:20:34 +01:00
dependabot[bot]
2589bd0c0b build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `497e011` to `b499a1d`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](497e01189e...b499a1d0d0)

---
updated-dependencies:
- dependency-name: submodules/falcosecurity-rules
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-28 11:16:27 +01:00
Gianmatteo Palmieri
928cb8bb8e new(tests): add unit test for exceptions condition
Signed-off-by: Gianmatteo Palmieri <mail@gian.im>
2024-02-28 08:28:26 +01:00
Gianmatteo Palmieri
ea781477d6 fix(engine): logical issue in exceptions condition
Signed-off-by: Gianmatteo Palmieri <mail@gian.im>
2024-02-28 08:28:26 +01:00
Federico Di Pierro
f6818902de fix(ci): properly enforce bundled deps off in build-dev, like it was before https://github.com/falcosecurity/falco/pull/3092.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-02-27 11:07:25 +01:00
Federico Di Pierro
5ebc7bbd7c chore(ci): bumped codeql actions.
Moveover, to avoid spending too much time (and space) on the job, build without bundled deps.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-02-26 17:55:21 +01:00
Federico Aponte
f6af72fe76 cleanup: too many includes and useless defines
Signed-off-by: Federico Aponte <federico.aponte@sysdig.com>
2024-02-26 14:59:22 +01:00
Federico Aponte
4d66a50d5b fix: pessimizing move warning
Signed-off-by: Federico Aponte <federico.aponte@sysdig.com>
2024-02-26 14:59:22 +01:00
Federico Aponte
59c14f46a2 refactor: shared_ptr construction
Signed-off-by: Federico Aponte <federico.aponte@sysdig.com>
2024-02-26 14:59:22 +01:00
Federico Aponte
557929a82a refactor: use object rather than unique_ptr
Signed-off-by: Federico Aponte <federico.aponte@sysdig.com>
2024-02-26 14:59:22 +01:00
Federico Aponte
9a2b58c6f7 refactor: very minor improvement
Signed-off-by: Federico Aponte <federico.aponte@sysdig.com>
2024-02-26 14:59:22 +01:00
116 changed files with 3747 additions and 1258 deletions

View File

@@ -16,12 +16,22 @@ jobs:
fetch-version:
uses: ./.github/workflows/reusable_fetch_version.yaml
build-dev-packages:
build-dev-packages-sanitizers-x86_64:
needs: [fetch-version]
uses: ./.github/workflows/reusable_build_packages.yaml
with:
arch: x86_64
version: ${{ needs.fetch-version.outputs.version }}
build_type: Debug
sanitizers: true
build-dev-packages-x86_64:
needs: [fetch-version]
uses: ./.github/workflows/reusable_build_packages.yaml
with:
arch: x86_64
version: ${{ needs.fetch-version.outputs.version }}
build_type: Release
build-dev-packages-arm64:
needs: [fetch-version]
@@ -29,9 +39,11 @@ jobs:
with:
arch: aarch64
version: ${{ needs.fetch-version.outputs.version }}
build_type: Debug
sanitizers: false
test-dev-packages:
needs: [fetch-version, build-dev-packages]
needs: [fetch-version, build-dev-packages-sanitizers-x86_64]
uses: ./.github/workflows/reusable_test_packages.yaml
# The musl build job is currently disabled because we link libelf dynamically and it is
# not possible to dynamically link with musl
@@ -41,6 +53,7 @@ jobs:
# static: ["static", ""]
with:
arch: x86_64
sanitizers: true
# static: ${{ matrix.static != '' && true || false }}
version: ${{ needs.fetch-version.outputs.version }}
@@ -82,6 +95,7 @@ jobs:
arch: x86_64
git_ref: ${{ github.event.pull_request.head.sha }}
minimal: false
sanitizers: true
build_type: Debug
cmd: "echo $(build/userspace/falco/falco -c ./falco.yaml --version | grep 'Engine:' | awk '{print $2}') $(echo $(build/userspace/falco/falco -c ./falco.yaml --version | grep 'Schema version:' | awk '{print $3}') $(build/userspace/falco/falco -c ./falco.yaml --list --markdown | grep '^`' | sort) $(build/userspace/falco/falco -c ./falco.yaml --list-events | sort) | sha256sum)"

View File

@@ -21,7 +21,7 @@ on:
jobs:
analyze:
name: Analyze
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
permissions:
actions: read
contents: read
@@ -42,7 +42,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9
uses: github/codeql-action/init@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -60,16 +60,11 @@ jobs:
- name: Prepare project
run: |
mkdir build
pushd build
cmake -DBUILD_BPF=On ..
popd
cmake -B build -S . -DBUILD_BPF=On -DBUILD_FALCO_MODERN_BPF=Off -DUSE_BUNDLED_DEPS=Off -DUSE_BUNDLED_NLOHMANN_JSON=On -DUSE_BUNDLED_CXXOPTS=On -DUSE_BUNDLED_CPPHTTPLIB=On
- name: Build
run: |
pushd build
KERNELDIR=/lib/modules/$(uname -r)/build make -j4 all
popd
KERNELDIR=/lib/modules/$(uname -r)/build cmake --build build -j4
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9
uses: github/codeql-action/analyze@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5

View File

@@ -14,6 +14,11 @@ on:
description: Minimal build
required: true
type: boolean
sanitizers:
description: Enable sanitizer support
required: false
default: false
type: boolean
build_type:
description: One of 'Debug' or 'Release'
required: true
@@ -53,22 +58,23 @@ jobs:
- name: Prepare project
run: |
mkdir build
pushd build
cmake \
cmake -B build -S .\
-DBUILD_FALCO_UNIT_TESTS=On \
-DCMAKE_BUILD_TYPE=${{ inputs.build_type }} \
-DBUILD_FALCO_MODERN_BPF=Off \
-DBUILD_BPF=${{ inputs.minimal == true && 'OFF' || 'ON' }} \
-DBUILD_DRIVER=${{ inputs.minimal == true && 'OFF' || 'ON' }} \
-DMINIMAL_BUILD=${{ inputs.minimal == true && 'ON' || 'OFF' }} \
..
popd
-DUSE_ASAN=${{ inputs.sanitizers == true && 'ON' || 'OFF' }} \
-DUSE_UBSAN=${{ inputs.sanitizers == true && 'ON' || 'OFF' }} \
-DUSE_BUNDLED_DEPS=Off \
-DUSE_BUNDLED_NLOHMANN_JSON=On \
-DUSE_BUNDLED_CXXOPTS=On \
-DUSE_BUNDLED_CPPHTTPLIB=On \
- name: Build
run: |
pushd build
KERNELDIR=/lib/modules/$(uname -r)/build make -j4 all
popd
KERNELDIR=/lib/modules/$(uname -r)/build cmake --build build -j4
- name: Run unit tests
run: |

View File

@@ -10,6 +10,16 @@ on:
description: The Falco version to use when building packages
required: true
type: string
build_type:
description: The build type
required: false
type: string
default: 'Release'
sanitizers:
description: enable sanitizer support
required: false
type: boolean
default: false
jobs:
build-modern-bpf-skeleton:
@@ -21,109 +31,124 @@ jobs:
- name: Install build dependencies
run: |
dnf install -y bpftool ca-certificates cmake make automake gcc gcc-c++ kernel-devel clang git pkg-config autoconf automake libbpf-devel elfutils-libelf-devel
- name: Checkout
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- name: Build modern BPF skeleton
run: |
mkdir skeleton-build && cd skeleton-build
cmake -DUSE_BUNDLED_DEPS=ON -DBUILD_FALCO_MODERN_BPF=ON -DCREATE_TEST_TARGETS=Off -DFALCO_VERSION=${{ inputs.version }} ..
make ProbeSkeleton -j6
cmake -B skeleton-build -S . \
-DUSE_BUNDLED_DEPS=ON -DCREATE_TEST_TARGETS=Off -DFALCO_VERSION=${{ inputs.version }}
cmake --build skeleton-build --target ProbeSkeleton -j6
- name: Upload skeleton
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: bpf_probe_${{ inputs.arch }}.skel.h
path: skeleton-build/skel_dir/bpf_probe.skel.h
retention-days: 1
build-packages:
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' }}
needs: [build-modern-bpf-skeleton]
container: centos:7
steps:
# Always install deps before invoking checkout action, to properly perform a full clone.
- name: Install build dependencies
- name: Fix mirrors to use vault.centos.org
run: |
sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo
sed -i s/^#.*baseurl=http/baseurl=https/g /etc/yum.repos.d/*.repo
sed -i s/^mirrorlist=http/#mirrorlist=https/g /etc/yum.repos.d/*.repo
- name: Install scl repos
run: |
yum -y install centos-release-scl
- name: Fix new mirrors to use vault.centos.org
run: |
sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo
sed -i s/^#.*baseurl=http/baseurl=https/g /etc/yum.repos.d/*.repo
sed -i s/^mirrorlist=http/#mirrorlist=https/g /etc/yum.repos.d/*.repo
- name: Fix arm64 scl repos to use correct mirror
if: inputs.arch == 'aarch64'
run: |
sed -i 's/vault.centos.org\/centos/vault.centos.org\/altarch/g' /etc/yum.repos.d/CentOS-SCLo-scl*.repo
- name: Install build deps
run: |
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++
source /opt/rh/devtoolset-9/enable
yum install -y wget git make m4 rpm-build elfutils-libelf-devel perl-IPC-Cmd
yum install -y wget git make m4 rpm-build elfutils-libelf-devel perl-IPC-Cmd devtoolset-9-libasan-devel devtoolset-9-libubsan-devel
- name: Checkout
# It is not possible to upgrade the checkout action to versions >= v4.0.0 because of incompatibilities with centos 7's libc.
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- name: Download skeleton
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
with:
name: bpf_probe_${{ inputs.arch }}.skel.h
path: /tmp
- name: Install updated cmake
run: |
curl -L -o /tmp/cmake.tar.gz https://github.com/Kitware/CMake/releases/download/v3.22.5/cmake-3.22.5-linux-$(uname -m).tar.gz
gzip -d /tmp/cmake.tar.gz
tar -xpf /tmp/cmake.tar --directory=/tmp
cp -R /tmp/cmake-3.22.5-linux-$(uname -m)/* /usr
rm -rf /tmp/cmake-3.22.5-linux-$(uname -m)
curl -L https://github.com/Kitware/CMake/releases/download/v3.22.5/cmake-3.22.5-linux-$(uname -m).tar.gz \
| tar --directory=/usr --strip-components=1 -xzp
- name: Prepare project
run: |
mkdir build && cd build
source /opt/rh/devtoolset-9/enable
cmake \
-DCMAKE_BUILD_TYPE=Release \
cmake -B build -S . \
-DCMAKE_BUILD_TYPE=${{ inputs.build_type }} \
-DUSE_BUNDLED_DEPS=On \
-DFALCO_ETC_DIR=/etc/falco \
-DBUILD_FALCO_MODERN_BPF=ON \
-DMODERN_BPF_SKEL_DIR=/tmp \
-DBUILD_DRIVER=Off \
-DBUILD_BPF=Off \
-DFALCO_VERSION=${{ inputs.version }} \
..
-DUSE_ASAN=${{ (inputs.sanitizers == true && inputs.arch == 'x86_64' && 'ON') || 'OFF' }} \
-DFALCO_VERSION=${{ inputs.version }}
- name: Build project
run: |
cd build
source /opt/rh/devtoolset-9/enable
make falco -j6
cmake --build build --target falco -j6
- name: Build packages
run: |
cd build
source /opt/rh/devtoolset-9/enable
make package
cmake --build build --target package
- name: Upload Falco tar.gz package
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: falco-${{ inputs.version }}-${{ inputs.arch }}.tar.gz
name: falco-${{ inputs.version }}-${{ inputs.arch }}${{ inputs.sanitizers == true && '-sanitizers' || '' }}.tar.gz
path: |
${{ github.workspace }}/build/falco-*.tar.gz
- name: Upload Falco deb package
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: falco-${{ inputs.version }}-${{ inputs.arch }}.deb
name: falco-${{ inputs.version }}-${{ inputs.arch }}${{ inputs.sanitizers == true && '-sanitizers' || '' }}.deb
path: |
${{ github.workspace }}/build/falco-*.deb
- name: Upload Falco rpm package
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: falco-${{ inputs.version }}-${{ inputs.arch }}.rpm
name: falco-${{ inputs.version }}-${{ inputs.arch }}${{ inputs.sanitizers == true && '-sanitizers' || '' }}.rpm
path: |
${{ github.workspace }}/build/falco-*.rpm
# The musl build job is currently disabled because we link libelf dynamically and it is
# not possible to dynamically link with musl
build-musl-package:
# x86_64 only for now
# if: ${{ inputs.arch == 'x86_64' }}
if: false
if: false
runs-on: ubuntu-latest
container: alpine:3.17
steps:
@@ -131,32 +156,33 @@ jobs:
- name: Install build dependencies
run: |
apk add g++ gcc cmake make git bash perl linux-headers autoconf automake m4 libtool elfutils-dev libelf-static patch binutils bpftool clang
- name: Checkout
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
with:
fetch-depth: 0
- name: Prepare project
run: |
mkdir build && cd build
cmake -DCPACK_GENERATOR=TGZ -DBUILD_BPF=Off -DBUILD_DRIVER=Off -DCMAKE_BUILD_TYPE=Release -DUSE_BUNDLED_DEPS=On -DUSE_BUNDLED_LIBELF=Off -DBUILD_LIBSCAP_MODERN_BPF=ON -DMUSL_OPTIMIZED_BUILD=On -DFALCO_ETC_DIR=/etc/falco ../ -DFALCO_VERSION=${{ inputs.version }}
cmake -B build -S . \
-DCMAKE_BUILD_TYPE=${{ inputs.build_type }} \
-DCPACK_GENERATOR=TGZ \
-DBUILD_BPF=Off -DBUILD_DRIVER=Off \
-DUSE_BUNDLED_DEPS=On -DUSE_BUNDLED_LIBELF=Off -DBUILD_LIBSCAP_MODERN_BPF=ON -DMUSL_OPTIMIZED_BUILD=On -DFALCO_ETC_DIR=/etc/falco -DFALCO_VERSION=${{ inputs.version }}
- name: Build project
run: |
cd build
make -j6 all
cmake --build build -j6
- name: Build packages
run: |
cd build
make -j6 package
cmake --build build -j6 --target package
- name: Rename static package
run: |
cd build
mv falco-${{ inputs.version }}-x86_64.tar.gz falco-${{ inputs.version }}-static-x86_64.tar.gz
mv falco-${{ inputs.version }}-x86_64.tar.gz falco-${{ inputs.version }}-static-x86_64.tar.gz
- name: Upload Falco static package
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
@@ -178,41 +204,39 @@ jobs:
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1
with:
node-version: 14
- name: Checkout
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
with:
fetch-depth: 0
- name: Prepare project
run: |
mkdir build && cd build
emcmake cmake \
emcmake cmake -B build -S . \
-DBUILD_BPF=Off \
-DBUILD_DRIVER=Off \
-DBUILD_LIBSCAP_MODERN_BPF=OFF \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_FALCO_MODERN_BPF=Off \
-DCMAKE_BUILD_TYPE=${{ inputs.build_type }} \
-DUSE_BUNDLED_DEPS=On \
-DFALCO_ETC_DIR=/etc/falco \
-DBUILD_FALCO_UNIT_TESTS=On \
-DFALCO_VERSION=${{ inputs.version }} \
..
-DFALCO_VERSION=${{ inputs.version }}
- name: Build project
run: |
cd build
emmake make -j6 all
- name: Run unit Tests
run: |
cd build
node ./unit_tests/falco_unit_tests.js
- name: Build packages
run: |
cd build
emmake make -j6 package
- name: Upload Falco WASM package
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
@@ -229,19 +253,18 @@ jobs:
with:
fetch-depth: 0
# NOTE: Backslash doesn't work as line continuation on Windows.
- name: Prepare project
run: |
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DMINIMAL_BUILD=On -DUSE_BUNDLED_DEPS=On -DBUILD_FALCO_UNIT_TESTS=On -DFALCO_VERSION=${{ inputs.version }} ..
cmake -B build -S . -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DMINIMAL_BUILD=On -DUSE_BUNDLED_DEPS=On -DBUILD_FALCO_UNIT_TESTS=On -DFALCO_VERSION=${{ inputs.version }}
- name: Build project
run: |
cmake --build build --target package --config Release
cmake --build build --target package --config ${{ inputs.build_type }}
- name: Run unit Tests
run: |
build/unit_tests/Release/falco_unit_tests.exe
build/unit_tests/${{ inputs.build_type }}/falco_unit_tests.exe
- name: Upload Falco win32 installer
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
@@ -254,7 +277,7 @@ jobs:
with:
name: falco-${{ inputs.version }}-win32.exe
path: |
${{ github.workspace }}/build/userspace/falco/Release/falco.exe
${{ github.workspace }}/build/userspace/falco/${{ inputs.build_type }}/falco.exe
build-macos-package:
if: ${{ inputs.arch == 'x86_64' }}
@@ -267,9 +290,8 @@ jobs:
- name: Prepare project
run: |
mkdir build
cd build
cmake -DMINIMAL_BUILD=On -DUSE_BUNDLED_DEPS=On -DBUILD_FALCO_UNIT_TESTS=On -DFALCO_VERSION=${{ inputs.version }} ..
cmake -B build -S . \
-DMINIMAL_BUILD=On -DUSE_BUNDLED_DEPS=On -DBUILD_FALCO_UNIT_TESTS=On -DFALCO_VERSION=${{ inputs.version }}
- name: Build project
run: |

View File

@@ -5,34 +5,33 @@ on:
version:
description: "Falco version"
value: ${{ jobs.fetch-version.outputs.version }}
jobs:
# We need to use an ubuntu-latest to fetch Falco version because
# Falco version is computed by some cmake scripts that do git sorceries
# to get the current version.
# But centos7 jobs have a git version too old and actions/checkout does not
# But centos7 jobs have a git version too old and actions/checkout does not
# fully clone the repo, but uses http rest api instead.
fetch-version:
runs-on: ubuntu-latest
# Map the job outputs to step outputs
outputs:
version: ${{ steps.store_version.outputs.version }}
version: ${{ steps.store_version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
with:
fetch-depth: 0
- name: Install build dependencies
run: |
sudo apt update
sudo apt update
sudo apt install -y cmake build-essential
- name: Configure project
run: |
mkdir build && cd build
cmake -DUSE_BUNDLED_DEPS=On -DUSE_DYNAMIC_LIBELF=Off ..
cmake -B build -S . -DUSE_BUNDLED_DEPS=On -DUSE_DYNAMIC_LIBELF=Off
- name: Load and store Falco version output
id: store_version
run: |

View File

@@ -152,9 +152,7 @@ jobs:
- name: Setup Cosign
if: inputs.sign
uses: sigstore/cosign-installer@11086d25041f77fe8fe7b9ea4e48e3b9192b8f19 # v3.1.2
with:
cosign-release: v2.0.2
uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0
- name: Sign images with cosign
if: inputs.sign

View File

@@ -15,6 +15,11 @@ on:
description: The Falco version to use when testing packages
required: true
type: string
sanitizers:
description: Use sanitizer enabled build
required: false
default: false
type: boolean
jobs:
test-packages:
@@ -24,7 +29,7 @@ jobs:
- name: Download binary
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
with:
name: falco-${{ inputs.version }}${{ inputs.static && '-static' || '' }}-${{ inputs.arch }}.tar.gz
name: falco-${{ inputs.version }}${{ inputs.static && '-static' || '' }}-${{ inputs.arch }}${{ inputs.sanitizers == true && '-sanitizers' || '' }}.tar.gz
- name: Install Falco package
run: |
@@ -39,8 +44,16 @@ jobs:
run: |
sudo apt update -y
sudo apt install -y --no-install-recommends linux-headers-$(uname -r)
# Some builds use sanitizers, we always install support for them so they can run
- name: Install sanitizer support
run: |
sudo apt update -y
sudo apt install -y libasan5 libubsan1
- name: Run tests
env:
LSAN_OPTIONS: "intercept_tls_get_addr=0"
uses: falcosecurity/testing@main
with:
test-falco: 'true'

View File

@@ -43,7 +43,7 @@ jobs:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@e38b1902ae4f44df626f11ba0734b14fb91f8f86 # v2.1.2
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
with:
results_file: results.sarif
results_format: sarif

View File

@@ -19,10 +19,11 @@ jobs:
- name: Build and run cppcheck 🏎️
run: |
mkdir build
cd build && cmake -DUSE_BUNDLED_DEPS=On -DUSE_DYNAMIC_LIBELF=Off -DBUILD_WARNINGS_AS_ERRORS=ON -DCREATE_TEST_TARGETS=Off -DCMAKE_BUILD_TYPE="release" -DBUILD_BPF=Off -DBUILD_DRIVER=Off ..
make -j4 cppcheck
make -j4 cppcheck_htmlreport
cmake -B build -S . \
-DCMAKE_BUILD_TYPE="release" \
-DUSE_BUNDLED_DEPS=On -DUSE_DYNAMIC_LIBELF=Off -DBUILD_WARNINGS_AS_ERRORS=ON -DCREATE_TEST_TARGETS=Off -DBUILD_BPF=Off -DBUILD_DRIVER=Off
cmake --build build -j4 --target cppcheck
cmake --build build -j4 --target cppcheck_htmlreport
- name: Upload reports ⬆️
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3

View File

@@ -1,5 +1,181 @@
# Change Log
## v0.38.2
Released on 2024-08-19
### Bug Fixes
* fix(engine): fix metrics names to better adhere to best practices [[#3272](https://github.com/falcosecurity/falco/pull/3272)] - [@incertum](https://github.com/incertum)
* fix(ci): use vault.centos.org for centos:7 CI build. [[#3274](https://github.com/falcosecurity/falco/pull/3274)] - [@FedeDP](https://github.com/FedeDP)
## v0.38.1
Released on 2024-06-19
### Major Changes
* new(metrics): enable plugins metrics [[#3228](https://github.com/falcosecurity/falco/pull/3228)] - [@mrgian](https://github.com/mrgian)
### Minor Changes
* cleanup(falco): clarify that --print variants only affect syscalls [[#3238](https://github.com/falcosecurity/falco/pull/3238)] - [@LucaGuerra](https://github.com/LucaGuerra)
* update(engine): enable -p option for all sources, -pk, -pc etc only for syscall sources [[#3239](https://github.com/falcosecurity/falco/pull/3239)] - [@LucaGuerra](https://github.com/LucaGuerra)
### Bug Fixes
* fix(engine): enable output substitution only for syscall rules, prevent engine from exiting with validation errors when a plugin is loaded and -pc/pk is specified [[#3236](https://github.com/falcosecurity/falco/pull/3236)] - [@mrgian](https://github.com/mrgian)
* fix(metrics): allow each metric output channel to be selected independently [[#3232](https://github.com/falcosecurity/falco/pull/3232)] - [@incertum](https://github.com/incertum)
* fix(userspace/falco): fixed `falco_metrics::to_text` implementation when running with plugins [[#3230](https://github.com/falcosecurity/falco/pull/3230)] - [@FedeDP](https://github.com/FedeDP)
### Statistics
| MERGED PRS | NUMBER |
|-----------------|--------|
| Not user-facing | 0 |
| Release note | 6 |
| Total | 6 |
## v0.38.0
Released on 2024-05-30
### Breaking Changes :warning:
* new(scripts,docker)!: enable automatic driver selection logic in packages and docker images. Modern eBPF is now also the default driver and the highest priority one in the new driver selection logic. [[#3154](https://github.com/falcosecurity/falco/pull/3154)] - [@FedeDP](https://github.com/FedeDP)
* cleanup(falco.yaml)!: remove some deprecated configs [[#3087](https://github.com/falcosecurity/falco/pull/3087)] - [@Andreagit97](https://github.com/Andreagit97)
* cleanup(docker)!: remove unused builder dockerfile [[#3088](https://github.com/falcosecurity/falco/pull/3088)] - [@Andreagit97](https://github.com/Andreagit97)
More details: https://falco.org/blog/falco-0-38-0/#breaking-changes-and-deprecations
### Major Changes
* new(webserver): a metrics endpoint has been added providing prometheus metrics. It can be optionally enabled using the new `metrics.prometheus_enabled` configuration option. It will only be activated if the `metrics.enabled` is true as well. [[#3140](https://github.com/falcosecurity/falco/pull/3140)] - [@sgaist](https://github.com/sgaist)
* new(metrics): add `rules_counters_enabled` option [[#3192](https://github.com/falcosecurity/falco/pull/3192)] - [@incertum](https://github.com/incertum)
* new(build): provide signatures for .tar.gz packages [[#3201](https://github.com/falcosecurity/falco/pull/3201)] - [@LucaGuerra](https://github.com/LucaGuerra)
* new(engine): add print_enabled_rules_falco_logger when log_level debug [[#3189](https://github.com/falcosecurity/falco/pull/3189)] - [@incertum](https://github.com/incertum)
* new(falco): allow selecting which rules to load from the configuration file or command line [[#3178](https://github.com/falcosecurity/falco/pull/3178)] - [@LucaGuerra](https://github.com/LucaGuerra)
* new(metrics): add file sha256sum metrics for loaded config and rules files [[#3187](https://github.com/falcosecurity/falco/pull/3187)] - [@incertum](https://github.com/incertum)
* new(engine): throw an error when an invalid macro/list name is used [[#3116](https://github.com/falcosecurity/falco/pull/3116)] - [@mrgian](https://github.com/mrgian)
* new(engine): raise warning instead of error on invalid macro/list name [[#3167](https://github.com/falcosecurity/falco/pull/3167)] - [@mrgian](https://github.com/mrgian)
* new(userspace): support split config files [[#3024](https://github.com/falcosecurity/falco/pull/3024)] - [@FedeDP](https://github.com/FedeDP)
* new(engine): enforce unique exceptions names [[#3134](https://github.com/falcosecurity/falco/pull/3134)] - [@mrgian](https://github.com/mrgian)
* new(engine): add warning when appending an exception with no values [[#3133](https://github.com/falcosecurity/falco/pull/3133)] - [@mrgian](https://github.com/mrgian)
* feat(metrics): coherent metrics stats model including few metrics naming changes [[#3129](https://github.com/falcosecurity/falco/pull/3129)] - [@incertum](https://github.com/incertum)
* new(config): add `falco_libs.thread_table_size` [[#3071](https://github.com/falcosecurity/falco/pull/3071)] - [@incertum](https://github.com/incertum)
* new(proposals): introduce on host anomaly detection framework [[#2655](https://github.com/falcosecurity/falco/pull/2655)] - [@incertum](https://github.com/incertum)
### Minor Changes
* update(cmake): bump falcoctl to v0.8.0. [[#3219](https://github.com/falcosecurity/falco/pull/3219)] - [@FedeDP](https://github.com/FedeDP)
* update(rules): update falco-rules to 3.1.0 [[#3217](https://github.com/falcosecurity/falco/pull/3217)] - [@LucaGuerra](https://github.com/LucaGuerra)
* refactor(userspace): move falco logger under falco engine [[#3208](https://github.com/falcosecurity/falco/pull/3208)] - [@jasondellaluce](https://github.com/jasondellaluce)
* chore(docs): apply features adoption and deprecation proposal to config file keys [[#3206](https://github.com/falcosecurity/falco/pull/3206)] - [@FedeDP](https://github.com/FedeDP)
* cleanup(metrics): add original rule name as label [[#3205](https://github.com/falcosecurity/falco/pull/3205)] - [@incertum](https://github.com/incertum)
* update(falco): deprecate options -T, -t and -D [[#3193](https://github.com/falcosecurity/falco/pull/3193)] - [@LucaGuerra](https://github.com/LucaGuerra)
* refactor: bump libs and driver, support field modifiers [[#3186](https://github.com/falcosecurity/falco/pull/3186)] - [@jasondellaluce](https://github.com/jasondellaluce)
* chore(userspace/falco): deprecated old 'rules_file' config key [[#3162](https://github.com/falcosecurity/falco/pull/3162)] - [@FedeDP](https://github.com/FedeDP)
* chore(falco): update falco libs and driver to master (Apr 8th 2024) [[#3158](https://github.com/falcosecurity/falco/pull/3158)] - [@LucaGuerra](https://github.com/LucaGuerra)
* update(build): update libs to 026ffe1d8f1b25c6ccdc09afa2c02afdd3e3f672 [[#3151](https://github.com/falcosecurity/falco/pull/3151)] - [@LucaGuerra](https://github.com/LucaGuerra)
* cleanup: minor adjustments to readme, add new testing section [[#3072](https://github.com/falcosecurity/falco/pull/3072)] - [@incertum](https://github.com/incertum)
* refactor(userspace/engine): reduce allocations during rules loading [[#3065](https://github.com/falcosecurity/falco/pull/3065)] - [@jasondellaluce](https://github.com/jasondellaluce)
* update(CI): publish wasm package as dev-wasm [[#3017](https://github.com/falcosecurity/falco/pull/3017)] - [@Rohith-Raju](https://github.com/Rohith-Raju)
### Bug Fixes
* fix(userspace/falco): fix state initialization avoid a crash during hot reload [[#3190](https://github.com/falcosecurity/falco/pull/3190)] - [@FedeDP](https://github.com/FedeDP)
* fix(userspace/engine): make sure exception fields are not optional in replace mode [[#3108](https://github.com/falcosecurity/falco/pull/3108)] - [@jasondellaluce](https://github.com/jasondellaluce)
* fix(docker): added zstd to driver loader images [[#3203](https://github.com/falcosecurity/falco/pull/3203)] - [@FedeDP](https://github.com/FedeDP)
* fix(engine): raise warning instead of error on not-unique exceptions names [[#3159](https://github.com/falcosecurity/falco/pull/3159)] - [@mrgian](https://github.com/mrgian)
* fix(engine): apply output substitutions for all sources [[#3135](https://github.com/falcosecurity/falco/pull/3135)] - [@mrgian](https://github.com/mrgian)
* fix(userspace/configuration): make sure that folders that would trigger permission denied are not traversed [[#3127](https://github.com/falcosecurity/falco/pull/3127)] - [@sgaist](https://github.com/sgaist)
* fix(engine): logical issue in exceptions condition [[#3115](https://github.com/falcosecurity/falco/pull/3115)] - [@mrgian](https://github.com/mrgian)
* fix(cmake): properly let falcoctl cmake module create /usr/share/falco/plugins/ folder. [[#3105](https://github.com/falcosecurity/falco/pull/3105)] - [@FedeDP](https://github.com/FedeDP)
### Non user-facing changes
* update(scripts/falcoctl): bump falco-rules version to 3 [[#3128](https://github.com/falcosecurity/falco/pull/3128)] - [@alacuku](https://github.com/alacuku)
* build(deps): Bump submodules/falcosecurity-rules from `59bf03b` to `9e56293` [[#3212](https://github.com/falcosecurity/falco/pull/3212)] - [@dependabot[bot]](https://github.com/apps/dependabot)
* chore(gha): update cosign to v3.5.0 [[#3209](https://github.com/falcosecurity/falco/pull/3209)] - [@LucaGuerra](https://github.com/LucaGuerra)
* build(deps): Bump submodules/falcosecurity-rules from `29c41c4` to `59bf03b` [[#3207](https://github.com/falcosecurity/falco/pull/3207)] - [@dependabot[bot]](https://github.com/apps/dependabot)
* update(cmake): bumped libs to 0.17.0-rc1 and falcoctl to v0.8.0-rc6. [[#3204](https://github.com/falcosecurity/falco/pull/3204)] - [@FedeDP](https://github.com/FedeDP)
* build(deps): Bump submodules/falcosecurity-rules from `3f668d0` to `3cac61c` [[#3044](https://github.com/falcosecurity/falco/pull/3044)] - [@dependabot[bot]](https://github.com/apps/dependabot)
* build(deps): Bump submodules/falcosecurity-testing from `ae3950a` to `7abf76f` [[#3094](https://github.com/falcosecurity/falco/pull/3094)] - [@dependabot[bot]](https://github.com/apps/dependabot)
* fix(ci): enforce bundled deps OFF in build-dev CI [[#3118](https://github.com/falcosecurity/falco/pull/3118)] - [@FedeDP](https://github.com/FedeDP)
* build(deps): Bump submodules/falcosecurity-rules from `88a40c8` to `869c9a7` [[#3156](https://github.com/falcosecurity/falco/pull/3156)] - [@dependabot[bot]](https://github.com/apps/dependabot)
* update(cmake): bumped falcoctl to v0.8.0-rc5. [[#3199](https://github.com/falcosecurity/falco/pull/3199)] - [@FedeDP](https://github.com/FedeDP)
* build(deps): Bump submodules/falcosecurity-rules from `4f153f5` to `29c41c4` [[#3198](https://github.com/falcosecurity/falco/pull/3198)] - [@dependabot[bot]](https://github.com/apps/dependabot)
* update(cmake): bump falcoctl to v0.8.0-rc4 [[#3191](https://github.com/falcosecurity/falco/pull/3191)] - [@FedeDP](https://github.com/FedeDP)
* refactor: smart pointer usage [[#3184](https://github.com/falcosecurity/falco/pull/3184)] - [@federico-sysdig](https://github.com/federico-sysdig)
* build(deps): Bump submodules/falcosecurity-rules from `ec255e6` to `4f153f5` [[#3182](https://github.com/falcosecurity/falco/pull/3182)] - [@dependabot[bot]](https://github.com/apps/dependabot)
* update(cmake): bumped libs and driver to latest master. [[#3177](https://github.com/falcosecurity/falco/pull/3177)] - [@FedeDP](https://github.com/FedeDP)
* chore(cmake): enable modern bpf build by default. [[#3180](https://github.com/falcosecurity/falco/pull/3180)] - [@FedeDP](https://github.com/FedeDP)
* cleanup(docs): fix typo in license blocks [[#3175](https://github.com/falcosecurity/falco/pull/3175)] - [@LucaGuerra](https://github.com/LucaGuerra)
* chore(docker,scripts): set old eBPF probe as lowest priority driver. [[#3173](https://github.com/falcosecurity/falco/pull/3173)] - [@FedeDP](https://github.com/FedeDP)
* build(deps): Bump submodules/falcosecurity-rules from `869c9a7` to `ec255e6` [[#3170](https://github.com/falcosecurity/falco/pull/3170)] - [@dependabot[bot]](https://github.com/apps/dependabot)
* update(app): close inspectors at teardown time [[#3169](https://github.com/falcosecurity/falco/pull/3169)] - [@LucaGuerra](https://github.com/LucaGuerra)
* fix(docker): fixed docker entrypoints for driver loading. [[#3168](https://github.com/falcosecurity/falco/pull/3168)] - [@FedeDP](https://github.com/FedeDP)
* fix(docker,scripts): do not load falcoctl driver loader when installing Falco deb package in docker images [[#3166](https://github.com/falcosecurity/falco/pull/3166)] - [@FedeDP](https://github.com/FedeDP)
* update(ci): build both release and debug versions [[#3161](https://github.com/falcosecurity/falco/pull/3161)] - [@LucaGuerra](https://github.com/LucaGuerra)
* chore(userspace/falco): watch all configs files. [[#3160](https://github.com/falcosecurity/falco/pull/3160)] - [@FedeDP](https://github.com/FedeDP)
* fix(ci): update scorecard-action to v2.3.1 [[#3153](https://github.com/falcosecurity/falco/pull/3153)] - [@LucaGuerra](https://github.com/LucaGuerra)
* cleanup(falco): consolidate falco::grpc::server in one class [[#3150](https://github.com/falcosecurity/falco/pull/3150)] - [@LucaGuerra](https://github.com/LucaGuerra)
* new(build): enable ASan and UBSan builds with options and in CI [[#3147](https://github.com/falcosecurity/falco/pull/3147)] - [@LucaGuerra](https://github.com/LucaGuerra)
* fix(userspace): variable / function shadowing [[#3123](https://github.com/falcosecurity/falco/pull/3123)] - [@sgaist](https://github.com/sgaist)
* build(deps): Bump submodules/falcosecurity-rules from `fbf0a4e` to `88a40c8` [[#3145](https://github.com/falcosecurity/falco/pull/3145)] - [@dependabot[bot]](https://github.com/apps/dependabot)
* fix(cmake): fix USE_BUNDLED_DEPS=ON and BUILD_FALCO_UNIT_TESTS=ON [[#3146](https://github.com/falcosecurity/falco/pull/3146)] - [@LucaGuerra](https://github.com/LucaGuerra)
* Add --kernelversion and --kernelrelease options to falco driver loader entrypoint [[#3143](https://github.com/falcosecurity/falco/pull/3143)] - [@Sryther](https://github.com/Sryther)
* build(deps): Bump submodules/falcosecurity-rules from `44addef` to `fbf0a4e` [[#3139](https://github.com/falcosecurity/falco/pull/3139)] - [@dependabot[bot]](https://github.com/apps/dependabot)
* chore: bump to latest libs commit [[#3137](https://github.com/falcosecurity/falco/pull/3137)] - [@Andreagit97](https://github.com/Andreagit97)
* refactor: Use FetchContent for integrating three bundled libs [[#3107](https://github.com/falcosecurity/falco/pull/3107)] - [@federico-sysdig](https://github.com/federico-sysdig)
* build(deps): Bump submodules/falcosecurity-rules from `dc7970d` to `44addef` [[#3136](https://github.com/falcosecurity/falco/pull/3136)] - [@dependabot[bot]](https://github.com/apps/dependabot)
* build(deps): Bump submodules/falcosecurity-rules from `f88b991` to `dc7970d` [[#3126](https://github.com/falcosecurity/falco/pull/3126)] - [@dependabot[bot]](https://github.com/apps/dependabot)
* refactor(ci): Avoid using command make directly [[#3101](https://github.com/falcosecurity/falco/pull/3101)] - [@federico-sysdig](https://github.com/federico-sysdig)
* docs(proposal): 20231220-features-adoption-and-deprecation.md [[#2986](https://github.com/falcosecurity/falco/pull/2986)] - [@leogr](https://github.com/leogr)
* build(deps): Bump submodules/falcosecurity-rules from `b499a1d` to `f88b991` [[#3125](https://github.com/falcosecurity/falco/pull/3125)] - [@dependabot[bot]](https://github.com/apps/dependabot)
* docs(README.md): Falco Graduates within the CNCF [[#3124](https://github.com/falcosecurity/falco/pull/3124)] - [@leogr](https://github.com/leogr)
* build(deps): Bump submodules/falcosecurity-rules from `497e011` to `b499a1d` [[#3111](https://github.com/falcosecurity/falco/pull/3111)] - [@dependabot[bot]](https://github.com/apps/dependabot)
* chore(ci): bumped codeql actions. [[#3114](https://github.com/falcosecurity/falco/pull/3114)] - [@FedeDP](https://github.com/FedeDP)
* Cleanup warnings and smart ptrs [[#3112](https://github.com/falcosecurity/falco/pull/3112)] - [@federico-sysdig](https://github.com/federico-sysdig)
* new(build): add options to use bundled dependencies [[#3092](https://github.com/falcosecurity/falco/pull/3092)] - [@mrgian](https://github.com/mrgian)
* fix(ci): test-dev-packages-arm64 needs build-dev-packages-arm64. [[#3110](https://github.com/falcosecurity/falco/pull/3110)] - [@FedeDP](https://github.com/FedeDP)
* refactor: bump libs and driver, and adopt unique pointers wherever possible [[#3109](https://github.com/falcosecurity/falco/pull/3109)] - [@jasondellaluce](https://github.com/jasondellaluce)
* cleanup: falco_engine test fixture [[#3099](https://github.com/falcosecurity/falco/pull/3099)] - [@federico-sysdig](https://github.com/federico-sysdig)
* refactor: test AtomicSignalHandler.handle_once_wait_consistency [[#3100](https://github.com/falcosecurity/falco/pull/3100)] - [@federico-sysdig](https://github.com/federico-sysdig)
* Cleanup variable use [[#3097](https://github.com/falcosecurity/falco/pull/3097)] - [@sgaist](https://github.com/sgaist)
* cleanup(submodules): dropped testing submodule. [[#3098](https://github.com/falcosecurity/falco/pull/3098)] - [@FedeDP](https://github.com/FedeDP)
* cleanup(ci): make use of falcosecurity/testing provided composite action [[#3093](https://github.com/falcosecurity/falco/pull/3093)] - [@FedeDP](https://github.com/FedeDP)
* Improve const correctness [[#3083](https://github.com/falcosecurity/falco/pull/3083)] - [@sgaist](https://github.com/sgaist)
* Improve exception throwing [[#3085](https://github.com/falcosecurity/falco/pull/3085)] - [@sgaist](https://github.com/sgaist)
* fix(ci): update sync in deb and rpm scripts with acl [[#3062](https://github.com/falcosecurity/falco/pull/3062)] - [@LucaGuerra](https://github.com/LucaGuerra)
* cleanup(tests): consolidate Falco engine and rule loader tests [[#3066](https://github.com/falcosecurity/falco/pull/3066)] - [@LucaGuerra](https://github.com/LucaGuerra)
* cleanup: falco_engine deps and include paths [[#3090](https://github.com/falcosecurity/falco/pull/3090)] - [@federico-sysdig](https://github.com/federico-sysdig)
* fix: Some compiler warnings [[#3089](https://github.com/falcosecurity/falco/pull/3089)] - [@federico-sysdig](https://github.com/federico-sysdig)
* build(deps): Bump submodules/falcosecurity-rules from `0f60976` to `497e011` [[#3081](https://github.com/falcosecurity/falco/pull/3081)] - [@dependabot[bot]](https://github.com/apps/dependabot)
* fix(c++): add missing explicit to single argument constructors [[#3069](https://github.com/falcosecurity/falco/pull/3069)] - [@sgaist](https://github.com/sgaist)
* Improve class initialization [[#3074](https://github.com/falcosecurity/falco/pull/3074)] - [@sgaist](https://github.com/sgaist)
* build(deps): Bump submodules/falcosecurity-rules from `6ed2036` to `0f60976` [[#3078](https://github.com/falcosecurity/falco/pull/3078)] - [@dependabot[bot]](https://github.com/apps/dependabot)
* build(deps): Bump submodules/falcosecurity-rules from `1053b2d` to `6ed2036` [[#3067](https://github.com/falcosecurity/falco/pull/3067)] - [@dependabot[bot]](https://github.com/apps/dependabot)
* fix(c++): add missing overrides [[#3064](https://github.com/falcosecurity/falco/pull/3064)] - [@sgaist](https://github.com/sgaist)
* new(build): prune deb-dev and rpm-dev directories [[#3056](https://github.com/falcosecurity/falco/pull/3056)] - [@LucaGuerra](https://github.com/LucaGuerra)
* refactor(userspace): align falco to gen-event class family deprecation [[#3051](https://github.com/falcosecurity/falco/pull/3051)] - [@jasondellaluce](https://github.com/jasondellaluce)
* build(deps): Bump submodules/falcosecurity-rules from `3cac61c` to `1053b2d` [[#3047](https://github.com/falcosecurity/falco/pull/3047)] - [@dependabot[bot]](https://github.com/apps/dependabot)
* fix: adopt new libsinsp logger [[#3026](https://github.com/falcosecurity/falco/pull/3026)] - [@therealbobo](https://github.com/therealbobo)
* refactor: cleanup libs relative include paths [[#2936](https://github.com/falcosecurity/falco/pull/2936)] - [@therealbobo](https://github.com/therealbobo)
* chore(ci): bumped rn2md to latest master. [[#3046](https://github.com/falcosecurity/falco/pull/3046)] - [@FedeDP](https://github.com/FedeDP)
* Support alternate rules loader [[#3008](https://github.com/falcosecurity/falco/pull/3008)] - [@mstemm](https://github.com/mstemm)
* fix(ci): fixed release body driver version. [[#3042](https://github.com/falcosecurity/falco/pull/3042)] - [@FedeDP](https://github.com/FedeDP)
* build(deps): Bump submodules/falcosecurity-rules from `c39d31a` to `3f668d0` [[#3039](https://github.com/falcosecurity/falco/pull/3039)] - [@dependabot[bot]](https://github.com/apps/dependabot)
## v0.37.1
Released on 2024-02-13

View File

@@ -21,6 +21,9 @@ 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(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)
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)
@@ -49,7 +52,7 @@ 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" OFF)
option(BUILD_FALCO_MODERN_BPF "Build modern BPF support for Falco" ON)
if(BUILD_FALCO_MODERN_BPF)
add_definitions(-DHAS_MODERN_BPF)
endif()
@@ -161,12 +164,15 @@ endif()
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}")
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}")
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}")
endif()
if(NOT MINIMAL_BUILD)

View File

@@ -10,7 +10,7 @@
At its core, Falco is a kernel monitoring and detection agent that observes events, such as syscalls, based on custom rules. Falco can enhance these events by integrating metadata from the container runtime and Kubernetes. The collected events can be analyzed off-host in SIEM or data lake systems.
Falco, originally created by [Sysdig](https://sysdig.com), is an incubating project under the [Cloud Native Computing Foundation](https://cncf.io) (CNCF) used in production by various [organisations](https://github.com/falcosecurity/falco/blob/master/ADOPTERS.md).
Falco, originally created by [Sysdig](https://sysdig.com), is a **graduated project** under the [Cloud Native Computing Foundation](https://cncf.io) (CNCF) used in production by various [organisations](https://github.com/falcosecurity/falco/blob/master/ADOPTERS.md).
For detailed technical information and insights into the cyber threats that Falco can detect, visit the official [Falco](https://falco.org/) website.

View File

@@ -53,6 +53,17 @@ if(NOT MSVC)
set(FALCO_SECURITY_FLAGS "${FALCO_SECURITY_FLAGS} -D_FORTIFY_SOURCE=2")
endif()
if(USE_ASAN)
set(FALCO_SECURITY_FLAGS "${FALCO_SECURITY_FLAGS} -fsanitize=address")
endif()
if(USE_UBSAN)
set(FALCO_SECURITY_FLAGS "${FALCO_SECURITY_FLAGS} -fsanitize=undefined")
if(UBSAN_HALT_ON_ERROR)
set(FALCO_SECURITY_FLAGS "${FALCO_SECURITY_FLAGS} -fno-sanitize-recover=undefined")
endif()
endif()
set(CMAKE_COMMON_FLAGS "${FALCO_SECURITY_FLAGS} -Wall -ggdb ${FALCO_EXTRA_FEATURE_FLAGS} ${MINIMAL_BUILD_FLAGS} ${MUSL_FLAGS}")
if(BUILD_WARNINGS_AS_ERRORS)

View File

@@ -12,32 +12,15 @@
# specific language governing permissions and limitations under the License.
#
#
# cpp-httplib (https://github.com/yhirose/cpp-httplib)
#
option(USE_BUNDLED_CPPHTTPLIB "Enable building of the bundled cpp-httplib" ${USE_BUNDLED_DEPS})
if(CPPHTTPLIB_INCLUDE)
# we already have cpp-httplib
elseif(NOT USE_BUNDLED_CPPHTTPLIB)
find_package(httplib CONFIG REQUIRED)
get_target_property(CPPHTTPLIB_INCLUDE httplib::httplib INTERFACE_INCLUDE_DIRECTORIES)
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)
else()
set(CPPHTTPLIB_SRC "${PROJECT_BINARY_DIR}/cpp-httplib-prefix/src/cpp-httplib")
set(CPPHTTPLIB_INCLUDE "${CPPHTTPLIB_SRC}")
message(STATUS "Using bundled cpp-httplib in ${CPPHTTPLIB_SRC}")
ExternalProject_Add(cpp-httplib
PREFIX "${PROJECT_BINARY_DIR}/cpp-httplib-prefix"
URL "https://github.com/yhirose/cpp-httplib/archive/refs/tags/v0.13.1.tar.gz"
URL_HASH "SHA256=9b837d290b61e3f0c4239da0b23bbf14c382922e2bf2a9bac21c1e3feabe1ff9"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND "")
find_package(httplib CONFIG REQUIRED)
endif()
if(NOT TARGET cpp-httplib)
add_custom_target(cpp-httplib)
endif()

View File

@@ -34,8 +34,8 @@ else()
# In case you want to test against another driver version (or branch, or commit) just pass the variable -
# ie., `cmake -DDRIVER_VERSION=dev ..`
if(NOT DRIVER_VERSION)
set(DRIVER_VERSION "f2eabad40d2b3bd74c63743ed7f7a020c85f3aaa")
set(DRIVER_CHECKSUM "SHA256=5e1d0d6ff736b49b8b49e9cf5881be8db622cea5586d71d1974b6f8152e0b978")
set(DRIVER_VERSION "7.2.1+driver")
set(DRIVER_CHECKSUM "SHA256=0ae749718557812dc008bdfd8eaa81355094a0975380df1021b1e2bf2ee91457")
endif()
# cd /path/to/build && cmake /path/to/source

View File

@@ -16,14 +16,14 @@ include(ExternalProject)
string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} FALCOCTL_SYSTEM_NAME)
set(FALCOCTL_VERSION "0.7.2")
set(FALCOCTL_VERSION "0.9.0")
if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
set(FALCOCTL_SYSTEM_PROC_GO "amd64")
set(FALCOCTL_HASH "abbbef2beefceb3d518a638fbad220ca6002840d33a20a7f1de9b358c4dbef45")
set(FALCOCTL_HASH "04a689cca5b18c82427fe0cdc15c37b35f3f4696f6bc13d92aa903183b25b2c5")
else() # aarch64
set(FALCOCTL_SYSTEM_PROC_GO "arm64")
set(FALCOCTL_HASH "8dafef99948355febfa311bb940f8c714af631a249f4ae05ffd7d4c5f181e2c4")
set(FALCOCTL_HASH "cd37537a7d1a81e5e372760e14b3a945c650f845e98649fc15e560b0ba7a6597")
endif()
ExternalProject_Add(

View File

@@ -35,8 +35,8 @@ else()
# In case you want to test against another falcosecurity/libs version (or branch, or commit) just pass the variable -
# ie., `cmake -DFALCOSECURITY_LIBS_VERSION=dev ..`
if(NOT FALCOSECURITY_LIBS_VERSION)
set(FALCOSECURITY_LIBS_VERSION "f2eabad40d2b3bd74c63743ed7f7a020c85f3aaa")
set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=5e1d0d6ff736b49b8b49e9cf5881be8db622cea5586d71d1974b6f8152e0b978")
set(FALCOSECURITY_LIBS_VERSION "0.17.3")
set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=6ff90672fe35d725e79dcb1d940c1518154daef28a3eb1cd127432c503cab079")
endif()
# cd /path/to/build && cmake /path/to/source

View File

@@ -12,29 +12,15 @@
# specific language governing permissions and limitations under the License.
#
#
# njson (https://github.com/nlohmann/json)
#
option(USE_BUNDLED_NLOHMANN_JSON "Enable building of the bundled nlohmann-json" ${USE_BUNDLED_DEPS})
if(nlohmann_json_INCLUDE_DIRS)
# we already have nlohmnann-json
elseif(NOT USE_BUNDLED_NLOHMANN_JSON)
find_package(nlohmann_json CONFIG REQUIRED)
get_target_property(nlohmann_json_INCLUDE_DIRS nlohmann_json::nlohmann_json INTERFACE_INCLUDE_DIRECTORIES)
else()
set(nlohmann_json_INCLUDE_DIRS "${PROJECT_BINARY_DIR}/njson-prefix/include")
message(STATUS "Using bundled nlohmann-json in ${nlohmann_json_INCLUDE_DIRS}")
ExternalProject_Add(njson
URL "https://github.com/nlohmann/json/archive/v3.3.0.tar.gz"
URL_HASH "SHA256=2fd1d207b4669a7843296c41d3b6ac5b23d00dec48dba507ba051d14564aa801"
CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/njson-prefix -DJSON_BuildTests=OFF -DBUILD_TESTING=OFF
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
)
endif()
if(NOT TARGET njson)
add_custom_target(njson)
FetchContent_MakeAvailable(nlohmann_json)
else()
find_package(nlohmann_json CONFIG REQUIRED)
endif()

View File

@@ -16,8 +16,8 @@ include(GNUInstallDirs)
include(ExternalProject)
# falco_rules.yaml
set(FALCOSECURITY_RULES_FALCO_VERSION "falco-rules-3.0.0")
set(FALCOSECURITY_RULES_FALCO_CHECKSUM "SHA256=2e91799fee49c2daf58fb482e47410a21433eb116e02cde18206f7af87449ddb")
set(FALCOSECURITY_RULES_FALCO_VERSION "falco-rules-3.1.0")
set(FALCOSECURITY_RULES_FALCO_CHECKSUM "SHA256=3b617920c0b66128627613e591a954eb9572747a4c287bc13b53b38786250162")
set(FALCOSECURITY_RULES_FALCO_PATH "${PROJECT_BINARY_DIR}/falcosecurity-rules-falco-prefix/src/falcosecurity-rules-falco/falco_rules.yaml")
ExternalProject_Add(
falcosecurity-rules-falco

View File

@@ -12,45 +12,15 @@
# specific language governing permissions and limitations under the License.
#
#
# yamlcpp (https://github.com/jbeder/yaml-cpp)
#
option(USE_BUNDLED_YAMLCPP "Enable building of the bundled yamlcpp" ${USE_BUNDLED_DEPS})
if(YAMLCPP_INCLUDE_DIR)
# we already have yamlcpp
elseif(NOT USE_BUNDLED_YAMLCPP)
find_path(YAMLCPP_INCLUDE_DIR NAMES yaml-cpp/yaml.h)
find_library(YAMLCPP_LIB NAMES yaml-cpp)
if(YAMLCPP_INCLUDE_DIR)
message(STATUS "Found yamlcpp: include: ${YAMLCPP_INCLUDE_DIR}")
else()
message(FATAL_ERROR "Couldn't find system yamlcpp")
endif()
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)
else()
set(YAMLCPP_SRC "${PROJECT_BINARY_DIR}/yamlcpp-prefix/src/yamlcpp")
set(YAMLCPP_INCLUDE_DIR "${YAMLCPP_SRC}/include")
message(STATUS "Using bundled yaml-cpp in '${YAMLCPP_SRC}'")
if(NOT WIN32)
set(YAMLCPP_LIB "${YAMLCPP_SRC}/libyaml-cpp.a")
else()
set(YAMLCPP_LIB "${YAMLCPP_SRC}/${CMAKE_BUILD_TYPE}/yaml-cpp.lib")
endif()
ExternalProject_Add(
yamlcpp
URL "https://github.com/jbeder/yaml-cpp/archive/yaml-cpp-0.7.0.tar.gz"
URL_HASH "SHA256=43e6a9fcb146ad871515f0d0873947e5d497a1c9c60c58cb102a97b47208b7c3"
BUILD_BYPRODUCTS ${YAMLCPP_LIB}
CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release -DYAML_MSVC_SHARED_RT=Off -DYAML_BUILD_SHARED_LIBS=Off -DYAML_CPP_BUILD_TESTS=Off -DYAML_CPP_BUILD_TOOLS=OFF -DYAML_CPP_BUILD_CONTRIB=OFF -DCMAKE_DEBUG_POSTFIX=''
BUILD_IN_SOURCE 1
INSTALL_COMMAND "")
endif()
if(NOT TARGET yamlcpp)
add_custom_target(yamlcpp)
find_package(yaml-cpp CONFIG REQUIRED)
endif()

View File

@@ -37,6 +37,7 @@ RUN apt-get update \
netcat \
patchelf \
xz-utils \
zstd \
&& rm -rf /var/lib/apt/lists/*
RUN if [ "$TARGETARCH" = "amd64" ]; \
@@ -92,7 +93,7 @@ RUN rm -rf /usr/bin/clang \
RUN curl -s https://falco.org/repo/falcosecurity-packages.asc | apt-key add - \
&& echo "deb https://download.falco.org/packages/${VERSION_BUCKET} stable main" | tee -a /etc/apt/sources.list.d/falcosecurity.list \
&& apt-get update -y \
&& if [ "$FALCO_VERSION" = "latest" ]; then apt-get install -y --no-install-recommends falco; else apt-get install -y --no-install-recommends falco=${FALCO_VERSION}; fi \
&& if [ "$FALCO_VERSION" = "latest" ]; then FALCO_DRIVER_CHOICE=none apt-get install -y --no-install-recommends falco; else FALCO_DRIVER_CHOICE=none apt-get install -y --no-install-recommends falco=${FALCO_VERSION}; fi \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

View File

@@ -24,7 +24,9 @@ print_usage() {
echo " docker run -i -t --privileged -v /root/.falco:/root/.falco -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro -v /etc:/host/etc:ro falcosecurity/falco-driver-loader-legacy:latest [driver] [options]"
echo ""
echo "Available drivers:"
echo " kmod kernel module (default)"
echo " auto leverage automatic driver selection logic (default)"
echo " modern_ebpf modern eBPF CORE probe"
echo " kmod kernel module"
echo " ebpf eBPF probe"
echo ""
echo "Options:"
@@ -53,18 +55,17 @@ done
ENABLE_COMPILE="false"
ENABLE_DOWNLOAD="false"
HTTP_INSECURE="false"
has_driver=
driver=
has_opts=
while test $# -gt 0; do
case "$1" in
kmod|ebpf)
if [ -n "$has_driver" ]; then
auto|kmod|ebpf|modern_ebpf)
if [ -n "$driver" ]; then
>&2 echo "Only one driver per invocation"
print_usage
exit 1
else
/usr/bin/falcoctl driver config --type $1
has_driver="true"
driver=$1
fi
;;
-h|--help)
@@ -85,11 +86,6 @@ while test $# -gt 0; do
;;
--http-insecure)
HTTP_INSECURE="true"
;;
--source-only)
>&2 echo "Support dropped in Falco 0.37.0."
print_usage
exit 1
;;
--print-env)
/usr/bin/falcoctl driver printenv
@@ -109,9 +105,22 @@ while test $# -gt 0; do
shift
done
# No opts passed, enable both compile and download
if [ -z "$has_opts" ]; then
ENABLE_COMPILE="true"
ENABLE_DOWNLOAD="true"
ENABLE_COMPILE="true"
ENABLE_DOWNLOAD="true"
fi
# Default value: auto
if [ -z "$driver" ]; then
driver="auto"
fi
if [ "$driver" != "auto" ]; then
/usr/bin/falcoctl driver config --type $driver
else
# Needed because we need to configure Falco to start with correct driver
/usr/bin/falcoctl driver config --type modern_ebpf --type kmod --type ebpf
fi
/usr/bin/falcoctl driver install --compile=$ENABLE_COMPILE --download=$ENABLE_DOWNLOAD --http-insecure=$HTTP_INSECURE --http-headers="$FALCOCTL_DRIVER_HTTP_HEADERS"

View File

@@ -24,16 +24,20 @@ print_usage() {
echo " docker run -i -t --privileged -v /root/.falco:/root/.falco -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro -v /etc:/host/etc:ro falcosecurity/falco-driver-loader:latest [driver] [options]"
echo ""
echo "Available drivers:"
echo " kmod kernel module (default)"
echo " auto leverage automatic driver selection logic (default)"
echo " modern_ebpf modern eBPF CORE probe"
echo " kmod kernel module"
echo " ebpf eBPF probe"
echo ""
echo "Options:"
echo " --help show this help message"
echo " --clean try to remove an already present driver installation"
echo " --compile try to compile the driver locally (default true)"
echo " --download try to download a prebuilt driver (default true)"
echo " --http-insecure enable insecure downloads"
echo " --print-env skip execution and print env variables for other tools to consume"
echo " --help show this help message"
echo " --clean try to remove an already present driver installation"
echo " --compile try to compile the driver locally (default true)"
echo " --download try to download a prebuilt driver (default true)"
echo " --kernel-release <value> set the kernel release"
echo " --kernel-version <value> set the kernel version"
echo " --http-insecure enable insecure downloads"
echo " --print-env skip execution and print env variables for other tools to consume"
echo ""
echo "Environment variables:"
echo " FALCOCTL_DRIVER_REPOS specify different URL(s) where to look for prebuilt Falco drivers (comma separated)"
@@ -53,18 +57,19 @@ done
ENABLE_COMPILE="false"
ENABLE_DOWNLOAD="false"
HTTP_INSECURE="false"
has_driver=
driver=
has_opts=
extra_args=
while test $# -gt 0; do
case "$1" in
kmod|ebpf)
if [ -n "$has_driver" ]; then
auto|kmod|ebpf|modern_ebpf)
if [ -n "$driver" ]; then
>&2 echo "Only one driver per invocation"
print_usage
exit 1
else
/usr/bin/falcoctl driver config --type $1
has_driver="true"
driver=$1
fi
;;
-h|--help)
@@ -85,11 +90,14 @@ while test $# -gt 0; do
;;
--http-insecure)
HTTP_INSECURE="true"
;;
--source-only)
>&2 echo "Support dropped in Falco 0.37.0."
print_usage
exit 1
;;
--kernel-release)
extra_args+="--kernelrelease=$2 "
shift
;;
--kernel-version)
extra_args+="--kernelversion=$2 "
shift
;;
--print-env)
/usr/bin/falcoctl driver printenv
@@ -109,9 +117,22 @@ while test $# -gt 0; do
shift
done
# No opts passed, enable both compile and download
if [ -z "$has_opts" ]; then
ENABLE_COMPILE="true"
ENABLE_DOWNLOAD="true"
ENABLE_COMPILE="true"
ENABLE_DOWNLOAD="true"
fi
/usr/bin/falcoctl driver install --compile=$ENABLE_COMPILE --download=$ENABLE_DOWNLOAD --http-insecure=$HTTP_INSECURE --http-headers="$FALCOCTL_DRIVER_HTTP_HEADERS"
# Default value: auto
if [ -z "$driver" ]; then
driver="auto"
fi
if [ "$driver" != "auto" ]; then
/usr/bin/falcoctl driver config --type $driver
else
# Needed because we need to configure Falco to start with correct driver
/usr/bin/falcoctl driver config --type modern_ebpf --type kmod --type ebpf
fi
/usr/bin/falcoctl driver install --compile=$ENABLE_COMPILE --download=$ENABLE_DOWNLOAD --http-insecure=$HTTP_INSECURE --http-headers="$FALCOCTL_DRIVER_HTTP_HEADERS" $extra_args

View File

@@ -39,12 +39,13 @@ RUN apt-get update \
netcat-openbsd \
patchelf \
xz-utils \
zstd \
&& rm -rf /var/lib/apt/lists/*
RUN curl -s https://falco.org/repo/falcosecurity-packages.asc | apt-key add - \
&& echo "deb https://download.falco.org/packages/${VERSION_BUCKET} stable main" | tee -a /etc/apt/sources.list.d/falcosecurity.list \
&& apt-get update -y \
&& if [ "$FALCO_VERSION" = "latest" ]; then apt-get install -y --no-install-recommends falco; else apt-get install -y --no-install-recommends falco=${FALCO_VERSION}; fi \
&& if [ "$FALCO_VERSION" = "latest" ]; then FALCO_DRIVER_CHOICE=none apt-get install -y --no-install-recommends falco; else FALCO_DRIVER_CHOICE=none apt-get install -y --no-install-recommends falco=${FALCO_VERSION}; fi \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

View File

@@ -24,7 +24,9 @@ print_usage() {
echo " docker run -i -t --privileged -v /root/.falco:/root/.falco -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro -v /etc:/host/etc:ro -e 'FALCO_DRIVER_LOADER_OPTIONS=[driver] [options]' falcosecurity/falco:latest"
echo ""
echo "Available FALCO_DRIVER_LOADER_OPTIONS drivers:"
echo " kmod kernel module (default)"
echo " auto leverage automatic driver selection logic (default)"
echo " modern_ebpf modern eBPF CORE probe"
echo " kmod kernel module"
echo " ebpf eBPF probe"
echo ""
echo "FALCO_DRIVER_LOADER_OPTIONS options:"
@@ -60,19 +62,18 @@ if [[ -z "${SKIP_DRIVER_LOADER}" ]]; then
ENABLE_COMPILE="false"
ENABLE_DOWNLOAD="false"
HTTP_INSECURE="false"
has_driver=
driver=
has_opts=
for opt in "${falco_driver_loader_option_arr[@]}"
do
case "$opt" in
kmod|ebpf)
if [ -n "$has_driver" ]; then
auto|kmod|ebpf|modern_ebpf)
if [ -n "$driver" ]; then
>&2 echo "Only one driver per invocation"
print_usage
exit 1
else
/usr/bin/falcoctl driver config --type $opt
has_driver="true"
driver=$opt
fi
;;
-h|--help)
@@ -91,34 +92,43 @@ if [[ -z "${SKIP_DRIVER_LOADER}" ]]; then
ENABLE_DOWNLOAD="true"
has_opts="true"
;;
--http-insecure)
HTTP_INSECURE="true"
;;
--source-only)
>&2 echo "Support dropped in Falco 0.37.0."
print_usage
exit 1
;;
--http-insecure)
HTTP_INSECURE="true"
;;
--print-env)
/usr/bin/falcoctl driver printenv
exit 0
;;
--*)
>&2 echo "Unknown option: $1"
>&2 echo "Unknown option: $opt"
print_usage
exit 1
;;
*)
>&2 echo "Unknown driver: $1"
>&2 echo "Unknown driver: $opt"
print_usage
exit 1
;;
esac
done
# No opts passed, enable both compile and download
if [ -z "$has_opts" ]; then
ENABLE_COMPILE="true"
ENABLE_DOWNLOAD="true"
fi
# Default value: auto
if [ -z "$driver" ]; then
driver="auto"
fi
if [ "$driver" != "auto" ]; then
/usr/bin/falcoctl driver config --type $driver
else
# Needed because we need to configure Falco to start with correct driver
/usr/bin/falcoctl driver config --type modern_ebpf --type kmod --type ebpf
fi
/usr/bin/falcoctl driver install --compile=$ENABLE_COMPILE --download=$ENABLE_DOWNLOAD --http-insecure=$HTTP_INSECURE --http-headers="$FALCOCTL_DRIVER_HTTP_HEADERS"
fi

View File

@@ -25,46 +25,64 @@
#
# (Falco command-line arguments)
# (Falco environment variables)
# Falco config files settings
# config_files [Stable]
# watch_config_files [Stable]
# Falco rules files
# rules_file
# rules_files [Stable]
# Falco rules
# rules [Incubating]
# Falco engine
# engine
# engine [Stable]
# Falco plugins
# load_plugins
# plugins
# Falco config files
# watch_config_files
# load_plugins [Stable]
# plugins [Stable]
# Falco outputs settings
# time_format_iso_8601
# priority
# json_output
# json_include_output_property
# json_include_tags_property
# buffered_outputs
# rule_matching
# outputs_queue
# time_format_iso_8601 [Stable]
# priority [Stable]
# json_output [Stable]
# json_include_output_property [Stable]
# json_include_tags_property [Stable]
# buffered_outputs [Stable]
# rule_matching [Incubating]
# outputs_queue [Stable]
# Falco outputs channels
# stdout_output
# syslog_output
# file_output
# http_output
# program_output
# grpc_output
# stdout_output [Stable]
# syslog_output [Stable]
# file_output [Stable]
# http_output [Stable]
# program_output [Stable]
# grpc_output [Stable]
# Falco exposed services
# grpc
# webserver
# grpc [Stable]
# webserver [Stable]
# Falco logging / alerting / metrics related to software functioning (basic)
# log_stderr
# log_syslog
# log_level
# libs_logger
# log_stderr [Stable]
# log_syslog [Stable]
# log_level [Stable]
# libs_logger [Stable]
# Falco logging / alerting / metrics related to software functioning (advanced)
# output_timeout
# syscall_event_timeouts
# syscall_event_drops -> [CHANGE NOTICE] Automatic notifications will be simplified in Falco 0.38! If you depend on the detailed drop counters payload, use 'metrics.output_rule' along with 'metrics.kernel_event_counters_enabled' instead
# metrics
# output_timeout [Stable]
# syscall_event_timeouts [Stable]
# syscall_event_drops [Stable] -> [CHANGE NOTICE] Automatic notifications will be simplified in Falco 0.38! If you depend on the detailed drop counters payload, use 'metrics.output_rule' along with 'metrics.kernel_event_counters_enabled' instead
# metrics [Stable]
# Falco performance tuning (advanced)
# base_syscalls
# base_syscalls [Stable]
# Falco libs
# falco_libs [Incubating]
########################
# Config maturity tags #
########################
# As per features adoption and deprecation proposal we support 4 levels of configuration keys maturity:
# * Sandbox -> Experimental/alpha features, not recommended for production use, can be removed at any time without further notice.
# * Incubating -> Beta features, long-term support is not guaranteed.
# * Stable -> General Availability (GA) features for which long-term support is expected.
# * Deprecated -> Deprecated keys, soon to be removed.
#
# For more info, please take a look at the proposal: https://github.com/falcosecurity/falco/blob/master/proposals/20231220-features-adoption-and-deprecation.md.
################################
# Falco command-line arguments #
@@ -112,15 +130,44 @@
# disabling the automatic artifacts followed by falcoctl.
###############################
# Falco config files settings #
###############################
# [Stable] `config_files`
#
# Falco will load additional configs files specified here.
# Their loading is assumed to be made *after* main config file has been processed,
# exactly in the order they are specified.
# Therefore, loaded config files *can* override values from main config file.
# Also, nested include is not allowed, ie: included config files won't be able to include other config files.
#
# Like for 'rules_files', specifying a folder will load all the configs files present in it in a lexicographical order.
config_files:
- /etc/falco/config.d
# [Stable] `watch_config_files`
#
# Falco monitors configuration and rules files for changes and automatically
# reloads itself to apply the updated configuration when any modifications are
# detected. This feature is particularly useful when you want to make real-time
# changes to the configuration or rules of Falco without interrupting its
# operation or losing its state. For more information about Falco's state
# engine, please refer to the `base_syscalls` section.
watch_config_files: true
#####################
# Falco rules files #
#####################
# [Stable] `rules_file`
# [Stable] `rules_files`
# NOTICE: Before Falco 0.38, this config key was `rules_file` (singular form), which is now deprecated in favor of `rules_files` (plural form).
#
# Falco rules can be specified using files or directories, which are loaded at
# startup. The name "rules_file" is maintained for backwards compatibility. If
# the entry is a file, it will be read directly. If the entry is a directory,
# startup.
#
# If the entry is a file, it will be read directly. If the entry is a directory,
# all files within that directory will be read in alphabetical order.
#
# The falco_rules.yaml file ships with the Falco package and is overridden with
@@ -149,11 +196,44 @@
# "first match wins" principle. However, enabling the `all` matching option may result
# in a performance penalty. We recommend carefully testing this alternative setting
# before deploying it in production. Read more under the `rule_matching` configuration.
rules_file:
rules_files:
- /etc/falco/falco_rules.yaml
- /etc/falco/falco_rules.local.yaml
- /etc/falco/rules.d
# [Incubating] `rules`
#
# --- [Description]
#
# Falco rules can be enabled or disabled by name (with wildcards *) and/or by tag.
#
# This configuration is applied after all rules files have been loaded, including
# their overrides, and will take precedence over the enabled/disabled configuration
# specified or overridden in the rules files.
#
# The ordering matters and selections are evaluated in order. For instance, if you
# need to only enable a rule you would first disable all of them and then only
# enable what you need, regardless of the enabled status in the files.
#
# --- [Examples]
#
# Only enable two rules:
#
# rules:
# - disable:
# rule: "*"
# - enable:
# rule: Netcat Remote Code Execution in Container
# - enable:
# rule: Delete or rename shell history
#
# Disable all rules with a specific tag:
#
# rules:
# - disable:
# tag: network
#
################
# Falco engine #
################
@@ -320,7 +400,7 @@ rules_file:
# buffers (higher `cpus_for_each_buffer`) can lower the memory footprint.
#
engine:
kind: kmod
kind: modern_ebpf
kmod:
buf_size_preset: 4
drop_failed_exit: false
@@ -401,21 +481,6 @@ plugins:
library_path: libjson.so
######################
# Falco config files #
######################
# [Stable] `watch_config_files`
#
# Falco monitors configuration and rule files for changes and automatically
# reloads itself to apply the updated configuration when any modifications are
# detected. This feature is particularly useful when you want to make real-time
# changes to the configuration or rules of Falco without interrupting its
# operation or losing its state. For more information about Falco's state
# engine, please refer to the `base_syscalls` section.
watch_config_files: true
##########################
# Falco outputs settings #
##########################
@@ -469,7 +534,7 @@ json_include_tags_property: true
# output mechanism. By default, buffering is disabled (false).
buffered_outputs: false
# [Experimental] `rule_matching`
# [Incubating] `rule_matching`
#
# The `rule_matching` configuration key's values are:
# - `first`: Falco stops checking conditions of rules against upcoming event
@@ -693,6 +758,11 @@ webserver:
# Can be an IPV4 or IPV6 address, defaults to IPV4
listen_address: 0.0.0.0
k8s_healthz_endpoint: /healthz
# [Incubating] `prometheus_metrics_enabled`
#
# Enable the metrics endpoint providing Prometheus values
# It will only have an effect if metrics.enabled is set to true as well.
prometheus_metrics_enabled: false
ssl_enabled: false
ssl_certificate: /etc/falco/falco.pem
@@ -922,6 +992,8 @@ syscall_event_drops:
# as Falco does not automatically rotate the file. It can be used in combination
# with `output_rule`.
#
# `rules_counters_enabled`: Emit counts for each rule.
#
# `resource_utilization_enabled`: Emit CPU and memory usage metrics. CPU usage
# is reported as a percentage of one CPU and can be normalized to the total
# number of CPUs to determine overall usage. Memory metrics are provided in raw
@@ -965,19 +1037,30 @@ syscall_event_drops:
# beneficial for exploring the data schema and ensuring that fields with empty
# values are included in the output.
#
# todo: prometheus export option
# `plugins_metrics_enabled`: Falco can now expose your custom plugins'
# metrics. Please note that if the respective plugin has no metrics implemented,
# there will be no metrics available. In other words, there are no default or
# generic plugin metrics at this time. This may be subject to change.
#
# If metrics are enabled, the web server can be configured to activate the
# corresponding Prometheus endpoint using `webserver.prometheus_metrics_enabled`.
# Prometheus output can be used in combination with the other output options.
#
# todo: syscall_counters_enabled option
metrics:
enabled: false
interval: 1h
# Typically, in production, you only use `output_rule` or `output_file`, but not both.
# However, if you have a very unique use case, you can use both together.
# Set `webserver.prometheus_metrics_enabled` for Prometheus output.
output_rule: true
# output_file: /tmp/falco_stats.jsonl
rules_counters_enabled: true
resource_utilization_enabled: true
state_counters_enabled: true
kernel_event_counters_enabled: true
libbpf_stats_enabled: true
plugins_metrics_enabled: true
convert_memory_to_mb: true
include_empty_values: false
@@ -1100,6 +1183,29 @@ base_syscalls:
custom_set: []
repair: false
##############
# Falco libs #
##############
# [Incubating] `falco_libs`
#
# `thread_table_size`
#
# Set the maximum number of entries (the absolute maximum value can only be MAX UINT32)
# for Falco's internal threadtable (process cache). Please note that Falco operates at a
# granular level, focusing on individual threads. Falco rules reference the thread leader
# as the process. The size of the threadtable should typically be much higher than the
# number of currently alive processes. The default value should work well on modern
# infrastructures and be sufficient to absorb bursts.
#
# Reducing its size can help in better memory management, but as a consequence, your
# process tree may be more frequently disrupted due to missing threads. You can explore
# `metrics.state_counters_enabled` to measure how the internal state handling is performing,
# and the fields called `n_drops_full_threadtable` or `n_store_evts_drops` will inform you
# if you should increase this value for optimal performance.
falco_libs:
thread_table_size: 262144
# [Stable] Guidance for Kubernetes container engine command-line args settings
#
# Modern cloud environments, particularly Kubernetes, heavily rely on

View File

@@ -335,7 +335,7 @@ typedef struct
// the type of the value they return (string, integer...).
// Required: no
// Arguments:
// - evtnum: the number of the event that is bein processed
// - evtnum: the number of the event that is being processed
// - id: the numeric identifier of the field to extract. It corresponds to the
// position of the field in the array returned by get_fields().
// - arg: the field argument, if an argument has been specified for the field,

View File

@@ -0,0 +1,219 @@
# Features Adoption and Deprecation Policies Proposal
This proposal aims to introduce a balance between maintaining adopter trust and the need for The Falco Project to evolve. Historically, Falco has favored rapid evolution over providing long-term support for features and interfaces. However, some project subsystems have been implicitly assumed not to allow backward-incompatible changes (e.g., we have almost never removed a condition syntax field). These implicit conventions have never been formalized, and decisions in this regard have been left unspecified.
## Goals
- Establish adopter expectations on the operational cost of using Falco.
- Provide a clear path for features to be adopted and dismissed.
- Allow quick evolution and experimentation without disrupting our adopters' deployments.
- Detail the process for introducing new features, following a "sandbox" to "incubating" to "stable" progression.
- Define the scope of the policy, including which aspects of Falco are covered (e.g., command line flags, configuration files, rules syntax).
- Establish stages for deprecating features, aligning with the project's current status (pre- and post-1.0 stages).
- Adopt a semantic versioning (semver) approach.
## Non-Goals
- Define the number of previous releases that will receive patches or security updates and the duration of this support.
- Define the criteria for Falco 1.0.
## Scope
The proposed policies apply to Falco, its subsystems (e.g., rules, the plugin system), and all [core projects](https://github.com/falcosecurity/evolution#core) which are deemed [stable](https://github.com/falcosecurity/evolution/blob/main/REPOSITORIES.md#stable), thus officially supported by The Falco Project.
## Definitions
### Feature Changes
A feature is a distinct and specific functionality or characteristic of Falco and its core components that provides value to the user by enabling them to perform particular tasks. Features encompass aspects such as functionality, user value, usability, integrability, scalability, configurability, and discoverability. Features can range from essential user interface elements to complex, multifunctional operations.
A feature change refers to any modification or update to an existing feature or the addition of a new feature. This does not include documentation, Falco compatibility across different environments, platforms, systems, or other software or hardware, bug fixing (stated it does not require a feature change to overcome the problem), and performance (unless a change produces a measurable effect on usability).
### Behavior Changes
A behavior change refers to alterations in how Falco, or a specific feature within it, operates or responds under certain conditions. Unlike feature changes, behavior changes are more about tweaking the underlying logic or the way existing features interact or perform, particularly the expected behavior of Falco when run with the default configuration.
Behaviors are generally documented. Any modification that does not meet the conditions and expectations of an already documented feature is assumed to be a behavior change.
Undocumented behaviors may be included in this definition if there's strong evidence or suspicion that users rely on those undocumented behaviors.
### User-Facing Changes
User-facing changes refer to any feature changes, behavior changes, modifications, or additions that are directly noticeable and interactable by the end users. These changes affect how Falco operates from the user's perspective (notably any change that can lead to user disruption). Unlike internal changes (i.e., code refactoring, CI, maintenance-related changes), which are under-the-hood improvements not directly visible to the user, user-facing changes are evident in the Falco and its core components interface and functionality.
### CLI/Config Area
Falco is comprised of the Falco binary and other programs and tools cooperating (notably [falcoctl](https://github.com/falcosecurity/falcoctl)). These programs are the primary user interface for Falco. Any feature or behavior changes to the following elements of these programs are assumed to be user-facing changes to the CLI/Config area:
- Program name.
- Distribution mechanism and packaging (e.g., a container image).
- Command line flags and options.
- Environment variables.
- Configurations.
- Elements that affect the program's lifecycle (e.g., the effect of sending a SIGINT to the program).
- Elements that allow scripting, automation, or interaction with other programs (e.g., piping and redirection).
- Program inputs, excluding elements explicitly governed by other areas (e.g., [Falco rules](#rules-area)).
- Program outputs excluding elements explicitly governed by other areas (e.g., [Falco outputs/alerts](#outputs-alerts-area)).
### Rules System Area
Rules are the primary input for Falco. Any feature or behavior changes to the following aspects or elements are assumed to be user-facing changes to the rules system area:
- Syntax.
- File format.
- Schema (i.e., supported fields).
- Elements that affect the way users can implement rules.
- Elements that affect the way rules are triggered.
However, any change related to the rule's output when triggered (i.e., the alert) is out of scope for this area (see next section).
Note that this area does not include changes related to the ruleset files. Ruleset distributions follow their own [Rules Maturity Framework](https://github.com/falcosecurity/rules/blob/main/CONTRIBUTING.md#rules-maturity-framework) policies.
### Outputs/Alerts Area
Alerts, delivered through Falco output channels, are Falco's primary output. The way and the format in which alerts are produced can have a significant impact on adopters. For example, removing a supported rule field also impacts this area, as adopters may have relied on that field when consuming Falco output.
Any feature or behavior changes to the following aspects or elements are assumed to be user-facing changes to the Outputs/Alerts area:
- Output and logging formats.
- Schema of outputted data (i.e., supported fields).
- Falco output channels.
- Any element that might be consumed from the output.
### Subsystem APIs (Plugins, gRPC Output, Metrics, etc.) Area
Falco is also comprised of several subsystems providing specific APIs. These subsystems notably include plugin system API, gRPC output API, and metrics API.
In the context of this proposal, only changes to **public APIs** are assumed to be user-facing changes to this area.
Public APIs are defined as those supporting Falco functioning and explicitly intended for user usage. Internal APIs consumed by Falco or other tools are out of scope for this area. For instance, the driver APIs or libs APIs are intended to be mainly consumed by Falco and not by users.
### Platform Support Area
Platform support for Falco encompasses the range of platforms, systems, and environments it is designed to operate in. Platform support may significantly vary by Falco's data sources and use cases. For example, its compatibility differs when utilized for Kubernetes audit events versus system call events. Additionally, platform support can be influenced by deployment methods (e.g., directly on a host versus within Kubernetes) or configurations (e.g., running in privileged versus least privileged mode).
Given the diversity of potential platforms and setups, only those explicitly listed in Falco's documentation are considered officially supported. While Falco may function on other platforms, official support is guaranteed solely for documented ones.
Therefore, changes in platform compatibility or behavior that are documented explicitly assumed to be user-facing changes to the Platform Support area.
### Release Cycle
In the context of this proposal, a release cycle is the period between two consecutive major or minor releases of Falco. Hotfix/Patch releases must not be counted.
The actual duration of a release cycle can vary. Still, it's assumed to be about 16 weeks (as per our current defined [Release Cycles and Development Iterations](https://github.com/falcosecurity/falco/blob/master/proposals/20230511-roadmap-management.md#release-cycles-and-development-iterations)). In case of future modification to the Falco release schedule, a period of minimum 3 months must be assumed.
## Proposal
### Maturation Levels
Maturation levels (inspired by those we already have in place for [repositories](https://github.com/falcosecurity/evolution/blob/main/REPOSITORIES.md#status)) are used to characterize the maturity of a feature. Each feature will have an assigned level at any specific time (i.e., a Falco release). Levels are shown in the table below.
| Maturity Level | Intended for |
| --- | --- |
| Sandbox | Experimental/alpha features, not recommended for production use, can be removed at any time without further notice. |
| Incubating | Beta features, long-term support is not guaranteed. |
| Stable | General Availability (GA) features for which long-term support is expected. |
| Deprecated | See the [deprecation policy](#Deprecation-policy) section below. |
### Adoption Policy
The adoption policy applies to any backward compatible user-facing changes which add functionalities. For non-backward compatible changes see the [deprecation policy](#Deprecation-policy) below.
**Adoption rules**:
1. A feature can be introduced at only one of the following levels:
- Sandbox: The feature must be opt-in (e.g., not enabled by default), labeled as *Sandbox* and the user must be proactively informed by the experimental nature of the feature (i.e. emitting a notice when the feature is being enabled).
- Incubating: The feature must be labeled as *Incubating*.
2. Any functionality additions to an existing feature are inherently introduced at the same level as the feature itself unless logically separable (for instance, a sub-feature that may be enabled separately).
3. A feature can be promoted *from Sandbox to Incubating* or *from Incubating to Stable* only after at least one release cycle has passed without user-facing changes to the feature.
4. A feature cannot be demoted to a previous level.
_Note about behaviors_:
This policy indirectly applies to behaviors, too. Behavior changes are assumed to be a consequence of a feature change. The adoption level of a documented behavior is considered to be the same as the related feature. Furthermore, behavior changes are particularly relevant in the context of deprecation (see the next section).
### Deprecation Policy
The deprecation policy applies to any non-backward compatible user-facing changes. Any other changes introduced in a backward-compatible manner does not fall under the scope of this deprecation policy.
**Deprecation rules**:
1. Sandbox features can be removed or changed at any time without notice. No deprecation period is required.
2. Incubating or Stable features and documented behaviors must enter a deprecation period and function for no less than the indicated release cycles (see tables below) after their announced deprecation.
- If the change affects the feature partially, the deprecation applies only to that feature part.
- If the change removes the feature entirely, the deprecation applies to the entire feature.
3. At least for the entire deprecation period, the feature must be labeled as *Deprecated* in all relevant documentation, and:
- for deprecated configurations or CLI elements, a warning must be emitted warnings when the feature is being enabled or used;
- for deprecated APIs, when technically feasible, the API should be signal the deprecation status (this may vary depending on the specific subsystem);
- for deprecated behaviors the documentation must highlight the _before_ and _after_ behavior, alongside with a prominent deprecation notice.
4. Any Pull Request introducing a deprecation notice must be labeled and include a note in the format `DEPRECATION NOTICE: ...`.
5. Any Pull Request introducing a breaking change due to the end of the deprecation notice period must be labeled and include a note in the format `BREAKING CHANGE: ...`.
- It is also recommended for code commits that introduce a breaking change to follow the related [conventional commit spec](https://www.conventionalcommits.org/en/v1.0.0/#specification).
The minimum deprecation period length depends on the affected area. If a single change spans multiple areas, the area with the most extended deprecation period is assumed. Longer deprecation periods are allowed if the feature is deemed to be particularly critical or widely used.
#### Deprecation Period Lengths
_The units represent the number of releases._
##### Before Falco 1.0
| Area | Stable | Incubating |
| -------------- | ------ | ---------- |
| *all areas* | 1 | 0 |
##### Since Falco 1.0 onward
| Area | Stable | Incubating |
| -------------- | ------ | ---------- |
| Behaviors | 2 | 1 |
| Rules System | 2 | 1 |
| Output/Alerts | 2 | 1 |
| Platform | 2 | 1 |
| CLI/Config | 1 | 1 |
| Subsystem APIs | 1 | 0 |
### Examples
**Example 1** Let's consider a feature _foo_ in the Output/Alerts Area introduced in Falco 1.0.0 and labeled as *Incubating*. The feature is promoted to *Stable* in Falco 1.1.0 (because the feature did not get any user-facing change).
Subsequently, maintainers decide that backward-compatible changes must be introduced in _foo_ to improve its functionality. The part of the feature to be changed is labeled as *Deprecated* in Falco 1.2.0, and the deprecation period starts. The non-backward compatible change is then introduced in Falco 1.4.0.
**Example 2** The `--bar` flag in the CLI/Config Area has been introduced since Falco 1.1.0 and is labeled as *Stable*. Before releasing Falco 1.5.0, maintainers realize `--bar` is redundant and should be removed. The flag is labeled as *Deprecated* in Falco 1.5.0, and the deprecation period starts. The flag is removed in Falco 1.6.0.
### Exceptions
- Ruleset in the official distributions follow the [Rules Maturity Framework](https://github.com/falcosecurity/rules/blob/main/CONTRIBUTING.md#rules-maturity-framework) policies.
- Subsystems or subcomponents may have additional criteria and exceptions. Stated other criteria and exceptions must not directly affect the main Falco distribution (e.g., *falcoctl* can have a different release cycle and different policies; however, if Falco relies on a specific *falcoctl* feature, that *falcoctl* feature adoption and deprecation must be strictly compatible with the rules described in this proposal).
- Internal APIs are out of scope for this policy. Their adoption models and deprecation policies might be regulated separately.
- Different parties may provide plugins, and each plugin may have a different maturity level. Only those plugins officially maintained by The Falco Project and identified as "core" for Falco are in scope for this policy; all others are excluded.
- Any other exceptions to the rules provided by this policy require a formal core maintainer majority vote.
### Versioning
Regarding the above policies, component versioning must adhere to [Semantic Versioning 2.0.0](https://semver.org/). However, in the context of Falco core components, the scope extends beyond the strict API definition and includes any user-facing changes.
Thus, given a version number `MAJOR.MINOR.PATCH` increment the:
- *MAJOR* version when the deprecation period of one or more _stable_ features ends, thus introducing incompatible user-facing or API changes.
- *MINOR* version when adding functionality in a backward-compatible manner.
- *PATCH* version when making backward-compatible bug fixes.
Moreover, *MAJOR* version zero (0.y.z) is for versioning stabilization (i.e., before defining the public set of user-facing features and APIs). At this stage, the *MINOR* version is allowed to be incremented instead of the *MAJOR* version.
### Documentation
Documentation must be tied to a specific release and reflect the adoption level status of a feature at that specific release. In particular:
- Deprecated items must be labeled `DEPRECATED` in all relevant documentation.
- Stable items must be sufficiently documented. Explicitly labeling the Stable status is not required or recommended.
- Incubating items must be sufficiently documented and labeled `INCUBATING` in all relevant documentation.
- Sandbox items may be partially documented and labeled `SANDBOX` in all relevant documentation, if any. The relevant documentation must also explicitly state the experimental nature of the item.
## Transition Phases
Since software components may need to adapt to implement the requirements this proposal mandates, we assume the following stages are required to transition from the current state to the desired state fully:
- Within Falco 0.38, at least stable features must be identified, and the adoption policy and relevant documentation should be implemented in Falco. Exceptions may be made temporarily for the deprecation policy.
- Within subsequent releases and no later than Falco 1.0.0 (still not scheduled to date), all the policies must be strictly implemented in Falco and documented in [falco.org](falco.org). The [Rules Maturity Framework](https://github.com/falcosecurity/rules/blob/main/CONTRIBUTING.md#rules-maturity-framework) must be adapted to ensure it aligns with the spirit of this proposal. Exceptions may be made temporarily for other [core projects](https://github.com/falcosecurity/evolution#core) with [stable](https://github.com/falcosecurity/evolution/blob/main/REPOSITORIES.md#stable) status, assuming exceptions don't severely affect the main Falco distribution.
- Within Falco 1.1.0, all the policies must be strictly implemented in Falco and in all [core projects](https://github.com/falcosecurity/evolution#core) with [stable](https://github.com/falcosecurity/evolution/blob/main/REPOSITORIES.md#stable) status.
During the transition phases, maintainers can fine-tune these policies and add further exceptions, eventually. After this initial transition phases, the policy is assumed to be established. From then on, any policy modifications, updates, and exceptions must be subject to a core maintainer majority vote to ensure the policy remains relevant and practical.

View File

@@ -47,7 +47,18 @@ endif()
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)
list(APPEND FALCOCTL_DRIVER_TYPES_LIST "modern_ebpf")
endif()
if (BUILD_DRIVER)
list(APPEND FALCOCTL_DRIVER_TYPES_LIST "kmod")
endif()
if (BUILD_BPF)
list(APPEND FALCOCTL_DRIVER_TYPES_LIST "ebpf")
endif()
string(REPLACE ";" ", " FALCOCTL_DRIVER_TYPES "${FALCOCTL_DRIVER_TYPES_LIST}")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/falcoctl/falcoctl.yaml.in ${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()

View File

@@ -17,7 +17,8 @@
# limitations under the License.
#
chosen_driver=
# By default, we use the automatic selection for drivers
chosen_driver="auto"
chosen_unit=
CHOICE=
@@ -38,43 +39,56 @@ systemctl --system disable 'falcoctl-artifact-follow.service' || true
systemctl --system unmask falcoctl-artifact-follow.service || true
if [ "$1" = "configure" ]; then
# "auto" case is not managed here since it is already the default, so no CHOICE=2
case $FALCO_DRIVER_CHOICE in
kmod)
CHOICE=2
none)
CHOICE=1
;;
ebpf)
kmod)
CHOICE=3
;;
modern_ebpf)
ebpf)
CHOICE=4
;;
modern_ebpf)
CHOICE=5
;;
esac
if [ -z $CHOICE ] && [ -x /usr/bin/dialog ] && [ "${FALCO_FRONTEND}" != "noninteractive" ]; then
# If dialog is installed, create a dialog to let users choose the correct driver for them
CHOICE=$(dialog --clear --title "Falco drivers" --menu "Choose your preferred driver:" 12 55 4 \
1 "Manual configuration (no unit is started)" \
2 "Kmod" \
3 "eBPF" \
4 "Modern eBPF" \
2 "Automatic selection" \
3 "Kmod" \
4 "eBPF" \
5 "Modern eBPF" \
2>&1 >/dev/tty)
fi
fi
# "auto" case is not managed here since it is already the default, so no CHOICE=2
case $CHOICE in
2)
chosen_driver="kmod"
chosen_unit="kmod"
1)
chosen_driver=""
;;
3)
chosen_driver="ebpf"
chosen_unit="bpf"
chosen_driver="kmod"
;;
4)
chosen_driver="ebpf"
;;
5)
chosen_driver="modern_ebpf"
chosen_unit="modern-bpf"
;;
esac
if [ -n "$CHOICE" ]; then
echo "[POST-INSTALL] Configure falcoctl driver type:"
falcoctl driver config --type $chosen_driver
if [ -n "$chosen_driver" ]; then
echo "[POST-INSTALL] Configure falcoctl '$chosen_driver' driver type:"
if [ "$chosen_driver" = "auto" ]; then
# Configure falcoctl to enable all drivers
falcoctl driver config --type "modern_ebpf" --type "kmod" --type "ebpf"
# Load the actually automatic chosen driver
chosen_driver=$(falcoctl driver printenv | grep DRIVER= | cut -d'"' -f2)
else
falcoctl driver config --type "$chosen_driver"
fi
CHOICE=
case $FALCOCTL_ENABLED in
no)
@@ -108,10 +122,15 @@ case "$chosen_driver" in
# Only compile for kmod, in this way we use dkms
echo "[POST-INSTALL] Call 'falcoctl driver install for kmod:"
falcoctl driver install --download=false
chosen_unit="kmod"
;;
"ebpf")
echo "[POST-INSTALL] Call 'falcoctl driver install for ebpf':"
falcoctl driver install
chosen_unit="bpf"
;;
"modern_ebpf")
chosen_unit="modern-bpf"
;;
esac

View File

@@ -1,5 +1,5 @@
driver:
type: "kmod"
type: [@FALCOCTL_DRIVER_TYPES@]
name: "@DRIVER_NAME@"
repos:
- "@DRIVERS_REPO@"
@@ -10,7 +10,7 @@ artifact:
every: 6h0m0s
falcoVersions: http://localhost:8765/versions
refs:
- falco-rules:0
- falco-rules:3
indexes:
- name: falcosecurity
url: https://falcosecurity.github.io/falcoctl/index.yaml

View File

@@ -39,9 +39,15 @@ fi
s3_bucket_repo="s3://falco-distribution/packages/${repo}/${arch}"
cloudfront_path="/packages/${repo}/${arch}"
# sign
gpg --detach-sign --digest-algo SHA256 --armor ${file}
# publish
package=$(basename -- ${file})
echo "Publishing ${package} to ${s3_bucket_repo}..."
aws s3 cp ${file} ${s3_bucket_repo}/${package} --acl public-read
aws s3 cp ${file}.asc ${s3_bucket_repo}/${package}.asc --acl public-read
aws cloudfront create-invalidation --distribution-id ${AWS_CLOUDFRONT_DIST_ID} --paths ${cloudfront_path}/${package}
aws cloudfront create-invalidation --distribution-id ${AWS_CLOUDFRONT_DIST_ID} --paths ${cloudfront_path}/${package}
aws cloudfront create-invalidation --distribution-id ${AWS_CLOUDFRONT_DIST_ID} --paths ${cloudfront_path}/${package}.asc

View File

@@ -16,7 +16,8 @@
# limitations under the License.
#
chosen_driver=
# By default, we use the automatic selection for drivers
chosen_driver="auto"
chosen_unit=
CHOICE=
@@ -37,43 +38,56 @@ systemctl --system disable 'falcoctl-artifact-follow.service' || true
systemctl --system unmask falcoctl-artifact-follow.service || true
if [ $1 -ge 1 ]; then
# "auto" case is not managed here since it is already the default, so no CHOICE=2
case $FALCO_DRIVER_CHOICE in
kmod)
CHOICE=2
none)
CHOICE=1
;;
ebpf)
kmod)
CHOICE=3
;;
modern_ebpf)
ebpf)
CHOICE=4
;;
modern_ebpf)
CHOICE=5
;;
esac
if [ -z $CHOICE ] && [ -x /usr/bin/dialog ] && [ "${FALCO_FRONTEND}" != "noninteractive" ]; then
# If dialog is installed, create a dialog to let users choose the correct driver for them
CHOICE=$(dialog --clear --title "Falco drivers" --menu "Choose your preferred driver:" 12 55 4 \
1 "Manual configuration (no unit is started)" \
2 "Kmod" \
3 "eBPF" \
4 "Modern eBPF" \
2 "Automatic selection" \
3 "Kmod" \
4 "eBPF" \
5 "Modern eBPF" \
2>&1 >/dev/tty)
fi
fi
# "auto" case is not managed here since it is already the default, so no CHOICE=2
case $CHOICE in
2)
chosen_driver="kmod"
chosen_unit="kmod"
1)
chosen_driver=""
;;
3)
chosen_driver="ebpf"
chosen_unit="bpf"
chosen_driver="kmod"
;;
4)
chosen_driver="ebpf"
;;
5)
chosen_driver="modern_ebpf"
chosen_unit="modern-bpf"
;;
esac
if [ -n "$CHOICE" ]; then
echo "[POST-INSTALL] Configure falcoctl driver type:"
falcoctl driver config --type $chosen_driver
if [ -n "$chosen_driver" ]; then
echo "[POST-INSTALL] Configure falcoctl '$chosen_driver' driver type:"
if [ "$chosen_driver" = "auto" ]; then
# Configure falcoctl to enable all drivers
falcoctl driver config --type "modern_ebpf" --type "kmod" --type "ebpf"
# Load the actually automatic chosen driver
chosen_driver=$(falcoctl driver printenv | grep DRIVER= | cut -d'"' -f2)
else
falcoctl driver config --type "$chosen_driver"
fi
CHOICE=
case $FALCOCTL_ENABLED in
no)
@@ -105,12 +119,17 @@ systemctl --system daemon-reload || true
case "$chosen_driver" in
"kmod")
# Only compile for kmod, in this way we use dkms
echo "[POST-INSTALL] Call 'falcoctl driver install for kmod:"
falcoctl driver install --download=false
echo "[POST-INSTALL] Call 'falcoctl driver install for kmod:"
falcoctl driver install --download=false
chosen_unit="kmod"
;;
"ebpf")
echo "[POST-INSTALL] Call 'falcoctl driver install for ebpf':"
falcoctl driver install
chosen_unit="bpf"
;;
"modern_ebpf")
chosen_unit="modern-bpf"
;;
esac

View File

@@ -44,6 +44,7 @@ add_executable(falco_unit_tests
engine/test_rule_loader.cpp
engine/test_rulesets.cpp
falco/test_configuration.cpp
falco/test_configuration_rule_selection.cpp
falco/app/actions/test_select_event_sources.cpp
falco/app/actions/test_load_config.cpp
)
@@ -65,10 +66,13 @@ PRIVATE
${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}
)
if (EMSCRIPTEN)

View File

@@ -263,11 +263,11 @@ static void load_rules(sinsp& inspector,
rule_loader::collector collector;
rule_loader::compiler compiler;
EXPECT_TRUE(reader.read(*(cfg.get()), collector));
EXPECT_TRUE(reader.read(*cfg, collector));
compile_output = compiler.new_compile_output();
compiler.compile(*(cfg.get()), collector, *(compile_output.get()));
compiler.compile(*cfg, collector, *compile_output);
}
TEST(engine_loader_alt_loader, load_rules)
@@ -303,16 +303,15 @@ 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.get()),
ruleset->add_compile_output(*compile_output,
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
// should be enabled.
bool match_exact = true;
uint16_t ruleset_id = 0;
ruleset->enable("", match_exact, ruleset_id);
ruleset->enable("", filter_ruleset::match_type::substring, ruleset_id);
EXPECT_EQ(ruleset->enabled_count(ruleset_id), 1);
}

View File

@@ -44,6 +44,36 @@ static std::string single_rule = R"END(
tags: [exec process]
)END";
static std::string multi_rule = R"END(
- rule: first actual rule
desc: A test rule
condition: evt.type=execve
output: A test rule matched (evt.type=%evt.type)
priority: INFO
source: syscall
tags: [process]
- rule: second disabled rule
desc: A disabled rule
condition: evt.type=execve
output: A disabled 2 rule matched (evt.type=%evt.type)
priority: INFO
source: syscall
enabled: false
tags: [exec process]
- rule: third disabled rule
desc: A disabled rule
condition: evt.type=execve
output: A disabled 3 rule matched (evt.type=%evt.type)
priority: INFO
source: syscall
enabled: false
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";
@@ -216,3 +246,41 @@ TEST_F(test_falco_engine, enable_rule_name_exact)
EXPECT_EQ(0, m_engine->num_rules_for_ruleset(ruleset_3));
EXPECT_EQ(2, m_engine->num_rules_for_ruleset(ruleset_4));
}
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));
EXPECT_EQ(0, m_engine->num_rules_for_ruleset(ruleset_1));
EXPECT_EQ(0, m_engine->num_rules_for_ruleset(ruleset_2));
EXPECT_EQ(0, m_engine->num_rules_for_ruleset(ruleset_3));
EXPECT_EQ(0, m_engine->num_rules_for_ruleset(ruleset_4));
// As long as there are no *, exact matches work
m_engine->enable_rule_wildcard("first actual rule", true, ruleset_1);
EXPECT_EQ(1, m_engine->num_rules_for_ruleset(ruleset_1));
EXPECT_EQ(0, m_engine->num_rules_for_ruleset(ruleset_2));
EXPECT_EQ(0, m_engine->num_rules_for_ruleset(ruleset_3));
EXPECT_EQ(0, m_engine->num_rules_for_ruleset(ruleset_4));
m_engine->enable_rule_wildcard("*rule", true, ruleset_2);
EXPECT_EQ(1, m_engine->num_rules_for_ruleset(ruleset_1));
EXPECT_EQ(3, m_engine->num_rules_for_ruleset(ruleset_2));
EXPECT_EQ(0, m_engine->num_rules_for_ruleset(ruleset_3));
EXPECT_EQ(0, m_engine->num_rules_for_ruleset(ruleset_4));
// This should enable the second rule
m_engine->enable_rule_wildcard("*second*r*", true, ruleset_3);
EXPECT_EQ(1, m_engine->num_rules_for_ruleset(ruleset_1));
EXPECT_EQ(3, m_engine->num_rules_for_ruleset(ruleset_2));
EXPECT_EQ(1, m_engine->num_rules_for_ruleset(ruleset_3));
EXPECT_EQ(0, m_engine->num_rules_for_ruleset(ruleset_4));
m_engine->enable_rule_wildcard("*", true, ruleset_4);
EXPECT_EQ(1, m_engine->num_rules_for_ruleset(ruleset_1));
EXPECT_EQ(3, m_engine->num_rules_for_ruleset(ruleset_2));
EXPECT_EQ(1, m_engine->num_rules_for_ruleset(ruleset_3));
EXPECT_EQ(3, m_engine->num_rules_for_ruleset(ruleset_4));
}

View File

@@ -72,3 +72,32 @@ TEST(FalcoUtils, parse_prometheus_interval)
*/
ASSERT_EQ(falco::utils::parse_prometheus_interval("200"), 0UL);
}
TEST(FalcoUtils, sanitize_metric_name)
{
ASSERT_EQ(falco::utils::sanitize_metric_name("Testing rule 2 (CVE-2244)"), "Testing_rule_2_CVE_2244");
ASSERT_EQ(falco::utils::sanitize_metric_name("Testing rule__:2)"), "Testing_rule_:2");
ASSERT_EQ(falco::utils::sanitize_metric_name("This@is_a$test rule123"), "This_is_a_test_rule123");
ASSERT_EQ(falco::utils::sanitize_metric_name("RULEwith:special#characters"), "RULEwith:special_characters");
}
TEST(FalcoUtils, matches_wildcard)
{
ASSERT_TRUE(falco::utils::matches_wildcard("*", "anything"));
ASSERT_TRUE(falco::utils::matches_wildcard("**", "anything"));
ASSERT_TRUE(falco::utils::matches_wildcard("*", ""));
ASSERT_TRUE(falco::utils::matches_wildcard("no star", "no star"));
ASSERT_TRUE(falco::utils::matches_wildcard("", ""));
ASSERT_TRUE(falco::utils::matches_wildcard("hello*world", "hello new world"));
ASSERT_TRUE(falco::utils::matches_wildcard("hello*world*", "hello new world yes"));
ASSERT_TRUE(falco::utils::matches_wildcard("*hello*world", "come on hello this world"));
ASSERT_TRUE(falco::utils::matches_wildcard("*hello*****world", "come on hello this world"));
ASSERT_FALSE(falco::utils::matches_wildcard("no star", ""));
ASSERT_FALSE(falco::utils::matches_wildcard("", "no star"));
ASSERT_FALSE(falco::utils::matches_wildcard("star", "no star"));
ASSERT_FALSE(falco::utils::matches_wildcard("hello*world", "hello new thing"));
ASSERT_FALSE(falco::utils::matches_wildcard("hello*world", "hello new world yes"));
ASSERT_FALSE(falco::utils::matches_wildcard("*hello*world", "come on hello this world yes"));
ASSERT_FALSE(falco::utils::matches_wildcard("*hello*world*", "come on hello this yes"));
}

View File

@@ -8,7 +8,7 @@ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless ASSERT_EQd by applicable law or agreed to in writing, software
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
@@ -18,6 +18,8 @@ limitations under the License.
#include <gtest/gtest.h>
#include <engine/filter_macro_resolver.h>
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)
@@ -35,19 +37,19 @@ static std::vector<filter_macro_resolver::value_info>::const_iterator find_value
TEST(MacroResolver, should_resolve_macros_on_a_filter_AST)
{
libsinsp::filter::ast::pos_info macro_pos(12, 85, 27);
filter_ast::pos_info macro_pos(12, 85, 27);
std::shared_ptr<libsinsp::filter::ast::expr> macro = libsinsp::filter::ast::unary_check_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<libsinsp::filter::ast::expr>> filter_and;
filter_and.push_back(libsinsp::filter::ast::unary_check_expr::create("evt.name", "", "exists"));
filter_and.push_back(libsinsp::filter::ast::not_expr::create(libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos)));
std::shared_ptr<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::and_expr::create(filter_and);
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)));
std::shared_ptr<filter_ast::expr> filter = filter_ast::and_expr::create(filter_and);
std::vector<std::unique_ptr<libsinsp::filter::ast::expr>> expected_and;
expected_and.push_back(libsinsp::filter::ast::unary_check_expr::create("evt.name", "", "exists"));
expected_and.push_back(libsinsp::filter::ast::not_expr::create(clone(macro.get())));
std::shared_ptr<libsinsp::filter::ast::expr> expected = libsinsp::filter::ast::and_expr::create(expected_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::not_expr::create(clone(macro.get())));
std::shared_ptr<filter_ast::expr> expected = filter_ast::and_expr::create(expected_and);
filter_macro_resolver resolver;
resolver.set_macro(MACRO_NAME, macro);
@@ -69,17 +71,17 @@ TEST(MacroResolver, should_resolve_macros_on_a_filter_AST)
TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_single_node)
{
libsinsp::filter::ast::pos_info macro_pos(12, 85, 27);
filter_ast::pos_info macro_pos(12, 85, 27);
std::shared_ptr<libsinsp::filter::ast::expr> macro = libsinsp::filter::ast::unary_check_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<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::value_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);
// first run
libsinsp::filter::ast::expr* old_filter_ptr = filter.get();
filter_ast::expr* old_filter_ptr = filter.get();
ASSERT_TRUE(resolver.run(filter));
ASSERT_NE(filter.get(), old_filter_ptr);
ASSERT_EQ(resolver.get_resolved_macros().size(), 1);
@@ -99,21 +101,21 @@ TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_single_node)
TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_multiple_macros)
{
libsinsp::filter::ast::pos_info a_macro_pos(11, 75, 43);
libsinsp::filter::ast::pos_info b_macro_pos(91, 21, 9);
filter_ast::pos_info a_macro_pos(11, 75, 43);
filter_ast::pos_info b_macro_pos(91, 21, 9);
std::shared_ptr<libsinsp::filter::ast::expr> a_macro = libsinsp::filter::ast::unary_check_expr::create("one.field", "", "exists");
std::shared_ptr<libsinsp::filter::ast::expr> b_macro = libsinsp::filter::ast::unary_check_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<libsinsp::filter::ast::expr>> filter_or;
filter_or.push_back(libsinsp::filter::ast::value_expr::create(MACRO_A_NAME, a_macro_pos));
filter_or.push_back(libsinsp::filter::ast::value_expr::create(MACRO_B_NAME, b_macro_pos));
std::shared_ptr<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::or_expr::create(filter_or);
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));
filter_or.push_back(filter_ast::identifier_expr::create(MACRO_B_NAME, b_macro_pos));
std::shared_ptr<filter_ast::expr> filter = filter_ast::or_expr::create(filter_or);
std::vector<std::unique_ptr<libsinsp::filter::ast::expr>> expected_or;
std::vector<std::unique_ptr<filter_ast::expr>> expected_or;
expected_or.push_back(clone(a_macro.get()));
expected_or.push_back(clone(b_macro.get()));
std::shared_ptr<libsinsp::filter::ast::expr> expected_filter = libsinsp::filter::ast::or_expr::create(expected_or);
std::shared_ptr<filter_ast::expr> expected_filter = filter_ast::or_expr::create(expected_or);
filter_macro_resolver resolver;
resolver.set_macro(MACRO_A_NAME, a_macro);
@@ -143,23 +145,23 @@ TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_multiple_macros)
TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_nested_macros)
{
libsinsp::filter::ast::pos_info a_macro_pos(47, 1, 76);
libsinsp::filter::ast::pos_info b_macro_pos(111, 65, 2);
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<libsinsp::filter::ast::expr>> a_macro_and;
a_macro_and.push_back(libsinsp::filter::ast::unary_check_expr::create("one.field", "", "exists"));
a_macro_and.push_back(libsinsp::filter::ast::value_expr::create(MACRO_B_NAME, b_macro_pos));
std::shared_ptr<libsinsp::filter::ast::expr> a_macro = libsinsp::filter::ast::and_expr::create(a_macro_and);
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::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<libsinsp::filter::ast::expr> b_macro =
libsinsp::filter::ast::unary_check_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<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::value_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<libsinsp::filter::ast::expr>> expected_and;
expected_and.push_back(libsinsp::filter::ast::unary_check_expr::create("one.field", "", "exists"));
expected_and.push_back(libsinsp::filter::ast::unary_check_expr::create("another.field", "", "exists"));
std::shared_ptr<libsinsp::filter::ast::expr> expected_filter = libsinsp::filter::ast::and_expr::create(expected_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("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;
resolver.set_macro(MACRO_A_NAME, a_macro);
@@ -191,12 +193,12 @@ TEST(MacroResolver, should_resolve_macros_on_a_filter_AST_nested_macros)
TEST(MacroResolver, should_find_unknown_macros)
{
libsinsp::filter::ast::pos_info macro_pos(9, 4, 2);
filter_ast::pos_info macro_pos(9, 4, 2);
std::vector<std::unique_ptr<libsinsp::filter::ast::expr>> filter_and;
filter_and.push_back(libsinsp::filter::ast::unary_check_expr::create("evt.name", "", "exists"));
filter_and.push_back(libsinsp::filter::ast::not_expr::create(libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos)));
std::shared_ptr<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::and_expr::create(filter_and);
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)));
std::shared_ptr<filter_ast::expr> filter = filter_ast::and_expr::create(filter_and);
filter_macro_resolver resolver;
ASSERT_FALSE(resolver.run(filter));
@@ -208,15 +210,15 @@ TEST(MacroResolver, should_find_unknown_macros)
TEST(MacroResolver, should_find_unknown_nested_macros)
{
libsinsp::filter::ast::pos_info a_macro_pos(32, 84, 9);
libsinsp::filter::ast::pos_info b_macro_pos(1, 0, 5);
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<libsinsp::filter::ast::expr>> a_macro_and;
a_macro_and.push_back(libsinsp::filter::ast::unary_check_expr::create("one.field", "", "exists"));
a_macro_and.push_back(libsinsp::filter::ast::value_expr::create(MACRO_B_NAME, b_macro_pos));
std::shared_ptr<libsinsp::filter::ast::expr> a_macro = libsinsp::filter::ast::and_expr::create(a_macro_and);
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::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<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::value_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,12 +236,12 @@ TEST(MacroResolver, should_find_unknown_nested_macros)
TEST(MacroResolver, should_undefine_macro)
{
libsinsp::filter::ast::pos_info macro_pos_1(12, 9, 3);
libsinsp::filter::ast::pos_info macro_pos_2(9, 6, 3);
filter_ast::pos_info macro_pos_1(12, 9, 3);
filter_ast::pos_info macro_pos_2(9, 6, 3);
std::shared_ptr<libsinsp::filter::ast::expr> macro = libsinsp::filter::ast::unary_check_expr::create("test.field", "", "exists");
std::shared_ptr<libsinsp::filter::ast::expr> a_filter = libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos_1);
std::shared_ptr<libsinsp::filter::ast::expr> b_filter = libsinsp::filter::ast::value_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,9 +263,9 @@ TEST(MacroResolver, should_undefine_macro)
/* checks that the macro AST is cloned and not shared across resolved filters */
TEST(MacroResolver, should_clone_macro_AST)
{
libsinsp::filter::ast::pos_info macro_pos(5, 2, 8888);
std::shared_ptr<libsinsp::filter::ast::unary_check_expr> macro = libsinsp::filter::ast::unary_check_expr::create("test.field", "", "exists");
std::shared_ptr<libsinsp::filter::ast::expr> filter = libsinsp::filter::ast::value_expr::create(MACRO_NAME, macro_pos);
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);
filter_macro_resolver resolver;
resolver.set_macro(MACRO_NAME, macro);
@@ -274,6 +276,6 @@ TEST(MacroResolver, should_clone_macro_AST)
ASSERT_TRUE(resolver.get_unknown_macros().empty());
ASSERT_TRUE(filter->is_equal(macro.get()));
macro->field = "another.field";
macro->left = filter_ast::field_expr::create("another.field", "");
ASSERT_FALSE(filter->is_equal(macro.get()));
}

View File

@@ -8,7 +8,7 @@ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless ASSERTd by applicable law or agreed to in writing, software
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

View File

@@ -680,6 +680,42 @@ 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(
- rule: test_rule
desc: test rule description
condition: evt.type = close
output: user=%user.name command=%proc.cmdline file=%fd.name
priority: INFO
exceptions:
- name: test_exception
fields: proc.name
comps: in
values: ["cat"]
# when appending, it's fine to provide partial exception definitions
- rule: test_rule
exceptions:
- name: test_exception
values: [echo]
override:
exceptions: append
# when replacing, we don't allow partial exception definitions
- rule: test_rule
exceptions:
- name: test_exception
values: [id]
override:
exceptions: replace
)END";
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
ASSERT_FALSE(has_warnings());
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(
@@ -845,4 +881,300 @@ TEST_F(test_falco_engine, list_value_with_escaping)
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");
}
}
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
output: command=%proc.cmdline
priority: INFO
exceptions:
- name: test_exception
fields: [proc.cmdline]
comps: [contains]
values:
- [curl 127.0.0.1]
)END";
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
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(
- macro: test-macro
condition: evt.type = close
)END";
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
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(
- list: test list
items: [open, openat, openat2]
- rule: test_rule
desc: test rule description
condition: evt.type in (test list)
output: user=%user.name command=%proc.cmdline file=%fd.name
priority: INFO
enabled: false
)END";
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
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(
- rule: test_rule
desc: test rule
condition: proc.cmdline contains curl
output: command=%proc.cmdline
priority: INFO
exceptions:
- name: test_exception
fields: [proc.cmdline]
comps: [contains]
values:
- [curl 127.0.0.1]
- rule: test_rule
exceptions:
- name: test_exception
value: curl 1.1.1.1
append: true
)END";
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
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(
- rule: test_rule
desc: test rule
condition: proc.cmdline contains curl
output: command=%proc.cmdline
priority: INFO
exceptions:
- name: test_exception
fields: [proc.cmdline]
comps: [contains]
values:
- [curl 127.0.0.1]
- rule: test_rule
exceptions:
- name: test_exception
value: curl 1.1.1.1
override:
exceptions: append
)END";
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
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(
- rule: test_rule
desc: test rule
condition: proc.cmdline contains curl
output: command=%proc.cmdline
priority: INFO
exceptions:
- name: test_exception
fields: [proc.cmdline]
comps: [contains]
values:
- [curl 127.0.0.1]
- name: test_exception
fields: [proc.cmdline]
comps: [endswith]
values:
- [curl 127.0.0.1]
)END";
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
ASSERT_TRUE(check_warning_message("Multiple definitions of exception"));
}
static std::string s_exception_values_rule_base = R"END(
- rule: test_rule
desc: test rule
condition: evt.type = open
output: command=%proc.cmdline
priority: INFO
)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]
comps: [=]
values:
- [proc.pname]
)END";
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not proc.name = proc.pname)");
EXPECT_TRUE(check_warning_message("string 'proc.pname' may be a valid field wrongly interpreted as a string value"));
}
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]
comps: [=]
values:
- ["proc.pname"]
)END";
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not proc.name = proc.pname)");
EXPECT_TRUE(check_warning_message("string 'proc.pname' may be a valid field wrongly interpreted as a string value"));
}
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]
comps: [=]
values:
- ["proc.pname "]
)END";
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not proc.name = \"proc.pname \")");
EXPECT_TRUE(check_warning_message("string 'proc.pname ' may be a valid field wrongly interpreted as a string value"));
}
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]
comps: [=]
values:
- [toupper(proc.pname)]
)END";
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
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(
exceptions:
- name: test_exception
fields: [proc.name]
comps: [=]
values:
- ["toupper(proc.pname)"]
)END";
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
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(
exceptions:
- name: test_exception
fields: [proc.name]
comps: [=]
values:
- [toupper( proc.pname)]
)END";
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not proc.name = \"toupper( proc.pname)\")");
EXPECT_TRUE(check_warning_message("string 'toupper( proc.pname)' may be a valid field transformer wrongly interpreted as a string value"));
}
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]
comps: [=]
values:
- ["toupper( proc.pname)"]
)END";
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not proc.name = \"toupper( proc.pname)\")");
EXPECT_TRUE(check_warning_message("string 'toupper( proc.pname)' may be a valid field transformer wrongly interpreted as a string value"));
}
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)]
comps: [=]
values:
- [test]
)END";
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
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(
exceptions:
- name: test_exception
fields: ["tolower(proc.name)"]
comps: [=]
values:
- [test]
)END";
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
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(
exceptions:
- name: test_exception
fields: ["tolower( proc.name)"]
comps: [=]
values:
- [test]
)END";
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
ASSERT_FALSE(has_warnings());
EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not tolower(proc.name) = test)");
}

View File

@@ -74,46 +74,70 @@ TEST(Ruleset, enable_disable_rules_using_names)
r->add(rule_C, filter, ast);
/* Enable `rule_A` for RULESET_0 */
r->enable(rule_A.name, true, RULESET_0);
r->enable(rule_A.name, filter_ruleset::match_type::exact, RULESET_0);
ASSERT_EQ(r->enabled_count(RULESET_0), 1);
ASSERT_EQ(r->enabled_count(RULESET_1), 0);
ASSERT_EQ(r->enabled_count(RULESET_2), 0);
/* Disable `rule_A` for RULESET_1, this should have no effect */
r->disable(rule_A.name, true, RULESET_1);
r->disable(rule_A.name, filter_ruleset::match_type::exact, RULESET_1);
ASSERT_EQ(r->enabled_count(RULESET_0), 1);
ASSERT_EQ(r->enabled_count(RULESET_1), 0);
ASSERT_EQ(r->enabled_count(RULESET_2), 0);
/* Enable a not existing rule for RULESET_2, this should have no effect */
r->disable("<NA>", true, RULESET_2);
r->disable("<NA>", filter_ruleset::match_type::exact, RULESET_2);
ASSERT_EQ(r->enabled_count(RULESET_0), 1);
ASSERT_EQ(r->enabled_count(RULESET_1), 0);
ASSERT_EQ(r->enabled_count(RULESET_2), 0);
/* Enable all rules for RULESET_0 */
r->enable("rule_", false, RULESET_0);
r->enable("rule_", filter_ruleset::match_type::substring, RULESET_0);
ASSERT_EQ(r->enabled_count(RULESET_0), 3);
ASSERT_EQ(r->enabled_count(RULESET_1), 0);
ASSERT_EQ(r->enabled_count(RULESET_2), 0);
/* Try to disable all rules with exact match for RULESET_0, this should have no effect */
r->disable("rule_", true, RULESET_0);
r->disable("rule_", filter_ruleset::match_type::exact, RULESET_0);
ASSERT_EQ(r->enabled_count(RULESET_0), 3);
ASSERT_EQ(r->enabled_count(RULESET_1), 0);
ASSERT_EQ(r->enabled_count(RULESET_2), 0);
/* Disable all rules for RULESET_0 */
r->disable("rule_", false, RULESET_0);
r->disable("rule_", filter_ruleset::match_type::substring, RULESET_0);
ASSERT_EQ(r->enabled_count(RULESET_0), 0);
ASSERT_EQ(r->enabled_count(RULESET_1), 0);
ASSERT_EQ(r->enabled_count(RULESET_2), 0);
/* Enable rule_C for RULESET_2 without exact_match */
r->enable("_C", false, RULESET_2);
r->enable("_C", filter_ruleset::match_type::substring, RULESET_2);
ASSERT_EQ(r->enabled_count(RULESET_0), 0);
ASSERT_EQ(r->enabled_count(RULESET_1), 0);
ASSERT_EQ(r->enabled_count(RULESET_2), 1);
/* Disable rule_C for RULESET_2 without exact_match */
r->disable("_C", filter_ruleset::match_type::substring, RULESET_2);
ASSERT_EQ(r->enabled_count(RULESET_0), 0);
ASSERT_EQ(r->enabled_count(RULESET_1), 0);
ASSERT_EQ(r->enabled_count(RULESET_2), 0);
/* Enable all rules for RULESET_0 with wildcard */
r->enable("*", filter_ruleset::match_type::wildcard, RULESET_0);
ASSERT_EQ(r->enabled_count(RULESET_0), 3);
ASSERT_EQ(r->enabled_count(RULESET_1), 0);
ASSERT_EQ(r->enabled_count(RULESET_2), 0);
/* Disable rule C for RULESET_0 with wildcard */
r->disable("*C*", filter_ruleset::match_type::wildcard, RULESET_0);
ASSERT_EQ(r->enabled_count(RULESET_0), 2);
ASSERT_EQ(r->enabled_count(RULESET_1), 0);
ASSERT_EQ(r->enabled_count(RULESET_2), 0);
/* Disable all rules for RULESET_0 with wildcard */
r->disable("*_*", filter_ruleset::match_type::wildcard, RULESET_0);
ASSERT_EQ(r->enabled_count(RULESET_0), 0);
ASSERT_EQ(r->enabled_count(RULESET_1), 0);
ASSERT_EQ(r->enabled_count(RULESET_2), 0);
}
TEST(Ruleset, enable_disable_rules_using_tags)

View File

@@ -108,6 +108,7 @@ TEST_F(test_falco_engine, preconditions_postconditions)
s1.engine = nullptr;
s1.config = std::make_shared<falco_configuration>();
s1.options.all_events = false;
auto result = falco::app::actions::configure_interesting_sets(s1);
ASSERT_FALSE(result.success);
ASSERT_NE(result.errstr, "");

View File

@@ -8,7 +8,7 @@ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless ASSERTd by applicable law or agreed to in writing, software
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

View File

@@ -8,7 +8,7 @@ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless ASSERTd by applicable law or agreed to in writing, software
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

View File

@@ -8,7 +8,7 @@ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless ASSERTd by applicable law or agreed to in writing, software
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

View File

@@ -8,7 +8,7 @@ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless ASSERTd by applicable law or agreed to in writing, software
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
@@ -16,7 +16,7 @@ limitations under the License.
*/
#include <falco/atomic_signal_handler.h>
#include <falco/logger.h>
#include <engine/logger.h>
#include <gtest/gtest.h>

View File

@@ -8,7 +8,7 @@ You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless ASSERTd by applicable law or agreed to in writing, software
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
@@ -109,6 +109,484 @@ TEST(Configuration, modify_yaml_fields)
ASSERT_EQ(conf.get_scalar<bool>(key, false), true);
}
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;
outfile.close();
outfile.open("conf_2.yaml");
outfile << conf_yaml_2;
outfile.close();
std::vector<std::string> cmdline_config_options;
std::vector<std::string> loaded_conf_files;
falco_configuration falco_config;
ASSERT_ANY_THROW(falco_config.init_from_file("main.yaml", loaded_conf_files, cmdline_config_options));
std::filesystem::remove("main.yaml");
std::filesystem::remove("conf_2.yaml");
}
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 conf_yaml_2 =
"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";
const std::string conf_yaml_4 =
"base_value_4:\n"
" id: 4\n";
std::ofstream outfile("main.yaml");
outfile << main_conf_yaml;
outfile.close();
outfile.open("conf_2.yaml");
outfile << conf_yaml_2;
outfile.close();
outfile.open("conf_3.yaml");
outfile << conf_yaml_3;
outfile.close();
outfile.open("conf_4.yaml");
outfile << conf_yaml_4;
outfile.close();
std::vector<std::string> cmdline_config_options;
std::vector<std::string> loaded_conf_files;
falco_configuration falco_config;
ASSERT_NO_THROW(falco_config.init_from_file("main.yaml", loaded_conf_files, cmdline_config_options));
// main + conf_2 + conf_3
ASSERT_EQ(loaded_conf_files.size(), 3);
ASSERT_TRUE(falco_config.config.is_defined("foo"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo", ""), "bar");
ASSERT_TRUE(falco_config.config.is_defined("base_value.id"));
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value.id", 0), 1);
ASSERT_TRUE(falco_config.config.is_defined("base_value.name"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("base_value.name", ""), "foo");
ASSERT_TRUE(falco_config.config.is_defined("foo2"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo2", ""), "bar2");
ASSERT_TRUE(falco_config.config.is_defined("base_value_2.id"));
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value_2.id", 0), 2);
ASSERT_TRUE(falco_config.config.is_defined("foo3"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo3", ""), "bar3");
ASSERT_TRUE(falco_config.config.is_defined("base_value_3.id"));
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value_3.id", 0), 3);
ASSERT_TRUE(falco_config.config.is_defined("base_value_3.name"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("base_value_3.name", ""), "foo3");
ASSERT_FALSE(falco_config.config.is_defined("base_value_4.id")); // conf_4 is not included
std::filesystem::remove("main.yaml");
std::filesystem::remove("conf_2.yaml");
std::filesystem::remove("conf_3.yaml");
std::filesystem::remove("conf_4.yaml");
}
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.
*/
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 conf_yaml_2 =
"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";
std::ofstream outfile(temp_main.string());
outfile << main_conf_yaml;
outfile.close();
outfile.open("conf_2.yaml");
outfile << conf_yaml_2;
outfile.close();
outfile.open("conf_3.yaml");
outfile << conf_yaml_3;
outfile.close();
std::vector<std::string> cmdline_config_options;
std::vector<std::string> loaded_conf_files;
falco_configuration falco_config;
ASSERT_NO_THROW(falco_config.init_from_file(temp_main.string(), loaded_conf_files, cmdline_config_options));
// main + conf_2 + conf_3
ASSERT_EQ(loaded_conf_files.size(), 3);
ASSERT_TRUE(falco_config.config.is_defined("foo"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo", ""), "bar");
ASSERT_TRUE(falco_config.config.is_defined("base_value.id"));
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value.id", 0), 1);
ASSERT_TRUE(falco_config.config.is_defined("base_value.name"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("base_value.name", ""), "foo");
ASSERT_TRUE(falco_config.config.is_defined("foo2"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo2", ""), "bar2");
ASSERT_TRUE(falco_config.config.is_defined("base_value_2"));
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value_2.id", 0), 2);
ASSERT_TRUE(falco_config.config.is_defined("base_value_3.id"));
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value_3.id", 0), 3);
std::filesystem::remove(temp_main.string());
std::filesystem::remove("conf_2.yaml");
std::filesystem::remove("conf_3.yaml");
}
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 conf_yaml_2 =
"foo2: bar2\n"
"base_value_2:\n"
" id: 2\n";
const std::string conf_yaml_3 =
"base_value:\n"
" id: 3\n";
std::ofstream outfile("main.yaml");
outfile << main_conf_yaml;
outfile.close();
outfile.open("conf_2.yaml");
outfile << conf_yaml_2;
outfile.close();
outfile.open("conf_3.yaml");
outfile << conf_yaml_3;
outfile.close();
std::vector<std::string> cmdline_config_options;
std::vector<std::string> loaded_conf_files;
falco_configuration falco_config;
ASSERT_NO_THROW(falco_config.init_from_file("main.yaml", loaded_conf_files, cmdline_config_options));
// main + conf_2 + conf_3
ASSERT_EQ(loaded_conf_files.size(), 3);
ASSERT_TRUE(falco_config.config.is_defined("foo"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo", ""), "bar");
ASSERT_TRUE(falco_config.config.is_defined("base_value.id"));
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value.id", 0), 3); // overridden!
ASSERT_FALSE(falco_config.config.is_defined("base_value.name")); // no more present since entire `base_value` block was overridden
ASSERT_TRUE(falco_config.config.is_defined("foo2"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo2", ""), "bar2");
ASSERT_TRUE(falco_config.config.is_defined("base_value_2.id"));
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value_2.id", 0), 2);
ASSERT_FALSE(falco_config.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 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";
std::ofstream outfile("main.yaml");
outfile << main_conf_yaml;
outfile.close();
std::vector<std::string> cmdline_config_options;
std::vector<std::string> loaded_conf_files;
falco_configuration falco_config;
ASSERT_NO_THROW(falco_config.init_from_file("main.yaml", loaded_conf_files, cmdline_config_options));
// main
ASSERT_EQ(loaded_conf_files.size(), 1);
ASSERT_TRUE(falco_config.config.is_defined("base_value.id"));
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value.id", 0), 1);
ASSERT_TRUE(falco_config.config.is_defined("base_value.name"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("base_value.name", ""), "foo");
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";
const std::string conf_yaml_2 =
"foo2: bar2\n"
"base_value_2:\n"
" id: 2\n";
std::ofstream outfile("main.yaml");
outfile << main_conf_yaml;
outfile.close();
outfile.open("conf_2.yaml");
outfile << conf_yaml_2;
outfile.close();
std::vector<std::string> cmdline_config_options;
std::vector<std::string> loaded_conf_files;
falco_configuration falco_config;
ASSERT_NO_THROW(falco_config.init_from_file("main.yaml", loaded_conf_files, cmdline_config_options));
// main + conf_2
ASSERT_EQ(loaded_conf_files.size(), 2);
ASSERT_TRUE(falco_config.config.is_defined("foo"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo", ""), "bar");
ASSERT_TRUE(falco_config.config.is_defined("base_value.id"));
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value.id", 0), 1);
ASSERT_TRUE(falco_config.config.is_defined("base_value.name"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("base_value.name", ""), "foo");
ASSERT_TRUE(falco_config.config.is_defined("foo2"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo2", ""), "bar2");
ASSERT_TRUE(falco_config.config.is_defined("base_value_2.id"));
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value_2.id", 0), 2);
std::filesystem::remove("main.yaml");
std::filesystem::remove("conf_2.yaml");
}
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";
std::ofstream outfile("main.yaml");
outfile << main_conf_yaml;
outfile.close();
std::vector<std::string> cmdline_config_options;
std::vector<std::string> loaded_conf_files;
falco_configuration falco_config;
ASSERT_NO_THROW(falco_config.init_from_file("main.yaml", loaded_conf_files, cmdline_config_options));
// main
ASSERT_EQ(loaded_conf_files.size(), 1);
ASSERT_TRUE(falco_config.config.is_defined("foo"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo", ""), "bar");
ASSERT_TRUE(falco_config.config.is_defined("base_value.id"));
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value.id", 0), 1);
ASSERT_TRUE(falco_config.config.is_defined("base_value.name"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("base_value.name", ""), "foo");
std::filesystem::remove("main.yaml");
}
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";
std::ofstream outfile("main.yaml");
outfile << main_conf_yaml;
outfile.close();
std::vector<std::string> cmdline_config_options;
std::vector<std::string> loaded_conf_files;
falco_configuration falco_config;
ASSERT_ANY_THROW(falco_config.init_from_file("main.yaml", loaded_conf_files, cmdline_config_options));
std::filesystem::remove("main.yaml");
}
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 conf_yaml_2 =
"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";
std::filesystem::create_directory(std::filesystem::temp_directory_path() / "test");
std::ofstream outfile("main.yaml");
outfile << main_conf_yaml;
outfile.close();
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 << 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 << conf_yaml_4;
outfile.close();
std::vector<std::string> cmdline_config_options;
std::vector<std::string> loaded_conf_files;
falco_configuration falco_config;
ASSERT_NO_THROW(falco_config.init_from_file("main.yaml", loaded_conf_files, cmdline_config_options));
// main + conf_2 + conf_3.
// test/foo is not parsed.
ASSERT_EQ(loaded_conf_files.size(), 3);
ASSERT_TRUE(falco_config.config.is_defined("foo"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo", ""), "bar");
ASSERT_TRUE(falco_config.config.is_defined("base_value.id"));
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value.id", 0), 1);
ASSERT_TRUE(falco_config.config.is_defined("base_value.name"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("base_value.name", ""), "foo");
ASSERT_TRUE(falco_config.config.is_defined("base_value_2"));
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value_2.id", 0), 2);
ASSERT_TRUE(falco_config.config.is_defined("base_value_3.id"));
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value_3.id", 0), 3);
ASSERT_TRUE(falco_config.config.is_defined("foo2"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo2", ""), "bar3");
ASSERT_FALSE(falco_config.config.is_defined("foo4"));
std::filesystem::remove("main");
std::filesystem::remove_all(std::filesystem::temp_directory_path()/"test");
}
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";
const std::string conf_yaml_2 =
"foo2: bar2\n"
"base_value_2:\n"
" id: 2\n";
std::ofstream outfile("main.yaml");
outfile << main_conf_yaml;
outfile.close();
outfile.open("conf_2.yaml");
outfile << conf_yaml_2;
outfile.close();
// Pass "config_files=..." cmdline option
std::vector<std::string> cmdline_config_options;
cmdline_config_options.push_back((yaml_helper::configs_key+"=conf_2.yaml"));
std::vector<std::string> loaded_conf_files;
falco_configuration falco_config;
ASSERT_NO_THROW(falco_config.init_from_file("main.yaml", loaded_conf_files, cmdline_config_options));
// main + conf_2
ASSERT_EQ(loaded_conf_files.size(), 2);
ASSERT_TRUE(falco_config.config.is_defined("foo"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo", ""), "bar");
ASSERT_TRUE(falco_config.config.is_defined("base_value.id"));
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value.id", 0), 1);
ASSERT_TRUE(falco_config.config.is_defined("base_value.name"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("base_value.name", ""), "foo");
ASSERT_TRUE(falco_config.config.is_defined("foo2"));
ASSERT_EQ(falco_config.config.get_scalar<std::string>("foo2", ""), "bar2");
ASSERT_TRUE(falco_config.config.is_defined("base_value_2.id"));
ASSERT_EQ(falco_config.config.get_scalar<int>("base_value_2.id", 0), 2);
std::filesystem::remove("main.yaml");
std::filesystem::remove("conf_2.yaml");
}
TEST(Configuration, configuration_environment_variables)
{
// Set an environment variable for testing purposes
@@ -321,9 +799,9 @@ TEST(Configuration, configuration_webserver_ip)
std::vector<std::string> cmdline_config_options;
cmdline_config_options.push_back(option);
EXPECT_NO_THROW(falco_config.init(cmdline_config_options));
EXPECT_NO_THROW(falco_config.init_from_content("", cmdline_config_options));
ASSERT_EQ(falco_config.m_webserver_listen_address, address);
ASSERT_EQ(falco_config.m_webserver_config.m_listen_address, address);
}
std::vector<std::string> invalid_addresses = {"327.0.0.1",
@@ -358,6 +836,6 @@ TEST(Configuration, configuration_webserver_ip)
std::vector<std::string> cmdline_config_options;
cmdline_config_options.push_back(option);
EXPECT_ANY_THROW(falco_config.init(cmdline_config_options));
EXPECT_ANY_THROW(falco_config.init_from_content("", cmdline_config_options));
}
}

View File

@@ -0,0 +1,60 @@
// SPDX-License-Identifier: Apache-2.0
/*
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
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <gtest/gtest.h>
#include <falco/configuration.h>
TEST(ConfigurationRuleSelection, parse_yaml)
{
falco_configuration falco_config;
EXPECT_NO_THROW(falco_config.init_from_content(R"(
rules:
- enable:
rule: 'Terminal Shell in Container'
- disable:
tag: experimental
- enable:
rule: 'hello*'
)", {}));
ASSERT_EQ(falco_config.m_rules_selection.size(), 3);
ASSERT_EQ(falco_config.m_rules_selection[0].m_op, falco_configuration::rule_selection_operation::enable);
ASSERT_EQ(falco_config.m_rules_selection[0].m_rule, "Terminal Shell in Container");
ASSERT_EQ(falco_config.m_rules_selection[1].m_op, falco_configuration::rule_selection_operation::disable);
ASSERT_EQ(falco_config.m_rules_selection[1].m_tag, "experimental");
ASSERT_EQ(falco_config.m_rules_selection[2].m_op, falco_configuration::rule_selection_operation::enable);
ASSERT_EQ(falco_config.m_rules_selection[2].m_rule, "hello*");
}
TEST(ConfigurationRuleSelection, cli_options)
{
falco_configuration falco_config;
EXPECT_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_EQ(falco_config.m_rules_selection.size(), 2);
ASSERT_EQ(falco_config.m_rules_selection[0].m_op, falco_configuration::rule_selection_operation::disable);
ASSERT_EQ(falco_config.m_rules_selection[0].m_tag, "maturity_incubating");
ASSERT_EQ(falco_config.m_rules_selection[1].m_op, falco_configuration::rule_selection_operation::enable);
ASSERT_EQ(falco_config.m_rules_selection[1].m_rule, "Adding ssh keys to authorized_keys");
}

View File

@@ -22,6 +22,7 @@ add_library(falco_engine STATIC
filter_details_resolver.cpp
filter_macro_resolver.cpp
filter_warning_resolver.cpp
logger.cpp
stats_manager.cpp
rule_loader.cpp
rule_loader_reader.cpp
@@ -33,18 +34,15 @@ if (EMSCRIPTEN)
target_compile_options(falco_engine PRIVATE "-sDISABLE_EXCEPTION_CATCHING=0")
endif()
add_dependencies(falco_engine yamlcpp njson)
target_include_directories(falco_engine
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${nlohmann_json_INCLUDE_DIRS}
${TBB_INCLUDE_DIR}
${YAMLCPP_INCLUDE_DIR}
)
target_link_libraries(falco_engine
PUBLIC
sinsp
${YAMLCPP_LIB}
nlohmann_json::nlohmann_json
yaml-cpp
)

View File

@@ -17,6 +17,10 @@ limitations under the License.
#include "evttype_index_ruleset.h"
#include "falco_utils.h"
#include "logger.h"
#include <algorithm>
evttype_index_ruleset::evttype_index_ruleset(
@@ -223,50 +227,75 @@ void evttype_index_ruleset::add(
void evttype_index_ruleset::on_loading_complete()
{
// nothing to do for now
print_enabled_rules_falco_logger();
}
void evttype_index_ruleset::print_enabled_rules_falco_logger()
{
falco_logger::log(falco_logger::level::DEBUG, "Enabled rules:\n");
int n = 0;
for (const auto& ruleset_ptr : m_rulesets)
{
if (ruleset_ptr)
{
for (const auto& wrap : ruleset_ptr->get_filters())
{
n++;
falco_logger::log(falco_logger::level::DEBUG, std::string(" ") + wrap->rule.name + "\n");
}
}
}
falco_logger::log(falco_logger::level::DEBUG, "(" + std::to_string(n) + ") enabled rules in total\n");
}
void evttype_index_ruleset::clear()
{
for (size_t i = 0; i < m_rulesets.size(); i++)
{
std::shared_ptr<ruleset_filters> r(new ruleset_filters());
m_rulesets[i] = r;
m_rulesets[i] = std::make_shared<ruleset_filters>();
}
m_filters.clear();
}
void evttype_index_ruleset::enable(const std::string &substring, bool match_exact, uint16_t ruleset_id)
void evttype_index_ruleset::enable(const std::string &pattern, match_type match, uint16_t ruleset_id)
{
enable_disable(substring, match_exact, true, ruleset_id);
enable_disable(pattern, match, true, ruleset_id);
}
void evttype_index_ruleset::disable(const std::string &substring, bool match_exact, uint16_t ruleset_id)
void evttype_index_ruleset::disable(const std::string &pattern, match_type match, uint16_t ruleset_id)
{
enable_disable(substring, match_exact, false, ruleset_id);
enable_disable(pattern, match, false, ruleset_id);
}
void evttype_index_ruleset::enable_disable(const std::string &substring, bool match_exact, bool enabled, uint16_t ruleset_id)
void evttype_index_ruleset::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(new ruleset_filters());
m_rulesets.emplace_back(std::make_shared<ruleset_filters>());
}
for(const auto &wrap : m_filters)
{
bool matches;
std::string::size_type pos;
if(match_exact)
switch(match)
{
size_t pos = wrap->rule.name.find(substring);
case match_type::exact:
pos = wrap->rule.name.find(pattern);
matches = (substring == "" || (pos == 0 &&
substring.size() == wrap->rule.name.size()));
}
else
{
matches = (substring == "" || (wrap->rule.name.find(substring) != std::string::npos));
matches = (pattern == "" || (pos == 0 &&
pattern.size() == wrap->rule.name.size()));
break;
case match_type::substring:
matches = (pattern == "" || (wrap->rule.name.find(pattern) != std::string::npos));
break;
case match_type::wildcard:
matches = falco::utils::matches_wildcard(pattern, wrap->rule.name);
break;
default:
// should never happen
matches = false;
}
if(matches)
@@ -297,7 +326,7 @@ void evttype_index_ruleset::enable_disable_tags(const std::set<std::string> &tag
{
while(m_rulesets.size() < (size_t)ruleset_id + 1)
{
m_rulesets.emplace_back(new ruleset_filters());
m_rulesets.emplace_back(std::make_shared<ruleset_filters>());
}
for(const auto &wrap : m_filters)
@@ -326,7 +355,7 @@ uint64_t evttype_index_ruleset::enabled_count(uint16_t ruleset_id)
{
while(m_rulesets.size() < (size_t)ruleset_id + 1)
{
m_rulesets.emplace_back(new ruleset_filters());
m_rulesets.emplace_back(std::make_shared<ruleset_filters>());
}
return m_rulesets[ruleset_id]->num_filters();

View File

@@ -52,14 +52,18 @@ public:
void on_loading_complete() override;
// Print each enabled rule when running Falco with falco logger
// log_level=debug; invoked within on_loading_complete()
void print_enabled_rules_falco_logger();
void enable(
const std::string &substring,
bool match_exact,
const std::string &pattern,
match_type match,
uint16_t rulset_id) override;
void disable(
const std::string &substring,
bool match_exact,
const std::string &pattern,
match_type match,
uint16_t rulset_id) override;
void enable_tags(
@@ -85,8 +89,8 @@ private:
// Helper used by enable()/disable()
void enable_disable(
const std::string &substring,
bool match_exact,
const std::string &pattern,
match_type match,
bool enabled,
uint16_t rulset_id);
@@ -118,12 +122,17 @@ private:
uint64_t num_filters();
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(sinsp_evt *evt, falco_rule& match);
// Evaluate an event against the ruleset and return all the
// matching rules.
// Evaluate an event against the ruleset and return all the
// matching rules.
bool run(sinsp_evt *evt, std::vector<falco_rule>& matches);
libsinsp::events::set<ppm_sc_code> sc_codes();
@@ -164,9 +173,7 @@ public:
inline std::shared_ptr<filter_ruleset> new_ruleset() override
{
std::shared_ptr<filter_ruleset> ret(
new evttype_index_ruleset(m_filter_factory));
return ret;
return std::make_shared<evttype_index_ruleset>(m_filter_factory);
}
private:

View File

@@ -28,6 +28,8 @@ limitations under the License.
//
#define DEFAULT_OUTPUTS_QUEUE_CAPACITY_UNBOUNDED_MAX_LONG_VALUE std::ptrdiff_t(~size_t(0) / 2)
#define DEFAULT_FALCO_LIBS_THREAD_TABLE_SIZE 262144
//
// Most falco_* classes can throw exceptions. Unless directly related
// to low-level failures like inability to open file, etc, they will

View File

@@ -198,11 +198,11 @@ std::unique_ptr<load_result> falco_engine::load_rules(const std::string &rules_c
cfg.replace_output_container_info = m_replace_container_info;
// read rules YAML file and collect its definitions
if(m_rule_reader->read(cfg, *(m_rule_collector.get())))
if(m_rule_reader->read(cfg, *m_rule_collector))
{
// compile the definitions (resolve macro/list refs, exceptions, ...)
m_last_compile_output = m_rule_compiler->new_compile_output();
m_rule_compiler->compile(cfg, *(m_rule_collector.get()), *m_last_compile_output.get());
m_rule_compiler->compile(cfg, *m_rule_collector, *m_last_compile_output);
// clear the rules known by the engine and each ruleset
m_rules.clear();
@@ -210,7 +210,7 @@ std::unique_ptr<load_result> falco_engine::load_rules(const std::string &rules_c
// add rules to each ruleset
{
src.ruleset = create_ruleset(src.ruleset_factory);
src.ruleset->add_compile_output(*(m_last_compile_output.get()),
src.ruleset->add_compile_output(*m_last_compile_output,
m_min_priority,
src.name);
}
@@ -242,11 +242,11 @@ std::unique_ptr<load_result> falco_engine::load_rules(const std::string &rules_c
}
if(info->enabled)
{
source->ruleset->enable(rule.name, true, m_default_ruleset_id);
source->ruleset->enable(rule.name, filter_ruleset::match_type::exact, m_default_ruleset_id);
}
else
{
source->ruleset->disable(rule.name, true, m_default_ruleset_id);
source->ruleset->disable(rule.name, filter_ruleset::match_type::exact, m_default_ruleset_id);
}
}
}
@@ -272,17 +272,15 @@ void falco_engine::enable_rule(const std::string &substring, bool enabled, const
void falco_engine::enable_rule(const std::string &substring, bool enabled, const uint16_t ruleset_id)
{
bool match_exact = false;
for(const auto &it : m_sources)
{
if(enabled)
{
it.ruleset->enable(substring, match_exact, ruleset_id);
it.ruleset->enable(substring, filter_ruleset::match_type::substring, ruleset_id);
}
else
{
it.ruleset->disable(substring, match_exact, ruleset_id);
it.ruleset->disable(substring, filter_ruleset::match_type::substring, ruleset_id);
}
}
}
@@ -296,17 +294,37 @@ void falco_engine::enable_rule_exact(const std::string &rule_name, bool enabled,
void falco_engine::enable_rule_exact(const std::string &rule_name, bool enabled, const uint16_t ruleset_id)
{
bool match_exact = true;
for(const auto &it : m_sources)
{
if(enabled)
{
it.ruleset->enable(rule_name, match_exact, ruleset_id);
it.ruleset->enable(rule_name, filter_ruleset::match_type::exact, ruleset_id);
}
else
{
it.ruleset->disable(rule_name, match_exact, ruleset_id);
it.ruleset->disable(rule_name, filter_ruleset::match_type::exact, ruleset_id);
}
}
}
void falco_engine::enable_rule_wildcard(const std::string &rule_name, bool enabled, const std::string &ruleset)
{
uint16_t ruleset_id = find_ruleset_id(ruleset);
enable_rule_wildcard(rule_name, enabled, ruleset_id);
}
void falco_engine::enable_rule_wildcard(const std::string &rule_name, bool enabled, const uint16_t ruleset_id)
{
for(const auto &it : m_sources)
{
if(enabled)
{
it.ruleset->enable(rule_name, filter_ruleset::match_type::wildcard, ruleset_id);
}
else
{
it.ruleset->disable(rule_name, filter_ruleset::match_type::wildcard, ruleset_id);
}
}
}
@@ -450,9 +468,8 @@ std::size_t falco_engine::add_source(const std::string &source,
std::shared_ptr<sinsp_evt_formatter_factory> formatter_factory)
{
// evttype_index_ruleset is the default ruleset implementation
std::shared_ptr<filter_ruleset_factory> ruleset_factory(
new evttype_index_ruleset_factory(filter_factory));
size_t idx = add_source(source, filter_factory, formatter_factory, ruleset_factory);
size_t idx = add_source(source, filter_factory, formatter_factory,
std::make_shared<evttype_index_ruleset_factory>(filter_factory));
if(source == falco_common::syscall_source)
{
@@ -486,7 +503,7 @@ template <typename T> inline nlohmann::json sequence_to_json_array(const T& seq)
return ret;
}
nlohmann::json falco_engine::describe_rule(std::string *rule, const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
nlohmann::json falco_engine::describe_rule(std::string *rule_name, const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
{
// use previously-loaded collector definitions and the compiled
// output of rules, macros, and lists.
@@ -497,7 +514,7 @@ nlohmann::json falco_engine::describe_rule(std::string *rule, const std::vector<
// use collected and compiled info to print a json output
nlohmann::json output;
if(!rule)
if(!rule_name)
{
// Store required engine version
auto required_engine_version = m_rule_collector->required_engine_version();
@@ -528,51 +545,51 @@ nlohmann::json falco_engine::describe_rule(std::string *rule, const std::vector<
// Store information about rules
nlohmann::json rules_array = nlohmann::json::array();
for(const auto& r : m_last_compile_output->rules)
for(const auto& rule : m_last_compile_output->rules)
{
auto info = m_rule_collector->rules().at(r.name);
nlohmann::json rule;
get_json_details(rule, r, *info, plugins);
rules_array.push_back(std::move(rule));
auto info = m_rule_collector->rules().at(rule.name);
nlohmann::json details;
get_json_details(details, rule, *info, plugins);
rules_array.push_back(std::move(details));
}
output["rules"] = std::move(rules_array);
// Store information about macros
nlohmann::json macros_array = nlohmann::json::array();
for(const auto &m : m_last_compile_output->macros)
for(const auto &macro : m_last_compile_output->macros)
{
auto info = m_rule_collector->macros().at(m.name);
nlohmann::json macro;
get_json_details(macro, m, *info, plugins);
macros_array.push_back(std::move(macro));
auto info = m_rule_collector->macros().at(macro.name);
nlohmann::json details;
get_json_details(details, macro, *info, plugins);
macros_array.push_back(std::move(details));
}
output["macros"] = std::move(macros_array);
// Store information about lists
nlohmann::json lists_array = nlohmann::json::array();
for(const auto &l : m_last_compile_output->lists)
for(const auto &list : m_last_compile_output->lists)
{
auto info = m_rule_collector->lists().at(l.name);
nlohmann::json list;
get_json_details(list, l, *info, plugins);
lists_array.push_back(std::move(list));
auto info = m_rule_collector->lists().at(list.name);
nlohmann::json details;
get_json_details(details, list, *info, plugins);
lists_array.push_back(std::move(details));
}
output["lists"] = std::move(lists_array);
}
else
{
// build json information for just the specified rule
auto ri = m_rule_collector->rules().at(*rule);
auto ri = m_rule_collector->rules().at(*rule_name);
if(ri == nullptr || ri->unknown_source)
{
throw falco_exception("Rule \"" + *rule + "\" is not loaded");
throw falco_exception("Rule \"" + *rule_name + "\" is not loaded");
}
auto r = m_rules.at(ri->name);
auto rule = m_rules.at(ri->name);
nlohmann::json rule;
get_json_details(rule, *r, *ri, plugins);
nlohmann::json details;
get_json_details(details, *rule, *ri, plugins);
nlohmann::json rules_array = nlohmann::json::array();
rules_array.push_back(std::move(rule));
rules_array.push_back(std::move(details));
output["rules"] = std::move(rules_array);
}
@@ -689,13 +706,13 @@ void falco_engine::get_json_details(
void falco_engine::get_json_details(
nlohmann::json& out,
const falco_macro& m,
const falco_macro& macro,
const rule_loader::macro_info& info,
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
{
nlohmann::json macro_info;
macro_info["name"] = m.name;
macro_info["name"] = macro.name;
macro_info["condition"] = info.cond;
out["info"] = std::move(macro_info);
@@ -718,9 +735,9 @@ void falco_engine::get_json_details(
compiled_details.known_lists.insert(l.name);
}
filter_details_resolver().run(ast.get(), details);
filter_details_resolver().run(m.condition.get(), compiled_details);
filter_details_resolver().run(macro.condition.get(), compiled_details);
out["details"]["used"] = m.used;
out["details"]["used"] = macro.used;
out["details"]["macros"] = sequence_to_json_array(details.macros);
out["details"]["lists"] = sequence_to_json_array(details.lists);
out["details"]["condition_operators"] = sequence_to_json_array(compiled_details.operators);
@@ -728,11 +745,11 @@ void falco_engine::get_json_details(
// Store event types
nlohmann::json events;
get_json_evt_types(events, "", m.condition.get());
get_json_evt_types(events, "", macro.condition.get());
out["details"]["events"] = std::move(events);
// Store compiled condition
out["details"]["condition_compiled"] = libsinsp::filter::ast::as_string(m.condition.get());
out["details"]["condition_compiled"] = libsinsp::filter::ast::as_string(macro.condition.get());
// Compute the plugins that are actually used by this macro.
// Note: macros have no specific source, we need to set an empty list of used
@@ -890,6 +907,11 @@ void falco_engine::print_stats() const
fprintf(stdout, "%s", out.c_str());
}
const stats_manager& falco_engine::get_rule_stats_manager() const
{
return m_rule_stats_manager;
}
bool falco_engine::is_source_valid(const std::string &source) const
{
return m_sources.at(source) != nullptr;

View File

@@ -102,6 +102,12 @@ public:
// 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);
// 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);
//
// Enable/Disable any rules with any of the provided tags (set, exact matches only)
//
@@ -141,13 +147,23 @@ public:
// Print details on the given rule. If rule is NULL, print
// details on all rules.
//
nlohmann::json describe_rule(std::string *rule, 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; }
//
// Print statistics on how many events matched each rule.
//
void print_stats() const;
//
// 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;
//
// Set the sampling ratio, which can affect which events are
// matched against the set of rules.

View File

@@ -20,7 +20,7 @@ limitations under the License.
// The version of this Falco engine
#define FALCO_ENGINE_VERSION_MAJOR 0
#define FALCO_ENGINE_VERSION_MINOR 35
#define FALCO_ENGINE_VERSION_MINOR 40
#define FALCO_ENGINE_VERSION_PATCH 0
#define FALCO_ENGINE_VERSION \
@@ -34,4 +34,4 @@ limitations under the License.
// It represents the fields supported by this version of Falco,
// the event types, and the underlying driverevent schema. It's used to
// detetect changes in engine version in our CI jobs.
#define FALCO_ENGINE_CHECKSUM "8b7007b6fdef6abc6661ccfb4424052e7c4838d59f7be3ae31ab1e7b10223c93"
#define FALCO_ENGINE_CHECKSUM "bc9d0d94ae70ef26b7cf814f62273a48b2bb4133dff0baff5f194f6f1711875a"

View File

@@ -23,7 +23,8 @@ static const std::string error_codes[] = {
"LOAD_ERR_YAML_VALIDATE",
"LOAD_ERR_COMPILE_CONDITION",
"LOAD_ERR_COMPILE_OUTPUT",
"LOAD_ERR_VALIDATE"
"LOAD_ERR_VALIDATE",
"LOAD_ERR_EXTENSION"
};
const std::string& falco::load_result::error_code_str(error_code ec)
@@ -37,7 +38,8 @@ static const std::string error_strings[] = {
"Error validating internal structure of YAML file",
"Error compiling condition",
"Error compiling output",
"Error validating rule/macro/list/exception objects"
"Error validating rule/macro/list/exception objects",
"Error in extension item"
};
const std::string& falco::load_result::error_str(error_code ec)
@@ -51,7 +53,8 @@ static const std::string error_descs[] = {
"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 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)
@@ -67,7 +70,13 @@ static const std::string warning_codes[] = {
"LOAD_UNUSED_MACRO",
"LOAD_UNUSED_LIST",
"LOAD_UNKNOWN_ITEM",
"LOAD_DEPRECATED_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)
@@ -83,7 +92,13 @@ static const std::string warning_strings[] = {
"Unused macro",
"Unused list",
"Unknown rules file item",
"Used deprecated 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)
@@ -99,7 +114,13 @@ static const std::string warning_descs[] = {
"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."
"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)

View File

@@ -57,7 +57,12 @@ public:
LOAD_UNUSED_LIST,
LOAD_UNKNOWN_ITEM,
LOAD_DEPRECATED_ITEM,
LOAD_WARNING_EXTENSION
LOAD_WARNING_EXTENSION,
LOAD_APPEND_NO_VALUES,
LOAD_EXCEPTION_NAME_NOT_UNIQUE,
LOAD_INVALID_MACRO_NAME,
LOAD_INVALID_LIST_NAME,
LOAD_COMPILE_CONDITION
};
virtual ~load_result() = default;

View File

@@ -56,12 +56,30 @@ struct falco_source
// matches an event.
mutable std::vector<falco_rule> m_rules;
inline bool is_field_defined(const std::string& field) const
inline bool is_valid_lhs_field(const std::string& field) const
{
if (filter_factory->new_filtercheck(field.c_str()) != nullptr)
// 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)
{
return true;
try
{
auto filter = field;
filter.append(" exists");
sinsp_filter_compiler(filter_factory, filter).compile();
return true;
}
catch (...)
{
return false;
}
}
return false;
// otherwise, simply attempt creating a filtercheck with the given
// field name and see if we succeed
return filter_factory->new_filtercheck(field.c_str()) != nullptr;
}
};

View File

@@ -17,13 +17,18 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
#include <cstring>
#include <iomanip>
#include "falco_utils.h"
#include <libsinsp/utils.h>
#include <re2/re2.h>
#if defined(__linux__) and !defined(MINIMAL_BUILD) and !defined(__EMSCRIPTEN__)
#include <openssl/sha.h>
#endif
#include <cstring>
#include <fstream>
#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)?$"
@@ -114,6 +119,50 @@ uint64_t parse_prometheus_interval(std::string interval_str)
return interval;
}
#if defined(__linux__) and !defined(MINIMAL_BUILD) and !defined(__EMSCRIPTEN__)
std::string calculate_file_sha256sum(const std::string& filename)
{
std::ifstream file(filename, std::ios::binary);
if (!file.is_open())
{
return "";
}
SHA256_CTX sha256_context;
SHA256_Init(&sha256_context);
constexpr size_t buffer_size = 4096;
char buffer[buffer_size];
while (file.read(buffer, buffer_size))
{
SHA256_Update(&sha256_context, buffer, buffer_size);
}
SHA256_Update(&sha256_context, buffer, file.gcount());
unsigned char digest[SHA256_DIGEST_LENGTH];
SHA256_Final(digest, &sha256_context);
std::stringstream ss;
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_metric_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() == '_')
{
sanitized_name.pop_back();
}
return sanitized_name;
}
std::string wrap_text(const std::string& in, uint32_t indent, uint32_t line_len)
{
std::istringstream is(in);
@@ -145,7 +194,7 @@ uint32_t hardware_concurrency()
void readfile(const std::string& filename, std::string& data)
{
std::ifstream file(filename.c_str(), std::ios::in);
std::ifstream file(filename, std::ios::in);
if(file.is_open())
{
@@ -160,6 +209,48 @@ void readfile(const std::string& filename, std::string& data)
return;
}
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)
{
// regular match (no wildcards)
return pattern == s;
}
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)
{
// pattern was just a sequence of stars *, **, ***, ... . This always matches.
return true;
}
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)
{
return false;
}
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))
{
return false;
}
return matches_wildcard(pattern.substr(star_pos), s.substr(star_pos));
}
}
namespace network
{
bool is_unix_scheme(const std::string& url)

View File

@@ -20,31 +20,18 @@ limitations under the License.
#pragma once
#include <sstream>
#include <fstream>
#include <iostream>
#include <string>
#include <thread>
#include <unordered_set>
#include <set>
#include <vector>
#include <cstdint>
#include <string>
#ifdef __GNUC__
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#else
#define likely(x) (x)
#define unlikely(x) (x)
namespace falco::utils
{
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);
#endif
namespace falco
{
namespace utils
{
uint64_t parse_prometheus_interval(std::string interval_str);
std::string sanitize_metric_name(const std::string& name);
std::string wrap_text(const std::string& in, uint32_t indent, uint32_t linelen);
@@ -52,10 +39,11 @@ void readfile(const std::string& filename, std::string& data);
uint32_t hardware_concurrency();
bool matches_wildcard(const std::string &pattern, const std::string &s);
namespace network
{
static const std::string UNIX_SCHEME("unix://");
bool is_unix_scheme(const std::string& url);
} // namespace network
} // namespace utils
} // namespace falco
} // namespace falco::utils

View File

@@ -17,9 +17,11 @@ limitations under the License.
#include "filter_details_resolver.h"
#include <stdexcept>
using namespace libsinsp::filter;
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())
@@ -36,35 +38,28 @@ void filter_details::reset()
operators.clear();
lists.clear();
evtnames.clear();
transformers.clear();
}
void filter_details_resolver::run(ast::expr* filter, filter_details& details)
{
visitor v(details);
// note: we may have ASTs composed on only one macro ref
v.m_expect_macro = true;
filter->accept(&v);
}
void filter_details_resolver::visitor::visit(ast::and_expr* e)
{
m_expect_macro = false;
for(size_t i = 0; i < e->children.size(); i++)
{
m_expect_macro = true;
e->children[i]->accept(this);
m_expect_macro = false;
}
}
void filter_details_resolver::visitor::visit(ast::or_expr* e)
{
m_expect_macro = false;
for(size_t i = 0; i < e->children.size(); i++)
{
m_expect_macro = true;
e->children[i]->accept(this);
m_expect_macro = false;
}
}
@@ -99,36 +94,61 @@ void filter_details_resolver::visitor::visit(ast::list_expr* e)
void filter_details_resolver::visitor::visit(ast::binary_check_expr* e)
{
m_expect_macro = false;
m_details.fields.insert(get_field_name(e->field, e->arg));
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())
{
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 = e->field == "evt.type" || e->field == "evt.asynctype";
e->value->accept(this);
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)
{
m_expect_macro = false;
m_details.fields.insert(get_field_name(e->field, e->arg));
m_last_node_field_name.clear();
e->left->accept(this);
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)
{
// 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())
{
m_details.macros.insert(e->identifier);
}
}
void filter_details_resolver::visitor::visit(ast::value_expr* e)
{
if (m_expect_macro)
{
if(m_details.known_macros.find(e->value) != m_details.known_macros.end())
{
m_details.macros.insert(e->value);
}
// todo(jasondellaluce): should we throw an error if we
// encounter an unknown macro?
}
else if (m_expect_evtname)
if (m_expect_evtname)
{
m_details.evtnames.insert(e->value);
}
}
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)
{
m_details.transformers.insert(e->transformer);
e->value->accept(this);
}

View File

@@ -34,6 +34,7 @@ struct filter_details
std::unordered_set<std::string> operators;
std::unordered_set<std::string> lists;
std::unordered_set<std::string> evtnames;
std::unordered_set<std::string> transformers;
void reset();
};
@@ -60,22 +61,25 @@ private:
explicit visitor(filter_details& details) :
m_details(details),
m_expect_list(false),
m_expect_macro(false),
m_expect_evtname(false) {}
m_expect_evtname(false),
m_last_node_field_name() {}
visitor(visitor&&) = default;
visitor(const visitor&) = delete;
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;
filter_details& m_details;
bool m_expect_list;
bool m_expect_macro;
bool m_expect_evtname;
std::string m_last_node_field_name;
};
};

View File

@@ -101,8 +101,6 @@ void filter_macro_resolver::visitor::visit(ast::list_expr* e)
void filter_macro_resolver::visitor::visit(ast::binary_check_expr* e)
{
// avoid exploring checks, so that we can be sure that each
// value_expr* node visited is a macro identifier
m_node_substitute = nullptr;
}
@@ -113,10 +111,22 @@ void filter_macro_resolver::visitor::visit(ast::unary_check_expr* e)
void filter_macro_resolver::visitor::visit(ast::value_expr* e)
{
// we are supposed to get here only in case
// of identier-only children from either a 'not',
// an 'and' or an 'or'.
const auto& macro = m_macros.find(e->value);
m_node_substitute = nullptr;
}
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)
{
m_node_substitute = nullptr;
}
void filter_macro_resolver::visitor::visit(ast::identifier_expr* e)
{
const auto& macro = m_macros.find(e->identifier);
if (macro != m_macros.end() && macro->second) // skip null-ptr macros
{
// note: checks for loop detection
@@ -126,7 +136,7 @@ void filter_macro_resolver::visitor::visit(ast::value_expr* e)
auto msg = "reference loop in macro '" + macro->first + "'";
m_errors.push_back({msg, e->get_pos()});
m_node_substitute = nullptr;
m_unknown_macros.push_back({e->value, e->get_pos()});
m_unknown_macros.push_back({e->identifier, e->get_pos()});
return;
}
@@ -140,12 +150,12 @@ void filter_macro_resolver::visitor::visit(ast::value_expr* e)
{
m_node_substitute = std::move(new_node);
}
m_resolved_macros.push_back({e->value, e->get_pos()});
m_resolved_macros.push_back({e->identifier, e->get_pos()});
m_macros_path.pop_back();
}
else
{
m_node_substitute = nullptr;
m_unknown_macros.push_back({e->value, e->get_pos()});
m_unknown_macros.push_back({e->identifier, e->get_pos()});
}
}

View File

@@ -35,7 +35,7 @@ class filter_macro_resolver
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 modified in order to apply
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
@@ -121,10 +121,13 @@ class filter_macro_resolver
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;

View File

@@ -41,6 +41,10 @@ public:
ruleset_retriever_func_t get_ruleset;
};
enum class match_type {
exact, substring, wildcard
};
virtual ~filter_ruleset() = default;
void set_engine_state(const engine_state_funcs &engine_state);
@@ -167,31 +171,37 @@ public:
/*!
\brief Find those rules matching the provided substring and enable
them in the provided ruleset.
\param substring Substring used to match rule names.
If empty, all rules are matched.
\param match_exact If true, substring must be an exact match for a
given rule name. Otherwise, any rules having substring as a substring
in the rule name are enabled/disabled.
\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(
const std::string &substring,
bool match_exact,
const std::string &pattern,
match_type match,
uint16_t ruleset_id) = 0;
/*!
\brief Find those rules matching the provided substring and disable
them in the provided ruleset.
\param substring Substring used to match rule names.
If empty, all rules are matched.
\param match_exact If true, substring must be an exact match for a
given rule name. Otherwise, any rules having substring as a substring
in the rule name are enabled/disabled.
\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(
const std::string &substring,
bool match_exact,
const std::string &pattern,
match_type match,
uint16_t ruleset_id) = 0;
/*!

View File

@@ -49,14 +49,22 @@ bool filter_warning_resolver::run(
void filter_warning_resolver::visitor::visit(
libsinsp::filter::ast::binary_check_expr* e)
{
if (is_unsafe_field(e->field) && is_equality_operator(e->op))
m_last_node_is_unsafe_field = false;
e->left->accept(this);
if (m_last_node_is_unsafe_field && is_equality_operator(e->op))
{
m_is_equality_check = true;
e->value->accept(this);
e->right->accept(this);
m_is_equality_check = false;
}
}
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)
{

View File

@@ -49,17 +49,22 @@ public:
private:
struct visitor : public libsinsp::filter::ast::base_expr_visitor
{
visitor(): m_is_equality_check(false), m_warnings(nullptr) {}
visitor():
m_is_equality_check(false),
m_last_node_is_unsafe_field(false),
m_warnings(nullptr) {}
visitor(visitor&&) = default;
visitor& operator = (visitor&&) = default;
visitor(const visitor&) = delete;
visitor& operator = (const visitor&) = delete;
bool m_is_equality_check;
bool m_last_node_is_unsafe_field;
std::set<falco::load_result::warning_code>* m_warnings;
void visit(libsinsp::filter::ast::value_expr* e) override;
void visit(libsinsp::filter::ast::list_expr* e) override;
void visit(libsinsp::filter::ast::binary_check_expr* e) override;
void visit(libsinsp::filter::ast::field_expr* e) override;
};
};

View File

@@ -81,12 +81,12 @@ rule_loader::context::context(const libsinsp::filter::ast::pos_info& pos,
// 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 name = "\"" + (
std::string condition_name = "\"" + (
condition.length() > 20
? condition.substr(0, 20 - 3) + "...\""
: condition + "\"");
std::replace(name.begin(), name.end(), '\n', ' ');
std::replace(name.begin(), name.end(), '\r', ' ');
std::replace(condition_name.begin(), condition_name.end(), '\n', ' ');
std::replace(condition_name.begin(), condition_name.end(), '\r', ' ');
std::string item_name = "";
@@ -100,7 +100,7 @@ rule_loader::context::context(const libsinsp::filter::ast::pos_info& pos,
condpos.line = pos.line + lastpos.pos.line;
condpos.column = pos.col + lastpos.pos.column;
init(name, condpos, rule_loader::context::CONDITION_EXPRESSION, item_name, parent);
init(condition_name, condpos, rule_loader::context::CONDITION_EXPRESSION, item_name, parent);
}
const std::string& rule_loader::context::name() const

View File

@@ -270,10 +270,8 @@ namespace rule_loader
const std::string& cont,
const indexed_vector<falco_source>& srcs,
const std::string& name)
: content(cont), sources(srcs), name(name),
output_extra(), replace_output_container_info(false)
: content(cont), sources(srcs), name(name), res(std::make_unique<result>(name))
{
res.reset(new result(name));
}
// inputs
@@ -281,7 +279,7 @@ namespace rule_loader
const indexed_vector<falco_source>& sources;
std::string name;
std::string output_extra;
bool replace_output_container_info;
bool replace_output_container_info = false;
// outputs
std::unique_ptr<result> res;

View File

@@ -88,7 +88,7 @@ static void validate_exception_info(
{
for (const auto &v : ex.fields.items)
{
THROW(!source->is_field_defined(v.item),
THROW(!source->is_valid_lhs_field(v.item),
std::string("'") + v.item + "' is not a supported filter field",
ex.ctx);
}
@@ -109,7 +109,7 @@ static void validate_exception_info(
ex.ctx);
if (source)
{
THROW(!source->is_field_defined(ex.fields.item),
THROW(!source->is_valid_lhs_field(ex.fields.item),
std::string("'") + ex.fields.item + "' is not a supported filter field",
ex.ctx);
}

View File

@@ -76,6 +76,7 @@ static void build_rule_exception_infos(
std::string& condition)
{
std::string tmp;
condition = "(" + condition + ")";
for (const auto &ex : exceptions)
{
std::string icond;
@@ -342,35 +343,35 @@ void rule_loader::compiler::compile_list_infos(
const collector& col,
indexed_vector<falco_list>& out) const
{
std::list<std::string> used;
falco_list v;
std::list<std::string> used_names;
falco_list infos;
for (const auto &list : col.lists())
{
v.name = list.name;
v.items.clear();
infos.name = list.name;
infos.items.clear();
for (const auto &item : list.items)
{
const auto ref = col.lists().at(item);
if (ref && ref->index < list.visibility)
{
used.push_back(ref->name);
used_names.push_back(ref->name);
for (const auto &val : ref->items)
{
v.items.push_back(val);
infos.items.push_back(val);
}
}
else
{
v.items.push_back(item);
infos.items.push_back(item);
}
}
v.used = false;
auto list_id = out.insert(v, v.name);
infos.used = false;
auto list_id = out.insert(infos, infos.name);
out.at(list_id)->id = list_id;
}
for (const auto &v : used)
for (const auto &name : used_names)
{
out.at(v)->used = true;
out.at(name)->used = true;
}
}
@@ -439,27 +440,35 @@ bool rule_loader::compiler::compile_condition(
sinsp_filter_compiler compiler(filter_factory, ast_out.get());
try
{
filter_out = std::move(compiler.compile());
filter_out = compiler.compile();
}
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,
cond_ctx);
ctx);
return false;
}
rule_loader::context ctx(compiler.get_pos(), condition, cond_ctx);
throw rule_loader::rule_load_exception(
falco::load_result::load_result::LOAD_ERR_COMPILE_CONDITION,
err,
ctx);
}
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);
}
return true;
}
@@ -500,7 +509,12 @@ void rule_loader::compiler::compile_rule_infos(
// build rule output message
rule.output = r.output;
if (r.source == falco_common::syscall_source)
// plugins sources do not have any container info and so we won't apply -pk, -pc, etc.
// on the other hand, when using plugins you might want to append custom output based on the plugin
// TODO: this is not flexible enough (esp. if you mix plugin with syscalls),
// it would be better to add configuration options to control the output.
if (!cfg.replace_output_container_info || r.source == falco_common::syscall_source)
{
apply_output_substitutions(cfg, rule.output);
}

View File

@@ -25,8 +25,20 @@ limitations under the License.
#include "rule_loading_messages.h"
#include <libsinsp/logger.h>
#include <re2/re2.h>
#define THROW(cond, err, ctx) { if ((cond)) { throw rule_loader::rule_load_exception(falco::load_result::LOAD_ERR_YAML_VALIDATE, (err), (ctx)); } }
// Sinsp Filter grammar tokens taken from "libsinsp/filter/parser.h"
// These regular expressions are used here to check for invalid macro/list names
// todo(mrgian): to avoid code duplication we can move regex definitions in libsinsp/filter/parser.h
// and include it here instead of redefining them.
#define RGX_IDENTIFIER "([a-zA-Z]+[a-zA-Z0-9_]*)"
#define RGX_BARESTR "([^()\"'[:space:]=,]+)"
static re2::RE2 s_rgx_identifier(RGX_IDENTIFIER, re2::RE2::POSIX);
static re2::RE2 s_rgx_barestr(RGX_BARESTR, re2::RE2::POSIX);
// Don't call this directly, call decode_val/decode_optional_val instead.
template <typename T>
static void decode_val_generic(const YAML::Node& item, const char *key, T& out, const rule_loader::context& ctx, bool optional)
@@ -270,6 +282,7 @@ static void decode_exception_values(
}
static void read_rule_exceptions(
rule_loader::configuration& cfg,
const YAML::Node& item,
std::vector<rule_loader::rule_exception_info>& exceptions,
const rule_loader::context& parent,
@@ -303,6 +316,15 @@ static void read_rule_exceptions(
rule_loader::rule_exception_info v_ex(ex_ctx);
v_ex.name = name;
// Check if an exception with the same name has already been defined
for (auto &exception : exceptions)
{
if(v_ex.name == exception.name)
{
cfg.res->add_warning(falco::load_result::LOAD_EXCEPTION_NAME_NOT_UNIQUE, "Multiple definitions of exception '" + v_ex.name + "' in the same rule", ex_ctx);
}
}
// note: the legacy lua loader used to throw a "xxx must strings" error
// fields are optional when append is true
@@ -322,19 +344,24 @@ static void read_rule_exceptions(
decode_exception_values(val, v_ex_val, vctx);
v_ex.values.push_back(v_ex_val);
}
}
else if (append)
{
cfg.res->add_warning(falco::load_result::LOAD_APPEND_NO_VALUES, "Overriding/appending exception with no values", ex_ctx);
}
exceptions.push_back(v_ex);
}
}
static void read_rule_exceptions(
rule_loader::configuration& cfg,
const YAML::Node& item,
std::optional<std::vector<rule_loader::rule_exception_info>>& exceptions,
const rule_loader::context& parent,
bool append)
{
std::vector<rule_loader::rule_exception_info> decoded;
read_rule_exceptions(item, decoded, parent, append);
read_rule_exceptions(cfg, item, decoded, parent, append);
exceptions = decoded;
}
@@ -359,9 +386,11 @@ void rule_loader::reader::read_item(
const YAML::Node& item,
const rule_loader::context& parent)
{
rule_loader::context tmp(item, rule_loader::context::RULES_CONTENT_ITEM, "", parent);
THROW(!item.IsMap(), "Unexpected element type. "
"Each element should be a yaml associative array.", tmp);
{
rule_loader::context tmp(item, rule_loader::context::RULES_CONTENT_ITEM, "", parent);
THROW(!item.IsMap(), "Unexpected element type. "
"Each element should be a yaml associative array.", tmp);
}
if (item["required_engine_version"].IsDefined())
{
@@ -440,6 +469,13 @@ void rule_loader::reader::read_item(
decode_val(item, "list", name, tmp);
rule_loader::context ctx(item, rule_loader::context::LIST, name, parent);
bool invalid_name = !re2::RE2::FullMatch(name, s_rgx_barestr);
if(invalid_name)
{
cfg.res->add_warning(falco::load_result::LOAD_INVALID_LIST_NAME, "List has an invalid name. List names should match a regular expression: " RGX_BARESTR, ctx);
}
rule_loader::list_info v(ctx);
bool append = false;
@@ -480,6 +516,13 @@ void rule_loader::reader::read_item(
decode_val(item, "macro", name, tmp);
rule_loader::context ctx(item, rule_loader::context::MACRO, name, parent);
bool invalid_name = !re2::RE2::FullMatch(name, s_rgx_identifier);
if(invalid_name)
{
cfg.res->add_warning(falco::load_result::LOAD_INVALID_MACRO_NAME, "Macro has an invalid name. Macro names should match a regular expression: " RGX_IDENTIFIER, ctx);
}
rule_loader::macro_info v(ctx);
v.name = name;
@@ -575,7 +618,7 @@ void rule_loader::reader::read_item(
if (check_update_expected(expected_keys, override_append, "append", "exceptions", ctx))
{
read_rule_exceptions(item, v.exceptions, ctx, true);
read_rule_exceptions(cfg, item, v.exceptions, ctx, true);
}
if (check_update_expected(expected_keys, override_append, "append", "output", ctx))
@@ -607,7 +650,7 @@ void rule_loader::reader::read_item(
if (check_update_expected(expected_keys, override_replace, "replace", "exceptions", ctx))
{
read_rule_exceptions(item, v.exceptions, ctx, true);
read_rule_exceptions(cfg, item, v.exceptions, ctx, false);
}
if (check_update_expected(expected_keys, override_replace, "replace", "output", ctx))
@@ -672,7 +715,7 @@ void rule_loader::reader::read_item(
if(item["exceptions"].IsDefined())
{
read_rule_exceptions(item, v.exceptions, ctx, true);
read_rule_exceptions(cfg, item, v.exceptions, ctx, true);
}
// TODO restore this error and update testing
@@ -728,7 +771,7 @@ void rule_loader::reader::read_item(
decode_optional_val(item, "warn_evttypes", v.warn_evttypes, ctx);
decode_optional_val(item, "skip-if-unknown-filter", v.skip_if_unknown_filter, ctx);
decode_tags(item, v.tags, ctx);
read_rule_exceptions(item, v.exceptions, ctx, has_append_flag);
read_rule_exceptions(cfg, item, v.exceptions, ctx, false);
collector.define(cfg, v);
}
}

View File

@@ -44,7 +44,7 @@ void stats_manager::format(
out += "Rule counts by severity:\n";
for (size_t i = 0; i < m_by_priority.size(); i++)
{
auto val = m_by_priority[i].get()->load();
auto val = m_by_priority[i]->load();
if (val > 0)
{
falco_common::format_priority(
@@ -56,7 +56,7 @@ void stats_manager::format(
out += "Triggered rules by rule name:\n";
for (size_t i = 0; i < m_by_rule_id.size(); i++)
{
auto val = m_by_rule_id[i].get()->load();
auto val = m_by_rule_id[i]->load();
if (val > 0)
{
out += " " + rules.at(i)->name + ": " + std::to_string(val) + "\n";
@@ -68,13 +68,11 @@ void stats_manager::on_rule_loaded(const falco_rule& rule)
{
while (m_by_rule_id.size() <= rule.id)
{
m_by_rule_id.emplace_back();
m_by_rule_id[m_by_rule_id.size() - 1].reset(new std::atomic<uint64_t>(0));
m_by_rule_id.emplace_back(std::make_unique<std::atomic<uint64_t>>(0));
}
while (m_by_priority.size() <= (size_t) rule.priority)
{
m_by_priority.emplace_back();
m_by_priority[m_by_priority.size() - 1].reset(new std::atomic<uint64_t>(0));
m_by_priority.emplace_back(std::make_unique<std::atomic<uint64_t>>(0));
}
}

View File

@@ -63,6 +63,23 @@ public:
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::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
{
return m_by_rule_id;
}
private:
std::atomic<uint64_t> m_total;
std::vector<std::unique_ptr<std::atomic<uint64_t>>> m_by_priority;

View File

@@ -14,8 +14,7 @@
configure_file(config_falco.h.in config_falco.h)
set(
FALCO_SOURCES
add_library(falco_application STATIC
app/app.cpp
app/options.cpp
app/restart_handler.cpp
@@ -49,8 +48,8 @@ set(
app/actions/start_webserver.cpp
app/actions/validate_rules_files.cpp
app/actions/create_requested_paths.cpp
app/actions/close_inspectors.cpp
configuration.cpp
logger.cpp
falco_outputs.cpp
outputs_file.cpp
outputs_stdout.cpp
@@ -62,16 +61,12 @@ set(
set(
FALCO_INCLUDE_DIRECTORIES
"${PROJECT_SOURCE_DIR}/userspace/engine"
"${PROJECT_BINARY_DIR}/userspace/falco"
"${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_BINARY_DIR}"
"${PROJECT_BINARY_DIR}/driver/src"
"${CXXOPTS_INCLUDE_DIR}"
"${YAMLCPP_INCLUDE_DIR}"
"${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}"
)
list(APPEND FALCO_INCLUDE_DIRECTORIES "${FALCO_EXTRA_INCLUDE_DIRS}")
set(
FALCO_DEPENDENCIES
cxxopts
@@ -81,31 +76,28 @@ set(
FALCO_LIBRARIES
falco_engine
sinsp
"${YAMLCPP_LIB}"
yaml-cpp
)
list(APPEND FALCO_DEPENDENCIES yamlcpp)
if(NOT WIN32)
list(
APPEND FALCO_SOURCES
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)
list(
APPEND FALCO_SOURCES
target_sources(falco_application
PRIVATE
outputs_grpc.cpp
outputs_http.cpp
falco_metrics.cpp
webserver.cpp
grpc_context.cpp
grpc_server_impl.cpp
grpc_request_context.cpp
grpc_server.cpp
grpc_context.cpp
grpc_server_impl.cpp
${CMAKE_CURRENT_BINARY_DIR}/version.grpc.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/version.pb.cc
${CMAKE_CURRENT_BINARY_DIR}/outputs.grpc.pb.cc
@@ -115,7 +107,6 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT MINIMAL_BUILD)
list(
APPEND FALCO_INCLUDE_DIRECTORIES
"${CPPHTTPLIB_INCLUDE}"
"${OPENSSL_INCLUDE_DIR}"
"${GRPC_INCLUDE}"
"${GRPCPP_INCLUDE}"
@@ -128,29 +119,24 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT MINIMAL_BUILD)
list(APPEND FALCO_LIBRARIES "${GRPC_LIBRARIES}")
endif()
list(APPEND FALCO_DEPENDENCIES cpp-httplib)
list(
APPEND FALCO_LIBRARIES
httplib::httplib
"${GRPCPP_LIB}"
"${GRPC_LIB}"
"${GPR_LIB}"
"${PROTOBUF_LIB}"
"${CARES_LIB}"
"${OPENSSL_LIBRARIES}"
"${YAMLCPP_LIB}"
)
endif()
add_library(
falco_application STATIC
${FALCO_SOURCES}
)
if (EMSCRIPTEN)
target_compile_options(falco_application PRIVATE "-sDISABLE_EXCEPTION_CATCHING=0")
endif()
target_compile_definitions(falco_application PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT)
add_dependencies(falco_application ${FALCO_DEPENDENCIES})
target_link_libraries(

View File

@@ -56,6 +56,7 @@ falco::app::run_result stop_grpc_server(falco::app::state& s);
falco::app::run_result stop_webserver(falco::app::state& s);
falco::app::run_result unregister_signal_handlers(falco::app::state& s);
falco::app::run_result validate_rules_files(falco::app::state& s);
falco::app::run_result close_inspectors(falco::app::state& s);
}; // namespace actions
}; // namespace app

View File

@@ -0,0 +1,44 @@
// SPDX-License-Identifier: Apache-2.0
/*
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
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "actions.h"
#include "helpers.h"
using namespace falco::app;
using namespace falco::app::actions;
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)
{
s.offline_inspector->close();
}
for (const auto &src : s.loaded_sources)
{
auto src_info = s.source_infos.at(src);
if (src_info->inspector != nullptr)
{
src_info->inspector->close();
}
}
return run_result::ok();
}

View File

@@ -103,7 +103,14 @@ falco::app::run_result falco::app::actions::create_signal_handlers(falco::app::s
falco::app::restart_handler::watch_list_t dirs_to_watch;
if (s.config->m_watch_config_files)
{
files_to_watch.push_back(s.options.conf_filename);
files_to_watch.insert(
files_to_watch.end(),
s.config->m_loaded_configs_filenames.begin(),
s.config->m_loaded_configs_filenames.end());
dirs_to_watch.insert(
dirs_to_watch.end(),
s.config->m_loaded_configs_folders.begin(),
s.config->m_loaded_configs_folders.end());
files_to_watch.insert(
files_to_watch.end(),
s.config->m_loaded_rules_filenames.begin(),

View File

@@ -48,9 +48,10 @@ falco::app::run_result falco::app::actions::open_live_inspector(
{
try
{
if((s.config->m_metrics_flags & PPM_SCAP_STATS_STATE_COUNTERS))
if(s.config->m_falco_libs_thread_table_size > 0)
{
inspector->set_sinsp_stats_v2_enabled();
// Default value is set in libs as part of the sinsp_thread_manager setup
inspector->m_thread_manager->set_max_thread_table_size(s.config->m_falco_libs_thread_table_size);
}
if (source != falco_common::syscall_source) /* Plugin engine */

View File

@@ -66,13 +66,11 @@ void configure_output_format(falco::app::state& s)
void add_source_to_engine(falco::app::state& s, const std::string& src)
{
auto src_info = s.source_infos.at(src);
auto& filterchecks = *src_info->filterchecks.get();
auto& filterchecks = *src_info->filterchecks;
auto* inspector = src_info->inspector.get();
auto filter_factory = std::shared_ptr<sinsp_filter_factory>(
new sinsp_filter_factory(inspector, filterchecks));
auto formatter_factory = std::shared_ptr<sinsp_evt_formatter_factory>(
new sinsp_evt_formatter_factory(inspector, filterchecks));
auto filter_factory = std::make_shared<sinsp_filter_factory>(inspector, filterchecks);
auto formatter_factory = std::make_shared<sinsp_evt_formatter_factory>(inspector, filterchecks);
if(s.config->m_json_output)
{

View File

@@ -65,29 +65,29 @@ static bool populate_filterchecks(
std::unordered_set<std::string>& used_plugins,
std::string& err)
{
std::vector<const filter_check_info*> info;
for(const auto& p : inspector->get_plugin_manager()->plugins())
std::vector<const filter_check_info*> infos;
for(const auto& plugin : inspector->get_plugin_manager()->plugins())
{
if (!(p->caps() & CAP_EXTRACTION))
if (!(plugin->caps() & CAP_EXTRACTION))
{
continue;
}
// check if some fields are overlapping on this event sources
info.clear();
filterchecks.get_all_fields(info);
for (auto &info : info)
infos.clear();
filterchecks.get_all_fields(infos);
for (const auto &info : infos)
{
for (int32_t i = 0; i < info->m_nfields; i++)
{
// check if one of the fields extractable by the plugin
// is already provided by another filtercheck for this source
std::string fname = info->m_fields[i].m_name;
for (auto &f : p->fields())
for (const auto &field : plugin->fields())
{
if (std::string(f.m_name) == fname)
if (field.m_name == fname)
{
err = "Plugin '" + p->name()
err = "Plugin '" + plugin->name()
+ "' supports extraction of field '" + fname
+ "' that is overlapping for source '" + source + "'";
return false;
@@ -97,8 +97,8 @@ static bool populate_filterchecks(
}
// add plugin filterchecks to the event source
filterchecks.add_filter_check(sinsp_plugin::new_filtercheck(p));
used_plugins.insert(p->name());
filterchecks.add_filter_check(sinsp_plugin::new_filtercheck(plugin));
used_plugins.insert(plugin->name());
}
return true;
}
@@ -108,17 +108,26 @@ falco::app::run_result falco::app::actions::init_inspectors(falco::app::state& s
std::string err;
std::unordered_set<std::string> used_plugins;
const auto& all_plugins = s.offline_inspector->get_plugin_manager()->plugins();
for (const auto &src : s.loaded_sources)
{
auto src_info = s.source_infos.at(src);
// in capture mode, every event source uses the offline inspector.
// in live mode, we create a new inspector for each event source
src_info->inspector = s.is_capture_mode()
? s.offline_inspector
: std::make_shared<sinsp>();
if (s.is_capture_mode())
{
src_info->inspector = s.offline_inspector;
}
else
{
src_info->inspector = std::make_shared<sinsp>(false,
"",
"",
"",
s.config->m_metrics_flags & METRICS_V2_STATE_COUNTERS);
}
// do extra preparation for the syscall source
if (src == falco_common::syscall_source)
{
@@ -182,7 +191,7 @@ falco::app::run_result falco::app::actions::init_inspectors(falco::app::state& s
if (!populate_filterchecks(
src_info->inspector,
src,
*src_info->filterchecks.get(),
*src_info->filterchecks,
used_plugins,
err))
{
@@ -197,10 +206,10 @@ falco::app::run_result falco::app::actions::init_inspectors(falco::app::state& s
const auto& sources = src_info->inspector->event_sources();
if (sources.size() == 0 || sources.size() > 2 || sources[0] != falco_common::syscall_source)
{
std::string err;
for (const auto &s : sources)
err.clear();
for (const auto &source : sources)
{
err += (err.empty() ? "" : ", ") + s;
err += (err.empty() ? "" : ", ") + source;
}
return run_result::fatal("Illegal sources setup in live inspector for source '" + src + "': " + err);
}

View File

@@ -60,7 +60,7 @@ falco::app::run_result falco::app::actions::init_outputs(falco::app::state& s)
return run_result::ok();
}
s.outputs.reset(new falco_outputs(
s.outputs = std::make_shared<falco_outputs>(
s.engine,
s.config->m_outputs,
s.config->m_json_output,
@@ -70,7 +70,7 @@ falco::app::run_result falco::app::actions::init_outputs(falco::app::state& s)
s.config->m_buffered_outputs,
s.config->m_outputs_queue_capacity,
s.config->m_time_format_iso_8601,
hostname));
hostname);
return run_result::ok();
}

View File

@@ -28,12 +28,12 @@ falco::app::run_result falco::app::actions::list_plugins(const falco::app::state
if(s.options.list_plugins)
{
std::ostringstream os;
std::unique_ptr<sinsp> inspector(new sinsp());
sinsp inspector;
const auto& configs = s.config->m_plugins;
for (auto &c : configs)
{
// load the plugin (no need to initialize it)
auto plugin = inspector->register_plugin(c.m_library_path);
auto plugin = inspector.register_plugin(c.m_library_path);
format_plugin_info(plugin, os);
os << std::endl;
}

View File

@@ -29,18 +29,21 @@ static falco::app::run_result apply_deprecated_options(const falco::app::state&
falco::app::run_result falco::app::actions::load_config(const falco::app::state& s)
{
// List of loaded conf files, ie: s.options.conf_filename
// plus all the `config_files` expanded list of configs.
std::vector<std::string> loaded_conf_files;
try
{
if (!s.options.conf_filename.empty())
{
s.config->init(s.options.conf_filename, s.options.cmdline_config_options);
s.config->init_from_file(s.options.conf_filename, loaded_conf_files, s.options.cmdline_config_options);
}
else
{
// Is possible to have an empty config file when we want to use some command line
// options like `--help`, `--version`, ...
// The configs used in `load_yaml` will be initialized to the default values.
s.config->init(s.options.cmdline_config_options);
s.config->init_from_content("", s.options.cmdline_config_options);
}
}
catch (std::exception& e)
@@ -57,7 +60,11 @@ falco::app::run_result falco::app::actions::load_config(const falco::app::state&
}
if (!s.options.conf_filename.empty())
{
falco_logger::log(falco_logger::level::INFO, "Falco initialized with configuration file: " + s.options.conf_filename + "\n");
falco_logger::log(falco_logger::level::INFO, "Falco initialized with configuration files:\n");
for (const auto& path : loaded_conf_files)
{
falco_logger::log(falco_logger::level::INFO, std::string(" ") + path + "\n");
}
}
s.config->m_buffered_outputs = !s.options.unbuffered_outputs;

View File

@@ -29,10 +29,10 @@ falco::app::run_result falco::app::actions::load_plugins(falco::app::state& s)
return run_result::fatal("Loading plugins dynamic libraries is not supported by this Falco build");
}
#endif
// Initialize the set of loaded event sources.
// Initialize the set of loaded event sources.
// By default, the set includes the 'syscall' event source
state::source_info syscall_src_info;
syscall_src_info.filterchecks.reset(new sinsp_filter_check_list());
syscall_src_info.filterchecks = std::make_shared<sinsp_filter_check_list>();
s.source_infos.clear();
s.source_infos.insert(syscall_src_info, falco_common::syscall_source);
s.loaded_sources = { falco_common::syscall_source };
@@ -44,7 +44,7 @@ falco::app::run_result falco::app::actions::load_plugins(falco::app::state& s)
// plugins in order to have them available every time we need to access
// their static info. If Falco is in capture mode, this inspector is also
// used to open and read the trace file
s.offline_inspector.reset(new sinsp());
s.offline_inspector = std::make_shared<sinsp>();
// Load all the configured plugins
for(auto &p : s.config->m_plugins)
@@ -55,7 +55,7 @@ falco::app::run_result falco::app::actions::load_plugins(falco::app::state& s)
if(plugin->caps() & CAP_SOURCING && plugin->id() != 0)
{
state::source_info src_info;
src_info.filterchecks.reset(new filter_check_list());
src_info.filterchecks = std::make_shared<filter_check_list>();
auto sname = plugin->event_source();
s.source_infos.insert(src_info, sname);
// note: this avoids duplicate values

View File

@@ -17,6 +17,7 @@ limitations under the License.
#include "actions.h"
#include "helpers.h"
#include "falco_utils.h"
#include <libsinsp/plugin_manager.h>
@@ -83,6 +84,9 @@ falco::app::run_result falco::app::actions::load_rules_files(falco::app::state&
{
falco_logger::log(falco_logger::level::WARNING,res->as_string(true, rc) + "\n");
}
#if defined(__linux__) and !defined(MINIMAL_BUILD) and !defined(__EMSCRIPTEN__)
s.config->m_loaded_rules_filenames_sha256sum.insert({filename, falco::utils::calculate_file_sha256sum(filename)});
#endif
}
// note: we have an egg-and-chicken problem here. We would like to check
@@ -127,6 +131,12 @@ falco::app::run_result falco::app::actions::load_rules_files(falco::app::state&
return run_result::fatal(err);
}
if((!s.options.disabled_rule_substrings.empty() || !s.options.disabled_rule_tags.empty() || !s.options.enabled_rule_tags.empty()) &&
!s.config->m_rules_selection.empty())
{
return run_result::fatal("Specifying -D, -t, -T command line options together with \"rules:\" configuration or -o \"rules...\" is not supported.");
}
for (const auto& substring : s.options.disabled_rule_substrings)
{
falco_logger::log(falco_logger::level::INFO, "Disabling rules matching substring: " + substring + "\n");
@@ -154,6 +164,27 @@ falco::app::run_result falco::app::actions::load_rules_files(falco::app::state&
s.engine->enable_rule_by_tag(s.options.enabled_rule_tags, true);
}
for(const auto& sel : s.config->m_rules_selection)
{
bool enable = sel.m_op == falco_configuration::rule_selection_operation::enable;
if(sel.m_rule != "")
{
falco_logger::log(falco_logger::level::INFO,
(enable ? "Enabling" : "Disabling") + std::string(" rules with name: ") + sel.m_rule + "\n");
s.engine->enable_rule_wildcard(sel.m_rule, enable);
}
if(sel.m_tag != "")
{
falco_logger::log(falco_logger::level::INFO,
(enable ? "Enabling" : "Disabling") + std::string(" rules with tag: ") + sel.m_tag + "\n");
s.engine->enable_rule_by_tag(std::set<std::string>{sel.m_tag}, enable); // TODO wildcard support
}
}
// printout of `-L` option
if (s.options.describe_all_rules || !s.options.describe_rule.empty())
{

View File

@@ -24,28 +24,28 @@ limitations under the License.
using namespace falco::app;
using namespace falco::app::actions;
falco::app::run_result falco::app::actions::pidfile(const falco::app::state& s)
falco::app::run_result falco::app::actions::pidfile(const falco::app::state& state)
{
if (s.options.dry_run)
if (state.options.dry_run)
{
falco_logger::log(falco_logger::level::DEBUG, "Skipping pidfile creation in dry-run\n");
return run_result::ok();
}
if (!s.options.pidfilename.empty())
if (!state.options.pidfilename.empty())
{
int64_t self_pid = getpid();
std::ofstream pidfile;
pidfile.open(s.options.pidfilename);
std::ofstream stream;
stream.open(state.options.pidfilename);
if (!pidfile.good())
if (!stream.good())
{
falco_logger::log(falco_logger::level::ERR, "Could not write pid to pidfile " + s.options.pidfilename + ". Exiting.\n");
falco_logger::log(falco_logger::level::ERR, "Could not write pid to pidfile " + state.options.pidfilename + ". Exiting.\n");
exit(-1);
}
pidfile << self_pid;
pidfile.close();
stream << self_pid;
stream.close();
}

View File

@@ -25,8 +25,8 @@ falco::app::run_result falco::app::actions::print_generated_gvisor_config(falco:
{
if(!s.options.gvisor_generate_config_with_socket.empty())
{
std::unique_ptr<sinsp> i(new sinsp());
std::string gvisor_config = i->generate_gvisor_config(s.options.gvisor_generate_config_with_socket);
sinsp i;
std::string gvisor_config = i.generate_gvisor_config(s.options.gvisor_generate_config_with_socket);
printf("%s\n", gvisor_config.c_str());
return run_result::exit();
}

View File

@@ -27,14 +27,14 @@ falco::app::run_result falco::app::actions::print_plugin_info(const falco::app::
{
if(!s.options.print_plugin_info.empty())
{
std::unique_ptr<sinsp> inspector(new sinsp());
sinsp inspector;
for(auto &pc : s.config->m_plugins)
{
if (pc.m_name == s.options.print_plugin_info
|| pc.m_library_path == s.options.print_plugin_info)
{
// load the plugin
auto p = inspector->register_plugin(pc.m_library_path);
auto p = inspector.register_plugin(pc.m_library_path);
// print plugin descriptive info
std::ostringstream os;
@@ -61,7 +61,7 @@ falco::app::run_result falco::app::actions::print_plugin_info(const falco::app::
os << schema << std::endl;
os << std::endl;
printf("%s", os.str().c_str());
// init the plugin
std::string err;
if (!p->init(pc.m_init_config, err))

View File

@@ -108,7 +108,7 @@ falco::app::run_result falco::app::actions::print_support(falco::app::state& s)
support["version"] = infos.falco_version;
support["engine_info"] = infos.as_json();
support["cmdline"] = s.cmdline;
support["config"] = read_file(s.options.conf_filename);
support["config"] = s.config->dump();
support["rules_files"] = nlohmann::json::array();
for(const auto& filename : s.config->m_loaded_rules_filenames)
{

View File

@@ -199,7 +199,7 @@ static falco::app::run_result do_inspect(
}
else if(rc == SCAP_TIMEOUT)
{
if(unlikely(ev == nullptr))
if(ev == nullptr) [[unlikely]]
{
timeouts_since_last_success_or_msg++;
if(timeouts_since_last_success_or_msg > s.config->m_syscall_evt_timeout_max_consecutives
@@ -310,7 +310,7 @@ static falco::app::run_result do_inspect(
auto res = s.engine->process_event(source_engine_idx, ev, s.config->m_rule_matching);
if(res != nullptr)
{
for(auto& rule_res : *res.get())
for(auto& rule_res : *res)
{
s.outputs->handle_event(rule_res.evt, rule_res.rule, rule_res.source, rule_res.priority_num, rule_res.format, rule_res.tags);
}
@@ -413,9 +413,9 @@ static falco::app::run_result init_stats_writer(
return falco::app::run_result::fatal("Metrics interval was passed as numeric value without Prometheus time unit. Please specify a time unit");
}
if (config->m_metrics_enabled && !sw->has_output())
if (config->m_metrics_enabled && !(sw->has_output() || config->m_webserver_config.m_prometheus_metrics_enabled))
{
return falco::app::run_result::fatal("Metrics are enabled with no output configured. Please enable at least one output channel");
return falco::app::run_result::fatal("Metrics are enabled with no output configured. Please enable at least one output channel ('metrics.output_rule', 'metrics.output_file' or 'webserver.prometheus_metrics_enabled')");
}
falco_logger::log(falco_logger::level::INFO, "Setting metrics interval to " + config->m_metrics_interval_str + ", equivalent to " + std::to_string(config->m_metrics_interval) + " (ms)\n");
@@ -436,7 +436,7 @@ falco::app::run_result falco::app::actions::process_events(falco::app::state& s)
s.engine->complete_rule_loading();
// Initialize stats writer
auto statsw = std::make_shared<stats_writer>(s.outputs, s.config);
auto statsw = std::make_shared<stats_writer>(s.outputs, s.config, s.engine);
auto res = init_stats_writer(statsw, s.config, s.options.dry_run);
if (s.options.dry_run)
@@ -488,10 +488,9 @@ falco::app::run_result falco::app::actions::process_events(falco::app::state& s)
ctxs.reserve(s.enabled_sources.size());
for (const auto& source : s.enabled_sources)
{
ctxs.emplace_back();
auto& ctx = ctxs[ctxs.size() - 1];
auto& ctx = ctxs.emplace_back();
ctx.source = source;
ctx.sync.reset(new source_sync_context(termination_sem));
ctx.sync = std::make_unique<source_sync_context>(termination_sem);
auto src_info = s.source_infos.at(source);
try
@@ -517,9 +516,9 @@ falco::app::run_result falco::app::actions::process_events(falco::app::state& s)
{
auto res_ptr = &ctx.res;
auto sync_ptr = ctx.sync.get();
ctx.thread.reset(new std::thread([&s, src_info, &statsw, source, sync_ptr, res_ptr](){
ctx.thread = std::make_unique<std::thread>([&s, src_info, &statsw, source, sync_ptr, res_ptr]() {
process_inspector_events(s, src_info->inspector, statsw, source, sync_ptr, res_ptr);
}));
});
}
}
catch (std::exception &e)
@@ -536,9 +535,9 @@ falco::app::run_result falco::app::actions::process_events(falco::app::state& s)
// wait for event processing to terminate for all sources
// if a thread terminates with an error, we trigger the app termination
// to force all other event streams to terminate too.
// We accomulate the errors in a single run_result.
size_t closed_count = 0;
while (closed_count < ctxs.size())
// We accumulate the errors in a single run_result.
size_t stopped_count = 0;
while (stopped_count < ctxs.size())
{
if (!res.success && !termination_forced)
{
@@ -573,12 +572,12 @@ falco::app::run_result falco::app::actions::process_events(falco::app::state& s)
ctx.thread->join();
}
falco_logger::log(falco_logger::level::DEBUG, "Closing event source '" + ctx.source + "'\n");
s.source_infos.at(ctx.source)->inspector->close();
falco_logger::log(falco_logger::level::DEBUG, "Stopping capture for event source '" + ctx.source + "'\n");
s.source_infos.at(ctx.source)->inspector->stop_capture();
res = run_result::merge(res, ctx.res);
ctx.sync->join();
closed_count++;
stopped_count++;
}
}
}

View File

@@ -24,53 +24,48 @@ limitations under the License.
using namespace falco::app;
using namespace falco::app::actions;
falco::app::run_result falco::app::actions::start_webserver(falco::app::state& s)
falco::app::run_result falco::app::actions::start_webserver(falco::app::state& state)
{
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
if(!s.is_capture_mode() && s.config->m_webserver_enabled)
if(!state.is_capture_mode() && state.config->m_webserver_enabled)
{
if (s.options.dry_run)
if (state.options.dry_run)
{
falco_logger::log(falco_logger::level::DEBUG, "Skipping starting webserver in dry-run\n");
return run_result::ok();
}
std::string ssl_option = (s.config->m_webserver_ssl_enabled ? " (SSL)" : "");
falco_configuration::webserver_config webserver_config = state.config->m_webserver_config;
std::string ssl_option = (webserver_config.m_ssl_enabled ? " (SSL)" : "");
falco_logger::log(falco_logger::level::INFO, "Starting health webserver with threadiness "
+ std::to_string(s.config->m_webserver_threadiness)
+ std::to_string(webserver_config.m_threadiness)
+ ", listening on "
+ s.config->m_webserver_listen_address
+ webserver_config.m_listen_address
+ ":"
+ std::to_string(s.config->m_webserver_listen_port)
+ std::to_string(webserver_config.m_listen_port)
+ ssl_option + "\n");
s.webserver.start(
s.offline_inspector,
s.config->m_webserver_threadiness,
s.config->m_webserver_listen_port,
s.config->m_webserver_listen_address,
s.config->m_webserver_k8s_healthz_endpoint,
s.config->m_webserver_ssl_certificate,
s.config->m_webserver_ssl_enabled);
state.webserver.start(
state,
webserver_config);
}
#endif
return run_result::ok();
}
falco::app::run_result falco::app::actions::stop_webserver(falco::app::state& s)
falco::app::run_result falco::app::actions::stop_webserver(falco::app::state& state)
{
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
if(!s.is_capture_mode() && s.config->m_webserver_enabled)
if(!state.is_capture_mode() && state.config->m_webserver_enabled)
{
if (s.options.dry_run)
if (state.options.dry_run)
{
falco_logger::log(falco_logger::level::DEBUG, "Skipping stopping webserver in dry-run\n");
return run_result::ok();
}
s.webserver.stop();
state.webserver.stop();
}
#endif
return run_result::ok();
}

View File

@@ -95,6 +95,7 @@ bool falco::app::run(falco::app::state& s, bool& restart, std::string& errstr)
falco::app::actions::unregister_signal_handlers,
falco::app::actions::stop_grpc_server,
falco::app::actions::stop_webserver,
falco::app::actions::close_inspectors,
};
falco::app::run_result res = falco::app::run_result::ok();

View File

@@ -26,25 +26,6 @@ limitations under the License.
namespace falco {
namespace app {
// Most bool member variables do not need to be set explicitly, as
// they are bound to command line options that have default
// values. However, a few options can be ifdef'd out so explicitly
// initialize their linked variables.
options::options()
: event_buffer_format(sinsp_evt::PF_NORMAL),
list_fields(false),
list_plugins(false),
list_syscall_events(false),
markdown(false),
unbuffered_outputs(false),
dry_run(false)
{
}
options::~options()
{
}
bool options::parse(int argc, char **argv, std::string &errstr)
{
cxxopts::Options opts("falco", "Falco - Cloud Native Runtime Security");
@@ -117,6 +98,7 @@ bool options::parse(int argc, char **argv, std::string &errstr)
// Convert the vectors of enabled/disabled tags into sets to match falco engine API
if(m_cmdline_parsed.count("T") > 0)
{
falco_logger::log(falco_logger::level::WARNING, "The -T option is deprecated and will be removed in Falco 0.39.0. Use -o rules[].disable.tag=<tag> instead.");
for(auto &tag : m_cmdline_parsed["T"].as<std::vector<std::string>>())
{
disabled_rule_tags.insert(tag);
@@ -125,12 +107,18 @@ bool options::parse(int argc, char **argv, std::string &errstr)
if(m_cmdline_parsed.count("t") > 0)
{
falco_logger::log(falco_logger::level::WARNING, "The -t option is deprecated and will be removed in Falco 0.39.0. Use -o rules[].disable.rule=* -o rules[].enable.tag=<tag> instead.");
for(auto &tag : m_cmdline_parsed["t"].as<std::vector<std::string>>())
{
enabled_rule_tags.insert(tag);
}
}
if(disabled_rule_substrings.size() > 0)
{
falco_logger::log(falco_logger::level::WARNING, "The -D option is deprecated and will be removed in Falco 0.39.0. Use -o rules[].disable.rule=<wildcard-pattern> instead.");
}
// Some combinations of arguments are not allowed.
// You can't both disable and enable rules
@@ -168,7 +156,7 @@ void options::define(cxxopts::Options& opts)
#endif
("disable-source", "Turn off a specific <event_source>. By default, all loaded sources get enabled. Available sources are 'syscall' plus all sources defined by loaded plugins supporting the event sourcing capability. This option can be passed multiple times, but turning off all event sources simultaneously is not permitted. This option can not be mixed with --enable-source. This option has no effect when reproducing events from a capture file.", cxxopts::value(disable_sources), "<event_source>")
("dry-run", "Run Falco without processing events. It can help check that the configuration and rules do not have any errors.", cxxopts::value(dry_run)->default_value("false"))
("D", "Turn off any rules with names having the substring <substring>. This option can be passed multiple times. It cannot be mixed with -t.", cxxopts::value(disabled_rule_substrings), "<substring>")
("D", "DEPRECATED: use -o rules[].disable.rule=<wildcard-pattern> instead. Turn off any rules with names having the substring <substring>. This option can be passed multiple times. It cannot be mixed with -t.", cxxopts::value(disabled_rule_substrings), "<substring>")
("enable-source", "Enable a specific <event_source>. By default, all loaded sources get enabled. Available sources are 'syscall' plus all sources defined by loaded plugins supporting the event sourcing capability. This option can be passed multiple times. When using this option, only the event sources specified by it will be enabled. This option can not be mixed with --disable-source. This option has no effect when reproducing events from a capture file.", cxxopts::value(enable_sources), "<event_source>")
#ifdef HAS_GVISOR
("gvisor-generate-config", "Generate a configuration file that can be used for gVisor and exit. See --gvisor-config for more details.", cxxopts::value<std::string>(gvisor_generate_config_with_socket)->implicit_value("/run/falco/gvisor.sock"), "<socket_path>")
@@ -184,13 +172,13 @@ void options::define(cxxopts::Options& opts)
("N", "Only print field names when used in conjunction with the --list option. It has no effect when used with other options.", cxxopts::value(names_only)->default_value("false"))
("o,option", "Set the value of option <opt> to <val>. Overrides values in the configuration file. <opt> can be identified using its location in the configuration file using dot notation. Elements of list entries can be accessed via square brackets [].\n E.g. base.id = val\n base.subvalue.subvalue2 = val\n base.list[1]=val", cxxopts::value(cmdline_config_options), "<opt>=<val>")
("plugin-info", "Print info for the plugin specified by <plugin_name> and exit.\nThis includes all descriptive information like name and author, along with the\nschema format for the init configuration and a list of suggested open parameters.\n<plugin_name> can be the plugin's name or its configured 'library_path'.", cxxopts::value(print_plugin_info), "<plugin_name>")
("p,print", "Print (or replace) additional information in the rule's output.\nUse -pc or -pcontainer to append container details.\nUse -pk or -pkubernetes to add both container and Kubernetes details.\nIf using gVisor, choose -pcg or -pkg variants (or -pcontainer-gvisor and -pkubernetes-gvisor, respectively).\nIf a rule's output contains %container.info, it will be replaced with the corresponding details. Otherwise, these details will be directly appended to the rule's output.\nAlternatively, use -p <output_format> for a custom format. In this case, the given <output_format> will be appended to the rule's output without any replacement.", cxxopts::value(print_additional), "<output_format>")
("p,print", "Print (or replace) additional information in the rule's output.\nUse -pc or -pcontainer to append container details to syscall events.\nUse -pk or -pkubernetes to add both container and Kubernetes details to syscall events.\nIf using gVisor, choose -pcg or -pkg variants (or -pcontainer-gvisor and -pkubernetes-gvisor, respectively).\nIf a syscall rule's output contains %container.info, it will be replaced with the corresponding details. Otherwise, these details will be directly appended to the rule's output.\nAlternatively, use -p <output_format> for a custom format. In this case, the given <output_format> will be appended to the rule's output without any replacement to all events, including plugin events.", cxxopts::value(print_additional), "<output_format>")
("P,pidfile", "Write PID to specified <pid_file> path. By default, no PID file is created.", cxxopts::value(pidfilename)->default_value(""), "<pid_file>")
("r", "Rules file or directory to be loaded. This option can be passed multiple times. Falco defaults to the values in the configuration file when this option is not specified.", cxxopts::value<std::vector<std::string>>(), "<rules_file>")
("S,snaplen", "Collect only the first <len> bytes of each I/O buffer for 'syscall' events. By default, the first 80 bytes are collected by the driver and sent to the user space for processing. Use this option with caution since it can have a strong performance impact.", cxxopts::value(snaplen)->default_value("0"), "<len>")
("support", "Print support information, including version, rules files used, loaded configuration, etc., and exit. The output is in JSON format.", cxxopts::value(print_support)->default_value("false"))
("T", "Turn off any rules with a tag=<tag>. This option can be passed multiple times. This option can not be mixed with -t.", cxxopts::value<std::vector<std::string>>(), "<tag>")
("t", "Only enable those rules with a tag=<tag>. This option can be passed multiple times. This option can not be mixed with -T/-D.", cxxopts::value<std::vector<std::string>>(), "<tag>")
("T", "DEPRECATED: use -o rules[].disable.tag=<tag> instead. Turn off any rules with a tag=<tag>. This option can be passed multiple times. This option can not be mixed with -t.", cxxopts::value<std::vector<std::string>>(), "<tag>")
("t", "DEPRECATED: use -o rules[].disable.rule=* -o rules[].enable.tag=<tag> instead. Only enable those rules with a tag=<tag>. This option can be passed multiple times. This option can not be mixed with -T/-D.", cxxopts::value<std::vector<std::string>>(), "<tag>")
("U,unbuffered", "Turn off output buffering for configured outputs. This causes every single line emitted by Falco to be flushed, which generates higher CPU usage but is useful when piping those outputs into another process or a script.", cxxopts::value(unbuffered_outputs)->default_value("false"))
("V,validate", "Read the contents of the specified <rules_file> file(s), validate the loaded rules, and exit. This option can be passed multiple times to validate multiple files.", cxxopts::value(validate_rules_filenames), "<rules_file>")
("v", "Enable verbose output.", cxxopts::value(verbose)->default_value("false"))

View File

@@ -31,50 +31,50 @@ namespace app {
class options {
public:
options();
virtual ~options();
options() = default;
~options() = default;
options(options&&) = default;
options& operator = (options&&) = default;
options(const options&) = default;
options& operator = (const options&) = default;
// Each of these maps directly to a command line option.
bool help;
bool help = false;
std::string conf_filename;
bool all_events;
sinsp_evt::param_fmt event_buffer_format;
bool all_events = false;
sinsp_evt::param_fmt event_buffer_format = sinsp_evt::PF_NORMAL;
std::vector<std::string> cri_socket_paths;
bool disable_cri_async;
bool disable_cri_async = false;
std::vector<std::string> disable_sources;
std::vector<std::string> disabled_rule_substrings;
std::vector<std::string> enable_sources;
std::string gvisor_generate_config_with_socket;
bool describe_all_rules;
bool describe_all_rules = false;
std::string describe_rule;
bool print_ignored_events;
bool list_fields;
bool list_fields = false;
std::string list_source_fields;
bool list_plugins;
bool list_plugins = false;
std::string print_plugin_info;
bool list_syscall_events;
bool markdown;
int duration_to_tot;
bool names_only;
bool list_syscall_events = false;
bool markdown = false;
int duration_to_tot = 0;
bool names_only = false;
std::vector<std::string> cmdline_config_options;
std::string print_additional;
std::string pidfilename;
// Rules list as passed by the user, via cmdline option '-r'
std::list<std::string> rules_filenames;
uint64_t snaplen;
bool print_support;
uint64_t snaplen = 0;
bool print_support = false;
std::set<std::string> disabled_rule_tags;
std::set<std::string> enabled_rule_tags;
bool unbuffered_outputs;
bool unbuffered_outputs = false;
std::vector<std::string> validate_rules_filenames;
bool verbose;
bool print_version_info;
bool print_page_size;
bool dry_run;
bool verbose = false;
bool print_version_info = false;
bool print_page_size = false;
bool dry_run = false;
bool parse(int argc, char **argv, std::string &errstr);

View File

@@ -17,7 +17,7 @@ limitations under the License.
#include "restart_handler.h"
#include "signals.h"
#include "../logger.h"
#include "logger.h"
#include <string.h>
#include <fcntl.h>

View File

@@ -48,18 +48,11 @@ struct state
// Holds the info mapped for each loaded event source
struct source_info
{
source_info():
engine_idx(-1),
filterchecks(new filter_check_list()),
inspector(nullptr) { }
source_info(source_info&&) = default;
source_info& operator = (source_info&&) = default;
source_info(const source_info&) = default;
source_info& operator = (const source_info&) = default;
source_info() : filterchecks(std::make_shared<filter_check_list>()) {}
// The index of the given event source in the state's falco_engine,
// as returned by falco_engine::add_source
std::size_t engine_idx;
std::size_t engine_idx = -1;
// The filtercheck list containing all fields compatible
// with the given event source
std::shared_ptr<filter_check_list> filterchecks;
@@ -71,32 +64,21 @@ struct state
};
state():
restart(false),
config(std::make_shared<falco_configuration>()),
outputs(nullptr),
engine(std::make_shared<falco_engine>()),
loaded_sources(),
enabled_sources(),
offline_inspector(std::make_shared<sinsp>()),
source_infos(),
plugin_configs(),
selected_sc_set(),
syscall_buffer_bytes_size(DEFAULT_DRIVER_BUFFER_BYTES_DIM),
restarter(nullptr)
offline_inspector(std::make_shared<sinsp>())
{
}
state(const std::string& cmd, const falco::app::options& opts): state()
{
cmdline = cmd;
options = opts;
cmdline = cmd;
options = opts;
}
~state() = default;
std::string cmdline;
falco::app::options options;
std::atomic<bool> restart;
std::atomic<bool> restart = false;
std::shared_ptr<falco_configuration> config;
@@ -129,7 +111,7 @@ struct state
libsinsp::events::set<ppm_sc_code> selected_sc_set;
// Dimension of the syscall buffer in bytes.
uint64_t syscall_buffer_bytes_size;
uint64_t syscall_buffer_bytes_size = DEFAULT_DRIVER_BUFFER_BYTES_DIM;
// Helper responsible for watching of handling hot application restarts
std::shared_ptr<restart_handler> restarter;

Some files were not shown because too many files have changed in this diff Show More