mirror of
https://github.com/falcosecurity/falco.git
synced 2025-09-07 17:54:07 +00:00
refactor(userspace/engine): uniform json lib in rules description and not print from engine
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
This commit is contained in:
@@ -505,17 +505,17 @@ std::size_t falco_engine::add_source(const std::string &source,
|
||||
return m_sources.insert(src, source);
|
||||
}
|
||||
|
||||
template <typename T> inline Json::Value sequence_to_json_array(const T& seq)
|
||||
template <typename T> inline nlohmann::json sequence_to_json_array(const T& seq)
|
||||
{
|
||||
Json::Value ret = Json::arrayValue;
|
||||
nlohmann::json ret = nlohmann::json::array();
|
||||
for (auto it = seq.begin(); it != seq.end(); it++)
|
||||
{
|
||||
ret.append(*it);
|
||||
ret.push_back(*it);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void falco_engine::describe_rule(std::string *rule, const std::vector<std::shared_ptr<sinsp_plugin>>& plugins, bool json) const
|
||||
nlohmann::json falco_engine::describe_rule(std::string *rule, const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
|
||||
{
|
||||
// use previously-loaded collector definitions and the compiled
|
||||
// output of rules, macros, and lists.
|
||||
@@ -524,103 +524,69 @@ void falco_engine::describe_rule(std::string *rule, const std::vector<std::share
|
||||
throw falco_exception("rules most be loaded before describing them");
|
||||
}
|
||||
|
||||
if(!json)
|
||||
{
|
||||
static const char *rule_fmt = "%-50s %s\n";
|
||||
fprintf(stdout, rule_fmt, "Rule", "Description");
|
||||
fprintf(stdout, rule_fmt, "----", "-----------");
|
||||
if(!rule)
|
||||
{
|
||||
for(auto &r : m_rules)
|
||||
{
|
||||
auto str = falco::utils::wrap_text(r.description, 51, 110) + "\n";
|
||||
fprintf(stdout, rule_fmt, r.name.c_str(), str.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto r = m_rules.at(*rule);
|
||||
if(r == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto str = falco::utils::wrap_text(r->description, 51, 110) + "\n";
|
||||
fprintf(stdout, rule_fmt, r->name.c_str(), str.c_str());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// use collected and compiled info to print a json output
|
||||
Json::FastWriter writer;
|
||||
std::string json_str;
|
||||
nlohmann::json output;
|
||||
if(!rule)
|
||||
{
|
||||
// In this case we build json information about
|
||||
// all rules, macros and lists
|
||||
Json::Value output;
|
||||
|
||||
// Store required engine version
|
||||
auto required_engine_version = m_rule_collector.required_engine_version();
|
||||
output["required_engine_version"] = required_engine_version.version.as_string();
|
||||
|
||||
// Store required plugin versions
|
||||
Json::Value plugin_versions = Json::arrayValue;
|
||||
nlohmann::json plugin_versions = nlohmann::json::array();
|
||||
auto required_plugin_versions = m_rule_collector.required_plugin_versions();
|
||||
for(const auto& req : required_plugin_versions)
|
||||
{
|
||||
Json::Value r;
|
||||
nlohmann::json r;
|
||||
r["name"] = req.at(0).name;
|
||||
r["version"] = req.at(0).version;
|
||||
|
||||
Json::Value alternatives = Json::arrayValue;
|
||||
nlohmann::json alternatives = nlohmann::json::array();
|
||||
for(size_t i = 1; i < req.size(); i++)
|
||||
{
|
||||
Json::Value alternative;
|
||||
nlohmann::json alternative;
|
||||
alternative["name"] = req[i].name;
|
||||
alternative["version"] = req[i].version;
|
||||
alternatives.append(alternative);
|
||||
alternatives.push_back(alternative);
|
||||
}
|
||||
r["alternatives"] = alternatives;
|
||||
|
||||
plugin_versions.append(r);
|
||||
plugin_versions.push_back(r);
|
||||
}
|
||||
output["required_plugin_versions"] = plugin_versions;
|
||||
|
||||
// Store information about rules
|
||||
Json::Value rules_array = Json::arrayValue;
|
||||
nlohmann::json rules_array = nlohmann::json::array();
|
||||
for(const auto& r : m_last_compile_output->rules)
|
||||
{
|
||||
auto info = m_rule_collector.rules().at(r.name);
|
||||
Json::Value rule;
|
||||
nlohmann::json rule;
|
||||
get_json_details(rule, r, *info, plugins);
|
||||
rules_array.append(rule);
|
||||
rules_array.push_back(rule);
|
||||
}
|
||||
output["rules"] = rules_array;
|
||||
|
||||
// Store information about macros
|
||||
Json::Value macros_array = Json::arrayValue;
|
||||
nlohmann::json macros_array = nlohmann::json::array();
|
||||
for(const auto &m : m_last_compile_output->macros)
|
||||
{
|
||||
auto info = m_rule_collector.macros().at(m.name);
|
||||
Json::Value macro;
|
||||
nlohmann::json macro;
|
||||
get_json_details(macro, m, *info, plugins);
|
||||
macros_array.append(macro);
|
||||
macros_array.push_back(macro);
|
||||
}
|
||||
output["macros"] = macros_array;
|
||||
|
||||
// Store information about lists
|
||||
Json::Value lists_array = Json::arrayValue;
|
||||
nlohmann::json lists_array = nlohmann::json::array();
|
||||
for(const auto &l : m_last_compile_output->lists)
|
||||
{
|
||||
auto info = m_rule_collector.lists().at(l.name);
|
||||
Json::Value list;
|
||||
nlohmann::json list;
|
||||
get_json_details(list, l, *info, plugins);
|
||||
lists_array.append(list);
|
||||
lists_array.push_back(list);
|
||||
}
|
||||
output["lists"] = lists_array;
|
||||
|
||||
json_str = writer.write(output);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -631,21 +597,24 @@ void falco_engine::describe_rule(std::string *rule, const std::vector<std::share
|
||||
throw falco_exception("Rule \"" + *rule + "\" is not loaded");
|
||||
}
|
||||
auto r = m_rules.at(ri->name);
|
||||
Json::Value rule;
|
||||
|
||||
nlohmann::json rule;
|
||||
get_json_details(rule, *r, *ri, plugins);
|
||||
json_str = writer.write(rule);
|
||||
nlohmann::json rules_array = nlohmann::json::array();
|
||||
rules_array.push_back(rule);
|
||||
output["rules"] = rules_array;
|
||||
}
|
||||
|
||||
fprintf(stdout, "%s", json_str.c_str());
|
||||
return output;
|
||||
}
|
||||
|
||||
void falco_engine::get_json_details(
|
||||
Json::Value &out,
|
||||
nlohmann::json &out,
|
||||
const falco_rule &r,
|
||||
const rule_loader::rule_info &info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
|
||||
{
|
||||
Json::Value rule_info;
|
||||
nlohmann::json rule_info;
|
||||
|
||||
// Fill general rule information
|
||||
rule_info["name"] = r.name;
|
||||
@@ -665,7 +634,7 @@ void falco_engine::get_json_details(
|
||||
// get details related to the condition's filter
|
||||
filter_details details;
|
||||
filter_details compiled_details;
|
||||
Json::Value json_details;
|
||||
nlohmann::json json_details;
|
||||
for(const auto &m : m_rule_collector.macros())
|
||||
{
|
||||
details.known_macros.insert(m.name);
|
||||
@@ -726,7 +695,7 @@ void falco_engine::get_json_details(
|
||||
out["details"]["exception_operators"] = sequence_to_json_array(exception_operators);
|
||||
|
||||
// Store event types
|
||||
Json::Value events;
|
||||
nlohmann::json events;
|
||||
get_json_evt_types(events, info.source, r.condition.get());
|
||||
out["details"]["events"] = events;
|
||||
|
||||
@@ -739,7 +708,7 @@ void falco_engine::get_json_details(
|
||||
// - The fields used in the rule's condition, output, and exceptions
|
||||
// - The evt types used in the rule's condition checks, that can potentially
|
||||
// match plugin-provided async events
|
||||
Json::Value used_plugins;
|
||||
nlohmann::json used_plugins;
|
||||
// note: making a union of conditions's and output's fields
|
||||
// note: the condition's AST accounts for all the resolved refs and exceptions
|
||||
compiled_details.fields.insert(out_fields.begin(), out_fields.end());
|
||||
@@ -748,12 +717,12 @@ void falco_engine::get_json_details(
|
||||
}
|
||||
|
||||
void falco_engine::get_json_details(
|
||||
Json::Value& out,
|
||||
nlohmann::json& out,
|
||||
const falco_macro& m,
|
||||
const rule_loader::macro_info& info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
|
||||
{
|
||||
Json::Value macro_info;
|
||||
nlohmann::json macro_info;
|
||||
|
||||
macro_info["name"] = m.name;
|
||||
macro_info["condition"] = info.cond;
|
||||
@@ -766,7 +735,7 @@ void falco_engine::get_json_details(
|
||||
// get details related to the condition's filter
|
||||
filter_details details;
|
||||
filter_details compiled_details;
|
||||
Json::Value json_details;
|
||||
nlohmann::json json_details;
|
||||
for(const auto &m : m_rule_collector.macros())
|
||||
{
|
||||
details.known_macros.insert(m.name);
|
||||
@@ -787,7 +756,7 @@ void falco_engine::get_json_details(
|
||||
out["details"]["condition_fields"] = sequence_to_json_array(compiled_details.fields);
|
||||
|
||||
// Store event types
|
||||
Json::Value events;
|
||||
nlohmann::json events;
|
||||
get_json_evt_types(events, "", m.condition.get());
|
||||
out["details"]["events"] = events;
|
||||
|
||||
@@ -800,20 +769,20 @@ void falco_engine::get_json_details(
|
||||
// if a macro uses a plugin's field, we can't be sure which plugin actually
|
||||
// is used until we resolve the macro ref in a rule providing a source for
|
||||
// disambiguation.
|
||||
out["details"]["plugins"] = Json::arrayValue;
|
||||
out["details"]["plugins"] = nlohmann::json::array();
|
||||
}
|
||||
|
||||
void falco_engine::get_json_details(
|
||||
Json::Value& out,
|
||||
nlohmann::json& out,
|
||||
const falco_list& l,
|
||||
const rule_loader::list_info& info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const
|
||||
{
|
||||
Json::Value list_info;
|
||||
nlohmann::json list_info;
|
||||
list_info["name"] = l.name;
|
||||
|
||||
// note: the syntactic definitions still has the list refs unresolved
|
||||
Json::Value items = Json::arrayValue;
|
||||
nlohmann::json items = nlohmann::json::array();
|
||||
std::unordered_set<std::string> lists;
|
||||
for(const auto &i : info.items)
|
||||
{
|
||||
@@ -825,7 +794,7 @@ void falco_engine::get_json_details(
|
||||
lists.insert(i);
|
||||
continue;
|
||||
}
|
||||
items.append(i);
|
||||
items.push_back(i);
|
||||
}
|
||||
|
||||
list_info["items"] = items;
|
||||
@@ -833,11 +802,11 @@ void falco_engine::get_json_details(
|
||||
out["details"]["used"] = l.used;
|
||||
out["details"]["lists"] = sequence_to_json_array(lists);
|
||||
out["details"]["items_compiled"] = sequence_to_json_array(l.items);
|
||||
out["details"]["plugins"] = Json::arrayValue; // always empty
|
||||
out["details"]["plugins"] = nlohmann::json::array(); // always empty
|
||||
}
|
||||
|
||||
void falco_engine::get_json_evt_types(
|
||||
Json::Value& out,
|
||||
nlohmann::json& out,
|
||||
const std::string& source,
|
||||
libsinsp::filter::ast::expr* ast) const
|
||||
{
|
||||
@@ -860,7 +829,7 @@ void falco_engine::get_json_evt_types(
|
||||
}
|
||||
|
||||
void falco_engine::get_json_used_plugins(
|
||||
Json::Value& out,
|
||||
nlohmann::json& out,
|
||||
const std::string& source,
|
||||
const std::unordered_set<std::string>& evtnames,
|
||||
const std::unordered_set<std::string>& fields,
|
||||
|
@@ -136,7 +136,7 @@ public:
|
||||
// Print details on the given rule. If rule is NULL, print
|
||||
// details on all rules.
|
||||
//
|
||||
void describe_rule(std::string *rule, const std::vector<std::shared_ptr<sinsp_plugin>>& plugins, bool json) const;
|
||||
nlohmann::json describe_rule(std::string *rule, const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
|
||||
|
||||
//
|
||||
// Print statistics on how many events matched each rule.
|
||||
@@ -315,26 +315,26 @@ private:
|
||||
|
||||
// Retrieve json details from rules, macros, lists
|
||||
void get_json_details(
|
||||
Json::Value& out,
|
||||
nlohmann::json& out,
|
||||
const falco_rule& r,
|
||||
const rule_loader::rule_info& info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
|
||||
void get_json_details(
|
||||
Json::Value& out,
|
||||
nlohmann::json& out,
|
||||
const falco_macro& m,
|
||||
const rule_loader::macro_info& info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
|
||||
void get_json_details(
|
||||
Json::Value& out,
|
||||
nlohmann::json& out,
|
||||
const falco_list& l,
|
||||
const rule_loader::list_info& info,
|
||||
const std::vector<std::shared_ptr<sinsp_plugin>>& plugins) const;
|
||||
void get_json_evt_types(
|
||||
Json::Value& out,
|
||||
nlohmann::json& out,
|
||||
const std::string& source,
|
||||
libsinsp::filter::ast::expr* ast) const;
|
||||
void get_json_used_plugins(
|
||||
Json::Value& out,
|
||||
nlohmann::json& out,
|
||||
const std::string& source,
|
||||
const std::unordered_set<std::string>& evttypes,
|
||||
const std::unordered_set<std::string>& fields,
|
||||
|
@@ -20,6 +20,8 @@ limitations under the License.
|
||||
#include "../state.h"
|
||||
#include "../run_result.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace falco {
|
||||
namespace app {
|
||||
namespace actions {
|
||||
@@ -29,6 +31,8 @@ void print_enabled_event_sources(falco::app::state& s);
|
||||
void activate_interesting_kernel_tracepoints(falco::app::state& s, std::unique_ptr<sinsp>& inspector);
|
||||
void check_for_ignored_events(falco::app::state& s);
|
||||
void format_plugin_info(std::shared_ptr<sinsp_plugin> p, std::ostream& os);
|
||||
void format_described_rules_as_text(const nlohmann::json& v, std::ostream& os);
|
||||
|
||||
falco::app::run_result open_offline_inspector(falco::app::state& s);
|
||||
falco::app::run_result open_live_inspector(
|
||||
falco::app::state& s,
|
||||
|
@@ -16,6 +16,7 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
#include "helpers.h"
|
||||
#include "falco_utils.h"
|
||||
#include <plugin_manager.h>
|
||||
|
||||
#include <unordered_set>
|
||||
@@ -126,3 +127,22 @@ void falco::app::actions::format_plugin_info(std::shared_ptr<sinsp_plugin> p, st
|
||||
os << " - Async Events" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
static void format_two_columns(std::ostream& os, const std::string& l, const std::string& r)
|
||||
{
|
||||
static constexpr const int s_max_line_len = 4096;
|
||||
char buf[s_max_line_len];
|
||||
snprintf(buf, sizeof(buf) - 1, "%-50s %s", l.c_str(), r.c_str());
|
||||
os << buf << std::endl;
|
||||
}
|
||||
|
||||
void falco::app::actions::format_described_rules_as_text(const nlohmann::json& v, std::ostream& os)
|
||||
{
|
||||
format_two_columns(os, "Rule", "Description");
|
||||
format_two_columns(os, "----", "-----------");
|
||||
for(const auto &r : v["rules"])
|
||||
{
|
||||
auto str = falco::utils::wrap_text(r["info"]["description"], 51, 110) + "\n";
|
||||
format_two_columns(os, r["info"]["name"], str);
|
||||
}
|
||||
}
|
||||
|
@@ -155,17 +155,22 @@ falco::app::run_result falco::app::actions::load_rules_files(falco::app::state&
|
||||
s.engine->enable_rule_by_tag(s.options.enabled_rule_tags, true);
|
||||
}
|
||||
|
||||
if (s.options.describe_all_rules)
|
||||
// printout of `-L` option
|
||||
if (s.options.describe_all_rules || !s.options.describe_rule.empty())
|
||||
{
|
||||
std::string* rptr = !s.options.describe_rule.empty() ? &(s.options.describe_rule) : nullptr;
|
||||
const auto& plugins = s.offline_inspector->get_plugin_manager()->plugins();
|
||||
s.engine->describe_rule(NULL, plugins, s.config->m_json_output);
|
||||
return run_result::exit();
|
||||
}
|
||||
auto out = s.engine->describe_rule(rptr, plugins);
|
||||
|
||||
if (!s.config->m_json_output)
|
||||
{
|
||||
format_described_rules_as_text(out, std::cout);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << out.dump() << std::endl;
|
||||
}
|
||||
|
||||
if (!s.options.describe_rule.empty())
|
||||
{
|
||||
const auto& plugins = s.offline_inspector->get_plugin_manager()->plugins();
|
||||
s.engine->describe_rule(&(s.options.describe_rule), plugins, s.config->m_json_output);
|
||||
return run_result::exit();
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user