General-purpose list_fields(), via factories

Take advantage of the changes in
https://github.com/falcosecurity/libs/pull/75 to have a
general-purpose way to list fields for a given event source.

in the engine, list_fields() now takes a source, iterates over filter
factories, and calls get_fields() for each factory, printing the results.

list_source_fields now calls the engine regardless of source.

Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
This commit is contained in:
Mark Stemm 2021-08-25 16:48:02 -07:00 committed by poiana
parent 3202921355
commit 943a37fcf7
5 changed files with 96 additions and 60 deletions

View File

@ -85,61 +85,61 @@ uint32_t falco_engine::engine_version()
#define CONSOLE_LINE_LEN 79 #define CONSOLE_LINE_LEN 79
void falco_engine::list_fields(bool names_only) void falco_engine::list_fields(std::string &source, bool names_only)
{ {
for(auto &chk_field : json_factory().get_fields()) for(auto &it : m_filter_factories)
{ {
if(!names_only) if(source != "" && source != it.first)
{ {
printf("\n----------------------\n"); continue;
printf("Field Class: %s (%s)\n\n", chk_field.m_name.c_str(), chk_field.m_desc.c_str());
if(chk_field.m_class_info != "")
{
std::string str = falco::utils::wrap_text(chk_field.m_class_info, 0, 0, CONSOLE_LINE_LEN);
printf("%s\n", str.c_str());
}
} }
for(auto &field : chk_field.m_fields) for(auto &chk_field : it.second->get_fields())
{ {
printf("%s", field.m_name.c_str()); if(!names_only)
if(names_only)
{ {
printf("\n"); // Add some pretty printing around deesc, but if there's no desc keep
continue; // as an empty string.
} std::string desc = chk_field.desc;
uint32_t namelen = field.m_name.size(); if(!desc.empty())
{
desc = string(" (") + desc + ")";
}
if(namelen >= DESCRIPTION_TEXT_START) printf("\n----------------------\n");
{ printf("Field Class: %s%s\n\n", chk_field.name.c_str(), desc.c_str());
printf("\n"); if(chk_field.class_info != "")
namelen = 0; {
std::string str = falco::utils::wrap_text(chk_field.class_info, 0, 0, CONSOLE_LINE_LEN);
printf("%s\n", str.c_str());
}
} }
for(uint32_t l = 0; l < DESCRIPTION_TEXT_START - namelen; l++) for(auto &field : chk_field.fields)
{ {
printf(" "); printf("%s", field.name.c_str());
if(names_only)
{
printf("\n");
continue;
}
uint32_t namelen = field.name.size();
if(namelen >= DESCRIPTION_TEXT_START)
{
printf("\n");
namelen = 0;
}
for(uint32_t l = 0; l < DESCRIPTION_TEXT_START - namelen; l++)
{
printf(" ");
}
std::string str = falco::utils::wrap_text(field.desc, namelen, DESCRIPTION_TEXT_START, CONSOLE_LINE_LEN);
printf("%s\n", str.c_str());
} }
std::string desc = field.m_desc;
switch(field.m_idx_mode)
{
case json_event_filter_check::IDX_REQUIRED:
case json_event_filter_check::IDX_ALLOWED:
desc += " (";
desc += json_event_filter_check::s_index_mode_strs[field.m_idx_mode];
desc += ", ";
desc += json_event_filter_check::s_index_type_strs[field.m_idx_type];
desc += ")";
break;
case json_event_filter_check::IDX_NONE:
default:
break;
};
std::string str = falco::utils::wrap_text(desc, namelen, DESCRIPTION_TEXT_START, CONSOLE_LINE_LEN);
printf("%s\n", str.c_str());
} }
} }
} }

View File

@ -57,7 +57,8 @@ public:
static uint32_t engine_version(); static uint32_t engine_version();
// Print to stdout (using printf) a description of each field supported by this engine. // Print to stdout (using printf) a description of each field supported by this engine.
void list_fields(bool names_only=false); // If source is non-empty, only fields for the provided source are printed.
void list_fields(std::string &source, bool names_only);
// //
// Load rules either directly or from a filename. // Load rules either directly or from a filename.

View File

