mirror of
https://github.com/falcosecurity/falco.git
synced 2026-03-24 13:42:09 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d9188a316 | ||
|
|
5cc102545f | ||
|
|
2801c62666 | ||
|
|
c6cffc1f48 | ||
|
|
4894c93d5e |
@@ -60,7 +60,7 @@ if(MUSL_OPTIMIZED_BUILD)
|
|||||||
set(MUSL_FLAGS "-static -Os")
|
set(MUSL_FLAGS "-static -Os")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CMAKE_COMMON_FLAGS "-Wall -ggdb ${DRAIOS_FEATURE_FLAGS} ${MINIMAL_BUILD_FLAGS} ${MUSL_FLAGS}")
|
set(CMAKE_COMMON_FLAGS "-Wall -pg -ggdb ${DRAIOS_FEATURE_FLAGS} ${MINIMAL_BUILD_FLAGS} ${MUSL_FLAGS}")
|
||||||
|
|
||||||
if(BUILD_WARNINGS_AS_ERRORS)
|
if(BUILD_WARNINGS_AS_ERRORS)
|
||||||
set(CMAKE_SUPPRESSED_WARNINGS
|
set(CMAKE_SUPPRESSED_WARNINGS
|
||||||
|
|||||||
@@ -28,10 +28,7 @@
|
|||||||
# The files will be read in the order presented here, so make sure if
|
# The files will be read in the order presented here, so make sure if
|
||||||
# you have overrides they appear in later files.
|
# you have overrides they appear in later files.
|
||||||
rules_file:
|
rules_file:
|
||||||
- /etc/falco/falco_rules.yaml
|
- /tmp/falco
|
||||||
- /etc/falco/falco_rules.local.yaml
|
|
||||||
- /etc/falco/k8s_audit_rules.yaml
|
|
||||||
- /etc/falco/rules.d
|
|
||||||
|
|
||||||
# If true, the times displayed in log messages and output messages
|
# If true, the times displayed in log messages and output messages
|
||||||
# will be in ISO 8601. By default, times are displayed in the local
|
# will be in ISO 8601. By default, times are displayed in the local
|
||||||
|
|||||||
@@ -2425,9 +2425,9 @@
|
|||||||
- rule: Contact K8S API Server From Container
|
- rule: Contact K8S API Server From Container
|
||||||
desc: Detect attempts to contact the K8S API Server from a container
|
desc: Detect attempts to contact the K8S API Server from a container
|
||||||
condition: >
|
condition: >
|
||||||
evt.type=connect and evt.dir=< and
|
evt.type=connect and evt.dir=< and
|
||||||
(fd.typechar=4 or fd.typechar=6) and
|
(fd.typechar=4 or fd.typechar=6) and
|
||||||
container and
|
container and
|
||||||
not k8s_containers and
|
not k8s_containers and
|
||||||
k8s_api_server and
|
k8s_api_server and
|
||||||
not user_known_contact_k8s_api_server_activities
|
not user_known_contact_k8s_api_server_activities
|
||||||
@@ -2647,7 +2647,7 @@
|
|||||||
- rule: Delete or rename shell history
|
- rule: Delete or rename shell history
|
||||||
desc: Detect shell history deletion
|
desc: Detect shell history deletion
|
||||||
condition: >
|
condition: >
|
||||||
(modify_shell_history or truncate_shell_history) and
|
(modify_shell_history or truncate_shell_history) and
|
||||||
not var_lib_docker_filepath and
|
not var_lib_docker_filepath and
|
||||||
not proc.name in (docker_binaries)
|
not proc.name in (docker_binaries)
|
||||||
output: >
|
output: >
|
||||||
@@ -2881,7 +2881,7 @@
|
|||||||
tags: [container, mitre_execution]
|
tags: [container, mitre_execution]
|
||||||
|
|
||||||
|
|
||||||
# This rule is enabled by default.
|
# This rule is enabled by default.
|
||||||
# If you want to disable it, modify the following macro.
|
# If you want to disable it, modify the following macro.
|
||||||
- macro: consider_packet_socket_communication
|
- macro: consider_packet_socket_communication
|
||||||
condition: (always_true)
|
condition: (always_true)
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ if(MINIMAL_BUILD)
|
|||||||
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp/third-party/jsoncpp"
|
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp/third-party/jsoncpp"
|
||||||
"${SYSDIG_SOURCE_DIR}/userspace/libscap"
|
"${SYSDIG_SOURCE_DIR}/userspace/libscap"
|
||||||
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp"
|
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp"
|
||||||
"${PROJECT_BINARY_DIR}/userspace/engine")
|
"${PROJECT_BINARY_DIR}/userspace/engine"
|
||||||
|
"${PROJECT_SOURCE_DIR}/userspace/libhawk")
|
||||||
else()
|
else()
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
falco_engine
|
falco_engine
|
||||||
@@ -51,11 +52,17 @@ else()
|
|||||||
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp/third-party/jsoncpp"
|
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp/third-party/jsoncpp"
|
||||||
"${SYSDIG_SOURCE_DIR}/userspace/libscap"
|
"${SYSDIG_SOURCE_DIR}/userspace/libscap"
|
||||||
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp"
|
"${SYSDIG_SOURCE_DIR}/userspace/libsinsp"
|
||||||
"${PROJECT_BINARY_DIR}/userspace/engine")
|
"${PROJECT_BINARY_DIR}/userspace/engine"
|
||||||
|
"${PROJECT_SOURCE_DIR}/userspace/libhawk")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(falco_engine "${FALCO_SINSP_LIBRARY}" "${LPEG_LIB}" "${LYAML_LIB}" "${LIBYAML_LIB}")
|
target_link_libraries(falco_engine "${FALCO_SINSP_LIBRARY}" "${LPEG_LIB}" "${LYAML_LIB}" "${LIBYAML_LIB}")
|
||||||
|
|
||||||
|
if(DEFINED LIBHAWK_LIBRARIES)
|
||||||
|
message(STATUS "Using externally provided libhawk implementations: ${LIBHAWK_LIBRARIES}")
|
||||||
|
target_link_libraries(falco_engine ${LIBHAWK_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
configure_file(config_falco_engine.h.in config_falco_engine.h)
|
configure_file(config_falco_engine.h.in config_falco_engine.h)
|
||||||
|
|
||||||
if(DEFINED FALCO_COMPONENT)
|
if(DEFINED FALCO_COMPONENT)
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ limitations under the License.
|
|||||||
|
|
||||||
#include "formats.h"
|
#include "formats.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C"
|
||||||
|
{
|
||||||
#include "lpeg.h"
|
#include "lpeg.h"
|
||||||
#include "lyaml.h"
|
#include "lyaml.h"
|
||||||
}
|
}
|
||||||
@@ -34,7 +35,6 @@ extern "C" {
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||||
|
|
||||||
|
|
||||||
string lua_on_event = "on_event";
|
string lua_on_event = "on_event";
|
||||||
string lua_print_stats = "print_stats";
|
string lua_print_stats = "print_stats";
|
||||||
|
|
||||||
@@ -42,24 +42,24 @@ using namespace std;
|
|||||||
|
|
||||||
nlohmann::json::json_pointer falco_engine::k8s_audit_time = "/stageTimestamp"_json_pointer;
|
nlohmann::json::json_pointer falco_engine::k8s_audit_time = "/stageTimestamp"_json_pointer;
|
||||||
|
|
||||||
falco_engine::falco_engine(bool seed_rng, const std::string& alternate_lua_dir)
|
falco_engine::falco_engine(bool seed_rng, const std::string &alternate_lua_dir):
|
||||||
: m_rules(NULL), m_next_ruleset_id(0),
|
m_rules(NULL), m_next_ruleset_id(0),
|
||||||
m_min_priority(falco_common::PRIORITY_DEBUG),
|
m_min_priority(falco_common::PRIORITY_DEBUG),
|
||||||
m_sampling_ratio(1), m_sampling_multiplier(0),
|
m_sampling_ratio(1), m_sampling_multiplier(0),
|
||||||
m_replace_container_info(false)
|
m_replace_container_info(false)
|
||||||
{
|
{
|
||||||
luaopen_lpeg(m_ls);
|
luaopen_lpeg(m_ls);
|
||||||
luaopen_yaml(m_ls);
|
luaopen_yaml(m_ls);
|
||||||
|
|
||||||
|
m_alternate_lua_dir = alternate_lua_dir;
|
||||||
falco_common::init(m_lua_main_filename.c_str(), alternate_lua_dir.c_str());
|
falco_common::init(m_lua_main_filename.c_str(), alternate_lua_dir.c_str());
|
||||||
falco_rules::init(m_ls);
|
falco_rules::init(m_ls);
|
||||||
|
|
||||||
m_sinsp_rules.reset(new falco_sinsp_ruleset());
|
clear_filters();
|
||||||
m_k8s_audit_rules.reset(new falco_ruleset());
|
|
||||||
|
|
||||||
if(seed_rng)
|
if(seed_rng)
|
||||||
{
|
{
|
||||||
srandom((unsigned) getpid());
|
srandom((unsigned)getpid());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_default_ruleset_id = find_ruleset_id(m_default_ruleset);
|
m_default_ruleset_id = find_ruleset_id(m_default_ruleset);
|
||||||
@@ -70,15 +70,24 @@ falco_engine::falco_engine(bool seed_rng, const std::string& alternate_lua_dir)
|
|||||||
|
|
||||||
falco_engine::~falco_engine()
|
falco_engine::~falco_engine()
|
||||||
{
|
{
|
||||||
if (m_rules)
|
if(m_rules)
|
||||||
{
|
{
|
||||||
delete m_rules;
|
delete m_rules;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
falco_engine *falco_engine::clone()
|
||||||
|
{
|
||||||
|
auto engine = new falco_engine(true, m_alternate_lua_dir);
|
||||||
|
engine->set_inspector(m_inspector);
|
||||||
|
engine->set_extra(m_extra, m_replace_container_info);
|
||||||
|
engine->set_min_priority(m_min_priority);
|
||||||
|
return engine;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t falco_engine::engine_version()
|
uint32_t falco_engine::engine_version()
|
||||||
{
|
{
|
||||||
return (uint32_t) FALCO_ENGINE_VERSION;
|
return (uint32_t)FALCO_ENGINE_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DESCRIPTION_TEXT_START 16
|
#define DESCRIPTION_TEXT_START 16
|
||||||
@@ -144,17 +153,28 @@ void falco_engine::list_fields(bool names_only)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void falco_engine::load_rules(const string &rules_content, bool verbose, bool all_events)
|
void falco_engine::load_rules_file(const string &rules_filename, bool verbose, bool all_events)
|
||||||
{
|
{
|
||||||
uint64_t dummy;
|
ifstream is;
|
||||||
|
|
||||||
return load_rules(rules_content, verbose, all_events, dummy);
|
is.open(rules_filename);
|
||||||
|
if(!is.is_open())
|
||||||
|
{
|
||||||
|
throw falco_exception("Could not open rules filename " +
|
||||||
|
rules_filename + " " +
|
||||||
|
"for reading");
|
||||||
|
}
|
||||||
|
|
||||||
|
string rules_content((istreambuf_iterator<char>(is)),
|
||||||
|
istreambuf_iterator<char>());
|
||||||
|
|
||||||
|
load_rules(rules_content, verbose, all_events);
|
||||||
}
|
}
|
||||||
|
|
||||||
void falco_engine::load_rules(const string &rules_content, bool verbose, bool all_events, uint64_t &required_engine_version)
|
void falco_engine::load_rules(const string &rules_content, bool verbose, bool all_events)
|
||||||
{
|
{
|
||||||
// The engine must have been given an inspector by now.
|
// The engine must have been given an inspector by now.
|
||||||
if(! m_inspector)
|
if(!m_inspector)
|
||||||
{
|
{
|
||||||
throw falco_exception("No inspector provided");
|
throw falco_exception("No inspector provided");
|
||||||
}
|
}
|
||||||
@@ -166,45 +186,52 @@ void falco_engine::load_rules(const string &rules_content, bool verbose, bool al
|
|||||||
|
|
||||||
if(!m_rules)
|
if(!m_rules)
|
||||||
{
|
{
|
||||||
m_rules = new falco_rules(m_inspector,
|
// Note that falco_formats is added to the lua state used by the falco engine only.
|
||||||
this,
|
// Within the engine, only formats.
|
||||||
m_ls);
|
// Formatter is used, so we can unconditionally set json_output to false.
|
||||||
|
bool json_output = false;
|
||||||
|
bool json_include_output_property = false;
|
||||||
|
falco_formats::init(m_inspector, this, m_ls, json_output, json_include_output_property);
|
||||||
|
m_rules = new falco_rules(m_inspector, this, m_ls);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that falco_formats is added to the lua state used
|
|
||||||
// by the falco engine only. Within the engine, only
|
|
||||||
// formats.formatter is used, so we can unconditionally set
|
|
||||||
// json_output to false.
|
|
||||||
bool json_output = false;
|
|
||||||
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, required_engine_version);
|
|
||||||
}
|
|
||||||
|
|
||||||
void falco_engine::load_rules_file(const string &rules_filename, bool verbose, bool all_events)
|
|
||||||
{
|
|
||||||
uint64_t dummy;
|
uint64_t dummy;
|
||||||
|
// m_sinsp_rules.reset(new falco_sinsp_ruleset());
|
||||||
|
// m_k8s_audit_rules.reset(new falco_ruleset());
|
||||||
|
m_rules->load_rules(rules_content, verbose, all_events, m_extra, m_replace_container_info, m_min_priority, dummy);
|
||||||
|
|
||||||
return load_rules_file(rules_filename, verbose, all_events, dummy);
|
m_is_ready = true;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
//
|
||||||
|
// auto local_rules = new falco_rules(m_inspector, this, m_ls);
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// uint64_t dummy;
|
||||||
|
// local_rules->load_rules(rules_content, verbose, all_events, m_extra, m_replace_container_info, m_min_priority, dummy);
|
||||||
|
|
||||||
|
// // m_rules = local_rules
|
||||||
|
// // std::atomic<falco_rules *> lore(m_rules);
|
||||||
|
// // std::atomic_exchange(&lore, local_rules);
|
||||||
|
// // SCHEDULE LOCAL_RULES AS NEXT RULESET
|
||||||
|
// }
|
||||||
|
// catch(const falco_exception &e)
|
||||||
|
// {
|
||||||
|
// // todo
|
||||||
|
// printf("IGNORE BECAUSE OF ERROR LOADING RULESET!\n");
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void falco_engine::load_rules_file(const string &rules_filename, bool verbose, bool all_events, uint64_t &required_engine_version)
|
// // todo(fntlnz): not sure we want this in falco_engine
|
||||||
|
// void falco_engine::watch_rules(bool verbose, bool all_events)
|
||||||
|
// {
|
||||||
|
// hawk_watch_rules((hawk_watch_rules_cb)rules_cb, reinterpret_cast<hawk_engine *>(this));
|
||||||
|
// }
|
||||||
|
|
||||||
|
bool falco_engine::is_ready()
|
||||||
{
|
{
|
||||||
ifstream is;
|
return m_is_ready;
|
||||||
|
|
||||||
is.open(rules_filename);
|
|
||||||
if (!is.is_open())
|
|
||||||
{
|
|
||||||
throw falco_exception("Could not open rules filename " +
|
|
||||||
rules_filename + " " +
|
|
||||||
"for reading");
|
|
||||||
}
|
|
||||||
|
|
||||||
string rules_content((istreambuf_iterator<char>(is)),
|
|
||||||
istreambuf_iterator<char>());
|
|
||||||
|
|
||||||
load_rules(rules_content, verbose, all_events, required_engine_version);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void falco_engine::enable_rule(const string &substring, bool enabled, const string &ruleset)
|
void falco_engine::enable_rule(const string &substring, bool enabled, const string &ruleset)
|
||||||
@@ -272,7 +299,7 @@ uint64_t falco_engine::num_rules_for_ruleset(const std::string &ruleset)
|
|||||||
uint16_t ruleset_id = find_ruleset_id(ruleset);
|
uint16_t ruleset_id = find_ruleset_id(ruleset);
|
||||||
|
|
||||||
return m_sinsp_rules->num_rules_for_ruleset(ruleset_id) +
|
return m_sinsp_rules->num_rules_for_ruleset(ruleset_id) +
|
||||||
m_k8s_audit_rules->num_rules_for_ruleset(ruleset_id);
|
m_k8s_audit_rules->num_rules_for_ruleset(ruleset_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void falco_engine::evttypes_for_ruleset(std::vector<bool> &evttypes, const std::string &ruleset)
|
void falco_engine::evttypes_for_ruleset(std::vector<bool> &evttypes, const std::string &ruleset)
|
||||||
@@ -311,15 +338,15 @@ unique_ptr<falco_engine::rule_result> falco_engine::process_sinsp_event(sinsp_ev
|
|||||||
|
|
||||||
if(lua_pcall(m_ls, 1, 3, 0) != 0)
|
if(lua_pcall(m_ls, 1, 3, 0) != 0)
|
||||||
{
|
{
|
||||||
const char* lerr = lua_tostring(m_ls, -1);
|
const char *lerr = lua_tostring(m_ls, -1);
|
||||||
string err = "Error invoking function output: " + string(lerr);
|
string err = "Error invoking function output: " + string(lerr);
|
||||||
throw falco_exception(err);
|
throw falco_exception(err);
|
||||||
}
|
}
|
||||||
res->evt = ev;
|
res->evt = ev;
|
||||||
const char *p = lua_tostring(m_ls, -3);
|
const char *p = lua_tostring(m_ls, -3);
|
||||||
res->rule = p;
|
res->rule = p;
|
||||||
res->source = "syscall";
|
res->source = "syscall";
|
||||||
res->priority_num = (falco_common::priority_type) lua_tonumber(m_ls, -2);
|
res->priority_num = (falco_common::priority_type)lua_tonumber(m_ls, -2);
|
||||||
res->format = lua_tostring(m_ls, -1);
|
res->format = lua_tostring(m_ls, -1);
|
||||||
lua_pop(m_ls, 3);
|
lua_pop(m_ls, 3);
|
||||||
}
|
}
|
||||||
@@ -333,6 +360,7 @@ unique_ptr<falco_engine::rule_result> falco_engine::process_sinsp_event(sinsp_ev
|
|||||||
|
|
||||||
unique_ptr<falco_engine::rule_result> falco_engine::process_sinsp_event(sinsp_evt *ev)
|
unique_ptr<falco_engine::rule_result> falco_engine::process_sinsp_event(sinsp_evt *ev)
|
||||||
{
|
{
|
||||||
|
// todo(leodido, fntlnz) > pass the last ruleset id
|
||||||
return process_sinsp_event(ev, m_default_ruleset_id);
|
return process_sinsp_event(ev, m_default_ruleset_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,7 +372,7 @@ unique_ptr<falco_engine::rule_result> falco_engine::process_k8s_audit_event(json
|
|||||||
}
|
}
|
||||||
|
|
||||||
// All k8s audit events have the single tag "1".
|
// All k8s audit events have the single tag "1".
|
||||||
if(!m_k8s_audit_rules->run((gen_event *) ev, 1, ruleset_id))
|
if(!m_k8s_audit_rules->run((gen_event *)ev, 1, ruleset_id))
|
||||||
{
|
{
|
||||||
return unique_ptr<struct rule_result>();
|
return unique_ptr<struct rule_result>();
|
||||||
}
|
}
|
||||||
@@ -359,15 +387,15 @@ unique_ptr<falco_engine::rule_result> falco_engine::process_k8s_audit_event(json
|
|||||||
|
|
||||||
if(lua_pcall(m_ls, 1, 3, 0) != 0)
|
if(lua_pcall(m_ls, 1, 3, 0) != 0)
|
||||||
{
|
{
|
||||||
const char* lerr = lua_tostring(m_ls, -1);
|
const char *lerr = lua_tostring(m_ls, -1);
|
||||||
string err = "Error invoking function output: " + string(lerr);
|
string err = "Error invoking function output: " + string(lerr);
|
||||||
throw falco_exception(err);
|
throw falco_exception(err);
|
||||||
}
|
}
|
||||||
res->evt = ev;
|
res->evt = ev;
|
||||||
const char *p = lua_tostring(m_ls, -3);
|
const char *p = lua_tostring(m_ls, -3);
|
||||||
res->rule = p;
|
res->rule = p;
|
||||||
res->source = "k8s_audit";
|
res->source = "k8s_audit";
|
||||||
res->priority_num = (falco_common::priority_type) lua_tonumber(m_ls, -2);
|
res->priority_num = (falco_common::priority_type)lua_tonumber(m_ls, -2);
|
||||||
res->format = lua_tostring(m_ls, -1);
|
res->format = lua_tostring(m_ls, -1);
|
||||||
lua_pop(m_ls, 3);
|
lua_pop(m_ls, 3);
|
||||||
}
|
}
|
||||||
@@ -393,7 +421,7 @@ bool falco_engine::parse_k8s_audit_json(nlohmann::json &j, std::list<json_event>
|
|||||||
{
|
{
|
||||||
// Note we only handle a single top level array, to
|
// Note we only handle a single top level array, to
|
||||||
// avoid excessive recursion.
|
// avoid excessive recursion.
|
||||||
if(! parse_k8s_audit_json(item, evts, false))
|
if(!parse_k8s_audit_json(item, evts, false))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -471,7 +499,7 @@ void falco_engine::print_stats()
|
|||||||
{
|
{
|
||||||
if(lua_pcall(m_ls, 0, 0, 0) != 0)
|
if(lua_pcall(m_ls, 0, 0, 0) != 0)
|
||||||
{
|
{
|
||||||
const char* lerr = lua_tostring(m_ls, -1);
|
const char *lerr = lua_tostring(m_ls, -1);
|
||||||
string err = "Error invoking function print_stats: " + string(lerr);
|
string err = "Error invoking function print_stats: " + string(lerr);
|
||||||
throw falco_exception(err);
|
throw falco_exception(err);
|
||||||
}
|
}
|
||||||
@@ -480,21 +508,20 @@ void falco_engine::print_stats()
|
|||||||
{
|
{
|
||||||
throw falco_exception("No function " + lua_print_stats + " found in lua rule loader module");
|
throw falco_exception("No function " + lua_print_stats + " found in lua rule loader module");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void falco_engine::add_sinsp_filter(string &rule,
|
void falco_engine::add_sinsp_filter(string &rule,
|
||||||
set<uint32_t> &evttypes,
|
set<uint32_t> &evttypes,
|
||||||
set<uint32_t> &syscalls,
|
set<uint32_t> &syscalls,
|
||||||
set<string> &tags,
|
set<string> &tags,
|
||||||
sinsp_filter* filter)
|
sinsp_filter *filter)
|
||||||
{
|
{
|
||||||
m_sinsp_rules->add(rule, evttypes, syscalls, tags, filter);
|
m_sinsp_rules->add(rule, evttypes, syscalls, tags, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void falco_engine::add_k8s_audit_filter(string &rule,
|
void falco_engine::add_k8s_audit_filter(string &rule,
|
||||||
set<string> &tags,
|
set<string> &tags,
|
||||||
json_event_filter* filter)
|
json_event_filter *filter)
|
||||||
{
|
{
|
||||||
// All k8s audit events have a single tag "1".
|
// All k8s audit events have a single tag "1".
|
||||||
std::set<uint32_t> event_tags = {1};
|
std::set<uint32_t> event_tags = {1};
|
||||||
@@ -536,8 +563,8 @@ inline bool falco_engine::should_drop_evt()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
double coin = (random() * (1.0/RAND_MAX));
|
double coin = (random() * (1.0 / RAND_MAX));
|
||||||
return (coin >= (1.0/(m_sampling_multiplier * m_sampling_ratio)));
|
return (coin >= (1.0 / (m_sampling_multiplier * m_sampling_ratio)));
|
||||||
}
|
}
|
||||||
|
|
||||||
sinsp_filter_factory &falco_engine::sinsp_factory()
|
sinsp_filter_factory &falco_engine::sinsp_factory()
|
||||||
|
|||||||
@@ -38,6 +38,11 @@ limitations under the License.
|
|||||||
#include "config_falco_engine.h"
|
#include "config_falco_engine.h"
|
||||||
#include "falco_common.h"
|
#include "falco_common.h"
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "hawk.h"
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// This class acts as the primary interface between a program and the
|
// This class acts as the primary interface between a program and the
|
||||||
// falco rules engine. Falco outputs (writing to files/syslog/etc) are
|
// falco rules engine. Falco outputs (writing to files/syslog/etc) are
|
||||||
@@ -47,9 +52,12 @@ limitations under the License.
|
|||||||
class falco_engine : public falco_common
|
class falco_engine : public falco_common
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
falco_engine(bool seed_rng=true, const std::string& alternate_lua_dir=FALCO_ENGINE_SOURCE_LUA_DIR);
|
falco_engine(bool seed_rng = true, const std::string &alternate_lua_dir = FALCO_ENGINE_SOURCE_LUA_DIR);
|
||||||
virtual ~falco_engine();
|
virtual ~falco_engine();
|
||||||
|
|
||||||
|
falco_engine(const falco_engine &rhs);
|
||||||
|
falco_engine *clone();
|
||||||
|
|
||||||
// A given engine has a version which identifies the fields
|
// A given engine has a version which identifies the fields
|
||||||
// and rules file format it supports. This version will change
|
// and rules file format it supports. This version will change
|
||||||
// any time the code that handles rules files, expression
|
// any time the code that handles rules files, expression
|
||||||
@@ -57,7 +65,7 @@ public:
|
|||||||
static uint32_t engine_version();
|
static uint32_t engine_version();
|
||||||
|
|
||||||
// Print to stdout (using printf) a description of each field supported by this engine.
|
// Print to stdout (using printf) a description of each field supported by this engine.
|
||||||
void list_fields(bool names_only=false);
|
void list_fields(bool names_only = false);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Load rules either directly or from a filename.
|
// Load rules either directly or from a filename.
|
||||||
@@ -65,12 +73,8 @@ public:
|
|||||||
void load_rules_file(const std::string &rules_filename, bool verbose, bool all_events);
|
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);
|
void load_rules(const std::string &rules_content, bool verbose, bool all_events);
|
||||||
|
|
||||||
//
|
// Watch and live-reload rules using an external ABI interface provided by libhawk
|
||||||
// Identical to above, but also returns the required engine version for the file/content.
|
void watch_rules(bool verbose, bool all_events);
|
||||||
// (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 substring.
|
// Enable/Disable any rules matching the provided substring.
|
||||||
@@ -85,7 +89,6 @@ public:
|
|||||||
// Wrapper that assumes the default ruleset
|
// Wrapper that assumes the default ruleset
|
||||||
void enable_rule(const std::string &substring, bool enabled);
|
void enable_rule(const std::string &substring, bool enabled);
|
||||||
|
|
||||||
|
|
||||||
// Like enable_rule, but the rule name must be an exact match.
|
// Like enable_rule, but the rule name must be an exact match.
|
||||||
void enable_rule_exact(const std::string &rule_name, bool enabled, const std::string &ruleset);
|
void enable_rule_exact(const std::string &rule_name, bool enabled, const std::string &ruleset);
|
||||||
|
|
||||||
@@ -154,7 +157,8 @@ public:
|
|||||||
|
|
||||||
// **Methods Related to k8s audit log events, which are
|
// **Methods Related to k8s audit log events, which are
|
||||||
// **represented as json objects.
|
// **represented as json objects.
|
||||||
struct rule_result {
|
struct rule_result
|
||||||
|
{
|
||||||
gen_event *evt;
|
gen_event *evt;
|
||||||
std::string rule;
|
std::string rule;
|
||||||
std::string source;
|
std::string source;
|
||||||
@@ -170,7 +174,7 @@ public:
|
|||||||
// Returns true if the json object was recognized as a k8s
|
// Returns true if the json object was recognized as a k8s
|
||||||
// audit event(s), false otherwise.
|
// audit event(s), false otherwise.
|
||||||
//
|
//
|
||||||
bool parse_k8s_audit_json(nlohmann::json &j, std::list<json_event> &evts, bool top=true);
|
bool parse_k8s_audit_json(nlohmann::json &j, std::list<json_event> &evts, bool top = true);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Given an event, check it against the set of rules in the
|
// Given an event, check it against the set of rules in the
|
||||||
@@ -195,7 +199,7 @@ public:
|
|||||||
//
|
//
|
||||||
void add_k8s_audit_filter(std::string &rule,
|
void add_k8s_audit_filter(std::string &rule,
|
||||||
std::set<std::string> &tags,
|
std::set<std::string> &tags,
|
||||||
json_event_filter* filter);
|
json_event_filter *filter);
|
||||||
|
|
||||||
// **Methods Related to Sinsp Events e.g system calls
|
// **Methods Related to Sinsp Events e.g system calls
|
||||||
//
|
//
|
||||||
@@ -236,13 +240,14 @@ public:
|
|||||||
std::set<uint32_t> &evttypes,
|
std::set<uint32_t> &evttypes,
|
||||||
std::set<uint32_t> &syscalls,
|
std::set<uint32_t> &syscalls,
|
||||||
std::set<std::string> &tags,
|
std::set<std::string> &tags,
|
||||||
sinsp_filter* filter);
|
sinsp_filter *filter);
|
||||||
|
|
||||||
sinsp_filter_factory &sinsp_factory();
|
sinsp_filter_factory &sinsp_factory();
|
||||||
json_event_filter_factory &json_factory();
|
json_event_filter_factory &json_factory();
|
||||||
|
|
||||||
private:
|
bool is_ready();
|
||||||
|
|
||||||
|
private:
|
||||||
static nlohmann::json::json_pointer k8s_audit_time;
|
static nlohmann::json::json_pointer k8s_audit_time;
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -262,6 +267,8 @@ private:
|
|||||||
std::unique_ptr<falco_sinsp_ruleset> m_sinsp_rules;
|
std::unique_ptr<falco_sinsp_ruleset> m_sinsp_rules;
|
||||||
std::unique_ptr<falco_ruleset> m_k8s_audit_rules;
|
std::unique_ptr<falco_ruleset> m_k8s_audit_rules;
|
||||||
|
|
||||||
|
std::string m_alternate_lua_dir;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Here's how the sampling ratio and multiplier influence
|
// Here's how the sampling ratio and multiplier influence
|
||||||
// whether or not an event is dropped in
|
// whether or not an event is dropped in
|
||||||
@@ -291,5 +298,6 @@ private:
|
|||||||
|
|
||||||
std::string m_extra;
|
std::string m_extra;
|
||||||
bool m_replace_container_info;
|
bool m_replace_container_info;
|
||||||
};
|
|
||||||
|
|
||||||
|
bool m_is_ready = false;
|
||||||
|
};
|
||||||
|
|||||||
@@ -146,11 +146,11 @@ endif()
|
|||||||
configure_file(config_falco.h.in config_falco.h)
|
configure_file(config_falco.h.in config_falco.h)
|
||||||
|
|
||||||
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()
|
||||||
|
|||||||
@@ -68,16 +68,6 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
|
|||||||
|
|
||||||
m_config->get_sequence<list<string>>(rules_files, string("rules_file"));
|
m_config->get_sequence<list<string>>(rules_files, string("rules_file"));
|
||||||
|
|
||||||
for(auto &file : rules_files)
|
|
||||||
{
|
|
||||||
// Here, we only include files that exist
|
|
||||||
struct stat buffer;
|
|
||||||
if(stat(file.c_str(), &buffer) == 0)
|
|
||||||
{
|
|
||||||
read_rules_file_directory(file, m_rules_filenames);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_json_output = m_config->get_scalar<bool>("json_output", false);
|
m_json_output = m_config->get_scalar<bool>("json_output", false);
|
||||||
m_json_include_output_property = m_config->get_scalar<bool>("json_include_output_property", true);
|
m_json_include_output_property = m_config->get_scalar<bool>("json_include_output_property", true);
|
||||||
|
|
||||||
@@ -242,69 +232,6 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
|
|||||||
m_syscall_evt_simulate_drops = m_config->get_scalar<bool>("syscall_event_drops", "simulate_drops", false);
|
m_syscall_evt_simulate_drops = m_config->get_scalar<bool>("syscall_event_drops", "simulate_drops", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void falco_configuration::read_rules_file_directory(const string &path, list<string> &rules_filenames)
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
int rc = stat(path.c_str(), &st);
|
|
||||||
|
|
||||||
if(rc != 0)
|
|
||||||
{
|
|
||||||
std::cerr << "Could not get info on rules file " << path << ": " << strerror(errno) << std::endl;
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(st.st_mode & S_IFDIR)
|
|
||||||
{
|
|
||||||
// It's a directory. Read the contents, sort
|
|
||||||
// alphabetically, and add every path to
|
|
||||||
// rules_filenames
|
|
||||||
vector<string> dir_filenames;
|
|
||||||
|
|
||||||
DIR *dir = opendir(path.c_str());
|
|
||||||
|
|
||||||
if(!dir)
|
|
||||||
{
|
|
||||||
std::cerr << "Could not get read contents of directory " << path << ": " << strerror(errno) << std::endl;
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(struct dirent *ent = readdir(dir); ent; ent = readdir(dir))
|
|
||||||
{
|
|
||||||
string efile = path + "/" + ent->d_name;
|
|
||||||
|
|
||||||
rc = stat(efile.c_str(), &st);
|
|
||||||
|
|
||||||
if(rc != 0)
|
|
||||||
{
|
|
||||||
std::cerr << "Could not get info on rules file " << efile << ": " << strerror(errno) << std::endl;
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(st.st_mode & S_IFREG)
|
|
||||||
{
|
|
||||||
dir_filenames.push_back(efile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(dir);
|
|
||||||
|
|
||||||
std::sort(dir_filenames.begin(),
|
|
||||||
dir_filenames.end());
|
|
||||||
|
|
||||||
for(string &ent : dir_filenames)
|
|
||||||
{
|
|
||||||
rules_filenames.push_back(ent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Assume it's a file and just add to
|
|
||||||
// rules_filenames. If it can't be opened/etc that
|
|
||||||
// will be reported later..
|
|
||||||
rules_filenames.push_back(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool split(const string &str, char delim, pair<string, string> &parts)
|
static bool split(const string &str, char delim, pair<string, string> &parts)
|
||||||
{
|
{
|
||||||
@@ -346,4 +273,4 @@ void falco_configuration::set_cmdline_option(const string &opt)
|
|||||||
{
|
{
|
||||||
m_config->set_scalar(keyval.first, keyval.second);
|
m_config->set_scalar(keyval.first, keyval.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,9 +190,6 @@ public:
|
|||||||
void init(std::string conf_filename, std::list<std::string>& cmdline_options);
|
void init(std::string conf_filename, std::list<std::string>& cmdline_options);
|
||||||
void init(std::list<std::string>& cmdline_options);
|
void init(std::list<std::string>& cmdline_options);
|
||||||
|
|
||||||
static void read_rules_file_directory(const string& path, list<string>& rules_filenames);
|
|
||||||
|
|
||||||
std::list<std::string> m_rules_filenames;
|
|
||||||
bool m_json_output;
|
bool m_json_output;
|
||||||
bool m_json_include_output_property;
|
bool m_json_include_output_property;
|
||||||
std::string m_log_level;
|
std::string m_log_level;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
10
userspace/libhawk/hawk.h
Normal file
10
userspace/libhawk/hawk.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef HAWK_H
|
||||||
|
#define HAWK_H
|
||||||
|
extern void hawk_init();
|
||||||
|
extern void hawk_destroy();
|
||||||
|
|
||||||
|
typedef void* hawk_engine;
|
||||||
|
typedef void (*hawk_watch_rules_cb)(char* rules_content, hawk_engine* engine);
|
||||||
|
extern void hawk_watch_rules(hawk_watch_rules_cb cb, hawk_engine* engine);
|
||||||
|
|
||||||
|
#endif //HAWK_H
|
||||||
Reference in New Issue
Block a user