mirror of
https://github.com/falcosecurity/falco.git
synced 2025-09-10 02:59:38 +00:00
Add ability to filter events by priority/cleanups
Clean up the handling of priority levels within rules. It used to be a mix of strings handled in various places. Now, in falco_common.h there's a consistent type for priority-as-number as well as a list of priority-as-string values. Priorities are passed around as numbers instead of strings. It's still permissive about capitalization. Also add the ability to load rules by severity. New falco config option "priority=<val>"/-o priority=<val> specifies the minimum priority level of rules that will be loaded. Add unit tests for same. The test suppresses INFO notifications for a rule/trace file combination that would otherwise generate them.
This commit is contained in:
@@ -21,6 +21,16 @@ along with falco. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "config_falco_engine.h"
|
||||
#include "falco_common.h"
|
||||
|
||||
std::vector<std::string> falco_common::priority_names = {
|
||||
"Emergency",
|
||||
"Alert",
|
||||
"Critical",
|
||||
"Error",
|
||||
"Warning",
|
||||
"Notice",
|
||||
"Informational",
|
||||
"Debug"};
|
||||
|
||||
falco_common::falco_common()
|
||||
{
|
||||
m_ls = lua_open();
|
||||
|
@@ -74,6 +74,22 @@ public:
|
||||
|
||||
void set_inspector(sinsp *inspector);
|
||||
|
||||
// Priority levels, as a vector of strings
|
||||
static std::vector<std::string> priority_names;
|
||||
|
||||
// Same as numbers/indices into the above vector
|
||||
enum priority_type
|
||||
{
|
||||
PRIORITY_EMERGENCY = 0,
|
||||
PRIORITY_ALERT = 1,
|
||||
PRIORITY_CRITICAL = 2,
|
||||
PRIORITY_ERROR = 3,
|
||||
PRIORITY_WARNING = 4,
|
||||
PRIORITY_NOTICE = 5,
|
||||
PRIORITY_INFORMATIONAL = 6,
|
||||
PRIORITY_DEBUG = 7
|
||||
};
|
||||
|
||||
protected:
|
||||
lua_State *m_ls;
|
||||
|
||||
|
@@ -41,6 +41,7 @@ using namespace std;
|
||||
|
||||
falco_engine::falco_engine(bool seed_rng)
|
||||
: m_rules(NULL), m_next_ruleset_id(0),
|
||||
m_min_priority(falco_common::PRIORITY_DEBUG),
|
||||
m_sampling_ratio(1), m_sampling_multiplier(0),
|
||||
m_replace_container_info(false)
|
||||
{
|
||||
@@ -89,7 +90,7 @@ void falco_engine::load_rules(const string &rules_content, bool verbose, bool al
|
||||
bool json_output = false;
|
||||
falco_formats::init(m_inspector, m_ls, json_output);
|
||||
|
||||
m_rules->load_rules(rules_content, verbose, all_events, m_extra, m_replace_container_info);
|
||||
m_rules->load_rules(rules_content, verbose, all_events, m_extra, m_replace_container_info, m_min_priority);
|
||||
}
|
||||
|
||||
void falco_engine::load_rules_file(const string &rules_filename, bool verbose, bool all_events)
|
||||
@@ -134,6 +135,11 @@ void falco_engine::enable_rule_by_tag(const set<string> &tags, bool enabled)
|
||||
enable_rule_by_tag(tags, enabled, m_default_ruleset);
|
||||
}
|
||||
|
||||
void falco_engine::set_min_priority(falco_common::priority_type priority)
|
||||
{
|
||||
m_min_priority = priority;
|
||||
}
|
||||
|
||||
uint16_t falco_engine::find_ruleset_id(const std::string &ruleset)
|
||||
{
|
||||
auto it = m_known_rulesets.lower_bound(ruleset);
|
||||
@@ -178,7 +184,7 @@ unique_ptr<falco_engine::rule_result> falco_engine::process_event(sinsp_evt *ev,
|
||||
res->evt = ev;
|
||||
const char *p = lua_tostring(m_ls, -3);
|
||||
res->rule = p;
|
||||
res->priority = lua_tostring(m_ls, -2);
|
||||
res->priority_num = (falco_common::priority_type) lua_tonumber(m_ls, -2);
|
||||
res->format = lua_tostring(m_ls, -1);
|
||||
lua_pop(m_ls, 3);
|
||||
}
|
||||
|
@@ -67,10 +67,13 @@ public:
|
||||
// Wrapper that assumes the default ruleset
|
||||
void enable_rule_by_tag(const std::set<std::string> &tags, bool enabled);
|
||||
|
||||
// Only load rules having this priority or more severe.
|
||||
void set_min_priority(falco_common::priority_type priority);
|
||||
|
||||
struct rule_result {
|
||||
sinsp_evt *evt;
|
||||
std::string rule;
|
||||
std::string priority;
|
||||
falco_common::priority_type priority_num;
|
||||
std::string format;
|
||||
};
|
||||
|
||||
@@ -158,6 +161,7 @@ private:
|
||||
uint16_t m_next_ruleset_id;
|
||||
std::map<string, uint16_t> m_known_rulesets;
|
||||
std::unique_ptr<sinsp_evttype_filter> m_evttype_filter;
|
||||
falco_common::priority_type m_min_priority;
|
||||
|
||||
//
|
||||
// Here's how the sampling ratio and multiplier influence
|
||||
|
@@ -58,6 +58,17 @@ function map(f, arr)
|
||||
return res
|
||||
end
|
||||
|
||||
priorities = {"Emergency", "Alert", "Critical", "Error", "Warning", "Notice", "Informational", "Debug"}
|
||||
|
||||
local function priority_num_for(s)
|
||||
s = string.lower(s)
|
||||
for i,v in ipairs(priorities) do
|
||||
if (string.find(string.lower(v), "^"..s)) then
|
||||
return i - 1 -- (numbers start at 0, lua indices start at 1)
|
||||
end
|
||||
end
|
||||
error("Invalid priority level: "..s)
|
||||
end
|
||||
|
||||
--[[
|
||||
Take a filter AST and set it up in the libsinsp runtime, using the filter API.
|
||||
@@ -171,7 +182,7 @@ function table.tostring( tbl )
|
||||
end
|
||||
|
||||
|
||||
function load_rules(rules_content, rules_mgr, verbose, all_events, extra, replace_container_info)
|
||||
function load_rules(rules_content, rules_mgr, verbose, all_events, extra, replace_container_info, min_priority)
|
||||
|
||||
compiler.set_verbose(verbose)
|
||||
compiler.set_all_events(all_events)
|
||||
@@ -293,18 +304,23 @@ function load_rules(rules_content, rules_mgr, verbose, all_events, extra, replac
|
||||
end
|
||||
end
|
||||
|
||||
-- Note that we can overwrite rules, but the rules are still
|
||||
-- loaded in the order in which they first appeared,
|
||||
-- potentially across multiple files.
|
||||
if state.rules_by_name[v['rule']] == nil then
|
||||
state.ordered_rule_names[#state.ordered_rule_names+1] = v['rule']
|
||||
-- Convert the priority-as-string to a priority-as-number now
|
||||
v['priority_num'] = priority_num_for(v['priority'])
|
||||
|
||||
if v['priority_num'] <= min_priority then
|
||||
-- Note that we can overwrite rules, but the rules are still
|
||||
-- loaded in the order in which they first appeared,
|
||||
-- potentially across multiple files.
|
||||
if state.rules_by_name[v['rule']] == nil then
|
||||
state.ordered_rule_names[#state.ordered_rule_names+1] = v['rule']
|
||||
end
|
||||
|
||||
-- The output field might be a folded-style, which adds a
|
||||
-- newline to the end. Remove any trailing newlines.
|
||||
v['output'] = compiler.trim(v['output'])
|
||||
|
||||
state.rules_by_name[v['rule']] = v
|
||||
end
|
||||
|
||||
-- The output field might be a folded-style, which adds a
|
||||
-- newline to the end. Remove any trailing newlines.
|
||||
v['output'] = compiler.trim(v['output'])
|
||||
|
||||
state.rules_by_name[v['rule']] = v
|
||||
end
|
||||
else
|
||||
error ("Unknown rule object: "..table.tostring(v))
|
||||
@@ -504,7 +520,7 @@ function on_event(evt_, rule_id)
|
||||
-- Prefix output with '*' so formatting is permissive
|
||||
output = "*"..rule.output
|
||||
|
||||
return rule.rule, rule.priority, output
|
||||
return rule.rule, rule.priority_num, output
|
||||
end
|
||||
|
||||
function print_stats()
|
||||
|
@@ -145,7 +145,8 @@ void falco_rules::enable_rule(string &rule, bool enabled)
|
||||
|
||||
void falco_rules::load_rules(const string &rules_content,
|
||||
bool verbose, bool all_events,
|
||||
string &extra, bool replace_container_info)
|
||||
string &extra, bool replace_container_info,
|
||||
falco_common::priority_type min_priority)
|
||||
{
|
||||
lua_getglobal(m_ls, m_lua_load_rules.c_str());
|
||||
if(lua_isfunction(m_ls, -1))
|
||||
@@ -221,7 +222,8 @@ void falco_rules::load_rules(const string &rules_content,
|
||||
lua_pushboolean(m_ls, (all_events ? 1 : 0));
|
||||
lua_pushstring(m_ls, extra.c_str());
|
||||
lua_pushboolean(m_ls, (replace_container_info ? 1 : 0));
|
||||
if(lua_pcall(m_ls, 6, 0, 0) != 0)
|
||||
lua_pushnumber(m_ls, min_priority);
|
||||
if(lua_pcall(m_ls, 7, 0, 0) != 0)
|
||||
{
|
||||
const char* lerr = lua_tostring(m_ls, -1);
|
||||
string err = "Error loading rules:" + string(lerr);
|
||||
|
@@ -24,6 +24,8 @@ along with falco. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "lua_parser.h"
|
||||
|
||||
#include "falco_common.h"
|
||||
|
||||
class falco_engine;
|
||||
|
||||
class falco_rules
|
||||
@@ -32,7 +34,8 @@ class falco_rules
|
||||
falco_rules(sinsp* inspector, falco_engine *engine, lua_State *ls);
|
||||
~falco_rules();
|
||||
void load_rules(const string &rules_content, bool verbose, bool all_events,
|
||||
std::string &extra, bool replace_container_info);
|
||||
std::string &extra, bool replace_container_info,
|
||||
falco_common::priority_type min_priority);
|
||||
void describe_rule(string *rule);
|
||||
|
||||
static void init(lua_State *ls);
|
||||
|
Reference in New Issue
Block a user