mirror of
https://github.com/falcosecurity/falco.git
synced 2026-03-30 16:42:34 +00:00
Compare commits
13 Commits
adding-ins
...
add-contex
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff75db9477 | ||
|
|
3b49a0a85f | ||
|
|
fc5858a3d6 | ||
|
|
23e28e32c2 | ||
|
|
2fef3f3dd5 | ||
|
|
4a0bb56586 | ||
|
|
b710217181 | ||
|
|
01b3a0aa95 | ||
|
|
eb7433f838 | ||
|
|
ffc9ac56d4 | ||
|
|
74e2833cd7 | ||
|
|
d1a6666742 | ||
|
|
4830f6991c |
@@ -41,6 +41,9 @@ class FalcoTest(Test):
|
|||||||
build_dir = os.path.join('/build', build_type)
|
build_dir = os.path.join('/build', build_type)
|
||||||
self.falcodir = self.params.get('falcodir', '/', default=os.path.join(self.basedir, build_dir))
|
self.falcodir = self.params.get('falcodir', '/', default=os.path.join(self.basedir, build_dir))
|
||||||
|
|
||||||
|
self.stdout_is = self.params.get('stdout_is', '*', default='')
|
||||||
|
self.stderr_is = self.params.get('stderr_is', '*', default='')
|
||||||
|
|
||||||
self.stdout_contains = self.params.get('stdout_contains', '*', default='')
|
self.stdout_contains = self.params.get('stdout_contains', '*', default='')
|
||||||
|
|
||||||
if not isinstance(self.stdout_contains, list):
|
if not isinstance(self.stdout_contains, list):
|
||||||
@@ -83,8 +86,21 @@ class FalcoTest(Test):
|
|||||||
if not isinstance(self.rules_file, list):
|
if not isinstance(self.rules_file, list):
|
||||||
self.rules_file = [self.rules_file]
|
self.rules_file = [self.rules_file]
|
||||||
|
|
||||||
|
self.validate_rules_file = self.params.get('validate_rules_file', '*', default=False)
|
||||||
|
|
||||||
|
if self.validate_rules_file == False:
|
||||||
|
self.validate_rules_file = []
|
||||||
|
else:
|
||||||
|
if not isinstance(self.validate_rules_file, list):
|
||||||
|
self.validate_rules_file = [self.validate_rules_file]
|
||||||
|
|
||||||
self.rules_args = ""
|
self.rules_args = ""
|
||||||
|
|
||||||
|
for file in self.validate_rules_file:
|
||||||
|
if not os.path.isabs(file):
|
||||||
|
file = os.path.join(self.basedir, file)
|
||||||
|
self.rules_args = self.rules_args + "-V " + file + " "
|
||||||
|
|
||||||
for file in self.rules_file:
|
for file in self.rules_file:
|
||||||
if not os.path.isabs(file):
|
if not os.path.isabs(file):
|
||||||
file = os.path.join(self.basedir, file)
|
file = os.path.join(self.basedir, file)
|
||||||
@@ -433,6 +449,15 @@ class FalcoTest(Test):
|
|||||||
|
|
||||||
res = self.falco_proc.run(timeout=180, sig=9)
|
res = self.falco_proc.run(timeout=180, sig=9)
|
||||||
|
|
||||||
|
if self.stdout_is != '':
|
||||||
|
print(self.stdout_is)
|
||||||
|
if self.stdout_is != res.stdout:
|
||||||
|
self.fail("Stdout was not exactly {}".format(self.stdout_is))
|
||||||
|
|
||||||
|
if self.stderr_is != '':
|
||||||
|
if self.stderr_is != res.stdout:
|
||||||
|
self.fail("Stdout was not exactly {}".format(self.stderr_is))
|
||||||
|
|
||||||
for pattern in self.stderr_contains:
|
for pattern in self.stderr_contains:
|
||||||
match = re.search(pattern, res.stderr)
|
match = re.search(pattern, res.stderr)
|
||||||
if match is None:
|
if match is None:
|
||||||
|
|||||||
@@ -238,6 +238,199 @@ trace_files: !mux
|
|||||||
- rules/endswith.yaml
|
- rules/endswith.yaml
|
||||||
trace_file: trace_files/cat_write.scap
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
invalid_not_yaml:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
Rules content is not yaml
|
||||||
|
---
|
||||||
|
This is not yaml
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/invalid_not_yaml.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
invalid_not_array:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
Rules content is not yaml array of objects
|
||||||
|
---
|
||||||
|
foo: bar
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/invalid_not_array.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
invalid_array_item_not_object:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
Unexpected element of type string. Each element should be a yaml associative array.
|
||||||
|
---
|
||||||
|
- foo
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/invalid_array_item_not_object.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
invalid_unexpected object:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
Unknown rule object: {foo="bar"}
|
||||||
|
---
|
||||||
|
- foo: bar
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/invalid_unexpected_object.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
invalid_engine_version_not_number:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
Value of required_engine_version must be a number
|
||||||
|
---
|
||||||
|
- required_engine_version: not-a-number
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/invalid_engine_version_not_number.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
invalid_yaml_parse_error:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
mapping values are not allowed in this context
|
||||||
|
---
|
||||||
|
this : is : not : yaml
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/invalid_yaml_parse_error.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
invalid_list_without_items:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
List must have property items
|
||||||
|
---
|
||||||
|
- list: bad_list
|
||||||
|
no_items: foo
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/invalid_list_without_items.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
invalid_macro_without_condition:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
Macro must have property condition
|
||||||
|
---
|
||||||
|
- macro: bad_macro
|
||||||
|
nope: 1
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/invalid_macro_without_condition.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
invalid_rule_without_output:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
Rule must have property output
|
||||||
|
---
|
||||||
|
- rule: no output rule
|
||||||
|
desc: some desc
|
||||||
|
condition: evt.type=fork
|
||||||
|
priority: INFO
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/invalid_rule_without_output.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
invalid_append_rule_without_condition:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
Rule must have property condition
|
||||||
|
---
|
||||||
|
- rule: no condition rule
|
||||||
|
append: true
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/invalid_append_rule_without_condition.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
invalid_append_macro_dangling:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
Macro dangling append has 'append' key but no macro by that name already exists
|
||||||
|
---
|
||||||
|
- macro: dangling append
|
||||||
|
condition: and evt.type=execve
|
||||||
|
append: true
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/invalid_append_macro_dangling.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
invalid_list_append_dangling:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
List my_list has 'append' key but no list by that name already exists
|
||||||
|
---
|
||||||
|
- list: my_list
|
||||||
|
items: [not-cat]
|
||||||
|
append: true
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/list_append_failure.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
invalid_rule_append_dangling:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
Rule my_rule has 'append' key but no rule by that name already exists
|
||||||
|
---
|
||||||
|
- rule: my_rule
|
||||||
|
condition: evt.type=open
|
||||||
|
append: true
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/rule_append_failure.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
invalid_missing_rule_name:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
Rule name is empty
|
||||||
|
---
|
||||||
|
- rule:
|
||||||
|
desc: some desc
|
||||||
|
condition: evt.type=execve
|
||||||
|
output: some output
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/invalid_missing_rule_name.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
invalid_missing_list_name:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
List name is empty
|
||||||
|
---
|
||||||
|
- list:
|
||||||
|
items: [foo]
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/invalid_missing_list_name.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
invalid_missing_macro_name:
|
||||||
|
exit_status: 1
|
||||||
|
stdout_is: |+
|
||||||
|
Macro name is empty
|
||||||
|
---
|
||||||
|
- macro:
|
||||||
|
condition: evt.type=execve
|
||||||
|
---
|
||||||
|
validate_rules_file:
|
||||||
|
- rules/invalid_missing_macro_name.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
invalid_rule_output:
|
invalid_rule_output:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stderr_contains: "Runtime error: Error loading rules:.* Invalid output format 'An open was seen %not_a_real_field': 'invalid formatting token not_a_real_field'. Exiting."
|
stderr_contains: "Runtime error: Error loading rules:.* Invalid output format 'An open was seen %not_a_real_field': 'invalid formatting token not_a_real_field'. Exiting."
|
||||||
@@ -601,7 +794,7 @@ trace_files: !mux
|
|||||||
|
|
||||||
list_append_failure:
|
list_append_failure:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stderr_contains: "List my_list has 'append' key but no list by that name already exists. Exiting"
|
stderr_contains: "List my_list has 'append' key but no list by that name already exists"
|
||||||
rules_file:
|
rules_file:
|
||||||
- rules/list_append_failure.yaml
|
- rules/list_append_failure.yaml
|
||||||
trace_file: trace_files/cat_write.scap
|
trace_file: trace_files/cat_write.scap
|
||||||
@@ -621,7 +814,7 @@ trace_files: !mux
|
|||||||
|
|
||||||
macro_append_failure:
|
macro_append_failure:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stderr_contains: "Macro my_macro has 'append' key but no macro by that name already exists. Exiting"
|
stderr_contains: "Macro my_macro has 'append' key but no macro by that name already exists"
|
||||||
rules_file:
|
rules_file:
|
||||||
- rules/macro_append_failure.yaml
|
- rules/macro_append_failure.yaml
|
||||||
trace_file: trace_files/cat_write.scap
|
trace_file: trace_files/cat_write.scap
|
||||||
@@ -641,7 +834,7 @@ trace_files: !mux
|
|||||||
|
|
||||||
rule_append_failure:
|
rule_append_failure:
|
||||||
exit_status: 1
|
exit_status: 1
|
||||||
stderr_contains: "Rule my_rule has 'append' key but no rule by that name already exists. Exiting"
|
stderr_contains: "Rule my_rule has 'append' key but no rule by that name already exists"
|
||||||
rules_file:
|
rules_file:
|
||||||
- rules/rule_append_failure.yaml
|
- rules/rule_append_failure.yaml
|
||||||
trace_file: trace_files/cat_write.scap
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|||||||
3
test/rules/invalid_append_macro_dangling.yaml
Normal file
3
test/rules/invalid_append_macro_dangling.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
- macro: dangling append
|
||||||
|
condition: and evt.type=execve
|
||||||
|
append: true
|
||||||
2
test/rules/invalid_append_rule_without_condition.yaml
Normal file
2
test/rules/invalid_append_rule_without_condition.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
- rule: no condition rule
|
||||||
|
append: true
|
||||||
1
test/rules/invalid_array_item_not_object.yaml
Normal file
1
test/rules/invalid_array_item_not_object.yaml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
- foo
|
||||||
34
test/rules/invalid_engine_version_not_number.yaml
Normal file
34
test/rules/invalid_engine_version_not_number.yaml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2016-2018 Draios Inc dba Sysdig.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
- required_engine_version: not-a-number
|
||||||
|
|
||||||
|
- list: cat_binaries
|
||||||
|
items: [cat]
|
||||||
|
|
||||||
|
- list: cat_capable_binaries
|
||||||
|
items: [cat_binaries]
|
||||||
|
|
||||||
|
- macro: is_cat
|
||||||
|
condition: proc.name in (cat_capable_binaries)
|
||||||
|
|
||||||
|
- rule: open_from_cat
|
||||||
|
desc: A process named cat does an open
|
||||||
|
condition: evt.type=open and is_cat
|
||||||
|
output: "An open was seen (command=%proc.cmdline)"
|
||||||
|
priority: WARNING
|
||||||
5
test/rules/invalid_list_without_items.yaml
Normal file
5
test/rules/invalid_list_without_items.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
- list: good_list
|
||||||
|
items: [foo]
|
||||||
|
|
||||||
|
- list: bad_list
|
||||||
|
no_items: foo
|
||||||
6
test/rules/invalid_macro_without_condition.yaml
Normal file
6
test/rules/invalid_macro_without_condition.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
- macro: bad_macro
|
||||||
|
nope: 1
|
||||||
|
|
||||||
|
- macro: good_macro
|
||||||
|
condition: evt.type=execve
|
||||||
|
|
||||||
2
test/rules/invalid_missing_list_name.yaml
Normal file
2
test/rules/invalid_missing_list_name.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
- list:
|
||||||
|
items: [foo]
|
||||||
2
test/rules/invalid_missing_macro_name.yaml
Normal file
2
test/rules/invalid_missing_macro_name.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
- macro:
|
||||||
|
condition: evt.type=execve
|
||||||
4
test/rules/invalid_missing_rule_name.yaml
Normal file
4
test/rules/invalid_missing_rule_name.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
- rule:
|
||||||
|
desc: some desc
|
||||||
|
condition: evt.type=execve
|
||||||
|
output: some output
|
||||||
1
test/rules/invalid_not_array.yaml
Normal file
1
test/rules/invalid_not_array.yaml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
foo: bar
|
||||||
1
test/rules/invalid_not_yaml.yaml
Normal file
1
test/rules/invalid_not_yaml.yaml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
This is not yaml
|
||||||
4
test/rules/invalid_rule_without_output.yaml
Normal file
4
test/rules/invalid_rule_without_output.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
- rule: no output rule
|
||||||
|
desc: some desc
|
||||||
|
condition: evt.type=fork
|
||||||
|
priority: INFO
|
||||||
1
test/rules/invalid_unexpected_object.yaml
Normal file
1
test/rules/invalid_unexpected_object.yaml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
- foo: bar
|
||||||
1
test/rules/invalid_yaml_parse_error.yaml
Normal file
1
test/rules/invalid_yaml_parse_error.yaml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
this : is : not : yaml
|
||||||
@@ -62,12 +62,12 @@ function expand_macros(ast, defs, changed)
|
|||||||
elseif ast.type == "Filter" then
|
elseif ast.type == "Filter" then
|
||||||
if (ast.value.type == "Macro") then
|
if (ast.value.type == "Macro") then
|
||||||
if (defs[ast.value.value] == nil) then
|
if (defs[ast.value.value] == nil) then
|
||||||
error("Undefined macro '".. ast.value.value .. "' used in filter.")
|
return false, "Undefined macro '".. ast.value.value .. "' used in filter."
|
||||||
end
|
end
|
||||||
defs[ast.value.value].used = true
|
defs[ast.value.value].used = true
|
||||||
ast.value = copy_ast_obj(defs[ast.value.value].ast)
|
ast.value = copy_ast_obj(defs[ast.value.value].ast)
|
||||||
changed = true
|
changed = true
|
||||||
return changed
|
return true, changed
|
||||||
end
|
end
|
||||||
return expand_macros(ast.value, defs, changed)
|
return expand_macros(ast.value, defs, changed)
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ function expand_macros(ast, defs, changed)
|
|||||||
|
|
||||||
if (ast.left.type == "Macro") then
|
if (ast.left.type == "Macro") then
|
||||||
if (defs[ast.left.value] == nil) then
|
if (defs[ast.left.value] == nil) then
|
||||||
error("Undefined macro '".. ast.left.value .. "' used in filter.")
|
return false, "Undefined macro '".. ast.left.value .. "' used in filter."
|
||||||
end
|
end
|
||||||
defs[ast.left.value].used = true
|
defs[ast.left.value].used = true
|
||||||
ast.left = copy_ast_obj(defs[ast.left.value].ast)
|
ast.left = copy_ast_obj(defs[ast.left.value].ast)
|
||||||
@@ -84,21 +84,27 @@ function expand_macros(ast, defs, changed)
|
|||||||
|
|
||||||
if (ast.right.type == "Macro") then
|
if (ast.right.type == "Macro") then
|
||||||
if (defs[ast.right.value] == nil) then
|
if (defs[ast.right.value] == nil) then
|
||||||
error("Undefined macro ".. ast.right.value .. " used in filter.")
|
return false, "Undefined macro ".. ast.right.value .. " used in filter."
|
||||||
end
|
end
|
||||||
defs[ast.right.value].used = true
|
defs[ast.right.value].used = true
|
||||||
ast.right = copy_ast_obj(defs[ast.right.value].ast)
|
ast.right = copy_ast_obj(defs[ast.right.value].ast)
|
||||||
changed = true
|
changed = true
|
||||||
end
|
end
|
||||||
|
|
||||||
local changed_left = expand_macros(ast.left, defs, false)
|
local status, changed_left = expand_macros(ast.left, defs, false)
|
||||||
local changed_right = expand_macros(ast.right, defs, false)
|
if status == false then
|
||||||
return changed or changed_left or changed_right
|
return false, changed_left
|
||||||
|
end
|
||||||
|
local status, changed_right = expand_macros(ast.right, defs, false)
|
||||||
|
if status == false then
|
||||||
|
return false, changed_right
|
||||||
|
end
|
||||||
|
return true, changed or changed_left or changed_right
|
||||||
|
|
||||||
elseif ast.type == "UnaryBoolOp" then
|
elseif ast.type == "UnaryBoolOp" then
|
||||||
if (ast.argument.type == "Macro") then
|
if (ast.argument.type == "Macro") then
|
||||||
if (defs[ast.argument.value] == nil) then
|
if (defs[ast.argument.value] == nil) then
|
||||||
error("Undefined macro ".. ast.argument.value .. " used in filter.")
|
return false, "Undefined macro ".. ast.argument.value .. " used in filter."
|
||||||
end
|
end
|
||||||
defs[ast.argument.value].used = true
|
defs[ast.argument.value].used = true
|
||||||
ast.argument = copy_ast_obj(defs[ast.argument.value].ast)
|
ast.argument = copy_ast_obj(defs[ast.argument.value].ast)
|
||||||
@@ -106,7 +112,7 @@ function expand_macros(ast, defs, changed)
|
|||||||
end
|
end
|
||||||
return expand_macros(ast.argument, defs, changed)
|
return expand_macros(ast.argument, defs, changed)
|
||||||
end
|
end
|
||||||
return changed
|
return true, changed
|
||||||
end
|
end
|
||||||
|
|
||||||
function get_macros(ast, set)
|
function get_macros(ast, set)
|
||||||
@@ -195,7 +201,7 @@ function compiler.compile_macro(line, macro_defs, list_defs)
|
|||||||
|
|
||||||
if (error_msg) then
|
if (error_msg) then
|
||||||
msg = "Compilation error when compiling \""..line.."\": ".. error_msg
|
msg = "Compilation error when compiling \""..line.."\": ".. error_msg
|
||||||
error(msg)
|
return false, msg
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Simply as a validation step, try to expand all macros in this
|
-- Simply as a validation step, try to expand all macros in this
|
||||||
@@ -206,14 +212,18 @@ function compiler.compile_macro(line, macro_defs, list_defs)
|
|||||||
if (ast.type == "Rule") then
|
if (ast.type == "Rule") then
|
||||||
-- Line is a filter, so expand macro references
|
-- Line is a filter, so expand macro references
|
||||||
repeat
|
repeat
|
||||||
expanded = expand_macros(ast_copy, macro_defs, false)
|
status, expanded = expand_macros(ast_copy, macro_defs, false)
|
||||||
|
if status == false then
|
||||||
|
msg = "Compilation error when compiling \""..line.."\": ".. expanded
|
||||||
|
return false, msg
|
||||||
|
end
|
||||||
until expanded == false
|
until expanded == false
|
||||||
|
|
||||||
else
|
else
|
||||||
error("Unexpected top-level AST type: "..ast.type)
|
return false, "Unexpected top-level AST type: "..ast.type
|
||||||
end
|
end
|
||||||
|
|
||||||
return ast
|
return true, ast
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@@ -227,22 +237,25 @@ function compiler.compile_filter(name, source, macro_defs, list_defs)
|
|||||||
|
|
||||||
if (error_msg) then
|
if (error_msg) then
|
||||||
msg = "Compilation error when compiling \""..source.."\": "..error_msg
|
msg = "Compilation error when compiling \""..source.."\": "..error_msg
|
||||||
error(msg)
|
return false, msg
|
||||||
end
|
end
|
||||||
|
|
||||||
if (ast.type == "Rule") then
|
if (ast.type == "Rule") then
|
||||||
-- Line is a filter, so expand macro references
|
-- Line is a filter, so expand macro references
|
||||||
repeat
|
repeat
|
||||||
expanded = expand_macros(ast, macro_defs, false)
|
status, expanded = expand_macros(ast, macro_defs, false)
|
||||||
|
if status == false then
|
||||||
|
return false, expanded
|
||||||
|
end
|
||||||
until expanded == false
|
until expanded == false
|
||||||
|
|
||||||
else
|
else
|
||||||
error("Unexpected top-level AST type: "..ast.type)
|
return false, "Unexpected top-level AST type: "..ast.type
|
||||||
end
|
end
|
||||||
|
|
||||||
filters = get_filters(ast)
|
filters = get_filters(ast)
|
||||||
|
|
||||||
return ast, filters
|
return true, ast, filters
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -179,6 +179,71 @@ function table.tostring( tbl )
|
|||||||
return "{" .. table.concat( result, "," ) .. "}"
|
return "{" .. table.concat( result, "," ) .. "}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Split rules_content by lines and also remember the line numbers for
|
||||||
|
-- each top -level object. Returns a table of lines and a table of
|
||||||
|
-- line numbers for objects.
|
||||||
|
|
||||||
|
function split_lines(rules_content)
|
||||||
|
lines = {}
|
||||||
|
indices = {}
|
||||||
|
|
||||||
|
idx = 1
|
||||||
|
last_pos = 1
|
||||||
|
pos = string.find(rules_content, "\n", 1, true)
|
||||||
|
|
||||||
|
while pos ~= nil do
|
||||||
|
line = string.sub(rules_content, last_pos, pos-1)
|
||||||
|
if line ~= "" then
|
||||||
|
lines[#lines+1] = line
|
||||||
|
if string.sub(line, 1, 1) == '-' then
|
||||||
|
indices[#indices+1] = idx
|
||||||
|
end
|
||||||
|
|
||||||
|
idx = idx + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
last_pos = pos+1
|
||||||
|
pos = string.find(rules_content, "\n", pos+1, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
if last_pos < string.len(rules_content) then
|
||||||
|
line = string.sub(rules_content, last_pos)
|
||||||
|
lines[#lines+1] = line
|
||||||
|
if string.sub(line, 1, 1) == '-' then
|
||||||
|
indices[#indices+1] = idx
|
||||||
|
end
|
||||||
|
|
||||||
|
idx = idx + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add a final index for last line in document
|
||||||
|
indices[#indices+1] = idx
|
||||||
|
|
||||||
|
return lines, indices
|
||||||
|
end
|
||||||
|
|
||||||
|
function get_context(rules_lines, row, num_lines)
|
||||||
|
|
||||||
|
local ret = "---\n"
|
||||||
|
|
||||||
|
idx = row
|
||||||
|
while (idx < (row + num_lines) and idx <= #rules_lines) do
|
||||||
|
ret = ret..rules_lines[idx].."\n"
|
||||||
|
idx = idx + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
ret = ret.."---"
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function build_error(rules_lines, row, num_lines, err)
|
||||||
|
|
||||||
|
local ret = err.."\n"..get_context(rules_lines, row, num_lines)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
function load_rules(sinsp_lua_parser,
|
function load_rules(sinsp_lua_parser,
|
||||||
json_lua_parser,
|
json_lua_parser,
|
||||||
@@ -190,16 +255,45 @@ function load_rules(sinsp_lua_parser,
|
|||||||
replace_container_info,
|
replace_container_info,
|
||||||
min_priority)
|
min_priority)
|
||||||
|
|
||||||
local rules = yaml.load(rules_content)
|
|
||||||
local required_engine_version = 0
|
local required_engine_version = 0
|
||||||
|
|
||||||
|
local lines, indices = split_lines(rules_content)
|
||||||
|
|
||||||
|
local status, rules = pcall(yaml.load, rules_content)
|
||||||
|
|
||||||
|
if status == false then
|
||||||
|
local pat = "^([%d]+):([%d]+): "
|
||||||
|
-- rules is actually an error string
|
||||||
|
|
||||||
|
local row = 0
|
||||||
|
local col = 0
|
||||||
|
|
||||||
|
row, col = string.match(rules, pat)
|
||||||
|
if row ~= nil and col ~= nil then
|
||||||
|
rules = string.gsub(rules, pat, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
row = tonumber(row)
|
||||||
|
col = tonumber(col)
|
||||||
|
|
||||||
|
return false, build_error(lines, row, 3, rules)
|
||||||
|
end
|
||||||
|
|
||||||
if rules == nil then
|
if rules == nil then
|
||||||
-- An empty rules file is acceptable
|
-- An empty rules file is acceptable
|
||||||
return required_engine_version
|
return true, required_engine_version
|
||||||
end
|
end
|
||||||
|
|
||||||
if type(rules) ~= "table" then
|
if type(rules) ~= "table" then
|
||||||
error("Rules content \""..rules_content.."\" is not yaml")
|
return false, build_error(lines, 1, 1, "Rules content is not yaml")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Look for non-numeric indices--implies that document is not array
|
||||||
|
-- of objects.
|
||||||
|
for key, val in pairs(rules) do
|
||||||
|
if type(key) ~= "number" then
|
||||||
|
return false, build_error(lines, 1, 1, "Rules content is not yaml array of objects")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Iterate over yaml list. In this pass, all we're doing is
|
-- Iterate over yaml list. In this pass, all we're doing is
|
||||||
@@ -209,17 +303,25 @@ function load_rules(sinsp_lua_parser,
|
|||||||
for i,v in ipairs(rules) do
|
for i,v in ipairs(rules) do
|
||||||
|
|
||||||
if (not (type(v) == "table")) then
|
if (not (type(v) == "table")) then
|
||||||
error ("Unexpected element of type " ..type(v)..". Each element should be a yaml associative array.")
|
return false, build_error(lines, indices[i], (indices[i+1]-indices[i]), "Unexpected element of type " ..type(v)..". Each element should be a yaml associative array.")
|
||||||
end
|
end
|
||||||
|
|
||||||
if (v['required_engine_version']) then
|
if (v['required_engine_version']) then
|
||||||
required_engine_version = v['required_engine_version']
|
required_engine_version = v['required_engine_version']
|
||||||
|
if type(required_engine_version) ~= "number" then
|
||||||
|
return false, build_error(lines, indices[i], (indices[i+1]-indices[i]), "Value of required_engine_version must be a number")
|
||||||
|
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
|
||||||
error("Rules require engine version "..v['required_engine_version']..", but engine version is "..falco_rules.engine_version(rules_mgr))
|
return false, build_error(lines, indices[i], (indices[i+1]-indices[i]), "Rules require engine version "..v['required_engine_version']..", but engine version is "..falco_rules.engine_version(rules_mgr))
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif (v['macro']) then
|
elseif (v['macro']) then
|
||||||
|
|
||||||
|
if (v['macro'] == nil or type(v['macro']) == "table") then
|
||||||
|
return false, build_error(lines, indices[i], (indices[i+1]-indices[i]), "Macro name is empty")
|
||||||
|
end
|
||||||
|
|
||||||
if v['source'] == nil then
|
if v['source'] == nil then
|
||||||
v['source'] = "syscall"
|
v['source'] = "syscall"
|
||||||
end
|
end
|
||||||
@@ -228,9 +330,9 @@ function load_rules(sinsp_lua_parser,
|
|||||||
state.ordered_macro_names[#state.ordered_macro_names+1] = v['macro']
|
state.ordered_macro_names[#state.ordered_macro_names+1] = v['macro']
|
||||||
end
|
end
|
||||||
|
|
||||||
for i, field in ipairs({'condition'}) do
|
for j, field in ipairs({'condition'}) do
|
||||||
if (v[field] == nil) then
|
if (v[field] == nil) then
|
||||||
error ("Missing "..field.." in macro with name "..v['macro'])
|
return false, build_error(lines, indices[i], (indices[i+1]-indices[i]), "Macro must have property "..field)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -243,7 +345,7 @@ function load_rules(sinsp_lua_parser,
|
|||||||
|
|
||||||
if append then
|
if append then
|
||||||
if state.macros_by_name[v['macro']] == nil then
|
if state.macros_by_name[v['macro']] == nil then
|
||||||
error ("Macro " ..v['macro'].. " has 'append' key but no macro by that name already exists")
|
return false, build_error(lines, indices[i], (indices[i+1]-indices[i]), "Macro " ..v['macro'].. " has 'append' key but no macro by that name already exists")
|
||||||
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']
|
||||||
@@ -254,13 +356,17 @@ function load_rules(sinsp_lua_parser,
|
|||||||
|
|
||||||
elseif (v['list']) then
|
elseif (v['list']) then
|
||||||
|
|
||||||
|
if (v['list'] == nil or type(v['list']) == "table") then
|
||||||
|
return false, build_error(lines, indices[i], (indices[i+1]-indices[i]), "List name is empty")
|
||||||
|
end
|
||||||
|
|
||||||
if state.lists_by_name[v['list']] == nil then
|
if state.lists_by_name[v['list']] == nil then
|
||||||
state.ordered_list_names[#state.ordered_list_names+1] = v['list']
|
state.ordered_list_names[#state.ordered_list_names+1] = v['list']
|
||||||
end
|
end
|
||||||
|
|
||||||
for i, field in ipairs({'items'}) do
|
for j, field in ipairs({'items'}) do
|
||||||
if (v[field] == nil) then
|
if (v[field] == nil) then
|
||||||
error ("Missing "..field.." in list with name "..v['list'])
|
return false, build_error(lines, indices[i], (indices[i+1]-indices[i]), "List must have property "..field)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -273,10 +379,10 @@ function load_rules(sinsp_lua_parser,
|
|||||||
|
|
||||||
if append then
|
if append then
|
||||||
if state.lists_by_name[v['list']] == nil then
|
if state.lists_by_name[v['list']] == nil then
|
||||||
error ("List " ..v['list'].. " has 'append' key but no list by that name already exists")
|
return false, build_error(lines, indices[i], (indices[i+1]-indices[i]), "List " ..v['list'].. " has 'append' key but no list by that name already exists")
|
||||||
end
|
end
|
||||||
|
|
||||||
for i, elem in ipairs(v['items']) do
|
for j, elem in ipairs(v['items']) do
|
||||||
table.insert(state.lists_by_name[v['list']]['items'], elem)
|
table.insert(state.lists_by_name[v['list']]['items'], elem)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@@ -286,7 +392,7 @@ function load_rules(sinsp_lua_parser,
|
|||||||
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
|
||||||
error ("Missing name in rule")
|
return false, build_error(lines, indices[i], (indices[i+1]-indices[i]), "Rule name is empty")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- By default, if a rule's condition refers to an unknown
|
-- By default, if a rule's condition refers to an unknown
|
||||||
@@ -309,15 +415,15 @@ function load_rules(sinsp_lua_parser,
|
|||||||
if append then
|
if append then
|
||||||
|
|
||||||
-- For append rules, all you need is the condition
|
-- For append rules, all you need is the condition
|
||||||
for i, field in ipairs({'condition'}) do
|
for j, field in ipairs({'condition'}) do
|
||||||
if (v[field] == nil) then
|
if (v[field] == nil) then
|
||||||
error ("Missing "..field.." in rule with name "..v['rule'])
|
return false, build_error(lines, indices[i], (indices[i+1]-indices[i]), "Rule must have property "..field)
|
||||||
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
|
||||||
error ("Rule " ..v['rule'].. " has 'append' key but no rule by that name already exists")
|
return false, build_error(lines, indices[i], (indices[i+1]-indices[i]), "Rule " ..v['rule'].. " has 'append' key but no rule by that name already exists")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
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']
|
||||||
@@ -325,9 +431,9 @@ function load_rules(sinsp_lua_parser,
|
|||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
for i, 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
|
||||||
error ("Missing "..field.." in rule with name "..v['rule'])
|
return false, build_error(lines, indices[i], (indices[i+1]-indices[i]), "Rule must have property "..field)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -356,7 +462,7 @@ function load_rules(sinsp_lua_parser,
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
error ("Unknown rule object: "..table.tostring(v))
|
return false, build_error(lines, indices[i], (indices[i+1]-indices[i]), "Unknown rule object: "..table.tostring(v))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -393,7 +499,11 @@ function load_rules(sinsp_lua_parser,
|
|||||||
|
|
||||||
local v = state.macros_by_name[name]
|
local v = state.macros_by_name[name]
|
||||||
|
|
||||||
local 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
|
||||||
|
return false, build_error(lines, indices[i], (indices[i+1]-indices[i]), ast)
|
||||||
|
end
|
||||||
|
|
||||||
if v['source'] == "syscall" then
|
if v['source'] == "syscall" then
|
||||||
if not all_events then
|
if not all_events then
|
||||||
@@ -413,8 +523,12 @@ function load_rules(sinsp_lua_parser,
|
|||||||
warn_evttypes = v['warn_evttypes']
|
warn_evttypes = v['warn_evttypes']
|
||||||
end
|
end
|
||||||
|
|
||||||
local filter_ast, filters = compiler.compile_filter(v['rule'], v['condition'],
|
local status, filter_ast, filters = compiler.compile_filter(v['rule'], v['condition'],
|
||||||
state.macros, state.lists)
|
state.macros, state.lists)
|
||||||
|
|
||||||
|
if status == false then
|
||||||
|
return false, build_error(lines, indices[i], (indices[i+1]-indices[i]), filter_ast)
|
||||||
|
end
|
||||||
|
|
||||||
local evtttypes = {}
|
local evtttypes = {}
|
||||||
local syscallnums = {}
|
local syscallnums = {}
|
||||||
@@ -551,7 +665,7 @@ 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
|
||||||
error ("Unexpected type in load_rule: "..filter_ast.type)
|
return false, build_error(lines, indices[i], (indices[i+1]-indices[i]), "Unexpected type in load_rule: "..filter_ast.type)
|
||||||
end
|
end
|
||||||
|
|
||||||
::next_rule::
|
::next_rule::
|
||||||
@@ -574,7 +688,7 @@ function load_rules(sinsp_lua_parser,
|
|||||||
|
|
||||||
io.flush()
|
io.flush()
|
||||||
|
|
||||||
return required_engine_version
|
return true, required_engine_version
|
||||||
end
|
end
|
||||||
|
|
||||||
local rule_fmt = "%-50s %s"
|
local rule_fmt = "%-50s %s"
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ limitations under the License.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "rules.h"
|
#include "rules.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
|
||||||
@@ -425,15 +427,30 @@ 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, 1, 0) != 0)
|
if(lua_pcall(m_ls, 9, 2, 0) != 0)
|
||||||
{
|
{
|
||||||
const char* lerr = lua_tostring(m_ls, -1);
|
const char* lerr = lua_tostring(m_ls, -1);
|
||||||
|
|
||||||
string err = "Error loading rules: " + string(lerr);
|
string err = "Error loading rules: " + string(lerr);
|
||||||
|
|
||||||
throw falco_exception(err);
|
throw falco_exception(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
required_engine_version = lua_tonumber(m_ls, -1);
|
// Either returns (true, required_engine_version), or (false, error string)
|
||||||
lua_pop(m_ls, 1);
|
bool successful = lua_toboolean(m_ls, -2);
|
||||||
|
|
||||||
|
if(successful)
|
||||||
|
{
|
||||||
|
required_engine_version = lua_tonumber(m_ls, -1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string err = lua_tostring(m_ls, -1);
|
||||||
|
throw falco_exception(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ limitations under the License.
|
|||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
#include "sinsp.h"
|
#include "sinsp.h"
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
@@ -57,13 +58,13 @@ class falco_rules
|
|||||||
void add_filter(string &rule, std::set<uint32_t> &evttypes, std::set<uint32_t> &syscalls, std::set<string> &tags);
|
void add_filter(string &rule, std::set<uint32_t> &evttypes, std::set<uint32_t> &syscalls, std::set<string> &tags);
|
||||||
void add_k8s_audit_filter(string &rule, std::set<string> &tags);
|
void add_k8s_audit_filter(string &rule, std::set<string> &tags);
|
||||||
void enable_rule(string &rule, bool enabled);
|
void enable_rule(string &rule, bool enabled);
|
||||||
|
std::string get_context(const std::string &content, uint64_t line, uint64_t column);
|
||||||
|
|
||||||
lua_parser* m_sinsp_lua_parser;
|
lua_parser* m_sinsp_lua_parser;
|
||||||
lua_parser* m_json_lua_parser;
|
lua_parser* m_json_lua_parser;
|
||||||
sinsp* m_inspector;
|
sinsp* m_inspector;
|
||||||
falco_engine *m_engine;
|
falco_engine *m_engine;
|
||||||
lua_State* m_ls;
|
lua_State* m_ls;
|
||||||
|
|
||||||
string m_lua_load_rules = "load_rules";
|
string m_lua_load_rules = "load_rules";
|
||||||
string m_lua_ignored_syscalls = "ignored_syscalls";
|
string m_lua_ignored_syscalls = "ignored_syscalls";
|
||||||
string m_lua_ignored_events = "ignored_events";
|
string m_lua_ignored_events = "ignored_events";
|
||||||
|
|||||||
@@ -716,7 +716,17 @@ int falco_init(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
for(auto file : validate_rules_filenames)
|
for(auto file : validate_rules_filenames)
|
||||||
{
|
{
|
||||||
engine->load_rules_file(file, verbose, all_events);
|
// Only include the prefix if there is more than one file
|
||||||
|
std::string prefix = (validate_rules_filenames.size() > 1 ? file + ": " : "");
|
||||||
|
try {
|
||||||
|
engine->load_rules_file(file, verbose, all_events);
|
||||||
|
}
|
||||||
|
catch(falco_exception &e)
|
||||||
|
{
|
||||||
|
printf("%s%s\n", prefix.c_str(), e.what());
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
printf("%sOk\n", prefix.c_str());
|
||||||
}
|
}
|
||||||
falco_logger::log(LOG_INFO, "Ok\n");
|
falco_logger::log(LOG_INFO, "Ok\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|||||||
Reference in New Issue
Block a user