Skip to content

Commit

Permalink
Merge branch 'falcosecurity:master' into installer-systemd-cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
happy-dude authored Aug 4, 2022
2 parents 0ee8b11 + a37e225 commit bb382f7
Show file tree
Hide file tree
Showing 36 changed files with 2,209 additions and 1,049 deletions.
438 changes: 380 additions & 58 deletions .circleci/config.yml

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ if(NOT DEFINED FALCO_ETC_DIR)
set(FALCO_ETC_DIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}/falco")
endif()

# This will be used to print the architecture for which Falco is compiled.
set(FALCO_TARGET_ARCH ${CMAKE_SYSTEM_PROCESSOR})

if(NOT DRAIOS_DEBUG_FLAGS)
set(DRAIOS_DEBUG_FLAGS "-D_DEBUG")
endif()
Expand Down
4 changes: 2 additions & 2 deletions cmake/modules/driver.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ else()
# In case you want to test against another driver version (or branch, or commit) just pass the variable -
# ie., `cmake -DDRIVER_VERSION=dev ..`
if(NOT DRIVER_VERSION)
set(DRIVER_VERSION "2.0.0+driver")
set(DRIVER_CHECKSUM "SHA256=e616dfe27f95670a63150339ea2484937c5ce9b7e42d176de86c3f61481ae676")
set(DRIVER_VERSION "b4c198773bf05486e122f6d3f7f63be125242413")
set(DRIVER_CHECKSUM "SHA256=e85fa42a0b58ba21ca7efb38c20ce25207f4816245bdf154e6b9a037a1cce930")
endif()

# cd /path/to/build && cmake /path/to/source
Expand Down
5 changes: 3 additions & 2 deletions cmake/modules/falcosecurity-libs.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ else()
# In case you want to test against another falcosecurity/libs version (or branch, or commit) just pass the variable -
# ie., `cmake -DFALCOSECURITY_LIBS_VERSION=dev ..`
if(NOT FALCOSECURITY_LIBS_VERSION)
set(FALCOSECURITY_LIBS_VERSION "0.7.0")
set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=3adc1620c0e830554a54cdd486158dc2c0c40552e113785b70fbbc99edb7d96f")
set(FALCOSECURITY_LIBS_VERSION "b4c198773bf05486e122f6d3f7f63be125242413")
set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=e85fa42a0b58ba21ca7efb38c20ce25207f4816245bdf154e6b9a037a1cce930")
endif()

# cd /path/to/build && cmake /path/to/source
Expand Down Expand Up @@ -68,6 +68,7 @@ set(BUILD_LIBSCAP_EXAMPLES OFF CACHE BOOL "")
set(USE_BUNDLED_TBB ON CACHE BOOL "")
set(USE_BUNDLED_B64 ON CACHE BOOL "")
set(USE_BUNDLED_JSONCPP ON CACHE BOOL "")
set(USE_BUNDLED_VALIJSON ON CACHE BOOL "")

list(APPEND CMAKE_MODULE_PATH "${FALCOSECURITY_LIBS_SOURCE_DIR}/cmake/modules")

Expand Down
4 changes: 3 additions & 1 deletion falco.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ watch_config_files: true
# time zone, as governed by /etc/localtime.
time_format_iso_8601: false

# Whether to output events in json or text
# If "true", print falco alert messages and rules file
# loading/validation results as json, which allows for easier
# consumption by downstream programs. Default is "false".
json_output: false

