mirror of
https://github.com/falcosecurity/falco.git
synced 2025-06-27 07:07:23 +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
|
// Event processing loop
|
||||||
//
|
//
|
||||||
void do_inspect(sinsp* inspector,
|
void do_inspect(sinsp* inspector,
|
||||||
digwatch_rules* rules,
|
digwatch_rules* rules,
|
||||||
digwatch_formats* formats)
|
digwatch_formats* formats,
|
||||||
|
lua_State* ls)
|
||||||
{
|
{
|
||||||
int32_t res;
|
int32_t res;
|
||||||
sinsp_evt* ev;
|
sinsp_evt* ev;
|
||||||
string line;
|
string line;
|
||||||
sinsp_evt_formatter* formatter;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop through the events
|
// Loop through the events
|
||||||
@ -89,20 +90,24 @@ void do_inspect(sinsp* inspector,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
formatter = formats->lookup_formatter(ev->get_check_id());
|
lua_getglobal(ls, lua_on_event.c_str());
|
||||||
if(!formatter)
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
bool has_all = formatter->tostring(ev, &line);
|
{
|
||||||
if(!has_all) {
|
throw sinsp_exception("No function " + lua_on_event + " found in lua compiler module");
|
||||||
cout << "(missing fields) ";
|
|
||||||
}
|
}
|
||||||
cout << line;
|
|
||||||
cout << endl;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +116,7 @@ void do_inspect(sinsp* inspector,
|
|||||||
//
|
//
|
||||||
int digwatch_init(int argc, char **argv)
|
int digwatch_init(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int result;
|
int result = EXIT_SUCCESS;
|
||||||
sinsp* inspector = NULL;
|
sinsp* inspector = NULL;
|
||||||
digwatch_rules* rules = NULL;
|
digwatch_rules* rules = NULL;
|
||||||
digwatch_formats* formats = NULL;
|
digwatch_formats* formats = NULL;
|
||||||
@ -120,7 +125,7 @@ int digwatch_init(int argc, char **argv)
|
|||||||
int long_index = 0;
|
int long_index = 0;
|
||||||
string lua_main_filename;
|
string lua_main_filename;
|
||||||
string lua_dir = DIGWATCH_INSTALLATION_DIR;
|
string lua_dir = DIGWATCH_INSTALLATION_DIR;
|
||||||
lua_State* ls;
|
lua_State* ls = NULL;
|
||||||
|
|
||||||
static struct option long_options[] =
|
static struct option long_options[] =
|
||||||
{
|
{
|
||||||
@ -147,7 +152,6 @@ int digwatch_init(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
case 'h':
|
case 'h':
|
||||||
usage();
|
usage();
|
||||||
result = EXIT_SUCCESS;
|
|
||||||
goto exit;
|
goto exit;
|
||||||
case 'm':
|
case 'm':
|
||||||
lua_main_filename = optarg;
|
lua_main_filename = optarg;
|
||||||
@ -220,7 +224,8 @@ int digwatch_init(int argc, char **argv)
|
|||||||
|
|
||||||
do_inspect(inspector,
|
do_inspect(inspector,
|
||||||
rules,
|
rules,
|
||||||
formats);
|
formats,
|
||||||
|
ls);
|
||||||
|
|
||||||
inspector->close();
|
inspector->close();
|
||||||
}
|
}
|
||||||
@ -242,7 +247,10 @@ exit:
|
|||||||
delete inspector;
|
delete inspector;
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_close(ls);
|
if(ls)
|
||||||
|
{
|
||||||
|
lua_close(ls);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,12 +6,12 @@ extern "C" {
|
|||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<uint32_t, sinsp_evt_formatter*> g_format_map;
|
|
||||||
sinsp* g_inspector;
|
sinsp* g_inspector;
|
||||||
|
|
||||||
const static struct luaL_reg ll_digwatch [] =
|
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}
|
{NULL,NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -24,20 +24,13 @@ digwatch_formats::digwatch_formats(sinsp* inspector, lua_State *ls)
|
|||||||
luaL_openlib(m_ls, "digwatch", ll_digwatch, 0);
|
luaL_openlib(m_ls, "digwatch", ll_digwatch, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int digwatch_formats::set_formatter (lua_State *ls) {
|
int digwatch_formats::formatter(lua_State *ls)
|
||||||
uint32_t index = luaL_checkinteger(ls, 1);
|
{
|
||||||
string format = luaL_checkstring(ls, 2);
|
string format = luaL_checkstring(ls, 1);
|
||||||
|
sinsp_evt_formatter* formatter;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if(format == "" || format == "default")
|
formatter = new sinsp_evt_formatter(g_inspector, format);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch(sinsp_exception& e)
|
catch(sinsp_exception& e)
|
||||||
{
|
{
|
||||||
@ -46,12 +39,25 @@ int digwatch_formats::set_formatter (lua_State *ls) {
|
|||||||
throw sinsp_exception("set_formatter error");
|
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:
|
public:
|
||||||
digwatch_formats(sinsp* inspector, lua_State *ls);
|
digwatch_formats(sinsp* inspector, lua_State *ls);
|
||||||
|
|
||||||
// set_formatter(index, format_string)
|
// formatter = digwatch.formatter(format_string)
|
||||||
static int set_formatter(lua_State *ls);
|
static int formatter(lua_State *ls);
|
||||||
sinsp_evt_formatter* lookup_formatter(uint32_t index);
|
|
||||||
|
// formatted_string = digwatch.format_event(evt, formatter)
|
||||||
|
static int format_event(lua_State *ls);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
lua_State* m_ls;
|
lua_State* m_ls;
|
||||||
|
@ -167,13 +167,13 @@ local function outputformat (format)
|
|||||||
return {type = "OutputFormat", value = format}
|
return {type = "OutputFormat", value = format}
|
||||||
end
|
end
|
||||||
|
|
||||||
local function functioncall (name, args)
|
local function functioncall (str, mname, fname, args)
|
||||||
return {type = "FunctionCall", name = name, arguments = args}
|
return {type = "FunctionCall", mname = mname, fname = fname, arguments = args, source = str}
|
||||||
end
|
end
|
||||||
|
|
||||||
local function rule(filter, output)
|
local function rule(filter, output)
|
||||||
if not output then
|
if not output then
|
||||||
output = outputformat("")
|
output = outputformat(nil)
|
||||||
end
|
end
|
||||||
return {type = "Rule", filter = filter, output = output}
|
return {type = "Rule", filter = filter, output = output}
|
||||||
end
|
end
|
||||||
@ -217,7 +217,7 @@ local G = {
|
|||||||
MacroDef = (C(V"Macro") * V"Skip" * V"Colon" * (V"Filter"));
|
MacroDef = (C(V"Macro") * V"Skip" * V"Colon" * (V"Filter"));
|
||||||
|
|
||||||
FuncArgs = symb("(") * list(V"Value", symb(",")) * symb(")");
|
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
|
-- Terminals
|
||||||
Value = terminal "Number" + terminal "String" + terminal "BareString";
|
Value = terminal "Number" + terminal "String" + terminal "BareString";
|
||||||
@ -462,7 +462,7 @@ function print_ast(ast, level)
|
|||||||
print(ast.value)
|
print(ast.value)
|
||||||
|
|
||||||
elseif t == "FunctionCall" then
|
elseif t == "FunctionCall" then
|
||||||
print(ast.name .. "(" )
|
print(ast.mname..ast.fname .. "(" )
|
||||||
print_ast(ast.arguments)
|
print_ast(ast.arguments)
|
||||||
print(")")
|
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"
|
local compiler = require "compiler"
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@ -72,10 +74,31 @@ local state
|
|||||||
to the line-oriented compiler.
|
to the line-oriented compiler.
|
||||||
--]]
|
--]]
|
||||||
local function init()
|
local function init()
|
||||||
return {macros={}, filter_ast=nil, n_rules=0}
|
return {macros={}, filter_ast=nil, n_rules=0, outputs={}}
|
||||||
end
|
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)
|
function load_rule(r)
|
||||||
if (state == nil) then
|
if (state == nil) then
|
||||||
state = init()
|
state = init()
|
||||||
@ -90,8 +113,9 @@ function load_rule(r)
|
|||||||
error ("Unexpected type in load_rule: "..line_ast.type)
|
error ("Unexpected type in load_rule: "..line_ast.type)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Register a formatter with the output string from this rule
|
state.n_rules = state.n_rules + 1
|
||||||
digwatch.set_formatter(state.n_rules, line_ast.output.value)
|
|
||||||
|
set_output(line_ast.output)
|
||||||
|
|
||||||
-- Store the index of this formatter in each relational expression that
|
-- Store the index of this formatter in each relational expression that
|
||||||
-- this rule contains.
|
-- this rule contains.
|
||||||
@ -100,8 +124,6 @@ function load_rule(r)
|
|||||||
-- event.
|
-- event.
|
||||||
mark_relational_nodes(line_ast.filter.value, state.n_rules)
|
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 ASTs are merged together into one big AST, with "OR" between each
|
||||||
-- rule.
|
-- rule.
|
||||||
if (state.filter_ast == nil) then
|
if (state.filter_ast == nil) then
|
||||||
@ -114,3 +136,15 @@ end
|
|||||||
function on_done()
|
function on_done()
|
||||||
install_filter(state.filter_ast)
|
install_filter(state.filter_ast)
|
||||||
end
|
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