Compare commits

...

3 Commits

Author SHA1 Message Date
Leonardo Di Donato
4616be1183 update(userspace/falco): initial CLI porting to cxxopts
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-12-16 14:24:32 +00:00
Leonardo Di Donato
dcbc509887 chore(userspace/falco): temporarily disabling the CLI and the startup
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-12-16 14:24:06 +00:00
Leonardo Di Donato
fa6e143a25 build(cmake/modules): download cxxopts lib
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2020-12-16 14:23:18 +00:00
6 changed files with 566 additions and 317 deletions

View File

@@ -176,9 +176,12 @@ if(NOT MINIMAL_BUILD)
INSTALL_COMMAND ${CMD_MAKE} COPT="-DNO_FILES" install-lib install-headers PREFIX=${CIVETWEB_SRC}/install "WITH_CPP=1") INSTALL_COMMAND ${CMD_MAKE} COPT="-DNO_FILES" install-lib install-headers PREFIX=${CIVETWEB_SRC}/install "WITH_CPP=1")
endif() endif()
#string-view-lite # string-view-lite
include(DownloadStringViewLite) include(DownloadStringViewLite)
# cxxopts
include(DownloadCxxOpts)
if(NOT MINIMAL_BUILD) if(NOT MINIMAL_BUILD)
# gRPC # gRPC
include(gRPC) include(gRPC)

View File

@@ -0,0 +1,28 @@
#
# Copyright (C) 2020 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(ExternalProject)
set(CXXOPTS_PREFIX ${CMAKE_BINARY_DIR}/cxxopts-prefix)
set(CXXOPTS_INCLUDE ${CXXOPTS_PREFIX}/include)
message(STATUS "Using bundled cxxopts in ${CXXOPTS_INCLUDE}")
ExternalProject_Add(
cxxopts
PREFIX ${CXXOPTS_PREFIX}
GIT_REPOSITORY "https://github.com/jarro2783/cxxopts.git"
GIT_TAG "master"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy ${CXXOPTS_PREFIX}/src/cxxopts/include/cxxopts.hpp
${CXXOPTS_INCLUDE}/cxxopts.hpp)

View File

