mirror of
https://github.com/falcosecurity/falco.git
synced 2025-06-29 08:07:24 +00:00
refactor(userspace/engine): reduce responsibilities of rule_loader
The rule_loader is now simply responsible of collecting list/macro/rule definitions and then compiling them as falco_rules. The ruleset file reading code will be moved to another class Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
This commit is contained in:
parent
af96a930eb
commit
9ed7d57838
File diff suppressed because it is too large
Load Diff
@ -33,38 +33,153 @@ class falco_engine;
|
|||||||
class rule_loader
|
class rule_loader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/*!
|
||||||
|
\brief Represents a section of text from which a certain info
|
||||||
|
struct has been decoded
|
||||||
|
*/
|
||||||
|
struct mark
|
||||||
|
{
|
||||||
|
std::string content;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Wraps an error by adding info about the text section
|
||||||
|
*/
|
||||||
|
inline std::string error(std::string err)
|
||||||
|
{
|
||||||
|
err += "\n---\n";
|
||||||
|
err += trim(content);
|
||||||
|
err += "\n---";
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Appends another text section info to this one
|
||||||
|
*/
|
||||||
|
inline void append(mark& m)
|
||||||
|
{
|
||||||
|
content += "\n\n";
|
||||||
|
content += m.content;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Erases the internal states and all the loaded rules
|
\brief Contains the info required to load rule definitions
|
||||||
|
*/
|
||||||
|
struct context
|
||||||
|
{
|
||||||
|
context(const std::string& cont): content(cont) {}
|
||||||
|
const std::string& content;
|
||||||
|
std::string output_extra;
|
||||||
|
bool replace_output_container_info;
|
||||||
|
falco_common::priority_type min_priority;
|
||||||
|
std::vector<std::string> warnings;
|
||||||
|
std::vector<std::string> errors;
|
||||||
|
falco_engine* engine;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Represents infos about an engine version requirement
|
||||||
|
*/
|
||||||
|
struct engine_version_info
|
||||||
|
{
|
||||||
|
uint32_t version;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Represents infos about a plugin version requirement
|
||||||
|
*/
|
||||||
|
struct plugin_version_info
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
std::string version;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Represents infos about a list
|
||||||
|
*/
|
||||||
|
struct list_info
|
||||||
|
{
|
||||||
|
mark context;
|
||||||
|
bool used;
|
||||||
|
size_t index;
|
||||||
|
size_t visibility;
|
||||||
|
std::string name;
|
||||||
|
std::vector<std::string> items;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Represents infos about a macro
|
||||||
|
*/
|
||||||
|
struct macro_info
|
||||||
|
{
|
||||||
|
mark context;
|
||||||
|
bool used;
|
||||||
|
size_t index;
|
||||||
|
size_t visibility;
|
||||||
|
std::string name;
|
||||||
|
std::string cond;
|
||||||
|
std::string source;
|
||||||
|
std::shared_ptr<libsinsp::filter::ast::expr> cond_ast;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Represents infos about a single rule exception
|
||||||
|
*/
|
||||||
|
struct rule_exception_info
|
||||||
|
{
|
||||||
|
/*!
|
||||||
|
\brief This is necessary due to the dynamic-typed nature of
|
||||||
|
exceptions. Each of fields, comps, and values, can either be a
|
||||||
|
single value or a list of values. This is a simple hack to make
|
||||||
|
this easier to implement in C++, that is not non-dynamic-typed.
|
||||||
|
*/
|
||||||
|
struct entry {
|
||||||
|
bool is_list;
|
||||||
|
std::string item;
|
||||||
|
std::vector<entry> items;
|
||||||
|
|
||||||
|
inline bool is_valid() const
|
||||||
|
{
|
||||||
|
return (is_list && !items.empty())
|
||||||
|
|| (!is_list && !item.empty());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
entry fields;
|
||||||
|
entry comps;
|
||||||
|
std::vector<entry> values;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Represents infos about a rule
|
||||||
|
*/
|
||||||
|
struct rule_info
|
||||||
|
{
|
||||||
|
mark context;
|
||||||
|
size_t index;
|
||||||
|
size_t visibility;
|
||||||
|
std::string name;
|
||||||
|
std::string cond;
|
||||||
|
std::string source;
|
||||||
|
std::string desc;
|
||||||
|
std::string output;
|
||||||
|
std::set<std::string> tags;
|
||||||
|
std::vector<rule_exception_info> exceptions;
|
||||||
|
falco_common::priority_type priority;
|
||||||
|
bool enabled;
|
||||||
|
bool warn_evttypes;
|
||||||
|
bool skip_if_unknown_filter;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Erases all the internal state and definitions
|
||||||
*/
|
*/
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|
||||||
/*!
|
|
||||||
\brief Returns the rules loaded after the last invocation of load()
|
|
||||||
*/
|
|
||||||
virtual const indexed_vector<falco_rule>& rules();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\brief Configures the loader. The changes will influence the next
|
|
||||||
invocation of load().
|
|
||||||
\param min_priority The minimum priority below which rules are skipped
|
|
||||||
by the loader
|
|
||||||
\param extra Text to be appended/substituted in the output of all rules
|
|
||||||
\param replace_container_info If true, the extra string is used to
|
|
||||||
replace the "%container.info" token in rules outputs. If false, the
|
|
||||||
"%container.info" token is substituted with a default text and the
|
|
||||||
extra string is appended at the end of the rule output. If a rule
|
|
||||||
output does not contain "%container.info", then this flag has no effect
|
|
||||||
and the extra string is appended at the end of the rule output anyways.
|
|
||||||
*/
|
|
||||||
virtual void configure(
|
|
||||||
falco_common::priority_type min_priority,
|
|
||||||
bool replace_container_info,
|
|
||||||
const std::string& extra);
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Returns true if the given plugin name and version are compatible
|
\brief Returns true if the given plugin name and version are compatible
|
||||||
with the loaded rulesets. If false is returned, required_version is
|
with the internal definitions. If false is returned, required_version is
|
||||||
filled with the required plugin version that didn't match.
|
filled with the required plugin version that didn't match.
|
||||||
*/
|
*/
|
||||||
virtual bool is_plugin_compatible(
|
virtual bool is_plugin_compatible(
|
||||||
@ -73,70 +188,52 @@ public:
|
|||||||
std::string& required_version);
|
std::string& required_version);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Parses the content of a ruleset. This should be called multiple
|
\brief Uses the internal state to compile a list of falco_rules
|
||||||
times to load different rulesets. The internal state (e.g. loaded
|
|
||||||
rules, plugin version requirements, etc...) gets updated at each
|
|
||||||
invocation of the load() method.
|
|
||||||
\param content The contents of the ruleset
|
|
||||||
\param engine The instance of falco_engine used to add rule filters
|
|
||||||
\param warnings Filled-out with warnings
|
|
||||||
\param warnings Filled-out with errors
|
|
||||||
\return true if the ruleset content is loaded successfully
|
|
||||||
*/
|
*/
|
||||||
virtual bool load(
|
bool compile(context& ctx, indexed_vector<falco_rule>& out);
|
||||||
const std::string& content,
|
|
||||||
falco_engine* engine,
|
/*!
|
||||||
std::vector<std::string>& warnings,
|
\brief Defines an info block. If a similar info block is found
|
||||||
std::vector<std::string>& errors);
|
in the internal state (e.g. another rule with same name), then
|
||||||
|
the previous definition gets overwritten
|
||||||
|
*/
|
||||||
|
virtual void define(context& ctx, engine_version_info& info);
|
||||||
|
virtual void define(context& ctx, plugin_version_info& info);
|
||||||
|
virtual void define(context& ctx, list_info& info);
|
||||||
|
virtual void define(context& ctx, macro_info& info);
|
||||||
|
virtual void define(context& ctx, rule_info& info);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Appends an info block to an existing one. An exception
|
||||||
|
is thrown if no existing definition can be matched with the appended
|
||||||
|
one
|
||||||
|
*/
|
||||||
|
virtual void append(context& ctx, list_info& info);
|
||||||
|
virtual void append(context& ctx, macro_info& info);
|
||||||
|
virtual void append(context& ctx, rule_info& info);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Updates the 'enabled' flag of an existing definition
|
||||||
|
*/
|
||||||
|
virtual void enable(context& ctx, rule_info& info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef pair<
|
void compile_list_infos(
|
||||||
YAML::Node,
|
context& ctx,
|
||||||
shared_ptr<libsinsp::filter::ast::expr>
|
indexed_vector<list_info>& out);
|
||||||
> macro_node;
|
void compile_macros_infos(
|
||||||
|
context& ctx,
|
||||||
bool read(
|
indexed_vector<list_info>& lists,
|
||||||
const std::string& content, falco_engine* engine,
|
indexed_vector<macro_info>& out);
|
||||||
std::vector<std::string>& warnings, std::vector<std::string>& errors);
|
void compile_rule_infos(
|
||||||
void read_item(
|
context& ctx,
|
||||||
falco_engine* engine, YAML::Node& item, vector<string>& warnings);
|
indexed_vector<list_info>& lists,
|
||||||
void read_required_engine_version(
|
indexed_vector<macro_info>& macros,
|
||||||
falco_engine* engine, YAML::Node& item, vector<string>& warnings);
|
indexed_vector<falco_rule>& out);
|
||||||
void read_required_plugin_versions(
|
|
||||||
falco_engine* engine, YAML::Node& item, vector<string>& warnings);
|
|
||||||
void read_macro(
|
|
||||||
falco_engine* engine, YAML::Node& item, vector<string>& warnings);
|
|
||||||
void read_list(
|
|
||||||
falco_engine* engine, YAML::Node& item, vector<string>& warnings);
|
|
||||||
void read_rule(
|
|
||||||
falco_engine* engine, YAML::Node& item, vector<string>& warnings);
|
|
||||||
void read_rule_exceptions(
|
|
||||||
falco_engine* engine, YAML::Node& item, bool append);
|
|
||||||
bool expand(falco_engine* engine,
|
|
||||||
std::vector<std::string>& warnings, std::vector<std::string>& errors);
|
|
||||||
void expand_list_infos(
|
|
||||||
std::map<string, bool>& used, indexed_vector<YAML::Node>& out);
|
|
||||||
void expand_macro_infos(
|
|
||||||
const indexed_vector<YAML::Node>& lists,
|
|
||||||
std::map<string, bool>& used_lists,
|
|
||||||
std::map<string, bool>& used_macros,
|
|
||||||
indexed_vector<macro_node>& out);
|
|
||||||
void expand_rule_infos(
|
|
||||||
falco_engine* engine,
|
|
||||||
const indexed_vector<YAML::Node>& lists,
|
|
||||||
const indexed_vector<macro_node>& macros,
|
|
||||||
std::map<string, bool>& used_lists,
|
|
||||||
std::map<string, bool>& used_macros,
|
|
||||||
vector<string>& warnings);
|
|
||||||
void apply_output_substitutions(std::string& output);
|
|
||||||
|
|
||||||
uint32_t m_cur_index;
|
uint32_t m_cur_index;
|
||||||
std::string m_extra;
|
indexed_vector<rule_info> m_rule_infos;
|
||||||
bool m_replace_container_info;
|
indexed_vector<macro_info> m_macro_infos;
|
||||||
falco_common::priority_type m_min_priority;
|
indexed_vector<list_info> m_list_infos;
|
||||||
indexed_vector<falco_rule> m_rules;
|
|
||||||
indexed_vector<YAML::Node> m_rule_infos;
|
|
||||||
indexed_vector<YAML::Node> m_macro_infos;
|
|
||||||
indexed_vector<YAML::Node> m_list_infos;
|
|
||||||
std::map<std::string, std::set<std::string>> m_required_plugin_versions;
|
std::map<std::string, std::set<std::string>> m_required_plugin_versions;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user