Skip to content

Commit

Permalink
Move json -> k8s audit event conversion out of falco engine
Browse files Browse the repository at this point in the history
Move the code that splits a json object into a list of k8s audit/json
events out of falco engine and into json_evt.

This, along with other changes, allows the falco engine to be more
general purpose and not directly tied to the notion of syscall vs k8s
audit events.

Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
  • Loading branch information
mstemm authored and poiana committed Oct 12, 2021
1 parent 044a7c1 commit 1c60dab
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 89 deletions.
78 changes: 0 additions & 78 deletions userspace/engine/falco_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,84 +386,6 @@ void falco_engine::populate_rule_result(unique_ptr<struct rule_result> &res, gen
}
}

bool falco_engine::parse_k8s_audit_json(nlohmann::json &j, std::list<json_event> &evts, bool top)
{
// Note that nlohmann::basic_json::value can throw nlohmann::basic_json::type_error (302, 306)
try
{
// If the object is an array, call parse_k8s_audit_json again for each item.
if(j.is_array())
{
if(top)
{
for(auto &item : j)
{
// Note we only handle a single top level array, to
// avoid excessive recursion.
if(! parse_k8s_audit_json(item, evts, false))
{
return false;
}
}

return true;
}
else
{
return false;
}
}

// If the kind is EventList, split it into individual events
if(j.value("kind", "<NA>") == "EventList")
{
for(auto &je : j["items"])
{
evts.emplace_back();
je["kind"] = "Event";

uint64_t ns = 0;
if(!sinsp_utils::parse_iso_8601_utc_string(je.value(k8s_audit_time, "<NA>"), ns))
{
return false;
}

std::string tmp;
sinsp_utils::ts_to_string(ns, &tmp, false, true);

evts.back().set_jevt(je, ns);
}

return true;
}
else if(j.value("kind", "<NA>") == "Event")
{
evts.emplace_back();
uint64_t ns = 0;
if(!sinsp_utils::parse_iso_8601_utc_string(j.value(k8s_audit_time, "<NA>"), ns))
{
return false;
}

evts.back().set_jevt(j, ns);
return true;
}
else
{
return false;
}
}
catch(exception &e)
{
return false;
}
}

unique_ptr<falco_engine::rule_result> falco_engine::process_k8s_audit_event(json_event *ev)
{
return process_k8s_audit_event(ev, m_default_ruleset_id);
}

void falco_engine::describe_rule(string *rule)
{
return m_rules->describe_rule(rule);
Expand Down
10 changes: 0 additions & 10 deletions userspace/engine/falco_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,16 +164,6 @@ class falco_engine : public falco_common
std::set<std::string> tags;
};

//
// Given a raw json object, return a list of k8s audit event
// objects that represent the object. This method handles
// things such as EventList splitting.
//
// Returns true if the json object was recognized as a k8s
// audit event(s), false otherwise.
//
bool parse_k8s_audit_json(nlohmann::json &j, std::list<json_event> &evts, bool top=true);

//
// Given an event, check it against the set of rules in the
// engine and if a matching rule is found, return details on
Expand Down
75 changes: 75 additions & 0 deletions userspace/engine/json_evt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,81 @@ uint64_t json_event::get_ts() const
return m_event_ts;
}

static nlohmann::json::json_pointer k8s_audit_time = "/stageTimestamp"_json_pointer;

bool falco_k8s_audit::parse_k8s_audit_json(nlohmann::json &j, std::list<json_event> &evts, bool top)
{
// Note that nlohmann::basic_json::value can throw nlohmann::basic_json::type_error (302, 306)
try
{
// If the object is an array, call parse_k8s_audit_json again for each item.
if(j.is_array())
{
if(top)
{
for(auto &item : j)
{
// Note we only handle a single top level array, to
// avoid excessive recursion.
if(! parse_k8s_audit_json(item, evts, false))
{
return false;
}
}

return true;
}
else
{
return false;
}
}

// If the kind is EventList, split it into individual events
if(j.value("kind", "<NA>") == "EventList")
{
for(auto &je : j["items"])
{
evts.emplace_back();
je["kind"] = "Event";

uint64_t ns = 0;
if(!sinsp_utils::parse_iso_8601_utc_string(je.value(k8s_audit_time, "<NA>"), ns))
{
return false;
}

std::string tmp;
sinsp_utils::ts_to_string(ns, &tmp, false, true);

evts.back().set_jevt(je, ns);
}

return true;
}
else if(j.value("kind", "<NA>") == "Event")
{
evts.emplace_back();
uint64_t ns = 0;
if(!sinsp_utils::parse_iso_8601_utc_string(j.value(k8s_audit_time, "<NA>"), ns))
{
return false;
}

evts.back().set_jevt(j, ns);
return true;
}
else
{
return false;
}
}
catch(exception &e)
{
return false;
}
}

json_event_value::json_event_value()
{
}
Expand Down
13 changes: 13 additions & 0 deletions userspace/engine/json_evt.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,19 @@ class json_event : public gen_event
uint64_t m_event_ts;
};

namespace falco_k8s_audit {

//
// Given a raw json object, return a list of k8s audit event
// objects that represent the object. This method handles
// things such as EventList splitting.
//
// Returns true if the json object was recognized as a k8s
// audit event(s), false otherwise.
//
bool parse_k8s_audit_json(nlohmann::json &j, std::list<json_event> &evts, bool top=true);
};

// A class representing an extracted value or a value on the rhs of a
// filter_check. This intentionally doesn't use the same types as
// ppm_events_public.h to take advantage of actual classes instead of
Expand Down
2 changes: 1 addition & 1 deletion userspace/falco/webserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ bool k8s_audit_handler::accept_data(falco_engine *engine,
bool ok;
try
{
ok = engine->parse_k8s_audit_json(j, jevts);
ok = falco_k8s_audit::parse_k8s_audit_json(j, jevts);
}
catch(json::type_error &e)
{
Expand Down

0 comments on commit 1c60dab

Please sign in to comment.