@@ -15,6 +15,7 @@ configure_file(config_falco.h.in config_falco.h)
set( set(
FALCO_SOURCES FALCO_SOURCES
cli.cpp
configuration.cpp configuration.cpp
logger.cpp logger.cpp
falco_outputs.cpp falco_outputs.cpp
@@ -34,6 +35,7 @@ set(
"${PROJECT_BINARY_DIR}/userspace/falco" "${PROJECT_BINARY_DIR}/userspace/falco"
"${PROJECT_BINARY_DIR}/driver/src" "${PROJECT_BINARY_DIR}/driver/src"
"${STRING_VIEW_LITE_INCLUDE}" "${STRING_VIEW_LITE_INCLUDE}"
"${CXXOPTS_INCLUDE}"
"${YAMLCPP_INCLUDE_DIR}" "${YAMLCPP_INCLUDE_DIR}"
"${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}"
"${DRAIOS_DEPENDENCIES_DIR}/yaml-${DRAIOS_YAML_VERSION}/target/include" "${DRAIOS_DEPENDENCIES_DIR}/yaml-${DRAIOS_YAML_VERSION}/target/include"
@@ -41,6 +43,7 @@ set(
set( set(
FALCO_DEPENDENCIES FALCO_DEPENDENCIES
cxxopts
string-view-lite string-view-lite
libyaml libyaml
b64 b64
@@ -123,16 +126,16 @@ target_include_directories(
${FALCO_INCLUDE_DIRECTORIES} ${FALCO_INCLUDE_DIRECTORIES}
) )
if(NOT MINIMAL_BUILD) # if(NOT MINIMAL_BUILD)
add_custom_command( # add_custom_command(
TARGET falco # TARGET falco
COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/verify_engine_fields.sh ${CMAKE_SOURCE_DIR} # COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/verify_engine_fields.sh ${CMAKE_SOURCE_DIR}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} # WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Comparing engine fields checksum in falco_engine.h to actual fields" # COMMENT "Comparing engine fields checksum in falco_engine.h to actual fields"
) # )
else() # else()
message(STATUS "Skipping engine fields checksum when building the minimal Falco.") # message(STATUS "Skipping engine fields checksum when building the minimal Falco.")
endif() # endif()
if(NOT MINIMAL_BUILD) if(NOT MINIMAL_BUILD)
add_custom_command( add_custom_command(

22
userspace/falco/cli.cpp Normal file
View File

@@ -0,0 +1,22 @@
/*
Copyright (C) 2020 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 "cli.h"
namespace falco
{
} // namespace falco

188
userspace/falco/cli.h Normal file
View File

@@ -0,0 +1,188 @@
/*
Copyright (C) 2020 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 <cxxopts.hpp>
namespace falco
{
class option_requires_specific_argument_exception : public cxxopts::OptionParseException
{
public:
explicit option_requires_specific_argument_exception(const std::string& option, const std::string& values):
OptionParseException("Option " + cxxopts::LQUOTE + option + cxxopts::RQUOTE + " requires an argument equal to " + values)
{
}
};
class option_cannot_be_specified_exception : public cxxopts::OptionParseException
{
public:
explicit option_cannot_be_specified_exception(const std::string& option1, const std::string& option2):
OptionParseException("Options " + cxxopts::LQUOTE + option1 + cxxopts::RQUOTE + " and " + cxxopts::LQUOTE + option2 + cxxopts::RQUOTE + " can not be specified together")
{
}
};
class cli
{
public:
cli(int argc, const char** argv):
m_argc(argc), m_argv(argv), m_options("falco", "Cloud-Native Runtime Security")
{
}
virtual ~cli()
{
}
void run()
{
// These options give some info about Falco (Falco exits).
m_options.add_options(
"help",
{
{"h,help", "Print help page."},
{"support", "Print support information (version, rules files, etc.)."},
{"version", "Print version info."},
});
// These are options responsible for listing Falco elements (Falco exits).
m_options.add_options(
"list",
{
{"L", "Show name and description of all rules."},
{"l", "Show name and description of a specific rule.", cxxopts::value<std::string>(), "rule name"},
{"list", "Show all fields.", cxxopts::value<std::string>()->implicit_value("all"), "sycall|k8s_audit"},
{"N", "Show field names only."},
});
// m_options.add_options(
// "output",
// {
// {},
// });
// m_options.add_options(
// "input",
// {
// {},
// });
m_options.add_options(
"filtering",
{
{"D", "Disable any rules with names having the given substring. Can be specified multiple times. Can not be specified with -t.", cxxopts::value<std::vector<std::string>>(), "substring"},
{"T", "Disable any rules with a specific tag. Can be specified several times. Can not be specified with -t.", cxxopts::value<std::vector<std::string>>(), "tag"},
{"t", "Only run those rules with a specific tag. Can be specified several times. Can not be specified with -T or -D.", cxxopts::value<std::vector<std::string>>(), "tag"},
});
m_result = m_options.parse(m_argc, m_argv);
process();
}
private:
void process()
{
if(m_result.count("help") && m_result["help"].as<bool>())
{
std::cout << m_options.help() << std::endl;
// todo: print > exit
}
if(m_result.count("support") && m_result["support"].as<bool>())
{
// todo: argv + config rule filenames > cmdline > print > exit
}
if(m_result.count("version") && m_result["version"].as<bool>())
{
// todo: print > exit
}
if(m_result.count("L") && m_result["L"].as<bool>())
{
// todo: engine > print > exit
// engine->describe_rule(NULL)
}
if(m_result.count("l"))
{
// todo: engine > print > exit
// engine->describe_rule(m_result["l"].as<string>());
}
if(m_result.count("list"))
{
auto source = m_result["list"].as<std::string>();
// todo: retrieve implicit value
if(source.empty() || (source != "syscall" && source != "k8s_audit" && source != "all"))
{
throw falco::option_requires_specific_argument_exception(
"list",
cxxopts::LQUOTE + "syscall" + cxxopts::RQUOTE + " or " + cxxopts::LQUOTE + "k8s_audit" + cxxopts::RQUOTE);
}
bool names_only = false;
if(m_result.count("N"))
{
names_only = m_result["N"].as<bool>();
}
// todo: engine + names_only + source
// se valore == syscall ==> + [-V]
}
bool count_D = m_result.count("D");
bool count_t = m_result.count("t");
bool count_T = m_result.count("T");
if(count_D > 0)
{
if(count_t > 0)
{
throw falco::option_cannot_be_specified_exception("D", "t");
}
// todo
// engine > not exit
}
if(count_T > 0)
{
if(count_t > 0)
{
throw falco::option_cannot_be_specified_exception("T", "t");
}
// todo
// engine > not exit
}
if(count_t > 0)
{
// todo
// engine > not exit
}
}
int m_argc;
const char** m_argv;
cxxopts::Options m_options;
cxxopts::ParseResult m_result;
};
} // namespace falco
// 3 tipi di azioni
// quelle che una volta date devono farlo uscire e non hanno bisogno di nessuna istanza
// quelle che hanno bisogno di inspector e/o engine e poi falco esce
// quelle che hanno bisogno di inspector e/o engine e poi falco esegue

View File

@@ -43,6 +43,7 @@ limitations under the License.
#include "falco_engine.h" #include "falco_engine.h"
#include "config_falco.h" #include "config_falco.h"
#include "statsfilewriter.h" #include "statsfilewriter.h"
#include "cli.h"
#ifndef MINIMAL_BUILD #ifndef MINIMAL_BUILD
#include "webserver.h" #include "webserver.h"
#include "grpc_server.h" #include "grpc_server.h"
@@ -74,106 +75,102 @@ static void restart_falco(int signal)
g_restart = true; g_restart = true;
} }
// // //
// Program help // // Program help
// // //
static void usage() // static void usage()
{ // {
printf( // printf(
"Falco version: " FALCO_VERSION "\n" // "Falco version: " FALCO_VERSION "\n"
"Usage: falco [options]\n\n" // "Usage: falco [options]\n\n"
"Options:\n" // "Options:\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"
" -A Monitor all events, including those with EF_DROP_SIMPLE_CONS flag.\n" // " -A Monitor all events, including those with EF_DROP_SIMPLE_CONS flag.\n"
" --alternate-lua-dir <path> Specify an alternate path for loading Falco lua files\n" // " --alternate-lua-dir <path> Specify an alternate path for loading Falco lua files\n"
" -b, --print-base64 Print data buffers in base64.\n" // " -b, --print-base64 Print data buffers in base64.\n"
" This is useful for encoding binary data that needs to be used over media designed to.\n" // " This is useful for encoding binary data that needs to be used over media designed to.\n"
" --cri <path> Path to CRI socket for container metadata.\n" // " --cri <path> Path to CRI socket for container metadata.\n"
" Use the specified socket to fetch data from a CRI-compatible runtime.\n" // " Use the specified socket to fetch data from a CRI-compatible runtime.\n"
" -d, --daemon Run as a daemon.\n" // " -d, --daemon Run as a daemon.\n"
" --disable-cri-async Disable asynchronous CRI metadata fetching.\n" // " --disable-cri-async Disable asynchronous CRI metadata fetching.\n"
" This is useful to let the input event wait for the container metadata fetch\n" // " This is useful to let the input event wait for the container metadata fetch\n"
" to finish before moving forward. Async fetching, in some environments leads\n" // " to finish before moving forward. Async fetching, in some environments leads\n"
" to empty fields for container metadata when the fetch is not fast enough to be\n" // " to empty fields for container metadata when the fetch is not fast enough to be\n"
" completed asynchronously. This can have a performance penalty on your environment\n" // " completed asynchronously. This can have a performance penalty on your environment\n"
" depending on the number of containers and the frequency at which they are created/started/stopped\n" // " depending on the number of containers and the frequency at which they are created/started/stopped\n"
" --disable-source <event_source>\n" // " --disable-source <event_source>\n"
" Disable a specific event source.\n" // " Disable a specific event source.\n"
" Available event sources are: syscall, k8s_audit.\n" // " Available event sources are: syscall, k8s_audit.\n"
" It can be passed multiple times.\n" // " It can be passed multiple times.\n"
" Can not disable both the event sources.\n" // " Can not disable both the event sources.\n"
" -D <substring> Disable any rules with names having the substring <substring>. Can be specified multiple times.\n"
" Can not be specified with -t.\n" // " -e <events_file> Read the events from <events_file> (in .scap format for sinsp events, or jsonl for\n"
" -e <events_file> Read the events from <events_file> (in .scap format for sinsp events, or jsonl for\n" // " k8s audit events) instead of tapping into live.\n"
" k8s audit events) instead of tapping into live.\n" // #ifndef MINIMAL_BUILD
#ifndef MINIMAL_BUILD // " -k <url>, --k8s-api <url>\n"
" -k <url>, --k8s-api <url>\n" // " Enable Kubernetes support by connecting to the API server specified as argument.\n"
" Enable Kubernetes support by connecting to the API server specified as argument.\n" // " E.g. \"http://admin:password@127.0.0.1:8080\".\n"
" E.g. \"http://admin:password@127.0.0.1:8080\".\n" // " The API server can also be specified via the environment variable FALCO_K8S_API.\n"
" The API server can also be specified via the environment variable FALCO_K8S_API.\n" // " -K <bt_file> | <cert_file>:<key_file[#password]>[:<ca_cert_file>], --k8s-api-cert <bt_file> | <cert_file>:<key_file[#password]>[:<ca_cert_file>]\n"
" -K <bt_file> | <cert_file>:<key_file[#password]>[:<ca_cert_file>], --k8s-api-cert <bt_file> | <cert_file>:<key_file[#password]>[:<ca_cert_file>]\n" // " Use the provided files names to authenticate user and (optionally) verify the K8S API server identity.\n"
" Use the provided files names to authenticate user and (optionally) verify the K8S API server identity.\n" // " Each entry must specify full (absolute, or relative to the current directory) path to the respective file.\n"
" Each entry must specify full (absolute, or relative to the current directory) path to the respective file.\n" // " Private key password is optional (needed only if key is password protected).\n"
" Private key password is optional (needed only if key is password protected).\n" // " CA certificate is optional. For all files, only PEM file format is supported. \n"
" CA certificate is optional. For all files, only PEM file format is supported. \n" // " Specifying CA certificate only is obsoleted - when single entry is provided \n"
" Specifying CA certificate only is obsoleted - when single entry is provided \n" // " for this option, it will be interpreted as the name of a file containing bearer token.\n"
" for this option, it will be interpreted as the name of a file containing bearer token.\n" // " Note that the format of this command-line option prohibits use of files whose names contain\n"
" Note that the format of this command-line option prohibits use of files whose names contain\n" // " ':' or '#' characters in the file name.\n"
" ':' or '#' characters in the file name.\n" // #endif
#endif
" -L Show the name and description of all rules and exit.\n"
" -l <rule> Show the name and description of the rule with name <rule> and exit.\n"
" --list [<source>] List all defined fields. If <source> is provided, only list those fields for\n"
" the source <source>. Current values for <source> are \"syscall\", \"k8s_audit\"\n" // #ifndef MINIMAL_BUILD
#ifndef MINIMAL_BUILD // " -m <url[,marathon_url]>, --mesos-api <url[,marathon_url]>\n"
" -m <url[,marathon_url]>, --mesos-api <url[,marathon_url]>\n" // " Enable Mesos support by connecting to the API server\n"
" Enable Mesos support by connecting to the API server\n" // " specified as argument. E.g. \"http://admin:password@127.0.0.1:5050\".\n"
" specified as argument. E.g. \"http://admin:password@127.0.0.1:5050\".\n" // " Marathon url is optional and defaults to Mesos address, port 8080.\n"
" Marathon url is optional and defaults to Mesos address, port 8080.\n" // " The API servers can also be specified via the environment variable FALCO_MESOS_API.\n"
" The API servers can also be specified via the environment variable FALCO_MESOS_API.\n" // #endif
#endif // " -M <num_seconds> Stop collecting after <num_seconds> reached.\n"
" -M <num_seconds> Stop collecting after <num_seconds> reached.\n"
" -N When used with --list, only print field names.\n" // " -o, --option <key>=<val> Set the value of option <key> to <val>. Overrides values in configuration file.\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"
" <key> can be a two-part <key>.<subkey>\n" // " -p <output_format>, --print <output_format>\n"
" -p <output_format>, --print <output_format>\n" // " Add additional information to each falco notification's output.\n"
" Add additional information to each falco notification's output.\n" // " With -pc or -pcontainer will use a container-friendly format.\n"
" With -pc or -pcontainer will use a container-friendly format.\n" // " With -pk or -pkubernetes will use a kubernetes-friendly format.\n"
" With -pk or -pkubernetes will use a kubernetes-friendly format.\n" // " With -pm or -pmesos will use a mesos-friendly format.\n"
" With -pm or -pmesos will use a mesos-friendly format.\n" // " Additionally, specifying -pc/-pk/-pm will change the interpretation\n"
" Additionally, specifying -pc/-pk/-pm will change the interpretation\n" // " of %%container.info in rule output fields.\n"
" of %%container.info in rule output fields.\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" // " -r <rules_file> Rules file/directory (defaults to value set in configuration file, or /etc/falco_rules.yaml).\n"
" -r <rules_file> Rules file/directory (defaults to value set in configuration file, or /etc/falco_rules.yaml).\n" // " Can be specified multiple times to read from multiple files/directories.\n"
" Can be specified multiple times to read from multiple files/directories.\n" // " -s <stats_file> If specified, append statistics related to Falco's reading/processing of events\n"
" -s <stats_file> If specified, append statistics related to Falco's reading/processing of events\n" // " to this file (only useful in live mode).\n"
" to this file (only useful in live mode).\n" // " --stats-interval <msec> When using -s <stats_file>, write statistics every <msec> ms.\n"
" --stats-interval <msec> When using -s <stats_file>, write statistics every <msec> ms.\n" // " This uses signals, so don't recommend intervals below 200 ms.\n"
" This uses signals, so don't recommend intervals below 200 ms.\n" // " Defaults to 5000 (5 seconds).\n"
" Defaults to 5000 (5 seconds).\n" // " -S <len>, --snaplen <len>\n"
" -S <len>, --snaplen <len>\n" // " Capture the first <len> bytes of each I/O buffer.\n"
" Capture the first <len> bytes of each I/O buffer.\n" // " By default, the first 80 bytes are captured. Use this\n"
" By default, the first 80 bytes are captured. Use this\n" // " option with caution, it can generate huge trace files.\n"
" option with caution, it can generate huge trace files.\n"
" --support Print support information including version, rules files used, etc. and exit.\n"
" -T <tag> Disable any rules with a tag=<tag>. Can be specified multiple times.\n" // " -U,--unbuffered Turn off output buffering to configured outputs.\n"
" Can not be specified with -t.\n" // " This causes every single line emitted by falco to be flushed,\n"
" -t <tag> Only run those rules with a tag=<tag>. Can be specified multiple times.\n" // " which generates higher CPU usage but is useful when piping those outputs\n"
" Can not be specified with -T/-D.\n" // " into another process or into a script.\n"
" -U,--unbuffered Turn off output buffering to configured outputs.\n" // " -u, --userspace Parse events from userspace.\n"
" This causes every single line emitted by falco to be flushed,\n" // " To be used in conjunction with the ptrace(2) based driver (pdig).\n"
" which generates higher CPU usage but is useful when piping those outputs\n" // " -V, --validate <rules_file> Read the contents of the specified rules(s) file and exit.\n"
" into another process or into a script.\n" // " Can be specified multiple times to validate multiple files.\n"
" -u, --userspace Parse events from userspace.\n" // " -v Verbose output.\n"
" To be used in conjunction with the ptrace(2) based driver (pdig).\n"
" -V, --validate <rules_file> Read the contents of the specified rules(s) file and exit.\n" // "\n"
" Can be specified multiple times to validate multiple files.\n" // );
" -v Verbose output.\n" // }
" --version Print version number.\n"
"\n"
);
}
static void display_fatal_err(const string &msg) static void display_fatal_err(const string &msg)
{ {
@@ -395,8 +392,7 @@ static void print_all_ignored_events(sinsp *inspector)
static void list_source_fields(falco_engine *engine, bool verbose, bool names_only, std::string &source) static void list_source_fields(falco_engine *engine, bool verbose, bool names_only, std::string &source)
{ {
if(source.size() > 0 && if(!source.empty() && !(source == "syscall" || source == "k8s_audit"))
!(source == "syscall" || source == "k8s_audit"))
{ {
throw std::invalid_argument("Value for --list must be \"syscall\" or \"k8s_audit\""); throw std::invalid_argument("Value for --list must be \"syscall\" or \"k8s_audit\"");
} }
@@ -413,7 +409,7 @@ static void list_source_fields(falco_engine *engine, bool verbose, bool names_on
// //
// ARGUMENT PARSING AND PROGRAM SETUP // ARGUMENT PARSING AND PROGRAM SETUP
// //
int falco_init(int argc, char **argv) int falco_init()
{ {
int result = EXIT_SUCCESS; int result = EXIT_SUCCESS;
sinsp* inspector = NULL; sinsp* inspector = NULL;
@@ -514,198 +510,197 @@ int falco_init(int argc, char **argv)
set<string> disabled_rule_tags; set<string> disabled_rule_tags;
set<string> enabled_rule_tags; set<string> enabled_rule_tags;
// // //
// Parse the args // // Parse the args
// // //
while((op = getopt_long(argc, argv, // while((op = getopt_long(argc, argv,
"hc:AbdD:e:F:ik:K:Ll:m:M:No:P:p:r:S:s:T:t:UuvV:w:", // "hc:AbdD:e:F:ik:K:Ll:m:M:No:P:p:r:S:s:T:t:UuvV:w:",
long_options, &long_index)) != -1) // long_options, &long_index)) != -1)
{ // {
switch(op) // switch(op)
{ // {
case 'h': // case 'h':
usage(); // usage();
goto exit; // goto exit;
case 'c': // case 'c':
conf_filename = optarg; // conf_filename = optarg;
break; // break;
case 'A': // case 'A':
all_events = true; // all_events = true;
break; // break;
case 'b': // case 'b':
event_buffer_format = sinsp_evt::PF_BASE64; // event_buffer_format = sinsp_evt::PF_BASE64;
break; // break;
case 'd': // case 'd':
daemon = true; // daemon = true;
break; // break;
case 'D': // case 'D':
substring = optarg; // substring = optarg;
disabled_rule_substrings.insert(substring); // disabled_rule_substrings.insert(substring);
break; // break;
case 'e': // case 'e':
trace_filename = optarg; // trace_filename = optarg;
#ifndef MINIMAL_BUILD // #ifndef MINIMAL_BUILD
k8s_api = new string(); // k8s_api = new string();
mesos_api = new string(); // mesos_api = new string();
#endif // #endif
break; // break;
case 'F': // case 'F':
list_flds = optarg; // list_flds = optarg;
break; // break;
case 'i': // case 'i':
print_ignored_events = true; // print_ignored_events = true;
break; // break;
#ifndef MINIMAL_BUILD // #ifndef MINIMAL_BUILD
case 'k': // case 'k':
k8s_api = new string(optarg); // k8s_api = new string(optarg);
break; // break;
case 'K': // case 'K':
k8s_api_cert = new string(optarg); // k8s_api_cert = new string(optarg);
break; // break;
#endif // #endif
case 'L': // case 'L':
describe_all_rules = true; // describe_all_rules = true;
break; // break;
case 'l': // case 'l':
describe_rule = optarg; // describe_rule = optarg;
break; // break;
#ifndef MINIMAL_BUILD // #ifndef MINIMAL_BUILD
case 'm': // case 'm':
mesos_api = new string(optarg); // mesos_api = new string(optarg);
break; // break;
#endif // #endif
case 'M': // case 'M':
duration_to_tot = atoi(optarg); // duration_to_tot = atoi(optarg);
if(duration_to_tot <= 0) // if(duration_to_tot <= 0)
{ // {
throw sinsp_exception(string("invalid duration") + optarg); // throw sinsp_exception(string("invalid duration") + optarg);
} // }
break; // break;
case 'N': // case 'N':
names_only = true; // names_only = true;
break; // break;
case 'o': // case 'o':
cmdline_options.push_back(optarg); // cmdline_options.push_back(optarg);
break; // break;
case 'P': // case 'P':
pidfilename = optarg; // pidfilename = optarg;
break; // break;
case 'p': // case 'p':
if(string(optarg) == "c" || string(optarg) == "container") // if(string(optarg) == "c" || string(optarg) == "container")
{ // {
output_format = "container=%container.name (id=%container.id)"; // output_format = "container=%container.name (id=%container.id)";
replace_container_info = true; // replace_container_info = true;
} // }
else if(string(optarg) == "k" || string(optarg) == "kubernetes") // else if(string(optarg) == "k" || string(optarg) == "kubernetes")
{ // {
output_format = "k8s.ns=%k8s.ns.name k8s.pod=%k8s.pod.name container=%container.id"; // output_format = "k8s.ns=%k8s.ns.name k8s.pod=%k8s.pod.name container=%container.id";
replace_container_info = true; // replace_container_info = true;
} // }
else if(string(optarg) == "m" || string(optarg) == "mesos") // else if(string(optarg) == "m" || string(optarg) == "mesos")
{ // {
output_format = "task=%mesos.task.name container=%container.id"; // output_format = "task=%mesos.task.name container=%container.id";
replace_container_info = true; // replace_container_info = true;
} // }
else // else
{ // {
output_format = optarg; // output_format = optarg;
replace_container_info = false; // replace_container_info = false;
} // }
break; // break;
case 'r': // case 'r':
falco_configuration::read_rules_file_directory(string(optarg), rules_filenames); // falco_configuration::read_rules_file_directory(string(optarg), rules_filenames);
break; // break;
case 'S': // case 'S':
snaplen = atoi(optarg); // snaplen = atoi(optarg);
break; // break;
case 's': // case 's':
stats_filename = optarg; // stats_filename = optarg;
break; // break;
case 'T': // case 'T':
disabled_rule_tags.insert(optarg); // disabled_rule_tags.insert(optarg);
break; // break;
case 't': // case 't':
enabled_rule_tags.insert(optarg); // enabled_rule_tags.insert(optarg);
break; // break;
case 'U': // case 'U':
buffered_outputs = false; // buffered_outputs = false;
buffered_cmdline = true; // buffered_cmdline = true;
break; // break;
case 'u': // case 'u':
userspace = true; // userspace = true;
break; // break;
case 'v': // case 'v':
verbose = true; // verbose = true;
break; // break;
case 'V': // case 'V':
validate_rules_filenames.push_back(optarg); // validate_rules_filenames.push_back(optarg);
break; // break;
case 'w': // case 'w':
outfile = optarg; // outfile = optarg;
break; // break;
case '?': // case '?':
result = EXIT_FAILURE; // result = EXIT_FAILURE;
goto exit; // goto exit;
case 0: // case 0:
if(string(long_options[long_index].name) == "version") // if(string(long_options[long_index].name) == "version")
{ // {
printf("Falco version: %s\n", FALCO_VERSION); // printf("Falco version: %s\n", FALCO_VERSION);
printf("Driver version: %s\n", DRIVER_VERSION); // printf("Driver version: %s\n", DRIVER_VERSION);
return EXIT_SUCCESS; // return EXIT_SUCCESS;
} // }
else if (string(long_options[long_index].name) == "cri") // else if (string(long_options[long_index].name) == "cri")
{ // {
if(optarg != NULL) // if(optarg != NULL)
{ // {
cri_socket_path = optarg; // cri_socket_path = optarg;
} // }
} // }
else if (string(long_options[long_index].name) == "disable-cri-async") // else if (string(long_options[long_index].name) == "disable-cri-async")
{ // {
cri_async = false; // cri_async = false;
} // }
else if (string(long_options[long_index].name) == "list") // else if (string(long_options[long_index].name) == "list")
{ // {
list_flds = true; // list_flds = true;
if(optarg != NULL) // if(optarg != NULL)
{ // {
list_flds_source = optarg; // list_flds_source = optarg;
} // }
} // }
else if (string(long_options[long_index].name) == "stats-interval") // else if (string(long_options[long_index].name) == "stats-interval")
{ // {
stats_interval = atoi(optarg); // stats_interval = atoi(optarg);
} // }
else if (string(long_options[long_index].name) == "support") // else if (string(long_options[long_index].name) == "support")
{ // {
print_support = true; // print_support = true;
} // }
else if (string(long_options[long_index].name) == "disable-source") // else if (string(long_options[long_index].name) == "disable-source")
{ // {
if(optarg != NULL) // if(optarg != NULL)
{ // {
disable_sources.insert(optarg); // disable_sources.insert(optarg);
} // }
} // }
else if (string(long_options[long_index].name)== "alternate-lua-dir") // else if (string(long_options[long_index].name)== "alternate-lua-dir")
{ // {
if(optarg != NULL) // if(optarg != NULL)
{ // {
alternate_lua_dir = optarg; // alternate_lua_dir = optarg;
if (alternate_lua_dir.back() != '/') { // if (alternate_lua_dir.back() != '/') {
alternate_lua_dir += '/'; // alternate_lua_dir += '/';
} // }
} // }
} // }
break; // break;
default: // default:
break; // break;
} // }
}
// }
inspector = new sinsp(); inspector = new sinsp();
inspector->set_buffer_format(event_buffer_format); inspector->set_buffer_format(event_buffer_format);
@@ -921,14 +916,14 @@ int falco_init(int argc, char **argv)
throw std::runtime_error(string("Could not uname() to find system info: %s\n") + strerror(errno)); throw std::runtime_error(string("Could not uname() to find system info: %s\n") + strerror(errno));
} }
for(char **arg = argv; *arg; arg++) // for(char **arg = argv; *arg; arg++)
{ // {
if(cmdline.size() > 0) // if(cmdline.size() > 0)
{ // {
cmdline += " "; // cmdline += " ";
} // }
cmdline += *arg; // cmdline += *arg;
} // }
support["version"] = FALCO_VERSION; support["version"] = FALCO_VERSION;
support["system_info"]["sysname"] = sysinfo.sysname; support["system_info"]["sysname"] = sysinfo.sysname;
@@ -1181,8 +1176,8 @@ int falco_init(int argc, char **argv)
falco_logger::log(LOG_ERR, "Unable to load the driver.\n"); falco_logger::log(LOG_ERR, "Unable to load the driver.\n");
} }
open_f(inspector); open_f(inspector);
} }
else else
{ {
rethrow_exception(current_exception()); rethrow_exception(current_exception());
} }
@@ -1291,7 +1286,7 @@ int falco_init(int argc, char **argv)
if(!trace_filename.empty() && !trace_is_scap) if(!trace_filename.empty() && !trace_is_scap)
{ {
#ifndef MINIMAL_BUILD #ifndef MINIMAL_BUILD
read_k8s_audit_trace_file(engine, read_k8s_audit_trace_file(engine,
outputs, outputs,
trace_filename); trace_filename);
@@ -1378,13 +1373,23 @@ exit:
// //
// MAIN // MAIN
// //
int main(int argc, char **argv) int main(int argc, const char **argv)
{ {
int rc; try
{
auto cli = new falco::cli(argc, argv);
cli->run();
}
catch(const cxxopts::OptionException &e)
{
display_fatal_err("Error parsing options: " + string(e.what()) + "\n");
return EXIT_FAILURE;
}
int rc;
// g_restart will cause the falco loop to exit, but we // g_restart will cause the falco loop to exit, but we
// should reload everything and start over. // should reload everything and start over.
while((rc = falco_init(argc, argv)) == EXIT_SUCCESS && g_restart) while((rc = falco_init()) == EXIT_SUCCESS && g_restart)
{ {
g_restart = false; g_restart = false;
optind = 1; optind = 1;