Compare commits

..

48 Commits

Author SHA1 Message Date
Federico Di Pierro
31d623261f wip
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2023-09-28 15:54:53 +02:00
Jason Dellaluce
d3e1a1f746 chore(userspace/engine): apply codespell suggestions
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-09-28 12:39:20 +02:00
Jason Dellaluce
aae114c331 refactor(userspace/engine)!: rename some description details outputs
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-09-28 12:39:20 +02:00
Jason Dellaluce
b67ad907a7 fix(userspace/engine): solve issues with filter details resolver
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-09-28 12:39:20 +02:00
Jason Dellaluce
dc264a0577 fix(userspace/engine): solve issues in describing rules/macros/lists
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-09-28 12:39:20 +02:00
Jason Dellaluce
8f411f3d3b refactor(userspace/engine): modularize rules files compilation
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-09-28 12:39:20 +02:00
Jason Dellaluce
cba80a404f fix(userspace/engine): print rules fields with arguments
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-09-28 12:39:20 +02:00
Jason Dellaluce
26bdefae8e update(userspace/engine): support printing plugins used by rules
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-09-28 12:39:20 +02:00
Jason Dellaluce
dce5cac820 update(userspace/engine): find evt names in filter resolver
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-09-28 12:39:20 +02:00
Jason Dellaluce
ab77a5d687 update(userspace/engine): refactor rule describe methods to accept plugins
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-09-28 12:39:20 +02:00
Federico Di Pierro
7c7ec800a6 chore(ci): bumped rn2md to latest master.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2023-09-27 11:20:12 +02:00
dependabot[bot]
e0ac9c4142 build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `7a7cf24` to `c366d5b`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](7a7cf24f7d...c366d5bd03)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-27 11:00:12 +02:00
Andrea Terzolo
4de74f3963 cleanup(falco)!: remove --userspace support
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2023-09-26 16:14:07 +02:00
Luca Guerra
cca1d705c2 fix(docs): 0.36.0 release date
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-26 12:38:07 +02:00
Luca Guerra
bbb8b014c5 update(docs): add changelog for 0.36.0
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-26 12:38:07 +02:00
dependabot[bot]
2571225571 build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `77ba57a` to `7a7cf24`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](77ba57ab2c...7a7cf24f7d)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-26 11:10:07 +02:00
Federico Di Pierro
b02898dc4c chore(cmake): bumped libs to 0.13.1.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2023-09-25 14:30:05 +02:00
dependabot[bot]
66ece1a9ac build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `69c9be8` to `77ba57a`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](69c9be89d7...77ba57ab2c)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-22 19:36:49 +02:00
Andrea Terzolo
ab6d76e6d2 chore: bump submodule testing to 62edc65
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2023-09-22 15:20:49 +02:00
Luca Guerra
260f189028 update(gha): add version for rn2md
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-22 14:34:49 +02:00
dependabot[bot]
1b29389ed4 build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `6d3fcf0` to `69c9be8`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](6d3fcf0467...69c9be89d7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-22 14:27:49 +02:00
Federico Di Pierro
bb92dcfd2f update(cmake): bumped falcoctl to 0.6.2.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2023-09-22 13:04:49 +02:00
Federico Di Pierro
0884ca4c6f chore: automatically attach release author to release body.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2023-09-22 12:18:49 +02:00
Federico Di Pierro
e836157771 chore(ci): added permissions to release-body job.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2023-09-21 21:04:47 +02:00
Federico Di Pierro
086deb9c6d chore(ci): only run release-body for latest releases, and properly override release name.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2023-09-21 21:04:47 +02:00
Federico Di Pierro
49adbf6d08 new(ci): autogenerate release body.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2023-09-21 21:04:47 +02:00
Andrea Terzolo
16a37e5c2e fix(dockerfile): remove useless CMD
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2023-09-21 17:38:47 +02:00
Andrea Terzolo
c5996bd0cf chore: bump libs to the latest tag
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2023-09-21 16:53:47 +02:00
Andrea Terzolo
83db0bb4e2 docs: add a warning for metrics
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2023-09-21 16:53:47 +02:00
Andrea Terzolo
d61eaeb5fc chore: bump to the latest libs
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2023-09-21 16:53:47 +02:00
Luca Guerra
111a76879b update(falco): bundle rules 2.0.0
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-21 16:16:47 +02:00
Leonardo Grasso
fe50ac22ee update: add SPDX license identifier
See https://github.com/falcosecurity/evolution/issues/318

Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-09-21 13:21:47 +02:00
dependabot[bot]
e3e854f016 build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `bea364e` to `6d3fcf0`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](bea364ef41...6d3fcf0467)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-21 12:36:47 +02:00
Federico Di Pierro
5ed9dc0c3a update(cmake): bumped plugins to latest stable versions.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2023-09-21 10:53:47 +02:00
Andrea Terzolo
2c95fae9eb chore: bump to latest libs
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2023-09-19 14:07:33 +02:00
dependabot[bot]
e3e9efa661 build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `ee5fb38` to `bea364e`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](ee5fb38eba...bea364ef41)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-19 08:45:41 +02:00
Luca Guerra
9f5e458f92 update(build): update falcoctl to 0.6.1
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-18 16:29:47 +02:00
dependabot[bot]
071910e6dc build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `43580b4` to `ee5fb38`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](43580b4ceb...ee5fb38eba)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-15 10:38:32 +02:00
Federico Di Pierro
cf10d9022e update(cmake): bumped libs to 0.13.0-rc2 and driver to 6.0.1+driver.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2023-09-14 15:49:27 +02:00
Luca Guerra
60a64ac647 fix(docker): get the driver loader legacy from the right directory
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-13 15:19:40 +02:00
Luca Guerra
e5e7a4761d fix(build): set the right bucket and version for driver legacy
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-13 15:19:40 +02:00
Andrea Terzolo
6bd40f3ea2 cleanup: thrown exceptions and avoid multiple logs
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2023-09-13 11:28:40 +02:00
dependabot[bot]
c9a424d75e build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `c6e01fa` to `43580b4`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](c6e01fa7a5...43580b4ceb)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-13 09:29:39 +02:00
dependabot[bot]
e2b21402ae build(deps): Bump submodules/falcosecurity-testing
Bumps [submodules/falcosecurity-testing](https://github.com/falcosecurity/testing) from `76d1743` to `30c3643`.
- [Commits](76d1743a0a...30c36439fc)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-13 09:28:40 +02:00
Luca Guerra
7b4264918b update(docs): add driver-loader-legacy to readme and fix bad c&p
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-12 13:33:35 +02:00
Jason Dellaluce
5595212ff9 fix(userspace/falco): clearing full output queue
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-09-12 13:19:35 +02:00
dependabot[bot]
fdd520f163 build(deps): Bump submodules/falcosecurity-rules
Bumps [submodules/falcosecurity-rules](https://github.com/falcosecurity/rules) from `d31dbc2` to `c6e01fa`.
- [Release notes](https://github.com/falcosecurity/rules/releases)
- [Commits](d31dbc26ea...c6e01fa7a5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-12 09:16:34 +02:00
Leonardo Grasso
b5e3ef95fe docs: add LICENSE file
This commit creates a copy of https://github.com/falcosecurity/falco/blob/master/COPYING (which is kept for historical reasons) to address the recommendation reported by https://github.com/falcosecurity/evolution/issues/317

Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-09-12 09:15:34 +02:00
18 changed files with 522 additions and 268 deletions

View File

@@ -147,7 +147,7 @@ jobs:
sed -i s/FALCOVER/${{ github.event.release.tag_name }}/g release-body.md
- name: Generate release notes
uses: leodido/rn2md@1a17f0e75758c15128a5146e8af5ca3a47209b3f
uses: leodido/rn2md@0669e5f3b21492c11c2db43cd6e267566f5880f3
with:
milestone: ${{ github.event.release.tag_name }}
output: ./notes.md

View File

@@ -3,7 +3,7 @@
## v0.36.0
Released on 2023-09-25
Released on 2023-09-26
### Breaking Changes

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 "0.13.1")
set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=2be42a27be3ffe6bd7e53eaa5d8358cab05a0dca821819c6e9059e51b9786219")
set(FALCOSECURITY_LIBS_VERSION "ebd17a1cfb5935d774681aa6a4696deb6561d965")
# set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=2be42a27be3ffe6bd7e53eaa5d8358cab05a0dca821819c6e9059e51b9786219")
endif()
# cd /path/to/build && cmake /path/to/source

View File

@@ -46,7 +46,6 @@ limitations under the License.
#include "utils.h"
#include "banned.h" // This raises a compilation error when certain functions are used
#include "evttype_index_ruleset.h"
#include "filter_details_resolver.h"
const std::string falco_engine::s_default_ruleset = "falco-default-ruleset";
@@ -191,22 +190,60 @@ void falco_engine::load_rules(const std::string &rules_content, bool verbose, bo
std::unique_ptr<load_result> falco_engine::load_rules(const std::string &rules_content, const std::string &name)
{
rule_loader::configuration cfg(rules_content, m_sources, name);
cfg.min_priority = m_min_priority;
cfg.output_extra = m_extra;
cfg.replace_output_container_info = m_replace_container_info;
cfg.default_ruleset_id = m_default_ruleset_id;
// read rules YAML file and collect its definitions
rule_loader::reader reader;
if (reader.read(cfg, m_rule_collector))
{
{
// compile the definitions (resolve macro/list refs, exceptions, ...)
rule_loader::compiler::compile_output out;
rule_loader::compiler().compile(cfg, m_rule_collector, out);
// clear the rules known by the engine and each ruleset
m_rules.clear();
for (auto &src : m_sources)
{
src.ruleset = src.ruleset_factory->new_ruleset();
}
rule_loader::compiler compiler;
m_rules.clear();
compiler.compile(cfg, m_rule_collector, m_rules);
// add rules to the engine and the rulesets
for (const auto& rule : out.rules)
{
// skip the rule if below the minimum priority
if (rule.priority > m_min_priority)
{
continue;
}
auto info = m_rule_collector.rules().at(rule.name);
if (!info)
{
// this is just defensive, it should never happen
throw falco_exception("can't find internal rule info at name: " + name);
}
// the rule is ok, we can add it to the engine and the rulesets
// note: the compiler should guarantee that the rule's condition
// is a valid sinsp filter
auto source = find_source(rule.source);
std::shared_ptr<gen_event_filter> filter(
sinsp_filter_compiler(source->filter_factory, rule.condition.get()).compile());
auto rule_id = m_rules.insert(rule, rule.name);
m_rules.at(rule_id)->id = rule_id;
source->ruleset->add(rule, filter, rule.condition);
// By default rules are enabled/disabled for the default ruleset
if(info->enabled)
{
source->ruleset->enable(rule.name, true, m_default_ruleset_id);
}
else
{
source->ruleset->disable(rule.name, true, m_default_ruleset_id);
}
}
}
if (cfg.res->successful())
@@ -469,7 +506,17 @@ std::size_t falco_engine::add_source(const std::string &source,
return m_sources.insert(src, source);
}
void falco_engine::describe_rule(std::string *rule, bool json) const
template <typename T> inline Json::Value sequence_to_json_array(const T& seq)
{
Json::Value ret = Json::arrayValue;
for (auto it = seq.begin(); it != seq.end(); it++)
{
ret.append(*it);
}
return ret;
}
void falco_engine::describe_rule(std::string *rule, const std::vector<std::shared_ptr<sinsp_plugin>>& plugins, bool json) const
{
if(!json)
{
@@ -498,10 +545,20 @@ void falco_engine::describe_rule(std::string *rule, bool json) const
return;
}
std::unique_ptr<sinsp> insp(new sinsp());
// use previously-loaded collector definitions to obtain a compiled
// output of rules, macros, and lists.
// note: we ignore the loading result (errors, warnings), as they should have
// already been checked when previously-loading the rules files. Thus, we
// assume that the definitions will give no compilation error.
rule_loader::configuration cfg("", m_sources, "");
cfg.output_extra = m_extra;
cfg.replace_output_container_info = m_replace_container_info;
rule_loader::compiler::compile_output compiled;
rule_loader::compiler().compile(cfg, m_rule_collector, compiled);
// use collected and compiled info to print a json output
Json::FastWriter writer;
std::string json_str;
if(!rule)
{
// In this case we build json information about
@@ -537,33 +594,33 @@ void falco_engine::describe_rule(std::string *rule, bool json) const
// Store information about rules
Json::Value rules_array = Json::arrayValue;
for(const auto& r : m_rules)
for(const auto& r : compiled.rules)
{
auto ri = m_rule_collector.rules().at(r.name);
auto info = m_rule_collector.rules().at(r.name);
Json::Value rule;
get_json_details(r, *ri, insp.get(), rule);
// Append to rule array
get_json_details(rule, r, *info, plugins);
rules_array.append(rule);
}
output["rules"] = rules_array;
// Store information about macros
Json::Value macros_array;
for(const auto &m : m_rule_collector.macros())
Json::Value macros_array = Json::arrayValue;
for(const auto &m : compiled.macros)
{
auto info = m_rule_collector.macros().at(m.name);
Json::Value macro;
get_json_details(m, macro);
get_json_details(macro, m, *info, plugins);
macros_array.append(macro);
}
output["macros"] = macros_array;
// Store information about lists
Json::Value lists_array = Json::arrayValue;
for(const auto &l : m_rule_collector.lists())
for(const auto &l : compiled.lists)
{
auto info = m_rule_collector.lists().at(l.name);
Json::Value list;
get_json_details(l, list);
get_json_details(list, l, *info, plugins);
lists_array.append(list);
}
output["lists"] = lists_array;
@@ -580,68 +637,73 @@ void falco_engine::describe_rule(std::string *rule, bool json) const
}
auto r = m_rules.at(ri->name);
Json::Value rule;
get_json_details(*r, *ri, insp.get(), rule);
get_json_details(rule, *r, *ri, plugins);
json_str = writer.write(rule);
}
fprintf(stdout, "%s", json_str.c_str());
}
void falco_engine::get_json_details(const falco_rule &r,
const rule_loader::rule_info &ri,
sinsp *insp,
Json::Value &rule) const
void falco_engine::get_json_details(
Json::Value &out,
const falco_rule &r,
const rule_loader::rule_info &info,
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
{
Json::Value rule_info;
// Fill general rule information
rule_info["name"] = r.name;
rule_info["condition"] = ri.cond;
rule_info["condition"] = info.cond;
rule_info["priority"] = format_priority(r.priority, false);
rule_info["output"] = r.output;
rule_info["output"] = info.output;
rule_info["description"] = r.description;
rule_info["enabled"] = ri.enabled;
rule_info["enabled"] = info.enabled;
rule_info["source"] = r.source;
Json::Value tags = Json::arrayValue;
for(const auto &t : ri.tags)
{
tags.append(t);
}
rule_info["tags"] = tags;
rule["info"] = rule_info;
rule_info["tags"] = sequence_to_json_array(info.tags);
out["info"] = rule_info;
// Parse rule condition and build the AST
// Assumption: no exception because rules have already been loaded.
auto ast = libsinsp::filter::parser(ri.cond).parse();
// Parse rule condition and build the non-compiled AST
// Assumption: no error because rules have already been loaded.
auto ast = libsinsp::filter::parser(info.cond).parse();
// get details related to the condition's filter
filter_details details;
filter_details compiled_details;
Json::Value json_details;
get_json_details(ast.get(), json_details);
rule["details"] = json_details;
for(const auto &m : m_rule_collector.macros())
{
details.known_macros.insert(m.name);
compiled_details.known_macros.insert(m.name);
}
for(const auto &l : m_rule_collector.lists())
{
details.known_lists.insert(l.name);
compiled_details.known_lists.insert(l.name);
}
filter_details_resolver().run(ast.get(), details);
filter_details_resolver().run(r.condition.get(), compiled_details);
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);
out["details"]["condition_fields"] = sequence_to_json_array(compiled_details.fields);
// Get fields from output string
auto fmt = create_formatter(r.source, r.output);
std::vector<std::string> out_fields;
fmt->get_field_names(out_fields);
Json::Value outputFields = Json::arrayValue;
for(const auto &of : out_fields)
{
outputFields.append(of);
}
rule["details"]["output_fields"] = outputFields;
out["details"]["output_fields"] = sequence_to_json_array(out_fields);
// Get fields from exceptions
Json::Value exception_fields = Json::arrayValue;
for(const auto &f : r.exception_fields)
{
exception_fields.append(f);
}
rule["details"]["exception_fields"] = exception_fields;
out["details"]["exception_fields"] = sequence_to_json_array(r.exception_fields);
// Get names and operators from exceptions
Json::Value exception_names = Json::arrayValue;
Json::Value exception_operators = Json::arrayValue;
for(const auto &e : ri.exceptions)
std::unordered_set<std::string> exception_names;
std::unordered_set<std::string> exception_operators;
for(const auto &e : info.exceptions)
{
exception_names.append(e.name);
exception_names.insert(e.name);
if(e.comps.is_list)
{
for(const auto& c : e.comps.items)
@@ -651,140 +713,236 @@ void falco_engine::get_json_details(const falco_rule &r,
// considering max two levels of lists
for(const auto& i : c.items)
{
exception_operators.append(i.item);
exception_operators.insert(i.item);
}
}
else
{
exception_operators.append(c.item);
exception_operators.insert(c.item);
}
}
}
else
{
exception_operators.append(e.comps.item);
exception_operators.insert(e.comps.item);
}
}
rule["details"]["exceptions"] = exception_names;
rule["details"]["exception_operators"] = exception_operators;
out["details"]["exception_names"] = sequence_to_json_array(exception_names);
out["details"]["exception_operators"] = sequence_to_json_array(exception_operators);
if(ri.source == falco_common::syscall_source)
{
// Store event types
Json::Value events;
get_json_evt_types(ast.get(), events);
rule["details"]["events"] = events;
}
// Store event types
Json::Value events;
get_json_evt_types(events, info.source, r.condition.get());
out["details"]["events"] = events;
// Store compiled condition and output
out["details"]["condition_compiled"] = libsinsp::filter::ast::as_string(r.condition.get());
out["details"]["output_compiled"] = r.output;
// Compute the plugins that are actually used by this rule. This is involves:
// - The rule's event source, that can be implemented by a plugin
// - The fields used in the rule's condition, output, and exceptions
// - The evt types used in the rule's condition checks, that can potentially
// match plugin-provided async events
Json::Value used_plugins;
// note: making a union of conditions's and output's fields
// note: the condition's AST accounts for all the resolved refs and exceptions
compiled_details.fields.insert(out_fields.begin(), out_fields.end());
get_json_used_plugins(used_plugins, info.source, compiled_details.evtnames, compiled_details.fields, plugins);
out["details"]["plugins"] = used_plugins;
}
void falco_engine::get_json_details(const rule_loader::macro_info& m,
Json::Value& macro) const
void falco_engine::get_json_details(
Json::Value& out,
const falco_macro& m,
const rule_loader::macro_info& info,
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
{
Json::Value macro_info;
macro_info["name"] = m.name;
macro_info["condition"] = m.cond;
macro["info"] = macro_info;
macro_info["condition"] = info.cond;
out["info"] = macro_info;
// Parse the macro condition and build the non-compiled AST
// Assumption: no exception because rules have already been loaded.
auto ast = libsinsp::filter::parser(m.cond).parse();
auto ast = libsinsp::filter::parser(info.cond).parse();
// get details related to the condition's filter
filter_details details;
filter_details compiled_details;
Json::Value json_details;
get_json_details(ast.get(), json_details);
macro["details"] = json_details;
for(const auto &m : m_rule_collector.macros())
{
details.known_macros.insert(m.name);
compiled_details.known_macros.insert(m.name);
}
for(const auto &l : m_rule_collector.lists())
{
details.known_lists.insert(l.name);
compiled_details.known_lists.insert(l.name);
}
filter_details_resolver().run(ast.get(), details);
filter_details_resolver().run(m.condition.get(), compiled_details);
out["details"]["used"] = m.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);
out["details"]["condition_fields"] = sequence_to_json_array(compiled_details.fields);
// Store event types
Json::Value events;
get_json_evt_types(ast.get(), events);
macro["details"]["events"] = events;
get_json_evt_types(events, "", m.condition.get());
out["details"]["events"] = events;
// Store compiled condition
out["details"]["condition_compiled"] = libsinsp::filter::ast::as_string(m.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
// plugins because we can't be certain about their actual usage. For example,
// if a macro uses a plugin's field, we can't be sure which plugin actually
// is used until we resolve the macro ref in a rule providing a source for
// disambiguation.
out["details"]["plugins"] = Json::arrayValue;
}
void falco_engine::get_json_details(const rule_loader::list_info& l,
Json::Value& list) const
void falco_engine::get_json_details(
Json::Value& out,
const falco_list& l,
const rule_loader::list_info& info,
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
{
Json::Value list_info;
list_info["name"] = l.name;
// note: the syntactic definitions still has the list refs unresolved
Json::Value items = Json::arrayValue;
Json::Value lists = Json::arrayValue;
for(const auto &i : l.items)
std::unordered_set<std::string> lists;
for(const auto &i : info.items)
{
if(m_rule_collector.lists().at(i) != nullptr)
// if an item is present in the syntactic def of a list, but not
// on the compiled_items of the same list, then we can assume it
// being a resolved list ref
if(std::find(l.items.begin(), l.items.end(), i) == l.items.end())
{
lists.append(i);
lists.insert(i);
continue;
}
items.append(i);
}
list_info["items"] = items;
list["info"] = list_info;
list["details"]["lists"] = lists;
out["info"] = list_info;
out["details"]["used"] = l.used;
out["details"]["lists"] = sequence_to_json_array(lists);
out["details"]["items_compiled"] = sequence_to_json_array(l.items);
out["details"]["plugins"] = Json::arrayValue; // always empty
}
void falco_engine::get_json_details(libsinsp::filter::ast::expr* ast,
Json::Value& output) const
void falco_engine::get_json_evt_types(
Json::Value& out,
const std::string& source,
libsinsp::filter::ast::expr* ast) const
{
filter_details details;
for(const auto &m : m_rule_collector.macros())
// note: this duplicates part of the logic of evttype_index_ruleset,
// not good but it's our best option for now
if (source.empty() || source == falco_common::syscall_source)
{
details.known_macros.insert(m.name);
auto evtcodes = libsinsp::filter::ast::ppm_event_codes(ast);
evtcodes.insert(ppm_event_code::PPME_ASYNCEVENT_E);
auto syscodes = libsinsp::filter::ast::ppm_sc_codes(ast);
auto syscodes_to_evt_names = libsinsp::events::sc_set_to_event_names(syscodes);
auto evtcodes_to_evt_names = libsinsp::events::event_set_to_names(evtcodes, false);
out = sequence_to_json_array(unordered_set_union(syscodes_to_evt_names, evtcodes_to_evt_names));
}
for(const auto &l : m_rule_collector.lists())
else
{
details.known_lists.insert(l.name);
out = sequence_to_json_array(libsinsp::events::event_set_to_names(
{ppm_event_code::PPME_PLUGINEVENT_E, ppm_event_code::PPME_ASYNCEVENT_E}));
}
// Resolve the AST details
filter_details_resolver resolver;
resolver.run(ast, details);
Json::Value macros = Json::arrayValue;
for(const auto &m : details.macros)
{
macros.append(m);
}
output["macros"] = macros;
Json::Value operators = Json::arrayValue;
for(const auto &o : details.operators)
{
operators.append(o);
}
output["operators"] = operators;
Json::Value condition_fields = Json::arrayValue;
for(const auto &f : details.fields)
{
condition_fields.append(f);
}
output["condition_fields"] = condition_fields;
Json::Value lists = Json::arrayValue;
for(const auto &l : details.lists)
{
lists.append(l);
}
output["lists"] = lists;
details.reset();
}
void falco_engine::get_json_evt_types(libsinsp::filter::ast::expr* ast,
Json::Value& output) const
void falco_engine::get_json_used_plugins(
Json::Value& out,
const std::string& source,
const std::unordered_set<std::string>& evtnames,
const std::unordered_set<std::string>& fields,
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
{
output = Json::arrayValue;
auto evtcodes = libsinsp::filter::ast::ppm_event_codes(ast);
auto syscodes = libsinsp::filter::ast::ppm_sc_codes(ast);
auto syscodes_to_evt_names = libsinsp::events::sc_set_to_event_names(syscodes);
auto evtcodes_to_evt_names = libsinsp::events::event_set_to_names(evtcodes, false);
for (const auto& n : unordered_set_union(syscodes_to_evt_names, evtcodes_to_evt_names))
// note: condition and output fields may have an argument, so
// we need to isolate the field names
std::unordered_set<std::string> fieldnames;
for (auto f: fields)
{
output.append(n);
auto argpos = f.find('[');
if (argpos != std::string::npos)
{
f = f.substr(0, argpos);
}
fieldnames.insert(f);
}
}
std::unordered_set<std::string> used_plugins;
for (const auto& p : plugins)
{
bool used = false;
if (p->caps() & CAP_SOURCING)
{
// The rule's source is implemented by a plugin with event
// sourcing capability.
// Note: if Falco loads two plugins implementing the same source,
// they will both be included in the list.
if (!used && p->event_source() == source)
{
used_plugins.insert(p->name());
used = true;
}
}
if (!used && p->caps() & CAP_EXTRACTION)
{
// The rule uses a field implemented by a plugin with field
// extraction capability that is compatible with the rule's source.
// Note: here we're assuming that Falco will prevent loading
// plugins implementing fields with the same name for the same
// event source (implemented in init_inspectors app action).
if (sinsp_plugin::is_source_compatible(p->extract_event_sources(), source))
{
for (const auto &f : p->fields())
{
if (!used && fieldnames.find(f.m_name) != fieldnames.end())
{
used_plugins.insert(p->name());
used = true;
break;
}
}
}
}
if (!used && p->caps() & CAP_ASYNC)
{
// The rule matches an event type implemented by a plugin with
// async events capability that is compatible with the rule's source.
// Note: if Falco loads two plugins implementing async events with
// the same name, they will both be included in the list.
if (sinsp_plugin::is_source_compatible(p->async_event_sources(), source))
{
for (const auto &n : p->async_event_names())
{
if (!used && evtnames.find(n) != evtnames.end())
{
used_plugins.insert(p->name());
used = true;
break;
}
}
}
}
}
out = sequence_to_json_array(used_plugins);
}
void falco_engine::print_stats() const
{

View File

@@ -125,7 +125,7 @@ public:
// Print details on the given rule. If rule is NULL, print
// details on all rules.
//
void describe_rule(std::string *rule, bool json) const;
void describe_rule(std::string *rule, const std::vector<std::shared_ptr<sinsp_plugin>>& plugins, bool json) const;
//
// Print statistics on how many events matched each rule.
@@ -303,18 +303,31 @@ private:
inline bool should_drop_evt() const;
// Retrieve json details from rules, macros, lists
void get_json_details(const falco_rule& r,
const rule_loader::rule_info& ri,
sinsp* insp,
Json::Value& rule) const;
void get_json_details(const rule_loader::macro_info& m,
Json::Value& macro) const;
void get_json_details(const rule_loader::list_info& l,
Json::Value& list) const;
void get_json_details(libsinsp::filter::ast::expr* ast,
Json::Value& output) const;
void get_json_evt_types(libsinsp::filter::ast::expr* ast,
Json::Value& output) const;
void get_json_details(
Json::Value& out,
const falco_rule& r,
const rule_loader::rule_info& info,
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
void get_json_details(
Json::Value& out,
const falco_macro& m,
const rule_loader::macro_info& info,
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
void get_json_details(
Json::Value& out,
const falco_list& l,
const rule_loader::list_info& info,
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
void get_json_evt_types(
Json::Value& out,
const std::string& source,
libsinsp::filter::ast::expr* ast) const;
void get_json_used_plugins(
Json::Value& out,
const std::string& source,
const std::unordered_set<std::string>& evttypes,
const std::unordered_set<std::string>& fields,
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
rule_loader::collector m_rule_collector;
indexed_vector<falco_rule> m_rules;

View File

@@ -21,6 +21,46 @@ limitations under the License.
#include <string>
#include "falco_common.h"
#include <filter/ast.h>
/*!
\brief Represents a list in the Falco Engine.
The rule ID must be unique across all the lists loaded in the engine.
*/
struct falco_list
{
falco_list(): used(false), id(0) { }
falco_list(falco_list&&) = default;
falco_list& operator = (falco_list&&) = default;
falco_list(const falco_list&) = default;
falco_list& operator = (const falco_list&) = default;
~falco_list() = default;
bool used;
std::size_t id;
std::string name;
std::vector<std::string> items;
};
/*!
\brief Represents a macro in the Falco Engine.
The rule ID must be unique across all the macros loaded in the engine.
*/
struct falco_macro
{
falco_macro(): used(false), id(0) { }
falco_macro(falco_macro&&) = default;
falco_macro& operator = (falco_macro&&) = default;
falco_macro(const falco_macro&) = default;
falco_macro& operator = (const falco_macro&) = default;
~falco_macro() = default;
bool used;
std::size_t id;
std::string name;
std::shared_ptr<libsinsp::filter::ast::expr> condition;
};
/*!
\brief Represents a rule in the Falco Engine.
The rule ID must be unique across all the rules loaded in the engine.
@@ -32,6 +72,7 @@ struct falco_rule
falco_rule& operator = (falco_rule&&) = default;
falco_rule(const falco_rule&) = default;
falco_rule& operator = (const falco_rule&) = default;
~falco_rule() = default;
std::size_t id;
std::string source;
@@ -41,4 +82,5 @@ struct falco_rule
std::set<std::string> tags;
std::set<std::string> exception_fields;
falco_common::priority_type priority;
std::shared_ptr<libsinsp::filter::ast::expr> condition;
};

View File

@@ -19,12 +19,23 @@ limitations under the License.
using namespace libsinsp::filter;
std::string get_field_name(const std::string& name, const std::string& arg)
{
std::string fld = name;
if (!arg.empty())
{
fld += "[" + arg + "]";
}
return fld;
}
void filter_details::reset()
{
fields.clear();
macros.clear();
operators.clear();
lists.clear();
evtnames.clear();
}
void filter_details_resolver::run(ast::expr* filter, filter_details& details)
@@ -35,6 +46,7 @@ void filter_details_resolver::run(ast::expr* filter, filter_details& details)
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;
@@ -45,6 +57,7 @@ void filter_details_resolver::visitor::visit(ast::and_expr* e)
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;
@@ -70,35 +83,50 @@ void filter_details_resolver::visitor::visit(ast::list_expr* e)
}
}
}
if (m_expect_evtname)
{
for(const auto& item : e->values)
{
if(m_details.known_lists.find(item) == m_details.known_lists.end())
{
m_details.evtnames.insert(item);
}
}
}
}
void filter_details_resolver::visitor::visit(ast::binary_check_expr* e)
{
m_expect_macro = false;
m_details.fields.insert(e->field);
m_details.fields.insert(get_field_name(e->field, e->arg));
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 = false;
m_expect_list = false;
}
void filter_details_resolver::visitor::visit(ast::unary_check_expr* e)
{
m_expect_macro = false;
m_details.fields.insert(e->field);
m_details.fields.insert(get_field_name(e->field, e->arg));
m_details.operators.insert(e->op);
}
void filter_details_resolver::visitor::visit(ast::value_expr* e)
{
if(m_expect_macro)
if (m_expect_macro)
{
auto it = m_details.known_macros.find(e->value);
if(it == m_details.known_macros.end())
if(m_details.known_macros.find(e->value) != m_details.known_macros.end())
{
return;
m_details.macros.insert(e->value);
}
m_details.macros.insert(e->value);
// todo(jasondellaluce): should we throw an error if we
// encounter an unknown macro?
}
else if (m_expect_evtname)
{
m_details.evtnames.insert(e->value);
}
}

View File

@@ -33,6 +33,7 @@ struct filter_details
std::unordered_set<std::string> macros;
std::unordered_set<std::string> operators;
std::unordered_set<std::string> lists;
std::unordered_set<std::string> evtnames;
void reset();
};
@@ -59,7 +60,8 @@ private:
visitor(filter_details& details) :
m_details(details),
m_expect_list(false),
m_expect_macro(false) {}
m_expect_macro(false),
m_expect_evtname(false) {}
visitor(visitor&&) = default;
visitor& operator = (visitor&&) = default;
visitor(const visitor&) = delete;
@@ -76,5 +78,6 @@ private:
filter_details& m_details;
bool m_expect_list;
bool m_expect_macro;
bool m_expect_evtname;
};
};

View File

@@ -532,12 +532,12 @@ rule_loader::plugin_version_info::plugin_version_info(context &ctx)
}
rule_loader::list_info::list_info(context &ctx)
: ctx(ctx), used(false), index(0), visibility(0)
: ctx(ctx), index(0), visibility(0)
{
}
rule_loader::macro_info::macro_info(context &ctx)
: ctx(ctx), cond_ctx(ctx), used(false), index(0), visibility(0)
: ctx(ctx), cond_ctx(ctx), index(0), visibility(0)
{
}

View File

@@ -273,8 +273,7 @@ namespace rule_loader
const indexed_vector<falco_source>& srcs,
const std::string& name)
: content(cont), sources(srcs), name(name),
default_ruleset_id(0), replace_output_container_info(false),
min_priority(falco_common::PRIORITY_DEBUG)
output_extra(), replace_output_container_info(false)
{
res.reset(new result(name));
}
@@ -283,14 +282,15 @@ namespace rule_loader
configuration(const configuration&) = delete;
configuration& operator = (const configuration&) = delete;
// inputs
const std::string& content;
const indexed_vector<falco_source>& sources;
std::string name;
std::unique_ptr<result> res;
std::string output_extra;
uint16_t default_ruleset_id;
bool replace_output_container_info;
falco_common::priority_type min_priority;
// outputs
std::unique_ptr<result> res;
};
/*!
@@ -359,7 +359,6 @@ namespace rule_loader
list_info& operator = (const list_info&) = default;
context ctx;
bool used;
size_t index;
size_t visibility;
std::string name;
@@ -380,12 +379,10 @@ namespace rule_loader
context ctx;
context cond_ctx;
bool used;
size_t index;
size_t visibility;
std::string name;
std::string cond;
std::shared_ptr<libsinsp::filter::ast::expr> cond_ast;
};
/*!

View File

@@ -160,8 +160,30 @@ static void build_rule_exception_infos(
}
}
static inline rule_loader::list_info* list_info_from_name(
const rule_loader::collector& c, const std::string& name)
{
auto ret = c.lists().at(name);
if (!ret)
{
throw falco_exception("can't find internal list info at name: " + name);
}
return ret;
}
static inline rule_loader::macro_info* macro_info_from_name(
const rule_loader::collector& c, const std::string& name)
{
auto ret = c.macros().at(name);
if (!ret)
{
throw falco_exception("can't find internal macro info at name: " + name);
}
return ret;
}
// todo(jasondellaluce): this breaks string escaping in lists
static bool resolve_list(std::string& cnd, const rule_loader::list_info& list)
static bool resolve_list(std::string& cnd, const falco_list& list)
{
static std::string blanks = " \t\n\r";
static std::string delims = blanks + "(),=";
@@ -232,18 +254,20 @@ static bool resolve_list(std::string& cnd, const rule_loader::list_info& list)
}
static void resolve_macros(
indexed_vector<rule_loader::macro_info>& macros,
const indexed_vector<rule_loader::macro_info>& infos,
indexed_vector<falco_macro>& macros,
std::shared_ptr<ast::expr>& ast,
const std::string& condition,
uint32_t visibility,
const rule_loader::context &ctx)
{
filter_macro_resolver macro_resolver;
for (auto &m : macros)
for (auto &m : infos)
{
if (m.index < visibility)
{
macro_resolver.set_macro(m.name, m.cond_ast);
auto macro = macros.at(m.name);
macro_resolver.set_macro(m.name, macro->condition);
}
}
macro_resolver.run(ast);
@@ -272,7 +296,7 @@ static void resolve_macros(
// note: there is no visibility order between filter conditions and lists
static std::shared_ptr<ast::expr> parse_condition(
std::string condition,
indexed_vector<rule_loader::list_info>& lists,
indexed_vector<falco_list>& lists,
const rule_loader::context &ctx)
{
for (auto &l : lists)
@@ -319,13 +343,14 @@ static void apply_output_substitutions(
void rule_loader::compiler::compile_list_infos(
configuration& cfg,
const collector& col,
indexed_vector<list_info>& out) const
indexed_vector<falco_list>& out) const
{
std::string tmp;
std::vector<std::string> used;
for (auto &list : col.lists())
{
list_info v = list;
falco_list v;
v.name = list.name;
v.items.clear();
for (auto &item : list.items)
{
@@ -347,7 +372,8 @@ void rule_loader::compiler::compile_list_infos(
}
}
v.used = false;
out.insert(v, v.name);
auto list_id = out.insert(v, v.name);
out.at(list_id)->id = list_id;
}
for (auto &v : used)
{
@@ -359,20 +385,23 @@ void rule_loader::compiler::compile_list_infos(
void rule_loader::compiler::compile_macros_infos(
configuration& cfg,
const collector& col,
indexed_vector<list_info>& lists,
indexed_vector<macro_info>& out) const
indexed_vector<falco_list>& lists,
indexed_vector<falco_macro>& out) const
{
for (auto &m : col.macros())
{
macro_info entry = m;
entry.cond_ast = parse_condition(m.cond, lists, m.cond_ctx);
falco_macro entry;
entry.name = m.name;
entry.condition = parse_condition(m.cond, lists, m.cond_ctx);
entry.used = false;
out.insert(entry, m.name);
auto macro_id = out.insert(entry, m.name);
out.at(macro_id)->id = macro_id;
}
for (auto &m : out)
{
resolve_macros(out, m.cond_ast, m.cond, m.visibility, m.ctx);
auto info = macro_info_from_name(col, m.name);
resolve_macros(col.macros(), out, m.condition, info->cond, info->visibility, info->ctx);
}
}
@@ -386,8 +415,8 @@ static bool err_is_unknown_type_or_field(const std::string& err)
void rule_loader::compiler::compile_rule_infos(
configuration& cfg,
const collector& col,
indexed_vector<list_info>& lists,
indexed_vector<macro_info>& macros,
indexed_vector<falco_list>& lists,
indexed_vector<falco_macro>& macros,
indexed_vector<falco_rule>& out) const
{
std::string err, condition;
@@ -401,12 +430,6 @@ void rule_loader::compiler::compile_rule_infos(
continue;
}
// skip the rule if below the minimum priority
if (r.priority > cfg.min_priority)
{
continue;
}
// note: this should not be nullptr if the source is not unknown
auto source = cfg.sources.at(r.source);
THROW(!source,
@@ -423,12 +446,12 @@ void rule_loader::compiler::compile_rule_infos(
build_rule_exception_infos(
r.exceptions, rule.exception_fields, condition);
}
auto ast = parse_condition(condition, lists, r.cond_ctx);
resolve_macros(macros, ast, condition, MAX_VISIBILITY, r.ctx);
rule.condition = parse_condition(condition, lists, r.cond_ctx);
resolve_macros(col.macros(), macros, rule.condition, condition, MAX_VISIBILITY, r.ctx);
// check for warnings in the filtering condition
warn_codes.clear();
if (warn_resolver.run(ast.get(), warn_codes))
if (warn_resolver.run(rule.condition.get(), warn_codes))
{
for (auto &w : warn_codes)
{
@@ -443,8 +466,11 @@ void rule_loader::compiler::compile_rule_infos(
apply_output_substitutions(cfg, rule.output);
}
// validate the rule's output
if(!is_format_valid(*cfg.sources.at(r.source), rule.output, err))
{
// skip the rule silently if skip_if_unknown_filter is true and
// we encountered some specific kind of errors
if (err_is_unknown_type_or_field(err) && r.skip_if_unknown_filter)
{
cfg.res->add_warning(
@@ -459,30 +485,18 @@ void rule_loader::compiler::compile_rule_infos(
r.output_ctx);
}
// construct rule definition and compile it to a filter
rule.name = r.name;
rule.source = r.source;
rule.description = r.desc;
rule.priority = r.priority;
rule.tags = r.tags;
auto rule_id = out.insert(rule, rule.name);
out.at(rule_id)->id = rule_id;
// This also compiles the filter, and might throw a
// falco_exception with details on the compilation
// failure.
sinsp_filter_compiler compiler(cfg.sources.at(r.source)->filter_factory, ast.get());
try {
std::shared_ptr<gen_event_filter> filter(compiler.compile());
source->ruleset->add(*out.at(rule_id), filter, ast);
// validate the rule's condition: we compile it into a sinsp filter
// on-the-fly and we throw an exception with details on failure
sinsp_filter_compiler compiler(cfg.sources.at(r.source)->filter_factory, rule.condition.get());
try
{
compiler.compile();
}
catch (const sinsp_exception& e)
{
// Allow errors containing "nonexistent field" if
// skip_if_unknown_filter is true
// skip the rule silently if skip_if_unknown_filter is true and
// we encountered some specific kind of errors
std::string err = e.what();
if (err_is_unknown_type_or_field(err) && r.skip_if_unknown_filter)
{
cfg.res->add_warning(
@@ -491,7 +505,6 @@ void rule_loader::compiler::compile_rule_infos(
r.cond_ctx);
continue;
}
rule_loader::context ctx(compiler.get_pos(), condition, r.cond_ctx);
throw rule_loader::rule_load_exception(
falco::load_result::load_result::LOAD_ERR_COMPILE_CONDITION,
@@ -499,20 +512,10 @@ void rule_loader::compiler::compile_rule_infos(
ctx);
}
// By default rules are enabled/disabled for the default ruleset
if(r.enabled)
{
source->ruleset->enable(rule.name, true, cfg.default_ruleset_id);
}
else
{
source->ruleset->disable(rule.name, true, cfg.default_ruleset_id);
}
// populate set of event types and emit an special warning
if(rule.source == falco_common::syscall_source)
if(r.source == falco_common::syscall_source)
{
auto evttypes = libsinsp::filter::ast::ppm_event_codes(ast.get());
auto evttypes = libsinsp::filter::ast::ppm_event_codes(rule.condition.get());
if ((evttypes.empty() || evttypes.size() > 100) && r.warn_evttypes)
{
cfg.res->add_warning(
@@ -521,23 +524,29 @@ void rule_loader::compiler::compile_rule_infos(
r.ctx);
}
}
// finalize the rule definition and add it to output
rule.name = r.name;
rule.source = r.source;
rule.description = r.desc;
rule.priority = r.priority;
rule.tags = r.tags;
auto rule_id = out.insert(rule, rule.name);
out.at(rule_id)->id = rule_id;
}
}
void rule_loader::compiler::compile(
configuration& cfg,
const collector& col,
indexed_vector<falco_rule>& out) const
compile_output& out) const
{
indexed_vector<list_info> lists;
indexed_vector<macro_info> macros;
// expand all lists, macros, and rules
try
{
compile_list_infos(cfg, col, lists);
compile_macros_infos(cfg, col, lists, macros);
compile_rule_infos(cfg, col, lists, macros, out);
compile_list_infos(cfg, col, out.lists);
compile_macros_infos(cfg, col, out.lists, out.macros);
compile_rule_infos(cfg, col, out.lists, out.macros, out.rules);
}
catch(rule_load_exception &e)
{
@@ -546,24 +555,24 @@ void rule_loader::compiler::compile(
}
// print info on any dangling lists or macros that were not used anywhere
for (auto &m : macros)
for (auto &m : out.macros)
{
if (!m.used)
{
cfg.res->add_warning(
falco::load_result::load_result::LOAD_UNUSED_MACRO,
"Macro not referred to by any other rule/macro",
m.ctx);
macro_info_from_name(col, m.name)->ctx);
}
}
for (auto &l : lists)
for (auto &l : out.lists)
{
if (!l.used)
{
cfg.res->add_warning(
falco::load_result::LOAD_UNUSED_LIST,
"List not referred to by any other rule/macro",
l.ctx);
list_info_from_name(col, l.name)->ctx);
}
}
}

View File

@@ -31,6 +31,23 @@ namespace rule_loader
class compiler
{
public:
/*!
\brief The output of a compilation.
*/
struct compile_output
{
compile_output() = default;
virtual ~compile_output() = default;
compile_output(compile_output&&) = default;
compile_output& operator = (compile_output&&) = default;
compile_output(const compile_output&) = default;
compile_output& operator = (const compile_output&) = default;
indexed_vector<falco_list> lists;
indexed_vector<falco_macro> macros;
indexed_vector<falco_rule> rules;
};
compiler() = default;
virtual ~compiler() = default;
compiler(compiler&&) = default;
@@ -44,25 +61,25 @@ public:
virtual void compile(
configuration& cfg,
const collector& col,
indexed_vector<falco_rule>& out) const;
compile_output& out) const;
private:
void compile_list_infos(
configuration& cfg,
const collector& col,
indexed_vector<list_info>& out) const;
indexed_vector<falco_list>& out) const;
void compile_macros_infos(
configuration& cfg,
const collector& col,
indexed_vector<list_info>& lists,
indexed_vector<macro_info>& out) const;
indexed_vector<falco_list>& lists,
indexed_vector<falco_macro>& out) const;
void compile_rule_infos(
configuration& cfg,
const collector& col,
indexed_vector<list_info>& lists,
indexed_vector<macro_info>& macros,
indexed_vector<falco_list>& lists,
indexed_vector<falco_macro>& macros,
indexed_vector<falco_rule>& out) const;
};

View File

@@ -86,15 +86,6 @@ falco::app::run_result falco::app::actions::open_live_inspector(
falco_logger::log(LOG_INFO, "Opening '" + source + "' source with no driver\n");
inspector->open_nodriver();
}
else if (s.options.userspace) /* udig engine. */
{
// open_udig() is the underlying method used in the capture code to parse userspace events from the kernel.
//
// Falco uses a ptrace(2) based userspace implementation.
// Regardless of the implementation, the underlying method remains the same.
falco_logger::log(LOG_WARNING, "The udig engine is deprecated and will be removed in Falco 0.37. Opening '" + source + "' source with udig\n");
inspector->open_udig();
}
else if(s.is_gvisor_enabled()) /* gvisor engine. */
{
falco_logger::log(LOG_INFO, "Opening '" + source + "' source with gVisor. Configuration path: " + s.options.gvisor_config);

View File

@@ -157,13 +157,15 @@ falco::app::run_result falco::app::actions::load_rules_files(falco::app::state&
if (s.options.describe_all_rules)
{
s.engine->describe_rule(NULL, s.config->m_json_output);
const auto& plugins = s.offline_inspector->get_plugin_manager()->plugins();
s.engine->describe_rule(NULL, plugins, s.config->m_json_output);
return run_result::exit();
}
if (!s.options.describe_rule.empty())
{
s.engine->describe_rule(&(s.options.describe_rule), s.config->m_json_output);
const auto& plugins = s.offline_inspector->get_plugin_manager()->plugins();
s.engine->describe_rule(&(s.options.describe_rule), plugins, s.config->m_json_output);
return run_result::exit();
}

View File

@@ -37,7 +37,6 @@ options::options()
list_plugins(false),
list_syscall_events(false),
markdown(false),
userspace(false),
modern_bpf(false),
dry_run(false),
nodriver(false)
@@ -148,14 +147,13 @@ bool options::parse(int argc, char **argv, std::string &errstr)
int open_modes = 0;
open_modes += !trace_filename.empty();
open_modes += userspace;
open_modes += !gvisor_config.empty();
open_modes += modern_bpf;
open_modes += getenv("FALCO_BPF_PROBE") != NULL;
open_modes += nodriver;
if (open_modes > 1)
{
errstr = std::string("You can not specify more than one of -e, -u (--userspace), -g (--gvisor-config), --modern-bpf, --nodriver, and the FALCO_BPF_PROBE env var");
errstr = std::string("You can not specify more than one of -e, -g (--gvisor-config), --modern-bpf, --nodriver, and the FALCO_BPF_PROBE env var");
return false;
}
@@ -220,9 +218,6 @@ void options::define(cxxopts::Options& opts)
("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>")
("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"))
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
("u,userspace", "[DEPRECATED: this option will be removed in Falco 0.37] Use a userspace driver to collect 'syscall' events. To be used in conjunction with the ptrace(2) based driver (pdig).", cxxopts::value(userspace)->default_value("false"))
#endif
("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"))
("version", "Print version information and exit.", cxxopts::value(print_version_info)->default_value("false"))

View File

@@ -75,7 +75,6 @@ public:
std::set<std::string> disabled_rule_tags;
std::set<std::string> enabled_rule_tags;
bool unbuffered_outputs;
bool userspace;
std::vector<std::string> validate_rules_filenames;
bool verbose;
bool print_version_info;

View File

@@ -229,7 +229,7 @@ void stats_writer::collector::get_metrics_output_fields_wrapper(
{
static const char* all_driver_engines[] = {
BPF_ENGINE, KMOD_ENGINE, MODERN_BPF_ENGINE,
SOURCE_PLUGIN_ENGINE, NODRIVER_ENGINE, UDIG_ENGINE, GVISOR_ENGINE };
SOURCE_PLUGIN_ENGINE, NODRIVER_ENGINE, GVISOR_ENGINE };
const scap_agent_info* agent_info = inspector->get_agent_info();
const scap_machine_info* machine_info = inspector->get_machine_info();