From 0b2d3a1ea0dcc3339f45d61f9cb825e40b5fff9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20=C4=8Cern=C3=BD?= Date: Tue, 17 Dec 2024 17:21:51 +0100 Subject: [PATCH] Introduce 'environment' header key to SCE checks This adds a new mechanism that allow content authors to control the execution of SCE checks depending on environment. They can use the `environment` key to disable running their SCE check during a build of a bootable container image, or on contrary, disable running the SCE check outside of the bootable container image build environment. We need to distinguish generic SCE checks from SCE checks that are meant to be executed only during the "podman build" phase of the bootable containers. We need to have a way to specify that some code is special for this environment. This way, we will prevent using SCE checks that require DBUS or other special SCE checks. Also, it will prevent using SCE checks that are designed only for the bootable containers to be executed in other scenarios. This change depends on this OpenSCAP PR: https://github.com/OpenSCAP/openscap/pull/2189 --- .../developer/06_contributing_with_content.md | 7 ++++ shared/templates/sebool/sce-bash.template | 1 + .../service_disabled/sce-bash.template | 1 + .../service_enabled/sce-bash.template | 1 + .../socket_disabled/sce-bash.template | 1 + shared/templates/sysctl/sce-bash.template | 1 + .../templates/timer_enabled/sce-bash.template | 1 + ssg/build_sce.py | 35 ++++++++++++++++++- 8 files changed, 47 insertions(+), 1 deletion(-) diff --git a/docs/manual/developer/06_contributing_with_content.md b/docs/manual/developer/06_contributing_with_content.md index e1f5e4f906e..11af2c115d5 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 `normal`. + 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..b8fc73703c1 100644 --- a/ssg/build_sce.py +++ b/ssg/build_sce.py @@ -34,12 +34,33 @@ def load_sce_and_metadata(file_path, local_env_yaml): return load_sce_and_metadata_parsed(raw_content) +def _modify_sce_with_environment(sce_content, environment): + if environment == "any": + return + if environment == "bootc": + condition = "\"$OSCAP_BOOTC_BUILD\" == \"YES\"" + if environment == "normal": + condition = "\"$OSCAP_BOOTC_BUILD\" != \"YES\"" + for i in range(len(sce_content)): + if len(sce_content[i]) > 0: + sce_content[i] = (4 * " ") + sce_content[i] + sce_content.insert(0, "if [[ " + condition + " ]] ; then") + sce_content.append("else") + sce_content.append(" echo \"The SCE check can't run in this environment.\"") + sce_content.append(" exit \"$XCCDF_RESULT_ERROR\"") + sce_content.append("fi") + + def load_sce_and_metadata_parsed(raw_content): metadata = dict() sce_content = [] - keywords = ['platform', 'check-import', 'check-export', 'complex-check'] + keywords = ['platform', 'check-import', 'check-export', 'complex-check', 'environment'] + shebang = "#!/usr/bin/bash" for line in raw_content.split("\n"): + if line.startswith("#!"): + shebang = line + continue found_metadata = False for keyword in keywords: if not line.startswith('# ' + keyword + ' = '): @@ -66,6 +87,18 @@ def load_sce_and_metadata_parsed(raw_content): if 'platform' in metadata: metadata['platform'] = metadata['platform'].split(',') + if "environment" not in metadata: + metadata["environment"] = "normal" + 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)) + ) + + _modify_sce_with_environment(sce_content, metadata["environment"]) + sce_content.insert(0, shebang) return "\n".join(sce_content), metadata