Files
falco/test/falco_test.py
Mark Stemm fc6d775e5b Add additional rules/tests for pipe installers.
Add additional rules related to using pipe installers within a fbash
session:

 - Modify write_etc to only trigger if *not* in a fbash session. There's
   a new rule write_etc_installer which has the same conditions when in
   a fbash session, logging at INFO severity.

 - A new rule write_rpm_database warns if any non package management
   program tries to write below /var/lib/rpm.

 - Add a new warning if any program below a fbash session tries to open
   an outbound network connection on ports other than http(s) and dns.

 - Add INFO level messages when programs in a fbash session try to run
   package management binaries (rpm,yum,etc) or service
   management (systemctl,chkconfig,etc) binaries.

In order to test these new INFO level rules, make up a third class of
trace files traces-info.zip containing trace files that should result in
info-level messages.

To differentiate warning and info level detection, add an attribute to
the multiplex file "detect_level", which is "Warning" for the files in
traces-positive and "Info" for the files in traces-info. Modify
falco_test.py to look specifically for a non-zero count for the given
detect_level.

Doing this exposed a bug in the way the level-specific counts were being
recorded--they were keeping counts by level name, not number. Fix that.
2016-06-06 10:29:41 -07:00

79 lines
2.7 KiB
Python

#!/usr/bin/env python
import os
import re
from avocado import Test
from avocado.utils import process
from avocado.utils import linux_modules
class FalcoTest(Test):
def setUp(self):
"""
Load the sysdig kernel module if not already loaded.
"""
self.falcodir = self.params.get('falcodir', '/', default=os.path.join(self.basedir, '../build'))
self.should_detect = self.params.get('detect', '*')
self.trace_file = self.params.get('trace_file', '*')
if self.should_detect:
self.detect_level = self.params.get('detect_level', '*')
# Doing this in 2 steps instead of simply using
# module_is_loaded to avoid logging lsmod output to the log.
lsmod_output = process.system_output("lsmod", verbose=False)
if linux_modules.parse_lsmod_for_module(lsmod_output, 'sysdig_probe') == {}:
self.log.debug("Loading sysdig kernel module")
process.run('sudo insmod {}/driver/sysdig-probe.ko'.format(self.falcodir))
self.str_variant = self.trace_file
def test(self):
self.log.info("Trace file %s", self.trace_file)
# Run the provided trace file though falco
cmd = '{}/userspace/falco/falco -r {}/../rules/falco_rules.yaml -c {}/../falco.yaml -e {}'.format(
self.falcodir, self.falcodir, self.falcodir, self.trace_file)
self.falco_proc = process.SubProcess(cmd)
res = self.falco_proc.run(timeout=60, sig=9)
if res.exit_status != 0:
self.error("Falco command \"{}\" exited with non-zero return value {}".format(
cmd, res.exit_status))
# Get the number of events detected.
match = re.search('Events detected: (\d+)', res.stdout)
if match is None:
self.fail("Could not find a line 'Events detected: <count>' in falco output")
events_detected = int(match.group(1))
if not self.should_detect and events_detected > 0:
self.fail("Detected {} events when should have detected none".format(events_detected))
if self.should_detect:
if events_detected == 0:
self.fail("Detected {} events when should have detected > 0".format(events_detected))
level_line = '{}: (\d+)'.format(self.detect_level)
match = re.search(level_line, res.stdout)
if match is None:
self.fail("Could not find a line '{}: <count>' in falco output".format(self.detect_level))
events_detected = int(match.group(1))
if not events_detected > 0:
self.fail("Detected {} events at level {} when should have detected > 0".format(events_detected, self.detect_level))
pass
if __name__ == "__main__":
main()