diff --git a/userspace/falco/app_actions/create_signal_handlers.cpp b/userspace/falco/app_actions/create_signal_handlers.cpp index 377eec82..7b7ce54f 100644 --- a/userspace/falco/app_actions/create_signal_handlers.cpp +++ b/userspace/falco/app_actions/create_signal_handlers.cpp @@ -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; } diff --git a/userspace/falco/app_actions/load_rules_files.cpp b/userspace/falco/app_actions/load_rules_files.cpp index 5633c05c..83fb026f 100644 --- a/userspace/falco/app_actions/load_rules_files.cpp +++ b/userspace/falco/app_actions/load_rules_files.cpp @@ -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; diff --git a/userspace/falco/app_actions/print_support.cpp b/userspace/falco/app_actions/print_support.cpp index c3773427..593b7ba6 100644 --- a/userspace/falco/app_actions/print_support.cpp +++ b/userspace/falco/app_actions/print_support.cpp @@ -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; diff --git a/userspace/falco/app_cmdline_options.cpp b/userspace/falco/app_cmdline_options.cpp index 4855305b..ea701d25 100644 --- a/userspace/falco/app_cmdline_options.cpp +++ b/userspace/falco/app_cmdline_options.cpp @@ -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>()) { - falco_configuration::read_rules_file_directory(path, rules_filenames); + rules_filenames.push_back(path); } } diff --git a/userspace/falco/app_cmdline_options.h b/userspace/falco/app_cmdline_options.h index 240356ff..a0269f6e 100644 --- a/userspace/falco/app_cmdline_options.h +++ b/userspace/falco/app_cmdline_options.h @@ -60,6 +60,7 @@ public: std::vector cmdline_config_options; std::string print_additional; std::string pidfilename; + // Rules list as passed by the user, via cmdline option '-c' std::list rules_filenames; std::string stats_filename; uint64_t stats_interval; diff --git a/userspace/falco/configuration.cpp b/userspace/falco/configuration.cpp index 85820c34..f6e53026 100644 --- a/userspace/falco/configuration.cpp +++ b/userspace/falco/configuration.cpp @@ -76,7 +76,7 @@ void falco_configuration::init(string conf_filename, const vector &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 &cmdli m_watch_config_files = m_config->get_scalar("watch_config_files", true); } -void falco_configuration::read_rules_file_directory(const string &path, list &rules_filenames) +void falco_configuration::read_rules_file_directory(const string &path, list &rules_filenames, list &rules_folders) { struct stat st; @@ -319,6 +319,8 @@ void falco_configuration::read_rules_file_directory(const string &path, list& cmdline_options); void init(const std::vector& cmdline_options); - static void read_rules_file_directory(const string& path, list& rules_filenames); + static void read_rules_file_directory(const string& path, list& rules_filenames, list &rules_folders); + // Rules list as passed by the user std::list m_rules_filenames; + // Actually loaded rules, with folders inspected + std::list m_loaded_rules_filenames; + // List of loaded rule folders + std::list m_loaded_rules_folders; bool m_json_output; bool m_json_include_output_property; bool m_json_include_tags_property;