mirror of
https://github.com/falcosecurity/falco.git
synced 2025-07-19 09:06:48 +00:00
Add more useful json output.
Instead of using sysdig's json output, which only contains the fields from the format string without any formatting text, use the string output to build a json object containing the format string, rule name, severity, and the event time (converted to a json-friendly ISO8601). This fixes https://github.com/draios/falco/issues/82.
This commit is contained in:
parent
9ab7f52fb0
commit
52a7c77596
@ -242,7 +242,6 @@ int falco_init(int argc, char **argv)
|
|||||||
sinsp* inspector = NULL;
|
sinsp* inspector = NULL;
|
||||||
falco_rules* rules = NULL;
|
falco_rules* rules = NULL;
|
||||||
int op;
|
int op;
|
||||||
sinsp_evt::param_fmt event_buffer_format;
|
|
||||||
int long_index = 0;
|
int long_index = 0;
|
||||||
string lua_main_filename;
|
string lua_main_filename;
|
||||||
string scap_filename;
|
string scap_filename;
|
||||||
@ -391,7 +390,7 @@ int falco_init(int argc, char **argv)
|
|||||||
|
|
||||||
rules = new falco_rules(inspector, ls, lua_main_filename);
|
rules = new falco_rules(inspector, ls, lua_main_filename);
|
||||||
|
|
||||||
falco_formats::init(inspector, ls);
|
falco_formats::init(inspector, ls, config.m_json_output);
|
||||||
falco_fields::init(inspector, ls);
|
falco_fields::init(inspector, ls);
|
||||||
|
|
||||||
falco_logger::init(ls);
|
falco_logger::init(ls);
|
||||||
@ -416,16 +415,6 @@ int falco_init(int argc, char **argv)
|
|||||||
|
|
||||||
inspector->set_hostname_and_port_resolution_mode(false);
|
inspector->set_hostname_and_port_resolution_mode(false);
|
||||||
|
|
||||||
if (config.m_json_output)
|
|
||||||
{
|
|
||||||
event_buffer_format = sinsp_evt::PF_JSON;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
event_buffer_format = sinsp_evt::PF_NORMAL;
|
|
||||||
}
|
|
||||||
inspector->set_buffer_format(event_buffer_format);
|
|
||||||
|
|
||||||
for(std::vector<output_config>::iterator it = config.m_outputs.begin(); it != config.m_outputs.end(); ++it)
|
for(std::vector<output_config>::iterator it = config.m_outputs.begin(); it != config.m_outputs.end(); ++it)
|
||||||
{
|
{
|
||||||
add_output(ls, *it);
|
add_output(ls, *it);
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
|
#include <json/json.h>
|
||||||
|
|
||||||
#include "formats.h"
|
#include "formats.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
|
||||||
|
|
||||||
sinsp* falco_formats::s_inspector = NULL;
|
sinsp* falco_formats::s_inspector = NULL;
|
||||||
|
bool s_json_output = false;
|
||||||
|
|
||||||
const static struct luaL_reg ll_falco [] =
|
const static struct luaL_reg ll_falco [] =
|
||||||
{
|
{
|
||||||
@ -11,9 +14,10 @@ const static struct luaL_reg ll_falco [] =
|
|||||||
{NULL,NULL}
|
{NULL,NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
void falco_formats::init(sinsp* inspector, lua_State *ls)
|
void falco_formats::init(sinsp* inspector, lua_State *ls, bool json_output)
|
||||||
{
|
{
|
||||||
s_inspector = inspector;
|
s_inspector = inspector;
|
||||||
|
s_json_output = json_output;
|
||||||
|
|
||||||
luaL_openlib(ls, "falco", ll_falco, 0);
|
luaL_openlib(ls, "falco", ll_falco, 0);
|
||||||
}
|
}
|
||||||
@ -42,15 +46,53 @@ int falco_formats::format_event (lua_State *ls)
|
|||||||
{
|
{
|
||||||
string line;
|
string line;
|
||||||
|
|
||||||
if (!lua_islightuserdata(ls, -1) || !lua_islightuserdata(ls, -2)) {
|
if (!lua_islightuserdata(ls, -1) ||
|
||||||
|
!lua_isstring(ls, -2) ||
|
||||||
|
!lua_isstring(ls, -3) ||
|
||||||
|
!lua_islightuserdata(ls, -4)) {
|
||||||
falco_logger::log(LOG_ERR, "Invalid arguments passed to format_event()\n");
|
falco_logger::log(LOG_ERR, "Invalid arguments passed to format_event()\n");
|
||||||
throw sinsp_exception("format_event error");
|
throw sinsp_exception("format_event error");
|
||||||
}
|
}
|
||||||
sinsp_evt* evt = (sinsp_evt*)lua_topointer(ls, 1);
|
sinsp_evt* evt = (sinsp_evt*)lua_topointer(ls, 1);
|
||||||
sinsp_evt_formatter* formatter = (sinsp_evt_formatter*)lua_topointer(ls, 2);
|
const char *rule = (char *) lua_tostring(ls, 2);
|
||||||
|
const char *level = (char *) lua_tostring(ls, 3);
|
||||||
|
sinsp_evt_formatter* formatter = (sinsp_evt_formatter*)lua_topointer(ls, 4);
|
||||||
|
|
||||||
formatter->tostring(evt, &line);
|
formatter->tostring(evt, &line);
|
||||||
|
|
||||||
|
// For JSON output, the formatter returned just the output
|
||||||
|
// string containing the format text and values. Use this to
|
||||||
|
// build a more detailed object containing the event time,
|
||||||
|
// rule, severity, full output, and fields.
|
||||||
|
if (s_json_output) {
|
||||||
|
Json::Value event;
|
||||||
|
Json::FastWriter writer;
|
||||||
|
|
||||||
|
// Convert the time-as-nanoseconds to a more json-friendly ISO8601.
|
||||||
|
time_t evttime = evt->get_ts()/1000000000;
|
||||||
|
char time_sec[20]; // sizeof "YYYY-MM-DDTHH:MM:SS"
|
||||||
|
char time_ns[12]; // sizeof ".sssssssssZ"
|
||||||
|
string iso8601evttime;
|
||||||
|
|
||||||
|
strftime(time_sec, sizeof(time_sec), "%FT%T", gmtime(&evttime));
|
||||||
|
snprintf(time_ns, sizeof(time_ns), ".%09luZ", evt->get_ts() % 1000000000);
|
||||||
|
iso8601evttime = time_sec;
|
||||||
|
iso8601evttime += time_ns;
|
||||||
|
event["time"] = iso8601evttime;
|
||||||
|
event["rule"] = rule;
|
||||||
|
event["priority"] = level;
|
||||||
|
event["output"] = line;
|
||||||
|
|
||||||
|
line = writer.write(event);
|
||||||
|
|
||||||
|
// Json::FastWriter may add a trailing newline. If it
|
||||||
|
// does, remove it.
|
||||||
|
if (line[line.length()-1] == '\n')
|
||||||
|
{
|
||||||
|
line.resize(line.length()-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lua_pushstring(ls, line.c_str());
|
lua_pushstring(ls, line.c_str());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ class sinsp_evt_formatter;
|
|||||||
class falco_formats
|
class falco_formats
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void init(sinsp* inspector, lua_State *ls);
|
static void init(sinsp* inspector, lua_State *ls, bool json_output);
|
||||||
|
|
||||||
// formatter = falco.formatter(format_string)
|
// formatter = falco.formatter(format_string)
|
||||||
static int formatter(lua_State *ls);
|
static int formatter(lua_State *ls);
|
||||||
|
@ -6,10 +6,10 @@ mod.levels = levels
|
|||||||
|
|
||||||
local outputs = {}
|
local outputs = {}
|
||||||
|
|
||||||
function mod.stdout(evt, level, format)
|
function mod.stdout(evt, rule, level, format)
|
||||||
format = "*%evt.time: "..levels[level+1].." "..format
|
format = "*%evt.time: "..levels[level+1].." "..format
|
||||||
formatter = falco.formatter(format)
|
formatter = falco.formatter(format)
|
||||||
msg = falco.format_event(evt, formatter)
|
msg = falco.format_event(evt, rule, levels[level+1], formatter)
|
||||||
print (msg)
|
print (msg)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -26,26 +26,26 @@ function mod.file_validate(options)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function mod.file(evt, level, format, options)
|
function mod.file(evt, rule, level, format, options)
|
||||||
format = "%evt.time: "..levels[level+1].." "..format
|
format = "%evt.time: "..levels[level+1].." "..format
|
||||||
formatter = falco.formatter(format)
|
formatter = falco.formatter(format)
|
||||||
msg = falco.format_event(evt, formatter)
|
msg = falco.format_event(evt, rule, levels[level+1], formatter)
|
||||||
|
|
||||||
file = io.open(options.filename, "a+")
|
file = io.open(options.filename, "a+")
|
||||||
file:write(msg, "\n")
|
file:write(msg, "\n")
|
||||||
file:close()
|
file:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
function mod.syslog(evt, level, format)
|
function mod.syslog(evt, rule, level, format)
|
||||||
|
|
||||||
formatter = falco.formatter(format)
|
formatter = falco.formatter(format)
|
||||||
msg = falco.format_event(evt, formatter)
|
msg = falco.format_event(evt, rule, levels[level+1], formatter)
|
||||||
falco.syslog(level, msg)
|
falco.syslog(level, msg)
|
||||||
end
|
end
|
||||||
|
|
||||||
function mod.event(event, level, format)
|
function mod.event(event, rule, level, format)
|
||||||
for index,o in ipairs(outputs) do
|
for index,o in ipairs(outputs) do
|
||||||
o.output(event, level, format, o.config)
|
o.output(event, rule, level, format, o.config)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -256,7 +256,7 @@ function on_event(evt_, rule_id)
|
|||||||
rule_output_counts.by_name[rule.rule] = rule_output_counts.by_name[rule.rule] + 1
|
rule_output_counts.by_name[rule.rule] = rule_output_counts.by_name[rule.rule] + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
output.event(evt_, rule.level, rule.output)
|
output.event(evt_, rule.rule, rule.level, rule.output)
|
||||||
end
|
end
|
||||||
|
|
||||||
function print_stats()
|
function print_stats()
|
||||||
|
Loading…
Reference in New Issue
Block a user