mirror of
https://github.com/falcosecurity/falco.git
synced 2025-07-31 22:16:49 +00:00
refactor(userspace/falco): generalize responsibilities of init_inspector action
Now, the action takes care of inizializing all app inspectors (just one in capture mode, one for each evt source in live mode), and of registering and initializing all loaded plugins in the right inspector as needed. The plugin initialization logic, which also involves the filtercheck list population and checks, was moved and refactored from the previous implementation of the load_plugins action. Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
This commit is contained in:
parent
ed025f1a86
commit
f9a152b24c
@ -15,44 +15,187 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
#include "application.h"
|
||||
#include <unordered_set>
|
||||
#include <plugin_manager.h>
|
||||
|
||||
using namespace falco::app;
|
||||
|
||||
application::run_result application::init_inspector()
|
||||
static void init_syscall_inspector(
|
||||
std::shared_ptr<sinsp> inspector,
|
||||
const falco::app::cmdline_options& opts)
|
||||
{
|
||||
m_state->inspector->set_buffer_format(m_options.event_buffer_format);
|
||||
inspector->set_buffer_format(opts.event_buffer_format);
|
||||
|
||||
// If required, set the CRI paths
|
||||
for (auto &p : m_options.cri_socket_paths)
|
||||
for (auto &p : opts.cri_socket_paths)
|
||||
{
|
||||
if (!p.empty())
|
||||
{
|
||||
m_state->inspector->add_cri_socket_path(p);
|
||||
inspector->add_cri_socket_path(p);
|
||||
}
|
||||
}
|
||||
|
||||
// Decide whether to do sync or async for CRI metadata fetch
|
||||
m_state->inspector->set_cri_async(!m_options.disable_cri_async);
|
||||
inspector->set_cri_async(!opts.disable_cri_async);
|
||||
|
||||
//
|
||||
// If required, set the snaplen
|
||||
//
|
||||
if(m_options.snaplen != 0)
|
||||
if(opts.snaplen != 0)
|
||||
{
|
||||
m_state->inspector->set_snaplen(m_options.snaplen);
|
||||
inspector->set_snaplen(opts.snaplen);
|
||||
}
|
||||
|
||||
if(!m_options.all_events)
|
||||
if(!opts.all_events)
|
||||
{
|
||||
// Drop EF_DROP_SIMPLE_CONS kernel side
|
||||
m_state->inspector->set_simple_consumer();
|
||||
inspector->set_simple_consumer();
|
||||
// Eventually, drop any EF_DROP_SIMPLE_CONS event
|
||||
// that reached userspace (there are some events that are not syscall-based
|
||||
// like signaldeliver, that have the EF_DROP_SIMPLE_CONS flag)
|
||||
m_state->inspector->set_drop_event_flags(EF_DROP_SIMPLE_CONS);
|
||||
inspector->set_drop_event_flags(EF_DROP_SIMPLE_CONS);
|
||||
}
|
||||
|
||||
m_state->inspector->set_hostname_and_port_resolution_mode(false);
|
||||
inspector->set_hostname_and_port_resolution_mode(false);
|
||||
}
|
||||
|
||||
static bool populate_filterchecks(
|
||||
std::shared_ptr<sinsp> inspector,
|
||||
const std::string& source,
|
||||
filter_check_list& filterchecks,
|
||||
std::unordered_set<std::string>& used_plugins,
|
||||
std::string& err)
|
||||
{
|
||||
std::vector<const filter_check_info*> info;
|
||||
for(const auto& p : inspector->get_plugin_manager()->plugins())
|
||||
{
|
||||
if (!(p->caps() & CAP_EXTRACTION))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if some fields are overlapping on this event sources
|
||||
info.clear();
|
||||
filterchecks.get_all_fields(info);
|
||||
for (auto &info : info)
|
||||
{
|
||||
for (int32_t i = 0; i < info->m_nfields; i++)
|
||||
{
|
||||
// check if one of the fields extractable by the plugin
|
||||
// is already provided by another filtercheck for this source
|
||||
std::string fname = info->m_fields[i].m_name;
|
||||
for (auto &f : p->fields())
|
||||
{
|
||||
if (std::string(f.m_name) == fname)
|
||||
{
|
||||
err = "Plugin '" + p->name()
|
||||
+ "' supports extraction of field '" + fname
|
||||
+ "' that is overlapping for source '" + source + "'";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add plugin filterchecks to the event source
|
||||
filterchecks.add_filter_check(sinsp_plugin::new_filtercheck(p));
|
||||
used_plugins.insert(p->name());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// todo(XXX): rename this to init_inspectors()
|
||||
application::run_result application::init_inspector()
|
||||
{
|
||||
std::string err;
|
||||
std::unordered_set<std::string> used_plugins;
|
||||
const auto& all_plugins = m_state->offline_inspector->get_plugin_manager()->plugins();
|
||||
|
||||
for (const auto &src : m_state->loaded_sources)
|
||||
{
|
||||
auto src_info = m_state->sources.at(src);
|
||||
|
||||
// in capture mode, every event source uses the offline inspector.
|
||||
// in live mode, we create a new inspector for each event source
|
||||
src_info->inspector = is_capture_mode()
|
||||
? m_state->offline_inspector
|
||||
: std::make_shared<sinsp>();
|
||||
|
||||
// handle syscall and plugin sources differently
|
||||
// todo(jasondellaluce): change this once we support extracting plugin fields from syscalls too
|
||||
if (src == falco_common::syscall_source)
|
||||
{
|
||||
init_syscall_inspector(src_info->inspector, m_options);
|
||||
continue;
|
||||
}
|
||||
|
||||
// load and init all plugins compatible with this event source
|
||||
// (if in capture mode, all plugins will be inited on the same inspector)
|
||||
for (const auto& p : all_plugins)
|
||||
{
|
||||
std::shared_ptr<sinsp_plugin> plugin = nullptr;
|
||||
auto config = m_state->plugin_configs.at(p->name());
|
||||
auto is_input = p->caps() & CAP_SOURCING && p->event_source() == src;
|
||||
|
||||
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
|
||||
if (is_input || (p->caps() & CAP_EXTRACTION && p->is_source_compatible(src)))
|
||||
{
|
||||
plugin = src_info->inspector->register_plugin(config->m_library_path);
|
||||
}
|
||||
}
|
||||
|
||||
// init the plugin, if we registered it into an inspector
|
||||
// (in capture mode, this is true for every plugin)
|
||||
if (plugin)
|
||||
{
|
||||
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(gen_check);
|
||||
}
|
||||
used_plugins.insert(plugin->name());
|
||||
}
|
||||
}
|
||||
|
||||
// populate filtercheck list for this inspector
|
||||
if (!populate_filterchecks(
|
||||
src_info->inspector,
|
||||
src,
|
||||
src_info->filterchecks,
|
||||
used_plugins,
|
||||
err))
|
||||
{
|
||||
return run_result::fatal(err);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// check if some plugin with field extraction capability remains unused
|
||||
for (const auto& p : all_plugins)
|
||||
{
|
||||
if(used_plugins.find(p->name()) == used_plugins.end()
|
||||
&& p->caps() & CAP_EXTRACTION
|
||||
&& !(p->caps() & CAP_SOURCING && p->is_source_compatible(p->event_source())))
|
||||
{
|
||||
return run_result::fatal("Plugin '" + p->name()
|
||||
+ "' has field extraction capability but is not compatible with any known event source");
|
||||
}
|
||||
}
|
||||
|
||||
return run_result::ok();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user