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.
This commit is contained in:
Mark Stemm 2016-11-28 11:31:36 -08:00
parent 704eb57e3c
commit 2961eb4d21
8 changed files with 57 additions and 49 deletions

View File

@ -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)

View File

@ -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;
};

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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 == "") {

View File

@ -27,7 +27,6 @@ along with falco. If not, see <http://www.gnu.org/licenses/>.
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)
{

View File

@ -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;
};