new(falco): implement rule selection configuration in falco.yaml

Signed-off-by: Luca Guerra <luca@guerra.sh>
This commit is contained in:
Luca Guerra
2024-04-19 10:30:32 +00:00
committed by poiana
parent 60e6798f9b
commit 35bd348e21
17 changed files with 476 additions and 56 deletions

View File

@@ -17,6 +17,8 @@ limitations under the License.
#include "evttype_index_ruleset.h"
#include "falco_utils.h"
#include <algorithm>
evttype_index_ruleset::evttype_index_ruleset(
@@ -235,17 +237,17 @@ void evttype_index_ruleset::clear()
m_filters.clear();
}
void evttype_index_ruleset::enable(const std::string &substring, bool match_exact, uint16_t ruleset_id)
void evttype_index_ruleset::enable(const std::string &pattern, match_type match, uint16_t ruleset_id)
{
enable_disable(substring, match_exact, true, ruleset_id);
enable_disable(pattern, match, true, ruleset_id);
}
void evttype_index_ruleset::disable(const std::string &substring, bool match_exact, uint16_t ruleset_id)
void evttype_index_ruleset::disable(const std::string &pattern, match_type match, uint16_t ruleset_id)
{
enable_disable(substring, match_exact, false, ruleset_id);
enable_disable(pattern, match, false, ruleset_id);
}
void evttype_index_ruleset::enable_disable(const std::string &substring, bool match_exact, bool enabled, uint16_t ruleset_id)
void evttype_index_ruleset::enable_disable(const std::string &pattern, match_type match, bool enabled, uint16_t ruleset_id)
{
while(m_rulesets.size() < (size_t)ruleset_id + 1)
{
@@ -255,17 +257,25 @@ void evttype_index_ruleset::enable_disable(const std::string &substring, bool ma
for(const auto &wrap : m_filters)
{
bool matches;
std::string::size_type pos;
if(match_exact)
switch(match)
{
size_t pos = wrap->rule.name.find(substring);
case match_type::exact:
pos = wrap->rule.name.find(pattern);
matches = (substring == "" || (pos == 0 &&
substring.size() == wrap->rule.name.size()));
}
else
{
matches = (substring == "" || (wrap->rule.name.find(substring) != std::string::npos));
matches = (pattern == "" || (pos == 0 &&
pattern.size() == wrap->rule.name.size()));
break;
case match_type::substring:
matches = (pattern == "" || (wrap->rule.name.find(pattern) != std::string::npos));
break;
case match_type::wildcard:
matches = falco::utils::matches_wildcard(pattern, wrap->rule.name);
break;
default:
// should never happen
matches = false;
}
if(matches)

View File

@@ -53,13 +53,13 @@ public:
void on_loading_complete() override;
void enable(
const std::string &substring,
bool match_exact,
const std::string &pattern,
match_type match,
uint16_t rulset_id) override;
void disable(
const std::string &substring,
bool match_exact,
const std::string &pattern,
match_type match,
uint16_t rulset_id) override;
void enable_tags(
@@ -85,8 +85,8 @@ private:
// Helper used by enable()/disable()
void enable_disable(
const std::string &substring,
bool match_exact,
const std::string &pattern,
match_type match,
bool enabled,
uint16_t rulset_id);

View File

@@ -242,11 +242,11 @@ std::unique_ptr<load_result> falco_engine::load_rules(const std::string &rules_c
}
if(info->enabled)
{
source->ruleset->enable(rule.name, true, m_default_ruleset_id);
source->ruleset->enable(rule.name, filter_ruleset::match_type::exact, m_default_ruleset_id);
}
else
{
source->ruleset->disable(rule.name, true, m_default_ruleset_id);
source->ruleset->disable(rule.name, filter_ruleset::match_type::exact, m_default_ruleset_id);
}
}
}
@@ -272,17 +272,15 @@ void falco_engine::enable_rule(const std::string &substring, bool enabled, const
void falco_engine::enable_rule(const std::string &substring, bool enabled, const uint16_t ruleset_id)
{
bool match_exact = false;
for(const auto &it : m_sources)
{
if(enabled)
{
it.ruleset->enable(substring, match_exact, ruleset_id);
it.ruleset->enable(substring, filter_ruleset::match_type::substring, ruleset_id);
}
else
{
it.ruleset->disable(substring, match_exact, ruleset_id);
it.ruleset->disable(substring, filter_ruleset::match_type::substring, ruleset_id);
}
}
}
@@ -296,17 +294,37 @@ void falco_engine::enable_rule_exact(const std::string &rule_name, bool enabled,
void falco_engine::enable_rule_exact(const std::string &rule_name, bool enabled, const uint16_t ruleset_id)
{
bool match_exact = true;
for(const auto &it : m_sources)
{
if(enabled)
{
it.ruleset->enable(rule_name, match_exact, ruleset_id);
it.ruleset->enable(rule_name, filter_ruleset::match_type::exact, ruleset_id);
}
else
{
it.ruleset->disable(rule_name, match_exact, ruleset_id);
it.ruleset->disable(rule_name, filter_ruleset::match_type::exact, ruleset_id);
}
}
}
void falco_engine::enable_rule_wildcard(const std::string &rule_name, bool enabled, const std::string &ruleset)
{
uint16_t ruleset_id = find_ruleset_id(ruleset);
enable_rule_wildcard(rule_name, enabled, ruleset_id);
}
void falco_engine::enable_rule_wildcard(const std::string &rule_name, bool enabled, const uint16_t ruleset_id)
{
for(const auto &it : m_sources)
{
if(enabled)
{
it.ruleset->enable(rule_name, filter_ruleset::match_type::wildcard, ruleset_id);
}
else
{
it.ruleset->disable(rule_name, filter_ruleset::match_type::wildcard, ruleset_id);
}
}
}

View File

@@ -102,6 +102,12 @@ public:
// Same as above but providing a ruleset id instead
void enable_rule_exact(const std::string &rule_name, bool enabled, const uint16_t ruleset_id);
// Like enable_rule, but wildcards are supported and substrings are not matched
void enable_rule_wildcard(const std::string &rule_name, bool enabled, const std::string &ruleset = s_default_ruleset);
// Same as above but providing a ruleset id instead
void enable_rule_wildcard(const std::string &rule_name, bool enabled, const uint16_t ruleset_id);
//
// Enable/Disable any rules with any of the provided tags (set, exact matches only)
//

View File

@@ -197,6 +197,48 @@ void readfile(const std::string& filename, std::string& data)
return;
}
bool matches_wildcard(const std::string &pattern, const std::string &s)
{
std::string::size_type star_pos = pattern.find("*");
if(star_pos == std::string::npos)
{
// regular match (no wildcards)
return pattern == s;
}
if(star_pos == 0)
{
// wildcard at the beginning "*something*..."
std::string::size_type next_pattern_start = pattern.find_first_not_of("*");
if(next_pattern_start == std::string::npos)
{
// pattern was just a sequence of stars *, **, ***, ... . This always matches.
return true;
}
std::string next_pattern = pattern.substr(next_pattern_start);
std::string to_find = next_pattern.substr(0, next_pattern.find("*"));
std::string::size_type lit_pos = s.find(to_find);
if(lit_pos == std::string::npos)
{
return false;
}
return matches_wildcard(next_pattern.substr(to_find.size()), s.substr(lit_pos + to_find.size()));
} else
{
// wildcard at the end or in the middle "something*else*..."
if(pattern.substr(0, star_pos) != s.substr(0, star_pos))
{
return false;
}
return matches_wildcard(pattern.substr(star_pos), s.substr(star_pos));
}
}
namespace network
{
bool is_unix_scheme(const std::string& url)

View File

@@ -37,6 +37,8 @@ void readfile(const std::string& filename, std::string& data);
uint32_t hardware_concurrency();
bool matches_wildcard(const std::string &pattern, const std::string &s);
namespace network
{
static const std::string UNIX_SCHEME("unix://");

View File

@@ -41,6 +41,10 @@ public:
ruleset_retriever_func_t get_ruleset;
};
enum class match_type {
exact, substring, wildcard
};
virtual ~filter_ruleset() = default;
void set_engine_state(const engine_state_funcs &engine_state);
@@ -167,31 +171,37 @@ public:
/*!
\brief Find those rules matching the provided substring and enable
them in the provided 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 pattern Pattern used to match rule names.
\param match How to match the pattern against rules:
- exact: rules that has the same exact name as the pattern are matched
- substring: rules having the pattern as a substring in the rule are matched.
An empty pattern matches all rules.
- wildcard: rules with names that satisfies a wildcard (*) pattern are matched.
A "*" pattern matches all rules.
Wildcards can appear anywhere in the pattern (e.g. "*hello*world*")
\param ruleset_id The id of the ruleset to be used
*/
virtual void enable(
const std::string &substring,
bool match_exact,
const std::string &pattern,
match_type match,
uint16_t ruleset_id) = 0;
/*!
\brief Find those rules matching the provided substring and disable
them in the provided 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 pattern Pattern used to match rule names.
\param match How to match the pattern against rules:
- exact: rules that has the same exact name as the pattern are matched
- substring: rules having the pattern as a substring in the rule are matched.
An empty pattern matches all rules.
- wildcard: rules with names that satisfies a wildcard (*) pattern are matched.
A "*" pattern matches all rules.
Wildcards can appear anywhere in the pattern (e.g. "*hello*world*")
\param ruleset_id The id of the ruleset to be used
*/
virtual void disable(
const std::string &substring,
bool match_exact,
const std::string &pattern,
match_type match,
uint16_t ruleset_id) = 0;
/*!