# When using json output, whether or not to include the "output" property
Expand Down
1 change: 1 addition & 0 deletions rules/OWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ reviewers:
- fntlnz
- mfdii
- kaizhe
- darryk10
labels:
- area/rules
2 changes: 1 addition & 1 deletion scripts/falco-driver-loader
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ load_bpf_probe_compile() {

load_bpf_probe_download() {
local URL
URL=$(echo "${DRIVERS_REPO}/${DRIVER_VERSION}/${BPF_PROBE_FILENAME}" | sed s/+/%2B/g)
URL=$(echo "${DRIVERS_REPO}/${DRIVER_VERSION}/${ARCH}/${BPF_PROBE_FILENAME}" | sed s/+/%2B/g)

echo "* Trying to download a prebuilt eBPF probe from ${URL}"

Expand Down
103 changes: 77 additions & 26 deletions test/falco_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ def setUp(self):
else:
self.stderr_not_contains = [self.stderr_not_contains]

self.validate_ok = self.params.get('validate_ok', '*', default='')
self.validate_warnings = self.params.get('validate_warnings', '*', default='')
self.validate_errors = self.params.get('validate_errors', '*', default='')

self.exit_status = self.params.get('exit_status', '*', default=0)
self.should_detect = self.params.get('detect', '*', default=False)
self.check_detection_counts = self.params.get('check_detection_counts', '*', default=True)
Expand Down Expand Up @@ -105,6 +109,9 @@ def setUp(self):
if self.validate_rules_file == False:
self.validate_rules_file = []
else:
# Always enable json output when validating rules
# files. Makes parsing errors/warnings easier
self.json_output = True
if not isinstance(self.validate_rules_file, list):
self.validate_rules_file = [self.validate_rules_file]

Expand Down Expand Up @@ -153,13 +160,6 @@ def setUp(self):
detect_counts[key] = value
self.detect_counts = detect_counts

self.rules_warning = self.params.get(
'rules_warning', '*', default=False)
if self.rules_warning == False:
self.rules_warning = set()
else:
self.rules_warning = set(self.rules_warning)

# Maps from rule name to set of evttypes
self.rules_events = self.params.get('rules_events', '*', default=False)
if self.rules_events == False:
Expand Down Expand Up @@ -265,22 +265,6 @@ def tearDown(self):
if self.package != 'None':
self.uninstall_package()

def check_rules_warnings(self, res):

found_warning = set()

for match in re.finditer('Rule ([^:]+): warning \(([^)]+)\):', res.stderr.decode("utf-8")):
rule = match.group(1)
warning = match.group(2)
found_warning.add(rule)

self.log.debug("Expected warning rules: {}".format(self.rules_warning))
self.log.debug("Actual warning rules: {}".format(found_warning))

if found_warning != self.rules_warning:
self.fail("Expected rules with warnings {} does not match actual rules with warnings {}".format(
self.rules_warning, found_warning))

def check_rules_events(self, res):

found_events = {}
Expand Down Expand Up @@ -376,7 +360,68 @@ def check_outputs(self):

return True

def check_json_output(self, res):
def get_validate_json(self, res):
if self.validate_json is None:
# The first line of stdout should be the validation result as json
self.validate_json = json.loads(res.stdout.decode("utf-8").partition('\n')[0])
return self.validate_json

def check_validate_ok(self, res):
if self.validate_ok != '':
vobj = self.get_validate_json(res)
for expected in self.validate_ok:
found = False
for vres in vobj["falco_load_results"]:
if vres["successful"] and os.path.basename(vres["name"]) == expected:
found = True
break
if not found:
self.fail("Validation json did not contain a successful result for file '{}'".format(expected))

def check_validate_warnings(self, res):
if self.validate_warnings != '':
vobj = self.get_validate_json(res)
for warnobj in self.validate_warnings:
found = False
for vres in vobj["falco_load_results"]:
for warning in vres["warnings"]:
if warning["code"] == warnobj["code"]:
if ("message" in warnobj and warning["message"] == warnobj["message"]) or ("message_contains" in warnobj and warnobj["message_contains"] in warning["message"]):
for loc in warning["context"]["locations"]:
if loc["item_type"] == warnobj["item_type"] and loc["item_name"] == warnobj["item_name"]:
found = True
break
if not found:
if "message" in warnobj:
self.fail("Validation json did not contain a warning '{}' for '{}' '{}' with message '{}'".format(
warnobj["code"], warnobj["item_type"], warnobj["item_name"], warnobj["message"]))
else:
self.fail("Validation json did not contain a warning '{}' for '{}' '{}' with message containing '{}'".format(
warnobj["code"], warnobj["item_type"], warnobj["item_name"], warnobj["message_contains"]))

def check_validate_errors(self, res):
if self.validate_errors != '':
vobj = self.get_validate_json(res)
for errobj in self.validate_errors:
found = False
for vres in vobj["falco_load_results"]:
for error in vres["errors"]:
if error["code"] == errobj["code"]:
if ("message" in errobj and error["message"] == errobj["message"]) or ("message_contains" in errobj and errobj["message_contains"] in error["message"]):
for loc in error["context"]["locations"]:
if loc["item_type"] == errobj["item_type"] and loc["item_name"] == errobj["item_name"]:
found = True
break
if not found:
if "message" in errobj:
self.fail("Validation json did not contain a error '{}' for '{}' '{}' with message '{}'".format(
errobj["code"], errobj["item_type"], errobj["item_name"], errobj["message"]))
else:
self.fail("Validation json did not contain a error '{}' for '{}' '{}' with message containing '{}'".format(
errobj["code"], errobj["item_type"], errobj["item_name"], errobj["message_contains"]))


def check_json_event_output(self, res):
if self.json_output:
# Just verify that any lines starting with '{' are valid json objects.
# Doesn't do any deep inspection of the contents.
Expand Down Expand Up @@ -578,6 +623,8 @@ def test(self):
# This sets falco_binary_path as a side-effect.
self.install_package()

self.validate_json = None

trace_arg = self.trace_file

if self.trace_file:
Expand Down Expand Up @@ -644,18 +691,22 @@ def test(self):
self.error("Falco command \"{}\" exited with unexpected return value {} (!= {})".format(
cmd, res.exit_status, self.exit_status))

self.check_validate_ok(res)
self.check_validate_errors(res)
self.check_validate_warnings(res)

# No need to check any outputs if the falco process exited abnormally.
if res.exit_status != 0:
return

self.check_rules_warnings(res)
if len(self.rules_events) > 0:
self.check_rules_events(res)
if len(self.validate_rules_file) == 0 and self.check_detection_counts:
self.check_detections(res)
if len(self.detect_counts) > 0:
self.check_detections_by_rule(res)
self.check_json_output(res)
if not self.validate_rules_file:
self.check_json_event_output(res)
self.check_outputs()
self.check_output_strictly_contains(res)
self.check_grpc()
Expand Down
Loading

0 comments on commit bb382f7

Please sign in to comment.