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

refactor(userspace): change falco engine design to properly support multiple sources #2017

Merged
merged 10 commits into from
May 25, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
refactor(userspace/engine): introduce interface for rulesets and thei…
…r factory

This interface will allow us to use different ruleset implementations inside the same engine.
The goal is to define API boundaries that will allow swapping the current evttype-index
ruleset implementation more easily. Key benefits include: smaller component with less responsibilities,
easier substituibility, more testable design, opportunity to adopt different index strategies
depending on the ruleset implementation.

Signed-off-by: Jason Dellaluce <[email protected]>
jasondellaluce committed May 24, 2022
commit 72ee106c61bbffc2877adadac94da3fc24087f95
217 changes: 116 additions & 101 deletions userspace/engine/ruleset.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (C) 2019 The Falco Authors.
Copyright (C) 2022 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.
@@ -16,108 +16,123 @@ limitations under the License.

#pragma once

#include <string>
#include <set>
#include <vector>
#include <list>
#include <map>
#include <filter.h>
#include <event.h>
#include <gen_filter.h>
#include <filter/ast.h>
#include "falco_rule.h"

#include "sinsp.h"
#include "filter.h"
#include "event.h"

#include "gen_filter.h"

class falco_ruleset
/*!
\brief Represents a manager for rulesets.A ruleset represents a set of
enabled rules that is able to process events and find potential rule
matches. By convention, the ruleset with id = 0 is the default one.
*/
class filter_ruleset
leogr marked this conversation as resolved.
Show resolved Hide resolved
{
public:
falco_ruleset();
virtual ~falco_ruleset();

void add(string &source,
std::string &name,
std::set<std::string> &tags,
set<uint16_t> &evttypes,
std::shared_ptr<gen_event_filter> filter);

// rulesets are arbitrary numbers and should be managed by the caller.
// Note that rulesets are used to index into a std::vector so
// specifying unnecessarily large rulesets will result in
// unnecessarily large vectors.

// Find those rules matching the provided substring and set
// their enabled status to enabled. If match_exact is 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.
void enable(const std::string &substring, bool match_exact, bool enabled, uint16_t ruleset = 0);

// Find those rules that have a tag in the set of tags and set
// their enabled status to enabled. Note that the enabled
// status is on the rules, and not the tags--if a rule R has
// tags (a, b), and you call enable_tags([a], true) and then
// enable_tags([b], false), R will be disabled despite the
// fact it has tag a and was enabled by the first call to
// enable_tags.
void enable_tags(const std::set<std::string> &tags, bool enabled, uint16_t ruleset = 0);


// Return the number of falco rules enabled for the provided ruleset
uint64_t num_rules_for_ruleset(uint16_t ruleset = 0);

// Match all filters against the provided event.
bool run(gen_event *evt, uint16_t ruleset = 0);

// Populate the provided set of event types used by this ruleset.
void evttypes_for_ruleset(std::set<uint16_t> &evttypes, uint16_t ruleset);

private:

class filter_wrapper {
public:
std::string source;
std::string name;
std::set<std::string> tags;
std::set<uint16_t> evttypes;
std::shared_ptr<gen_event_filter> filter;
};

typedef std::list<std::shared_ptr<filter_wrapper>> filter_wrapper_list;

// A group of filters all having the same ruleset
class ruleset_filters {
public:
ruleset_filters();

virtual ~ruleset_filters();

void add_filter(std::shared_ptr<filter_wrapper> wrap);
void remove_filter(std::shared_ptr<filter_wrapper> wrap);

uint64_t num_filters();

bool run(gen_event *evt);

void evttypes_for_ruleset(std::set<uint16_t> &evttypes);

private:
void add_wrapper_to_list(filter_wrapper_list &wrappers, std::shared_ptr<filter_wrapper> wrap);
void remove_wrapper_from_list(filter_wrapper_list &wrappers, std::shared_ptr<filter_wrapper> wrap);

// Vector indexes from event type to a set of filters. There can
// be multiple filters for a given event type.
// NOTE: This is used only when the event sub-type is 0.
std::vector<filter_wrapper_list> m_filter_by_event_type;

filter_wrapper_list m_filter_all_event_types;

// All filters added. Used to make num_filters() fast.
std::set<std::shared_ptr<filter_wrapper>> m_filters;
};

// Vector indexes from ruleset id to set of rules.
std::vector<std::shared_ptr<ruleset_filters>> m_rulesets;
virtual ~filter_ruleset() = default;

/*!
\brief Adds a rule and its filtering condition inside the manager.
An exception is thrown is case of error. This method only adds the rule
inside the internal collection, but does not enable it for any ruleset.
The rule must be enabled for one or more rulesets with the enable() or
enable_tags() methods.
\param rule The rule to be added
\param condition The AST representing the rule's filtering condition
*/
virtual void add(
const falco_rule& rule,
std::shared_ptr<libsinsp::filter::ast::expr> condition) = 0;

/*!
\brief Erases the internal state. All rules are disabled in each
ruleset, and all the rules defined with add() are removed.
*/
virtual void clear() = 0;

/*!
\brief Returns the numeric id of a ruleset given its name.
If a ruleset has been used before, its previously assigned id is
returned. Otherwise, a new ruleset is created with the given name
and a new id is assigned to it.
*/
virtual uint16_t ruleset_id(const std::string &name) = 0;

/*!
\brief This is meant to be called after all rules have been added
with add() and enabled on the given ruleset with enable()/enable_tags().
*/
virtual void on_loading_complete() = 0;

/*!
\brief Processes an event and tries to find a match in a given ruleset.
\return true if a match is found, false otherwise
\param evt The event to be processed
\param match If true is returned, this is filled-out with the rule
that matched the event
\param ruleset The id of the ruleset to be used
*/
virtual bool run(
gen_event *evt,
falco_rule& match,
uint16_t ruleset = 0) = 0;

/*!
\brief Returns the number of rules enabled in a given ruleset
\param ruleset The id of the ruleset to be used
*/
virtual uint64_t enabled_count(uint16_t ruleset = 0) = 0;

/*!
\brief Returns the union of the evttypes of all the rules enabled
in a given ruleset
\param ruleset The id of the ruleset to be used
*/
virtual void enabled_evttypes(
std::set<uint16_t> &evttypes,
uint16_t ruleset) = 0;

/*!
\brief Find those rules matching the provided substring and set
their enabled status to enabled in a given 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 enabled The enabled status to set on all matching rules
\param ruleset The id of the ruleset to be used
*/
virtual void enable(
const std::string &substring,
bool match_exact,
bool enabled,
uint16_t ruleset = 0) = 0;

/*!
\brief Find those rules that have a tag in the set of tags and
set their enabled status to enabled. Note that the enabled
status is on the rules, and not the tags--if a rule R has
tags (a, b), and you call enable_tags([a], true) and then
enable_tags([b], false), R will be disabled despite the
fact it has tag a and was enabled by the first call to
enable_tags.
\param substring Tags used to match ruless
\param enabled The enabled status to set on all matching rules
\param ruleset The id of the ruleset to be used
*/
virtual void enable_tags(
const std::set<std::string> &tags,
bool enabled,
uint16_t ruleset = 0) = 0;
};

// All filters added. The set of enabled filters is held in m_rulesets
std::set<std::shared_ptr<filter_wrapper>> m_filters;
/*!
\brief Represents a factory that creates filter_ruleset objects
*/
class filter_ruleset_factory
{
public:
virtual std::shared_ptr<filter_ruleset> new_ruleset() = 0;
};