diff --git a/docs/manual/developer/06_contributing_with_content.md b/docs/manual/developer/06_contributing_with_content.md index e1f5e4f906e..ab5c430c7e9 100644 --- a/docs/manual/developer/06_contributing_with_content.md +++ b/docs/manual/developer/06_contributing_with_content.md @@ -825,6 +825,13 @@ are unique to SCE: it is not necessary. Additionally, OCIL checks, if any is present in the `rule.yml`, are added as a top-level OR-operator `` with the results of this ``. + - `environment`: can be `normal`, `bootc`, `any`. + The default value that is used when this key is not set is `any`. + This key specifies the environment in which the SCE check can run in. + This way you can restrict some SCE checks to run or not run in Image mode. + If set to `bootc`, the SCE check code will be modified to not run outside of the bootable image build process. + If set to `normal`, the SCE check code will be modified to not run during the bootable image build process. + If set to `any`, the SCE check code will not be modified and therefore will run in any environment. For an example of SCE content, consider the check: diff --git a/shared/templates/sebool/sce-bash.template b/shared/templates/sebool/sce-bash.template index 143aedfe1d8..87a442ecbcc 100644 --- a/shared/templates/sebool/sce-bash.template +++ b/shared/templates/sebool/sce-bash.template @@ -1,4 +1,5 @@ #!/usr/bin/env bash +# environment = bootc # check-import = stdout {{% if not SEBOOL_BOOL %}} # check-export = var_{{{ SEBOOLID }}}=var_{{{ SEBOOLID }}} diff --git a/shared/templates/service_disabled/sce-bash.template b/shared/templates/service_disabled/sce-bash.template index 84addf8e8cc..4d86b9fdc99 100644 --- a/shared/templates/service_disabled/sce-bash.template +++ b/shared/templates/service_disabled/sce-bash.template @@ -1,5 +1,6 @@ #!/bin/bash # check-import = stdout +# environment = bootc if [[ $(systemctl is-enabled {{{ DAEMONNAME }}}.service) == "masked" ]] ; then exit "$XCCDF_RESULT_PASS" fi diff --git a/shared/templates/service_enabled/sce-bash.template b/shared/templates/service_enabled/sce-bash.template index 5d33a00d3a6..03254c17170 100644 --- a/shared/templates/service_enabled/sce-bash.template +++ b/shared/templates/service_enabled/sce-bash.template @@ -1,4 +1,5 @@ #!/bin/bash +# environment = bootc # check-import = stdout if [[ $(systemctl is-enabled {{{ DAEMONNAME }}}.service) == "enabled" ]] ; then exit "$XCCDF_RESULT_PASS" diff --git a/shared/templates/socket_disabled/sce-bash.template b/shared/templates/socket_disabled/sce-bash.template index 2b27cd73ba6..3b0cca18f0c 100644 --- a/shared/templates/socket_disabled/sce-bash.template +++ b/shared/templates/socket_disabled/sce-bash.template @@ -1,4 +1,5 @@ #!/bin/bash +# environment = bootc # check-import = stdout if [[ $(systemctl is-enabled {{{ SOCKETNAME }}}.socket) == "masked" ]] ; then exit "$XCCDF_RESULT_PASS" diff --git a/shared/templates/sysctl/sce-bash.template b/shared/templates/sysctl/sce-bash.template index 54a120e983e..352b701f9b0 100644 --- a/shared/templates/sysctl/sce-bash.template +++ b/shared/templates/sysctl/sce-bash.template @@ -1,4 +1,5 @@ #!/usr/bin/env bash +# environment = bootc # check-import = stdout {{% if SYSCTLVAL == "" %}} # check-export = sysctl_{{{ SYSCTLID }}}_value=sysctl_{{{ SYSCTLID }}}_value diff --git a/shared/templates/timer_enabled/sce-bash.template b/shared/templates/timer_enabled/sce-bash.template index 53101b496dd..a09354aa387 100644 --- a/shared/templates/timer_enabled/sce-bash.template +++ b/shared/templates/timer_enabled/sce-bash.template @@ -1,4 +1,5 @@ #!/bin/bash +# environment = bootc # check-import = stdout if [[ $(systemctl is-enabled {{{ TIMERNAME }}}.timer) == "enabled" ]] ; then exit "$XCCDF_RESULT_PASS" diff --git a/ssg/build_sce.py b/ssg/build_sce.py index 110a73f7617..17906a0f560 100644 --- a/ssg/build_sce.py +++ b/ssg/build_sce.py @@ -34,26 +34,34 @@ def load_sce_and_metadata(file_path, local_env_yaml): return load_sce_and_metadata_parsed(raw_content) -def load_sce_and_metadata_parsed(raw_content): +def _process_raw_content_line(line, sce_content, metadata): + found_metadata = False + keywords = ['platform', 'check-import', 'check-export', 'complex-check', 'environment'] + for keyword in keywords: + if not line.startswith('# ' + keyword + ' = '): + continue + found_metadata = True + # Strip off the initial comment marker + _, value = line[2:].split('=', maxsplit=1) + metadata[keyword] = value.strip() + + if not found_metadata: + sce_content.append(line) + + +def _parse_metadata(raw_content): metadata = dict() sce_content = [] - - keywords = ['platform', 'check-import', 'check-export', 'complex-check'] + shebang = "#!/usr/bin/bash" for line in raw_content.split("\n"): - found_metadata = False - for keyword in keywords: - if not line.startswith('# ' + keyword + ' = '): - continue - - found_metadata = True + if line.startswith("#!"): + shebang = line + continue + _process_raw_content_line(line, sce_content, metadata) + return shebang, "\n".join(sce_content), metadata - # Strip off the initial comment marker - _, value = line[2:].split('=', maxsplit=1) - metadata[keyword] = value.strip() - - if not found_metadata: - sce_content.append(line) +def _set_metadata_default_values(metadata): if 'check-export' in metadata: # Special case for the variables exposed to the SCE script: prepend # the OSCAP_VALUE prefix to reference the variable @@ -66,7 +74,42 @@ def load_sce_and_metadata_parsed(raw_content): if 'platform' in metadata: metadata['platform'] = metadata['platform'].split(',') - return "\n".join(sce_content), metadata + if "environment" not in metadata: + metadata["environment"] = "any" + environment_options = ["normal", "bootc", "any"] + if metadata["environment"] not in environment_options: + raise RuntimeError( + "Wrong value of the 'environment' headers: '%s'. It needs to be " + "one of %s" % ( + metadata["environment"], ", ".join(environment_options)) + ) + + +def _modify_sce_with_environment(sce_content, environment): + if environment == "any": + return sce_content + if environment == "bootc": + condition = "(rpm -q --quiet bootc && [ -e /run/.containerenv ])" + if environment == "normal": + condition = "! (rpm -q --quiet bootc && [ -e /run/.containerenv ])" + lines = list(sce_content.split("\n")) + for i in range(len(lines)): + if len(lines[i]) > 0: + lines[i] = (4 * " ") + lines[i] + lines.insert(0, "if " + condition + " ; then") + lines.append("else") + lines.append(" echo \"The SCE check can't run in this environment.\"") + lines.append(" exit \"$XCCDF_RESULT_ERROR\"") + lines.append("fi") + return "\n".join(lines) + + +def load_sce_and_metadata_parsed(raw_content): + shebang, sce_content, metadata = _parse_metadata(raw_content) + _set_metadata_default_values(metadata) + sce_content = _modify_sce_with_environment(sce_content, metadata["environment"]) + sce_content = shebang + "\n" + sce_content + return sce_content, metadata def _check_is_applicable_for_product(metadata, product):