@ -690,7 +690,7 @@ size_t json_event_filter_check::parsed_size()
} }
} }
json_event_filter_check::check_info &json_event_filter_check::get_fields() json_event_filter_check::check_info &json_event_filter_check::get_info()
{ {
return m_info; return m_info;
} }
@ -1432,7 +1432,7 @@ json_event_filter_factory::json_event_filter_factory()
for(auto &chk : m_defined_checks) for(auto &chk : m_defined_checks)
{ {
m_info.push_back(chk->get_fields()); m_info.push_back(chk->get_info());
} }
} }
@ -1464,9 +1464,51 @@ gen_event_filter_check *json_event_filter_factory::new_filtercheck(const char *f
return NULL; return NULL;
} }
std::list<json_event_filter_check::check_info> &json_event_filter_factory::get_fields() std::list<gen_event_filter_factory::filter_fieldclass_info> json_event_filter_factory::get_fields()
{ {
return m_info; std::list<gen_event_filter_factory::filter_fieldclass_info> ret;
// It's not quite copy to the public information, as m_info
// has addl info about indexing. That info is added to the
// description.
for(auto &chk: m_defined_checks)
{
json_event_filter_check::check_info &info = chk->get_info();
gen_event_filter_factory::filter_fieldclass_info cinfo;
cinfo.name = info.m_name;
cinfo.desc = info.m_desc;
cinfo.class_info = info.m_class_info;
for(auto &field : info.m_fields)
{
gen_event_filter_factory::filter_field_info info;
info.name = field.m_name;
info.desc = field.m_desc;
switch(field.m_idx_mode)
{
case json_event_filter_check::IDX_REQUIRED:
case json_event_filter_check::IDX_ALLOWED:
info.desc += " (";
info.desc += json_event_filter_check::s_index_mode_strs[field.m_idx_mode];
info.desc += ", ";
info.desc += json_event_filter_check::s_index_type_strs[field.m_idx_type];
info.desc += ")";
break;
case json_event_filter_check::IDX_NONE:
default:
break;
};
cinfo.fields.emplace_back(std::move(info));
}
ret.emplace_back(std::move(cinfo));
}
return ret;
} }
json_event_formatter::json_event_formatter(json_event_filter_factory &json_factory, std::string &format): json_event_formatter::json_event_formatter(json_event_filter_factory &json_factory, std::string &format):

View File

@ -189,7 +189,7 @@ public:
// brackets (e.g. ka.image[foo]) // brackets (e.g. ka.image[foo])
size_t parsed_size(); size_t parsed_size();
check_info &get_fields(); check_info &get_info();
// //
// Allocate a new check of the same type. Must be overridden. // Allocate a new check of the same type. Must be overridden.
@ -399,7 +399,7 @@ public:
gen_event_filter_check *new_filtercheck(const char *fldname); gen_event_filter_check *new_filtercheck(const char *fldname);
// All defined field names // All defined field names
std::list<json_event_filter_check::check_info> &get_fields(); std::list<gen_event_filter_factory::filter_fieldclass_info> get_fields();
private: private:
std::list<std::shared_ptr<json_event_filter_check>> m_defined_checks; std::list<std::shared_ptr<json_event_filter_check>> m_defined_checks;

View File

@ -424,21 +424,14 @@ static void print_all_ignored_events(sinsp *inspector)
printf("\n"); printf("\n");
} }
static void list_source_fields(falco_engine *engine, bool verbose, bool names_only, std::string &source) static void list_source_fields(falco_engine *engine, bool names_only, std::string &source)
{ {
if(source.size() > 0 && if(source.size() > 0 &&
!(source == "syscall" || source == "k8s_audit")) !(source == "syscall" || source == "k8s_audit"))
{ {
throw std::invalid_argument("Value for --list must be \"syscall\" or \"k8s_audit\""); throw std::invalid_argument("Value for --list must be \"syscall\" or \"k8s_audit\"");
} }
if(source == "" || source == "syscall") engine->list_fields(source, names_only);
{
list_fields(verbose, false, names_only);
}
if(source == "" || source == "k8s_audit")
{
engine->list_fields(names_only);
}
} }
// //
@ -781,7 +774,7 @@ int falco_init(int argc, char **argv)
if(list_flds) if(list_flds)
{ {
list_source_fields(engine, verbose, names_only, list_flds_source); list_source_fields(engine, names_only, list_flds_source);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }