mirror of
https://github.com/falcosecurity/falco.git
synced 2025-08-24 08:58:52 +00:00
new(userspace): added json schema validation for rules.
Also, a new `--rule-schema` cli option was added to print the schema and leave. Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
This commit is contained in:
parent
d14825faf0
commit
895e50d3a0
@ -50,6 +50,7 @@ add_library(falco_application STATIC
|
||||
app/actions/create_requested_paths.cpp
|
||||
app/actions/close_inspectors.cpp
|
||||
app/actions/print_config_schema.cpp
|
||||
app/actions/print_rule_schema.cpp
|
||||
configuration.cpp
|
||||
falco_outputs.cpp
|
||||
outputs_file.cpp
|
||||
|
@ -45,6 +45,7 @@ falco::app::run_result print_ignored_events(const falco::app::state& s);
|
||||
falco::app::run_result print_kernel_version(const falco::app::state& s);
|
||||
falco::app::run_result print_page_size(const falco::app::state& s);
|
||||
falco::app::run_result print_plugin_info(const falco::app::state& s);
|
||||
falco::app::run_result print_rule_schema(falco::app::state& s);
|
||||
falco::app::run_result print_support(falco::app::state& s);
|
||||
falco::app::run_result print_syscall_events(falco::app::state& s);
|
||||
falco::app::run_result print_version(falco::app::state& s);
|
||||
|
@ -26,6 +26,9 @@ namespace falco {
|
||||
namespace app {
|
||||
namespace actions {
|
||||
|
||||
// Map that holds { rule filename | validation status } for each rule file read.
|
||||
typedef std::map<std::string, std::string> rule_read_res;
|
||||
|
||||
bool check_rules_plugin_requirements(falco::app::state& s, std::string& err);
|
||||
void print_enabled_event_sources(falco::app::state& s);
|
||||
void activate_interesting_kernel_tracepoints(falco::app::state& s, std::unique_ptr<sinsp>& inspector);
|
||||
@ -40,10 +43,14 @@ falco::app::run_result open_live_inspector(
|
||||
const std::string& source);
|
||||
|
||||
template<class InputIterator>
|
||||
void read_files(InputIterator begin, InputIterator end,
|
||||
rule_read_res read_files(InputIterator begin, InputIterator end,
|
||||
std::vector<std::string>& rules_contents,
|
||||
falco::load_result::rules_contents_t& rc)
|
||||
falco::load_result::rules_contents_t& rc,
|
||||
const nlohmann::json& schema={})
|
||||
{
|
||||
rule_read_res res;
|
||||
yaml_helper reader;
|
||||
std::string validation;
|
||||
// Read the contents in a first pass
|
||||
for(auto it = begin; it != end; it++)
|
||||
{
|
||||
@ -57,6 +64,9 @@ void read_files(InputIterator begin, InputIterator end,
|
||||
|
||||
std::string rules_content((std::istreambuf_iterator<char>(is)),
|
||||
std::istreambuf_iterator<char>());
|
||||
|
||||
reader.load_from_string(rules_content, schema, &validation);
|
||||
res[filename] = validation;
|
||||
rules_contents.emplace_back(std::move(rules_content));
|
||||
}
|
||||
|
||||
@ -75,6 +85,8 @@ void read_files(InputIterator begin, InputIterator end,
|
||||
{
|
||||
throw falco_exception("Unexpected mismatch in rules content name/rules content sets?");
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
@ -66,7 +66,7 @@ falco::app::run_result falco::app::actions::load_config(const falco::app::state&
|
||||
auto config_path = pair.first;
|
||||
auto validation = pair.second;
|
||||
auto priority = validation == yaml_helper::validation_ok ? falco_logger::level::INFO : falco_logger::level::WARNING;
|
||||
falco_logger::log(priority, std::string(" ") + config_path + " | validation: " + validation + "\n");
|
||||
falco_logger::log(priority, std::string(" ") + config_path + " | schema validation: " + validation + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,11 +54,12 @@ falco::app::run_result falco::app::actions::load_rules_files(falco::app::state&
|
||||
std::vector<std::string> rules_contents;
|
||||
falco::load_result::rules_contents_t rc;
|
||||
|
||||
rule_read_res validation_res;
|
||||
try {
|
||||
read_files(s.config->m_loaded_rules_filenames.begin(),
|
||||
validation_res = read_files(s.config->m_loaded_rules_filenames.begin(),
|
||||
s.config->m_loaded_rules_filenames.end(),
|
||||
rules_contents,
|
||||
rc);
|
||||
rc, s.config->m_rule_schema);
|
||||
}
|
||||
catch(falco_exception& e)
|
||||
{
|
||||
@ -66,9 +67,12 @@ falco::app::run_result falco::app::actions::load_rules_files(falco::app::state&
|
||||
}
|
||||
|
||||
std::string err = "";
|
||||
falco_logger::log(falco_logger::level::INFO, "Loading rules from:\n");
|
||||
for(auto &filename : s.config->m_loaded_rules_filenames)
|
||||
{
|
||||
falco_logger::log(falco_logger::level::INFO, "Loading rules from file " + filename + "\n");
|
||||
auto validation = validation_res[filename];
|
||||
auto priority = validation == yaml_helper::validation_ok ? falco_logger::level::INFO : falco_logger::level::WARNING;
|
||||
falco_logger::log(priority, std::string(" ") + filename + " | schema validation: " + validation + "\n");
|
||||
std::unique_ptr<falco::load_result> res;
|
||||
|
||||
res = s.engine->load_rules(rc.at(filename), filename);
|
||||
|
31
userspace/falco/app/actions/print_rule_schema.cpp
Normal file
31
userspace/falco/app/actions/print_rule_schema.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2024 The Falco Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include "actions.h"
|
||||
|
||||
using namespace falco::app;
|
||||
using namespace falco::app::actions;
|
||||
|
||||
falco::app::run_result falco::app::actions::print_rule_schema(falco::app::state &s)
|
||||
{
|
||||
if(s.options.print_rule_schema)
|
||||
{
|
||||
printf("%s", s.config->m_rule_schema.dump(2).c_str());
|
||||
return run_result::exit();
|
||||
}
|
||||
return run_result::ok();
|
||||
}
|
@ -33,11 +33,12 @@ falco::app::run_result falco::app::actions::validate_rules_files(falco::app::sta
|
||||
std::vector<std::string> rules_contents;
|
||||
falco::load_result::rules_contents_t rc;
|
||||
|
||||
rule_read_res validation_res;
|
||||
try {
|
||||
read_files(s.options.validate_rules_filenames.begin(),
|
||||
validation_res = read_files(s.options.validate_rules_filenames.begin(),
|
||||
s.options.validate_rules_filenames.end(),
|
||||
rules_contents,
|
||||
rc);
|
||||
rc,s.config->m_rule_schema);
|
||||
}
|
||||
catch(falco_exception& e)
|
||||
{
|
||||
@ -71,7 +72,9 @@ falco::app::run_result falco::app::actions::validate_rules_files(falco::app::sta
|
||||
falco_logger::log(falco_logger::level::INFO, "Validating rules file(s):\n");
|
||||
for(const auto& file : s.options.validate_rules_filenames)
|
||||
{
|
||||
falco_logger::log(falco_logger::level::INFO, " " + file + "\n");
|
||||
auto validation = validation_res[file];
|
||||
auto priority = validation == yaml_helper::validation_ok ? falco_logger::level::INFO : falco_logger::level::WARNING;
|
||||
falco_logger::log(priority, std::string(" ") + file + " | schema validation: " + validation + "\n");
|
||||
}
|
||||
|
||||
// The json output encompasses all files so the
|
||||
|
@ -61,6 +61,7 @@ bool falco::app::run(falco::app::state& s, bool& restart, std::string& errstr)
|
||||
// loading plugins, opening inspector, etc.).
|
||||
std::list<app_action> run_steps = {
|
||||
falco::app::actions::print_config_schema,
|
||||
falco::app::actions::print_rule_schema,
|
||||
falco::app::actions::load_config,
|
||||
falco::app::actions::print_help,
|
||||
falco::app::actions::print_kernel_version,
|
||||
|
@ -115,6 +115,7 @@ void options::define(cxxopts::Options& opts)
|
||||
("c", "Configuration file. If not specified tries " FALCO_SOURCE_CONF_FILE ", " FALCO_INSTALL_CONF_FILE ".", cxxopts::value(conf_filename), "<path>")
|
||||
#endif
|
||||
("config-schema", "Print the config json schema and exit.", cxxopts::value(print_config_schema)->default_value("false"))
|
||||
("rule-schema", "Print the rule json schema and exit.", cxxopts::value(print_rule_schema)->default_value("false"))
|
||||
("A", "Monitor all events supported by Falco and defined in rules and configs. Some events are ignored by default when -A is not specified (the -i option lists these events ignored). Using -A can impact performance. This option has no effect when reproducing events from a capture file.", cxxopts::value(all_events)->default_value("false"))
|
||||
("b,print-base64", "Print data buffers in base64. This is useful for encoding binary data that needs to be used over media designed to consume this format.")
|
||||
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(MINIMAL_BUILD)
|
||||
|
@ -41,6 +41,7 @@ public:
|
||||
// Each of these maps directly to a command line option.
|
||||
bool help = false;
|
||||
bool print_config_schema = false;
|
||||
bool print_rule_schema = false;
|
||||
std::string conf_filename;
|
||||
bool all_events = false;
|
||||
sinsp_evt::param_fmt event_buffer_format = sinsp_evt::PF_NORMAL;
|
||||
|
File diff suppressed because one or more lines are too long
@ -210,9 +210,9 @@ public:
|
||||
replay_config m_replay = {};
|
||||
gvisor_config m_gvisor = {};
|
||||
|
||||
// Needed by tests
|
||||
yaml_helper m_config;
|
||||
nlohmann::json m_config_schema;
|
||||
nlohmann::json m_rule_schema;
|
||||
|
||||
private:
|
||||
void merge_config_files(const std::string& config_name, config_loaded_res &res);
|
||||
|
Loading…
Reference in New Issue
Block a user