Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rules result add compile condition context #2216

Merged
merged 2 commits into from
Dec 1, 2022

Conversation

mstemm
Copy link
Contributor

@mstemm mstemm commented Sep 20, 2022

What type of PR is this?

Uncomment one (or more) /kind <> lines:

/kind bug

/kind cleanup

/kind design

/kind documentation

/kind failing-test

/kind feature

/kind release

If contributing rules or changes to rules, please make sure to also uncomment one of the following line:

/kind rule-update

/kind rule-create

Any specific area of the project related to this PR?

Uncomment one (or more) /area <> lines:

/area build

/area engine

/area rules

/area tests

/area proposals

/area CI

What this PR does / why we need it:

Which issue(s) this PR fixes:

Fixes #

Special notes for your reviewer:

Does this PR introduce a user-facing change?:

new(engine): Also include exact locations for rule condition compile errors (missing macros, etc).

@mstemm
Copy link
Contributor Author

mstemm commented Sep 22, 2022

I'm going to wait for the changes in #2206 as that allows referring to things like rule_load_exception independently of the rule loader. Given that filter_rulesets often compile an ast to a filter, we really should document what exceptions filter rulesets can throw so falco knows which ones to catch and convert to rule loading errors.

@leogr
Copy link
Member

leogr commented Sep 27, 2022

/milestone 0.34.0

@poiana poiana added this to the 0.34.0 milestone Sep 27, 2022
@mstemm mstemm force-pushed the rules-result-add-compile-condition-context branch 2 times, most recently from b5ac7da to f307364 Compare September 29, 2022 20:37
@mstemm
Copy link
Contributor Author

mstemm commented Oct 10, 2022

This is ready for review now.

userspace/engine/filter_macro_resolver.cpp Outdated Show resolved Hide resolved
tests/engine/test_filter_macro_resolver.cpp Show resolved Hide resolved
@@ -82,8 +87,9 @@ class filter_macro_resolver
struct visitor : public libsinsp::filter::ast::expr_visitor
{
std::unique_ptr<libsinsp::filter::ast::expr> m_node_substitute;
std::unordered_set<std::string>* m_unknown_macros;
std::unordered_set<std::string>* m_resolved_macros;
macro_info_map* m_unknown_macros;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above, these can become references by having an explicit visitor(...) constructor. I think this would be safer and clearer now that we also deal with maps (it would have been a good improvement anyway).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, changed them to references.

try {
source->ruleset->add(*out.at(rule_id), ast);
shared_ptr<gen_event_filter> filter(compiler.compile());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of this, I don't like the fact that we bundle a sinsp_filter_compiler inside the rule_loader::compiler class. In the future, we potentially may want to have multiple implementation of filters, and in general I don't think this should be part of this class' responsibilities.

Given this, I propose two options. I'm leaning towards option 1 because it makes these changes less impactful and better modularizes each class' responsibilities.

Option 1
The only reason why we are passing a gen_event_filter, and compiling the filter here instead then in filter_ruleset, is to have access to the compiler's filter position in case of error. As such, we could simply create a new exception type (e.g. falco_rule_compile_exception) child of falco_exception. This new exception type would carry the AST position information in case of error. Then, make filter_ruleset::add throw both falco_rule_compile_exception and falco_exception by documentation, and catch those two errors here.

So here we would do a catch chain such as: if we have a falco_rule_compile_exception, then throw an error with a filter-condition-specific context with a specific position, otherwise if we have a generic falco_exception just throw an error with r.cond_ctx.

In this way, we would have all the information we need for information reporting here were we need it, by also making all these changes less impactful and by not changing the filter_ruleset interface (if not for the "throws" guarantees). Also, the rule_loader::compile class will not have more responsibilities than we should (e.g. compiling a filter), and we have a clear separation between the rule condition AST and its black-box compiled filter (of which each filter_ruleset implementation is solely responsible).

Option 2
Let's proceed with these changes, but in future PRs (reminder for ourselves):

  • Make gen_event_filter become a real interface, so that there can actually be multiple implementations of it
  • Add an intermediary class between rule_loader::compiler and filter_ruleset that takes care of 1) compiling the filter and report condition errors, 2) add it to the ruleset and to the state's rule list, and 3) enable/disable it on the ruleset. All these are becoming too many responsibilities for rule_loader::compiler, which is only supposed to resolve all the engine definitions in a list of rules.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think of each step of rule loading, compilation, and filter management being separate responsibilities, so I'm not sure moving the compilation into the filter_ruleset is a good idea either. To me the filter_ruleset is just about managing collections of filters, where it can optimize/prefilter/etc based on stuff like event type, as the current one does.

I guess I would think of compilation as something that could be plugged into the rule loader and accessed via event source, as we currently do with filter_factory/formatter_factory. In a fully aligned design, the engine would just be configured with compilers, and a compiler could in turn be configured with fields, so a filter factory would be responsible for compilation too.

So I guess I'd lean towards option 2 with some tbd on the actual interfaces.

@jasondellaluce
Copy link
Contributor

Sorry for being late, this was pushed over a lot due to the Falco release and KubeCon's attendance from most maintainers. Left you my comments.

Now that ASTs have parse positions and the compiler will return the
position of the last error, use that in falco rules to return errors
within condition strings instead of reporting the position as the
beginning of the condition.

This led to a change in the filter_ruleset interface--now, an ast is
compiled to a filter before being passed to the filter_ruleset
object. That avoids polluting the interface with a lot of details
about rule_loader contexts, errors, etc. The ast is still provided in
case the filter_ruleset wants to do indexing/analysis of the filter.

Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
@mstemm mstemm force-pushed the rules-result-add-compile-condition-context branch from f307364 to 0d15c9b Compare November 10, 2022 20:39
Now that ASTs contain parse positions, use them when reporting errors
about unknown macros.

When doing the first pass to find all macro references, save macros as
a map<macro name,parse position> instead of a set<macro name>. While
making that change, change the visitor struct to use references
instead of pointers.

In the second pass, when reporting any unresolved macro references,
also report the parse position.

The unit tests also check that the positions of macros are properly
returned in the resolved/unresolved maps.

Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
@mstemm mstemm force-pushed the rules-result-add-compile-condition-context branch from 0d15c9b to 5ec7953 Compare November 10, 2022 22:02
Copy link
Contributor

@jasondellaluce jasondellaluce left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, let's go with this for now, we may find a more elegant solution for filter compilation in the future.

@@ -20,9 +20,27 @@ limitations under the License.
using namespace std;
using namespace libsinsp::filter::ast;

static pos_info create_pos(uint32_t idx, uint32_t line, uint32_t col)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is good, but let's backport it to libs as a constructor/equality operator next!

@poiana
Copy link
Contributor

poiana commented Dec 1, 2022

LGTM label has been added.

Git tree hash: 20fefb817c596bd1ad353f0dba4e33802942bff2

Copy link
Contributor

@FedeDP FedeDP left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/approve

@poiana
Copy link
Contributor

poiana commented Dec 1, 2022

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: FedeDP, jasondellaluce, mstemm

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:
  • OWNERS [FedeDP,jasondellaluce,mstemm]

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@poiana poiana merged commit 910b8ff into master Dec 1, 2022
@poiana poiana deleted the rules-result-add-compile-condition-context branch December 1, 2022 16:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

5 participants