Use filter_fieldclass_info::as_string to print field info

Instead of having a falco-specific function to print field info, use
the built-in filter_fieldclass_info::as_string() instead. This is a
better implementation (displays addl info, has better wrapping, wider
output) and having a single implementation allows for consistent
outputs between falco and other potential programs that could use the libs.

Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
This commit is contained in:
Mark Stemm 2021-12-08 12:32:34 -08:00 committed by poiana
parent 473b94b386
commit eded1062cd
4 changed files with 52 additions and 72 deletions

View File

@ -75,12 +75,21 @@ uint32_t falco_engine::engine_version()
return (uint32_t) FALCO_ENGINE_VERSION;
}
#define DESCRIPTION_TEXT_START 16
#define CONSOLE_LINE_LEN 79
void falco_engine::list_fields(std::string &source, bool names_only)
// Return a key that uniquely represents a field class.
// For now, we assume name + shortdesc is unique.
static std::string fieldclass_key(const gen_event_filter_factory::filter_fieldclass_info &fld_info)
{
return fld_info.name + fld_info.shortdesc;
}
void falco_engine::list_fields(std::string &source, bool verbose, bool names_only)
{
// Maps from field class name + short desc to list of event
// sources for which this field class can be used.
std::map<std::string,std::set<std::string>> fieldclass_event_sources;
// Do a first pass to group together classes that are
// applicable to multiple event sources.
for(auto &it : m_filter_factories)
{
if(source != "" && source != it.first)
@ -88,51 +97,47 @@ void falco_engine::list_fields(std::string &source, bool names_only)
continue;
}
for(auto &chk_field : it.second->get_fields())
for(auto &fld_class : it.second->get_fields())
{
if(!names_only)
{
// Add some pretty printing around deesc, but if there's no desc keep
// as an empty string.
std::string desc = chk_field.desc;
if(!desc.empty())
{
desc = string(" (") + desc + ")";
}
fieldclass_event_sources[fieldclass_key(fld_class)].insert(it.first);
}
}
printf("\n----------------------\n");
printf("Field Class: %s%s\n\n", chk_field.name.c_str(), desc.c_str());
if(chk_field.class_info != "")
{
std::string str = falco::utils::wrap_text(chk_field.class_info, 0, 0, CONSOLE_LINE_LEN);
printf("%s\n", str.c_str());
}
// The set of field classes already printed. Used to avoid
// printing field classes multiple times for different sources
std::set<std::string> seen_fieldclasses;
// In the second pass, actually print info, skipping duplicate
// field classes and also printing info on supported sources.
for(auto &it : m_filter_factories)
{
if(source != "" && source != it.first)
{
continue;
}
for(auto &fld_class : it.second->get_fields())
{
std::string key = fieldclass_key(fld_class);
if(seen_fieldclasses.find(key) != seen_fieldclasses.end())
{
continue;
}
for(auto &field : chk_field.fields)
seen_fieldclasses.insert(key);
if(!names_only)
{
printf("%s", field.name.c_str());
if(names_only)
printf("%s\n", fld_class.as_string(verbose,
fieldclass_event_sources[fieldclass_key(fld_class)]).c_str());
}
else
{
for(auto &field : fld_class.fields)
{
printf("\n");
continue;
printf("%s\n", field.name.c_str());
}
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());
}
}
}

View File

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

View File

@ -27,31 +27,6 @@ namespace falco
namespace utils
{
std::string wrap_text(const std::string& str, uint32_t initial_pos, uint32_t indent, uint32_t line_len)
{
std::string ret;
size_t len = str.size();
for(uint32_t l = 0; l < len; l++)
{
if(l % (line_len - indent) == 0 && l != 0)
{
ret += "\n";
for(uint32_t m = 0; m < indent; m++)
{
ret += " ";
}
}
ret += str.at(l);
}
ret += "\n";
return ret;
}
uint32_t hardware_concurrency()
{
auto hc = std::thread::hardware_concurrency();

View File

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