diff --git a/userspace/falco/CMakeLists.txt b/userspace/falco/CMakeLists.txt index fd6582bf..00eeaba5 100644 --- a/userspace/falco/CMakeLists.txt +++ b/userspace/falco/CMakeLists.txt @@ -32,6 +32,7 @@ set( app_actions/process_events.cpp app_actions/print_help.cpp app_actions/print_ignored_events.cpp + app_actions/print_plugin_info.cpp app_actions/print_support.cpp app_actions/print_version.cpp app_actions/start_grpc_server.cpp diff --git a/userspace/falco/app_actions/list_plugins.cpp b/userspace/falco/app_actions/list_plugins.cpp index 3e61ce04..e409fe35 100644 --- a/userspace/falco/app_actions/list_plugins.cpp +++ b/userspace/falco/app_actions/list_plugins.cpp @@ -27,21 +27,7 @@ application::run_result application::list_plugins() const auto &plugins = m_state->inspector->get_plugin_manager()->plugins(); for (auto &p : plugins) { - os << "Name: " << p->name() << std::endl; - os << "Description: " << p->description() << std::endl; - os << "Contact: " << p->contact() << std::endl; - os << "Version: " << p->plugin_version().as_string() << std::endl; - os << "Capabilities: " << std::endl; - if(p->caps() & CAP_SOURCING) - { - os << " - Event Sourcing (ID=" << p->id(); - os << ", source='" << p->event_source() << "')" << std::endl; - } - if(p->caps() & CAP_EXTRACTION) - { - os << " - Field Extraction" << std::endl; - } - + format_plugin_info(p, os); os << std::endl; } diff --git a/userspace/falco/app_actions/print_plugin_info.cpp b/userspace/falco/app_actions/print_plugin_info.cpp new file mode 100644 index 00000000..ba6a2950 --- /dev/null +++ b/userspace/falco/app_actions/print_plugin_info.cpp @@ -0,0 +1,130 @@ +/* +Copyright (C) 2022 The Falco Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "application.h" +#include + +using namespace falco::app; + +void application::format_plugin_info(std::shared_ptr p, std::ostream& os) const +{ + os << "Name: " << p->name() << std::endl; + os << "Description: " << p->description() << std::endl; + os << "Contact: " << p->contact() << std::endl; + os << "Version: " << p->plugin_version().as_string() << std::endl; + os << "Capabilities: " << std::endl; + if(p->caps() & CAP_SOURCING) + { + os << " - Event Sourcing (ID=" << p->id(); + os << ", source='" << p->event_source() << "')" << std::endl; + } + if(p->caps() & CAP_EXTRACTION) + { + os << " - Field Extraction" << std::endl; + } +} + +application::run_result application::print_plugin_info() +{ +#ifdef MUSL_OPTIMIZED + if(!m_options.print_plugin_info.empty()) + { + return run_result::fatal("Can not load or use plugins with musl optimized build"); + } +#else // MUSL_OPTIMIZED + if(!m_options.print_plugin_info.empty()) + { + for(auto &pc : m_state->config->m_plugins) + { + if (pc.m_name == m_options.print_plugin_info + || pc.m_library_path == m_options.print_plugin_info) + { + // load the plugin + auto p = m_state->inspector->register_plugin(pc.m_library_path); + + // print plugin descriptive info + std::ostringstream os; + format_plugin_info(p, os); + os << std::endl; + printf("%s", os.str().c_str()); + + // print plugin init schema + os.str(""); + os.clear(); + ss_plugin_schema_type type; + auto schema = p->get_init_schema(type); + os << "Init config schema type: "; + switch (type) + { + case SS_PLUGIN_SCHEMA_JSON: + os << "JSON" << std::endl; + break; + case SS_PLUGIN_SCHEMA_NONE: + default: + os << "Not available, plugin does not implement the init config schema functionality" << std::endl; + break; + } + os << schema << std::endl; + os << std::endl; + printf("%s", os.str().c_str()); + + // init the plugin + std::string err; + if (!p->init(pc.m_init_config, err)) + { + return run_result::fatal(err); + } + + // print plugin suggested open parameters + if (p->caps() & CAP_SOURCING) + { + os.str(""); + os.clear(); + auto params = p->list_open_params(); + if (params.empty()) + { + os << "No suggested open params available: "; + os << "plugin has not been configured, or it does not implement the open params suggestion functionality" << std::endl; + } + else + { + os << "Suggested open params:" << std::endl; + for(auto &oparam : p->list_open_params()) + { + if(oparam.desc == "") + { + os << oparam.value << std::endl; + } + else + { + os << oparam.value << ": " << oparam.desc << std::endl; + } + } + } + os << std::endl; + printf("%s", os.str().c_str()); + } + + // exit + return run_result::exit(); + } + } + return run_result::fatal("can't find plugin and print its info: " + m_options.print_plugin_info); + } +#endif // MUSL_OPTIMIZED + + return run_result::ok(); +} \ No newline at end of file diff --git a/userspace/falco/app_cmdline_options.cpp b/userspace/falco/app_cmdline_options.cpp index 7f028ea6..a41b27de 100644 --- a/userspace/falco/app_cmdline_options.cpp +++ b/userspace/falco/app_cmdline_options.cpp @@ -182,6 +182,7 @@ void cmdline_options::define() ("markdown", "When used with --list/--list-syscall-events, print the content in Markdown format", cxxopts::value(markdown)) ("N", "When used with --list, only print field names.", cxxopts::value(names_only)->default_value("false")) ("o,option", "Set the value of option to . Overrides values in configuration file. can be identified using its location in configuration file using dot notation. Elements which are entries of lists can be accessed via square brackets [].\n E.g. base.id = val\n base.subvalue.subvalue2 = val\n base.list[1]=val", cxxopts::value(cmdline_config_options), "=") + ("plugin-info", "Print info for a single plugin and exit.\nThis includes all descriptivo info like name and author, along with the\nschema format for the init configuration and a list of suggested open parameters.\n can be the name of the plugin or its configured library_path.", cxxopts::value(print_plugin_info), "") ("p,print", "Add additional information to each falco notification's output.\nWith -pc or -pcontainer will use a container-friendly format.\nWith -pk or -pkubernetes will use a kubernetes-friendly format.\nWith -pm or -pmesos will use a mesos-friendly format.\nAdditionally, specifying -pc/-pk/-pm will change the interpretation of %container.info in rule output fields.", cxxopts::value(print_additional), "") ("P,pidfile", "When run as a daemon, write pid to specified file", cxxopts::value(pidfilename)->default_value("/var/run/falco.pid"), "") ("r", "Rules file/directory (defaults to value set in configuration file, or /etc/falco_rules.yaml). Can be specified multiple times to read from multiple files/directories.", cxxopts::value>(), "") diff --git a/userspace/falco/app_cmdline_options.h b/userspace/falco/app_cmdline_options.h index 1228483b..f3d0af33 100644 --- a/userspace/falco/app_cmdline_options.h +++ b/userspace/falco/app_cmdline_options.h @@ -52,6 +52,7 @@ public: bool list_fields; std::string list_source_fields; bool list_plugins; + std::string print_plugin_info; bool list_syscall_events; bool markdown; std::string mesos_api; diff --git a/userspace/falco/application.cpp b/userspace/falco/application.cpp index dedce1e4..489b9de4 100644 --- a/userspace/falco/application.cpp +++ b/userspace/falco/application.cpp @@ -128,6 +128,7 @@ bool application::run(std::string &errstr, bool &restart) std::bind(&application::create_signal_handlers, this), std::bind(&application::load_config, this), std::bind(&application::init_inspector, this), + std::bind(&application::print_plugin_info, this), std::bind(&application::load_plugins, this), std::bind(&application::init_falco_engine, this), std::bind(&application::list_fields, this), diff --git a/userspace/falco/application.h b/userspace/falco/application.h index 4756c399..3556cd33 100644 --- a/userspace/falco/application.h +++ b/userspace/falco/application.h @@ -153,6 +153,7 @@ private: run_result open_inspector(); run_result print_help(); run_result print_ignored_events(); + run_result print_plugin_info(); run_result print_support(); run_result print_version(); run_result process_events(); @@ -176,6 +177,7 @@ private: void configure_output_format(); void check_for_ignored_events(); void print_all_ignored_events(); + void format_plugin_info(std::shared_ptr p, std::ostream& os) const; run_result do_inspect(syscall_evt_drop_mgr &sdropmgr, uint64_t duration_to_tot_ns, uint64_t &num_events);