mirror of
https://github.com/falcosecurity/falco.git
synced 2025-09-07 17:54:07 +00:00
update(userspace/engine): introduce new check_plugin_requirements
API
Signed-off-by: Andrea Terzolo <andrea.terzolo@polito.it>
This commit is contained in:
@@ -82,7 +82,7 @@ trace_files: !mux
|
||||
|
||||
incompat_plugin_rules_version:
|
||||
exit_status: 1
|
||||
stderr_contains: "Plugin cloudtrail version .* not compatible with required plugin version 100000.0.0."
|
||||
stderr_contains: "Plugin 'cloudtrail' version '.*' is not compatible with required plugin version '100000.0.0'"
|
||||
conf_file: BUILD_DIR/test/confs/plugins/cloudtrail_json_create_instances.yaml
|
||||
rules_file:
|
||||
- rules/plugins/cloudtrail_incompat_plugin_version.yaml
|
||||
|
@@ -430,11 +430,47 @@ bool falco_engine::is_source_valid(const std::string &source)
|
||||
return (find_ruleset(source) != m_rulesets.end());
|
||||
}
|
||||
|
||||
bool falco_engine::is_plugin_compatible(const std::string &name,
|
||||
const std::string &version,
|
||||
std::string &required_version)
|
||||
bool falco_engine::check_plugin_requirements(
|
||||
const std::vector<plugin_version_requirement>& plugins,
|
||||
std::string& err)
|
||||
{
|
||||
return m_rule_loader.is_plugin_compatible(name, version, required_version);
|
||||
for (const auto &req : m_rule_loader.required_plugin_versions())
|
||||
{
|
||||
bool found = false;
|
||||
for (const auto &plugin : plugins)
|
||||
{
|
||||
if (req.first == plugin.name)
|
||||
{
|
||||
found = true;
|
||||
sinsp_version plugin_version(plugin.version);
|
||||
if(!plugin_version.m_valid)
|
||||
{
|
||||
err = "Plugin '" + req.first
|
||||
+ "' has invalid version string '"
|
||||
+ plugin.version + "'";
|
||||
return false;
|
||||
}
|
||||
for (const auto &reqver: req.second)
|
||||
{
|
||||
sinsp_version req_version(reqver);
|
||||
if (!plugin_version.check(req_version))
|
||||
{
|
||||
err = "Plugin '" + plugin.name
|
||||
+ "' version '" + plugin.version
|
||||
+ "' is not compatible with required plugin version '"
|
||||
+ reqver + "'";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
err = "Plugin '" + req.first + "' is required but not loaded";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void falco_engine::clear_filters()
|
||||
|
@@ -222,11 +222,19 @@ public:
|
||||
std::shared_ptr<gen_event_formatter> create_formatter(const std::string &source,
|
||||
const std::string &output);
|
||||
|
||||
// Return whether the provided plugin name + version is
|
||||
// compatible with the current set of loaded rules files.
|
||||
// required_version will be filled in with the required
|
||||
// version when the method returns false.
|
||||
bool is_plugin_compatible(const std::string &name, const std::string &version, std::string &required_version);
|
||||
// The rule loader definition is aliased as it is exactly what we need
|
||||
typedef rule_loader::plugin_version_info plugin_version_requirement;
|
||||
|
||||
//
|
||||
// Returns true if the provided list of plugins satisfies all the
|
||||
// version requirements of the internal definitions. The list is represented
|
||||
// as a vectors of pair of strings. In each pair, the first element is
|
||||
// the name of the plugin and the second element is its version.
|
||||
// If false is returned, err is filled with error causing the check failure.
|
||||
//
|
||||
bool check_plugin_requirements(
|
||||
const std::vector<plugin_version_requirement>& plugins,
|
||||
std::string& err);
|
||||
|
||||
private:
|
||||
struct ruleset_node
|
||||
|
@@ -167,7 +167,7 @@ static void validate_exception_info(
|
||||
}
|
||||
|
||||
static void build_rule_exception_infos(
|
||||
vector<rule_loader::rule_exception_info>& exceptions,
|
||||
const vector<rule_loader::rule_exception_info>& exceptions,
|
||||
set<string>& exception_fields,
|
||||
string& condition)
|
||||
{
|
||||
@@ -421,32 +421,9 @@ void rule_loader::clear()
|
||||
m_required_plugin_versions.clear();
|
||||
}
|
||||
|
||||
bool rule_loader::is_plugin_compatible(
|
||||
const string &name,
|
||||
const string &version,
|
||||
string &required_version)
|
||||
const std::map<std::string, std::set<std::string>> rule_loader::required_plugin_versions() const
|
||||
{
|
||||
set<string> required_plugin_versions;
|
||||
sinsp_version plugin_version(version);
|
||||
if(!plugin_version.m_valid)
|
||||
{
|
||||
throw falco_exception(
|
||||
string("Plugin version string ") + version + " not valid");
|
||||
}
|
||||
auto it = m_required_plugin_versions.find(name);
|
||||
if (it != m_required_plugin_versions.end())
|
||||
{
|
||||
for (auto &rversion : it->second)
|
||||
{
|
||||
sinsp_version req_version(rversion);
|
||||
if (!plugin_version.check(req_version))
|
||||
{
|
||||
required_version = rversion;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return m_required_plugin_versions;
|
||||
}
|
||||
|
||||
void rule_loader::define(configuration& cfg, engine_version_info& info)
|
||||
@@ -458,6 +435,9 @@ void rule_loader::define(configuration& cfg, engine_version_info& info)
|
||||
|
||||
void rule_loader::define(configuration& cfg, plugin_version_info& info)
|
||||
{
|
||||
sinsp_version plugin_version(info.version);
|
||||
THROW(!plugin_version.m_valid, "Invalid required version '" + info.version
|
||||
+ "' for plugin '" + info.name + "'");
|
||||
m_required_plugin_versions[info.name].insert(info.version);
|
||||
}
|
||||
|
||||
@@ -575,7 +555,7 @@ void rule_loader::enable(configuration& cfg, rule_info& info)
|
||||
prev->enabled = info.enabled;
|
||||
}
|
||||
|
||||
void rule_loader::compile_list_infos(configuration& cfg, indexed_vector<list_info>& out)
|
||||
void rule_loader::compile_list_infos(configuration& cfg, indexed_vector<list_info>& out) const
|
||||
{
|
||||
string tmp;
|
||||
vector<string> used;
|
||||
@@ -622,10 +602,10 @@ void rule_loader::compile_list_infos(configuration& cfg, indexed_vector<list_inf
|
||||
void rule_loader::compile_macros_infos(
|
||||
configuration& cfg,
|
||||
indexed_vector<list_info>& lists,
|
||||
indexed_vector<macro_info>& out)
|
||||
indexed_vector<macro_info>& out) const
|
||||
{
|
||||
set<string> used;
|
||||
context* info_ctx = NULL;
|
||||
const context* info_ctx = NULL;
|
||||
try
|
||||
{
|
||||
for (auto &m : m_macro_infos)
|
||||
@@ -654,7 +634,7 @@ void rule_loader::compile_rule_infos(
|
||||
configuration& cfg,
|
||||
indexed_vector<list_info>& lists,
|
||||
indexed_vector<macro_info>& macros,
|
||||
indexed_vector<falco_rule>& out)
|
||||
indexed_vector<falco_rule>& out) const
|
||||
{
|
||||
string err, condition;
|
||||
set<string> warn_codes;
|
||||
@@ -753,7 +733,7 @@ void rule_loader::compile_rule_infos(
|
||||
}
|
||||
}
|
||||
|
||||
bool rule_loader::compile(configuration& cfg, indexed_vector<falco_rule>& out)
|
||||
bool rule_loader::compile(configuration& cfg, indexed_vector<falco_rule>& out) const
|
||||
{
|
||||
indexed_vector<list_info> lists;
|
||||
indexed_vector<macro_info> macros;
|
||||
|
@@ -44,10 +44,11 @@ public:
|
||||
/*!
|
||||
\brief Wraps an error by adding info about the text section
|
||||
*/
|
||||
inline std::string error(std::string err)
|
||||
inline std::string error(std::string err) const
|
||||
{
|
||||
std::string cnt = content;
|
||||
err += "\n---\n";
|
||||
err += trim(content);
|
||||
err += trim(cnt);
|
||||
err += "\n---";
|
||||
return err;
|
||||
}
|
||||
@@ -179,20 +180,16 @@ public:
|
||||
*/
|
||||
virtual void clear();
|
||||
|
||||
/*!
|
||||
\brief Returns true if the given plugin name and version are compatible
|
||||
with the internal definitions. If false is returned, required_version is
|
||||
filled with the required plugin version that didn't match.
|
||||
*/
|
||||
virtual bool is_plugin_compatible(
|
||||
const std::string& name,
|
||||
const std::string& version,
|
||||
std::string& required_version);
|
||||
|
||||
/*!
|
||||
\brief Uses the internal state to compile a list of falco_rules
|
||||
*/
|
||||
bool compile(configuration& cfg, indexed_vector<falco_rule>& out);
|
||||
virtual bool compile(configuration& cfg, indexed_vector<falco_rule>& out) const;
|
||||
|
||||
/*!
|
||||
\brief Returns the set of all required versions for each plugin according
|
||||
to the internal definitions.
|
||||
*/
|
||||
virtual const std::map<std::string, std::set<std::string>> required_plugin_versions() const;
|
||||
|
||||
/*!
|
||||
\brief Defines an info block. If a similar info block is found
|
||||
@@ -222,16 +219,16 @@ public:
|
||||
private:
|
||||
void compile_list_infos(
|
||||
configuration& cfg,
|
||||
indexed_vector<list_info>& out);
|
||||
indexed_vector<list_info>& out) const;
|
||||
void compile_macros_infos(
|
||||
configuration& cfg,
|
||||
indexed_vector<list_info>& lists,
|
||||
indexed_vector<macro_info>& out);
|
||||
indexed_vector<macro_info>& out) const;
|
||||
void compile_rule_infos(
|
||||
configuration& cfg,
|
||||
indexed_vector<list_info>& lists,
|
||||
indexed_vector<macro_info>& macros,
|
||||
indexed_vector<falco_rule>& out);
|
||||
indexed_vector<falco_rule>& out) const;
|
||||
|
||||
uint32_t m_cur_index;
|
||||
indexed_vector<rule_info> m_rule_infos;
|
||||
|
@@ -117,16 +117,21 @@ application::run_result application::load_rules_files()
|
||||
}
|
||||
|
||||
// Ensure that all plugins are compatible with the loaded set of rules
|
||||
for(const auto &plugin : m_state->inspector->get_plugin_manager()->plugins())
|
||||
std::string plugin_vers_err = "";
|
||||
std::vector<falco_engine::plugin_version_requirement> plugin_reqs;
|
||||
for (const auto &plugin : m_state->inspector->get_plugin_manager()->plugins())
|
||||
{
|
||||
std::string required_version;
|
||||
|
||||
if(!m_state->engine->is_plugin_compatible(plugin->name(), plugin->plugin_version().as_string(), required_version))
|
||||
falco_engine::plugin_version_requirement req;
|
||||
req.name = plugin->name();
|
||||
req.version = plugin->plugin_version().as_string();
|
||||
plugin_reqs.push_back(req);
|
||||
}
|
||||
if (!m_state->engine->check_plugin_requirements(plugin_reqs, plugin_vers_err))
|
||||
{
|
||||
ret.success = false;
|
||||
ret.errstr = "Plugin " + plugin->name() + " version " + plugin->plugin_version().as_string() + " not compatible with required plugin version " + required_version;
|
||||
ret.errstr = plugin_vers_err;
|
||||
ret.proceed = false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Free-up memory for the rule loader, which is not used from now on
|
||||
|
Reference in New Issue
Block a user