mirror of
https://github.com/falcosecurity/falco.git
synced 2025-09-07 01:30:13 +00:00
update(userspace/engine): better modularize the code for getting json details
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
This commit is contained in:
@@ -462,29 +462,23 @@ void falco_engine::describe_rule(std::string *rule, bool json) const
|
|||||||
|
|
||||||
Json::FastWriter writer;
|
Json::FastWriter writer;
|
||||||
std::string json_str;
|
std::string json_str;
|
||||||
filter_details details;
|
|
||||||
for(const auto &m : m_rule_collector.macros())
|
|
||||||
{
|
|
||||||
// Assumption: no exception because rules have already been loaded.
|
|
||||||
auto cond_ast = libsinsp::filter::parser(m.cond).parse();
|
|
||||||
std::shared_ptr<libsinsp::filter::ast::expr> cond_ast_ptr = std::move(cond_ast);
|
|
||||||
details.known_macros[m.name] = cond_ast_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(const auto &l : m_rule_collector.lists())
|
|
||||||
{
|
|
||||||
details.known_lists.insert(l.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!rule)
|
if(!rule)
|
||||||
{
|
{
|
||||||
|
// In this case we build json information about
|
||||||
|
// all rules, macros and lists
|
||||||
Json::Value output;
|
Json::Value output;
|
||||||
|
|
||||||
|
// Store information about rules
|
||||||
Json::Value rules_array = Json::arrayValue;
|
Json::Value rules_array = Json::arrayValue;
|
||||||
for(const auto& r : m_rules)
|
for(const auto& r : m_rules)
|
||||||
{
|
{
|
||||||
auto json_details = get_json_rule_details(r, details);
|
auto ri = m_rule_collector.rules().at(r.name);
|
||||||
rules_array.append(json_details);
|
Json::Value rule;
|
||||||
|
get_json_details(r, *ri, rule);
|
||||||
|
|
||||||
|
// Append to rule array
|
||||||
|
rules_array.append(rule);
|
||||||
}
|
}
|
||||||
output["rules"] = rules_array;
|
output["rules"] = rules_array;
|
||||||
|
|
||||||
@@ -492,7 +486,9 @@ void falco_engine::describe_rule(std::string *rule, bool json) const
|
|||||||
Json::Value macros_array;
|
Json::Value macros_array;
|
||||||
for(const auto &m : m_rule_collector.macros())
|
for(const auto &m : m_rule_collector.macros())
|
||||||
{
|
{
|
||||||
macros_array.append(m.name);
|
Json::Value macro;
|
||||||
|
get_json_details(m, macro);
|
||||||
|
macros_array.append(macro);
|
||||||
}
|
}
|
||||||
output["macros"] = macros_array;
|
output["macros"] = macros_array;
|
||||||
|
|
||||||
@@ -501,16 +497,8 @@ void falco_engine::describe_rule(std::string *rule, bool json) const
|
|||||||
for(const auto &l : m_rule_collector.lists())
|
for(const auto &l : m_rule_collector.lists())
|
||||||
{
|
{
|
||||||
Json::Value list;
|
Json::Value list;
|
||||||
list["name"] = l.name;
|
get_json_details(l, list);
|
||||||
|
lists_array.append(list);
|
||||||
Json::Value items = Json::arrayValue;
|
|
||||||
for(const auto& i : l.items)
|
|
||||||
{
|
|
||||||
items.append(i);
|
|
||||||
}
|
|
||||||
list["items"] = items;
|
|
||||||
|
|
||||||
lists_array.append(list);
|
|
||||||
}
|
}
|
||||||
output["lists"] = lists_array;
|
output["lists"] = lists_array;
|
||||||
|
|
||||||
@@ -518,30 +506,49 @@ void falco_engine::describe_rule(std::string *rule, bool json) const
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto r = m_rules.at(*rule);
|
// build json information for just the specified rule
|
||||||
if(r == nullptr)
|
auto ri = m_rule_collector.rules().at(*rule);
|
||||||
|
if(ri == nullptr)
|
||||||
{
|
{
|
||||||
throw falco_exception("Rule \"" + *rule + "\" is not loaded");
|
throw falco_exception("Rule \"" + *rule + "\" is not loaded");
|
||||||
}
|
}
|
||||||
|
auto r = m_rules.at(ri->name);
|
||||||
auto json_details = get_json_rule_details(*r, details);
|
Json::Value rule;
|
||||||
json_str = writer.write(json_details);
|
get_json_details(*r, *ri, rule);
|
||||||
|
json_str = writer.write(rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stdout, "%s", json_str.c_str());
|
fprintf(stdout, "%s", json_str.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value falco_engine::get_json_rule_details(const falco_rule& r, filter_details& details) const
|
void falco_engine::get_json_details(const falco_rule &r,
|
||||||
|
const rule_loader::rule_info &ri,
|
||||||
|
Json::Value &rule) const
|
||||||
{
|
{
|
||||||
// Parse rule condition and build the AST
|
Json::Value rule_info;
|
||||||
// Assumption: the parsing will not throw an exception because
|
|
||||||
// rules have already been loaded.
|
|
||||||
auto rule_info = m_rule_collector.rules().at(r.name);
|
|
||||||
auto ast = libsinsp::filter::parser(rule_info->cond).parse();
|
|
||||||
|
|
||||||
// Resolve the AST details
|
// Fill general rule information
|
||||||
filter_details_resolver resolver;
|
rule_info["name"] = r.name;
|
||||||
resolver.run(ast.get(), details);
|
rule_info["condition"] = ri.cond;
|
||||||
|
rule_info["priority"] = format_priority(r.priority, false);
|
||||||
|
rule_info["output"] = r.output;
|
||||||
|
rule_info["description"] = r.description;
|
||||||
|
rule_info["enabled"] = ri.enabled;
|
||||||
|
rule_info["source"] = r.source;
|
||||||
|
Json::Value tags = Json::arrayValue;
|
||||||
|
for(const auto &t : ri.tags)
|
||||||
|
{
|
||||||
|
tags.append(t);
|
||||||
|
}
|
||||||
|
rule_info["tags"] = tags;
|
||||||
|
rule["info"] = rule_info;
|
||||||
|
|
||||||
|
// Parse rule condition and build the AST
|
||||||
|
// Assumption: no exception because rules have already been loaded.
|
||||||
|
auto ast = libsinsp::filter::parser(ri.cond).parse();
|
||||||
|
Json::Value json_details;
|
||||||
|
get_json_details(ast.get(), json_details);
|
||||||
|
rule["details"] = json_details;
|
||||||
|
|
||||||
// Get fields from output string
|
// Get fields from output string
|
||||||
auto insp = new sinsp;
|
auto insp = new sinsp;
|
||||||
@@ -549,15 +556,110 @@ Json::Value falco_engine::get_json_rule_details(const falco_rule& r, filter_deta
|
|||||||
std::vector<std::string> out_fields;
|
std::vector<std::string> out_fields;
|
||||||
fmt.get_field_names(out_fields);
|
fmt.get_field_names(out_fields);
|
||||||
delete insp;
|
delete insp;
|
||||||
|
Json::Value outputFields = Json::arrayValue;
|
||||||
|
for(const auto &of : out_fields)
|
||||||
|
{
|
||||||
|
outputFields.append(of);
|
||||||
|
}
|
||||||
|
rule["details"]["outputFields"] = outputFields;
|
||||||
|
|
||||||
// Build JSON object for the output
|
// Get fields from exceptions
|
||||||
Json::Value output;
|
Json::Value exception_fields = Json::arrayValue;
|
||||||
|
for(const auto &f : r.exception_fields)
|
||||||
|
{
|
||||||
|
exception_fields.append(f);
|
||||||
|
}
|
||||||
|
rule["details"]["exceptionFields"] = exception_fields;
|
||||||
|
|
||||||
output["name"] = r.name;
|
// Get operators from exceptions
|
||||||
output["description"] = r.description;
|
Json::Value exception_operators = Json::arrayValue;
|
||||||
output["priority"] = format_priority(r.priority, false);
|
for(const auto &e : ri.exceptions)
|
||||||
output["output"] = r.output;
|
{
|
||||||
output["enabled"] = rule_info->enabled;
|
if(e.comps.is_list)
|
||||||
|
{
|
||||||
|
for(const auto& c : e.comps.items)
|
||||||
|
{
|
||||||
|
exception_operators.append(c.item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
exception_operators.append(e.comps.item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rule["details"]["exceptionOperators"] = exception_operators;
|
||||||
|
|
||||||
|
if(ri.source == falco_common::syscall_source)
|
||||||
|
{
|
||||||
|
// Store event types
|
||||||
|
Json::Value events;
|
||||||
|
get_json_evt_types(ast.get(), events);
|
||||||
|
rule["details"]["events"] = events;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void falco_engine::get_json_details(const rule_loader::macro_info& m,
|
||||||
|
Json::Value& macro) const
|
||||||
|
{
|
||||||
|
Json::Value macro_info;
|
||||||
|
|
||||||
|
macro_info["name"] = m.name;
|
||||||
|
macro_info["condition"] = m.cond;
|
||||||
|
macro["info"] = macro_info;
|
||||||
|
|
||||||
|
// Assumption: no exception because rules have already been loaded.
|
||||||
|
auto ast = libsinsp::filter::parser(m.cond).parse();
|
||||||
|
|
||||||
|
Json::Value json_details;
|
||||||
|
get_json_details(ast.get(), json_details);
|
||||||
|
macro["details"] = json_details;
|
||||||
|
|
||||||
|
// Store event types
|
||||||
|
Json::Value events;
|
||||||
|
get_json_evt_types(ast.get(), events);
|
||||||
|
macro["details"]["events"] = events;
|
||||||
|
}
|
||||||
|
|
||||||
|
void falco_engine::get_json_details(const rule_loader::list_info& l,
|
||||||
|
Json::Value& list) const
|
||||||
|
{
|
||||||
|
Json::Value list_info;
|
||||||
|
list_info["name"] = l.name;
|
||||||
|
list["info"] = list_info;
|
||||||
|
|
||||||
|
Json::Value items = Json::arrayValue;
|
||||||
|
Json::Value lists = Json::arrayValue;
|
||||||
|
for(const auto &i : l.items)
|
||||||
|
{
|
||||||
|
if(m_rule_collector.lists().at(i) != nullptr)
|
||||||
|
{
|
||||||
|
lists.append(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
items.append(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
list["details"]["items"] = items;
|
||||||
|
list["details"]["lists"] = lists;
|
||||||
|
}
|
||||||
|
|
||||||
|
void falco_engine::get_json_details(libsinsp::filter::ast::expr* ast,
|
||||||
|
Json::Value& output) const
|
||||||
|
{
|
||||||
|
filter_details details;
|
||||||
|
for(const auto &m : m_rule_collector.macros())
|
||||||
|
{
|
||||||
|
details.known_macros.insert(m.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const auto &l : m_rule_collector.lists())
|
||||||
|
{
|
||||||
|
details.known_lists.insert(l.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve the AST details
|
||||||
|
filter_details_resolver resolver;
|
||||||
|
resolver.run(ast, details);
|
||||||
|
|
||||||
Json::Value macros = Json::arrayValue;
|
Json::Value macros = Json::arrayValue;
|
||||||
for(const auto &m : details.macros)
|
for(const auto &m : details.macros)
|
||||||
@@ -580,57 +682,37 @@ Json::Value falco_engine::get_json_rule_details(const falco_rule& r, filter_deta
|
|||||||
}
|
}
|
||||||
output["conditionFields"] = condition_fields;
|
output["conditionFields"] = condition_fields;
|
||||||
|
|
||||||
Json::Value output_fields = Json::arrayValue;
|
|
||||||
for(const auto &f : out_fields)
|
|
||||||
{
|
|
||||||
output_fields.append(f);
|
|
||||||
}
|
|
||||||
output["outputFields"] = output_fields;
|
|
||||||
|
|
||||||
Json::Value exception_fields = Json::arrayValue;
|
|
||||||
for(const auto &f : r.exception_fields)
|
|
||||||
{
|
|
||||||
exception_fields.append(f);
|
|
||||||
}
|
|
||||||
output["exceptionFields"] = exception_fields;
|
|
||||||
|
|
||||||
Json::Value lists = Json::arrayValue;
|
Json::Value lists = Json::arrayValue;
|
||||||
for(const auto &l : details.lists)
|
for(const auto &l : details.lists)
|
||||||
{
|
{
|
||||||
lists.append(l);
|
lists.append(l);
|
||||||
}
|
}
|
||||||
output["lists"] = lists;
|
output["lists"] = lists;
|
||||||
|
|
||||||
|
details.reset();
|
||||||
|
}
|
||||||
|
|
||||||
if (rule_info->source == falco_common::syscall_source)
|
void falco_engine::get_json_evt_types(libsinsp::filter::ast::expr* ast,
|
||||||
|
Json::Value& output) const
|
||||||
|
{
|
||||||
|
output = Json::arrayValue;
|
||||||
|
auto evttypes = libsinsp::filter::ast::ppm_event_codes(ast);
|
||||||
|
if(evttypes.size() != libsinsp::events::all_event_set().size())
|
||||||
{
|
{
|
||||||
Json::Value events = Json::arrayValue;
|
|
||||||
std::unordered_set<std::string> evts;
|
std::unordered_set<std::string> evts;
|
||||||
for(const auto &e : rule_info->evttypes)
|
for(const auto &e : evttypes)
|
||||||
{
|
{
|
||||||
auto evt_info = libsinsp::events::info(e);
|
auto evt_info = libsinsp::events::info(e);
|
||||||
auto res = evts.insert(std::string(evt_info->name));
|
auto res = evts.insert(std::string(evt_info->name));
|
||||||
if(res.second)
|
if(res.second)
|
||||||
{
|
{
|
||||||
events.append(evt_info->name);
|
output.append(evt_info->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output["events"] = events;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
output["source"] = rule_info->source;
|
|
||||||
|
|
||||||
Json::Value tags = Json::arrayValue;
|
|
||||||
for(const auto &t : rule_info->tags)
|
|
||||||
{
|
|
||||||
tags.append(t);
|
|
||||||
}
|
|
||||||
output["tags"] = tags;
|
|
||||||
|
|
||||||
details.reset();
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void falco_engine::print_stats() const
|
void falco_engine::print_stats() const
|
||||||
{
|
{
|
||||||
std::string out;
|
std::string out;
|
||||||
|
@@ -299,8 +299,18 @@ private:
|
|||||||
//
|
//
|
||||||
inline bool should_drop_evt() const;
|
inline bool should_drop_evt() const;
|
||||||
|
|
||||||
// Retrieve details of a rule in json format
|
// Retrieve json details from rules, macros, lists
|
||||||
Json::Value get_json_rule_details(const falco_rule& r, filter_details& details) const;
|
void get_json_details(const falco_rule& r,
|
||||||
|
const rule_loader::rule_info& ri,
|
||||||
|
Json::Value& rule) const;
|
||||||
|
void get_json_details(const rule_loader::macro_info& m,
|
||||||
|
Json::Value& macro) const;
|
||||||
|
void get_json_details(const rule_loader::list_info& l,
|
||||||
|
Json::Value& list) const;
|
||||||
|
void get_json_details(libsinsp::filter::ast::expr* ast,
|
||||||
|
Json::Value& output) const;
|
||||||
|
void get_json_evt_types(libsinsp::filter::ast::expr* ast,
|
||||||
|
Json::Value& output) const;
|
||||||
|
|
||||||
rule_loader::collector m_rule_collector;
|
rule_loader::collector m_rule_collector;
|
||||||
indexed_vector<falco_rule> m_rules;
|
indexed_vector<falco_rule> m_rules;
|
||||||
|
@@ -92,8 +92,5 @@ void filter_details_resolver::visitor::visit(ast::value_expr* e)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_details.macros.insert(it->first);
|
m_details.macros.insert(e->value);
|
||||||
|
|
||||||
// Recursively visit the macro AST as well
|
|
||||||
it->second->accept(this);
|
|
||||||
}
|
}
|
@@ -24,7 +24,7 @@ limitations under the License.
|
|||||||
struct filter_details
|
struct filter_details
|
||||||
{
|
{
|
||||||
// input macros and lists
|
// input macros and lists
|
||||||
std::unordered_map<std::string, std::shared_ptr<libsinsp::filter::ast::expr>> known_macros;
|
std::unordered_set<std::string> known_macros;
|
||||||
std::unordered_set<std::string> known_lists;
|
std::unordered_set<std::string> known_lists;
|
||||||
|
|
||||||
// output details
|
// output details
|
||||||
|
@@ -456,7 +456,6 @@ namespace rule_loader
|
|||||||
std::set<std::string> tags;
|
std::set<std::string> tags;
|
||||||
std::vector<rule_exception_info> exceptions;
|
std::vector<rule_exception_info> exceptions;
|
||||||
falco_common::priority_type priority;
|
falco_common::priority_type priority;
|
||||||
libsinsp::events::set<ppm_event_code> evttypes;
|
|
||||||
bool enabled;
|
bool enabled;
|
||||||
bool warn_evttypes;
|
bool warn_evttypes;
|
||||||
bool skip_if_unknown_filter;
|
bool skip_if_unknown_filter;
|
||||||
|
@@ -386,11 +386,7 @@ void rule_loader::compiler::compile_rule_infos(
|
|||||||
std::string err, condition;
|
std::string err, condition;
|
||||||
std::set<falco::load_result::load_result::warning_code> warn_codes;
|
std::set<falco::load_result::load_result::warning_code> warn_codes;
|
||||||
filter_warning_resolver warn_resolver;
|
filter_warning_resolver warn_resolver;
|
||||||
|
for (auto &r : col.rules())
|
||||||
// note: cast away the const qualifier in the for loop
|
|
||||||
// this is needed because we want to store information about evttypes
|
|
||||||
// used by any rules, which might come in handy when describing rules.
|
|
||||||
for (auto &r : const_cast<indexed_vector<rule_info>&>(col.rules()))
|
|
||||||
{
|
{
|
||||||
// skip the rule if below the minimum priority
|
// skip the rule if below the minimum priority
|
||||||
if (r.priority > cfg.min_priority)
|
if (r.priority > cfg.min_priority)
|
||||||
@@ -509,7 +505,6 @@ void rule_loader::compiler::compile_rule_infos(
|
|||||||
"Rule matches too many evt.type values. This has a significant performance penalty.",
|
"Rule matches too many evt.type values. This has a significant performance penalty.",
|
||||||
r.ctx);
|
r.ctx);
|
||||||
}
|
}
|
||||||
r.evttypes = evttypes;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user