From 0d46fcf8197dbe1e44a94760ba7b26bfc188989a Mon Sep 17 00:00:00 2001 From: Mark Stemm Date: Mon, 28 Nov 2016 11:31:36 -0800 Subject: [PATCH] Move container.info handling to falco engine. container.info handling used to be handled by the the falco_outputs object. However, this caused problems for applications that only used the falco engine, doing their own output formatting for matching events. Fix this by moving output formatting into the falco engine itself. The part that replaces %container.info/adds extra formatting to the end of a rule's output now happens while loading the rule. --- userspace/engine/falco_engine.cpp | 11 ++++++-- userspace/engine/falco_engine.h | 13 ++++++++++ userspace/engine/lua/rule_loader.lua | 26 ++++++++++++++++++- userspace/engine/rules.cpp | 8 ++++-- userspace/engine/rules.h | 3 ++- userspace/falco/falco.cpp | 2 +- userspace/falco/falco_outputs.cpp | 39 +--------------------------- userspace/falco/falco_outputs.h | 4 --- 8 files changed, 57 insertions(+), 49 deletions(-) diff --git a/userspace/engine/falco_engine.cpp b/userspace/engine/falco_engine.cpp index e7dfcacc..910a73b9 100644 --- a/userspace/engine/falco_engine.cpp +++ b/userspace/engine/falco_engine.cpp @@ -38,7 +38,8 @@ string lua_print_stats = "print_stats"; using namespace std; falco_engine::falco_engine(bool seed_rng) - : m_rules(NULL), m_sampling_ratio(1), m_sampling_multiplier(0) + : m_rules(NULL), m_sampling_ratio(1), m_sampling_multiplier(0), + m_replace_container_info(false) { luaopen_lpeg(m_ls); luaopen_yaml(m_ls); @@ -72,7 +73,7 @@ void falco_engine::load_rules(const string &rules_content, bool verbose, bool al { m_rules = new falco_rules(m_inspector, this, m_ls); } - m_rules->load_rules(rules_content, verbose, all_events); + m_rules->load_rules(rules_content, verbose, all_events, m_extra, m_replace_container_info); } void falco_engine::load_rules_file(const string &rules_filename, bool verbose, bool all_events) @@ -184,6 +185,12 @@ void falco_engine::set_sampling_multiplier(double sampling_multiplier) m_sampling_multiplier = sampling_multiplier; } +void falco_engine::set_extra(string &extra, bool replace_container_info) +{ + m_extra = extra; + m_replace_container_info = replace_container_info; +} + inline bool falco_engine::should_drop_evt() { if(m_sampling_multiplier == 0) diff --git a/userspace/engine/falco_engine.h b/userspace/engine/falco_engine.h index 7b6c0971..5820c570 100644 --- a/userspace/engine/falco_engine.h +++ b/userspace/engine/falco_engine.h @@ -96,6 +96,16 @@ public: // void set_sampling_multiplier(double sampling_multiplier); + // + // You can optionally add "extra" formatting fields to the end + // of all output expressions. You can also choose to replace + // %container.info with the extra information or add it to the + // end of the expression. This is used in open source falco to + // add k8s/mesos/container information to outputs when + // available. + // + void set_extra(string &extra, bool replace_container_info); + private: // @@ -132,5 +142,8 @@ private: double m_sampling_multiplier; std::string m_lua_main_filename = "rule_loader.lua"; + + std::string m_extra; + bool m_replace_container_info; }; diff --git a/userspace/engine/lua/rule_loader.lua b/userspace/engine/lua/rule_loader.lua index 837b73ec..fde97fa3 100644 --- a/userspace/engine/lua/rule_loader.lua +++ b/userspace/engine/lua/rule_loader.lua @@ -162,7 +162,7 @@ function table.tostring( tbl ) end -function load_rules(rules_content, rules_mgr, verbose, all_events) +function load_rules(rules_content, rules_mgr, verbose, all_events, extra, replace_container_info) compiler.set_verbose(verbose) compiler.set_all_events(all_events) @@ -257,6 +257,30 @@ function load_rules(rules_content, rules_mgr, verbose, all_events) if (v['enabled'] == false) then falco_rules.enable_rule(rules_mgr, v['rule'], 0) end + + -- If the format string contains %container.info, replace it + -- with extra. Otherwise, add extra onto the end of the format + -- string. + if string.find(v['output'], "%container.info", nil, true) ~= nil then + + -- There may not be any extra, or we're not supposed + -- to replace it, in which case we use the generic + -- "%container.name (id=%container.id)" + if replace_container_info == false then + v['output'] = string.gsub(v['output'], "%%container.info", "%%container.name (id=%%container.id)") + if extra ~= "" then + v['output'] = v['output'].." "..extra + end + else + safe_extra = string.gsub(extra, "%%", "%%%%") + v['output'] = string.gsub(v['output'], "%%container.info", safe_extra) + end + else + -- Just add the extra to the end + if extra ~= "" then + v['output'] = v['output'].." "..extra + end + end else error ("Unexpected type in load_rule: "..filter_ast.type) end diff --git a/userspace/engine/rules.cpp b/userspace/engine/rules.cpp index 8b14a1c3..75bdfa08 100644 --- a/userspace/engine/rules.cpp +++ b/userspace/engine/rules.cpp @@ -108,7 +108,9 @@ void falco_rules::enable_rule(string &rule, bool enabled) m_engine->enable_rule(rule, enabled); } -void falco_rules::load_rules(const string &rules_content, bool verbose, bool all_events) +void falco_rules::load_rules(const string &rules_content, + bool verbose, bool all_events, + string &extra, bool replace_container_info) { lua_getglobal(m_ls, m_lua_load_rules.c_str()); if(lua_isfunction(m_ls, -1)) @@ -182,7 +184,9 @@ void falco_rules::load_rules(const string &rules_content, bool verbose, bool all lua_pushlightuserdata(m_ls, this); lua_pushboolean(m_ls, (verbose ? 1 : 0)); lua_pushboolean(m_ls, (all_events ? 1 : 0)); - if(lua_pcall(m_ls, 4, 0, 0) != 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) { const char* lerr = lua_tostring(m_ls, -1); string err = "Error loading rules:" + string(lerr); diff --git a/userspace/engine/rules.h b/userspace/engine/rules.h index da2e7b06..d81fa405 100644 --- a/userspace/engine/rules.h +++ b/userspace/engine/rules.h @@ -31,7 +31,8 @@ class falco_rules public: falco_rules(sinsp* inspector, falco_engine *engine, lua_State *ls); ~falco_rules(); - void load_rules(const string &rules_content, bool verbose, bool all_events); + void load_rules(const string &rules_content, bool verbose, bool all_events, + std::string &extra, bool replace_container_info); void describe_rule(string *rule); static void init(lua_State *ls); diff --git a/userspace/falco/falco.cpp b/userspace/falco/falco.cpp index b7c9d150..eee175e9 100644 --- a/userspace/falco/falco.cpp +++ b/userspace/falco/falco.cpp @@ -337,10 +337,10 @@ int falco_init(int argc, char **argv) inspector = new sinsp(); engine = new falco_engine(); engine->set_inspector(inspector); + engine->set_extra(output_format, replace_container_info); outputs = new falco_outputs(); outputs->set_inspector(inspector); - outputs->set_extra(output_format, replace_container_info); // Some combinations of arguments are not allowed. if (daemon && pidfilename == "") { diff --git a/userspace/falco/falco_outputs.cpp b/userspace/falco/falco_outputs.cpp index 545ade75..03f6b8a7 100644 --- a/userspace/falco/falco_outputs.cpp +++ b/userspace/falco/falco_outputs.cpp @@ -27,7 +27,6 @@ along with falco. If not, see . using namespace std; falco_outputs::falco_outputs() - : m_replace_container_info(false) { } @@ -52,12 +51,6 @@ void falco_outputs::init(bool json_output) falco_logger::init(m_ls); } -void falco_outputs::set_extra(string &extra, bool replace_container_info) -{ - m_extra = extra; - m_replace_container_info = replace_container_info; -} - void falco_outputs::add_output(output_config oc) { uint8_t nargs = 1; @@ -94,42 +87,12 @@ void falco_outputs::handle_event(sinsp_evt *ev, string &level, string &priority, { lua_getglobal(m_ls, m_lua_output_event.c_str()); - // If the format string contains %container.info, replace it - // with extra. Otherwise, add extra onto the end of the format - // string. - string format_w_extra = format; - size_t pos; - - if((pos = format_w_extra.find("%container.info")) != string::npos) - { - // There may not be any extra, or we're not supposed - // to replace it, in which case we use the generic - // "%container.name (id=%container.id)" - if(m_extra == "" || ! m_replace_container_info) - { - // 15 == strlen(%container.info) - format_w_extra.replace(pos, 15, "%container.name (id=%container.id)"); - } - else - { - format_w_extra.replace(pos, 15, m_extra); - } - } - else - { - // Just add the extra to the end - if (m_extra != "") - { - format_w_extra += " " + m_extra; - } - } - if(lua_isfunction(m_ls, -1)) { lua_pushlightuserdata(m_ls, ev); lua_pushstring(m_ls, level.c_str()); lua_pushstring(m_ls, priority.c_str()); - lua_pushstring(m_ls, format_w_extra.c_str()); + lua_pushstring(m_ls, format.c_str()); if(lua_pcall(m_ls, 4, 0, 0) != 0) { diff --git a/userspace/falco/falco_outputs.h b/userspace/falco/falco_outputs.h index 1f13f653..247d837c 100644 --- a/userspace/falco/falco_outputs.h +++ b/userspace/falco/falco_outputs.h @@ -44,8 +44,6 @@ public: void add_output(output_config oc); - void set_extra(string &extra, bool replace_container_info); - // // ev is an event that has matched some rule. Pass the event // to all configured outputs. @@ -56,6 +54,4 @@ private: std::string m_lua_add_output = "add_output"; std::string m_lua_output_event = "output_event"; std::string m_lua_main_filename = "output.lua"; - std::string m_extra; - bool m_replace_container_info; };