Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mark some scenarios as specific to SCE #12052

Merged
merged 2 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/bin/bash
# check = sce
# variables = var_nftables_family=inet,var_nftables_table=filter

var_nftables_family="ip"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/bin/bash
# check = sce
# variables = var_nftables_family=inet,var_nftables_table=filter

nft list tables |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/bin/bash
# check = sce
# variables = var_nftables_family=inet,var_nftables_table=filter

var_nftables_family="inet"
Expand Down
4 changes: 4 additions & 0 deletions tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ The header consists of comments (starting by `#`). Possible keys are:
variables (XCCDF Values), use the `variables` key instead. This key is
intended to be used in regression testing of bugs in profiles, it isn't
intended for casual use.
- `check` is a string specifying one of the available check engine types
(`oval`, `sce`, `any`). It specifies for which check engine the scenario should
be executed. The special value `any` means that this scenario works with any
check engine and it's the default behavior that is used if this key isn't provided.
- `remediation` is a string specifying one of the allowed remediation types (eg.
`bash`, `ansible`, `none`). The `none` value means that the tested rule has no
implemented remediation. The `none` value can also be used in case that
Expand Down
28 changes: 25 additions & 3 deletions tests/ssg_test_suite/rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@ def _load_all_tests(self, rule):
return all_tests

def _get_rule_test_content(self, rule):
checks = xml_operations.find_checks_in_rule(self.datastream, self.benchmark_id, rule.id)
all_tests = self._load_all_tests(rule)
scenarios = []
other_content = dict()
Expand All @@ -414,8 +415,8 @@ def _get_rule_test_content(self, rule):
if re.search(scenario_matches_regex, file_name):
scenario = Scenario(file_name, file_content)
scenario.override_profile(self.scenarios_profile)
if scenario.matches_regex_and_platform(
self.scenarios_regex, self.benchmark_cpes):
if scenario.matches_regex_and_check_and_platform(
self.scenarios_regex, checks, self.benchmark_cpes):
scenarios.append(scenario)
else:
other_content[file_name] = file_content
Expand Down Expand Up @@ -532,6 +533,13 @@ def _verify_rule_presence(self, rule_id, script, profiles):


def _check_rule_scenario(self, scenario, remote_rule_dir, rule_id, remediation_available):
if "sce" in scenario.script_params["check"] and not self.test_env.sce_support:
logging.warning(
"Scenario {0} is used for SCE testing but OpenSCAP installed "
"on the back end doesn't support SCE. To test SCE, please "
"install the openscap-engine-sce package on the back end.".format(scenario.script)
)
return
if not _apply_script(
remote_rule_dir, self.test_env, scenario.script):
logging.error("Environment failed to prepare, skipping test")
Expand Down Expand Up @@ -586,6 +594,7 @@ def _parse_parameters(self):
'templates': [],
'packages': [],
'platform': ['multi_platform_all'],
'check': ['any'],
'remediation': ['all'],
'variables': [],
}
Expand Down Expand Up @@ -645,9 +654,22 @@ def matches_platform(self, benchmark_cpes):
self.script)
return False

def matches_regex_and_platform(self, scenarios_regex, benchmark_cpes):
def matches_check(self, rule_checks):
if "any" in self.script_params["check"]:
return True
for check in self.script_params["check"]:
if check in rule_checks:
return True
logging.warning(
"Script %s is not applicable for %s check type" %
(self.script, ", ".join(self.script_params['check'])))
return False


def matches_regex_and_check_and_platform(self, scenarios_regex, checks, benchmark_cpes):
return (
self.matches_regex(scenarios_regex)
and self.matches_check(checks)
and self.matches_platform(benchmark_cpes))


Expand Down
13 changes: 13 additions & 0 deletions tests/ssg_test_suite/test_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import ssg_test_suite
from ssg_test_suite import common
from ssg_test_suite.log import LogHelper


class SavedState(object):
Expand Down Expand Up @@ -62,6 +63,7 @@ def __init__(self, scanning_mode):
self.running_state = None

self.scanning_mode = scanning_mode
self.sce_support = False
self.backend = None
self.ssh_port = None

