mirror of
https://github.com/falcosecurity/falco.git
synced 2025-06-30 08:32:12 +00:00
Add regression tests for configurable outputs.
- In the regression tests, make the config file configurable in the multiplex file via 'conf_file'. - A new multiplex file item 'outputs' containing a list of <filename>: <regex> tuples. For each item, the test reads the file and matches each line against the regex. A match must be found for the test to pass. - Add 2 new tests that test file output and program output. They write to files below /tmp/falco_outputs/ and the contents are checked to ensure that alerts are written.
This commit is contained in:
parent
6ab0139532
commit
897df28036
27
test/confs/file_output.yaml
Normal file
27
test/confs/file_output.yaml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# File containing Falco rules, loaded at startup.
|
||||||
|
rules_file: /etc/falco_rules.yaml
|
||||||
|
|
||||||
|
# Whether to output events in json or text
|
||||||
|
json_output: false
|
||||||
|
|
||||||
|
# Send information logs to stderr and/or syslog Note these are *not* security
|
||||||
|
# notification logs! These are just Falco lifecycle (and possibly error) logs.
|
||||||
|
log_stderr: false
|
||||||
|
log_syslog: false
|
||||||
|
|
||||||
|
# Where security notifications should go.
|
||||||
|
# Multiple outputs can be enabled.
|
||||||
|
|
||||||
|
syslog_output:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
file_output:
|
||||||
|
enabled: true
|
||||||
|
filename: /tmp/falco_outputs/file_output.txt
|
||||||
|
|
||||||
|
stdout_output:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
program_output:
|
||||||
|
enabled: false
|
||||||
|
program: mail -s "Falco Notification" someone@example.com
|
27
test/confs/program_output.yaml
Normal file
27
test/confs/program_output.yaml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# File containing Falco rules, loaded at startup.
|
||||||
|
rules_file: /etc/falco_rules.yaml
|
||||||
|
|
||||||
|
# Whether to output events in json or text
|
||||||
|
json_output: false
|
||||||
|
|
||||||
|
# Send information logs to stderr and/or syslog Note these are *not* security
|
||||||
|
# notification logs! These are just Falco lifecycle (and possibly error) logs.
|
||||||
|
log_stderr: false
|
||||||
|
log_syslog: false
|
||||||
|
|
||||||
|
# Where security notifications should go.
|
||||||
|
# Multiple outputs can be enabled.
|
||||||
|
|
||||||
|
syslog_output:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
file_output:
|
||||||
|
enabled: false
|
||||||
|
filename: ./output.txt
|
||||||
|
|
||||||
|
stdout_output:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
program_output:
|
||||||
|
enabled: true
|
||||||
|
program: cat > /tmp/falco_outputs/program_output.txt
|
@ -36,6 +36,10 @@ class FalcoTest(Test):
|
|||||||
file = os.path.join(self.basedir, file)
|
file = os.path.join(self.basedir, file)
|
||||||
self.rules_args = self.rules_args + "-r " + file + " "
|
self.rules_args = self.rules_args + "-r " + file + " "
|
||||||
|
|
||||||
|
self.conf_file = self.params.get('conf_file', '*', default=os.path.join(self.basedir, '../falco.yaml'))
|
||||||
|
if not os.path.isabs(self.conf_file):
|
||||||
|
self.conf_file = os.path.join(self.basedir, self.conf_file)
|
||||||
|
|
||||||
self.disabled_rules = self.params.get('disabled_rules', '*', default='')
|
self.disabled_rules = self.params.get('disabled_rules', '*', default='')
|
||||||
|
|
||||||
if self.disabled_rules == '':
|
if self.disabled_rules == '':
|
||||||
@ -82,6 +86,20 @@ class FalcoTest(Test):
|
|||||||
|
|
||||||
self.str_variant = self.trace_file
|
self.str_variant = self.trace_file
|
||||||
|
|
||||||
|
self.outputs = self.params.get('outputs', '*', default='')
|
||||||
|
|
||||||
|
if self.outputs == '':
|
||||||
|
self.outputs = {}
|
||||||
|
else:
|
||||||
|
outputs = []
|
||||||
|
for item in self.outputs:
|
||||||
|
for item2 in item:
|
||||||
|
output = {}
|
||||||
|
output['file'] = item2[0]
|
||||||
|
output['line'] = item2[1]
|
||||||
|
outputs.append(output)
|
||||||
|
self.outputs = outputs
|
||||||
|
|
||||||
def check_rules_warnings(self, res):
|
def check_rules_warnings(self, res):
|
||||||
|
|
||||||
found_warning = sets.Set()
|
found_warning = sets.Set()
|
||||||
@ -140,6 +158,23 @@ class FalcoTest(Test):
|
|||||||
if not events_detected > 0:
|
if not events_detected > 0:
|
||||||
self.fail("Detected {} events at level {} when should have detected > 0".format(events_detected, level))
|
self.fail("Detected {} events at level {} when should have detected > 0".format(events_detected, level))
|
||||||
|
|
||||||
|
def check_outputs(self):
|
||||||
|
for output in self.outputs:
|
||||||
|
# Open the provided file and match each line against the
|
||||||
|
# regex in line.
|
||||||
|
file = open(output['file'], 'r')
|
||||||
|
found = False
|
||||||
|
for line in file:
|
||||||
|
match = re.search(output['line'], line)
|
||||||
|
|
||||||
|
if match is not None:
|
||||||
|
found = True
|
||||||
|
|
||||||
|
if found == False:
|
||||||
|
self.fail("Could not find a line '{}' in file '{}'".format(output['line'], output['file']))
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def check_json_output(self, res):
|
def check_json_output(self, res):
|
||||||
if self.json_output:
|
if self.json_output:
|
||||||
# Just verify that any lines starting with '{' are valid json objects.
|
# Just verify that any lines starting with '{' are valid json objects.
|
||||||
@ -155,8 +190,8 @@ class FalcoTest(Test):
|
|||||||
self.log.info("Trace file %s", self.trace_file)
|
self.log.info("Trace file %s", self.trace_file)
|
||||||
|
|
||||||
# Run the provided trace file though falco
|
# Run the provided trace file though falco
|
||||||
cmd = '{}/userspace/falco/falco {} {} -c {}/../falco.yaml -e {} -o json_output={} -v'.format(
|
cmd = '{}/userspace/falco/falco {} {} -c {} -e {} -o json_output={} -v'.format(
|
||||||
self.falcodir, self.rules_args, self.disabled_args, self.falcodir, self.trace_file, self.json_output)
|
self.falcodir, self.rules_args, self.disabled_args, self.conf_file, self.trace_file, self.json_output)
|
||||||
|
|
||||||
self.falco_proc = process.SubProcess(cmd)
|
self.falco_proc = process.SubProcess(cmd)
|
||||||
|
|
||||||
@ -171,6 +206,7 @@ class FalcoTest(Test):
|
|||||||
self.check_rules_events(res)
|
self.check_rules_events(res)
|
||||||
self.check_detections(res)
|
self.check_detections(res)
|
||||||
self.check_json_output(res)
|
self.check_json_output(res)
|
||||||
|
self.check_outputs()
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -112,3 +112,23 @@ trace_files: !mux
|
|||||||
disabled_rules:
|
disabled_rules:
|
||||||
- "open.*"
|
- "open.*"
|
||||||
trace_file: trace_files/cat_write.scap
|
trace_file: trace_files/cat_write.scap
|
||||||
|
|
||||||
|
file_output:
|
||||||
|
detect: True
|
||||||
|
detect_level: WARNING
|
||||||
|
rules_file:
|
||||||
|
- rules/single_rule.yaml
|
||||||
|
conf_file: confs/file_output.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
outputs:
|
||||||
|
- /tmp/falco_outputs/file_output.txt: Warning An open was seen
|
||||||
|
|
||||||
|
program_output:
|
||||||
|
detect: True
|
||||||
|
detect_level: WARNING
|
||||||
|
rules_file:
|
||||||
|
- rules/single_rule.yaml
|
||||||
|
conf_file: confs/program_output.yaml
|
||||||
|
trace_file: trace_files/cat_write.scap
|
||||||
|
outputs:
|
||||||
|
- /tmp/falco_outputs/program_output.txt: Warning An open was seen
|
||||||
|
@ -50,6 +50,8 @@ function prepare_multiplex_file() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function run_tests() {
|
function run_tests() {
|
||||||
|
rm -rf /tmp/falco_outputs
|
||||||
|
mkdir /tmp/falco_outputs
|
||||||
CMD="avocado run --multiplex $MULT_FILE --job-results-dir $SCRIPTDIR/job-results -- $SCRIPTDIR/falco_test.py"
|
CMD="avocado run --multiplex $MULT_FILE --job-results-dir $SCRIPTDIR/job-results -- $SCRIPTDIR/falco_test.py"
|
||||||
echo "Running: $CMD"
|
echo "Running: $CMD"
|
||||||
$CMD
|
$CMD
|
||||||
|
Loading…
Reference in New Issue
Block a user