From 7fd350d49a32926d82ecca3e49f0f1a79f2237fe Mon Sep 17 00:00:00 2001 From: Mark Stemm Date: Mon, 4 May 2020 17:39:15 -0700 Subject: [PATCH] Allow exact matches for rule names Currently, when calling enable_rule, the provided rule name pattern is a substring match, that is if the rules file has a rule "My fantastic rule", and you call engine->enable_rule("fantastic", true), the rule will be enabled. This can cause problems if one rule name is a complete subset of another rule name e.g. rules "My rule" and "My rule is great", and calling engine->enable_rule("My rule", true). To allow for this case, add an alternate method enable_rule_exact() in both default ruleset and ruleset variants. In this case, the rule name must be an exact match. In the underlying ruleset code, add a "match_exact" option to falco_ruleset::enable() that denotes whether the substring is an exact or substring match. This doesn't change the default behavior of falco in any way, as the existing calls still use enable_rule(). Signed-off-by: Mark Stemm --- userspace/engine/falco_engine.cpp | 19 +++++++++++++++++-- userspace/engine/falco_engine.h | 7 +++++++ userspace/engine/ruleset.cpp | 14 ++++++++++++-- userspace/engine/ruleset.h | 7 +++++-- 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/userspace/engine/falco_engine.cpp b/userspace/engine/falco_engine.cpp index 801aea92..df74e1a0 100644 --- a/userspace/engine/falco_engine.cpp +++ b/userspace/engine/falco_engine.cpp @@ -211,9 +211,10 @@ void falco_engine::load_rules_file(const string &rules_filename, bool verbose, b void falco_engine::enable_rule(const string &substring, bool enabled, const string &ruleset) { uint16_t ruleset_id = find_ruleset_id(ruleset); + bool match_exact = false; - m_sinsp_rules->enable(substring, enabled, ruleset_id); - m_k8s_audit_rules->enable(substring, enabled, ruleset_id); + m_sinsp_rules->enable(substring, match_exact, enabled, ruleset_id); + m_k8s_audit_rules->enable(substring, match_exact, enabled, ruleset_id); } void falco_engine::enable_rule(const string &substring, bool enabled) @@ -221,6 +222,20 @@ void falco_engine::enable_rule(const string &substring, bool enabled) enable_rule(substring, enabled, m_default_ruleset); } +void falco_engine::enable_rule_exact(const string &rule_name, bool enabled, const string &ruleset) +{ + uint16_t ruleset_id = find_ruleset_id(ruleset); + bool match_exact = true; + + m_sinsp_rules->enable(rule_name, match_exact, enabled, ruleset_id); + m_k8s_audit_rules->enable(rule_name, match_exact, enabled, ruleset_id); +} + +void falco_engine::enable_rule_exact(const string &rule_name, bool enabled) +{ + enable_rule_exact(rule_name, enabled, m_default_ruleset); +} + void falco_engine::enable_rule_by_tag(const set &tags, bool enabled, const string &ruleset) { uint16_t ruleset_id = find_ruleset_id(ruleset); diff --git a/userspace/engine/falco_engine.h b/userspace/engine/falco_engine.h index 56b0cc91..768eaf60 100644 --- a/userspace/engine/falco_engine.h +++ b/userspace/engine/falco_engine.h @@ -85,6 +85,13 @@ public: // Wrapper that assumes the default ruleset void enable_rule(const std::string &substring, bool enabled); + + // Like enable_rule, but the rule name must be an exact match. + void enable_rule_exact(const std::string &rule_name, bool enabled, const std::string &ruleset); + + // Wrapper that assumes the default ruleset + void enable_rule_exact(const std::string &rule_name, bool enabled); + // // Enable/Disable any rules with any of the provided tags (set, exact matches only) // diff --git a/userspace/engine/ruleset.cpp b/userspace/engine/ruleset.cpp index 7ed8a004..3156320b 100644 --- a/userspace/engine/ruleset.cpp +++ b/userspace/engine/ruleset.cpp @@ -201,7 +201,7 @@ void falco_ruleset::add(string &name, } } -void falco_ruleset::enable(const string &substring, bool enabled, uint16_t ruleset) +void falco_ruleset::enable(const string &substring, bool match_exact, bool enabled, uint16_t ruleset) { while(m_rulesets.size() < (size_t)ruleset + 1) { @@ -212,7 +212,17 @@ void falco_ruleset::enable(const string &substring, bool enabled, uint16_t rules { bool matches; - matches = (substring == "" || (val.first.find(substring) != string::npos)); + if(match_exact) + { + size_t pos = val.first.find(substring); + + matches = (substring == "" || (pos == 0 && + substring.size() == val.first.size())); + } + else + { + matches = (substring == "" || (val.first.find(substring) != string::npos)); + } if(matches) { diff --git a/userspace/engine/ruleset.h b/userspace/engine/ruleset.h index 353a66f9..c41e74be 100644 --- a/userspace/engine/ruleset.h +++ b/userspace/engine/ruleset.h @@ -45,8 +45,11 @@ public: // unnecessarily large vectors. // Find those rules matching the provided substring and set - // their enabled status to enabled. - void enable(const std::string &substring, bool enabled, uint16_t ruleset = 0); + // 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