mirror of
https://github.com/falcosecurity/falco.git
synced 2025-08-24 08:58:52 +00:00
refactor(falco/app): apply early return pattern in actions code
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
This commit is contained in:
parent
31c94df10e
commit
9e2c22804c
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -147,13 +147,14 @@ falco::app::run_result falco::app::actions::init_inspectors(falco::app::state& s
|
||||
std::string err;
|
||||
std::unordered_set<std::string> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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<filter_check_list>();
|
||||
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<filter_check_list>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -157,30 +157,29 @@ static void print_events(const std::vector<event_entry>& 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<ppm_event_code> 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<ppm_event_code> 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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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<std::string> 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<std::string> 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:
|
||||
//
|
||||
// <filename>: Ok
|
||||
// or
|
||||
// <filename>: 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<falco::load_result> 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:
|
||||
//
|
||||
// <filename>: Ok
|
||||
// or
|
||||
// <filename>: 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<falco::load_result> 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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user