Skip to content

Commit

Permalink
Add support for tagging falco rules.
Browse files Browse the repository at this point in the history
Add support for tagging falco rules with tags, enabling/disabling sets
of rules based on the tags they have, and having the ability to run a
subset of loaded rules against a given event:

 - in sinsp_evttype_filter::add(), you now provide a set of tags for
   each filter (can be empty).
 - internal to sinsp_evttype_filter, m_filter_by_tag maintains a mapping
   from tag to list of filters having that tag. This is used for
   sinsp_evttype_filter::enable_tags, which allows enabling/disabling
   all filters having a given tag.
 - In sinsp_evttype_filter, rules are grouped into rulesets. All rules have
   a ruleset of 0 which reflects their original loaded status.
 - In ::enable/::enable_tags(), you can provide an optional ruleset
   id (number, defaults to 0) that lets you select sets of rules that
   are enabled given that ruleset id.
 - The filter_wrapper boolean is now a vector indexed by ruleset
   id. filter_wrapper is also now a class with a constructor that
   initializes the vector to one ruleset id (0) that is enabled.

Having multiple rulesets lets you call enable/enable_tags multiple times
with different rulesets. It's one set of rules, but the ruleset allows
you to have different subsets of rules enabled/disabled.

 - ::run() also takes an optional ruleset argument. Once you find the
   matching set of filters given the event type, check the filter's enabled
   vector to see if the filter is enabled given the provided ruleset. If
   so, the filter runs against the event.
 - In sinsp_evttype_filter, clean up use of auto loops to use const references
   whenever possible and use std:: for stl objects in the header file.
  • Loading branch information
mstemm committed Feb 10, 2017
1 parent 99bb210 commit d314eec
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 22 deletions.
66 changes: 56 additions & 10 deletions userspace/libsinsp/filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2002,22 +2002,31 @@ sinsp_evttype_filter::~sinsp_evttype_filter()

m_catchall_evttype_filters.clear();

for(auto val : m_evttype_filters)
for(const auto &val : m_evttype_filters)
{
delete val.second->filter;
delete val.second;
}
m_evttype_filters.clear();
}

sinsp_evttype_filter::filter_wrapper::filter_wrapper()
: enabled{true}
{
}

sinsp_evttype_filter::filter_wrapper::~filter_wrapper()
{
}

