mirror of
https://github.com/falcosecurity/falco.git
synced 2025-06-26 14:52:20 +00:00
Merge pull request #10 from draios/support-function-outputs
Support function outputs
This commit is contained in:
commit
3feaa86db0
@ -45,18 +45,19 @@ static void usage()
|
||||
);
|
||||
}
|
||||
|
||||
string lua_on_event = "on_event";
|
||||
|
||||
//
|
||||
// Event processing loop
|
||||
//
|
||||
void do_inspect(sinsp* inspector,
|
||||
digwatch_rules* rules,
|
||||
digwatch_formats* formats)
|
||||
digwatch_formats* formats,
|
||||
lua_State* ls)
|
||||
{
|
||||
int32_t res;
|
||||
sinsp_evt* ev;
|
||||
string line;
|
||||
sinsp_evt_formatter* formatter;
|
||||
|
||||
//
|
||||
// Loop through the events
|
||||
@ -89,20 +90,24 @@ void do_inspect(sinsp* inspector,
|
||||
continue;
|
||||
}
|
||||
|
||||
formatter = formats->lookup_formatter(ev->get_check_id());
|
||||
if(!formatter)
|
||||
lua_getglobal(ls, lua_on_event.c_str());
|
||||
|
||||
if(lua_isfunction(ls, -1))
|
||||
{
|
||||
throw sinsp_exception("Error: No formatter for event with id %d " + to_string(ev->get_check_id()));
|
||||
lua_pushlightuserdata(ls, ev);
|
||||
lua_pushnumber(ls, ev->get_check_id());
|
||||
|
||||
if(lua_pcall(ls, 2, 0, 0) != 0)
|
||||
{
|
||||
const char* lerr = lua_tostring(ls, -1);
|
||||
string err = "Error installing rules: " + string(lerr);
|
||||
throw sinsp_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
bool has_all = formatter->tostring(ev, &line);
|
||||
if(!has_all) {
|
||||
cout << "(missing fields) ";
|
||||
else
|
||||
{
|
||||
throw sinsp_exception("No function " + lua_on_event + " found in lua compiler module");
|
||||
}
|
||||
cout << line;
|
||||
cout << endl;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,7 +116,7 @@ void do_inspect(sinsp* inspector,
|
||||
//
|
||||
int digwatch_init(int argc, char **argv)
|
||||
{
|
||||
int result;
|
||||
int result = EXIT_SUCCESS;
|
||||
sinsp* inspector = NULL;
|
||||
digwatch_rules* rules = NULL;
|
||||
digwatch_formats* formats = NULL;
|
||||
@ -120,7 +125,7 @@ int digwatch_init(int argc, char **argv)
|
||||
int long_index = 0;
|
||||
string lua_main_filename;
|
||||
string lua_dir = DIGWATCH_INSTALLATION_DIR;
|
||||
lua_State* ls;
|
||||
lua_State* ls = NULL;
|
||||
|
||||
static struct option long_options[] =
|
||||
{
|
||||
@ -147,7 +152,6 @@ int digwatch_init(int argc, char **argv)
|
||||
{
|
||||
case 'h':
|
||||
usage();
|
||||
result = EXIT_SUCCESS;
|
||||
goto exit;
|
||||
case 'm':
|
||||
lua_main_filename = optarg;
|
||||
@ -220,7 +224,8 @@ int digwatch_init(int argc, char **argv)
|
||||
|
||||
do_inspect(inspector,
|
||||
rules,
|
||||
formats);
|
||||
formats,
|
||||
ls);
|
||||
|
||||
inspector->close();
|
||||
}
|
||||
@ -242,7 +247,10 @@ exit:
|
||||
delete inspector;
|
||||
}
|
||||
|
||||
lua_close(ls);
|
||||
if(ls)
|
||||
{
|
||||
lua_close(ls);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -6,12 +6,12 @@ extern "C" {
|
||||
#include "lauxlib.h"
|
||||
}
|
||||
|
||||
std::map<uint32_t, sinsp_evt_formatter*> g_format_map;
|
||||
sinsp* g_inspector;
|
||||
|
||||
const static struct luaL_reg ll_digwatch [] =
|
||||
{
|
||||
{"set_formatter", &digwatch_formats::set_formatter},
|
||||
{"formatter", &digwatch_formats::formatter},
|
||||
{"format_event", &digwatch_formats::format_event},
|
||||
{NULL,NULL}
|
||||
};
|
||||
|
||||
@ -24,20 +24,13 @@ digwatch_formats::digwatch_formats(sinsp* inspector, lua_State *ls)
|
||||
luaL_openlib(m_ls, "digwatch", ll_digwatch, 0);
|
||||
}
|
||||
|
||||
int digwatch_formats::set_formatter (lua_State *ls) {
|
||||
uint32_t index = luaL_checkinteger(ls, 1);
|
||||
string format = luaL_checkstring(ls, 2);
|
||||
|
||||
int digwatch_formats::formatter(lua_State *ls)
|
||||
{
|
||||
string format = luaL_checkstring(ls, 1);
|
||||
sinsp_evt_formatter* formatter;
|
||||
try
|
||||
{
|
||||
if(format == "" || format == "default")
|
||||
{
|
||||
g_format_map[index] = new sinsp_evt_formatter(g_inspector, DEFAULT_OUTPUT_STR);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_format_map[index] = new sinsp_evt_formatter(g_inspector, format);
|
||||
}
|
||||
formatter = new sinsp_evt_formatter(g_inspector, format);
|
||||
}
|
||||
catch(sinsp_exception& e)
|
||||
{
|
||||
@ -46,12 +39,25 @@ int digwatch_formats::set_formatter (lua_State *ls) {
|
||||
throw sinsp_exception("set_formatter error");
|
||||
}
|
||||
|
||||
return 0;
|
||||
lua_pushlightuserdata(ls, formatter);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sinsp_evt_formatter* digwatch_formats::lookup_formatter(uint32_t index)
|
||||
int digwatch_formats::format_event (lua_State *ls)
|
||||
{
|
||||
return g_format_map[index];
|
||||
string line;
|
||||
|
||||
if (!lua_islightuserdata(ls, -1) || !lua_islightuserdata(ls, -2)) {
|
||||
string err = "invalid arguments passed to format_event() ";
|
||||
throw sinsp_exception("format_event error");
|
||||
}
|
||||
sinsp_evt* evt = (sinsp_evt*)lua_topointer(ls, 1);
|
||||
sinsp_evt_formatter* formatter = (sinsp_evt_formatter*)lua_topointer(ls, 2);
|
||||
|
||||
formatter->tostring(evt, &line);
|
||||
|
||||
lua_pushstring(ls, line.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,9 +10,11 @@ class digwatch_formats
|
||||
public:
|
||||
digwatch_formats(sinsp* inspector, lua_State *ls);
|
||||
|
||||
// set_formatter(index, format_string)
|
||||
static int set_formatter(lua_State *ls);
|
||||
sinsp_evt_formatter* lookup_formatter(uint32_t index);
|
||||
// formatter = digwatch.formatter(format_string)
|
||||
static int formatter(lua_State *ls);
|
||||
|
||||
// formatted_string = digwatch.format_event(evt, formatter)
|
||||
static int format_event(lua_State *ls);
|
||||
|
||||
private:
|
||||
lua_State* m_ls;
|
||||
|
@ -167,13 +167,13 @@ local function outputformat (format)
|
||||
return {type = "OutputFormat", value = format}
|
||||
end
|
||||
|
||||
local function functioncall (name, args)
|
||||
return {type = "FunctionCall", name = name, arguments = args}
|
||||
local function functioncall (str, mname, fname, args)
|
||||
return {type = "FunctionCall", mname = mname, fname = fname, arguments = args, source = str}
|
||||
end
|
||||
|
||||
local function rule(filter, output)
|
||||
if not output then
|
||||
output = outputformat("")
|
||||
output = outputformat(nil)
|
||||
end
|
||||
return {type = "Rule", filter = filter, output = output}
|
||||
end
|
||||
@ -217,7 +217,7 @@ local G = {
|
||||
MacroDef = (C(V"Macro") * V"Skip" * V"Colon" * (V"Filter"));
|
||||
|
||||
FuncArgs = symb("(") * list(V"Value", symb(",")) * symb(")");
|
||||
Output = ((V"Name" * V"FuncArgs") / functioncall) + P(1)^0 / outputformat;
|
||||
Output = (C(V"Name" * P(".") * V"Name" * V"FuncArgs") / functioncall) + P(1)^0 / outputformat;
|
||||
|
||||
-- Terminals
|
||||
Value = terminal "Number" + terminal "String" + terminal "BareString";
|
||||
@ -462,7 +462,7 @@ function print_ast(ast, level)
|
||||
print(ast.value)
|
||||
|
||||
elseif t == "FunctionCall" then
|
||||
print(ast.name .. "(" )
|
||||
print(ast.mname..ast.fname .. "(" )
|
||||
print_ast(ast.arguments)
|
||||
print(")")
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
--]]
|
||||
|
||||
local DEFAULT_OUTPUT_FORMAT = "%evt.num %evt.time %evt.cpu %proc.name (%thread.tid) %evt.dir %evt.type %evt.args"
|
||||
|
||||
local compiler = require "compiler"
|
||||
|
||||
--[[
|
||||
@ -72,10 +74,31 @@ local state
|
||||
to the line-oriented compiler.
|
||||
--]]
|
||||
local function init()
|
||||
return {macros={}, filter_ast=nil, n_rules=0}
|
||||
return {macros={}, filter_ast=nil, n_rules=0, outputs={}}
|
||||
end
|
||||
|
||||
|
||||
function set_output(output_ast)
|
||||
|
||||
if(output_ast.type == "OutputFormat") then
|
||||
|
||||
local format
|
||||
if output_ast.value==nil then
|
||||
format = DEFAULT_OUTPUT_FORMAT
|
||||
else
|
||||
format = output_ast.value
|
||||
end
|
||||
|
||||
state.outputs[state.n_rules] = {type="format", formatter=digwatch.formatter(format)}
|
||||
|
||||
elseif (output_ast.type == "FunctionCall") then
|
||||
require(output_ast.mname)
|
||||
state.outputs[state.n_rules] = {type="function", mname = output_ast.mname, source=output_ast.source}
|
||||
else
|
||||
error ("Unexpected type in set_output: ".. output_ast.type)
|
||||
end
|
||||
end
|
||||
|
||||
function load_rule(r)
|
||||
if (state == nil) then
|
||||
state = init()
|
||||
@ -90,8 +113,9 @@ function load_rule(r)
|
||||
error ("Unexpected type in load_rule: "..line_ast.type)
|
||||
end
|
||||
|
||||
-- Register a formatter with the output string from this rule
|
||||
digwatch.set_formatter(state.n_rules, line_ast.output.value)
|
||||
state.n_rules = state.n_rules + 1
|
||||
|
||||
set_output(line_ast.output)
|
||||
|
||||
-- Store the index of this formatter in each relational expression that
|
||||
-- this rule contains.
|
||||
@ -100,8 +124,6 @@ function load_rule(r)
|
||||
-- event.
|
||||
mark_relational_nodes(line_ast.filter.value, state.n_rules)
|
||||
|
||||
state.n_rules = state.n_rules + 1
|
||||
|
||||
-- Rule ASTs are merged together into one big AST, with "OR" between each
|
||||
-- rule.
|
||||
if (state.filter_ast == nil) then
|
||||
@ -114,3 +136,15 @@ end
|
||||
function on_done()
|
||||
install_filter(state.filter_ast)
|
||||
end
|
||||
|
||||
evt = nil
|
||||
function on_event(evt_, rule_id)
|
||||
if state.outputs[rule_id].type == "format" then
|
||||
print(digwatch.format_event(evt, state.outputs[rule_id].formatter))
|
||||
elseif state.outputs[rule_id].type == "function" then
|
||||
local reqmod = "local "..state.outputs[rule_id].mname.." = require('" ..state.outputs[rule_id].mname .. "')";
|
||||
evt = evt_
|
||||
assert(loadstring(reqmod .. "; print(type(evt));" ..state.outputs[rule_id].source))()
|
||||
end
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user