mirror of
https://github.com/falcosecurity/falco.git
synced 2025-07-16 15:51:55 +00:00
Add support bundle (#517)
* Expose required_engine_version when loading rules When loading a rules file, have alternate methods that return the required_engine_version. The existing methods remain unchanged and just call the new methods with a dummy placeholder. * Add --support argument to print support bundle Add an argument --support that can be used as a single way to collect necessary support information, including the falco version, config, commandline, and all rules files. There might be a big of extra structure to the rules files, as they actually support an array of "variants", but we're thinking ahead to cases where there might be a comprehensive library of rules files and choices, so we're adding the extra structure.
This commit is contained in:
parent
bd4c3ffa39
commit
5e9bbd139c
@ -143,6 +143,13 @@ void falco_engine::list_fields(bool names_only)
|
||||
}
|
||||
|
||||
void falco_engine::load_rules(const string &rules_content, bool verbose, bool all_events)
|
||||
{
|
||||
uint64_t dummy;
|
||||
|
||||
return load_rules(rules_content, verbose, all_events, dummy);
|
||||
}
|
||||
|
||||
void falco_engine::load_rules(const string &rules_content, bool verbose, bool all_events, uint64_t &required_engine_version)
|
||||
{
|
||||
// The engine must have been given an inspector by now.
|
||||
if(! m_inspector)
|
||||
@ -171,10 +178,17 @@ void falco_engine::load_rules(const string &rules_content, bool verbose, bool al
|
||||
bool json_include_output_property = false;
|
||||
falco_formats::init(m_inspector, this, m_ls, json_output, json_include_output_property);
|
||||
|
||||
m_rules->load_rules(rules_content, verbose, all_events, m_extra, m_replace_container_info, m_min_priority);
|
||||
m_rules->load_rules(rules_content, verbose, all_events, m_extra, m_replace_container_info, m_min_priority, required_engine_version);
|
||||
}
|
||||
|
||||
void falco_engine::load_rules_file(const string &rules_filename, bool verbose, bool all_events)
|
||||
{
|
||||
uint64_t dummy;
|
||||
|
||||
return load_rules_file(rules_filename, verbose, all_events, dummy);
|
||||
}
|
||||
|
||||
void falco_engine::load_rules_file(const string &rules_filename, bool verbose, bool all_events, uint64_t &required_engine_version)
|
||||
{
|
||||
ifstream is;
|
||||
|
||||
@ -189,7 +203,7 @@ void falco_engine::load_rules_file(const string &rules_filename, bool verbose, b
|
||||
string rules_content((istreambuf_iterator<char>(is)),
|
||||
istreambuf_iterator<char>());
|
||||
|
||||
load_rules(rules_content, verbose, all_events);
|
||||
load_rules(rules_content, verbose, all_events, required_engine_version);
|
||||
}
|
||||
|
||||
void falco_engine::enable_rule(const string &pattern, bool enabled, const string &ruleset)
|
||||
|
@ -68,6 +68,13 @@ public:
|
||||
void load_rules_file(const std::string &rules_filename, bool verbose, bool all_events);
|
||||
void load_rules(const std::string &rules_content, bool verbose, bool all_events);
|
||||
|
||||
//
|
||||
// Identical to above, but also returns the required engine version for the file/content.
|
||||
// (If no required engine version is specified, returns 0).
|
||||
//
|
||||
void load_rules_file(const std::string &rules_filename, bool verbose, bool all_events, uint64_t &required_engine_version);
|
||||
void load_rules(const std::string &rules_content, bool verbose, bool all_events, uint64_t &required_engine_version);
|
||||
|
||||
//
|
||||
// Enable/Disable any rules matching the provided pattern
|
||||
// (regex). When provided, enable/disable these rules in the
|
||||
|
@ -195,10 +195,11 @@ function load_rules(sinsp_lua_parser,
|
||||
min_priority)
|
||||
|
||||
local rules = yaml.load(rules_content)
|
||||
local required_engine_version = 0
|
||||
|
||||
if rules == nil then
|
||||
-- An empty rules file is acceptable
|
||||
return
|
||||
return required_engine_version
|
||||
end
|
||||
|
||||
if type(rules) ~= "table" then
|
||||
@ -216,6 +217,7 @@ function load_rules(sinsp_lua_parser,
|
||||
end
|
||||
|
||||
if (v['required_engine_version']) then
|
||||
required_engine_version = v['required_engine_version']
|
||||
if falco_rules.engine_version(rules_mgr) < v['required_engine_version'] then
|
||||
error("Rules require engine version "..v['required_engine_version']..", but engine version is "..falco_rules.engine_version(rules_mgr))
|
||||
end
|
||||
@ -549,6 +551,8 @@ function load_rules(sinsp_lua_parser,
|
||||
end
|
||||
|
||||
io.flush()
|
||||
|
||||
return required_engine_version
|
||||
end
|
||||
|
||||
local rule_fmt = "%-50s %s"
|
||||
|
@ -223,7 +223,8 @@ int falco_rules::engine_version(lua_State *ls)
|
||||
void falco_rules::load_rules(const string &rules_content,
|
||||
bool verbose, bool all_events,
|
||||
string &extra, bool replace_container_info,
|
||||
falco_common::priority_type min_priority)
|
||||
falco_common::priority_type min_priority,
|
||||
uint64_t &required_engine_version)
|
||||
{
|
||||
lua_getglobal(m_ls, m_lua_load_rules.c_str());
|
||||
if(lua_isfunction(m_ls, -1))
|
||||
@ -398,12 +399,15 @@ void falco_rules::load_rules(const string &rules_content,
|
||||
lua_pushstring(m_ls, extra.c_str());
|
||||
lua_pushboolean(m_ls, (replace_container_info ? 1 : 0));
|
||||
lua_pushnumber(m_ls, min_priority);
|
||||
if(lua_pcall(m_ls, 9, 0, 0) != 0)
|
||||
if(lua_pcall(m_ls, 9, 1, 0) != 0)
|
||||
{
|
||||
const char* lerr = lua_tostring(m_ls, -1);
|
||||
string err = "Error loading rules: " + string(lerr);
|
||||
throw falco_exception(err);
|
||||
}
|
||||
|
||||
required_engine_version = lua_tonumber(m_ls, -1);
|
||||
lua_pop(m_ls, 1);
|
||||
} else {
|
||||
throw falco_exception("No function " + m_lua_load_rules + " found in lua rule module");
|
||||
}
|
||||
|
@ -41,7 +41,8 @@ class falco_rules
|
||||
~falco_rules();
|
||||
void load_rules(const string &rules_content, bool verbose, bool all_events,
|
||||
std::string &extra, bool replace_container_info,
|
||||
falco_common::priority_type min_priority);
|
||||
falco_common::priority_type min_priority,
|
||||
uint64_t &required_engine_version);
|
||||
void describe_rule(string *rule);
|
||||
|
||||
static void init(lua_State *ls);
|
||||
|
@ -28,6 +28,7 @@ limitations under the License.
|
||||
#include <string>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
@ -135,6 +136,8 @@ static void usage()
|
||||
" Capture the first <len> bytes of each I/O buffer.\n"
|
||||
" By default, the first 80 bytes are captured. Use this\n"
|
||||
" option with caution, it can generate huge trace files.\n"
|
||||
" --support Print support information including version, rules files used, etc.\n"
|
||||
" and exit.\n"
|
||||
" -T <tag> Disable any rules with a tag=<tag>. Can be specified multiple times.\n"
|
||||
" Can not be specified with -t.\n"
|
||||
" -t <tag> Only run those rules with a tag=<tag>. Can be specified multiple times.\n"
|
||||
@ -197,6 +200,15 @@ void read_k8s_audit_trace_file(falco_engine *engine,
|
||||
}
|
||||
}
|
||||
|
||||
static std::string read_file(std::string filename)
|
||||
{
|
||||
std::ifstream t(filename);
|
||||
std::string str((std::istreambuf_iterator<char>(t)),
|
||||
std::istreambuf_iterator<char>());
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
//
|
||||
// Event processing loop
|
||||
//
|
||||
@ -389,6 +401,7 @@ int falco_init(int argc, char **argv)
|
||||
bool print_ignored_events = false;
|
||||
bool list_flds = false;
|
||||
string list_flds_source = "";
|
||||
bool print_support = false;
|
||||
|
||||
// Used for writing trace files
|
||||
int duration_seconds = 0;
|
||||
@ -398,6 +411,7 @@ int falco_init(int argc, char **argv)
|
||||
bool compress = false;
|
||||
bool buffered_outputs = true;
|
||||
bool buffered_cmdline = false;
|
||||
std::map<string,uint64_t> required_engine_versions;
|
||||
|
||||
// Used for stats
|
||||
double duration;
|
||||
@ -418,6 +432,7 @@ int falco_init(int argc, char **argv)
|
||||
{"print", required_argument, 0, 'p' },
|
||||
{"pidfile", required_argument, 0, 'P' },
|
||||
{"snaplen", required_argument, 0, 'S' },
|
||||
{"support", no_argument, 0},
|
||||
{"unbuffered", no_argument, 0, 'U' },
|
||||
{"version", no_argument, 0, 0 },
|
||||
{"validate", required_argument, 0, 'V' },
|
||||
@ -573,6 +588,10 @@ int falco_init(int argc, char **argv)
|
||||
list_flds_source = optarg;
|
||||
}
|
||||
}
|
||||
else if (string(long_options[long_index].name) == "support")
|
||||
{
|
||||
print_support = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -701,7 +720,10 @@ int falco_init(int argc, char **argv)
|
||||
for (auto filename : config.m_rules_filenames)
|
||||
{
|
||||
falco_logger::log(LOG_INFO, "Loading rules from file " + filename + ":\n");
|
||||
engine->load_rules_file(filename, verbose, all_events);
|
||||
uint64_t required_engine_version;
|
||||
|
||||
engine->load_rules_file(filename, verbose, all_events, required_engine_version);
|
||||
required_engine_versions[filename] = required_engine_version;
|
||||
}
|
||||
|
||||
// You can't both disable and enable rules
|
||||
@ -738,6 +760,49 @@ int falco_init(int argc, char **argv)
|
||||
engine->enable_rule_by_tag(enabled_rule_tags, true);
|
||||
}
|
||||
|
||||
if(print_support)
|
||||
{
|
||||
nlohmann::json support;
|
||||
struct utsname sysinfo;
|
||||
std::string cmdline;
|
||||
|
||||
if(uname(&sysinfo) != 0)
|
||||
{
|
||||
throw std::runtime_error(string("Could not uname() to find system info: %s\n") + strerror(errno));
|
||||
}
|
||||
|
||||
for(char **arg = argv; *arg; arg++)
|
||||
{
|
||||
if(cmdline.size() > 0)
|
||||
{
|
||||
cmdline += " ";
|
||||
}
|
||||
cmdline += *arg;
|
||||
}
|
||||
|
||||
support["version"] = FALCO_VERSION;
|
||||
support["system_info"]["sysname"] = sysinfo.sysname;
|
||||
support["system_info"]["nodename"] = sysinfo.nodename;
|
||||
support["system_info"]["release"] = sysinfo.release;
|
||||
support["system_info"]["version"] = sysinfo.version;
|
||||
support["system_info"]["machine"] = sysinfo.machine;
|
||||
support["cmdline"] = cmdline;
|
||||
support["config"] = read_file(conf_filename);
|
||||
support["rules_files"] = nlohmann::json::array();
|
||||
for(auto filename : config.m_rules_filenames)
|
||||
{
|
||||
nlohmann::json finfo;
|
||||
finfo["name"] = filename;
|
||||
nlohmann::json variant;
|
||||
variant["required_engine_version"] = required_engine_versions[filename];
|
||||
variant["content"] = read_file(filename);
|
||||
finfo["variants"].push_back(variant);
|
||||
support["rules_files"].push_back(finfo);
|
||||
}
|
||||
printf("%s\n", support.dump().c_str());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
outputs->init(config.m_json_output,
|
||||
config.m_json_include_output_property,
|
||||
config.m_notifications_rate, config.m_notifications_max_burst,
|
||||
|
Loading…
Reference in New Issue
Block a user