mirror of
https://github.com/falcosecurity/falco.git
synced 2026-03-30 08:32:17 +00:00
Compare commits
4 Commits
master
...
feat/captu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e41c2de552 | ||
|
|
7fa92debef | ||
|
|
61d77cfb59 | ||
|
|
f3f355ce4f |
@@ -42,9 +42,9 @@ else()
|
||||
# version (or branch, or commit) just pass the variable - ie., `cmake
|
||||
# -DFALCOSECURITY_LIBS_VERSION=dev ..`
|
||||
if(NOT FALCOSECURITY_LIBS_VERSION)
|
||||
set(FALCOSECURITY_LIBS_VERSION "7b08f8a0a12b56d59eab73052e637ca123623f61")
|
||||
set(FALCOSECURITY_LIBS_VERSION "362b1709f4dee99c91f72e551120b3f8cdf0e508")
|
||||
set(FALCOSECURITY_LIBS_CHECKSUM
|
||||
"SHA256=43c72a98e48d04177c8223ccdfe88de6f09958f2330b6b9ee26882f1a77e369f"
|
||||
"SHA256=833c3d706ce3cfeb45e17216509a1270d33bca26552326737f66d43fdad30b3d"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
29
falco.yaml
29
falco.yaml
@@ -461,11 +461,19 @@ engine:
|
||||
# 2. `all_rules`: Captures events when any enabled rule is triggered.
|
||||
#
|
||||
# When a capture starts, Falco records events from the moment the triggering rule
|
||||
# fires until the deadline is reached. The deadline is determined by the rule's
|
||||
# `capture_duration` if specified, otherwise the `default_duration` is used.
|
||||
# If additional rules trigger during an active capture, the deadline is extended
|
||||
# accordingly. Once the deadline expires, the capture stops and data is written
|
||||
# to a file. Subsequent captures create new files with unique names.
|
||||
# fires until a stop condition is reached. The stop conditions are:
|
||||
# - Duration: determined by the rule's `capture_duration` if specified, otherwise
|
||||
# the `default_duration` is used.
|
||||
# - Event count: determined by the rule's `capture_events` if specified, otherwise
|
||||
# the `default_events` is used.
|
||||
# - File size: determined by the rule's `capture_filesize` if specified, otherwise
|
||||
# the `default_filesize` is used.
|
||||
#
|
||||
# When multiple stop conditions are configured, the first one reached wins (OR
|
||||
# semantics). If additional rules trigger during an active capture, the limits
|
||||
# are extended accordingly. Once a stop condition is met, the capture stops and
|
||||
# data is written to a file. Subsequent captures create new files with unique
|
||||
# names.
|
||||
#
|
||||
# Captured data is stored in files with a `.scap` extension, which can be
|
||||
# analyzed later using:
|
||||
@@ -483,12 +491,15 @@ engine:
|
||||
# Use `capture.mode` to choose between `rules` and `all_rules` modes.
|
||||
#
|
||||
# Set `capture.default_duration` to define the default capture duration
|
||||
# in milliseconds.
|
||||
# in milliseconds. Optionally, set `capture.default_events` to limit the
|
||||
# number of captured events, and `capture.default_filesize` to limit the
|
||||
# capture file size in kB.
|
||||
#
|
||||
# --- [Suggestions]
|
||||
#
|
||||
# When using `mode: rules`, configure individual rules to enable capture by
|
||||
# adding `capture: true` and optionally `capture_duration` to specific rules.
|
||||
# adding `capture: true` and optionally `capture_duration`, `capture_events`,
|
||||
# and/or `capture_filesize` to specific rules.
|
||||
# For example:
|
||||
#
|
||||
# - rule: Suspicious File Access
|
||||
@@ -512,6 +523,10 @@ capture:
|
||||
mode: rules
|
||||
# -- Default capture duration in milliseconds if not specified in the rule.
|
||||
default_duration: 5000
|
||||
# -- Default maximum number of captured events (0 = unlimited).
|
||||
# default_events: 0
|
||||
# -- Default maximum capture file size in kB (0 = unlimited).
|
||||
# default_filesize: 0
|
||||
|
||||
#################
|
||||
# Falco plugins #
|
||||
|
||||
@@ -1516,3 +1516,282 @@ TEST_F(test_falco_engine, no_deprecated_field_warning_in_output) {
|
||||
ASSERT_FALSE(check_warning_message("evt.dir")) << m_load_result_string;
|
||||
EXPECT_EQ(num_rules_for_ruleset(), 1);
|
||||
}
|
||||
|
||||
// Capture field tests
|
||||
|
||||
TEST_F(test_falco_engine, rule_capture_enabled) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule
|
||||
condition: evt.type = close
|
||||
output: user=%user.name
|
||||
priority: WARNING
|
||||
capture: true
|
||||
)END";
|
||||
|
||||
std::string rule_name = "test_rule";
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
|
||||
auto rule_description = m_engine->describe_rule(&rule_name, {});
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["capture"].template get<bool>(), true);
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_capture_disabled_by_default) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule
|
||||
condition: evt.type = close
|
||||
output: user=%user.name
|
||||
priority: INFO
|
||||
)END";
|
||||
|
||||
std::string rule_name = "test_rule";
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
|
||||
auto rule_description = m_engine->describe_rule(&rule_name, {});
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["capture"].template get<bool>(), false);
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["capture_duration"].template get<uint32_t>(),
|
||||
0u);
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["capture_events"].template get<uint32_t>(), 0u);
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["capture_filesize"].template get<uint32_t>(),
|
||||
0u);
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_capture_duration) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule
|
||||
condition: evt.type = close
|
||||
output: user=%user.name
|
||||
priority: WARNING
|
||||
capture: true
|
||||
capture_duration: 10000
|
||||
)END";
|
||||
|
||||
std::string rule_name = "test_rule";
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
|
||||
auto rule_description = m_engine->describe_rule(&rule_name, {});
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["capture_duration"].template get<uint32_t>(),
|
||||
10000u);
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_capture_events) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule
|
||||
condition: evt.type = close
|
||||
output: user=%user.name
|
||||
priority: WARNING
|
||||
capture: true
|
||||
capture_events: 25000
|
||||
)END";
|
||||
|
||||
std::string rule_name = "test_rule";
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
|
||||
auto rule_description = m_engine->describe_rule(&rule_name, {});
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["capture_events"].template get<uint32_t>(),
|
||||
25000u);
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_capture_filesize) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule
|
||||
condition: evt.type = close
|
||||
output: user=%user.name
|
||||
priority: WARNING
|
||||
capture: true
|
||||
capture_filesize: 80000
|
||||
)END";
|
||||
|
||||
std::string rule_name = "test_rule";
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
|
||||
auto rule_description = m_engine->describe_rule(&rule_name, {});
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["capture_filesize"].template get<uint32_t>(),
|
||||
80000u);
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_capture_all_fields) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule
|
||||
condition: evt.type = close
|
||||
output: user=%user.name
|
||||
priority: WARNING
|
||||
capture: true
|
||||
capture_duration: 5000
|
||||
capture_events: 10000
|
||||
capture_filesize: 2048
|
||||
)END";
|
||||
|
||||
std::string rule_name = "test_rule";
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
|
||||
auto rule_description = m_engine->describe_rule(&rule_name, {});
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["capture"].template get<bool>(), true);
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["capture_duration"].template get<uint32_t>(),
|
||||
5000u);
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["capture_events"].template get<uint32_t>(),
|
||||
10000u);
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["capture_filesize"].template get<uint32_t>(),
|
||||
2048u);
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_override_capture_replace) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule
|
||||
condition: evt.type = close
|
||||
output: user=%user.name
|
||||
priority: WARNING
|
||||
capture: true
|
||||
|
||||
- rule: test_rule
|
||||
capture: false
|
||||
override:
|
||||
capture: replace
|
||||
)END";
|
||||
|
||||
std::string rule_name = "test_rule";
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
|
||||
auto rule_description = m_engine->describe_rule(&rule_name, {});
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["capture"].template get<bool>(), false);
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_override_capture_duration_replace) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule
|
||||
condition: evt.type = close
|
||||
output: user=%user.name
|
||||
priority: WARNING
|
||||
capture: true
|
||||
capture_duration: 5000
|
||||
|
||||
- rule: test_rule
|
||||
capture_duration: 15000
|
||||
override:
|
||||
capture_duration: replace
|
||||
)END";
|
||||
|
||||
std::string rule_name = "test_rule";
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
|
||||
auto rule_description = m_engine->describe_rule(&rule_name, {});
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["capture_duration"].template get<uint32_t>(),
|
||||
15000u);
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_override_capture_events_replace) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule
|
||||
condition: evt.type = close
|
||||
output: user=%user.name
|
||||
priority: WARNING
|
||||
capture_events: 1000
|
||||
|
||||
- rule: test_rule
|
||||
capture_events: 5000
|
||||
override:
|
||||
capture_events: replace
|
||||
)END";
|
||||
|
||||
std::string rule_name = "test_rule";
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
|
||||
auto rule_description = m_engine->describe_rule(&rule_name, {});
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["capture_events"].template get<uint32_t>(),
|
||||
5000u);
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_override_capture_filesize_replace) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule
|
||||
condition: evt.type = close
|
||||
output: user=%user.name
|
||||
priority: WARNING
|
||||
capture_filesize: 1024
|
||||
|
||||
- rule: test_rule
|
||||
capture_filesize: 4096
|
||||
override:
|
||||
capture_filesize: replace
|
||||
)END";
|
||||
|
||||
std::string rule_name = "test_rule";
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
|
||||
|
||||
auto rule_description = m_engine->describe_rule(&rule_name, {});
|
||||
ASSERT_EQ(rule_description["rules"][0]["info"]["capture_filesize"].template get<uint32_t>(),
|
||||
4096u);
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_capture_events_wrong_type) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule
|
||||
condition: evt.type = close
|
||||
output: user=%user.name
|
||||
priority: INFO
|
||||
capture_events: "not_a_number"
|
||||
)END";
|
||||
|
||||
// String value for an integer field causes a load error
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_capture_filesize_wrong_type) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule
|
||||
condition: evt.type = close
|
||||
output: user=%user.name
|
||||
priority: INFO
|
||||
capture_filesize: "not_a_number"
|
||||
)END";
|
||||
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_capture_duration_wrong_type) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule
|
||||
condition: evt.type = close
|
||||
output: user=%user.name
|
||||
priority: INFO
|
||||
capture_duration: "not_a_number"
|
||||
)END";
|
||||
|
||||
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
|
||||
}
|
||||
|
||||
TEST_F(test_falco_engine, rule_capture_wrong_type) {
|
||||
std::string rules_content = R"END(
|
||||
- rule: test_rule
|
||||
desc: test rule
|
||||
condition: evt.type = close
|
||||
output: user=%user.name
|
||||
priority: INFO
|
||||
capture: "yes"
|
||||
)END";
|
||||
|
||||
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
|
||||
ASSERT_VALIDATION_STATUS(yaml_helper::validation_failed) << m_load_result->schema_validation();
|
||||
}
|
||||
|
||||
@@ -79,6 +79,8 @@ plugins:
|
||||
EXPECT_EQ(config.m_capture_path_prefix, "/tmp/falco");
|
||||
EXPECT_EQ(config.m_capture_mode, capture_mode_t::RULES);
|
||||
EXPECT_EQ(config.m_capture_default_duration_ns, 5000 * 1000000LL); // 5 seconds in ns
|
||||
EXPECT_EQ(config.m_capture_default_events, 0u);
|
||||
EXPECT_EQ(config.m_capture_default_filesize_kb, 0u);
|
||||
}
|
||||
|
||||
TEST(Capture, capture_config_enabled_rules_mode) {
|
||||
@@ -132,3 +134,51 @@ capture:
|
||||
// Should throw an exception for invalid mode
|
||||
EXPECT_THROW(res = config.init_from_content(config_content, {}), std::logic_error);
|
||||
}
|
||||
|
||||
TEST(Capture, capture_config_with_events_limit) {
|
||||
std::string config_content = R"(
|
||||
capture:
|
||||
enabled: true
|
||||
default_events: 50000
|
||||
)";
|
||||
|
||||
falco_configuration config;
|
||||
config_loaded_res res;
|
||||
ASSERT_NO_THROW(res = config.init_from_content(config_content, {}));
|
||||
|
||||
EXPECT_EQ(config.m_capture_default_events, 50000u);
|
||||
EXPECT_EQ(config.m_capture_default_filesize_kb, 0u);
|
||||
}
|
||||
|
||||
TEST(Capture, capture_config_with_filesize_limit) {
|
||||
std::string config_content = R"(
|
||||
capture:
|
||||
enabled: true
|
||||
default_filesize: 10240
|
||||
)";
|
||||
|
||||
falco_configuration config;
|
||||
config_loaded_res res;
|
||||
ASSERT_NO_THROW(res = config.init_from_content(config_content, {}));
|
||||
|
||||
EXPECT_EQ(config.m_capture_default_events, 0u);
|
||||
EXPECT_EQ(config.m_capture_default_filesize_kb, 10240u);
|
||||
}
|
||||
|
||||
TEST(Capture, capture_config_with_all_limits) {
|
||||
std::string config_content = R"(
|
||||
capture:
|
||||
enabled: true
|
||||
default_duration: 15000
|
||||
default_events: 25000
|
||||
default_filesize: 80000
|
||||
)";
|
||||
|
||||
falco_configuration config;
|
||||
config_loaded_res res;
|
||||
ASSERT_NO_THROW(res = config.init_from_content(config_content, {}));
|
||||
|
||||
EXPECT_EQ(config.m_capture_default_duration_ns, 15000 * 1000000LL);
|
||||
EXPECT_EQ(config.m_capture_default_events, 25000u);
|
||||
EXPECT_EQ(config.m_capture_default_filesize_kb, 80000u);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2025 The Falco Authors.
|
||||
Copyright (C) 2026 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.
|
||||
@@ -415,6 +415,8 @@ std::unique_ptr<std::vector<falco_engine::rule_result>> falco_engine::process_ev
|
||||
rule_result.priority_num = rule.priority;
|
||||
rule_result.capture = rule.capture;
|
||||
rule_result.capture_duration_ns = uint64_t(rule.capture_duration) * 1000000LL;
|
||||
rule_result.capture_events = uint64_t(rule.capture_events);
|
||||
rule_result.capture_filesize_kb = uint64_t(rule.capture_filesize);
|
||||
rule_result.tags = rule.tags;
|
||||
rule_result.exception_fields = rule.exception_fields;
|
||||
rule_result.extra_output_fields = rule.extra_output_fields;
|
||||
@@ -572,6 +574,8 @@ void falco_engine::get_json_details(
|
||||
rule_info["source"] = r.source;
|
||||
rule_info["capture"] = r.capture;
|
||||
rule_info["capture_duration"] = r.capture_duration;
|
||||
rule_info["capture_events"] = r.capture_events;
|
||||
rule_info["capture_filesize"] = r.capture_filesize;
|
||||
rule_info["tags"] = sequence_to_json_array(info.tags);
|
||||
out["info"] = std::move(rule_info);
|
||||
|
||||
|
||||
@@ -229,6 +229,8 @@ public:
|
||||
extra_output_field_t extra_output_fields;
|
||||
bool capture;
|
||||
uint64_t capture_duration_ns;
|
||||
uint64_t capture_events;
|
||||
uint64_t capture_filesize_kb;
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
@@ -20,7 +20,7 @@ limitations under the License.
|
||||
|
||||
// The version of this Falco engine
|
||||
#define FALCO_ENGINE_VERSION_MAJOR 0
|
||||
#define FALCO_ENGINE_VERSION_MINOR 60
|
||||
#define FALCO_ENGINE_VERSION_MINOR 61
|
||||
#define FALCO_ENGINE_VERSION_PATCH 0
|
||||
|
||||
#define FALCO_ENGINE_VERSION \
|
||||
|
||||
@@ -81,7 +81,9 @@ struct falco_rule {
|
||||
id(0),
|
||||
priority(falco_common::PRIORITY_DEBUG),
|
||||
capture(false),
|
||||
capture_duration(0) {}
|
||||
capture_duration(0),
|
||||
capture_events(0),
|
||||
capture_filesize(0) {}
|
||||
falco_rule(falco_rule&&) = default;
|
||||
falco_rule& operator=(falco_rule&&) = default;
|
||||
falco_rule(const falco_rule&) = default;
|
||||
@@ -112,6 +114,8 @@ struct falco_rule {
|
||||
falco_common::priority_type priority;
|
||||
bool capture;
|
||||
uint32_t capture_duration;
|
||||
uint32_t capture_events;
|
||||
uint32_t capture_filesize;
|
||||
std::shared_ptr<libsinsp::filter::ast::expr> condition;
|
||||
std::shared_ptr<sinsp_filter> filter;
|
||||
};
|
||||
|
||||
@@ -80,6 +80,12 @@ const char rule_schema_string[] = LONG_STRING_CONST(
|
||||
"capture_duration": {
|
||||
"type": "integer"
|
||||
},
|
||||
"capture_events": {
|
||||
"type": "integer"
|
||||
},
|
||||
"capture_filesize": {
|
||||
"type": "integer"
|
||||
},
|
||||
"source": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -189,6 +195,12 @@ const char rule_schema_string[] = LONG_STRING_CONST(
|
||||
"capture_duration": {
|
||||
"$ref": "#/definitions/OverriddenItem"
|
||||
},
|
||||
"capture_events": {
|
||||
"$ref": "#/definitions/OverriddenItem"
|
||||
},
|
||||
"capture_filesize": {
|
||||
"$ref": "#/definitions/OverriddenItem"
|
||||
},
|
||||
"tags": {
|
||||
"$ref": "#/definitions/OverriddenItem"
|
||||
},
|
||||
|
||||
@@ -503,6 +503,8 @@ struct rule_info {
|
||||
falco_common::priority_type priority;
|
||||
bool capture;
|
||||
uint32_t capture_duration;
|
||||
uint32_t capture_events;
|
||||
uint32_t capture_filesize;
|
||||
bool enabled;
|
||||
bool warn_evttypes;
|
||||
bool skip_if_unknown_filter;
|
||||
@@ -523,7 +525,8 @@ struct rule_update_info {
|
||||
bool has_any_value() {
|
||||
return cond.has_value() || output.has_value() || desc.has_value() || tags.has_value() ||
|
||||
exceptions.has_value() || priority.has_value() || enabled.has_value() ||
|
||||
capture.has_value() || capture_duration.has_value() || warn_evttypes.has_value() ||
|
||||
capture.has_value() || capture_duration.has_value() || capture_events.has_value() ||
|
||||
capture_filesize.has_value() || warn_evttypes.has_value() ||
|
||||
skip_if_unknown_filter.has_value();
|
||||
}
|
||||
|
||||
@@ -539,6 +542,8 @@ struct rule_update_info {
|
||||
std::optional<falco_common::priority_type> priority;
|
||||
std::optional<bool> capture;
|
||||
std::optional<uint32_t> capture_duration;
|
||||
std::optional<uint32_t> capture_events;
|
||||
std::optional<uint32_t> capture_filesize;
|
||||
std::optional<bool> enabled;
|
||||
std::optional<bool> warn_evttypes;
|
||||
std::optional<bool> skip_if_unknown_filter;
|
||||
|
||||
@@ -321,6 +321,14 @@ void rule_loader::collector::selective_replace(configuration& cfg, rule_update_i
|
||||
prev->capture_duration = *info.capture_duration;
|
||||
}
|
||||
|
||||
if(info.capture_events.has_value()) {
|
||||
prev->capture_events = *info.capture_events;
|
||||
}
|
||||
|
||||
if(info.capture_filesize.has_value()) {
|
||||
prev->capture_filesize = *info.capture_filesize;
|
||||
}
|
||||
|
||||
if(info.enabled.has_value()) {
|
||||
prev->enabled = *info.enabled;
|
||||
}
|
||||
|
||||
@@ -544,6 +544,8 @@ void rule_loader::compiler::compile_rule_infos(const configuration& cfg,
|
||||
rule.priority = r.priority;
|
||||
rule.capture = r.capture;
|
||||
rule.capture_duration = r.capture_duration;
|
||||
rule.capture_events = r.capture_events;
|
||||
rule.capture_filesize = r.capture_filesize;
|
||||
rule.tags = r.tags;
|
||||
auto rule_id = out.insert(rule, rule.name);
|
||||
out.at(rule_id)->id = rule_id;
|
||||
|
||||
@@ -683,6 +683,8 @@ void rule_loader::reader::read_item(rule_loader::configuration& cfg,
|
||||
"priority",
|
||||
"capture",
|
||||
"capture_duration",
|
||||
"capture_events",
|
||||
"capture_filesize",
|
||||
"tags",
|
||||
"exceptions",
|
||||
"enabled",
|
||||
@@ -821,6 +823,22 @@ void rule_loader::reader::read_item(rule_loader::configuration& cfg,
|
||||
decode_val(item, "capture_duration", v.capture_duration, ctx);
|
||||
}
|
||||
|
||||
if(check_update_expected(expected_keys,
|
||||
override_replace,
|
||||
"replace",
|
||||
"capture_events",
|
||||
ctx)) {
|
||||
decode_val(item, "capture_events", v.capture_events, ctx);
|
||||
}
|
||||
|
||||
if(check_update_expected(expected_keys,
|
||||
override_replace,
|
||||
"replace",
|
||||
"capture_filesize",
|
||||
ctx)) {
|
||||
decode_val(item, "capture_filesize", v.capture_filesize, ctx);
|
||||
}
|
||||
|
||||
if(check_update_expected(expected_keys,
|
||||
override_replace,
|
||||
"replace",
|
||||
@@ -885,6 +903,8 @@ void rule_loader::reader::read_item(rule_loader::configuration& cfg,
|
||||
v.enabled = true;
|
||||
v.capture = false;
|
||||
v.capture_duration = 0;
|
||||
v.capture_events = 0;
|
||||
v.capture_filesize = 0;
|
||||
v.warn_evttypes = true;
|
||||
v.skip_if_unknown_filter = false;
|
||||
|
||||
@@ -932,6 +952,8 @@ void rule_loader::reader::read_item(rule_loader::configuration& cfg,
|
||||
decode_optional_val(item, "enabled", v.enabled, ctx);
|
||||
decode_optional_val(item, "capture", v.capture, ctx);
|
||||
decode_optional_val(item, "capture_duration", v.capture_duration, ctx);
|
||||
decode_optional_val(item, "capture_events", v.capture_events, ctx);
|
||||
decode_optional_val(item, "capture_filesize", v.capture_filesize, ctx);
|
||||
decode_optional_val(item, "warn_evttypes", v.warn_evttypes, ctx);
|
||||
decode_optional_val(item, "skip-if-unknown-filter", v.skip_if_unknown_filter, ctx);
|
||||
decode_tags(item, v.tags, ctx);
|
||||
|
||||
@@ -149,6 +149,8 @@ static falco::app::run_result do_inspect(
|
||||
auto dumper = std::make_unique<sinsp_dumper>();
|
||||
uint64_t dump_started_ts = 0;
|
||||
uint64_t dump_deadline_ts = 0;
|
||||
uint64_t dump_max_events = 0;
|
||||
uint64_t dump_max_filesize_kb = 0;
|
||||
|
||||
//
|
||||
// Start capture
|
||||
@@ -178,6 +180,8 @@ static falco::app::run_result do_inspect(
|
||||
if(dump_started_ts != 0) {
|
||||
dump_started_ts = 0;
|
||||
dump_deadline_ts = 0;
|
||||
dump_max_events = 0;
|
||||
dump_max_filesize_kb = 0;
|
||||
dumper->close();
|
||||
}
|
||||
});
|
||||
@@ -188,6 +192,8 @@ static falco::app::run_result do_inspect(
|
||||
if(dump_started_ts != 0) {
|
||||
dump_started_ts = 0;
|
||||
dump_deadline_ts = 0;
|
||||
dump_max_events = 0;
|
||||
dump_max_filesize_kb = 0;
|
||||
dumper->close();
|
||||
}
|
||||
s.restart.store(true);
|
||||
@@ -331,6 +337,20 @@ static falco::app::run_result do_inspect(
|
||||
if(evt_deadline_ts > dump_deadline_ts) {
|
||||
dump_deadline_ts = evt_deadline_ts;
|
||||
}
|
||||
// Compute event count limit
|
||||
auto evt_max_events = rule_res.capture_events > 0
|
||||
? rule_res.capture_events
|
||||
: s.config->m_capture_default_events;
|
||||
if(evt_max_events > dump_max_events) {
|
||||
dump_max_events = evt_max_events;
|
||||
}
|
||||
// Compute file size limit
|
||||
auto evt_max_filesize = rule_res.capture_filesize_kb > 0
|
||||
? rule_res.capture_filesize_kb
|
||||
: s.config->m_capture_default_filesize_kb;
|
||||
if(evt_max_filesize > dump_max_filesize_kb) {
|
||||
dump_max_filesize_kb = evt_max_filesize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,14 +367,20 @@ static falco::app::run_result do_inspect(
|
||||
}
|
||||
|
||||
// Save events when a dump is in progress.
|
||||
// If the deadline is reached, close the dump.
|
||||
// If any stop condition is reached, close the dump.
|
||||
if(dump_started_ts != 0) {
|
||||
dumper->dump(ev);
|
||||
if(ev->get_ts() > dump_deadline_ts) {
|
||||
bool stop = ev->get_ts() > dump_deadline_ts;
|
||||
stop = stop || (dump_max_events > 0 && dumper->written_events() >= dump_max_events);
|
||||
stop = stop || (dump_max_filesize_kb > 0 &&
|
||||
dumper->written_bytes() >= dump_max_filesize_kb * 1024);
|
||||
if(stop) {
|
||||
dumper->flush();
|
||||
dumper->close();
|
||||
dump_started_ts = 0;
|
||||
dump_deadline_ts = 0;
|
||||
dump_max_events = 0;
|
||||
dump_max_filesize_kb = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -327,6 +327,12 @@ const char config_schema_string[] = LONG_STRING_CONST(
|
||||
},
|
||||
"default_duration": {
|
||||
"type": "integer"
|
||||
},
|
||||
"default_events": {
|
||||
"type": "integer"
|
||||
},
|
||||
"default_filesize": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"title": "Capture"
|
||||
|
||||
@@ -100,7 +100,9 @@ falco_configuration::falco_configuration():
|
||||
m_capture_enabled(false),
|
||||
m_capture_path_prefix("/tmp/falco"),
|
||||
m_capture_mode(capture_mode_t::RULES),
|
||||
m_capture_default_duration_ns(5000 * 1000000LL) {
|
||||
m_capture_default_duration_ns(5000 * 1000000LL),
|
||||
m_capture_default_events(0),
|
||||
m_capture_default_filesize_kb(0) {
|
||||
m_config_schema = nlohmann::json::parse(config_schema_string);
|
||||
}
|
||||
|
||||
@@ -618,6 +620,8 @@ void falco_configuration::load_yaml(const std::string &config_name) {
|
||||
// Convert to nanoseconds
|
||||
m_capture_default_duration_ns =
|
||||
m_config.get_scalar<uint32_t>("capture.default_duration", 5000) * 1000000LL;
|
||||
m_capture_default_events = m_config.get_scalar<uint64_t>("capture.default_events", 0);
|
||||
m_capture_default_filesize_kb = m_config.get_scalar<uint64_t>("capture.default_filesize", 0);
|
||||
|
||||
m_plugins_hostinfo = m_config.get_scalar<bool>("plugins_hostinfo", true);
|
||||
|
||||
|
||||
@@ -198,6 +198,8 @@ public:
|
||||
std::string m_capture_path_prefix;
|
||||
capture_mode_t m_capture_mode = capture_mode_t::RULES;
|
||||
uint64_t m_capture_default_duration_ns;
|
||||
uint64_t m_capture_default_events;
|
||||
uint64_t m_capture_default_filesize_kb;
|
||||
|
||||
// Falco engine
|
||||
engine_kind_t m_engine_mode = engine_kind_t::KMOD;
|
||||
|
||||
Reference in New Issue
Block a user