mirror of
https://github.com/falcosecurity/falco.git
synced 2025-08-01 22:47:46 +00:00
Application changes to support actions
Changes to the falco::app::application object to support actions: - All of the code that was in falco_init is now in methods of application. (A later commit actually moves the code from falco_init and into the split-up methods, this commit just declares them). - Methods return an application::run_result object, which is a tuple of success/errstr/proceed. proceed=false is used to short circuit calling methods (think --help, --list, --support, etc.) - application now has a run() method which runs the methods in an order that honors any implicit dependencies (e.g. you have to init an inspector before you open it, you have to do almost everything else before processing events, etc.) - There are a few methods devoted to teardown, they are always called after the group of run methods are called. - State that needs to be saved between methods, or saved between the run and teardown functions, is in a falco::app::application::state object. Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
This commit is contained in:
parent
0a51f4f1f1
commit
9de80b7b92
@ -24,9 +24,40 @@ limitations under the License.
|
||||
#include "application.h"
|
||||
#include "falco_common.h"
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
||||
namespace falco {
|
||||
namespace app {
|
||||
|
||||
std::string application::s_syscall_source = falco_common::syscall_source;
|
||||
std::string application::s_k8s_audit_source = "k8s_audit";
|
||||
|
||||
application::run_result::run_result()
|
||||
: success(true), errstr(""), proceed(true)
|
||||
{
|
||||
}
|
||||
|
||||
application::run_result::~run_result()
|
||||
{
|
||||
}
|
||||
|
||||
application::state::state()
|
||||
: restart(false),
|
||||
terminate(false),
|
||||
reopen_outputs(false),
|
||||
enabled_sources({application::s_syscall_source, application::s_k8s_audit_source}),
|
||||
trace_is_scap(true)
|
||||
{
|
||||
config = std::make_shared<falco_configuration>();
|
||||
outputs = std::make_shared<falco_outputs>();
|
||||
engine = std::make_shared<falco_engine>();
|
||||
inspector = std::make_shared<sinsp>();
|
||||
}
|
||||
|
||||
application::state::~state()
|
||||
{
|
||||
}
|
||||
|
||||
application::application()
|
||||
: m_initialized(false)
|
||||
{
|
||||
@ -36,26 +67,129 @@ application::~application()
|
||||
{
|
||||
}
|
||||
|
||||
cmdline_options &application::options()
|
||||
void application::terminate()
|
||||
{
|
||||
if(!m_initialized)
|
||||
if(m_state != nullptr)
|
||||
{
|
||||
throw falco_exception("App init() not called yet");
|
||||
m_state->terminate = true;
|
||||
}
|
||||
}
|
||||
|
||||
return m_cmdline_options;
|
||||
void application::reopen_outputs()
|
||||
{
|
||||
if(m_state != nullptr)
|
||||
{
|
||||
m_state->reopen_outputs = true;
|
||||
}
|
||||
}
|
||||
|
||||
void application::restart()
|
||||
{
|
||||
if(m_state != nullptr)
|
||||
{
|
||||
m_state->restart = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool application::init(int argc, char **argv, std::string &errstr)
|
||||
{
|
||||
if(!m_cmdline_options.parse(argc, argv, errstr))
|
||||
if(m_initialized)
|
||||
{
|
||||
throw falco_exception("Application already initialized");
|
||||
}
|
||||
|
||||
m_state.reset(new state());
|
||||
|
||||
if(!m_options.parse(argc, argv, errstr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for(char **arg = argv; *arg; arg++)
|
||||
{
|
||||
if(m_state->cmdline.size() > 0)
|
||||
{
|
||||
m_state->cmdline += " ";
|
||||
}
|
||||
m_state->cmdline += *arg;
|
||||
}
|
||||
|
||||
m_initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool application::run(std::string &errstr, bool &restart)
|
||||
{
|
||||
run_result res;
|
||||
|
||||
// The order here is the order in which the methods will be
|
||||
// called. Before changing the order, ensure that all
|
||||
// dependencies are honored (e.g. don't process events before
|
||||
// loading plugins, opening inspector, etc.).
|
||||
std::list<std::function<run_result()>> run_steps = {
|
||||
std::bind(&application::print_help, this),
|
||||
std::bind(&application::print_version, this),
|
||||
std::bind(&application::create_signal_handlers, this),
|
||||
std::bind(&application::load_config, this),
|
||||
std::bind(&application::init_inspector, this),
|
||||
std::bind(&application::init_falco_engine, this),
|
||||
std::bind(&application::load_plugins, this),
|
||||
std::bind(&application::list_fields, this),
|
||||
std::bind(&application::list_plugins, this),
|
||||
std::bind(&application::load_rules_files, this),
|
||||
std::bind(&application::print_ignored_events, this),
|
||||
std::bind(&application::print_support, this),
|
||||
std::bind(&application::validate_rules_files, this),
|
||||
std::bind(&application::daemonize, this),
|
||||
std::bind(&application::init_outputs, this),
|
||||
std::bind(&application::open_inspector, this),
|
||||
#ifndef MINIMAL_BUILD
|
||||
std::bind(&application::start_grpc_server, this),
|
||||
std::bind(&application::start_webserver, this),
|
||||
#endif
|
||||
std::bind(&application::process_events, this)
|
||||
};
|
||||
|
||||
std::list<std::function<bool(std::string &)>> teardown_steps = {
|
||||
std::bind(&application::close_inspector, this, _1),
|
||||
std::bind(&application::unregister_signal_handlers, this, _1),
|
||||
#ifndef MINIMAL_BUILD
|
||||
std::bind(&application::stop_grpc_server, this, _1),
|
||||
std::bind(&application::stop_webserver, this, _1)
|
||||
#endif
|
||||
};
|
||||
|
||||
for (auto &func : run_steps)
|
||||
{
|
||||
res = func();
|
||||
|
||||
if(!res.proceed)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &func : teardown_steps)
|
||||
{
|
||||
std::string errstr;
|
||||
|
||||
if(!func(errstr))
|
||||
{
|
||||
// Note only printing warning here--we want all functions
|
||||
// to occur even if some return errors.
|
||||
fprintf(stderr, "Could not tear down in run(): %s\n", errstr.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if(!res.success)
|
||||
{
|
||||
errstr = res.errstr;
|
||||
}
|
||||
|
||||
restart = m_state->restart;
|
||||
|
||||
return res.success;
|
||||
}
|
||||
|
||||
}; // namespace app
|
||||
}; // namespace falco
|
||||
|
@ -14,19 +14,14 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// The falco "app" will eventually replace the monolithic code in
|
||||
// falco.cpp. We expect it will be responsible for the following:
|
||||
// - Parsing/validating command line options
|
||||
// - Parsing/validating falco config
|
||||
// - Initialize prerequisites (inspector, falco engine, webserver, etc)
|
||||
// - Loading plugins
|
||||
// - Loading/validating rules
|
||||
// - Command/subcommand execution (e.g. --list/--list-fields, or
|
||||
// nothing specified to run "main" loop)
|
||||
|
||||
// For now, it is only responsible for command line options.
|
||||
#pragma once
|
||||
|
||||
#include "configuration.h"
|
||||
#ifndef MINIMAL_BUILD
|
||||
#include "grpc_server.h"
|
||||
#include "webserver.h"
|
||||
#endif
|
||||
|
||||
#include "app_cmdline_options.h"
|
||||
|
||||
#include <string>
|
||||
@ -36,16 +31,150 @@ namespace app {
|
||||
|
||||
class application {
|
||||
public:
|
||||
|
||||
application();
|
||||
virtual ~application();
|
||||
|
||||
cmdline_options &options();
|
||||
// These are only used in signal handlers. Other than there,
|
||||
// the control flow of the application should not be changed
|
||||
// from the outside.
|
||||
void terminate();
|
||||
void reopen_outputs();
|
||||
void restart();
|
||||
|
||||
bool init(int argc, char **argv, std::string &errstr);
|
||||
|
||||
private:
|
||||
// Returns whether the application completed with errors or
|
||||
// not. errstr will contain details when run() returns false.
|
||||
//
|
||||
// If restart (generally set by signal handlers) is
|
||||
// true, the application should be restarted instead of
|
||||
// exiting.
|
||||
bool run(std::string &errstr, bool &restart);
|
||||
|
||||
cmdline_options m_cmdline_options;
|
||||
private:
|
||||
static std::string s_syscall_source;
|
||||
static std::string s_k8s_audit_source;
|
||||
|
||||
// Holds the state used and shared by the below methods that
|
||||
// actually implement the application. Declared as a
|
||||
// standalone class to allow for a bit of separation between
|
||||
// application state and instance variables, and to also defer
|
||||
// initializing this state until application::init.
|
||||
class state {
|
||||
public:
|
||||
state();
|
||||
virtual ~state();
|
||||
|
||||
bool restart;
|
||||
bool terminate;
|
||||
bool reopen_outputs;
|
||||
|
||||
std::shared_ptr<falco_configuration> config;
|
||||
std::shared_ptr<falco_outputs> outputs;
|
||||
std::shared_ptr<falco_engine> engine;
|
||||
std::shared_ptr<sinsp> inspector;
|
||||
std::set<std::string> enabled_sources;
|
||||
|
||||
// The event sources that correspond to "syscalls" and
|
||||
// "k8s_audit events".
|
||||
std::size_t syscall_source_idx;
|
||||
std::size_t k8s_audit_source_idx;
|
||||
|
||||
// The event source actually used to process events in
|
||||
// process_events(). Will generally be
|
||||
// syscall_source_idx, or a plugin index if plugins
|
||||
// are loaded.
|
||||
std::size_t event_source_idx;
|
||||
|
||||
std::list<sinsp_plugin::info> plugin_infos;
|
||||
|
||||
// All filterchecks created by plugins go in this
|
||||
// list. If we ever support multiple event sources at
|
||||
// the same time, this, and the factories created in
|
||||
// init_inspector/load_plugins, will have to be a map
|
||||
// from event source to filtercheck list.
|
||||
filter_check_list plugin_filter_checks;
|
||||
|
||||
std::map<string,uint64_t> required_engine_versions;
|
||||
|
||||
std::string cmdline;
|
||||
|
||||
bool trace_is_scap;
|
||||
#ifndef MINIMAL_BUILD
|
||||
falco::grpc::server grpc_server;
|
||||
std::thread grpc_server_thread;
|
||||
|
||||
falco_webserver webserver;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Used in the below methods to indicate how to proceed.
|
||||
struct run_result {
|
||||
|
||||
run_result();
|
||||
virtual ~run_result();
|
||||
|
||||
// If true, the method completed successfully.
|
||||
bool success;
|
||||
|
||||
// If success==false, details on the error.
|
||||
std::string errstr;
|
||||
|
||||
// If true, subsequent methods should be performed. If
|
||||
// false, subsequent methods should *not* be performed
|
||||
// and falco should tear down/exit/restart.
|
||||
bool proceed;
|
||||
};
|
||||
|
||||
// These methods comprise the code the application "runs". The
|
||||
// order in which the methods run is in application.cpp.
|
||||
run_result create_signal_handlers();
|
||||
run_result daemonize();
|
||||
run_result init_falco_engine();
|
||||
run_result init_inspector();
|
||||
run_result init_outputs();
|
||||
run_result list_fields();
|
||||
run_result list_plugins();
|
||||
run_result load_config();
|
||||
run_result load_plugins();
|
||||
run_result load_rules_files();
|
||||
run_result open_inspector();
|
||||
run_result print_help();
|
||||
run_result print_ignored_events();
|
||||
run_result print_support();
|
||||
run_result print_version();
|
||||
run_result process_events();
|
||||
#ifndef MINIMAL_BUILD
|
||||
run_result start_grpc_server();
|
||||
run_result start_webserver();
|
||||
#endif
|
||||
run_result validate_rules_files();
|
||||
|
||||
// These methods comprise application teardown. The order in
|
||||
// which the methods run is in application.cpp.
|
||||
bool close_inspector(std::string &errstr);
|
||||
bool unregister_signal_handlers(std::string &errstr);
|
||||
#ifndef MINIMAL_BUILD
|
||||
bool stop_grpc_server(std::string &errstr);
|
||||
bool stop_webserver(std::string &errstr);
|
||||
#endif
|
||||
|
||||
// Methods called by the above methods
|
||||
bool create_handler(int sig, void (*func)(int), run_result &ret);
|
||||
void configure_output_format();
|
||||
void check_for_ignored_events();
|
||||
void print_all_ignored_events();
|
||||
void read_k8s_audit_trace_file(string &trace_filename);
|
||||
uint64_t do_inspect(syscall_evt_drop_mgr &sdropmgr,
|
||||
uint64_t duration_to_tot_ns,
|
||||
run_result &result);
|
||||
|
||||
// This could probably become a direct object once lua is
|
||||
// removed from falco. Currently, creating any global
|
||||
// application object results in a crash in
|
||||
// falco_common::init(), as it loads all lua modules.
|
||||
std::unique_ptr<state> m_state;
|
||||
cmdline_options m_options;
|
||||
bool m_initialized;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user