diff --git a/userspace/falco/app/actions/init_falco_engine.cpp b/userspace/falco/app/actions/init_falco_engine.cpp index effdc788..0f91fc93 100644 --- a/userspace/falco/app/actions/init_falco_engine.cpp +++ b/userspace/falco/app/actions/init_falco_engine.cpp @@ -170,14 +170,15 @@ falco::app::run_result falco::app::actions::init_falco_engine(falco::app::state& if(s.is_capture_mode()) { auto manager = s.offline_inspector->get_plugin_manager(); for(const auto& p : manager->plugins()) { - if(p->caps() & CAP_SOURCING && p->id() != 0) { - bool added = false; - auto source_idx = manager->source_idx_by_plugin_id(p->id(), added); - auto engine_idx = s.source_infos.at(p->event_source())->engine_idx; - if(!added || source_idx != engine_idx) { - return run_result::fatal("Could not add event source in the engine: " + - p->event_source()); - } + if((p->caps() & CAP_SOURCING) == 0 || p->id() == 0) { + continue; + } + bool added = false; + auto source_idx = manager->source_idx_by_plugin_id(p->id(), added); + auto engine_idx = s.source_infos.at(p->event_source())->engine_idx; + if(!added || source_idx != engine_idx) { + return run_result::fatal("Could not add event source in the engine: " + + p->event_source()); } } } diff --git a/userspace/falco/app/actions/init_inspectors.cpp b/userspace/falco/app/actions/init_inspectors.cpp index c1aeb752..203bc232 100644 --- a/userspace/falco/app/actions/init_inspectors.cpp +++ b/userspace/falco/app/actions/init_inspectors.cpp @@ -147,13 +147,14 @@ falco::app::run_result falco::app::actions::init_inspectors(falco::app::state& s std::string err; std::unordered_set used_plugins; const auto& all_plugins = s.offline_inspector->get_plugin_manager()->plugins(); + const bool is_capture_mode = s.is_capture_mode(); for(const auto& src : s.loaded_sources) { auto src_info = s.source_infos.at(src); // in capture mode, every event source uses the offline inspector. // in live mode, we create a new inspector for each event source - if(s.is_capture_mode()) { + if(is_capture_mode) { src_info->inspector = s.offline_inspector; } else { src_info->inspector = @@ -174,15 +175,16 @@ falco::app::run_result falco::app::actions::init_inspectors(falco::app::state& s ((p->id() != 0 && src == p->event_source()) || (p->id() == 0 && src == falco_common::syscall_source)); - if(s.is_capture_mode()) { + if(is_capture_mode) { // in capture mode, every plugin is already registered // in the offline inspector by the load_plugins action plugin = p; } else { - // in live mode, for the inspector assigned to the given - // event source, we must register the plugin supporting - // that event source and also plugins with field extraction - // capability that are compatible with that event source + // in live mode, for the inspector assigned to the given event source, we must + // register a plugin if one of the following condition applies to it: + // - it has event sourcing capability for the given event source + // - it has one among field extraction, event parsing and async events capabilities + // and is compatible (with respect to that capability) with the given event source if(is_input || (p->caps() & CAP_EXTRACTION && sinsp_plugin::is_source_compatible(p->extract_event_sources(), src)) || @@ -194,22 +196,23 @@ falco::app::run_result falco::app::actions::init_inspectors(falco::app::state& s } } - // init the plugin, if we registered it into an inspector - // (in capture mode, this is true for every plugin) - if(plugin) { - // avoid initializing the same plugin twice in the same - // inspector if we're in capture mode - if(!s.is_capture_mode() || used_plugins.find(p->name()) == used_plugins.end()) { - if(!plugin->init(config->m_init_config, err)) { - return run_result::fatal(err); - } - } - if(is_input) { - auto gen_check = src_info->inspector->new_generic_filtercheck(); - src_info->filterchecks->add_filter_check(std::move(gen_check)); - } - used_plugins.insert(plugin->name()); + if(!plugin) { + continue; } + + // init the plugin only if we registered it into an inspector (in capture mode, this is + // true for every plugin). Avoid initializing the same plugin twice in the same + // inspector if we're in capture mode + if(!is_capture_mode || used_plugins.find(p->name()) == used_plugins.end()) { + if(!plugin->init(config->m_init_config, err)) { + return run_result::fatal(err); + } + } + if(is_input) { + auto gen_check = src_info->inspector->new_generic_filtercheck(); + src_info->filterchecks->add_filter_check(std::move(gen_check)); + } + used_plugins.insert(plugin->name()); } // populate filtercheck list for this inspector @@ -221,20 +224,22 @@ falco::app::run_result falco::app::actions::init_inspectors(falco::app::state& s return run_result::fatal(err); } - // in live mode, each inspector should have registered at most two event sources: - // the "syscall" on, loaded at default at index 0, and optionally another - // one defined by a plugin, at index 1 - if(!s.is_capture_mode()) { - const auto& sources = src_info->inspector->event_sources(); - if(sources.size() == 0 || sources.size() > 2 || - sources[0] != falco_common::syscall_source) { - err.clear(); - for(const auto& source : sources) { - err += (err.empty() ? "" : ", ") + source; - } - return run_result::fatal("Illegal sources setup in live inspector for source '" + - src + "': " + err); + if(is_capture_mode) { + continue; + } + + // in live mode, each inspector should have registered at most two event sources: the + // "syscall" on, loaded at default at index 0, and optionally another one defined by a + // plugin, at index 1 + const auto& sources = src_info->inspector->event_sources(); + if(sources.size() == 0 || sources.size() > 2 || + sources[0] != falco_common::syscall_source) { + err.clear(); + for(const auto& source : sources) { + err += (err.empty() ? "" : ", ") + source; } + return run_result::fatal("Illegal sources setup in live inspector for source '" + src + + "': " + err); } } diff --git a/userspace/falco/app/actions/list_fields.cpp b/userspace/falco/app/actions/list_fields.cpp index 5e63998d..23999009 100644 --- a/userspace/falco/app/actions/list_fields.cpp +++ b/userspace/falco/app/actions/list_fields.cpp @@ -21,17 +21,18 @@ using namespace falco::app; using namespace falco::app::actions; falco::app::run_result falco::app::actions::list_fields(falco::app::state& s) { - if(s.options.list_fields) { - if(s.options.list_source_fields != "" && - !s.engine->is_source_valid(s.options.list_source_fields)) { - return run_result::fatal("Value for --list must be a valid source type"); - } - s.engine->list_fields(s.options.list_source_fields, - s.options.verbose, - s.options.names_only, - s.options.markdown); - return run_result::exit(); + if(!s.options.list_fields) { + return run_result::ok(); } - return run_result::ok(); + if(s.options.list_source_fields != "" && + !s.engine->is_source_valid(s.options.list_source_fields)) { + return run_result::fatal("Value for --list must be a valid source type"); + } + + s.engine->list_fields(s.options.list_source_fields, + s.options.verbose, + s.options.names_only, + s.options.markdown); + return run_result::exit(); } diff --git a/userspace/falco/app/actions/list_plugins.cpp b/userspace/falco/app/actions/list_plugins.cpp index 7a782873..3587c8ee 100644 --- a/userspace/falco/app/actions/list_plugins.cpp +++ b/userspace/falco/app/actions/list_plugins.cpp @@ -24,20 +24,20 @@ using namespace falco::app; using namespace falco::app::actions; falco::app::run_result falco::app::actions::list_plugins(const falco::app::state& s) { - if(s.options.list_plugins) { - std::ostringstream os; - sinsp inspector; - const auto& configs = s.config->m_plugins; - for(auto& c : configs) { - // load the plugin (no need to initialize it) - auto plugin = inspector.register_plugin(c.m_library_path); - format_plugin_info(plugin, os); - os << std::endl; - } - - printf("%lu Plugins Loaded:\n\n%s\n", configs.size(), os.str().c_str()); - return run_result::exit(); + if(!s.options.list_plugins) { + return run_result::ok(); } - return run_result::ok(); + std::ostringstream os; + sinsp inspector; + const auto& configs = s.config->m_plugins; + for(auto& c : configs) { + // load the plugin (no need to initialize it) + auto plugin = inspector.register_plugin(c.m_library_path); + format_plugin_info(plugin, os); + os << std::endl; + } + + printf("%lu Plugins Loaded:\n\n%s\n", configs.size(), os.str().c_str()); + return run_result::exit(); } diff --git a/userspace/falco/app/actions/load_plugins.cpp b/userspace/falco/app/actions/load_plugins.cpp index 3f14fe80..b64d0145 100644 --- a/userspace/falco/app/actions/load_plugins.cpp +++ b/userspace/falco/app/actions/load_plugins.cpp @@ -51,16 +51,18 @@ falco::app::run_result falco::app::actions::load_plugins(falco::app::state& s) { "Loading plugin '" + p.m_name + "' from file " + p.m_library_path + "\n"); auto plugin = s.offline_inspector->register_plugin(p.m_library_path); s.plugin_configs.insert(p, plugin->name()); - if(plugin->caps() & CAP_SOURCING && plugin->id() != 0) { - state::source_info src_info; - src_info.filterchecks = std::make_shared(); - auto sname = plugin->event_source(); - s.source_infos.insert(src_info, sname); - // note: this avoids duplicate values - if(std::find(s.loaded_sources.begin(), s.loaded_sources.end(), sname) == - s.loaded_sources.end()) { - s.loaded_sources.push_back(sname); - } + if((plugin->caps() & CAP_SOURCING) == 0 || plugin->id() == 0) { + continue; + } + // Account the plugin event source + state::source_info src_info; + src_info.filterchecks = std::make_shared(); + auto src_name = plugin->event_source(); + s.source_infos.insert(src_info, src_name); + // note: this avoids duplicate values + if(std::find(s.loaded_sources.begin(), s.loaded_sources.end(), src_name) == + s.loaded_sources.end()) { + s.loaded_sources.push_back(src_name); } } diff --git a/userspace/falco/app/actions/pidfile.cpp b/userspace/falco/app/actions/pidfile.cpp index 6bdfad8f..c062f750 100644 --- a/userspace/falco/app/actions/pidfile.cpp +++ b/userspace/falco/app/actions/pidfile.cpp @@ -30,21 +30,23 @@ falco::app::run_result falco::app::actions::pidfile(const falco::app::state& sta return run_result::ok(); } - if(!state.options.pidfilename.empty()) { - int64_t self_pid = getpid(); - - std::ofstream stream; - stream.open(state.options.pidfilename); - - if(!stream.good()) { - falco_logger::log( - falco_logger::level::ERR, - "Could not write pid to pidfile " + state.options.pidfilename + ". Exiting.\n"); - exit(-1); - } - stream << self_pid; - stream.close(); + if(state.options.pidfilename.empty()) { + return run_result::ok(); } + int64_t self_pid = getpid(); + + std::ofstream stream; + stream.open(state.options.pidfilename); + + if(!stream.good()) { + falco_logger::log( + falco_logger::level::ERR, + "Could not write pid to pidfile " + state.options.pidfilename + ". Exiting.\n"); + exit(-1); + } + stream << self_pid; + stream.close(); + return run_result::ok(); } diff --git a/userspace/falco/app/actions/print_config_schema.cpp b/userspace/falco/app/actions/print_config_schema.cpp index 06c261a9..bc75d884 100644 --- a/userspace/falco/app/actions/print_config_schema.cpp +++ b/userspace/falco/app/actions/print_config_schema.cpp @@ -21,9 +21,10 @@ using namespace falco::app; using namespace falco::app::actions; falco::app::run_result falco::app::actions::print_config_schema(falco::app::state &s) { - if(s.options.print_config_schema) { - printf("%s", s.config->m_config_schema.dump(2).c_str()); - return run_result::exit(); + if(!s.options.print_config_schema) { + return run_result::ok(); } - return run_result::ok(); + + printf("%s", s.config->m_config_schema.dump(2).c_str()); + return run_result::exit(); } diff --git a/userspace/falco/app/actions/print_generated_gvisor_config.cpp b/userspace/falco/app/actions/print_generated_gvisor_config.cpp index cc23e5c5..5ca72b65 100644 --- a/userspace/falco/app/actions/print_generated_gvisor_config.cpp +++ b/userspace/falco/app/actions/print_generated_gvisor_config.cpp @@ -22,12 +22,13 @@ using namespace falco::app; using namespace falco::app::actions; falco::app::run_result falco::app::actions::print_generated_gvisor_config(falco::app::state& s) { - if(!s.options.gvisor_generate_config_with_socket.empty()) { - sinsp i; - std::string gvisor_config = - i.generate_gvisor_config(s.options.gvisor_generate_config_with_socket); - printf("%s\n", gvisor_config.c_str()); - return run_result::exit(); + if(s.options.gvisor_generate_config_with_socket.empty()) { + return run_result::ok(); } - return run_result::ok(); + + sinsp i; + std::string gvisor_config = + i.generate_gvisor_config(s.options.gvisor_generate_config_with_socket); + printf("%s\n", gvisor_config.c_str()); + return run_result::exit(); } diff --git a/userspace/falco/app/actions/print_help.cpp b/userspace/falco/app/actions/print_help.cpp index a553cafe..df4e67bb 100644 --- a/userspace/falco/app/actions/print_help.cpp +++ b/userspace/falco/app/actions/print_help.cpp @@ -21,9 +21,10 @@ using namespace falco::app; using namespace falco::app::actions; falco::app::run_result falco::app::actions::print_help(falco::app::state& s) { - if(s.options.help) { - printf("%s", s.options.usage().c_str()); - return run_result::exit(); + if(!s.options.help) { + return run_result::ok(); } - return run_result::ok(); + + printf("%s", s.options.usage().c_str()); + return run_result::exit(); } diff --git a/userspace/falco/app/actions/print_kernel_version.cpp b/userspace/falco/app/actions/print_kernel_version.cpp index 9db5946c..1705a527 100644 --- a/userspace/falco/app/actions/print_kernel_version.cpp +++ b/userspace/falco/app/actions/print_kernel_version.cpp @@ -28,22 +28,25 @@ using namespace falco::app::actions; falco::app::run_result falco::app::actions::print_kernel_version(const falco::app::state& s) { #ifdef __linux__ // We print this info only when a kernel driver is injected - if(s.is_modern_ebpf() || s.is_ebpf() || s.is_kmod()) { - std::ifstream input_file("/proc/version"); - if(!input_file.is_open()) { - // We don't want to fail, we just need to log something - falco_logger::log(falco_logger::level::INFO, - "Cannot read under '/proc/version' (err_message: '" + - std::string(strerror(errno)) + "', err_code: " + - std::to_string(errno) + "). No info provided, go on."); - return run_result::ok(); - } - - std::stringstream buffer; - buffer << input_file.rdbuf(); - std::string contents(buffer.str()); - falco_logger::log(falco_logger::level::INFO, "System info: " + contents); + bool const is_kernel_driver_injected = s.is_modern_ebpf() || s.is_ebpf() || s.is_kmod(); + if(!is_kernel_driver_injected) { + return run_result::ok(); } + + std::ifstream input_file("/proc/version"); + if(!input_file.is_open()) { + // We don't want to fail, we just need to log something + falco_logger::log( + falco_logger::level::INFO, + "Cannot read under '/proc/version' (err_message: '" + std::string(strerror(errno)) + + "', err_code: " + std::to_string(errno) + "). No info provided, go on."); + return run_result::ok(); + } + + std::stringstream buffer; + buffer << input_file.rdbuf(); + std::string contents(buffer.str()); + falco_logger::log(falco_logger::level::INFO, "System info: " + contents); #endif return run_result::ok(); } diff --git a/userspace/falco/app/actions/print_page_size.cpp b/userspace/falco/app/actions/print_page_size.cpp index 2dd8c11f..1c44642c 100644 --- a/userspace/falco/app/actions/print_page_size.cpp +++ b/userspace/falco/app/actions/print_page_size.cpp @@ -24,25 +24,24 @@ using namespace falco::app; using namespace falco::app::actions; falco::app::run_result falco::app::actions::print_page_size(const falco::app::state& s) { - if(s.options.print_page_size) { -#ifndef _WIN32 - long page_size = getpagesize(); -#else - SYSTEM_INFO sysInfo; - - GetSystemInfo(&sysInfo); - - long page_size = sysInfo.dwPageSize; -#endif - if(page_size <= 0) { - return run_result::fatal( - "\nUnable to get the system page size through 'getpagesize()'\n"); - } else { - falco_logger::log( - falco_logger::level::INFO, - "Your system page size is: " + std::to_string(page_size) + " bytes\n"); - } - return run_result::exit(); + if(!s.options.print_page_size) { + return run_result::ok(); } - return run_result::ok(); + +#ifndef _WIN32 + long page_size = getpagesize(); +#else + SYSTEM_INFO sysInfo; + + GetSystemInfo(&sysInfo); + + long page_size = sysInfo.dwPageSize; +#endif + if(page_size <= 0) { + return run_result::fatal("\nUnable to get the system page size through 'getpagesize()'\n"); + } + + falco_logger::log(falco_logger::level::INFO, + "Your system page size is: " + std::to_string(page_size) + " bytes\n"); + return run_result::exit(); } diff --git a/userspace/falco/app/actions/print_plugin_info.cpp b/userspace/falco/app/actions/print_plugin_info.cpp index 3f080a35..565f7e84 100644 --- a/userspace/falco/app/actions/print_plugin_info.cpp +++ b/userspace/falco/app/actions/print_plugin_info.cpp @@ -24,78 +24,81 @@ using namespace falco::app; using namespace falco::app::actions; falco::app::run_result falco::app::actions::print_plugin_info(const falco::app::state &s) { - if(!s.options.print_plugin_info.empty()) { - sinsp inspector; - for(auto &pc : s.config->m_plugins) { - if(pc.m_name == s.options.print_plugin_info || - pc.m_library_path == s.options.print_plugin_info) { - // load the plugin - auto p = 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(const 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: " + - s.options.print_plugin_info); + if(s.options.print_plugin_info.empty()) { + return run_result::ok(); } - return run_result::ok(); + sinsp inspector; + for(auto &pc : s.config->m_plugins) { + if(pc.m_name != s.options.print_plugin_info && + pc.m_library_path != s.options.print_plugin_info) { + continue; + } + + // found matching plugin; load it + auto p = 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(const 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: " + + s.options.print_plugin_info); } diff --git a/userspace/falco/app/actions/print_rule_schema.cpp b/userspace/falco/app/actions/print_rule_schema.cpp index 23de26b2..f2010f4f 100644 --- a/userspace/falco/app/actions/print_rule_schema.cpp +++ b/userspace/falco/app/actions/print_rule_schema.cpp @@ -21,9 +21,10 @@ using namespace falco::app; using namespace falco::app::actions; falco::app::run_result falco::app::actions::print_rule_schema(falco::app::state &s) { - if(s.options.print_rule_schema) { - printf("%s", s.engine->m_rule_schema.dump(2).c_str()); - return run_result::exit(); + if(!s.options.print_rule_schema) { + return run_result::ok(); } - return run_result::ok(); + + printf("%s", s.engine->m_rule_schema.dump(2).c_str()); + return run_result::exit(); } diff --git a/userspace/falco/app/actions/print_support.cpp b/userspace/falco/app/actions/print_support.cpp index 3471f5ae..96ab2abb 100644 --- a/userspace/falco/app/actions/print_support.cpp +++ b/userspace/falco/app/actions/print_support.cpp @@ -88,31 +88,30 @@ static int get_sysinfo(nlohmann::json& support) { #endif falco::app::run_result falco::app::actions::print_support(falco::app::state& s) { - if(s.options.print_support) { - nlohmann::json support; - - if(get_sysinfo(support) != 0) { - return run_result::fatal(std::string("Could not get system info: ") + strerror(errno)); - } - - const falco::versions_info infos(s.offline_inspector); - support["version"] = infos.falco_version; - support["engine_info"] = infos.as_json(); - support["cmdline"] = s.cmdline; - support["config"] = s.config->dump(); - support["rules_files"] = nlohmann::json::array(); - for(const auto& filename : s.config->m_loaded_rules_filenames) { - nlohmann::json finfo; - finfo["name"] = filename; - nlohmann::json variant; - variant["content"] = read_file(filename); - finfo["variants"].push_back(variant); - support["rules_files"].push_back(finfo); - } - printf("%s\n", support.dump().c_str()); - - return run_result::exit(); + if(!s.options.print_support) { + return run_result::ok(); } - return run_result::ok(); + nlohmann::json support; + + if(get_sysinfo(support) != 0) { + return run_result::fatal(std::string("Could not get system info: ") + strerror(errno)); + } + + const falco::versions_info infos(s.offline_inspector); + support["version"] = infos.falco_version; + support["engine_info"] = infos.as_json(); + support["cmdline"] = s.cmdline; + support["config"] = s.config->dump(); + support["rules_files"] = nlohmann::json::array(); + for(const auto& filename : s.config->m_loaded_rules_filenames) { + nlohmann::json finfo; + finfo["name"] = filename; + nlohmann::json variant; + variant["content"] = read_file(filename); + finfo["variants"].push_back(variant); + support["rules_files"].push_back(finfo); + } + printf("%s\n", support.dump().c_str()); + return run_result::exit(); } diff --git a/userspace/falco/app/actions/print_syscall_events.cpp b/userspace/falco/app/actions/print_syscall_events.cpp index 7f21293f..ee93f90c 100644 --- a/userspace/falco/app/actions/print_syscall_events.cpp +++ b/userspace/falco/app/actions/print_syscall_events.cpp @@ -157,30 +157,29 @@ static void print_events(const std::vector& events, bool markdown) } falco::app::run_result falco::app::actions::print_syscall_events(falco::app::state& s) { - if(s.options.list_syscall_events) { - const falco::versions_info info(s.offline_inspector); - printf("The events below are valid for Falco *Schema Version*: %s\n", - info.driver_schema_version.c_str()); - - const libsinsp::events::set available = - libsinsp::events::all_event_set().diff( - sc_set_to_event_set(falco::app::ignored_sc_set())); - const struct events_by_category events_bc = get_event_entries_by_category(true, available); - - printf("## Syscall events\n\n"); - print_events(events_bc.syscalls, s.options.markdown); - - printf("\n\n## Tracepoint events\n\n"); - print_events(events_bc.tracepoints, s.options.markdown); - - printf("\n\n## Plugin events\n\n"); - print_events(events_bc.pluginevents, s.options.markdown); - - printf("\n\n## Metaevents\n\n"); - print_events(events_bc.metaevents, s.options.markdown); - - return run_result::exit(); + if(!s.options.list_syscall_events) { + return run_result::ok(); } - return run_result::ok(); + const falco::versions_info info(s.offline_inspector); + printf("The events below are valid for Falco *Schema Version*: %s\n", + info.driver_schema_version.c_str()); + + const libsinsp::events::set available = libsinsp::events::all_event_set().diff( + sc_set_to_event_set(falco::app::ignored_sc_set())); + const struct events_by_category events_bc = get_event_entries_by_category(true, available); + + printf("## Syscall events\n\n"); + print_events(events_bc.syscalls, s.options.markdown); + + printf("\n\n## Tracepoint events\n\n"); + print_events(events_bc.tracepoints, s.options.markdown); + + printf("\n\n## Plugin events\n\n"); + print_events(events_bc.pluginevents, s.options.markdown); + + printf("\n\n## Metaevents\n\n"); + print_events(events_bc.metaevents, s.options.markdown); + + return run_result::exit(); } diff --git a/userspace/falco/app/actions/print_version.cpp b/userspace/falco/app/actions/print_version.cpp index bc3b8efc..9f58635b 100644 --- a/userspace/falco/app/actions/print_version.cpp +++ b/userspace/falco/app/actions/print_version.cpp @@ -22,22 +22,22 @@ using namespace falco::app; using namespace falco::app::actions; falco::app::run_result falco::app::actions::print_version(falco::app::state& s) { - if(s.options.print_version_info) { - const falco::versions_info info(s.offline_inspector); - if(s.config->m_json_output) { - printf("%s\n", info.as_json().dump().c_str()); - } else { - printf("Falco version: %s\n", info.falco_version.c_str()); - printf("Libs version: %s\n", info.libs_version.c_str()); - printf("Plugin API: %s\n", info.plugin_api_version.c_str()); - printf("Engine: %s\n", info.engine_version.c_str()); - printf("Driver:\n"); - printf(" API version: %s\n", info.driver_api_version.c_str()); - printf(" Schema version: %s\n", info.driver_schema_version.c_str()); - printf(" Default driver: %s\n", info.default_driver_version.c_str()); - } - return run_result::exit(); + if(!s.options.print_version_info) { + return run_result::ok(); } - return run_result::ok(); + const falco::versions_info info(s.offline_inspector); + if(s.config->m_json_output) { + printf("%s\n", info.as_json().dump().c_str()); + } else { + printf("Falco version: %s\n", info.falco_version.c_str()); + printf("Libs version: %s\n", info.libs_version.c_str()); + printf("Plugin API: %s\n", info.plugin_api_version.c_str()); + printf("Engine: %s\n", info.engine_version.c_str()); + printf("Driver:\n"); + printf(" API version: %s\n", info.driver_api_version.c_str()); + printf(" Schema version: %s\n", info.driver_schema_version.c_str()); + printf(" Default driver: %s\n", info.default_driver_version.c_str()); + } + return run_result::exit(); } diff --git a/userspace/falco/app/actions/start_grpc_server.cpp b/userspace/falco/app/actions/start_grpc_server.cpp index a0ce78ea..4ef7a0a4 100644 --- a/userspace/falco/app/actions/start_grpc_server.cpp +++ b/userspace/falco/app/actions/start_grpc_server.cpp @@ -27,44 +27,46 @@ using namespace falco::app::actions; falco::app::run_result falco::app::actions::start_grpc_server(falco::app::state& s) { #if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD) // gRPC server - if(s.config->m_grpc_enabled) { - if(s.options.dry_run) { - falco_logger::log(falco_logger::level::DEBUG, - "Skipping starting gRPC server in dry-run\n"); - return run_result::ok(); - } - - falco_logger::log(falco_logger::level::INFO, - "gRPC server threadiness equals to " + - std::to_string(s.config->m_grpc_threadiness) + "\n"); - // TODO(fntlnz,leodido): when we want to spawn multiple threads we need to have a queue per - // thread, or implement different queuing mechanisms, round robin, fanout? What we want to - // achieve? - s.grpc_server.init(s.config->m_grpc_bind_address, - s.config->m_grpc_threadiness, - s.config->m_grpc_private_key, - s.config->m_grpc_cert_chain, - s.config->m_grpc_root_certs, - s.config->m_log_level); - s.grpc_server_thread = std::thread([&s] { s.grpc_server.run(); }); + if(!s.config->m_grpc_enabled) { + return run_result::ok(); } + + if(s.options.dry_run) { + falco_logger::log(falco_logger::level::DEBUG, "Skipping starting gRPC server in dry-run\n"); + return run_result::ok(); + } + + falco_logger::log(falco_logger::level::INFO, + "gRPC server threadiness equals to " + + std::to_string(s.config->m_grpc_threadiness) + "\n"); + // TODO(fntlnz,leodido): when we want to spawn multiple threads we need to have a queue per + // thread, or implement different queuing mechanisms, round robin, fanout? What we want to + // achieve? + s.grpc_server.init(s.config->m_grpc_bind_address, + s.config->m_grpc_threadiness, + s.config->m_grpc_private_key, + s.config->m_grpc_cert_chain, + s.config->m_grpc_root_certs, + s.config->m_log_level); + s.grpc_server_thread = std::thread([&s] { s.grpc_server.run(); }); #endif return run_result::ok(); } falco::app::run_result falco::app::actions::stop_grpc_server(falco::app::state& s) { #if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD) - if(s.config->m_grpc_enabled) { - if(s.options.dry_run) { - falco_logger::log(falco_logger::level::DEBUG, - "Skipping stopping gRPC server in dry-run\n"); - return run_result::ok(); - } + if(!s.config->m_grpc_enabled) { + return run_result::ok(); + } - if(s.grpc_server_thread.joinable()) { - s.grpc_server.shutdown(); - s.grpc_server_thread.join(); - } + if(s.options.dry_run) { + falco_logger::log(falco_logger::level::DEBUG, "Skipping stopping gRPC server in dry-run\n"); + return run_result::ok(); + } + + if(s.grpc_server_thread.joinable()) { + s.grpc_server.shutdown(); + s.grpc_server_thread.join(); } #endif return run_result::ok(); diff --git a/userspace/falco/app/actions/start_webserver.cpp b/userspace/falco/app/actions/start_webserver.cpp index df4d91ff..ce725b76 100644 --- a/userspace/falco/app/actions/start_webserver.cpp +++ b/userspace/falco/app/actions/start_webserver.cpp @@ -26,39 +26,40 @@ using namespace falco::app::actions; falco::app::run_result falco::app::actions::start_webserver(falco::app::state& state) { #if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD) - if(!state.is_capture_mode() && state.config->m_webserver_enabled) { - if(state.options.dry_run) { - falco_logger::log(falco_logger::level::DEBUG, - "Skipping starting webserver in dry-run\n"); - return run_result::ok(); - } - - falco_configuration::webserver_config webserver_config = state.config->m_webserver_config; - std::string ssl_option = (webserver_config.m_ssl_enabled ? " (SSL)" : ""); - falco_logger::log(falco_logger::level::INFO, - "Starting health webserver with threadiness " + - std::to_string(webserver_config.m_threadiness) + - ", listening on " + webserver_config.m_listen_address + ":" + - std::to_string(webserver_config.m_listen_port) + ssl_option + - "\n"); - - state.webserver.start(state, webserver_config); + if(state.is_capture_mode() || !state.config->m_webserver_enabled) { + return run_result::ok(); } + + if(state.options.dry_run) { + falco_logger::log(falco_logger::level::DEBUG, "Skipping starting webserver in dry-run\n"); + return run_result::ok(); + } + + falco_configuration::webserver_config webserver_config = state.config->m_webserver_config; + std::string ssl_option = (webserver_config.m_ssl_enabled ? " (SSL)" : ""); + falco_logger::log(falco_logger::level::INFO, + "Starting health webserver with threadiness " + + std::to_string(webserver_config.m_threadiness) + ", listening on " + + webserver_config.m_listen_address + ":" + + std::to_string(webserver_config.m_listen_port) + ssl_option + "\n"); + + state.webserver.start(state, webserver_config); #endif return run_result::ok(); } falco::app::run_result falco::app::actions::stop_webserver(falco::app::state& state) { #if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD) - if(!state.is_capture_mode() && state.config->m_webserver_enabled) { - if(state.options.dry_run) { - falco_logger::log(falco_logger::level::DEBUG, - "Skipping stopping webserver in dry-run\n"); - return run_result::ok(); - } - - state.webserver.stop(); + if(state.is_capture_mode() || !state.config->m_webserver_enabled) { + return run_result::ok(); } + + if(state.options.dry_run) { + falco_logger::log(falco_logger::level::DEBUG, "Skipping stopping webserver in dry-run\n"); + return run_result::ok(); + } + + state.webserver.stop(); #endif return run_result::ok(); } diff --git a/userspace/falco/app/actions/validate_rules_files.cpp b/userspace/falco/app/actions/validate_rules_files.cpp index 9e6f6be2..a49e8a50 100644 --- a/userspace/falco/app/actions/validate_rules_files.cpp +++ b/userspace/falco/app/actions/validate_rules_files.cpp @@ -26,115 +26,113 @@ using namespace falco::app; using namespace falco::app::actions; falco::app::run_result falco::app::actions::validate_rules_files(falco::app::state& s) { - if(s.options.validate_rules_filenames.size() > 0) { - std::vector rules_contents; - falco::load_result::rules_contents_t rc; + if(s.options.validate_rules_filenames.size() == 0) { + return run_result::ok(); + } - try { - read_files(s.options.validate_rules_filenames.begin(), - s.options.validate_rules_filenames.end(), - rules_contents, - rc); - } catch(falco_exception& e) { - return run_result::fatal(e.what()); + std::vector rules_contents; + falco::load_result::rules_contents_t rc; + + try { + read_files(s.options.validate_rules_filenames.begin(), + s.options.validate_rules_filenames.end(), + rules_contents, + rc); + } catch(falco_exception& e) { + return run_result::fatal(e.what()); + } + + bool successful = true; + + // The validation result is *always* printed to + // stdout. When json_output is true, the output is in + // json format and contains all errors/warnings for + // all files. + // + + // When json_output is false, it contains a summary of + // each file and whether it was valid or not, along + // with any errors. To match older falco behavior, + // this *only* contains errors. + // + // So for each file stdout will contain: + // + // : Ok + // or + // : Invalid + // [All Validation Errors] + // + // Warnings are only printed to stderr, and only + // printed when verbose is true. + std::string summary; + + falco_logger::log(falco_logger::level::INFO, "Validating rules file(s):\n"); + for(const auto& file : s.options.validate_rules_filenames) { + falco_logger::log(falco_logger::level::INFO, " " + file + "\n"); + } + + // The json output encompasses all files so the + // validation result is a single json object. + std::string err = ""; + nlohmann::json results = nlohmann::json::array(); + + for(auto& filename : s.options.validate_rules_filenames) { + std::unique_ptr res; + + res = s.engine->load_rules(rc.at(filename), filename); + if(!check_rules_plugin_requirements(s, err)) { + return run_result::fatal(err); } - bool successful = true; - - // The validation result is *always* printed to - // stdout. When json_output is true, the output is in - // json format and contains all errors/warnings for - // all files. - // - - // When json_output is false, it contains a summary of - // each file and whether it was valid or not, along - // with any errors. To match older falco behavior, - // this *only* contains errors. - // - // So for each file stdout will contain: - // - // : Ok - // or - // : Invalid - // [All Validation Errors] - // - // Warnings are only printed to stderr, and only - // printed when verbose is true. - std::string summary; - - falco_logger::log(falco_logger::level::INFO, "Validating rules file(s):\n"); - for(const auto& file : s.options.validate_rules_filenames) { - falco_logger::log(falco_logger::level::INFO, " " + file + "\n"); - } - - // The json output encompasses all files so the - // validation result is a single json object. - std::string err = ""; - nlohmann::json results = nlohmann::json::array(); - - for(auto& filename : s.options.validate_rules_filenames) { - std::unique_ptr res; - - res = s.engine->load_rules(rc.at(filename), filename); - if(!check_rules_plugin_requirements(s, err)) { - return run_result::fatal(err); - } - - successful &= res->successful(); - - if(s.config->m_json_output) { - results.push_back(res->as_json(rc)); - } - - if(summary != "") { - summary += "\n"; - } - - // Add to the summary if not successful, or successful - // with no warnings. - if(!res->successful() || (res->successful() && !res->has_warnings())) { - summary += res->as_string(true, rc); - } else { - // If here, there must be only warnings. - // Add a line to the summary noting that the - // file was ok with warnings, without actually - // printing the warnings. - summary += filename + ": Ok, with warnings"; - falco_logger::log(falco_logger::level::WARNING, res->as_string(true, rc) + "\n"); - } - } - - // printout of `-L` option - nlohmann::json describe_res; - if(successful && (s.options.describe_all_rules || !s.options.describe_rule.empty())) { - std::string* rptr = - !s.options.describe_rule.empty() ? &(s.options.describe_rule) : nullptr; - const auto& plugins = s.offline_inspector->get_plugin_manager()->plugins(); - describe_res = s.engine->describe_rule(rptr, plugins); - } + successful &= res->successful(); if(s.config->m_json_output) { - nlohmann::json res; - res["falco_load_results"] = results; - if(!describe_res.empty() && successful) { - res["falco_describe_results"] = std::move(describe_res); - } - std::cout << res.dump() << std::endl; - } else { - std::cout << summary << std::endl; - if(!describe_res.empty() && successful) { - std::cout << std::endl; - format_described_rules_as_text(describe_res, std::cout); - } + results.push_back(res->as_json(rc)); } - if(successful) { - return run_result::exit(); + if(summary != "") { + summary += "\n"; + } + + // Add to the summary if not successful, or successful + // with no warnings. + if(!res->successful() || (res->successful() && !res->has_warnings())) { + summary += res->as_string(true, rc); } else { - return run_result::fatal(summary); + // If here, there must be only warnings. + // Add a line to the summary noting that the + // file was ok with warnings, without actually + // printing the warnings. + summary += filename + ": Ok, with warnings"; + falco_logger::log(falco_logger::level::WARNING, res->as_string(true, rc) + "\n"); } } - return run_result::ok(); + // printout of `-L` option + nlohmann::json describe_res; + if(successful && (s.options.describe_all_rules || !s.options.describe_rule.empty())) { + std::string* rptr = !s.options.describe_rule.empty() ? &(s.options.describe_rule) : nullptr; + const auto& plugins = s.offline_inspector->get_plugin_manager()->plugins(); + describe_res = s.engine->describe_rule(rptr, plugins); + } + + if(s.config->m_json_output) { + nlohmann::json res; + res["falco_load_results"] = results; + if(!describe_res.empty() && successful) { + res["falco_describe_results"] = std::move(describe_res); + } + std::cout << res.dump() << std::endl; + } else { + std::cout << summary << std::endl; + if(!describe_res.empty() && successful) { + std::cout << std::endl; + format_described_rules_as_text(describe_res, std::cout); + } + } + + if(!successful) { + return run_result::fatal(summary); + } + return run_result::exit(); }