Expand Down Expand Up @@ -101,6 +103,7 @@ def start(self):
by subsequent procedures.
"""
self.refresh_connection_parameters()
self.check_sce_support()

def refresh_connection_parameters(self):
self.domain_ip = self.get_ip_address()
Expand Down Expand Up @@ -199,6 +202,16 @@ def online_scan(self, args, verbose_path):
def offline_scan(self, args, verbose_path):
raise NotImplementedError()

def check_sce_support(self):
log_file_name = os.path.join(LogHelper.LOG_DIR, "env-preparation.log")
with open(log_file_name, 'a') as log_file:
oscap_output = self.execute_ssh_command("oscap --version", log_file)
sce_regex = r"SCE Version: [\d.]+ \(from libopenscap_sce.so.\d+\)"
for line in oscap_output.splitlines():
if re.match(sce_regex, line):
self.sce_support = True
return


class VMTestEnv(TestEnv):
name = "libvirt-based"
Expand Down
23 changes: 23 additions & 0 deletions tests/ssg_test_suite/xml_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
from ssg.constants import puppet_system as puppet_rem_system
from ssg.constants import anaconda_system as anaconda_rem_system
from ssg.constants import ignition_system as ignition_rem_system
from ssg.constants import oval_namespace, SCE_SYSTEM

CHECK_SYSTEM_URI_TO_TYPE = {
oval_namespace: "oval",
SCE_SYSTEM: "sce",
}

SYSTEM_ATTRIBUTE = {
'bash': bash_rem_system,
Expand Down Expand Up @@ -307,3 +313,20 @@ def find_fix_in_benchmark(datastream, benchmark_id, rule_id, fix_type='bash', lo

fix = rule.find("xccdf-1.2:fix[@system='{0}']".format(system_attribute), PREFIX_TO_NS)
return fix


def find_checks_in_rule(datastream, benchmark_id, rule_id):
"""
Return check types for given rule from benchmark.
"""
checks = set()
rule = find_rule_in_benchmark(datastream, benchmark_id, rule_id)
if rule is None:
return checks
check_els = rule.findall("xccdf-1.2:check", PREFIX_TO_NS)
for check_el in check_els:
system = check_el.get("system")
check = CHECK_SYSTEM_URI_TO_TYPE.get(system, None)
if check is not None:
checks.add(check)
return checks
1 change: 1 addition & 0 deletions tests/unit/ssg_test_suite/data/correct.pass.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# packages = sudo,authselect
# platform = multi_platform_rhel,Fedora
# profiles = xccdf_org.ssgproject.content_profile_cis
# check = oval
# remediation = none
# variables = var_password_pam_remember=5,var_password_pam_remember_control_flag=requisite

Expand Down
8 changes: 8 additions & 0 deletions tests/unit/ssg_test_suite/test_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ def test_scenario():
assert "xccdf_org.ssgproject.content_profile_cis" in \
s.script_params["profiles"]
assert OSCAP_PROFILE_ALL_ID not in s.script_params["profiles"]
assert len(s.script_params["check"]) == 1
assert "oval" in s.script_params["check"]
assert len(s.script_params["remediation"]) == 1
assert "none" in s.script_params["remediation"]
assert len(s.script_params["variables"]) == 2
Expand All @@ -38,6 +40,10 @@ def test_scenario():
assert not s.matches_regex(r"^wrong")
assert s.matches_platform({"cpe:/o:redhat:enterprise_linux:7"})
assert not s.matches_platform({"cpe:/o:debian:debian:8"})
assert s.matches_check({"oval"})
assert not s.matches_check({"sce"})
assert not s.matches_check({"fancy_unsupported_language"})
assert not s.matches_check({})

def test_scenario_defaults():
file_name = "correct_defaults.pass.sh"
Expand All @@ -52,6 +58,8 @@ def test_scenario_defaults():
assert len(s.script_params["packages"]) == 0
assert len(s.script_params["platform"]) == 1
assert "multi_platform_all" in s.script_params["platform"]
assert len(s.script_params["check"]) == 1
assert "any" in s.script_params["check"]
assert len(s.script_params["remediation"]) == 1
assert "all" in s.script_params["remediation"]
assert len(s.script_params["variables"]) == 0
Expand Down
Loading