diff --git a/unit_tests/engine/test_rule_loader.cpp b/unit_tests/engine/test_rule_loader.cpp index 6d76e830..ae680cd6 100644 --- a/unit_tests/engine/test_rule_loader.cpp +++ b/unit_tests/engine/test_rule_loader.cpp @@ -1,6 +1,9 @@ #include #include "../test_falco_engine.h" +#include "yaml_helper.h" + +#define ASSERT_VALIDATION_STATUS(status) ASSERT_TRUE(sinsp_utils::startswith(m_load_result->schema_validation(), status)) std::string s_sample_ruleset = "sample-ruleset"; std::string s_sample_source = falco_common::syscall_source; @@ -24,6 +27,7 @@ TEST_F(test_falco_engine, list_append) )END"; ASSERT_TRUE(load_rules(rules_content, "legit_rules.yaml")) << m_load_result_string; + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_EQ(get_compiled_rule_condition("legit_rule"),"(evt.type = open and proc.name in (ash, bash, csh, ksh, sh, tcsh, zsh, dash, pwsh))"); } @@ -48,6 +52,7 @@ TEST_F(test_falco_engine, condition_append) )END"; ASSERT_TRUE(load_rules(rules_content, "legit_rules.yaml")) << m_load_result_string; + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_EQ(get_compiled_rule_condition("legit_rule"),"(evt.type = open and (((proc.aname = sshd and proc.name != sshd) or proc.name = systemd-logind or proc.name = login) or proc.name = ssh))"); } @@ -72,6 +77,7 @@ TEST_F(test_falco_engine, rule_override_append) std::string rule_name = "legit_rule"; ASSERT_TRUE(load_rules(rules_content, "legit_rules.yaml")) << m_load_result_string; + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); // Here we don't use the deprecated `append` flag, so we don't expect the warning. ASSERT_FALSE(check_warning_message(WARNING_APPEND)); @@ -102,6 +108,7 @@ TEST_F(test_falco_engine, rule_append) )END"; ASSERT_TRUE(load_rules(rules_content, "legit_rules.yaml")) << m_load_result_string; + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); // We should have at least one warning because the 'append' flag is deprecated. ASSERT_TRUE(check_warning_message(WARNING_APPEND)); @@ -128,6 +135,7 @@ TEST_F(test_falco_engine, rule_override_replace) std::string rule_name = "legit_rule"; ASSERT_TRUE(load_rules(rules_content, "legit_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"]["condition"].template get(), @@ -161,6 +169,7 @@ TEST_F(test_falco_engine, rule_override_append_replace) std::string rule_name = "legit_rule"; ASSERT_TRUE(load_rules(rules_content, "legit_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"]["condition"].template get(), @@ -196,6 +205,7 @@ TEST_F(test_falco_engine, rule_incorrect_override_type) )END"; ASSERT_FALSE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_TRUE(check_error_message("Key 'priority' cannot be appended to, use 'replace' instead")); ASSERT_TRUE(std::string(m_load_result_json["errors"][0]["context"]["snippet"]).find("priority: append") != std::string::npos); } @@ -219,6 +229,7 @@ TEST_F(test_falco_engine, rule_incorrect_append_override) )END"; ASSERT_FALSE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); // We should have at least one warning because the 'append' flag is deprecated. ASSERT_TRUE(check_warning_message(WARNING_APPEND)); @@ -248,6 +259,7 @@ TEST_F(test_falco_engine, macro_override_append_before_macro_definition) // We cannot define a macro override before the macro definition. ASSERT_FALSE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_MACRO)); } @@ -273,6 +285,7 @@ TEST_F(test_falco_engine, macro_override_replace_before_macro_definition) // The first override defines a macro that is overridden by the second macro definition ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_EQ(get_compiled_rule_condition("test_rule"),"evt.type in (open, openat)"); } @@ -297,6 +310,7 @@ TEST_F(test_falco_engine, macro_append_before_macro_definition) // We cannot define a macro override before the macro definition. ASSERT_FALSE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_MACRO)); } @@ -322,6 +336,7 @@ TEST_F(test_falco_engine, macro_override_append_after_macro_definition) // We cannot define a macro override before the macro definition. ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type in (open, openat) or evt.type = openat2)"); } @@ -346,6 +361,7 @@ TEST_F(test_falco_engine, macro_append_after_macro_definition) // We cannot define a macro override before the macro definition. ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type in (open, openat) or evt.type = openat2)"); } @@ -366,6 +382,7 @@ TEST_F(test_falco_engine, rule_override_append_before_rule_definition) )END"; ASSERT_FALSE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_RULE_APPEND)); } @@ -386,6 +403,7 @@ TEST_F(test_falco_engine, rule_override_replace_before_rule_definition) )END"; ASSERT_FALSE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_RULE_REPLACE)); } @@ -405,6 +423,7 @@ TEST_F(test_falco_engine, rule_append_before_rule_definition) )END"; ASSERT_FALSE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_RULE_APPEND)); } @@ -424,6 +443,7 @@ TEST_F(test_falco_engine, rule_override_append_after_rule_definition) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type in (open, openat) and proc.name = cat)"); } @@ -442,6 +462,7 @@ TEST_F(test_falco_engine, rule_append_after_rule_definition) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type in (open, openat) and proc.name = cat)"); } @@ -470,6 +491,7 @@ TEST_F(test_falco_engine, list_override_append_wrong_key) // considered. so in this situation, we are defining the list 2 times. The // second one overrides the first one. ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_failed) << m_load_result->schema_validation(); ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type = execve and proc.name in (blkid))"); } @@ -494,6 +516,7 @@ TEST_F(test_falco_engine, list_override_append_before_list_definition) // We cannot define a list override before the list definition. ASSERT_FALSE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_LIST)); } @@ -518,6 +541,7 @@ TEST_F(test_falco_engine, list_override_replace_before_list_definition) // With override replace we define a first list that then is overridden by the second one. ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type = execve and proc.name in (blkid))"); } @@ -541,6 +565,7 @@ TEST_F(test_falco_engine, list_append_before_list_definition) // We cannot define a list append before the list definition. ASSERT_FALSE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_TRUE(check_error_message(ERROR_NO_PREVIOUS_LIST)); } @@ -564,6 +589,7 @@ TEST_F(test_falco_engine, list_override_append_after_list_definition) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type = execve and proc.name in (blkid, csi-provisioner, csi-attacher))"); } @@ -585,6 +611,7 @@ TEST_F(test_falco_engine, list_append_after_list_definition) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_EQ(get_compiled_rule_condition("test_rule"),"(evt.type = execve and proc.name in (blkid, csi-provisioner, csi-attacher))"); } @@ -605,6 +632,7 @@ TEST_F(test_falco_engine, rule_override_without_field) )END"; ASSERT_FALSE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_TRUE(check_error_message("An append override for 'condition' was specified but 'condition' is not defined")); } @@ -627,6 +655,7 @@ TEST_F(test_falco_engine, rule_override_extra_field) )END"; ASSERT_FALSE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_TRUE(check_error_message("Unexpected key 'priority'")); } @@ -651,6 +680,7 @@ TEST_F(test_falco_engine, missing_enabled_key_with_override) // In the rule override we miss `enabled: true` ASSERT_FALSE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_TRUE(check_error_message("'enabled' was specified but 'enabled' is not defined")); } @@ -675,6 +705,7 @@ TEST_F(test_falco_engine, rule_override_with_enabled) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_FALSE(has_warnings()); // The rule should be enabled at the end. EXPECT_EQ(num_rules_for_ruleset(), 1); @@ -712,6 +743,7 @@ TEST_F(test_falco_engine, rule_override_exceptions_required_fields) )END"; ASSERT_FALSE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_FALSE(has_warnings()); ASSERT_TRUE(check_error_message("Item has no mapping for key 'fields'")) << m_load_result_json.dump(); } @@ -728,6 +760,7 @@ TEST_F(test_falco_engine, rule_not_enabled) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_FALSE(has_warnings()); EXPECT_EQ(num_rules_for_ruleset(), 0); } @@ -747,6 +780,7 @@ TEST_F(test_falco_engine, rule_enabled_warning) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_TRUE(check_warning_message(WARNING_ENABLED)); // The rule should be enabled at the end. EXPECT_EQ(num_rules_for_ruleset(), 1); @@ -772,6 +806,7 @@ TEST_F(test_falco_engine, rule_enabled_is_ignored_by_append) // 'enabled' is ignored by the append, this syntax is not supported // so the rule is not enabled. ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); EXPECT_EQ(num_rules_for_ruleset(), 0); } @@ -797,6 +832,7 @@ TEST_F(test_falco_engine, rewrite_rule) // The above syntax is not supported, we cannot override the content // of a rule in this way. ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); // In this case the rule is completely overridden but this syntax is not supported. EXPECT_EQ(num_rules_for_ruleset(), 1); ASSERT_EQ(get_compiled_rule_condition("test_rule"),"proc.name = cat"); @@ -817,6 +853,7 @@ TEST_F(test_falco_engine, required_engine_version_semver) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_FALSE(has_warnings()); } @@ -835,6 +872,7 @@ TEST_F(test_falco_engine, required_engine_version_not_semver) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_FALSE(has_warnings()); } @@ -853,6 +891,7 @@ TEST_F(test_falco_engine, required_engine_version_invalid) )END"; ASSERT_FALSE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_TRUE(check_error_message("Unable to parse engine version")); } @@ -865,22 +904,23 @@ TEST_F(test_falco_engine, list_value_with_escaping) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_TRUE(m_load_result->successful()); - ASSERT_TRUE(m_load_result->has_warnings()); // a warning for the unused list + ASSERT_TRUE(m_load_result->has_warnings()); // a warning for the unused list - auto rule_description = m_engine->describe_rule(nullptr, {}); - ASSERT_TRUE(m_load_result->successful()); - ASSERT_EQ(rule_description["rules"].size(), 0); - ASSERT_EQ(rule_description["macros"].size(), 0); - ASSERT_EQ(rule_description["lists"].size(), 1); + auto rule_description = m_engine->describe_rule(nullptr, {}); + ASSERT_TRUE(m_load_result->successful()); + ASSERT_EQ(rule_description["rules"].size(), 0); + ASSERT_EQ(rule_description["macros"].size(), 0); + ASSERT_EQ(rule_description["lists"].size(), 1); - // escaped values must not be interpreted as list refs by mistake - ASSERT_EQ(rule_description["lists"][0]["details"]["lists"].size(), 0); + // escaped values must not be interpreted as list refs by mistake + ASSERT_EQ(rule_description["lists"][0]["details"]["lists"].size(), 0); - // values should be escaped correctly - ASSERT_EQ(rule_description["lists"][0]["details"]["items_compiled"].size(), 2); - ASSERT_EQ(rule_description["lists"][0]["details"]["items_compiled"][0].template get(), "non_escaped_val"); - ASSERT_EQ(rule_description["lists"][0]["details"]["items_compiled"][1].template get(), "escaped val"); + // values should be escaped correctly + ASSERT_EQ(rule_description["lists"][0]["details"]["items_compiled"].size(), 2); + ASSERT_EQ(rule_description["lists"][0]["details"]["items_compiled"][0].template get(), "non_escaped_val"); + ASSERT_EQ(rule_description["lists"][0]["details"]["items_compiled"][1].template get(), "escaped val"); } TEST_F(test_falco_engine, exceptions_condition) @@ -900,6 +940,7 @@ TEST_F(test_falco_engine, exceptions_condition) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_EQ(get_compiled_rule_condition("test_rule"),"((proc.cmdline contains curl or proc.cmdline contains wget) and not proc.cmdline contains \"curl 127.0.0.1\")"); } @@ -911,6 +952,7 @@ TEST_F(test_falco_engine, macro_name_invalid) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_TRUE(check_warning_message("Macro has an invalid name. Macro names should match a regular expression")); } @@ -930,6 +972,7 @@ TEST_F(test_falco_engine, list_name_invalid) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_TRUE(check_warning_message("List has an invalid name. List names should match a regular expression")); } @@ -958,6 +1001,7 @@ TEST_F(test_falco_engine, exceptions_append_no_values) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_failed) << m_load_result->schema_validation(); ASSERT_TRUE(check_warning_message("Overriding/appending exception with no values")); } @@ -985,6 +1029,7 @@ TEST_F(test_falco_engine, exceptions_override_no_values) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_failed) << m_load_result->schema_validation(); ASSERT_TRUE(check_warning_message("Overriding/appending exception with no values")); } @@ -1010,6 +1055,7 @@ TEST_F(test_falco_engine, exceptions_names_not_unique) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_TRUE(check_warning_message("Multiple definitions of exception")); } @@ -1033,6 +1079,7 @@ TEST_F(test_falco_engine, exceptions_values_rhs_field_ambiguous) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not proc.name = proc.pname)"); EXPECT_TRUE(check_warning_message("'proc.pname' may be a valid field misused as a const string value")); } @@ -1049,6 +1096,7 @@ TEST_F(test_falco_engine, exceptions_values_rhs_field_ambiguous_quoted) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not proc.name = proc.pname)"); EXPECT_TRUE(check_warning_message("'proc.pname' may be a valid field misused as a const string value")); } @@ -1065,6 +1113,7 @@ TEST_F(test_falco_engine, exceptions_values_rhs_field_ambiguous_space_quoted) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not proc.name = \"proc.pname \")"); EXPECT_TRUE(check_warning_message("'proc.pname ' may be a valid field misused as a const string value")); } @@ -1081,6 +1130,7 @@ TEST_F(test_falco_engine, exceptions_values_rhs_transformer) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not proc.name = toupper(proc.pname))"); } @@ -1096,6 +1146,7 @@ TEST_F(test_falco_engine, exceptions_values_transformer_value_quoted) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not proc.name = toupper(proc.pname))"); } @@ -1111,6 +1162,7 @@ TEST_F(test_falco_engine, exceptions_values_transformer_space) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not proc.name = \"toupper( proc.pname)\")"); EXPECT_TRUE(check_warning_message("'toupper( proc.pname)' may be a valid field transformer misused as a const string value")); } @@ -1127,6 +1179,7 @@ TEST_F(test_falco_engine, exceptions_values_transformer_space_quoted) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not proc.name = \"toupper( proc.pname)\")"); EXPECT_TRUE(check_warning_message("'toupper( proc.pname)' may be a valid field transformer misused as a const string value")); } @@ -1143,6 +1196,7 @@ TEST_F(test_falco_engine, exceptions_fields_transformer) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); EXPECT_FALSE(has_warnings()); EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not tolower(proc.name) = test)"); } @@ -1159,6 +1213,7 @@ TEST_F(test_falco_engine, exceptions_fields_transformer_quoted) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_FALSE(has_warnings()); EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not tolower(proc.name) = test)"); } @@ -1175,6 +1230,7 @@ TEST_F(test_falco_engine, exceptions_fields_transformer_space_quoted) )END"; ASSERT_TRUE(load_rules(rules_content, "rules.yaml")); + ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation(); ASSERT_FALSE(has_warnings()); EXPECT_EQ(get_compiled_rule_condition("test_rule"), "(evt.type = open and not tolower(proc.name) = test)"); } diff --git a/userspace/engine/falco_engine.cpp b/userspace/engine/falco_engine.cpp index dd2603bf..a02aa17e 100644 --- a/userspace/engine/falco_engine.cpp +++ b/userspace/engine/falco_engine.cpp @@ -47,6 +47,153 @@ limitations under the License. const std::string falco_engine::s_default_ruleset = "falco-default-ruleset"; +static const std::string rule_schema_string = R"( +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "type": "array", + "items": { + "$ref": "#/definitions/FalcoRule" + }, + "definitions": { + "FalcoRule": { + "type": "object", + "additionalProperties": false, + "properties": { + "required_engine_version": { + "type": "string" + }, + "macro": { + "type": "string" + }, + "condition": { + "type": "string" + }, + "list": { + "type": "string" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/Item" + } + }, + "rule": { + "type": "string" + }, + "desc": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "output": { + "type": "string" + }, + "append": { + "type": "boolean" + }, + "priority": { + "$ref": "#/definitions/Priority" + }, + "exceptions": { + "type": "array", + "items": { + "$ref": "#/definitions/Exception" + } + }, + "override": { + "$ref": "#/definitions/Override" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [], + "title": "FalcoRule" + }, + "Item": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "title": "Item" + }, + "Exception": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "fields": {}, + "comps": {}, + "values": {} + }, + "required": [ + "name", + "values" + ], + "title": "Exception" + }, + "Priority": { + "type": "string", + "enum": [ + "WARNING", + "NOTICE", + "INFO", + "ERROR", + "CRITICAL" + ], + "title": "Priority" + }, + "OverriddenItem": { + "type": "string", + "enum": [ + "append", + "replace" + ], + "title": "Priority" + }, + "Override": { + "type": "object", + "additionalProperties": false, + "properties": { + "items": { + "$ref": "#/definitions/OverriddenItem" + }, + "desc": { + "$ref": "#/definitions/OverriddenItem" + }, + "condition": { + "$ref": "#/definitions/OverriddenItem" + }, + "output": { + "$ref": "#/definitions/OverriddenItem" + }, + "priority": { + "$ref": "#/definitions/OverriddenItem" + }, + "enabled": { + "$ref": "#/definitions/OverriddenItem" + }, + "exceptions": { + "$ref": "#/definitions/OverriddenItem" + } + }, + "minProperties":1, + "title": "Override" + } + } +} +)"; + using namespace falco; falco_engine::falco_engine(bool seed_rng) @@ -67,6 +214,8 @@ falco_engine::falco_engine(bool seed_rng) m_default_ruleset_id = find_ruleset_id(s_default_ruleset); fill_engine_state_funcs(m_engine_state); + + m_rule_schema = nlohmann::json::parse(rule_schema_string); } falco_engine::~falco_engine() @@ -198,7 +347,7 @@ std::unique_ptr falco_engine::load_rules(const std::string &rules_c cfg.extra_output_fields = m_extra_output_fields; // read rules YAML file and collect its definitions - if(m_rule_reader->read(cfg, *m_rule_collector)) + if(m_rule_reader->read(cfg, *m_rule_collector, m_rule_schema)) { // compile the definitions (resolve macro/list refs, exceptions, ...) m_last_compile_output = m_rule_compiler->new_compile_output(); diff --git a/userspace/engine/falco_engine.h b/userspace/engine/falco_engine.h index 5af6d1c9..17171c4c 100644 --- a/userspace/engine/falco_engine.h +++ b/userspace/engine/falco_engine.h @@ -355,6 +355,8 @@ public: const std::vector& plugins, std::string& err) const; + nlohmann::json m_rule_schema; + private: // Create a ruleset using the provided factory and set the // engine state funcs for it. diff --git a/userspace/engine/falco_load_result.h b/userspace/engine/falco_load_result.h index 1f7b261b..23f2f8fc 100644 --- a/userspace/engine/falco_load_result.h +++ b/userspace/engine/falco_load_result.h @@ -87,6 +87,9 @@ public: // has_warnings() can both be true if there were only warnings. virtual bool has_warnings() = 0; + // Return json schema validation status. + virtual std::string schema_validation() = 0; + // This represents a set of rules contents as a mapping from // rules content name (usually filename) to rules content. The // rules content is actually a reference to the actual string diff --git a/userspace/engine/rule_loader.cpp b/userspace/engine/rule_loader.cpp index cd00a19b..b843419e 100644 --- a/userspace/engine/rule_loader.cpp +++ b/userspace/engine/rule_loader.cpp @@ -18,6 +18,7 @@ limitations under the License. #include #include "rule_loader.h" +#include "yaml_helper.h" static const std::string item_type_strings[] = { @@ -282,7 +283,8 @@ std::string rule_loader::context::snippet(const falco::load_result::rules_conten rule_loader::result::result(const std::string &name) : name(name), - success(true) + success(true), + schema_validation_str(yaml_helper::validation_none) { } @@ -296,6 +298,11 @@ bool rule_loader::result::has_warnings() return (warnings.size() > 0); } +std::string rule_loader::result::schema_validation() +{ + return schema_validation_str; +} + void rule_loader::result::add_error(load_result::error_code ec, const std::string& msg, const context& ctx) { error err = {ec, msg, ctx}; @@ -311,6 +318,11 @@ void rule_loader::result::add_warning(load_result::warning_code wc, const std::s warnings.push_back(warn); } +void rule_loader::result::set_schema_validation_status(const std::string& status) +{ + schema_validation_str = status; +} + const std::string& rule_loader::result::as_string(bool verbose, const rules_contents_t& contents) { if(verbose) diff --git a/userspace/engine/rule_loader.h b/userspace/engine/rule_loader.h index 3ec15f90..2cbbca6a 100644 --- a/userspace/engine/rule_loader.h +++ b/userspace/engine/rule_loader.h @@ -247,12 +247,16 @@ namespace rule_loader void add_warning(falco::load_result::warning_code ec, const std::string& msg, const context& ctx); + + void set_schema_validation_status(const std::string& status); + std::string schema_validation(); protected: const std::string& as_summary_string(); const std::string& as_verbose_string(const falco::load_result::rules_contents_t& contents); std::string name; bool success; + std::string schema_validation_str; std::vector errors; std::vector warnings; diff --git a/userspace/engine/rule_loader_reader.cpp b/userspace/engine/rule_loader_reader.cpp index 4d875cb4..6148a21a 100644 --- a/userspace/engine/rule_loader_reader.cpp +++ b/userspace/engine/rule_loader_reader.cpp @@ -23,6 +23,7 @@ limitations under the License. #include "rule_loader_reader.h" #include "falco_engine_version.h" #include "rule_loading_messages.h" +#include "yaml_helper.h" #include #include @@ -783,13 +784,15 @@ void rule_loader::reader::read_item( } } -bool rule_loader::reader::read(rule_loader::configuration& cfg, collector& collector) +bool rule_loader::reader::read(rule_loader::configuration& cfg, collector& collector, const nlohmann::json& schema) { std::vector docs; + yaml_helper reader; + std::string schema_validation; rule_loader::context ctx(cfg.name); try { - docs = YAML::LoadAll(cfg.content); + docs = reader.loadall_from_string(cfg.content, schema, &schema_validation); } catch (YAML::ParserException& e) { @@ -807,7 +810,7 @@ bool rule_loader::reader::read(rule_loader::configuration& cfg, collector& colle cfg.res->add_error(falco::load_result::LOAD_ERR_YAML_PARSE, "unknown YAML parsing error", ctx); return false; } - + cfg.res->set_schema_validation_status(schema_validation); for (auto doc = docs.begin(); doc != docs.end(); doc++) { if (doc->IsDefined() && !doc->IsNull()) diff --git a/userspace/engine/rule_loader_reader.h b/userspace/engine/rule_loader_reader.h index 0c331234..d105d037 100644 --- a/userspace/engine/rule_loader_reader.h +++ b/userspace/engine/rule_loader_reader.h @@ -43,7 +43,7 @@ public: \brief Reads the contents of a ruleset and uses a collector to store thew new definitions */ - virtual bool read(configuration& cfg, collector& loader); + virtual bool read(configuration& cfg, collector& loader, const nlohmann::json& schema={}); /*! \brief Engine version used to be represented as a simple progressive diff --git a/userspace/falco/yaml_helper.h b/userspace/engine/yaml_helper.h similarity index 93% rename from userspace/falco/yaml_helper.h rename to userspace/engine/yaml_helper.h index d1134873..067f006f 100644 --- a/userspace/falco/yaml_helper.h +++ b/userspace/engine/yaml_helper.h @@ -41,10 +41,10 @@ limitations under the License. #include #include -#include "config_falco.h" +//#include "config_falco.h" -#include "event_drops.h" -#include "falco_outputs.h" +//#include "event_drops.h" +//#include "falco_outputs.h" class yaml_helper; @@ -89,7 +89,37 @@ public: inline static const std::string configs_key = "config_files"; inline static const std::string validation_ok = "ok"; inline static const std::string validation_failed = "failed"; - inline static const std::string validation_none = "schema not provided"; + inline static const std::string validation_none = "none"; + + /** + * Load all the YAML document represented by the input string. + * Since this is used by rule loader, does not process env vars. + */ + std::vector loadall_from_string(const std::string& input, const nlohmann::json& schema={}, std::string *validation=nullptr) + { + auto nodes = YAML::LoadAll(input); + if (validation) + { + if(!schema.empty()) + { + // Validate each node. + for (const auto& node : nodes) + { + *validation = validate_node(node, schema); + if (*validation != validation_ok) + { + // Return first error + break; + } + } + } + else + { + *validation = validation_none; + } + } + return nodes; + } /** * Load the YAML document represented by the input string. diff --git a/userspace/falco/app/actions/helpers.h b/userspace/falco/app/actions/helpers.h index 222480b1..4bd62ffc 100644 --- a/userspace/falco/app/actions/helpers.h +++ b/userspace/falco/app/actions/helpers.h @@ -26,9 +26,6 @@ namespace falco { namespace app { namespace actions { -// Map that holds { rule filename | validation status } for each rule file read. -typedef std::map rule_read_res; - bool check_rules_plugin_requirements(falco::app::state& s, std::string& err); void print_enabled_event_sources(falco::app::state& s); void activate_interesting_kernel_tracepoints(falco::app::state& s, std::unique_ptr& inspector); @@ -43,14 +40,10 @@ falco::app::run_result open_live_inspector( const std::string& source); template -rule_read_res read_files(InputIterator begin, InputIterator end, +void read_files(InputIterator begin, InputIterator end, std::vector& rules_contents, - falco::load_result::rules_contents_t& rc, - const nlohmann::json& schema={}) + falco::load_result::rules_contents_t& rc) { - rule_read_res res; - yaml_helper reader; - std::string validation; // Read the contents in a first pass for(auto it = begin; it != end; it++) { @@ -65,8 +58,6 @@ rule_read_res read_files(InputIterator begin, InputIterator end, std::string rules_content((std::istreambuf_iterator(is)), std::istreambuf_iterator()); - reader.load_from_string(rules_content, schema, &validation); - res[filename] = validation; rules_contents.emplace_back(std::move(rules_content)); } @@ -85,8 +76,6 @@ rule_read_res read_files(InputIterator begin, InputIterator end, { throw falco_exception("Unexpected mismatch in rules content name/rules content sets?"); } - - return res; } diff --git a/userspace/falco/app/actions/load_rules_files.cpp b/userspace/falco/app/actions/load_rules_files.cpp index d1cb2726..ec4050ba 100644 --- a/userspace/falco/app/actions/load_rules_files.cpp +++ b/userspace/falco/app/actions/load_rules_files.cpp @@ -54,12 +54,11 @@ falco::app::run_result falco::app::actions::load_rules_files(falco::app::state& std::vector rules_contents; falco::load_result::rules_contents_t rc; - rule_read_res validation_res; try { - validation_res = read_files(s.config->m_loaded_rules_filenames.begin(), + read_files(s.config->m_loaded_rules_filenames.begin(), s.config->m_loaded_rules_filenames.end(), rules_contents, - rc, s.config->m_rule_schema); + rc); } catch(falco_exception& e) { @@ -70,12 +69,11 @@ falco::app::run_result falco::app::actions::load_rules_files(falco::app::state& falco_logger::log(falco_logger::level::INFO, "Loading rules from:\n"); for(auto &filename : s.config->m_loaded_rules_filenames) { - auto validation = validation_res[filename]; - auto priority = validation == yaml_helper::validation_ok ? falco_logger::level::INFO : falco_logger::level::WARNING; - falco_logger::log(priority, std::string(" ") + filename + " | schema validation: " + validation + "\n"); std::unique_ptr res; res = s.engine->load_rules(rc.at(filename), filename); + auto priority = res->schema_validation() == yaml_helper::validation_ok ? falco_logger::level::INFO : falco_logger::level::WARNING; + falco_logger::log(priority, std::string(" ") + filename + " | schema validation: " + res->schema_validation() + "\n"); if(!res->successful()) { diff --git a/userspace/falco/app/actions/print_rule_schema.cpp b/userspace/falco/app/actions/print_rule_schema.cpp index b153ec8c..1052c597 100644 --- a/userspace/falco/app/actions/print_rule_schema.cpp +++ b/userspace/falco/app/actions/print_rule_schema.cpp @@ -24,7 +24,7 @@ falco::app::run_result falco::app::actions::print_rule_schema(falco::app::state { if(s.options.print_rule_schema) { - printf("%s", s.config->m_rule_schema.dump(2).c_str()); + printf("%s", s.engine->m_rule_schema.dump(2).c_str()); return run_result::exit(); } return run_result::ok(); diff --git a/userspace/falco/app/actions/validate_rules_files.cpp b/userspace/falco/app/actions/validate_rules_files.cpp index 3ecf0d42..0ab57272 100644 --- a/userspace/falco/app/actions/validate_rules_files.cpp +++ b/userspace/falco/app/actions/validate_rules_files.cpp @@ -33,12 +33,11 @@ falco::app::run_result falco::app::actions::validate_rules_files(falco::app::sta std::vector rules_contents; falco::load_result::rules_contents_t rc; - rule_read_res validation_res; try { - validation_res = read_files(s.options.validate_rules_filenames.begin(), + read_files(s.options.validate_rules_filenames.begin(), s.options.validate_rules_filenames.end(), rules_contents, - rc,s.config->m_rule_schema); + rc); } catch(falco_exception& e) { @@ -69,24 +68,21 @@ falco::app::run_result falco::app::actions::validate_rules_files(falco::app::sta // printed when verbose is true. std::string summary; - falco_logger::log(falco_logger::level::INFO, "Validating rules file(s):\n"); - for(const auto& file : s.options.validate_rules_filenames) - { - auto validation = validation_res[file]; - auto priority = validation == yaml_helper::validation_ok ? falco_logger::level::INFO : falco_logger::level::WARNING; - falco_logger::log(priority, std::string(" ") + file + " | schema validation: " + validation + "\n"); - } - // The json output encompasses all files so the // validation result is a single json object. std::string err = ""; nlohmann::json results = nlohmann::json::array(); + falco_logger::log(falco_logger::level::INFO, "Validating rules file(s):\n"); for(auto &filename : s.options.validate_rules_filenames) { std::unique_ptr res; res = s.engine->load_rules(rc.at(filename), filename); + + auto priority = res->schema_validation() == yaml_helper::validation_ok ? falco_logger::level::INFO : falco_logger::level::WARNING; + falco_logger::log(priority, std::string(" ") + filename + " | schema validation: " + res->schema_validation() + "\n"); + if (!check_rules_plugin_requirements(s, err)) { return run_result::fatal(err); diff --git a/userspace/falco/configuration.cpp b/userspace/falco/configuration.cpp index 4bab01ad..0e9a49ce 100644 --- a/userspace/falco/configuration.cpp +++ b/userspace/falco/configuration.cpp @@ -55,87 +55,6 @@ static re2::RE2 ip_address_re("((^\\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]| // to format the json, add the new fields, and then minify it again. static const std::string config_schema_string = R"({"$schema":"http://json-schema.org/draft-06/schema#","$ref":"#/definitions/FalcoConfig","definitions":{"FalcoConfig":{"type":"object","additionalProperties":false,"properties":{"append_output":{"type":"array","items":{"$ref":"#/definitions/AppendOutput"}},"config_files":{"type":"array","items":{"type":"string"}},"watch_config_files":{"type":"boolean"},"rules_files":{"type":"array","items":{"type":"string"}},"rule_files":{"type":"array","items":{"type":"string"}},"rules":{"type":"array","items":{"$ref":"#/definitions/Rule"}},"engine":{"$ref":"#/definitions/Engine"},"load_plugins":{"type":"array","items":{"type":"string"}},"plugins":{"type":"array","items":{"$ref":"#/definitions/Plugin"}},"time_format_iso_8601":{"type":"boolean"},"priority":{"type":"string"},"json_output":{"type":"boolean"},"json_include_output_property":{"type":"boolean"},"json_include_tags_property":{"type":"boolean"},"buffered_outputs":{"type":"boolean"},"rule_matching":{"type":"string"},"outputs_queue":{"$ref":"#/definitions/OutputsQueue"},"stdout_output":{"$ref":"#/definitions/Output"},"syslog_output":{"$ref":"#/definitions/Output"},"file_output":{"$ref":"#/definitions/FileOutput"},"http_output":{"$ref":"#/definitions/HTTPOutput"},"program_output":{"$ref":"#/definitions/ProgramOutput"},"grpc_output":{"$ref":"#/definitions/Output"},"grpc":{"$ref":"#/definitions/Grpc"},"webserver":{"$ref":"#/definitions/Webserver"},"log_stderr":{"type":"boolean"},"log_syslog":{"type":"boolean"},"log_level":{"type":"string"},"libs_logger":{"$ref":"#/definitions/LibsLogger"},"output_timeout":{"type":"integer"},"syscall_event_timeouts":{"$ref":"#/definitions/SyscallEventTimeouts"},"syscall_event_drops":{"$ref":"#/definitions/SyscallEventDrops"},"metrics":{"$ref":"#/definitions/Metrics"},"base_syscalls":{"$ref":"#/definitions/BaseSyscalls"},"falco_libs":{"$ref":"#/definitions/FalcoLibs"},"container_engines":{"type":"object","additionalProperties":false,"properties":{"docker":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"}}},"cri":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"},"sockets":{"type":"array","items":{"type":"string"}},"disable_async":{"type":"boolean"}}},"podman":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"}}},"lxc":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"}}},"libvirt_lxc":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"}}},"bpm":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"}}}}}},"title":"FalcoConfig"},"AppendOutput":{"type":"object","additionalProperties":false,"properties":{"source":{"type":"string"},"tag":{"type":"string"},"rule":{"type":"string"},"format":{"type":"string"},"fields":{"type":"array","items":{"anyOf":[{"type":"object","additionalProperties":{"type":"string"}},{"type":"string"}]}}}},"BaseSyscalls":{"type":"object","additionalProperties":false,"properties":{"custom_set":{"type":"array","items":{"type":"string"}},"repair":{"type":"boolean"}},"minProperties":1,"title":"BaseSyscalls"},"Engine":{"type":"object","additionalProperties":false,"properties":{"kind":{"type":"string"},"kmod":{"$ref":"#/definitions/Kmod"},"ebpf":{"$ref":"#/definitions/Ebpf"},"modern_ebpf":{"$ref":"#/definitions/ModernEbpf"},"replay":{"$ref":"#/definitions/Replay"},"gvisor":{"$ref":"#/definitions/Gvisor"}},"required":["kind"],"title":"Engine"},"Ebpf":{"type":"object","additionalProperties":false,"properties":{"probe":{"type":"string"},"buf_size_preset":{"type":"integer"},"drop_failed_exit":{"type":"boolean"}},"required":["probe"],"title":"Ebpf"},"Gvisor":{"type":"object","additionalProperties":false,"properties":{"config":{"type":"string"},"root":{"type":"string"}},"required":["config","root"],"title":"Gvisor"},"Kmod":{"type":"object","additionalProperties":false,"properties":{"buf_size_preset":{"type":"integer"},"drop_failed_exit":{"type":"boolean"}},"minProperties":1,"title":"Kmod"},"ModernEbpf":{"type":"object","additionalProperties":false,"properties":{"cpus_for_each_buffer":{"type":"integer"},"buf_size_preset":{"type":"integer"},"drop_failed_exit":{"type":"boolean"}},"title":"ModernEbpf"},"Replay":{"type":"object","additionalProperties":false,"properties":{"capture_file":{"type":"string"}},"required":["capture_file"],"title":"Replay"},"FalcoLibs":{"type":"object","additionalProperties":false,"properties":{"thread_table_size":{"type":"integer"}},"minProperties":1,"title":"FalcoLibs"},"FileOutput":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"},"keep_alive":{"type":"boolean"},"filename":{"type":"string"}},"minProperties":1,"title":"FileOutput"},"Grpc":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"},"bind_address":{"type":"string"},"threadiness":{"type":"integer"}},"minProperties":1,"title":"Grpc"},"Output":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"}},"minProperties":1,"title":"Output"},"HTTPOutput":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"},"url":{"type":"string","format":"uri","qt-uri-protocols":["http"]},"user_agent":{"type":"string"},"insecure":{"type":"boolean"},"ca_cert":{"type":"string"},"ca_bundle":{"type":"string"},"ca_path":{"type":"string"},"mtls":{"type":"boolean"},"client_cert":{"type":"string"},"client_key":{"type":"string"},"echo":{"type":"boolean"},"compress_uploads":{"type":"boolean"},"keep_alive":{"type":"boolean"}},"minProperties":1,"title":"HTTPOutput"},"LibsLogger":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"},"severity":{"type":"string"}},"minProperties":1,"title":"LibsLogger"},"Metrics":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"},"interval":{"type":"string"},"output_rule":{"type":"boolean"},"output_file":{"type":"string"},"rules_counters_enabled":{"type":"boolean"},"resource_utilization_enabled":{"type":"boolean"},"state_counters_enabled":{"type":"boolean"},"kernel_event_counters_enabled":{"type":"boolean"},"libbpf_stats_enabled":{"type":"boolean"},"plugins_metrics_enabled":{"type":"boolean"},"convert_memory_to_mb":{"type":"boolean"},"include_empty_values":{"type":"boolean"}},"minProperties":1,"title":"Metrics"},"OutputsQueue":{"type":"object","additionalProperties":false,"properties":{"capacity":{"type":"integer"}},"minProperties":1,"title":"OutputsQueue"},"Plugin":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"},"library_path":{"type":"string"},"init_config":{"type":"string"},"open_params":{"type":"string"}},"required":["library_path","name"],"title":"Plugin"},"ProgramOutput":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"},"keep_alive":{"type":"boolean"},"program":{"type":"string"}},"required":["program"],"title":"ProgramOutput"},"Rule":{"type":"object","additionalProperties":false,"properties":{"disable":{"$ref":"#/definitions/Able"},"enable":{"$ref":"#/definitions/Able"}},"minProperties":1,"title":"Rule"},"Able":{"type":"object","additionalProperties":false,"properties":{"rule":{"type":"string"},"tag":{"type":"string"}},"minProperties":1,"title":"Able"},"SyscallEventDrops":{"type":"object","additionalProperties":false,"properties":{"threshold":{"type":"number"},"actions":{"type":"array","items":{"type":"string"}},"rate":{"type":"number"},"max_burst":{"type":"integer"},"simulate_drops":{"type":"boolean"}},"minProperties":1,"title":"SyscallEventDrops"},"SyscallEventTimeouts":{"type":"object","additionalProperties":false,"properties":{"max_consecutives":{"type":"integer"}},"minProperties":1,"title":"SyscallEventTimeouts"},"Webserver":{"type":"object","additionalProperties":false,"properties":{"enabled":{"type":"boolean"},"threadiness":{"type":"integer"},"listen_port":{"type":"integer"},"listen_address":{"type":"string"},"k8s_healthz_endpoint":{"type":"string"},"prometheus_metrics_enabled":{"type":"boolean"},"ssl_enabled":{"type":"boolean"},"ssl_certificate":{"type":"string"}},"minProperties":1,"title":"Webserver"}}})"; -static const std::string rule_schema_string = R"( -{ - "$schema": "http://json-schema.org/draft-06/schema#", - "type": "array", - "items": { - "$ref": "#/definitions/FalcoRule" - }, - "definitions": { - "FalcoRule": { - "type": "object", - "additionalProperties": false, - "properties": { - "required_engine_version": { - "type": "string" - }, - "macro": { - "type": "string" - }, - "condition": { - "type": "string" - }, - "list": { - "type": "string" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/Item" - } - }, - "rule": { - "type": "string" - }, - "desc": { - "type": "string" - }, - "enabled": { - "type": "boolean" - }, - "output": { - "type": "string" - }, - "priority": { - "$ref": "#/definitions/Priority" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": [], - "title": "FalcoRule" - }, - "Item": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "title": "Item" - }, - "Priority": { - "type": "string", - "enum": [ - "WARNING", - "NOTICE", - "INFO", - "ERROR", - "CRITICAL" - ], - "title": "Priority" - } - } -} -)"; - falco_configuration::falco_configuration(): m_json_output(false), m_json_include_output_property(true), @@ -169,7 +88,6 @@ falco_configuration::falco_configuration(): m_container_engines_cri_socket_paths({"/run/containerd/containerd.sock", "/run/crio/crio.sock","/run/k3s/containerd/containerd.sock"}) { m_config_schema = nlohmann::json::parse(config_schema_string); - m_rule_schema = nlohmann::json::parse(rule_schema_string); } config_loaded_res falco_configuration::init_from_content(const std::string& config_content, const std::vector& cmdline_options, const std::string& filename) diff --git a/userspace/falco/configuration.h b/userspace/falco/configuration.h index 2be1f233..33d0addd 100644 --- a/userspace/falco/configuration.h +++ b/userspace/falco/configuration.h @@ -212,7 +212,6 @@ public: yaml_helper m_config; nlohmann::json m_config_schema; - nlohmann::json m_rule_schema; private: void merge_config_files(const std::string& config_name, config_loaded_res &res);