From 91ee079ea649e00299e53313d584f74d854514bc Mon Sep 17 00:00:00 2001 From: Mark Stemm Date: Tue, 11 Jan 2022 13:36:51 -0800 Subject: [PATCH] Use swappable_falco_engine to hold falco engine Use an instance of swappable_falco_engine obj to hold the falco engine. This generally involves: - Passing around a reference to a swappable_falco_engine instead of a pointer to a falco_engine - Using swengine.engine() to access the current falco engine instead of the falco_engine pointer. Signed-off-by: Mark Stemm --- userspace/falco/falco.cpp | 68 ++++++++++++++++--------------- userspace/falco/falco_outputs.cpp | 4 +- userspace/falco/falco_outputs.h | 4 +- userspace/falco/formats.cpp | 10 ++--- userspace/falco/formats.h | 6 +-- userspace/falco/webserver.cpp | 22 ++++------ userspace/falco/webserver.h | 13 +++--- 7 files changed, 62 insertions(+), 65 deletions(-) diff --git a/userspace/falco/falco.cpp b/userspace/falco/falco.cpp index 4e55c84b..29d0a012 100644 --- a/userspace/falco/falco.cpp +++ b/userspace/falco/falco.cpp @@ -46,6 +46,7 @@ limitations under the License. #include "configuration.h" #include "falco_engine.h" #include "falco_engine_version.h" +#include "swappable_falco_engine.h" #include "config_falco.h" #include "statsfilewriter.h" #ifndef MINIMAL_BUILD @@ -209,7 +210,7 @@ std::list cmdline_options; #ifndef MINIMAL_BUILD // Read a jsonl file containing k8s audit events and pass each to the engine. -void read_k8s_audit_trace_file(falco_engine *engine, +void read_k8s_audit_trace_file(swappable_falco_engine &swengine, falco_outputs *outputs, string &trace_filename) { @@ -229,7 +230,7 @@ void read_k8s_audit_trace_file(falco_engine *engine, continue; } - if(!k8s_audit_handler::accept_data(engine, outputs, line, errstr)) + if(!k8s_audit_handler::accept_data(swengine, outputs, line, errstr)) { falco_logger::log(LOG_ERR, "Could not read k8s audit event line #" + to_string(line_num) + ", \"" + line + "\": " + errstr + ", stopping"); return; @@ -250,7 +251,7 @@ static std::string read_file(std::string filename) // // Event processing loop // -uint64_t do_inspect(falco_engine *engine, +uint64_t do_inspect(swappable_falco_engine &swengine, falco_outputs *outputs, sinsp* inspector, std::string &event_source, @@ -383,7 +384,7 @@ uint64_t do_inspect(falco_engine *engine, // engine, which will match the event against the set // of rules. If a match is found, pass the event to // the outputs. - unique_ptr res = engine->process_event(event_source, ev); + unique_ptr res = swengine.engine()->process_event(event_source, ev); if(res) { outputs->handle_event(res->evt, res->rule, res->source, res->priority_num, res->format, res->tags); @@ -436,13 +437,13 @@ static void print_all_ignored_events(sinsp *inspector) printf("\n"); } -static void check_for_ignored_events(sinsp &inspector, falco_engine &engine) +static void check_for_ignored_events(sinsp &inspector, swappable_falco_engine &swengine) { std::set evttypes; sinsp_evttables* einfo = inspector.get_event_info_tables(); const struct ppm_event_info* etable = einfo->m_event_info; - engine.evttypes_for_ruleset(syscall_source, evttypes); + swengine.engine()->evttypes_for_ruleset(syscall_source, evttypes); // Save event names so we don't warn for both the enter and exit event. std::set warn_event_names; @@ -484,14 +485,14 @@ static void check_for_ignored_events(sinsp &inspector, falco_engine &engine) } } -static void list_source_fields(falco_engine *engine, bool verbose, bool names_only, std::string &source) +static void list_source_fields(swappable_falco_engine &swengine, bool verbose, bool names_only, std::string &source) { if(source.size() > 0 && !engine->is_source_valid(source)) { throw std::invalid_argument("Value for --list must be a valid source type"); } - engine->list_fields(source, verbose, names_only); + swengine.engine()->list_fields(source, verbose, names_only); } // @@ -502,7 +503,7 @@ int falco_init(int argc, char **argv) int result = EXIT_SUCCESS; sinsp* inspector = NULL; sinsp_evt::param_fmt event_buffer_format = sinsp_evt::PF_NORMAL; - falco_engine *engine = NULL; + swappable_falco_engine swengine; falco_outputs *outputs = NULL; syscall_evt_drop_mgr sdropmgr; int op; @@ -559,7 +560,7 @@ int falco_init(int argc, char **argv) scap_stats cstats; #ifndef MINIMAL_BUILD - falco_webserver webserver; + falco_webserver webserver(swengine); falco::grpc::server grpc_server; std::thread grpc_server_thread; #endif @@ -824,8 +825,7 @@ int falco_init(int argc, char **argv) return EXIT_SUCCESS; } - engine = new falco_engine(true); - engine->set_extra(output_format, replace_container_info); + swengine.engine()->set_extra(output_format, replace_container_info); // Create "factories" that can create filters/formatters for // syscalls and k8s audit events. @@ -835,8 +835,8 @@ int falco_init(int argc, char **argv) std::shared_ptr syscall_formatter_factory(new sinsp_evt_formatter_factory(inspector)); std::shared_ptr k8s_audit_formatter_factory(new json_event_formatter_factory(k8s_audit_filter_factory)); - engine->add_source(syscall_source, syscall_filter_factory, syscall_formatter_factory); - engine->add_source(k8s_audit_source, k8s_audit_filter_factory, k8s_audit_formatter_factory); + swengine.engine()->add_source(syscall_source, syscall_filter_factory, syscall_formatter_factory); + swengine.engine()->add_source(k8s_audit_source, k8s_audit_filter_factory, k8s_audit_formatter_factory); if(disable_sources.size() > 0) { @@ -904,7 +904,7 @@ int falco_init(int argc, char **argv) // Only include the prefix if there is more than one file std::string prefix = (validate_rules_filenames.size() > 1 ? file + ": " : ""); try { - engine->load_rules_file(file, verbose, all_events); + swengine.engine()->load_rules_file(file, verbose, all_events); } catch(falco_exception &e) { @@ -983,7 +983,7 @@ int falco_init(int argc, char **argv) inspector->set_input_plugin_open_params(p.m_open_params.c_str()); } - engine->add_source(event_source, plugin_filter_factory, plugin_formatter_factory); + swengine.engine()->add_source(event_source, plugin_filter_factory, plugin_formatter_factory); } else { extractor_plugins.push_back(plugin); @@ -1057,7 +1057,7 @@ int falco_init(int argc, char **argv) if(list_flds) { - list_source_fields(engine, verbose, names_only, list_flds_source); + list_source_fields(swengine, verbose, names_only, list_flds_source); return EXIT_SUCCESS; } @@ -1066,7 +1066,7 @@ int falco_init(int argc, char **argv) config.m_rules_filenames = rules_filenames; } - engine->set_min_priority(config.m_min_priority); + swengine.engine()->set_min_priority(config.m_min_priority); if(buffered_cmdline) { @@ -1090,7 +1090,7 @@ int falco_init(int argc, char **argv) uint64_t required_engine_version; try { - engine->load_rules_file(filename, verbose, all_events, required_engine_version); + swengine.engine()->load_rules_file(filename, verbose, all_events, required_engine_version); } catch(falco_exception &e) { @@ -1106,7 +1106,7 @@ int falco_init(int argc, char **argv) { std::string required_version; - if(!engine->is_plugin_compatible(info.name, info.plugin_version.as_string(), required_version)) + if(!swengine.engine()->is_plugin_compatible(info.name, info.plugin_version.as_string(), required_version)) { throw std::invalid_argument(std::string("Plugin ") + info.name + " version " + info.plugin_version.as_string() + " not compatible with required plugin version " + required_version); } @@ -1121,7 +1121,7 @@ int falco_init(int argc, char **argv) for (auto substring : disabled_rule_substrings) { falco_logger::log(LOG_INFO, "Disabling rules matching substring: " + substring + "\n"); - engine->enable_rule(substring, false); + swengine.engine()->enable_rule(substring, false); } if(disabled_rule_tags.size() > 0) @@ -1130,7 +1130,7 @@ int falco_init(int argc, char **argv) { falco_logger::log(LOG_INFO, "Disabling rules with tag: " + tag + "\n"); } - engine->enable_rule_by_tag(disabled_rule_tags, false); + swengine.engine()->enable_rule_by_tag(disabled_rule_tags, false); } if(enabled_rule_tags.size() > 0) @@ -1138,14 +1138,19 @@ int falco_init(int argc, char **argv) // Since we only want to enable specific // rules, first disable all rules. - engine->enable_rule(all_rules, false); + swengine.engine()->enable_rule(all_rules, false); for(auto tag : enabled_rule_tags) { falco_logger::log(LOG_INFO, "Enabling rules with tag: " + tag + "\n"); } - engine->enable_rule_by_tag(enabled_rule_tags, true); + swengine.engine()->enable_rule_by_tag(enabled_rule_tags, true); } + // For syscalls, see if any event types used by the + // loaded rules are ones with the EF_DROP_SIMPLE_CONS + // label. + check_for_ignored_events(*inspector, swengine); + if(print_support) { nlohmann::json support; @@ -1223,13 +1228,13 @@ int falco_init(int argc, char **argv) if (describe_all_rules) { - engine->describe_rule(NULL); + swengine.engine()->describe_rule(NULL); goto exit; } if (describe_rule != "") { - engine->describe_rule(&describe_rule); + swengine.engine()->describe_rule(&describe_rule); goto exit; } @@ -1322,7 +1327,7 @@ int falco_init(int argc, char **argv) outputs = new falco_outputs(); - outputs->init(engine, + outputs->init(swengine, config.m_json_output, config.m_json_include_output_property, config.m_json_include_tags_property, @@ -1521,7 +1526,7 @@ int falco_init(int argc, char **argv) { std::string ssl_option = (config.m_webserver_ssl_enabled ? " (SSL)" : ""); falco_logger::log(LOG_INFO, "Starting internal webserver, listening on port " + to_string(config.m_webserver_listen_port) + ssl_option + "\n"); - webserver.init(&config, engine, outputs); + webserver.init(&config, outputs); webserver.start(); } @@ -1548,7 +1553,7 @@ int falco_init(int argc, char **argv) if(!trace_filename.empty() && !trace_is_scap) { #ifndef MINIMAL_BUILD - read_k8s_audit_trace_file(engine, + read_k8s_audit_trace_file(swengine, outputs, trace_filename); #endif @@ -1557,7 +1562,7 @@ int falco_init(int argc, char **argv) { uint64_t num_evts; - num_evts = do_inspect(engine, + num_evts = do_inspect(swengine, outputs, inspector, event_source, @@ -1596,7 +1601,7 @@ int falco_init(int argc, char **argv) } inspector->close(); - engine->print_stats(); + swengine.engine()->print_stats(); sdropmgr.print_stats(); #ifndef MINIMAL_BUILD webserver.stop(); @@ -1626,7 +1631,6 @@ int falco_init(int argc, char **argv) exit: delete inspector; - delete engine; delete outputs; return result; diff --git a/userspace/falco/falco_outputs.cpp b/userspace/falco/falco_outputs.cpp index ed38669e..75c6f702 100644 --- a/userspace/falco/falco_outputs.cpp +++ b/userspace/falco/falco_outputs.cpp @@ -60,7 +60,7 @@ falco_outputs::~falco_outputs() } } -void falco_outputs::init(falco_engine *engine, +void falco_outputs::init(swappable_falco_engine &swengine, bool json_output, bool json_include_output_property, bool json_include_tags_property, @@ -74,7 +74,7 @@ void falco_outputs::init(falco_engine *engine, throw falco_exception("falco_outputs already initialized"); } - m_formats.reset(new falco_formats(engine, json_include_output_property, json_include_tags_property)); + m_formats.reset(new falco_formats(swengine, json_include_output_property, json_include_tags_property)); m_json_output = json_output; diff --git a/userspace/falco/falco_outputs.h b/userspace/falco/falco_outputs.h index b58fbd6e..4c77cc8a 100644 --- a/userspace/falco/falco_outputs.h +++ b/userspace/falco/falco_outputs.h @@ -23,7 +23,7 @@ limitations under the License. #include "json_evt.h" #include "falco_common.h" #include "token_bucket.h" -#include "falco_engine.h" +#include "swappable_falco_engine.h" #include "outputs.h" #include "formats.h" #include "tbb/concurrent_queue.h" @@ -39,7 +39,7 @@ public: falco_outputs(); virtual ~falco_outputs(); - void init(falco_engine *engine, + void init(swappable_falco_engine &swengine, bool json_output, bool json_include_output_property, bool json_include_tags_property, diff --git a/userspace/falco/formats.cpp b/userspace/falco/formats.cpp index 58381776..df4e6502 100644 --- a/userspace/falco/formats.cpp +++ b/userspace/falco/formats.cpp @@ -17,13 +17,13 @@ limitations under the License. #include #include "formats.h" -#include "falco_engine.h" +#include "swappable_falco_engine.h" #include "banned.h" // This raises a compilation error when certain functions are used -falco_formats::falco_formats(falco_engine *engine, +falco_formats::falco_formats(swappable_falco_engine &swengine, bool json_include_output_property, bool json_include_tags_property) - : m_falco_engine(engine), + : m_swengine(swengine), m_json_include_output_property(json_include_output_property), m_json_include_tags_property(json_include_tags_property) { @@ -40,7 +40,7 @@ string falco_formats::format_event(gen_event *evt, const std::string &rule, cons std::shared_ptr formatter; - formatter = m_falco_engine->create_formatter(source, format); + formatter = m_swengine.engine()->create_formatter(source, format); // Format the original output string, regardless of output format formatter->tostring_withformat(evt, line, gen_event_formatter::OF_NORMAL); @@ -134,7 +134,7 @@ map falco_formats::get_field_values(gen_event *evt, const std::s { std::shared_ptr formatter; - formatter = m_falco_engine->create_formatter(source, format); + formatter = m_swengine.engine()->create_formatter(source, format); map ret; diff --git a/userspace/falco/formats.h b/userspace/falco/formats.h index 2424c0cf..cceff90d 100644 --- a/userspace/falco/formats.h +++ b/userspace/falco/formats.h @@ -28,12 +28,12 @@ extern "C" #include -#include "falco_engine.h" +#include "swappable_falco_engine.h" class falco_formats { public: - falco_formats(falco_engine *engine, + falco_formats(swappable_falco_engine &swengine, bool json_include_output_property, bool json_include_tags_property); virtual ~falco_formats(); @@ -45,7 +45,7 @@ public: const std::string &format); protected: - falco_engine *m_falco_engine; + swappable_falco_engine &m_swengine; bool m_json_include_output_property; bool m_json_include_tags_property; }; diff --git a/userspace/falco/webserver.cpp b/userspace/falco/webserver.cpp index 6405d0ca..80a54545 100644 --- a/userspace/falco/webserver.cpp +++ b/userspace/falco/webserver.cpp @@ -27,8 +27,8 @@ using namespace std; string k8s_audit_handler::m_k8s_audit_event_source = "k8s_audit"; -k8s_audit_handler::k8s_audit_handler(falco_engine *engine, falco_outputs *outputs): - m_engine(engine), m_outputs(outputs) +k8s_audit_handler::k8s_audit_handler(swappable_falco_engine &swengine, falco_outputs *outputs): + m_swengine(swengine), m_outputs(outputs) { } @@ -45,7 +45,7 @@ bool k8s_healthz_handler::handleGet(CivetServer *server, struct mg_connection *c return true; } -bool k8s_audit_handler::accept_data(falco_engine *engine, +bool k8s_audit_handler::accept_data(swappable_falco_engine &swengine, falco_outputs *outputs, std::string &data, std::string &errstr) @@ -89,7 +89,7 @@ bool k8s_audit_handler::accept_data(falco_engine *engine, try { - res = engine->process_event(m_k8s_audit_event_source, &jev); + res = swengine.engine()->process_event(m_k8s_audit_event_source, &jev); } catch(...) { @@ -120,7 +120,7 @@ bool k8s_audit_handler::accept_data(falco_engine *engine, bool k8s_audit_handler::accept_uploaded_data(std::string &post_data, std::string &errstr) { - return k8s_audit_handler::accept_data(m_engine, m_outputs, post_data, errstr); + return k8s_audit_handler::accept_data(m_swengine, m_outputs, post_data, errstr); } bool k8s_audit_handler::handleGet(CivetServer *server, struct mg_connection *conn) @@ -177,7 +177,8 @@ bool k8s_audit_handler::handlePost(CivetServer *server, struct mg_connection *co return true; } -falco_webserver::falco_webserver(): +falco_webserver::falco_webserver(swappable_falco_engine &swengine): + m_swengine(swengine), m_config(NULL) { } @@ -188,11 +189,9 @@ falco_webserver::~falco_webserver() } void falco_webserver::init(falco_configuration *config, - falco_engine *engine, falco_outputs *outputs) { m_config = config; - m_engine = engine; m_outputs = outputs; } @@ -214,11 +213,6 @@ void falco_webserver::start() throw falco_exception("No config provided to webserver"); } - if(!m_engine) - { - throw falco_exception("No engine provided to webserver"); - } - if(!m_outputs) { throw falco_exception("No outputs provided to webserver"); @@ -253,7 +247,7 @@ void falco_webserver::start() throw falco_exception("Could not create embedded webserver"); } - m_k8s_audit_handler = make_unique(m_engine, m_outputs); + m_k8s_audit_handler = make_unique(m_swengine, m_outputs); m_server->addHandler(m_config->m_webserver_k8s_audit_endpoint, *m_k8s_audit_handler); m_k8s_healthz_handler = make_unique(); m_server->addHandler(m_config->m_webserver_k8s_healthz_endpoint, *m_k8s_healthz_handler); diff --git a/userspace/falco/webserver.h b/userspace/falco/webserver.h index c7310cb7..db120e0b 100644 --- a/userspace/falco/webserver.h +++ b/userspace/falco/webserver.h @@ -19,26 +19,26 @@ limitations under the License. #include "CivetServer.h" #include "configuration.h" -#include "falco_engine.h" +#include "swappable_falco_engine.h" #include "falco_outputs.h" class k8s_audit_handler : public CivetHandler { public: - k8s_audit_handler(falco_engine *engine, falco_outputs *outputs); + k8s_audit_handler(swappable_falco_engine &swengine, falco_outputs *outputs); virtual ~k8s_audit_handler(); bool handleGet(CivetServer *server, struct mg_connection *conn); bool handlePost(CivetServer *server, struct mg_connection *conn); - static bool accept_data(falco_engine *engine, + static bool accept_data(swappable_falco_engine &swengine, falco_outputs *outputs, std::string &post_data, std::string &errstr); static std::string m_k8s_audit_event_source; private: - falco_engine *m_engine; + swappable_falco_engine &m_swengine; falco_outputs *m_outputs; bool accept_uploaded_data(std::string &post_data, std::string &errstr); }; @@ -60,18 +60,17 @@ public: class falco_webserver { public: - falco_webserver(); + falco_webserver(swappable_falco_engine &swengine); virtual ~falco_webserver(); void init(falco_configuration *config, - falco_engine *engine, falco_outputs *outputs); void start(); void stop(); private: - falco_engine *m_engine; + swappable_falco_engine &m_swengine; falco_configuration *m_config; falco_outputs *m_outputs; unique_ptr m_server;