void sinsp_evttype_filter::add(string &name,
list<uint32_t> &evttypes,
set<uint32_t> &evttypes,
set<string> &tags,
sinsp_filter *filter)
{
filter_wrapper *wrap = new filter_wrapper();
wrap->filter = filter;
wrap->evttypes = evttypes;
wrap->enabled = true;

m_evttype_filters.insert(pair<string,filter_wrapper *>(name, wrap));

Expand All @@ -2028,7 +2037,7 @@ void sinsp_evttype_filter::add(string &name,
else
{

for(auto evttype: evttypes)
for(const auto &evttype: evttypes)
{
list<filter_wrapper *> *filters = m_filter_by_evttype[evttype];
if(filters == NULL)
Expand All @@ -2040,30 +2049,65 @@ void sinsp_evttype_filter::add(string &name,
filters->push_back(wrap);
}
}

for(const auto &tag: tags)
{
auto it = m_filter_by_tag.lower_bound(tag);

if(it == m_filter_by_tag.end() ||
it->first != tag)
{
it = m_filter_by_tag.emplace_hint(it,
std::make_pair(tag, std::list<filter_wrapper*>()));
}

it->second.push_back(wrap);
}
}

void sinsp_evttype_filter::enable(string &pattern, bool enabled)
void sinsp_evttype_filter::enable(const string &pattern, bool enabled, uint16_t ruleset)
{
regex re(pattern);

for(auto val : m_evttype_filters)
for(const auto &val : m_evttype_filters)
{
if (regex_match(val.first, re))
{
val.second->enabled = enabled;
if(val.second->enabled.size() < (size_t) (ruleset + 1))
{
val.second->enabled.resize(ruleset + 1);
}
val.second->enabled[ruleset] = enabled;
}
}
}

void sinsp_evttype_filter::enable_tags(const set<string> &tags, bool enabled, uint16_t ruleset)
{
for(const auto &tag : tags)
{
for(const auto &wrap : m_filter_by_tag[tag])
{
if(wrap->enabled.size() < (size_t) (ruleset + 1))
{
wrap->enabled.resize(ruleset + 1);
}
wrap->enabled[ruleset] = enabled;
}
}
}

bool sinsp_evttype_filter::run(sinsp_evt *evt)
bool sinsp_evttype_filter::run(sinsp_evt *evt, uint16_t ruleset)
{
//
// First run any catchall event type filters (ones that did not
// explicitly specify any event type.
//
for(filter_wrapper *wrap : m_catchall_evttype_filters)
{
if(wrap->enabled && wrap->filter->run(evt) == true)
if(wrap->enabled.size() >= (size_t) (ruleset + 1) &&
wrap->enabled[ruleset] &&
wrap->filter->run(evt))
{
return true;
}
Expand All @@ -2075,7 +2119,9 @@ bool sinsp_evttype_filter::run(sinsp_evt *evt)
{
for(filter_wrapper *wrap : *filters)
{
if(wrap->enabled && wrap->filter->run(evt) == true)
if(wrap->enabled.size() >= (size_t) (ruleset + 1) &&
wrap->enabled[ruleset] &&
wrap->filter->run(evt))
{
return true;
}
Expand Down
48 changes: 40 additions & 8 deletions userspace/libsinsp/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ along with sysdig. If not, see <http://www.gnu.org/licenses/>.

#pragma once

#include <set>

#ifdef HAS_FILTERING

class sinsp_filter_expression;
Expand Down Expand Up @@ -171,29 +173,59 @@ class SINSP_PUBLIC sinsp_evttype_filter
virtual ~sinsp_evttype_filter();

void add(std::string &name,
list<uint32_t> &evttypes,
std::set<uint32_t> &evttypes,
std::set<string> &tags,
sinsp_filter* filter);

void enable(std::string &pattern, bool enabled);
// 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.

bool run(sinsp_evt *evt);
// Find those rules matching the provided pattern and set
// their enabled status to enabled.
void enable(const std::string &pattern, 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 eanble_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<string> &tags, bool enabled, uint16_t ruleset = 0);

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

private:

struct filter_wrapper {
class filter_wrapper {
public:
filter_wrapper();
virtual ~filter_wrapper();

sinsp_filter *filter;
list<uint32_t> evttypes;
bool enabled;
std::set<uint32_t> evttypes;

// Indexes from ruleset to enabled/disabled. Unlike
// m_filter_by_evttype, this is managed as a vector as we're
// expecting ruleset ids that are small and grouped in the range
// 0..k, as compared to all possible event types.
std::vector<bool> enabled;
};

// Maps from event type to filter. There can be multiple
// filters per event type.
list<filter_wrapper *> *m_filter_by_evttype[PPM_EVENT_MAX];
std::list<filter_wrapper *> *m_filter_by_evttype[PPM_EVENT_MAX];

// It's possible to add an event type filter with an empty
// list of event types, meaning it should run for all event
// types.
list<filter_wrapper *> m_catchall_evttype_filters;
std::list<filter_wrapper *> m_catchall_evttype_filters;

// Maps from tag to list of filters having that tag.
std::map<std::string, std::list<filter_wrapper *>> m_filter_by_tag;

// This holds all the filters in
// m_filter_by_evttype/m_catchall_evttype_filters, so they can
Expand Down
7 changes: 4 additions & 3 deletions userspace/libsinsp/sinsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1439,7 +1439,8 @@ const string sinsp::get_filter()
}

void sinsp::add_evttype_filter(string &name,
list<uint32_t> &evttypes,
set<uint32_t> &evttypes,
set<string> &tags,
sinsp_filter *filter)
{
// Create the evttype filter if it doesn't exist.
Expand All @@ -1448,7 +1449,7 @@ void sinsp::add_evttype_filter(string &name,
m_evttype_filter = new sinsp_evttype_filter();
}

m_evttype_filter->add(name, evttypes, filter);
m_evttype_filter->add(name, evttypes, tags, filter);
}

bool sinsp::run_filters_on_evt(sinsp_evt *evt)
Expand Down Expand Up @@ -1827,7 +1828,7 @@ void sinsp::init_k8s_client(string* api_server, string* ssl_cert, bool verbose)
m_k8s_api_server = api_server;
m_k8s_api_cert = ssl_cert;


#ifdef HAS_CAPTURE
if(m_k8s_api_detected && m_k8s_ext_detect_done)
#endif // HAS_CAPTURE
Expand Down
3 changes: 2 additions & 1 deletion userspace/libsinsp/sinsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,8 @@ class SINSP_PUBLIC sinsp
const string get_filter();

void add_evttype_filter(std::string &name,
list<uint32_t> &evttypes,
std::set<uint32_t> &evttypes,
std::set<std::string> &tags,
sinsp_filter* filter);

bool run_filters_on_evt(sinsp_evt *evt);
Expand Down

0 comments on commit d314eec

Please sign in to comment.