new(userspace/falco): new inotify watcher is now able to properly watch rules folders, when specified.

This means that when starting Falco passing to it a folder for its rules, it will properly manage
changes to any file inside the folders, plus any created/deleted file inside it.

Unified list of rules parsing, instead of having it done twice inside cmdline_options and configuration.
Instead, it is done only once, inside load_rules_files.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
This commit is contained in:
Federico Di Pierro
2022-05-06 12:58:18 +02:00
committed by poiana
parent 293a6c2b40
commit 3ba64d8a49
7 changed files with 43 additions and 13 deletions

View File

@@ -130,7 +130,7 @@ application::run_result application::attach_inotify_signals()
return ret;
}
/* Add watchers */
// Watch conf file
int wd = inotify_add_watch(inot_fd, m_options.conf_filename.c_str(), IN_CLOSE_WRITE);
if (wd == -1)
{
@@ -139,15 +139,33 @@ application::run_result application::attach_inotify_signals()
}
falco_logger::log(LOG_DEBUG, "Watching " + m_options.conf_filename +"\n");
for (const auto &rule : m_state->config->m_rules_filenames) {
wd = inotify_add_watch(inot_fd, rule.c_str(), IN_CLOSE_WRITE);
// Watch rules files
for (const auto &rule : m_state->config->m_loaded_rules_filenames)
{
wd = inotify_add_watch(inot_fd, rule.c_str(), IN_CLOSE_WRITE | IN_ONESHOT);
if (wd == -1)
{
ret.errstr = std::string("Failed to watch rule file: ") + rule;
return ret;
}
falco_logger::log(LOG_DEBUG, "Watching " + rule +"\n");
falco_logger::log(LOG_DEBUG, "Watching " + rule +".\n");
}
// Watch specified rules folders, if any:
// any newly created/removed file within the folder
// will trigger a Falco restart.
for (const auto &fld : m_state->config->m_loaded_rules_folders)
{
// For folders, we watch if any file is created or destroyed within
wd = inotify_add_watch(inot_fd, fld.c_str(), IN_CREATE | IN_DELETE | IN_ONESHOT);
if (wd == -1)
{
ret.errstr = std::string("Failed to watch rule folder: ") + fld;
return ret;
}
falco_logger::log(LOG_DEBUG, "Watching " + fld +" folder.\n");
}
ret.success = true;
ret.proceed = true;
}

View File

@@ -86,12 +86,17 @@ application::run_result application::load_rules_files()
}
falco_logger::log(LOG_DEBUG, "Configured rules filenames:\n");
for (const auto& filename : m_state->config->m_rules_filenames)
for (const auto& path : m_state->config->m_rules_filenames)
{
falco_logger::log(LOG_DEBUG, string(" ") + filename + "\n");
falco_logger::log(LOG_DEBUG, string(" ") + path + "\n");
}
for (const auto& filename : m_state->config->m_rules_filenames)
for (const auto &path : m_state->config->m_rules_filenames)
{
falco_configuration::read_rules_file_directory(path, m_state->config->m_loaded_rules_filenames, m_state->config->m_loaded_rules_folders);
}
for (const auto& filename : m_state->config->m_loaded_rules_filenames)
{
falco_logger::log(LOG_INFO, "Loading rules from file " + filename + ":\n");
uint64_t required_engine_version;

View File

@@ -58,7 +58,7 @@ application::run_result application::print_support()
support["engine_info"]["engine_version"] = FALCO_ENGINE_VERSION;
support["config"] = read_file(m_options.conf_filename);
support["rules_files"] = nlohmann::json::array();
for(auto filename : m_state->config->m_rules_filenames)
for(auto filename : m_state->config->m_loaded_rules_filenames)
{
nlohmann::json finfo;
finfo["name"] = filename;

View File

@@ -95,12 +95,11 @@ bool cmdline_options::parse(int argc, char **argv, std::string &errstr)
event_buffer_format = sinsp_evt::PF_BASE64;
}
// Expand any paths provided via -r and fill in rules_filenames
if(m_cmdline_parsed.count("r") > 0)
{
for(auto &path : m_cmdline_parsed["r"].as<std::vector<std::string>>())
{
falco_configuration::read_rules_file_directory(path, rules_filenames);
rules_filenames.push_back(path);
}
}

View File

@@ -60,6 +60,7 @@ public:
std::vector<std::string> cmdline_config_options;
std::string print_additional;
std::string pidfilename;
// Rules list as passed by the user, via cmdline option '-c'
std::list<std::string> rules_filenames;
std::string stats_filename;
uint64_t stats_interval;

View File

@@ -76,7 +76,7 @@ void falco_configuration::init(string conf_filename, const vector<string> &cmdli
struct stat buffer;
if(stat(file.c_str(), &buffer) == 0)
{
read_rules_file_directory(file, m_rules_filenames);
m_rules_filenames.push_back(file);
}
}
@@ -305,7 +305,7 @@ void falco_configuration::init(string conf_filename, const vector<string> &cmdli
m_watch_config_files = m_config->get_scalar<bool>("watch_config_files", true);
}
void falco_configuration::read_rules_file_directory(const string &path, list<string> &rules_filenames)
void falco_configuration::read_rules_file_directory(const string &path, list<string> &rules_filenames, list<string> &rules_folders)
{
struct stat st;
@@ -319,6 +319,8 @@ void falco_configuration::read_rules_file_directory(const string &path, list<str
if(st.st_mode & S_IFDIR)
{
rules_folders.push_back(path);
// It's a directory. Read the contents, sort
// alphabetically, and add every path to
// rules_filenames

View File

@@ -219,9 +219,14 @@ public:
void init(std::string conf_filename, const std::vector<std::string>& cmdline_options);
void init(const std::vector<std::string>& cmdline_options);
static void read_rules_file_directory(const string& path, list<string>& rules_filenames);
static void read_rules_file_directory(const string& path, list<string>& rules_filenames, list<string> &rules_folders);
// Rules list as passed by the user
std::list<std::string> m_rules_filenames;
// Actually loaded rules, with folders inspected
std::list<std::string> m_loaded_rules_filenames;
// List of loaded rule folders
std::list<std::string> m_loaded_rules_folders;
bool m_json_output;
bool m_json_include_output_property;
bool m_json_include_tags_property;