mirror of
https://github.com/falcosecurity/falco.git
synced 2025-07-07 11:49:07 +00:00
Merge pull request #50 from draios/cmdline-opts-daemonize
Clean up handling cmdline options wrt config file.
This commit is contained in:
commit
92c4c8f622
@ -7,18 +7,22 @@ using namespace std;
|
|||||||
|
|
||||||
|
|
||||||
// If we don't have a configuration file, we just use stdout output and all other defaults
|
// If we don't have a configuration file, we just use stdout output and all other defaults
|
||||||
void falco_configuration::init()
|
void falco_configuration::init(std::list<std::string> &cmdline_options)
|
||||||
{
|
{
|
||||||
|
init_cmdline_options(cmdline_options);
|
||||||
|
|
||||||
output_config stdout_output;
|
output_config stdout_output;
|
||||||
stdout_output.name = "stdout";
|
stdout_output.name = "stdout";
|
||||||
m_outputs.push_back(stdout_output);
|
m_outputs.push_back(stdout_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
void falco_configuration::init(string conf_filename)
|
void falco_configuration::init(string conf_filename, std::list<std::string> &cmdline_options)
|
||||||
{
|
{
|
||||||
string m_config_file = conf_filename;
|
string m_config_file = conf_filename;
|
||||||
m_config = new yaml_configuration(m_config_file);
|
m_config = new yaml_configuration(m_config_file);
|
||||||
|
|
||||||
|
init_cmdline_options(cmdline_options);
|
||||||
|
|
||||||
m_rules_filename = m_config->get_scalar<string>("rules_file", "/etc/falco_rules.yaml");
|
m_rules_filename = m_config->get_scalar<string>("rules_file", "/etc/falco_rules.yaml");
|
||||||
m_json_output = m_config->get_scalar<bool>("json_output", false);
|
m_json_output = m_config->get_scalar<bool>("json_output", false);
|
||||||
|
|
||||||
@ -58,3 +62,40 @@ void falco_configuration::init(string conf_filename)
|
|||||||
falco_logger::log_stderr = m_config->get_scalar<bool>("log_stderr", false);
|
falco_logger::log_stderr = m_config->get_scalar<bool>("log_stderr", false);
|
||||||
falco_logger::log_syslog = m_config->get_scalar<bool>("log_syslog", true);
|
falco_logger::log_syslog = m_config->get_scalar<bool>("log_syslog", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool split(const string &str, char delim, pair<string,string> &parts)
|
||||||
|
{
|
||||||
|
size_t pos;
|
||||||
|
|
||||||
|
if ((pos = str.find_first_of(delim)) == string::npos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
parts.first = str.substr(0, pos);
|
||||||
|
parts.second = str.substr(pos + 1);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void falco_configuration::init_cmdline_options(std::list<std::string> &cmdline_options)
|
||||||
|
{
|
||||||
|
for(const string &option : cmdline_options)
|
||||||
|
{
|
||||||
|
set_cmdline_option(option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void falco_configuration::set_cmdline_option(const std::string &opt)
|
||||||
|
{
|
||||||
|
pair<string,string> keyval;
|
||||||
|
pair<string,string> subkey;
|
||||||
|
|
||||||
|
if (! split(opt, '=', keyval)) {
|
||||||
|
throw sinsp_exception("Error parsing config option \"" + opt + "\". Must be of the form key=val or key.subkey=val");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (split(keyval.first, '.', subkey)) {
|
||||||
|
m_config->set_scalar(subkey.first, subkey.second, keyval.second);
|
||||||
|
} else {
|
||||||
|
m_config->set_scalar(keyval.first, keyval.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -56,6 +56,19 @@ public:
|
|||||||
return default_value;
|
return default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the top-level node identified by key to value
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
void set_scalar(const std::string &key, const T& value)
|
||||||
|
{
|
||||||
|
auto node = m_root;
|
||||||
|
if (node.IsDefined())
|
||||||
|
{
|
||||||
|
node[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a scalar value defined inside a 2 level nested structure like:
|
* Get a scalar value defined inside a 2 level nested structure like:
|
||||||
* file_output:
|
* file_output:
|
||||||
@ -84,6 +97,19 @@ public:
|
|||||||
return default_value;
|
return default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the second-level node identified by key[key][subkey] to value.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
void set_scalar(const std::string& key, const std::string& subkey, const T& value)
|
||||||
|
{
|
||||||
|
auto node = m_root;
|
||||||
|
if (node.IsDefined())
|
||||||
|
{
|
||||||
|
node[key][subkey] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
YAML::Node m_root;
|
YAML::Node m_root;
|
||||||
};
|
};
|
||||||
@ -92,12 +118,23 @@ private:
|
|||||||
class falco_configuration
|
class falco_configuration
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void init(std::string conf_filename);
|
void init(std::string conf_filename, std::list<std::string> &cmdline_options);
|
||||||
void init();
|
void init(std::list<std::string> &cmdline_options);
|
||||||
|
|
||||||
std::string m_rules_filename;
|
std::string m_rules_filename;
|
||||||
bool m_json_output;
|
bool m_json_output;
|
||||||
std::vector<output_config> m_outputs;
|
std::vector<output_config> m_outputs;
|
||||||
private:
|
private:
|
||||||
|
void init_cmdline_options(std::list<std::string> &cmdline_options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a <key>=<value> specifier, set the appropriate option
|
||||||
|
* in the underlying yaml config. <key> can contain '.'
|
||||||
|
* characters for nesting. Currently only 1- or 2- level keys
|
||||||
|
* are supported and only scalar values are supported.
|
||||||
|
*/
|
||||||
|
void set_cmdline_option(const std::string &spec);
|
||||||
|
|
||||||
yaml_configuration* m_config;
|
yaml_configuration* m_config;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,19 +29,18 @@ extern "C" {
|
|||||||
#include <yaml-cpp/yaml.h>
|
#include <yaml-cpp/yaml.h>
|
||||||
|
|
||||||
|
|
||||||
std::vector<string> valid_output_names {"stdout", "syslog"};
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Program help
|
// Program help
|
||||||
//
|
//
|
||||||
static void usage()
|
static void usage()
|
||||||
{
|
{
|
||||||
printf(
|
printf(
|
||||||
"Usage: falco [options] rules_filename\n\n"
|
"Usage: falco [options]\n\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
" -h, --help Print this page\n"
|
" -h, --help Print this page\n"
|
||||||
" -c Configuration file (default " FALCO_SOURCE_CONF_FILE ", " FALCO_INSTALL_CONF_FILE ")\n"
|
" -c Configuration file (default " FALCO_SOURCE_CONF_FILE ", " FALCO_INSTALL_CONF_FILE ")\n"
|
||||||
" -o Output type (options are 'stdout', 'syslog', default is 'stdout')\n"
|
" -o, --option <key>=<val> Set the value of option <key> to <val>. Overrides values in configuration file.\n"
|
||||||
|
" <key> can be a two-part <key>.<subkey>\n"
|
||||||
" -d, --daemon Run as a daemon\n"
|
" -d, --daemon Run as a daemon\n"
|
||||||
" -p, --pidfile <pid_file> When run as a daemon, write pid to specified file\n"
|
" -p, --pidfile <pid_file> When run as a daemon, write pid to specified file\n"
|
||||||
" -e <events_file> Read the events from <events_file> (in .scap format) instead of tapping into live.\n"
|
" -e <events_file> Read the events from <events_file> (in .scap format) instead of tapping into live.\n"
|
||||||
@ -50,9 +49,26 @@ static void usage()
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void display_fatal_err(const string &msg, bool daemon)
|
||||||
|
{
|
||||||
|
falco_logger::log(LOG_ERR, msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If stderr logging is not enabled, also log to stderr. When
|
||||||
|
* daemonized this will simply write to /dev/null.
|
||||||
|
*/
|
||||||
|
if (! falco_logger::log_stderr)
|
||||||
|
{
|
||||||
|
std::cerr << msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
string lua_on_event = "on_event";
|
string lua_on_event = "on_event";
|
||||||
string lua_add_output = "add_output";
|
string lua_add_output = "add_output";
|
||||||
|
|
||||||
|
// Splitting into key=value or key.subkey=value will be handled by configuration class.
|
||||||
|
std::list<string> cmdline_options;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Event processing loop
|
// Event processing loop
|
||||||
//
|
//
|
||||||
@ -194,7 +210,6 @@ int falco_init(int argc, char **argv)
|
|||||||
sinsp_evt::param_fmt event_buffer_format;
|
sinsp_evt::param_fmt event_buffer_format;
|
||||||
int long_index = 0;
|
int long_index = 0;
|
||||||
string lua_main_filename;
|
string lua_main_filename;
|
||||||
string output_name = "syslog";
|
|
||||||
string scap_filename;
|
string scap_filename;
|
||||||
string conf_filename;
|
string conf_filename;
|
||||||
string rules_filename;
|
string rules_filename;
|
||||||
@ -207,14 +222,15 @@ int falco_init(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
{"help", no_argument, 0, 'h' },
|
{"help", no_argument, 0, 'h' },
|
||||||
{"daemon", no_argument, 0, 'd' },
|
{"daemon", no_argument, 0, 'd' },
|
||||||
{"pidfile", required_argument, 0, 'd' },
|
{"option", required_argument, 0, 'o'},
|
||||||
|
{"pidfile", required_argument, 0, 'p' },
|
||||||
|
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
inspector = new sinsp();
|
inspector = new sinsp();
|
||||||
bool valid;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parse the args
|
// Parse the args
|
||||||
@ -232,12 +248,7 @@ int falco_init(int argc, char **argv)
|
|||||||
conf_filename = optarg;
|
conf_filename = optarg;
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
valid = std::find(valid_output_names.begin(), valid_output_names.end(), optarg) != valid_output_names.end();
|
cmdline_options.push_back(optarg);
|
||||||
if (!valid)
|
|
||||||
{
|
|
||||||
throw sinsp_exception(string("Invalid output name ") + optarg);
|
|
||||||
}
|
|
||||||
output_name = optarg;
|
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
scap_filename = optarg;
|
scap_filename = optarg;
|
||||||
@ -262,15 +273,7 @@ int falco_init(int argc, char **argv)
|
|||||||
|
|
||||||
// Some combinations of arguments are not allowed.
|
// Some combinations of arguments are not allowed.
|
||||||
if (daemon && pidfilename == "") {
|
if (daemon && pidfilename == "") {
|
||||||
falco_logger::log(LOG_ERR, "If -d is provided, a pid file must also be provided. Exiting.\n");
|
throw sinsp_exception("If -d is provided, a pid file must also be provided");
|
||||||
result = EXIT_FAILURE;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (daemon && output_name == "stdout") {
|
|
||||||
falco_logger::log(LOG_ERR, "If -d is provided, can not output to stdout. Exiting.\n");
|
|
||||||
result = EXIT_FAILURE;
|
|
||||||
goto exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ifstream* conf_stream;
|
ifstream* conf_stream;
|
||||||
@ -279,9 +282,7 @@ int falco_init(int argc, char **argv)
|
|||||||
conf_stream = new ifstream(conf_filename);
|
conf_stream = new ifstream(conf_filename);
|
||||||
if (!conf_stream->good())
|
if (!conf_stream->good())
|
||||||
{
|
{
|
||||||
falco_logger::log(LOG_ERR, "Could not find configuration file at " + conf_filename + ". Exiting.\n");
|
throw sinsp_exception("Could not find configuration file at " + conf_filename);
|
||||||
result = EXIT_FAILURE;
|
|
||||||
goto exit;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -308,13 +309,13 @@ int falco_init(int argc, char **argv)
|
|||||||
falco_configuration config;
|
falco_configuration config;
|
||||||
if (conf_filename.size())
|
if (conf_filename.size())
|
||||||
{
|
{
|
||||||
config.init(conf_filename);
|
config.init(conf_filename, cmdline_options);
|
||||||
// log after config init because config determines where logs go
|
// log after config init because config determines where logs go
|
||||||
falco_logger::log(LOG_INFO, "Falco initialized with configuration file " + conf_filename + "\n");
|
falco_logger::log(LOG_INFO, "Falco initialized with configuration file " + conf_filename + "\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
config.init();
|
config.init(cmdline_options);
|
||||||
falco_logger::log(LOG_INFO, "Falco initialized. No configuration file found, proceeding with defaults\n");
|
falco_logger::log(LOG_INFO, "Falco initialized. No configuration file found, proceeding with defaults\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,10 +442,13 @@ int falco_init(int argc, char **argv)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close stdin, stdout, stderr.
|
// Close stdin, stdout, stderr and reopen to /dev/null
|
||||||
close(0);
|
close(0);
|
||||||
close(1);
|
close(1);
|
||||||
close(2);
|
close(2);
|
||||||
|
open("/dev/null", O_RDONLY);
|
||||||
|
open("/dev/null", O_RDWR);
|
||||||
|
open("/dev/null", O_RDWR);
|
||||||
}
|
}
|
||||||
|
|
||||||
do_inspect(inspector,
|
do_inspect(inspector,
|
||||||
@ -455,13 +459,13 @@ int falco_init(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
catch(sinsp_exception& e)
|
catch(sinsp_exception& e)
|
||||||
{
|
{
|
||||||
falco_logger::log(LOG_ERR, "Runtime error: " + string(e.what()) + ". Exiting.\n");
|
display_fatal_err("Runtime error: " + string(e.what()) + ". Exiting.\n", daemon);
|
||||||
|
|
||||||
result = EXIT_FAILURE;
|
result = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
falco_logger::log(LOG_ERR, "Unexpected error, Exiting\n");
|
display_fatal_err("Unexpected error, Exiting\n", daemon);
|
||||||
|
|
||||||
result = EXIT_FAILURE;
|
result = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user