From eded1062cd11426448dffe6f0266372aa5fd84f7 Mon Sep 17 00:00:00 2001 From: Mark Stemm Date: Wed, 8 Dec 2021 12:32:34 -0800 Subject: [PATCH] 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 --- userspace/engine/falco_engine.cpp | 91 ++++++++++++++++--------------- userspace/engine/falco_engine.h | 2 +- userspace/engine/falco_utils.cpp | 25 --------- userspace/falco/falco.cpp | 6 +- 4 files changed, 52 insertions(+), 72 deletions(-) diff --git a/userspace/engine/falco_engine.cpp b/userspace/engine/falco_engine.cpp index 3ff29e3f..b3228e99 100644 --- a/userspace/engine/falco_engine.cpp +++ b/userspace/engine/falco_engine.cpp @@ -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> 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 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()); } } } diff --git a/userspace/engine/falco_engine.h b/userspace/engine/falco_engine.h index fd13c109..d3ba3728 100644 --- a/userspace/engine/falco_engine.h +++ b/userspace/engine/falco_engine.h @@ -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. diff --git a/userspace/engine/falco_utils.cpp b/userspace/engine/falco_utils.cpp index 2468f905..05f3c6bd 100644 --- a/userspace/engine/falco_utils.cpp +++ b/userspace/engine/falco_utils.cpp @@ -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(); diff --git a/userspace/falco/falco.cpp b/userspace/falco/falco.cpp index 6fc70e8d..9abd76e9 100644 --- a/userspace/falco/falco.cpp +++ b/userspace/falco/falco.cpp @@ -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; }