mirror of
https://github.com/falcosecurity/falco.git
synced 2025-09-08 10:09:40 +00:00
Make compile_condition() a protected method for use in subclasses
Move the part of compile_rule_infos that actually compiled a condition string into a sinsp_filter into a standalone method compile_condition(). That way it can be used by classes that derive from rule_loader::compiler() and want to compile condition strings. This implementation also saves the compiled filter as a part of the falco_rule object so it does not need to be compiled again wihin the falco engine after rules loading. Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
This commit is contained in:
@@ -405,17 +405,72 @@ static bool err_is_unknown_type_or_field(const std::string& err)
|
|||||||
|| err.find("unknown event type") != std::string::npos;
|
|| err.find("unknown event type") != std::string::npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rule_loader::compiler::compile_rule_infos(
|
bool rule_loader::compiler::compile_condition(
|
||||||
configuration& cfg,
|
configuration& cfg,
|
||||||
const collector& col,
|
indexed_vector<falco_list>& lists,
|
||||||
indexed_vector<falco_list>& lists,
|
const indexed_vector<rule_loader::macro_info>& macros,
|
||||||
indexed_vector<falco_macro>& macros,
|
const std::string& condition,
|
||||||
indexed_vector<falco_rule>& out) const
|
std::shared_ptr<gen_event_filter_factory> filter_factory,
|
||||||
|
rule_loader::context cond_ctx,
|
||||||
|
rule_loader::context parent_ctx,
|
||||||
|
bool allow_unknown_fields,
|
||||||
|
indexed_vector<falco_macro>& macros_out,
|
||||||
|
std::shared_ptr<libsinsp::filter::ast::expr>& ast_out,
|
||||||
|
std::shared_ptr<gen_event_filter>& filter_out) const
|
||||||
{
|
{
|
||||||
std::string err, condition;
|
|
||||||
std::set<falco::load_result::load_result::warning_code> warn_codes;
|
std::set<falco::load_result::load_result::warning_code> warn_codes;
|
||||||
filter_warning_resolver warn_resolver;
|
filter_warning_resolver warn_resolver;
|
||||||
for (const auto &r : col.rules())
|
ast_out = parse_condition(condition, lists, cond_ctx);
|
||||||
|
resolve_macros(macros, macros_out, ast_out, condition, MAX_VISIBILITY, parent_ctx);
|
||||||
|
|
||||||
|
// check for warnings in the filtering condition
|
||||||
|
if(warn_resolver.run(ast_out.get(), warn_codes))
|
||||||
|
{
|
||||||
|
for(const auto& w : warn_codes)
|
||||||
|
{
|
||||||
|
cfg.res->add_warning(w, "", parent_ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate the rule's condition: we compile it into a sinsp filter
|
||||||
|
// on-the-fly and we throw an exception with details on failure
|
||||||
|
sinsp_filter_compiler compiler(filter_factory, ast_out.get());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
filter_out.reset(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();
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rule_loader::compiler::compile_rule_infos(
|
||||||
|
configuration& cfg,
|
||||||
|
const collector& col,
|
||||||
|
indexed_vector<falco_list>& lists,
|
||||||
|
indexed_vector<falco_macro>& macros,
|
||||||
|
indexed_vector<falco_rule>& out) const
|
||||||
|
{
|
||||||
|
std::string err, condition;
|
||||||
|
for(const auto& r : col.rules())
|
||||||
{
|
{
|
||||||
// skip the rule if it has an unknown source
|
// skip the rule if it has an unknown source
|
||||||
if (r.unknown_source)
|
if (r.unknown_source)
|
||||||
@@ -439,18 +494,6 @@ void rule_loader::compiler::compile_rule_infos(
|
|||||||
build_rule_exception_infos(
|
build_rule_exception_infos(
|
||||||
r.exceptions, rule.exception_fields, condition);
|
r.exceptions, rule.exception_fields, condition);
|
||||||
}
|
}
|
||||||
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(rule.condition.get(), warn_codes))
|
|
||||||
{
|
|
||||||
for (const auto &w : warn_codes)
|
|
||||||
{
|
|
||||||
cfg.res->add_warning(w, "", r.ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// build rule output message
|
// build rule output message
|
||||||
rule.output = r.output;
|
rule.output = r.output;
|
||||||
@@ -478,31 +521,19 @@ void rule_loader::compiler::compile_rule_infos(
|
|||||||
r.output_ctx);
|
r.output_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate the rule's condition: we compile it into a sinsp filter
|
if (!compile_condition(cfg,
|
||||||
// on-the-fly and we throw an exception with details on failure
|
lists,
|
||||||
sinsp_filter_compiler compiler(cfg.sources.at(r.source)->filter_factory, rule.condition.get());
|
col.macros(),
|
||||||
try
|
condition,
|
||||||
|
cfg.sources.at(r.source)->filter_factory,
|
||||||
|
r.cond_ctx,
|
||||||
|
r.ctx,
|
||||||
|
r.skip_if_unknown_filter,
|
||||||
|
macros,
|
||||||
|
rule.condition,
|
||||||
|
rule.filter))
|
||||||
{
|
{
|
||||||
std::shared_ptr<sinsp_filter> sfPtr(compiler.compile());
|
continue;
|
||||||
}
|
|
||||||
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();
|
|
||||||
if (err_is_unknown_type_or_field(err) && r.skip_if_unknown_filter)
|
|
||||||
{
|
|
||||||
cfg.res->add_warning(
|
|
||||||
falco::load_result::load_result::LOAD_UNKNOWN_FILTER,
|
|
||||||
err,
|
|
||||||
r.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,
|
|
||||||
err,
|
|
||||||
ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// populate set of event types and emit an special warning
|
// populate set of event types and emit an special warning
|
||||||
|
@@ -50,6 +50,27 @@ public:
|
|||||||
configuration& cfg,
|
configuration& cfg,
|
||||||
const collector& col,
|
const collector& col,
|
||||||
compile_output& out) const;
|
compile_output& out) const;
|
||||||
|
protected:
|
||||||
|
/*!
|
||||||
|
\brief Compile a single condition expression,
|
||||||
|
including expanding macro and list references.
|
||||||
|
|
||||||
|
returns true if the condition could be compiled, and sets
|
||||||
|
ast_out/filter_out with the compiled filter + ast. Returns false if
|
||||||
|
the condition could not be compiled and should be skipped.
|
||||||
|
*/
|
||||||
|
bool compile_condition(
|
||||||
|
configuration& cfg,
|
||||||
|
indexed_vector<falco_list>& lists,
|
||||||
|
const indexed_vector<rule_loader::macro_info>& macros,
|
||||||
|
const std::string& condition,
|
||||||
|
std::shared_ptr<gen_event_filter_factory> filter_factory,
|
||||||
|
rule_loader::context cond_ctx,
|
||||||
|
rule_loader::context parent_ctx,
|
||||||
|
bool allow_unknown_fields,
|
||||||
|
indexed_vector<falco_macro>& macros_out,
|
||||||
|
std::shared_ptr<libsinsp::filter::ast::expr>& ast_out,
|
||||||
|
std::shared_ptr<gen_event_filter>& filter_out) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void compile_list_infos(
|
void compile_list_infos(
|
||||||
|
Reference in New Issue
Block a user