mirror of
https://github.com/falcosecurity/falco.git
synced 2026-03-30 00:22:12 +00:00
Compare commits
11 Commits
build/docs
...
add-except
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc570c58df | ||
|
|
68018d3a69 | ||
|
|
defde05c90 | ||
|
|
21ed93aa53 | ||
|
|
2eb286fd02 | ||
|
|
ab5a39c994 | ||
|
|
c4cc1d7996 | ||
|
|
b9671f936d | ||
|
|
0ffd1e9c5c | ||
|
|
81cdab21be | ||
|
|
60052bffcb |
@@ -585,7 +585,8 @@ class FalcoTest(Test):
|
|||||||
self.check_rules_warnings(res)
|
self.check_rules_warnings(res)
|
||||||
if len(self.rules_events) > 0:
|
if len(self.rules_events) > 0:
|
||||||
self.check_rules_events(res)
|
self.check_rules_events(res)
|
||||||
self.check_detections(res)
|
if len(self.validate_rules_file) == 0:
|
||||||
|
self.check_detections(res)
|
||||||
if len(self.detect_counts) > 0:
|
if len(self.detect_counts) > 0:
|
||||||
self.check_detections_by_rule(res)
|
self.check_detections_by_rule(res)
|
||||||
self.check_json_output(res)
|
self.check_json_output(res)
|
||||||
|
|||||||
@@ -262,6 +262,7 @@ trace_files: !mux
|
|||||||
invalid_not_yaml:
|
invalid_not_yaml:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stdout_is: |+
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
Rules content is not yaml
|
Rules content is not yaml
|
||||||
---
|
---
|
||||||
This is not yaml
|
This is not yaml
|
||||||
@@ -273,6 +274,7 @@ trace_files: !mux
|
|||||||
invalid_not_array:
|
invalid_not_array:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stdout_is: |+
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
Rules content is not yaml array of objects
|
Rules content is not yaml array of objects
|
||||||
---
|
---
|
||||||
foo: bar
|
foo: bar
|
||||||
@@ -284,6 +286,7 @@ trace_files: !mux
|
|||||||
invalid_array_item_not_object:
|
invalid_array_item_not_object:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stdout_is: |+
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
Unexpected element of type string. Each element should be a yaml associative array.
|
Unexpected element of type string. Each element should be a yaml associative array.
|
||||||
---
|
---
|
||||||
- foo
|
- foo
|
||||||
@@ -295,6 +298,7 @@ trace_files: !mux
|
|||||||
invalid_unexpected object:
|
invalid_unexpected object:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stdout_is: |+
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
Unknown rule object: {foo="bar"}
|
Unknown rule object: {foo="bar"}
|
||||||
---
|
---
|
||||||
- foo: bar
|
- foo: bar
|
||||||
@@ -306,6 +310,7 @@ trace_files: !mux
|
|||||||
invalid_engine_version_not_number:
|
invalid_engine_version_not_number:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stdout_is: |+
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
Value of required_engine_version must be a number
|
Value of required_engine_version must be a number
|
||||||
---
|
---
|
||||||
- required_engine_version: not-a-number
|
- required_engine_version: not-a-number
|
||||||
@@ -317,6 +322,7 @@ trace_files: !mux
|
|||||||
invalid_yaml_parse_error:
|
invalid_yaml_parse_error:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stdout_is: |+
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
mapping values are not allowed in this context
|
mapping values are not allowed in this context
|
||||||
---
|
---
|
||||||
this : is : not : yaml
|
this : is : not : yaml
|
||||||
@@ -328,6 +334,7 @@ trace_files: !mux
|
|||||||
invalid_list_without_items:
|
invalid_list_without_items:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stdout_is: |+
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
List must have property items
|
List must have property items
|
||||||
---
|
---
|
||||||
- list: bad_list
|
- list: bad_list
|
||||||
@@ -340,6 +347,7 @@ trace_files: !mux
|
|||||||
invalid_macro_without_condition:
|
invalid_macro_without_condition:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stdout_is: |+
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
Macro must have property condition
|
Macro must have property condition
|
||||||
---
|
---
|
||||||
- macro: bad_macro
|
- macro: bad_macro
|
||||||
@@ -352,6 +360,7 @@ trace_files: !mux
|
|||||||
invalid_rule_without_output:
|
invalid_rule_without_output:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stdout_is: |+
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
Rule must have property output
|
Rule must have property output
|
||||||
---
|
---
|
||||||
- rule: no output rule
|
- rule: no output rule
|
||||||
@@ -366,6 +375,7 @@ trace_files: !mux
|
|||||||
invalid_append_rule_without_condition:
|
invalid_append_rule_without_condition:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stdout_is: |+
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
Rule must have property condition
|
Rule must have property condition
|
||||||
---
|
---
|
||||||
- rule: no condition rule
|
- rule: no condition rule
|
||||||
@@ -378,6 +388,7 @@ trace_files: !mux
|
|||||||
invalid_append_macro_dangling:
|
invalid_append_macro_dangling:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stdout_is: |+
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
Macro dangling append has 'append' key but no macro by that name already exists
|
Macro dangling append has 'append' key but no macro by that name already exists
|
||||||
---
|
---
|
||||||
- macro: dangling append
|
- macro: dangling append
|
||||||
@@ -391,6 +402,7 @@ trace_files: !mux
|
|||||||
invalid_list_append_dangling:
|
invalid_list_append_dangling:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stdout_is: |+
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
List my_list has 'append' key but no list by that name already exists
|
List my_list has 'append' key but no list by that name already exists
|
||||||
---
|
---
|
||||||
- list: my_list
|
- list: my_list
|
||||||
@@ -404,6 +416,7 @@ trace_files: !mux
|
|||||||
invalid_rule_append_dangling:
|
invalid_rule_append_dangling:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stdout_is: |+
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
Rule my_rule has 'append' key but no rule by that name already exists
|
Rule my_rule has 'append' key but no rule by that name already exists
|
||||||
---
|
---
|
||||||
- rule: my_rule
|
- rule: my_rule
|
||||||
@@ -450,6 +463,7 @@ trace_files: !mux
|
|||||||
invalid_overwrite_macro_multiple_docs:
|
invalid_overwrite_macro_multiple_docs:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stdout_is: |+
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
Compilation error when compiling "foo": Undefined macro 'foo' used in filter.
|
Compilation error when compiling "foo": Undefined macro 'foo' used in filter.
|
||||||
---
|
---
|
||||||
- macro: some macro
|
- macro: some macro
|
||||||
@@ -463,6 +477,7 @@ trace_files: !mux
|
|||||||
invalid_append_macro_multiple_docs:
|
invalid_append_macro_multiple_docs:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stdout_is: |+
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
Compilation error when compiling "evt.type=execve foo": 17: syntax error, unexpected 'foo', expecting 'or', 'and'
|
Compilation error when compiling "evt.type=execve foo": 17: syntax error, unexpected 'foo', expecting 'or', 'and'
|
||||||
---
|
---
|
||||||
- macro: some macro
|
- macro: some macro
|
||||||
@@ -521,6 +536,7 @@ trace_files: !mux
|
|||||||
invalid_overwrite_rule_multiple_docs:
|
invalid_overwrite_rule_multiple_docs:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stdout_is: |+
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
Undefined macro 'bar' used in filter.
|
Undefined macro 'bar' used in filter.
|
||||||
---
|
---
|
||||||
- rule: some rule
|
- rule: some rule
|
||||||
@@ -559,6 +575,7 @@ trace_files: !mux
|
|||||||
invalid_missing_rule_name:
|
invalid_missing_rule_name:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stdout_is: |+
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
Rule name is empty
|
Rule name is empty
|
||||||
---
|
---
|
||||||
- rule:
|
- rule:
|
||||||
@@ -573,6 +590,7 @@ trace_files: !mux
|
|||||||
invalid_missing_list_name:
|
invalid_missing_list_name:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stdout_is: |+
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
List name is empty
|
List name is empty
|
||||||
---
|
---
|
||||||
- list:
|
- list:
|
||||||
@@ -585,6 +603,7 @@ trace_files: !mux
|
|||||||
invalid_missing_macro_name:
|
invalid_missing_macro_name:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stdout_is: |+
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
Macro name is empty
|
Macro name is empty
|
||||||
---
|
---
|
||||||
- macro:
|
- macro:
|
||||||
|
|||||||
259
test/falco_tests_exceptions.yaml
Normal file
259
test/falco_tests_exceptions.yaml
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2016-2020 The Falco Authors..
|
||||||
|
#
|
||||||
|
# This file is part of falco.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
trace_files: !mux
|
||||||
|
|
||||||
|
rule_exception_no_fields:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
|
Rule exception item ex1: must have fields property with a list of fields
|
||||||
|
---
|
||||||
|
- rule: My Rule
|
||||||
|
desc: Some desc
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: Some output
|
||||||
|
exceptions:
|
||||||
|
- name: ex1
|
||||||
|
priority: error
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/exceptions/rule_item_no_fields.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
exception_no_values:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
|
Exception item ex1: must have values property with a list of values
|
||||||
|
---
|
||||||
|
- exception: My Rule
|
||||||
|
items:
|
||||||
|
- name: ex1
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/exceptions/exception_item_no_values.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
rule_exception_no_name:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
|
Rule exception item must have name property
|
||||||
|
---
|
||||||
|
- rule: My Rule
|
||||||
|
desc: Some desc
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: Some output
|
||||||
|
exceptions:
|
||||||
|
- fields: [proc.name, fd.filename]
|
||||||
|
priority: error
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/exceptions/rule_item_no_name.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
exception_no_name:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
|
Exception item must have name property
|
||||||
|
---
|
||||||
|
- exception: My Rule
|
||||||
|
items:
|
||||||
|
- values:
|
||||||
|
- [nginx, /tmp/foo]
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/exceptions/exception_item_no_name.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
rule_exception_append:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
|
Can not append exceptions to existing rule, only conditions
|
||||||
|
---
|
||||||
|
- rule: My Rule
|
||||||
|
condition: and proc.name=apache
|
||||||
|
exceptions:
|
||||||
|
- name: ex2
|
||||||
|
fields: [proc.name, fd.filename]
|
||||||
|
append: true
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/exceptions/rule_append_exception.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
rule_exception_unknown_fields:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
|
Rule exception item ex1: field name not.exist is not a supported filter field
|
||||||
|
---
|
||||||
|
- rule: My Rule
|
||||||
|
desc: Some desc
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: Some output
|
||||||
|
exceptions:
|
||||||
|
- name: ex1
|
||||||
|
fields: [not.exist]
|
||||||
|
priority: error
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/exceptions/rule_item_unknown_fields.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
rule_exception_comps_fields_len_mismatch:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
|
Rule exception item ex1: fields and comps lists must have equal length
|
||||||
|
---
|
||||||
|
- rule: My Rule
|
||||||
|
desc: Some desc
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: Some output
|
||||||
|
exceptions:
|
||||||
|
- name: ex1
|
||||||
|
fields: [proc.name, fd.filename]
|
||||||
|
comps: [=]
|
||||||
|
priority: error
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/exceptions/rule_item_comps_fields_len_mismatch.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
rule_exception_unknown_comp:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
|
Rule exception item ex1: comparison operator no-comp is not a supported comparison operator
|
||||||
|
---
|
||||||
|
- rule: My Rule
|
||||||
|
desc: Some desc
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: Some output
|
||||||
|
exceptions:
|
||||||
|
- name: ex1
|
||||||
|
fields: [proc.name, fd.filename]
|
||||||
|
comps: [=, no-comp]
|
||||||
|
priority: error
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/exceptions/rule_item_unknown_comp.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
exception_fields_values_len_mismatch:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
1 errors:
|
||||||
|
Exception item ex1: fields and values lists must have equal length
|
||||||
|
---
|
||||||
|
- exception: My Rule
|
||||||
|
items:
|
||||||
|
- name: ex1
|
||||||
|
values:
|
||||||
|
- [nginx]
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/exceptions/exception_item_fields_values_len_mismatch.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
exception_item_not_in_rule:
|
||||||
|
exit_status: 0
|
||||||
|
stderr_contains: |+
|
||||||
|
1 warnings:
|
||||||
|
Exception My Rule: no set of fields matching name ex2
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/exceptions/exception_item_not_in_rule.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
rule_without_exception:
|
||||||
|
exit_status: 0
|
||||||
|
stderr_contains: |+
|
||||||
|
1 warnings:
|
||||||
|
Rule My Rule: consider adding an exceptions property to define supported exceptions fields
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/exceptions/rule_without_exception.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
rule_exception_no_values:
|
||||||
|
detect: True
|
||||||
|
detect_level: WARNING
|
||||||
|
rules_file:
|
||||||
|
- rules/exceptions/rule_exception_no_values.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
rule_exception_one_value:
|
||||||
|
detect: False
|
||||||
|
detect_level: WARNING
|
||||||
|
rules_file:
|
||||||
|
- rules/exceptions/rule_exception_one_value.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
rule_exception_second_value:
|
||||||
|
detect: False
|
||||||
|
detect_level: WARNING
|
||||||
|
rules_file:
|
||||||
|
- rules/exceptions/rule_exception_second_value.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
rule_exception_second_item:
|
||||||
|
detect: False
|
||||||
|
detect_level: WARNING
|
||||||
|
rules_file:
|
||||||
|
- rules/exceptions/rule_exception_second_item.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
rule_exception_third_item:
|
||||||
|
detect: False
|
||||||
|
detect_level: WARNING
|
||||||
|
rules_file:
|
||||||
|
- rules/exceptions/rule_exception_third_item.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
rule_exception_quoted:
|
||||||
|
detect: False
|
||||||
|
detect_level: WARNING
|
||||||
|
rules_file:
|
||||||
|
- rules/exceptions/rule_exception_quoted.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
rule_exception_append_values:
|
||||||
|
detect: False
|
||||||
|
detect_level: WARNING
|
||||||
|
rules_file:
|
||||||
|
- rules/exceptions/rule_exception_append.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
rule_exception_values_before:
|
||||||
|
detect: False
|
||||||
|
detect_level: WARNING
|
||||||
|
rules_file:
|
||||||
|
- rules/exceptions/rule_exception_values_before.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
rule_exception_comp:
|
||||||
|
detect: False
|
||||||
|
detect_level: WARNING
|
||||||
|
rules_file:
|
||||||
|
- rules/exceptions/rule_exception_comp.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
- rule: My Rule
|
||||||
|
desc: Some desc
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: Some output
|
||||||
|
exceptions:
|
||||||
|
- name: ex1
|
||||||
|
fields: [proc.name, fd.filename]
|
||||||
|
priority: error
|
||||||
|
|
||||||
|
- exception: My Rule
|
||||||
|
items:
|
||||||
|
- name: ex1
|
||||||
|
values:
|
||||||
|
- [nginx]
|
||||||
29
test/rules/exceptions/exception_item_no_name.yaml
Normal file
29
test/rules/exceptions/exception_item_no_name.yaml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
- rule: My Rule
|
||||||
|
desc: Some desc
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: Some output
|
||||||
|
exceptions:
|
||||||
|
- name: ex1
|
||||||
|
fields: [proc.name, fd.filename]
|
||||||
|
priority: error
|
||||||
|
|
||||||
|
- exception: My Rule
|
||||||
|
items:
|
||||||
|
- values:
|
||||||
|
- [nginx, /tmp/foo]
|
||||||
28
test/rules/exceptions/exception_item_no_values.yaml
Normal file
28
test/rules/exceptions/exception_item_no_values.yaml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
- rule: My Rule
|
||||||
|
desc: Some desc
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: Some output
|
||||||
|
exceptions:
|
||||||
|
- name: ex1
|
||||||
|
fields: [proc.name, fd.filename]
|
||||||
|
priority: error
|
||||||
|
|
||||||
|
- exception: My Rule
|
||||||
|
items:
|
||||||
|
- name: ex1
|
||||||
30
test/rules/exceptions/exception_item_not_in_rule.yaml
Normal file
30
test/rules/exceptions/exception_item_not_in_rule.yaml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
- rule: My Rule
|
||||||
|
desc: Some desc
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: Some output
|
||||||
|
exceptions:
|
||||||
|
- name: ex1
|
||||||
|
fields: [proc.name, fd.filename]
|
||||||
|
priority: error
|
||||||
|
|
||||||
|
- exception: My Rule
|
||||||
|
items:
|
||||||
|
- name: ex2
|
||||||
|
values:
|
||||||
|
- [apache, /tmp]
|
||||||
31
test/rules/exceptions/rule_append_exception.yaml
Normal file
31
test/rules/exceptions/rule_append_exception.yaml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
- rule: My Rule
|
||||||
|
desc: Some desc
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: Some output
|
||||||
|
exceptions:
|
||||||
|
- name: ex1
|
||||||
|
fields: [proc.name, fd.filename]
|
||||||
|
priority: error
|
||||||
|
|
||||||
|
- rule: My Rule
|
||||||
|
condition: and proc.name=apache
|
||||||
|
exceptions:
|
||||||
|
- name: ex2
|
||||||
|
fields: [proc.name, fd.filename]
|
||||||
|
append: true
|
||||||
40
test/rules/exceptions/rule_exception_append.yaml
Normal file
40
test/rules/exceptions/rule_exception_append.yaml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
- rule: Open From Cat
|
||||||
|
desc: A process named cat does an open
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: "An open was seen (command=%proc.cmdline)"
|
||||||
|
exceptions:
|
||||||
|
- name: proc_name
|
||||||
|
fields: [proc.name]
|
||||||
|
- name: proc_name_cmdline
|
||||||
|
fields: [proc.name, proc.cmdline]
|
||||||
|
- name: proc_name_cmdline_pname
|
||||||
|
fields: [proc.name, proc.cmdline, proc.pname]
|
||||||
|
priority: WARNING
|
||||||
|
|
||||||
|
- exception: Open From Cat
|
||||||
|
items:
|
||||||
|
- name: proc_name
|
||||||
|
values:
|
||||||
|
- [not-cat]
|
||||||
|
|
||||||
|
- exception: Open From Cat
|
||||||
|
items:
|
||||||
|
- name: proc_name
|
||||||
|
values:
|
||||||
|
- [cat]
|
||||||
37
test/rules/exceptions/rule_exception_comp.yaml
Normal file
37
test/rules/exceptions/rule_exception_comp.yaml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
- rule: Open From Cat
|
||||||
|
desc: A process named cat does an open
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: "An open was seen (command=%proc.cmdline)"
|
||||||
|
exceptions:
|
||||||
|
- name: proc_name
|
||||||
|
fields: [proc.name]
|
||||||
|
- name: proc_name_contains
|
||||||
|
fields: [proc.name]
|
||||||
|
comps: [contains]
|
||||||
|
- name: proc_name_cmdline
|
||||||
|
fields: [proc.name, proc.cmdline]
|
||||||
|
- name: proc_name_cmdline_pname
|
||||||
|
fields: [proc.name, proc.cmdline, proc.pname]
|
||||||
|
priority: WARNING
|
||||||
|
|
||||||
|
- exception: Open From Cat
|
||||||
|
items:
|
||||||
|
- name: proc_name_contains
|
||||||
|
values:
|
||||||
|
- [cat]
|
||||||
28
test/rules/exceptions/rule_exception_no_values.yaml
Normal file
28
test/rules/exceptions/rule_exception_no_values.yaml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
- rule: Open From Cat
|
||||||
|
desc: A process named cat does an open
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: "An open was seen (command=%proc.cmdline)"
|
||||||
|
exceptions:
|
||||||
|
- name: proc_name
|
||||||
|
fields: [proc.name]
|
||||||
|
- name: proc_name_cmdline
|
||||||
|
fields: [proc.name, proc.cmdline]
|
||||||
|
- name: proc_name_cmdline_pname
|
||||||
|
fields: [proc.name, proc.cmdline, proc.pname]
|
||||||
|
priority: WARNING
|
||||||
34
test/rules/exceptions/rule_exception_one_value.yaml
Normal file
34
test/rules/exceptions/rule_exception_one_value.yaml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
- rule: Open From Cat
|
||||||
|
desc: A process named cat does an open
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: "An open was seen (command=%proc.cmdline)"
|
||||||
|
exceptions:
|
||||||
|
- name: proc_name
|
||||||
|
fields: [proc.name]
|
||||||
|
- name: proc_name_cmdline
|
||||||
|
fields: [proc.name, proc.cmdline]
|
||||||
|
- name: proc_name_cmdline_pname
|
||||||
|
fields: [proc.name, proc.cmdline, proc.pname]
|
||||||
|
priority: WARNING
|
||||||
|
|
||||||
|
- exception: Open From Cat
|
||||||
|
items:
|
||||||
|
- name: proc_name
|
||||||
|
values:
|
||||||
|
- [cat]
|
||||||
35
test/rules/exceptions/rule_exception_quoted.yaml
Normal file
35
test/rules/exceptions/rule_exception_quoted.yaml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
- rule: Open From Cat
|
||||||
|
desc: A process named cat does an open
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: "An open was seen (command=%proc.cmdline)"
|
||||||
|
exceptions:
|
||||||
|
- name: proc_name
|
||||||
|
fields: [proc.name]
|
||||||
|
- name: proc_name_cmdline
|
||||||
|
fields: [proc.name, proc.cmdline]
|
||||||
|
- name: proc_name_cmdline_pname
|
||||||
|
fields: [proc.name, proc.cmdline, proc.pname]
|
||||||
|
priority: WARNING
|
||||||
|
|
||||||
|
- exception: Open From Cat
|
||||||
|
items:
|
||||||
|
- name: proc_name_cmdline
|
||||||
|
values:
|
||||||
|
- [not-cat, not-cat]
|
||||||
|
- [cat, '"cat /dev/null"']
|
||||||
40
test/rules/exceptions/rule_exception_second_item.yaml
Normal file
40
test/rules/exceptions/rule_exception_second_item.yaml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
- rule: Open From Cat
|
||||||
|
desc: A process named cat does an open
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: "An open was seen (command=%proc.cmdline)"
|
||||||
|
exceptions:
|
||||||
|
- name: proc_name
|
||||||
|
fields: [proc.name]
|
||||||
|
- name: proc_name_cmdline
|
||||||
|
fields: [proc.name, proc.cmdline]
|
||||||
|
- name: proc_name_cmdline_pname
|
||||||
|
fields: [proc.name, proc.cmdline, proc.pname]
|
||||||
|
priority: WARNING
|
||||||
|
|
||||||
|
- exception: Open From Cat
|
||||||
|
items:
|
||||||
|
- name: proc_name
|
||||||
|
values:
|
||||||
|
- [not-cat]
|
||||||
|
- name: proc_name_cmdline
|
||||||
|
values:
|
||||||
|
- [cat, "cat /dev/null"]
|
||||||
|
- name: proc_name_cmdline_pname
|
||||||
|
values:
|
||||||
|
- [not-cat, "cat /dev/null", bash]
|
||||||
35
test/rules/exceptions/rule_exception_second_value.yaml
Normal file
35
test/rules/exceptions/rule_exception_second_value.yaml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
- rule: Open From Cat
|
||||||
|
desc: A process named cat does an open
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: "An open was seen (command=%proc.cmdline)"
|
||||||
|
exceptions:
|
||||||
|
- name: proc_name
|
||||||
|
fields: [proc.name]
|
||||||
|
- name: proc_name_cmdline
|
||||||
|
fields: [proc.name, proc.cmdline]
|
||||||
|
- name: proc_name_cmdline_pname
|
||||||
|
fields: [proc.name, proc.cmdline, proc.pname]
|
||||||
|
priority: WARNING
|
||||||
|
|
||||||
|
- exception: Open From Cat
|
||||||
|
items:
|
||||||
|
- name: proc_name_cmdline
|
||||||
|
values:
|
||||||
|
- [not-cat, not-cat]
|
||||||
|
- [cat, "cat /dev/null"]
|
||||||
40
test/rules/exceptions/rule_exception_third_item.yaml
Normal file
40
test/rules/exceptions/rule_exception_third_item.yaml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
- rule: Open From Cat
|
||||||
|
desc: A process named cat does an open
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: "An open was seen (command=%proc.cmdline)"
|
||||||
|
exceptions:
|
||||||
|
- name: proc_name
|
||||||
|
fields: [proc.name]
|
||||||
|
- name: proc_name_cmdline
|
||||||
|
fields: [proc.name, proc.cmdline]
|
||||||
|
- name: proc_name_cmdline_pname
|
||||||
|
fields: [proc.name, proc.cmdline, proc.pname]
|
||||||
|
priority: WARNING
|
||||||
|
|
||||||
|
- exception: Open From Cat
|
||||||
|
items:
|
||||||
|
- name: proc_name
|
||||||
|
values:
|
||||||
|
- [not-cat]
|
||||||
|
- name: proc_name_cmdline
|
||||||
|
values:
|
||||||
|
- [not-cat, "cat /dev/null"]
|
||||||
|
- name: proc_name_cmdline_pname
|
||||||
|
values:
|
||||||
|
- [cat, "cat /dev/null", bash]
|
||||||
36
test/rules/exceptions/rule_exception_values_before.yaml
Normal file
36
test/rules/exceptions/rule_exception_values_before.yaml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
- exception: Open From Cat
|
||||||
|
items:
|
||||||
|
- name: proc_name
|
||||||
|
values:
|
||||||
|
- [cat]
|
||||||
|
|
||||||
|
- rule: Open From Cat
|
||||||
|
desc: A process named cat does an open
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: "An open was seen (command=%proc.cmdline)"
|
||||||
|
exceptions:
|
||||||
|
- name: proc_name
|
||||||
|
fields: [proc.name]
|
||||||
|
- name: proc_name_cmdline
|
||||||
|
fields: [proc.name, proc.cmdline]
|
||||||
|
- name: proc_name_cmdline_pname
|
||||||
|
fields: [proc.name, proc.cmdline, proc.pname]
|
||||||
|
priority: WARNING
|
||||||
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
- rule: My Rule
|
||||||
|
desc: Some desc
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: Some output
|
||||||
|
exceptions:
|
||||||
|
- name: ex1
|
||||||
|
fields: [proc.name, fd.filename]
|
||||||
|
comps: [=]
|
||||||
|
priority: error
|
||||||
23
test/rules/exceptions/rule_item_no_fields.yaml
Normal file
23
test/rules/exceptions/rule_item_no_fields.yaml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
- rule: My Rule
|
||||||
|
desc: Some desc
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: Some output
|
||||||
|
exceptions:
|
||||||
|
- name: ex1
|
||||||
|
priority: error
|
||||||
23
test/rules/exceptions/rule_item_no_name.yaml
Normal file
23
test/rules/exceptions/rule_item_no_name.yaml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
- rule: My Rule
|
||||||
|
desc: Some desc
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: Some output
|
||||||
|
exceptions:
|
||||||
|
- fields: [proc.name, fd.filename]
|
||||||
|
priority: error
|
||||||
25
test/rules/exceptions/rule_item_unknown_comp.yaml
Normal file
25
test/rules/exceptions/rule_item_unknown_comp.yaml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
- rule: My Rule
|
||||||
|
desc: Some desc
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: Some output
|
||||||
|
exceptions:
|
||||||
|
- name: ex1
|
||||||
|
fields: [proc.name, fd.filename]
|
||||||
|
comps: [=, no-comp]
|
||||||
|
priority: error
|
||||||
24
test/rules/exceptions/rule_item_unknown_fields.yaml
Normal file
24
test/rules/exceptions/rule_item_unknown_fields.yaml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
- rule: My Rule
|
||||||
|
desc: Some desc
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: Some output
|
||||||
|
exceptions:
|
||||||
|
- name: ex1
|
||||||
|
fields: [not.exist]
|
||||||
|
priority: error
|
||||||
21
test/rules/exceptions/rule_without_exception.yaml
Normal file
21
test/rules/exceptions/rule_without_exception.yaml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2020 The Falco Authors.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
- rule: My Rule
|
||||||
|
desc: Some desc
|
||||||
|
condition: evt.type=open and proc.name=cat
|
||||||
|
output: Some output
|
||||||
|
priority: error
|
||||||
@@ -98,7 +98,7 @@ function run_tests() {
|
|||||||
# as we're watching the return status when running avocado.
|
# as we're watching the return status when running avocado.
|
||||||
set +e
|
set +e
|
||||||
TEST_RC=0
|
TEST_RC=0
|
||||||
suites=($SCRIPTDIR/falco_traces.yaml $SCRIPTDIR/falco_tests.yaml $SCRIPTDIR/falco_k8s_audit_tests.yaml $SCRIPTDIR/falco_tests_psp.yaml)
|
suites=($SCRIPTDIR/falco_traces.yaml $SCRIPTDIR/falco_tests.yaml $SCRIPTDIR/falco_k8s_audit_tests.yaml $SCRIPTDIR/falco_tests_psp.yaml $SCRIPTDIR/falco_tests_exceptions.yaml)
|
||||||
|
|
||||||
if [ "$SKIP_PACKAGES_TESTS" = false ] ; then
|
if [ "$SKIP_PACKAGES_TESTS" = false ] ; then
|
||||||
suites+=($SCRIPTDIR/falco_tests_package.yaml)
|
suites+=($SCRIPTDIR/falco_tests_package.yaml)
|
||||||
|
|||||||
@@ -126,11 +126,31 @@ function set_output(output_format, state)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- This should be keep in sync with parser.lua
|
||||||
|
defined_comp_operators = {
|
||||||
|
["="]=1,
|
||||||
|
["=="] = 1,
|
||||||
|
["!"] = 1,
|
||||||
|
["<="] = 1,
|
||||||
|
[">="] = 1,
|
||||||
|
["<"] = 1,
|
||||||
|
[">"] = 1,
|
||||||
|
["contains"] = 1,
|
||||||
|
["icontains"] = 1,
|
||||||
|
["glob"] = 1,
|
||||||
|
["startswith"] = 1,
|
||||||
|
["endswith"] = 1,
|
||||||
|
["in"] = 1,
|
||||||
|
["intersects"] = 1,
|
||||||
|
["pmatch"] = 1
|
||||||
|
}
|
||||||
|
|
||||||
-- Note that the rules_by_name and rules_by_idx refer to the same rule
|
-- Note that the rules_by_name and rules_by_idx refer to the same rule
|
||||||
-- object. The by_name index is used for things like describing rules,
|
-- object. The by_name index is used for things like describing rules,
|
||||||
-- and the by_idx index is used to map the relational node index back
|
-- and the by_idx index is used to map the relational node index back
|
||||||
-- to a rule.
|
-- to a rule.
|
||||||
local state = {macros={}, lists={}, filter_ast=nil, rules_by_name={},
|
local state = {macros={}, lists={}, filter_ast=nil, rules_by_name={},
|
||||||
|
exceptions_by_name={},
|
||||||
skipped_rules_by_name={}, macros_by_name={}, lists_by_name={},
|
skipped_rules_by_name={}, macros_by_name={}, lists_by_name={},
|
||||||
n_rules=0, rules_by_idx={}, ordered_rule_names={}, ordered_macro_names={}, ordered_list_names={}}
|
n_rules=0, rules_by_idx={}, ordered_rule_names={}, ordered_macro_names={}, ordered_list_names={}}
|
||||||
|
|
||||||
@@ -256,16 +276,18 @@ end
|
|||||||
function build_error(rules_lines, row, num_lines, err)
|
function build_error(rules_lines, row, num_lines, err)
|
||||||
local ret = err.."\n---\n"..get_lines(rules_lines, row, num_lines).."---"
|
local ret = err.."\n---\n"..get_lines(rules_lines, row, num_lines).."---"
|
||||||
|
|
||||||
return ret
|
return {ret}
|
||||||
end
|
end
|
||||||
|
|
||||||
function build_error_with_context(ctx, err)
|
function build_error_with_context(ctx, err)
|
||||||
local ret = err.."\n---\n"..ctx.."---"
|
local ret = err.."\n---\n"..ctx.."---"
|
||||||
return ret
|
return {ret}
|
||||||
end
|
end
|
||||||
|
|
||||||
function load_rules_doc(rules_mgr, doc, load_state)
|
function load_rules_doc(rules_mgr, doc, load_state)
|
||||||
|
|
||||||
|
local warnings = {}
|
||||||
|
|
||||||
-- Iterate over yaml list. In this pass, all we're doing is
|
-- Iterate over yaml list. In this pass, all we're doing is
|
||||||
-- populating the set of rules, macros, and lists. We're not
|
-- populating the set of rules, macros, and lists. We're not
|
||||||
-- expanding/compiling anything yet. All that will happen in a
|
-- expanding/compiling anything yet. All that will happen in a
|
||||||
@@ -279,7 +301,7 @@ function load_rules_doc(rules_mgr, doc, load_state)
|
|||||||
load_state.indices[load_state.cur_item_idx])
|
load_state.indices[load_state.cur_item_idx])
|
||||||
|
|
||||||
if (not (type(v) == "table")) then
|
if (not (type(v) == "table")) then
|
||||||
return false, build_error_with_context(context, "Unexpected element of type " ..type(v)..". Each element should be a yaml associative array.")
|
return false, build_error_with_context(context, "Unexpected element of type " ..type(v)..". Each element should be a yaml associative array."), warnings
|
||||||
end
|
end
|
||||||
|
|
||||||
v['context'] = context
|
v['context'] = context
|
||||||
@@ -291,13 +313,13 @@ function load_rules_doc(rules_mgr, doc, load_state)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if falco_rules.engine_version(rules_mgr) < v['required_engine_version'] then
|
if falco_rules.engine_version(rules_mgr) < v['required_engine_version'] then
|
||||||
return false, build_error_with_context(v['context'], "Rules require engine version "..v['required_engine_version']..", but engine version is "..falco_rules.engine_version(rules_mgr))
|
return false, build_error_with_context(v['context'], "Rules require engine version "..v['required_engine_version']..", but engine version is "..falco_rules.engine_version(rules_mgr)), warnings
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif (v['macro']) then
|
elseif (v['macro']) then
|
||||||
|
|
||||||
if (v['macro'] == nil or type(v['macro']) == "table") then
|
if (v['macro'] == nil or type(v['macro']) == "table") then
|
||||||
return false, build_error_with_context(v['context'], "Macro name is empty")
|
return false, build_error_with_context(v['context'], "Macro name is empty"), warnings
|
||||||
end
|
end
|
||||||
|
|
||||||
if v['source'] == nil then
|
if v['source'] == nil then
|
||||||
@@ -310,7 +332,7 @@ function load_rules_doc(rules_mgr, doc, load_state)
|
|||||||
|
|
||||||
for j, field in ipairs({'condition'}) do
|
for j, field in ipairs({'condition'}) do
|
||||||
if (v[field] == nil) then
|
if (v[field] == nil) then
|
||||||
return false, build_error_with_context(v['context'], "Macro must have property "..field)
|
return false, build_error_with_context(v['context'], "Macro must have property "..field), warnings
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -323,7 +345,7 @@ function load_rules_doc(rules_mgr, doc, load_state)
|
|||||||
|
|
||||||
if append then
|
if append then
|
||||||
if state.macros_by_name[v['macro']] == nil then
|
if state.macros_by_name[v['macro']] == nil then
|
||||||
return false, build_error_with_context(v['context'], "Macro " ..v['macro'].. " has 'append' key but no macro by that name already exists")
|
return false, build_error_with_context(v['context'], "Macro " ..v['macro'].. " has 'append' key but no macro by that name already exists"), warnings
|
||||||
end
|
end
|
||||||
|
|
||||||
state.macros_by_name[v['macro']]['condition'] = state.macros_by_name[v['macro']]['condition'] .. " " .. v['condition']
|
state.macros_by_name[v['macro']]['condition'] = state.macros_by_name[v['macro']]['condition'] .. " " .. v['condition']
|
||||||
@@ -338,7 +360,7 @@ function load_rules_doc(rules_mgr, doc, load_state)
|
|||||||
elseif (v['list']) then
|
elseif (v['list']) then
|
||||||
|
|
||||||
if (v['list'] == nil or type(v['list']) == "table") then
|
if (v['list'] == nil or type(v['list']) == "table") then
|
||||||
return false, build_error_with_context(v['context'], "List name is empty")
|
return false, build_error_with_context(v['context'], "List name is empty"), warnings
|
||||||
end
|
end
|
||||||
|
|
||||||
if state.lists_by_name[v['list']] == nil then
|
if state.lists_by_name[v['list']] == nil then
|
||||||
@@ -347,7 +369,7 @@ function load_rules_doc(rules_mgr, doc, load_state)
|
|||||||
|
|
||||||
for j, field in ipairs({'items'}) do
|
for j, field in ipairs({'items'}) do
|
||||||
if (v[field] == nil) then
|
if (v[field] == nil) then
|
||||||
return false, build_error_with_context(v['context'], "List must have property "..field)
|
return false, build_error_with_context(v['context'], "List must have property "..field), warnings
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -360,7 +382,7 @@ function load_rules_doc(rules_mgr, doc, load_state)
|
|||||||
|
|
||||||
if append then
|
if append then
|
||||||
if state.lists_by_name[v['list']] == nil then
|
if state.lists_by_name[v['list']] == nil then
|
||||||
return false, build_error_with_context(v['context'], "List " ..v['list'].. " has 'append' key but no list by that name already exists")
|
return false, build_error_with_context(v['context'], "List " ..v['list'].. " has 'append' key but no list by that name already exists"), warnings
|
||||||
end
|
end
|
||||||
|
|
||||||
for j, elem in ipairs(v['items']) do
|
for j, elem in ipairs(v['items']) do
|
||||||
@@ -373,7 +395,7 @@ function load_rules_doc(rules_mgr, doc, load_state)
|
|||||||
elseif (v['rule']) then
|
elseif (v['rule']) then
|
||||||
|
|
||||||
if (v['rule'] == nil or type(v['rule']) == "table") then
|
if (v['rule'] == nil or type(v['rule']) == "table") then
|
||||||
return false, build_error_with_context(v['context'], "Rule name is empty")
|
return false, build_error_with_context(v['context'], "Rule name is empty"), warnings
|
||||||
end
|
end
|
||||||
|
|
||||||
-- By default, if a rule's condition refers to an unknown
|
-- By default, if a rule's condition refers to an unknown
|
||||||
@@ -386,6 +408,53 @@ function load_rules_doc(rules_mgr, doc, load_state)
|
|||||||
v['source'] = "syscall"
|
v['source'] = "syscall"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Add an empty exceptions property to the rule if not
|
||||||
|
-- defined, but add a warning about defining one
|
||||||
|
if v['exceptions'] == nil then
|
||||||
|
warnings[#warnings + 1] = "Rule "..v['rule']..": consider adding an exceptions property to define supported exceptions fields"
|
||||||
|
v['exceptions'] = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Validate the contents of the rule exception
|
||||||
|
if next(v['exceptions']) ~= nil then
|
||||||
|
|
||||||
|
for i, eitem in ipairs(v['exceptions']) do
|
||||||
|
local name = eitem['name']
|
||||||
|
local fields = eitem['fields']
|
||||||
|
local comps = eitem['comps']
|
||||||
|
|
||||||
|
if name == nil then
|
||||||
|
return false, build_error_with_context(v['context'], "Rule exception item must have name property"), warnings
|
||||||
|
end
|
||||||
|
|
||||||
|
if fields == nil then
|
||||||
|
return false, build_error_with_context(v['context'], "Rule exception item "..name..": must have fields property with a list of fields"), warnings
|
||||||
|
end
|
||||||
|
|
||||||
|
if comps == nil then
|
||||||
|
comps = {}
|
||||||
|
for c=1,#fields do
|
||||||
|
table.insert(comps, "=")
|
||||||
|
end
|
||||||
|
eitem['comps'] = comps
|
||||||
|
else
|
||||||
|
if #fields ~= #comps then
|
||||||
|
return false, build_error_with_context(v['context'], "Rule exception item "..name..": fields and comps lists must have equal length"), warnings
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for j, fname in ipairs(fields) do
|
||||||
|
if defined_noarg_filters[fname] == nil then
|
||||||
|
return false, build_error_with_context(v['context'], "Rule exception item "..name..": field name "..fname.." is not a supported filter field"), warnings
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for j, comp in ipairs(comps) do
|
||||||
|
if defined_comp_operators[comp] == nil then
|
||||||
|
return false, build_error_with_context(v['context'], "Rule exception item "..name..": comparison operator "..comp.." is not a supported comparison operator"), warnings
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Possibly append to the condition field of an existing rule
|
-- Possibly append to the condition field of an existing rule
|
||||||
append = false
|
append = false
|
||||||
|
|
||||||
@@ -398,15 +467,21 @@ function load_rules_doc(rules_mgr, doc, load_state)
|
|||||||
-- For append rules, all you need is the condition
|
-- For append rules, all you need is the condition
|
||||||
for j, field in ipairs({'condition'}) do
|
for j, field in ipairs({'condition'}) do
|
||||||
if (v[field] == nil) then
|
if (v[field] == nil) then
|
||||||
return false, build_error_with_context(v['context'], "Rule must have property "..field)
|
return false, build_error_with_context(v['context'], "Rule must have property "..field), warnings
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if state.rules_by_name[v['rule']] == nil then
|
if state.rules_by_name[v['rule']] == nil then
|
||||||
if state.skipped_rules_by_name[v['rule']] == nil then
|
if state.skipped_rules_by_name[v['rule']] == nil then
|
||||||
return false, build_error_with_context(v['context'], "Rule " ..v['rule'].. " has 'append' key but no rule by that name already exists")
|
return false, build_error_with_context(v['context'], "Rule " ..v['rule'].. " has 'append' key but no rule by that name already exists"), warnings
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
|
||||||
|
-- You can't append exceptions to a rule
|
||||||
|
if v['exceptions'] ~= nil then
|
||||||
|
return false, build_error_with_context(v['context'], "Can not append exceptions to existing rule, only conditions"), warnings
|
||||||
|
end
|
||||||
|
|
||||||
state.rules_by_name[v['rule']]['condition'] = state.rules_by_name[v['rule']]['condition'] .. " " .. v['condition']
|
state.rules_by_name[v['rule']]['condition'] = state.rules_by_name[v['rule']]['condition'] .. " " .. v['condition']
|
||||||
|
|
||||||
-- Add the current object to the context of the base rule
|
-- Add the current object to the context of the base rule
|
||||||
@@ -417,7 +492,7 @@ function load_rules_doc(rules_mgr, doc, load_state)
|
|||||||
|
|
||||||
for j, field in ipairs({'condition', 'output', 'desc', 'priority'}) do
|
for j, field in ipairs({'condition', 'output', 'desc', 'priority'}) do
|
||||||
if (v[field] == nil) then
|
if (v[field] == nil) then
|
||||||
return false, build_error_with_context(v['context'], "Rule must have property "..field)
|
return false, build_error_with_context(v['context'], "Rule must have property "..field), warnings
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -445,17 +520,77 @@ function load_rules_doc(rules_mgr, doc, load_state)
|
|||||||
state.skipped_rules_by_name[v['rule']] = v
|
state.skipped_rules_by_name[v['rule']] = v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
elseif (v['exception']) then
|
||||||
|
|
||||||
|
for i, eitem in ipairs(v['items']) do
|
||||||
|
local name = eitem['name']
|
||||||
|
local fields = eitem['values']
|
||||||
|
|
||||||
|
if name == nil then
|
||||||
|
return false, build_error_with_context(v['context'], "Exception item must have name property"), warnings
|
||||||
|
end
|
||||||
|
|
||||||
|
if fields == nil then
|
||||||
|
return false, build_error_with_context(v['context'], "Exception item "..name..": must have values property with a list of values"), warnings
|
||||||
|
end
|
||||||
|
end
|
||||||
|
state.exceptions_by_name[v['exception']] = v
|
||||||
else
|
else
|
||||||
-- Remove the context from the table, so the table is exactly what was parsed
|
|
||||||
local context = v['context']
|
local context = v['context']
|
||||||
v['context'] = nil
|
|
||||||
return false, build_error_with_context(context, "Unknown rule object: "..table.tostring(v))
|
arr = build_error_with_context(context, "Unknown top level object: "..table.tostring(v))
|
||||||
|
warnings[#warnings + 1] = arr[1]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return true, ""
|
return true, {}, warnings
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- cond and not ((proc.name=apk and fd.directory=/usr/lib/alpine) or (proc.name=npm and fd.directory=/usr/node/bin) or (con
|
||||||
|
function build_exception_condition_string(eitem, rexitems)
|
||||||
|
|
||||||
|
local fields = rexitems[eitem['name']]['fields']
|
||||||
|
local comps = rexitems[eitem['name']]['comps']
|
||||||
|
|
||||||
|
local icond = ""
|
||||||
|
|
||||||
|
for i, values in ipairs(eitem['values']) do
|
||||||
|
|
||||||
|
if #fields ~= #values then
|
||||||
|
return nil, "Exception item "..eitem['name']..": fields and values lists must have equal length"
|
||||||
|
end
|
||||||
|
|
||||||
|
if icond ~= "" then
|
||||||
|
icond=icond.." or "
|
||||||
|
end
|
||||||
|
|
||||||
|
icond=icond.."("
|
||||||
|
|
||||||
|
for k=1,#fields do
|
||||||
|
if k > 1 then
|
||||||
|
icond=icond.." and "
|
||||||
|
end
|
||||||
|
-- Quote the value if not already quoted
|
||||||
|
local ival = values[k]
|
||||||
|
if string.sub(values[k], 1, 1) ~= "'" and string.sub(values[k], 1, 1) ~= '"' then
|
||||||
|
ival = "\""..ival.."\""
|
||||||
|
end
|
||||||
|
|
||||||
|
icond = icond..fields[k].." "..comps[k]..ival
|
||||||
|
end
|
||||||
|
|
||||||
|
icond=icond..")"
|
||||||
|
end
|
||||||
|
|
||||||
|
return icond, nil
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns:
|
||||||
|
-- - Load Result: bool
|
||||||
|
-- - required engine version. will be nil when load result is false
|
||||||
|
-- - List of Errors
|
||||||
|
-- - List of Warnings
|
||||||
function load_rules(sinsp_lua_parser,
|
function load_rules(sinsp_lua_parser,
|
||||||
json_lua_parser,
|
json_lua_parser,
|
||||||
rules_content,
|
rules_content,
|
||||||
@@ -466,6 +601,8 @@ function load_rules(sinsp_lua_parser,
|
|||||||
replace_container_info,
|
replace_container_info,
|
||||||
min_priority)
|
min_priority)
|
||||||
|
|
||||||
|
local warnings = {}
|
||||||
|
|
||||||
local load_state = {lines={}, indices={}, cur_item_idx=0, min_priority=min_priority, required_engine_version=0}
|
local load_state = {lines={}, indices={}, cur_item_idx=0, min_priority=min_priority, required_engine_version=0}
|
||||||
|
|
||||||
load_state.lines, load_state.indices = split_lines(rules_content)
|
load_state.lines, load_state.indices = split_lines(rules_content)
|
||||||
@@ -487,36 +624,42 @@ function load_rules(sinsp_lua_parser,
|
|||||||
row = tonumber(row)
|
row = tonumber(row)
|
||||||
col = tonumber(col)
|
col = tonumber(col)
|
||||||
|
|
||||||
return false, build_error(load_state.lines, row, 3, docs)
|
return false, nil, build_error(load_state.lines, row, 3, docs), warnings
|
||||||
end
|
end
|
||||||
|
|
||||||
if docs == nil then
|
if docs == nil then
|
||||||
-- An empty rules file is acceptable
|
-- An empty rules file is acceptable
|
||||||
return true, load_state.required_engine_version
|
return true, load_state.required_engine_version, {}, warnings
|
||||||
end
|
end
|
||||||
|
|
||||||
if type(docs) ~= "table" then
|
if type(docs) ~= "table" then
|
||||||
return false, build_error(load_state.lines, 1, 1, "Rules content is not yaml")
|
return false, nil, build_error(load_state.lines, 1, 1, "Rules content is not yaml"), warnings
|
||||||
end
|
end
|
||||||
|
|
||||||
for docidx, doc in ipairs(docs) do
|
for docidx, doc in ipairs(docs) do
|
||||||
|
|
||||||
if type(doc) ~= "table" then
|
if type(doc) ~= "table" then
|
||||||
return false, build_error(load_state.lines, 1, 1, "Rules content is not yaml")
|
return false, nil, build_error(load_state.lines, 1, 1, "Rules content is not yaml"), warnings
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Look for non-numeric indices--implies that document is not array
|
-- Look for non-numeric indices--implies that document is not array
|
||||||
-- of objects.
|
-- of objects.
|
||||||
for key, val in pairs(doc) do
|
for key, val in pairs(doc) do
|
||||||
if type(key) ~= "number" then
|
if type(key) ~= "number" then
|
||||||
return false, build_error(load_state.lines, 1, 1, "Rules content is not yaml array of objects")
|
return false, nil, build_error(load_state.lines, 1, 1, "Rules content is not yaml array of objects"), warnings
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
res, errstr = load_rules_doc(rules_mgr, doc, load_state)
|
res, errors, doc_warnings = load_rules_doc(rules_mgr, doc, load_state)
|
||||||
|
|
||||||
|
if (doc_warnings ~= nil) then
|
||||||
|
for idx, warning in pairs(doc_warnings) do
|
||||||
|
table.insert(warnings, warning)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if not res then
|
if not res then
|
||||||
return res, errstr
|
return res, nil, errors, warnings
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -526,6 +669,52 @@ function load_rules(sinsp_lua_parser,
|
|||||||
-- in which they appeared in the file(s).
|
-- in which they appeared in the file(s).
|
||||||
reset_rules(rules_mgr)
|
reset_rules(rules_mgr)
|
||||||
|
|
||||||
|
-- Turn exceptions into condition strings and add them to each
|
||||||
|
-- rule's condition
|
||||||
|
for ename, exc in pairs(state.exceptions_by_name) do
|
||||||
|
|
||||||
|
if state.rules_by_name[ename] == nil then
|
||||||
|
warnings[#warnings + 1] = "No rule matching exception name "..exc['exception']
|
||||||
|
else
|
||||||
|
|
||||||
|
local rexitems = {}
|
||||||
|
|
||||||
|
-- Create a map from item name to object, speeds up matching
|
||||||
|
for i, iobj in ipairs(state.rules_by_name[ename].exceptions) do
|
||||||
|
rexitems[iobj['name']] = iobj
|
||||||
|
end
|
||||||
|
-- Usep the exception items, combined with any exceptions in
|
||||||
|
-- the rules, to build condition strings to append to the
|
||||||
|
-- rule's condition.
|
||||||
|
local econd = ""
|
||||||
|
|
||||||
|
for i, eitem in ipairs(exc['items']) do
|
||||||
|
|
||||||
|
if rexitems[eitem['name']] == nil then
|
||||||
|
warnings[#warnings + 1] = "Exception "..ename..": no set of fields matching name "..eitem['name']
|
||||||
|
else
|
||||||
|
icond, err = build_exception_condition_string(eitem, rexitems)
|
||||||
|
|
||||||
|
if err ~= nil then
|
||||||
|
return false, nil, build_error_with_context(exc['context'], err), warnings
|
||||||
|
end
|
||||||
|
|
||||||
|
if econd == "" then
|
||||||
|
econd = econd.." and not ("..icond
|
||||||
|
else
|
||||||
|
econd = econd.." or "..icond
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if econd ~= "" then
|
||||||
|
econd=econd..")"
|
||||||
|
|
||||||
|
state.rules_by_name[ename]['condition'] = "("..state.rules_by_name[ename]['condition']..") "..econd
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
for i, name in ipairs(state.ordered_list_names) do
|
for i, name in ipairs(state.ordered_list_names) do
|
||||||
|
|
||||||
local v = state.lists_by_name[name]
|
local v = state.lists_by_name[name]
|
||||||
@@ -556,7 +745,7 @@ function load_rules(sinsp_lua_parser,
|
|||||||
local status, ast = compiler.compile_macro(v['condition'], state.macros, state.lists)
|
local status, ast = compiler.compile_macro(v['condition'], state.macros, state.lists)
|
||||||
|
|
||||||
if status == false then
|
if status == false then
|
||||||
return false, build_error_with_context(v['context'], ast)
|
return false, nil, build_error_with_context(v['context'], ast), warnings
|
||||||
end
|
end
|
||||||
|
|
||||||
if v['source'] == "syscall" then
|
if v['source'] == "syscall" then
|
||||||
@@ -581,7 +770,7 @@ function load_rules(sinsp_lua_parser,
|
|||||||
state.macros, state.lists)
|
state.macros, state.lists)
|
||||||
|
|
||||||
if status == false then
|
if status == false then
|
||||||
return false, build_error_with_context(v['context'], filter_ast)
|
return false, nil, build_error_with_context(v['context'], filter_ast), warnings
|
||||||
end
|
end
|
||||||
|
|
||||||
local evtttypes = {}
|
local evtttypes = {}
|
||||||
@@ -631,12 +820,10 @@ function load_rules(sinsp_lua_parser,
|
|||||||
end
|
end
|
||||||
|
|
||||||
if not found then
|
if not found then
|
||||||
if v['skip-if-unknown-filter'] then
|
msg = "rule \""..v['rule'].."\" contains unknown filter "..filter
|
||||||
if verbose then
|
warnings[#warnings + 1] = msg
|
||||||
print("Skipping rule \""..v['rule'].."\" that contains unknown filter "..filter)
|
|
||||||
end
|
if not v['skip-if-unknown-filter'] then
|
||||||
goto next_rule
|
|
||||||
else
|
|
||||||
error("Rule \""..v['rule'].."\" contains unknown filter "..filter)
|
error("Rule \""..v['rule'].."\" contains unknown filter "..filter)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -719,30 +906,30 @@ function load_rules(sinsp_lua_parser,
|
|||||||
formatter = formats.formatter(v['source'], v['output'])
|
formatter = formats.formatter(v['source'], v['output'])
|
||||||
formats.free_formatter(v['source'], formatter)
|
formats.free_formatter(v['source'], formatter)
|
||||||
else
|
else
|
||||||
return false, build_error_with_context(v['context'], "Unexpected type in load_rule: "..filter_ast.type)
|
return false, nil, build_error_with_context(v['context'], "Unexpected type in load_rule: "..filter_ast.type), warnings
|
||||||
end
|
end
|
||||||
|
|
||||||
::next_rule::
|
::next_rule::
|
||||||
end
|
end
|
||||||
|
|
||||||
if verbose then
|
-- Print info on any dangling lists or macros that were not used anywhere
|
||||||
-- Print info on any dangling lists or macros that were not used anywhere
|
for name, macro in pairs(state.macros) do
|
||||||
for name, macro in pairs(state.macros) do
|
if macro.used == false then
|
||||||
if macro.used == false then
|
msg = "macro "..name.." not refered to by any rule/macro"
|
||||||
print("Warning: macro "..name.." not refered to by any rule/macro")
|
warnings[#warnings + 1] = msg
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
for name, list in pairs(state.lists) do
|
for name, list in pairs(state.lists) do
|
||||||
if list.used == false then
|
if list.used == false then
|
||||||
print("Warning: list "..name.." not refered to by any rule/macro/list")
|
msg = "list "..name.." not refered to by any rule/macro/list"
|
||||||
end
|
warnings[#warnings + 1] = msg
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
io.flush()
|
io.flush()
|
||||||
|
|
||||||
return true, load_state.required_engine_version
|
return true, load_state.required_engine_version, {}, warnings
|
||||||
end
|
end
|
||||||
|
|
||||||
local rule_fmt = "%-50s %s"
|
local rule_fmt = "%-50s %s"
|
||||||
|
|||||||
@@ -14,8 +14,9 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "rules.h"
|
#include "rules.h"
|
||||||
#include "logger.h"
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
@@ -219,6 +220,31 @@ int falco_rules::engine_version(lua_State *ls)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::list<std::string> get_lua_table_values(lua_State *ls, int idx)
|
||||||
|
{
|
||||||
|
std::list<std::string> ret;
|
||||||
|
|
||||||
|
if (lua_isnil(ls, idx)) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushnil(ls); /* first key */
|
||||||
|
while (lua_next(ls, idx-1) != 0) {
|
||||||
|
// key is at index -2, value is at index
|
||||||
|
// -1. We want the values.
|
||||||
|
if (! lua_isstring(ls, -1)) {
|
||||||
|
std::string err = "Non-string value in table of strings";
|
||||||
|
throw falco_exception(err);
|
||||||
|
}
|
||||||
|
ret.push_back(string(lua_tostring(ls, -1)));
|
||||||
|
|
||||||
|
// Remove value, keep key for next iteration
|
||||||
|
lua_pop(ls, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void falco_rules::load_rules(const string &rules_content,
|
void falco_rules::load_rules(const string &rules_content,
|
||||||
bool verbose, bool all_events,
|
bool verbose, bool all_events,
|
||||||
string &extra, bool replace_container_info,
|
string &extra, bool replace_container_info,
|
||||||
@@ -424,7 +450,7 @@ void falco_rules::load_rules(const string &rules_content,
|
|||||||
lua_pushstring(m_ls, extra.c_str());
|
lua_pushstring(m_ls, extra.c_str());
|
||||||
lua_pushboolean(m_ls, (replace_container_info ? 1 : 0));
|
lua_pushboolean(m_ls, (replace_container_info ? 1 : 0));
|
||||||
lua_pushnumber(m_ls, min_priority);
|
lua_pushnumber(m_ls, min_priority);
|
||||||
if(lua_pcall(m_ls, 9, 2, 0) != 0)
|
if(lua_pcall(m_ls, 9, 4, 0) != 0)
|
||||||
{
|
{
|
||||||
const char* lerr = lua_tostring(m_ls, -1);
|
const char* lerr = lua_tostring(m_ls, -1);
|
||||||
|
|
||||||
@@ -433,20 +459,49 @@ void falco_rules::load_rules(const string &rules_content,
|
|||||||
throw falco_exception(err);
|
throw falco_exception(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Either returns (true, required_engine_version), or (false, error string)
|
// Returns:
|
||||||
bool successful = lua_toboolean(m_ls, -2);
|
// Load result: bool
|
||||||
|
// required engine version: will be nil when load result is false
|
||||||
|
// array of errors
|
||||||
|
// array of warnings
|
||||||
|
bool successful = lua_toboolean(m_ls, -4);
|
||||||
|
required_engine_version = lua_tonumber(m_ls, -3);
|
||||||
|
std::list<std::string> errors = get_lua_table_values(m_ls, -2);
|
||||||
|
std::list<std::string> warnings = get_lua_table_values(m_ls, -1);
|
||||||
|
|
||||||
if(successful)
|
// Concatenate errors/warnings
|
||||||
|
std::ostringstream os;
|
||||||
|
if (errors.size() > 0)
|
||||||
{
|
{
|
||||||
required_engine_version = lua_tonumber(m_ls, -1);
|
os << errors.size() << " errors:" << std::endl;
|
||||||
}
|
for(auto err : errors)
|
||||||
else
|
{
|
||||||
{
|
os << err << std::endl;
|
||||||
std::string err = lua_tostring(m_ls, -1);
|
}
|
||||||
throw falco_exception(err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_pop(m_ls, 2);
|
if (warnings.size() > 0)
|
||||||
|
{
|
||||||
|
os << warnings.size() << " warnings:" << std::endl;
|
||||||
|
for(auto warn : warnings)
|
||||||
|
{
|
||||||
|
os << warn << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!successful)
|
||||||
|
{
|
||||||
|
throw falco_exception(os.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose && os.str() != "") {
|
||||||
|
// We don't really have a logging callback
|
||||||
|
// from the falco engine, but this would be a
|
||||||
|
// good place to use it.
|
||||||
|
fprintf(stderr, "When reading rules content: %s", os.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pop(m_ls, 4);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw falco_exception("No function " + m_lua_load_rules + " found in lua rule module");
|
throw falco_exception("No function " + m_lua_load_rules + " found in lua rule module");
|
||||||
|
|||||||
@@ -804,7 +804,7 @@ int falco_init(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
catch(falco_exception &e)
|
catch(falco_exception &e)
|
||||||
{
|
{
|
||||||
printf("%s%s\n", prefix.c_str(), e.what());
|
printf("%s%s", prefix.c_str(), e.what());
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
printf("%sOk\n", prefix.c_str());
|
printf("%sOk\n", prefix.c_str());
|
||||||
@@ -861,7 +861,15 @@ int falco_init(int argc, char **argv)
|
|||||||
falco_logger::log(LOG_INFO, "Loading rules from file " + filename + ":\n");
|
falco_logger::log(LOG_INFO, "Loading rules from file " + filename + ":\n");
|
||||||
uint64_t required_engine_version;
|
uint64_t required_engine_version;
|
||||||
|
|
||||||
engine->load_rules_file(filename, verbose, all_events, required_engine_version);
|
try {
|
||||||
|
engine->load_rules_file(filename, verbose, all_events, required_engine_version);
|
||||||
|
}
|
||||||
|
catch(falco_exception &e)
|
||||||
|
{
|
||||||
|
std::string prefix = "Could not load rules file " + filename + ": ";
|
||||||
|
|
||||||
|
throw falco_exception(prefix + e.what());
|
||||||
|
}
|
||||||
required_engine_versions[filename] = required_engine_version;
|
required_engine_versions[filename] = required_engine_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1171,8 +1179,8 @@ int falco_init(int argc, char **argv)
|
|||||||
falco_logger::log(LOG_ERR, "Unable to load the driver.\n");
|
falco_logger::log(LOG_ERR, "Unable to load the driver.\n");
|
||||||
}
|
}
|
||||||
open_f(inspector);
|
open_f(inspector);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rethrow_exception(current_exception());
|
rethrow_exception(current_exception());
|
||||||
}
|
}
|
||||||
@@ -1281,7 +1289,7 @@ int falco_init(int argc, char **argv)
|
|||||||
|
|
||||||
if(!trace_filename.empty() && !trace_is_scap)
|
if(!trace_filename.empty() && !trace_is_scap)
|
||||||
{
|
{
|
||||||
#ifndef MINIMAL_BUILD
|
#ifndef MINIMAL_BUILD
|
||||||
read_k8s_audit_trace_file(engine,
|
read_k8s_audit_trace_file(engine,
|
||||||
outputs,
|
outputs,
|
||||||
trace_filename);
|
trace_filename);
|
||||||
|
|||||||
Reference in New Issue
Block a user