diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d657a68e80..19da6596c8 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -54,6 +54,6 @@ jobs: make all - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d97186721..3304cddf72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -330,6 +330,7 @@ cmake_dependent_option(ENABLE_OSCAP_UTIL_AS_RPM "enable the scap-as-rpm utility, cmake_dependent_option(ENABLE_OSCAP_UTIL_SSH "enables the oscap-ssh utility, this lets you scan remote machines over ssh" ON "NOT WIN32" OFF) cmake_dependent_option(ENABLE_OSCAP_UTIL_VM "enables the oscap-vm utility, this lets you scan VMs and VM storage images" ON "NOT WIN32" OFF) cmake_dependent_option(ENABLE_OSCAP_UTIL_PODMAN "enables the oscap-podman utility, this lets you scan Podman containers and container images" ON "NOT WIN32" OFF) +cmake_dependent_option(ENABLE_OSCAP_UTIL_BOOTC "enables the oscap-bootc utility, this lets you build hardened bootable container images" ON "NOT WIN32" OFF) cmake_dependent_option(ENABLE_OSCAP_UTIL_CHROOT "enables the oscap-chroot utility, this lets you scan entire chroots using offline scanning" ON "NOT WIN32" OFF) option(ENABLE_OSCAP_UTIL_AUTOTAILOR "enables the autotailor utility that is able to perform command-line tailoring" TRUE) option(ENABLE_OSCAP_REMEDIATE_SERVICE "enables the oscap-remediate service" FALSE) @@ -467,6 +468,7 @@ message(STATUS "scap-as-rpm: ${ENABLE_OSCAP_UTIL_AS_RPM}") message(STATUS "oscap-ssh: ${ENABLE_OSCAP_UTIL_SSH}") message(STATUS "oscap-vm: ${ENABLE_OSCAP_UTIL_VM}") message(STATUS "oscap-podman: ${ENABLE_OSCAP_UTIL_PODMAN}") +message(STATUS "oscap-bootc: ${ENABLE_OSCAP_UTIL_BOOTC}") message(STATUS "oscap-chroot: ${ENABLE_OSCAP_UTIL_CHROOT}") message(STATUS "autotailor: ${ENABLE_OSCAP_UTIL_AUTOTAILOR}") message(STATUS " ") diff --git a/docs/manual/manual.adoc b/docs/manual/manual.adoc index 2391e06a05..82d6096bc6 100644 --- a/docs/manual/manual.adoc +++ b/docs/manual/manual.adoc @@ -1614,6 +1614,7 @@ If OpenSCAP is executed with verbosity level INFO or DEVEL their runtime values * `OSCAP_PROBE_MEMORY_USAGE_RATIO` - maximum memory usage ratio (used/total) for OpenSCAP probes, default: 0.1 * `OSCAP_PROBE_MAX_COLLECTED_ITEMS` - maximal count of collected items by OpenSCAP probe for a single OVAL object evaluation * `OSCAP_PROBE_IGNORE_PATHS` - Skip given paths during evaluation. If multiple paths should be skipped they need to be separated by a colon. The paths should be absolute canonical paths. +* `OSCAP_PREFERRED_ENGINE` - Set a preffered check engine for XCCDF rules. If a rule has multiple checks, the checks for the preffered check engine will be used. Allowed values: `SCE`, `OVAL`. If this variable is set to `SCE` and a rule has both SCE and OVAL checks the SCE check will be used. If this variable is set to `OVAL` and a rule has both SCE and OVAL checks the OVAL check will be used. If this environment variable isn't set, the standard XCCDF mechanism will be used for check selection. Also, OpenSCAP uses `libcurl` library which also can be configured using environment variables. See https://curl.se/libcurl/c/libcurl-env.html[the list of libcurl environment variables]. @@ -1839,6 +1840,43 @@ registry.access.redhat.com/ubi8 latest 3269c37eae33 2 months ago 208 MB Note that the `oscap-podman` command requires root privileges. +=== Building hardened bootable container images using oscap-bootc + +The `oscap-bootc` tool is a convenience script that makes building hardened bootable container images easier. +This tool is designed to be used during the build of the bootable container image. + +Include `oscap-bootc` in your `Containerfile` that will be used to build your bootable container image. +The `Containerfile` first needs to install the `openscap-utils` package which ships the `oscap-bootc` tool. + +Also, SCAP content needs to be installed to the image before `oscap-bootc` will be run. +Although any SCAP content can be consumed by the tool, the SCAP source data streams shipped in `scap-security-guide` are specially cared to be compatible with bootable containers. + +Example `Containerfile`: + +---- +FROM quay.io/centos-bootc/centos-bootc:stream9 + +RUN dnf install -y openscap-utils scap-security-guide + +RUN oscap-bootc --profile stig /usr/share/xml/scap/ssg/content/ssg-cs9-ds.xml +---- + +Once you have your `Containerfile`, execute the image build: + +---- +podman build -t hardened_image . +---- + +The `oscap-bootc` tool installs and removes all packages required by the selected profile to or from the image. +Then, it runs a scan and remediation with the selected profile. +It doesn't use offline scanning. +The configuration files and other content in the image are modified by this process, depending on the used SCAP content. + +The built bootable container image can be then deployed and booted. +After booting the image, the state of the resulting system will be in line with the selected security profile. + +The `oscap-bootc` tool can't be used anywhere else than in a `Containerfile`. + === Scanning of Docker containers and images using oscap-docker The `oscap-docker` is used to scan Docker containers and images. It can diff --git a/openscap.spec b/openscap.spec index edccd6100b..0440b4c689 100644 --- a/openscap.spec +++ b/openscap.spec @@ -88,6 +88,7 @@ Summary: OpenSCAP Utilities Requires: %{name}%{?_isa} = %{epoch}:%{version}-%{release} Requires: rpmdevtools rpm-build Requires: %{name}-scanner%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-engine-sce%{?_isa} = %{epoch}:%{version}-%{release} %description utils The %{name}-utils package contains command-line tools build on top diff --git a/src/OVAL/probes/unix/linux/rpm-helper.c b/src/OVAL/probes/unix/linux/rpm-helper.c index f7e29cc3d2..e31b2b2e0d 100644 --- a/src/OVAL/probes/unix/linux/rpm-helper.c +++ b/src/OVAL/probes/unix/linux/rpm-helper.c @@ -51,3 +51,32 @@ void rpmLibsPreload() const char* rcfiles = ""; rpmReadConfigFiles(rcfiles, NULL); } + +void set_rpm_db_path() +{ + /* + * Fedora >=36 changed the default dbpath in librpm from /var/lib/rpm to /usr/lib/sysimage/rpm. + * See: https://fedoraproject.org/wiki/Changes/RelocateRPMToUsr + * + * Therefore, when running openscap on a Fedora >=36 system scanning another systems (such as RHEL, SLES, Fedora<36) + * openscap's librpm will try to read the rpm db from /usr/lib/sysimage/rpm which doesn't exist and therefore won't work. + * On many systems, /var/lib/rpm is still a symlink to /usr/lib/sysimage/rpm, so using /var/lib/rpm can work there. + * However, on some systems, eg. bootc images, /var/lib/rpm isn't a symlink and doesn't contain the RPM database. + * + * We will first try if the "new" location /usr/lib/sysimage/rpm exists, and use it only if it exists. + * If it doesn't exist, we will fall back to the "old" location /var/lib/rpm. + */ + + struct stat sb; + const char *dbpath; + const char *prefix = getenv("OSCAP_PROBE_ROOT"); + char *path_with_prefix = oscap_path_join(prefix, "/usr/lib/sysimage/rpm"); + if (stat(path_with_prefix, &sb) == 0) { + dbpath = "/usr/lib/sysimage/rpm"; + } else { + dbpath = "/var/lib/rpm"; + } + free(path_with_prefix); + dI("Using %s as rpm database.", dbpath); + rpmPushMacro(NULL, "_dbpath", NULL, dbpath, RMIL_CMDLINE); +} diff --git a/src/OVAL/probes/unix/linux/rpm-helper.h b/src/OVAL/probes/unix/linux/rpm-helper.h index de7b5fe351..d58f6ccaf5 100644 --- a/src/OVAL/probes/unix/linux/rpm-helper.h +++ b/src/OVAL/probes/unix/linux/rpm-helper.h @@ -99,4 +99,7 @@ int rpmVerifyFile(const rpmts ts, const rpmfi fi, */ void rpmLibsPreload(void); +void set_rpm_db_path(void); + + #endif diff --git a/src/OVAL/probes/unix/linux/rpminfo_probe.c b/src/OVAL/probes/unix/linux/rpminfo_probe.c index 46ad1d9719..53f97bd4b4 100644 --- a/src/OVAL/probes/unix/linux/rpminfo_probe.c +++ b/src/OVAL/probes/unix/linux/rpminfo_probe.c @@ -294,17 +294,7 @@ void *rpminfo_probe_init(void) return ((void *)g_rpm); } - /* - * Fedora >=36 changed the default dbpath in librpm from /var/lib/rpm to /usr/lib/sysimage/rpm - * See: https://fedoraproject.org/wiki/Changes/RelocateRPMToUsr - * Therefore, when running openscap on a Fedora >=36 system scanning another systems (such as RHEL, SLES, Fedora<36) - * openscap's librpm will try to read the rpm db from /usr/lib/sysimage/rpm which doesn't exist and therefore won't work. - * In implementing this change, /var/lib/rpm is still a symlink to /usr/lib/sysimage/rpm - * so /var/lib/rpm still works. So /var/lib/rpm is a dbpath that will work on all systems. - * Therefore, set the dbpath to be /var/lib/rpm, allow openscap running on any system to scan any system. - */ - rpmPushMacro(NULL, "_dbpath", NULL, "/var/lib/rpm", RMIL_CMDLINE); - + set_rpm_db_path(); g_rpm->rpmts = rpmtsCreate(); pthread_mutex_init (&(g_rpm->mutex), NULL); diff --git a/src/OVAL/probes/unix/linux/rpmverify_probe.c b/src/OVAL/probes/unix/linux/rpmverify_probe.c index 6a8f4b4992..bf310ea7d7 100644 --- a/src/OVAL/probes/unix/linux/rpmverify_probe.c +++ b/src/OVAL/probes/unix/linux/rpmverify_probe.c @@ -236,16 +236,7 @@ void *rpmverify_probe_init(void) return (NULL); } - /* - * Fedora >=36 changed the default dbpath in librpm from /var/lib/rpm to /usr/lib/sysimage/rpm - * See: https://fedoraproject.org/wiki/Changes/RelocateRPMToUsr - * Therefore, when running openscap on a Fedora >=36 system scanning another systems (such as RHEL, SLES, Fedora<36) - * openscap's librpm will try to read the rpm db from /usr/lib/sysimage/rpm which doesn't exist and therefore won't work. - * In implementing this change, /var/lib/rpm is still a symlink to /usr/lib/sysimage/rpm - * so /var/lib/rpm still works. So /var/lib/rpm is a dbpath that will work on all systems. - * Therefore, set the dbpath to be /var/lib/rpm, allow openscap running on any system to scan any system. - */ - rpmPushMacro(NULL, "_dbpath", NULL, "/var/lib/rpm", RMIL_CMDLINE); + set_rpm_db_path(); struct rpm_probe_global *g_rpm = malloc(sizeof(struct rpm_probe_global)); g_rpm->rpmts = rpmtsCreate(); diff --git a/src/OVAL/probes/unix/linux/rpmverifyfile_probe.c b/src/OVAL/probes/unix/linux/rpmverifyfile_probe.c index 12145c411f..8da310e51b 100644 --- a/src/OVAL/probes/unix/linux/rpmverifyfile_probe.c +++ b/src/OVAL/probes/unix/linux/rpmverifyfile_probe.c @@ -358,16 +358,7 @@ void *rpmverifyfile_probe_init(void) struct rpm_probe_global *g_rpm = malloc(sizeof(struct rpm_probe_global)); - /* - * Fedora >=36 changed the default dbpath in librpm from /var/lib/rpm to /usr/lib/sysimage/rpm - * See: https://fedoraproject.org/wiki/Changes/RelocateRPMToUsr - * Therefore, when running openscap on a Fedora >=36 system scanning another systems (such as RHEL, SLES, Fedora<36) - * openscap's librpm will try to read the rpm db from /usr/lib/sysimage/rpm which doesn't exist and therefore won't work. - * In implementing this change, /var/lib/rpm is still a symlink to /usr/lib/sysimage/rpm - * so /var/lib/rpm still works. So /var/lib/rpm is a dbpath that will work on all systems. - * Therefore, set the dbpath to be /var/lib/rpm, allow openscap running on any system to scan any system. - */ - rpmPushMacro(NULL, "_dbpath", NULL, "/var/lib/rpm", RMIL_CMDLINE); + set_rpm_db_path(); g_rpm->rpmts = rpmtsCreate(); diff --git a/src/OVAL/probes/unix/linux/rpmverifypackage_probe.c b/src/OVAL/probes/unix/linux/rpmverifypackage_probe.c index 90d053aaae..55aae69744 100644 --- a/src/OVAL/probes/unix/linux/rpmverifypackage_probe.c +++ b/src/OVAL/probes/unix/linux/rpmverifypackage_probe.c @@ -354,16 +354,6 @@ void *rpmverifypackage_probe_init(void) return ((void *)g_rpm); } - /* - * Fedora >=36 changed the default dbpath in librpm from /var/lib/rpm to /usr/lib/sysimage/rpm - * See: https://fedoraproject.org/wiki/Changes/RelocateRPMToUsr - * Therefore, when running openscap on a Fedora >=36 system scanning another systems (such as RHEL, SLES, Fedora<36) - * openscap's librpm will try to read the rpm db from /usr/lib/sysimage/rpm which doesn't exist and therefore won't work. - * In implementing this change, /var/lib/rpm is still a symlink to /usr/lib/sysimage/rpm - * so /var/lib/rpm still works. So /var/lib/rpm is a dbpath that will work on all systems. - * Therefore, set the dbpath to be /var/lib/rpm, allow openscap running on any system to scan any system. - */ - rpmPushMacro(NULL, "_dbpath", NULL, "/var/lib/rpm", RMIL_CMDLINE); g_rpm->rpm.rpmts = rpmtsCreate(); @@ -377,6 +367,7 @@ void *rpmverifypackage_probe_init(void) rpmtsSetRootDir(g_rpm->rpm.rpmts, CHROOT_PATH()); } + set_rpm_db_path(); pthread_mutex_init(&(g_rpm->rpm.mutex), NULL); return ((void *)g_rpm); } diff --git a/src/SCE/sce_engine.c b/src/SCE/sce_engine.c index 962e409885..70670975b6 100644 --- a/src/SCE/sce_engine.c +++ b/src/SCE/sce_engine.c @@ -370,6 +370,7 @@ xccdf_test_result_type_t sce_engine_eval_rule(struct xccdf_policy *policy, const struct xccdf_check_import_iterator *check_import_it, void *usr) { + dI("Executing SCE check '%s'", href); struct sce_parameters* parameters = (struct sce_parameters*)usr; const char* xccdf_directory = parameters->xccdf_directory; bool use_sce_wrapper = false; // use osca-run-sce-script ? diff --git a/src/XCCDF_POLICY/xccdf_policy.c b/src/XCCDF_POLICY/xccdf_policy.c index f12b046baf..5ab9b16090 100644 --- a/src/XCCDF_POLICY/xccdf_policy.c +++ b/src/XCCDF_POLICY/xccdf_policy.c @@ -588,6 +588,16 @@ _xccdf_policy_rule_get_applicable_check(struct xccdf_policy *policy, struct xccd struct xccdf_check *check = xccdf_check_iterator_next(candidate_it); if (_xccdf_policy_is_engine_registered(policy, (char *) xccdf_check_get_system(check))) { result = check; + char *preferred_engine = getenv("OSCAP_PREFERRED_ENGINE"); + if (preferred_engine) { + if (strcmp("SCE", preferred_engine) && strcmp("OVAL", preferred_engine)) { + dW("Unknown value of OSCAP_PREFFERED_ENGINE: '%s'. It will be ignored.", preferred_engine); + } + if ((!strcmp("SCE", preferred_engine) && !strcmp("http://open-scap.org/page/SCE", check->system)) || + (!strcmp("OVAL", preferred_engine) && !strcmp("http://oval.mitre.org/XMLSchema/oval-definitions-5", check->system))) { + break; + } + } } else if (strcmp("http://oval.mitre.org/XMLSchema/oval-definitions-5", check->system) == 0) { print_oval_warning = true; } else if (strcmp("http://scap.nist.gov/schema/ocil/2", check->system) == 0) { diff --git a/src/XCCDF_POLICY/xccdf_policy_remediate.c b/src/XCCDF_POLICY/xccdf_policy_remediate.c index 9233913d9c..1dc30720d1 100644 --- a/src/XCCDF_POLICY/xccdf_policy_remediate.c +++ b/src/XCCDF_POLICY/xccdf_policy_remediate.c @@ -68,6 +68,11 @@ struct logvol_cmd { char *size; }; +struct bootc_commands { + struct oscap_list *dnf_install; + struct oscap_list *dnf_remove; +}; + static int _rule_add_info_message(struct xccdf_rule_result *rr, ...) { va_list ap; @@ -464,9 +469,9 @@ static inline int _xccdf_fix_execute(struct xccdf_rule_result *rr, struct xccdf_ int fork_result = fork(); if (fork_result >= 0) { - /* fork succeded */ + /* fork succeeded */ if (fork_result == 0) { - /* Execute fix and forward output to the parrent. */ + /* Execute fix and forward output to the parent. */ close(pipefd[0]); dup2(pipefd[1], fileno(stdout)); dup2(pipefd[1], fileno(stderr)); @@ -478,8 +483,14 @@ static inline int _xccdf_fix_execute(struct xccdf_rule_result *rr, struct xccdf_ NULL }; - char *const envp[2] = { + char *oscap_bootc_build = getenv("OSCAP_BOOTC_BUILD"); + char *oscap_bootc_build_kvarg = NULL; + if (oscap_bootc_build != NULL) { + oscap_bootc_build_kvarg = oscap_sprintf("OSCAP_BOOTC_BUILD=%s", oscap_bootc_build); + } + char *const envp[3] = { "PATH=/bin:/sbin:/usr/bin:/usr/sbin", + oscap_bootc_build_kvarg, NULL }; @@ -1860,6 +1871,144 @@ static int _xccdf_policy_generate_fix_kickstart(struct oscap_list *rules_to_fix, return ret; } +static int _parse_bootc_line(const char *line, struct bootc_commands *cmds) +{ + int ret = 0; + char *dup = strdup(line); + char **words = oscap_split(dup, " "); + enum states { + BOOTC_START, + BOOTC_DNF, + BOOTC_DNF_INSTALL, + BOOTC_DNF_REMOVE, + BOOTC_ERROR + }; + int state = BOOTC_START; + for (unsigned int i = 0; words[i] != NULL; i++) { + char *word = oscap_trim(words[i]); + if (*word == '\0') + continue; + switch (state) { + case BOOTC_START: + if (!strcmp(word, "dnf")) { + state = BOOTC_DNF; + } else { + ret = 1; + oscap_seterr(OSCAP_EFAMILY_OSCAP, "Unsupported command keyword '%s' in command: '%s'", word, line); + goto cleanup; + } + break; + case BOOTC_DNF: + if (!strcmp(word, "install")) { + state = BOOTC_DNF_INSTALL; + } else if (!strcmp(word, "remove")) { + state = BOOTC_DNF_REMOVE; + } else { + ret = 1; + oscap_seterr(OSCAP_EFAMILY_OSCAP, "Unsupported 'dnf' command keyword '%s' in command:'%s'", word, line); + goto cleanup; + } + break; + case BOOTC_DNF_INSTALL: + oscap_list_add(cmds->dnf_install, strdup(word)); + break; + case BOOTC_DNF_REMOVE: + oscap_list_add(cmds->dnf_remove, strdup(word)); + break; + case BOOTC_ERROR: + ret = 1; + oscap_seterr(OSCAP_EFAMILY_OSCAP, "Unexpected string '%s' in command: '%s'", word, line); + goto cleanup; + default: + break; + } + } + +cleanup: + free(words); + free(dup); + return ret; +} + +static int _xccdf_policy_rule_generate_bootc_fix(struct xccdf_policy *policy, struct xccdf_rule *rule, const char *template, struct bootc_commands *cmds) +{ + char *fix_text = NULL; + int ret = _xccdf_policy_rule_get_fix_text(policy, rule, template, &fix_text); + if (fix_text == NULL) { + return ret; + } + char *dup = strdup(fix_text); + char **lines = oscap_split(dup, "\n"); + for (unsigned int i = 0; lines[i] != NULL; i++) { + char *line = lines[i]; + char *trim_line = oscap_trim(strdup(line)); + if (*trim_line != '#' && *trim_line != '\0') { + _parse_bootc_line(trim_line, cmds); + } + free(trim_line); + } + free(lines); + free(dup); + free(fix_text); + return ret; +} + +static int _generate_bootc_dnf(struct bootc_commands *cmds, int output_fd) +{ + struct oscap_iterator *dnf_install_it = oscap_iterator_new(cmds->dnf_install); + if (oscap_iterator_has_more(dnf_install_it)) { + _write_text_to_fd(output_fd, "dnf -y install \\\n"); + while (oscap_iterator_has_more(dnf_install_it)) { + char *package = (char *) oscap_iterator_next(dnf_install_it); + _write_text_to_fd(output_fd, " "); + _write_text_to_fd(output_fd, package); + if (oscap_iterator_has_more(dnf_install_it)) + _write_text_to_fd(output_fd, " \\\n"); + } + _write_text_to_fd(output_fd, "\n\n"); + } + oscap_iterator_free(dnf_install_it); + + struct oscap_iterator *dnf_remove_it = oscap_iterator_new(cmds->dnf_remove); + if (oscap_iterator_has_more(dnf_remove_it)) { + _write_text_to_fd(output_fd, "dnf -y remove \\\n"); + while (oscap_iterator_has_more(dnf_remove_it)) { + char *package = (char *) oscap_iterator_next(dnf_remove_it); + _write_text_to_fd(output_fd, " "); + _write_text_to_fd(output_fd, package); + if (oscap_iterator_has_more(dnf_remove_it)) + _write_text_to_fd(output_fd, " \\\n"); + } + _write_text_to_fd(output_fd, "\n"); + } + oscap_iterator_free(dnf_remove_it); + return 0; +} + +static int _xccdf_policy_generate_fix_bootc(struct oscap_list *rules_to_fix, struct xccdf_policy *policy, const char *sys, int output_fd) +{ + struct bootc_commands cmds = { + .dnf_install = oscap_list_new(), + .dnf_remove = oscap_list_new(), + }; + int ret = 0; + struct oscap_iterator *rules_to_fix_it = oscap_iterator_new(rules_to_fix); + while (oscap_iterator_has_more(rules_to_fix_it)) { + struct xccdf_rule *rule = (struct xccdf_rule *) oscap_iterator_next(rules_to_fix_it); + ret = _xccdf_policy_rule_generate_bootc_fix(policy, rule, sys, &cmds); + if (ret != 0) + break; + } + oscap_iterator_free(rules_to_fix_it); + + _write_text_to_fd(output_fd, "#!/bin/bash\n"); + _generate_bootc_dnf(&cmds, output_fd); + + oscap_list_free(cmds.dnf_install, free); + oscap_list_free(cmds.dnf_remove, free); + return ret; +} + int xccdf_policy_generate_fix(struct xccdf_policy *policy, struct xccdf_result *result, const char *sys, const char *input_file_name, struct oscap_source *tailoring, int output_fd, int raw) { __attribute__nonnull__(policy); @@ -1919,6 +2068,8 @@ int xccdf_policy_generate_fix(struct xccdf_policy *policy, struct xccdf_result * ret = _xccdf_policy_generate_fix_blueprint(rules_to_fix, policy, sys, output_fd); } else if (strcmp(sys, "urn:xccdf:fix:script:kickstart") == 0) { ret = _xccdf_policy_generate_fix_kickstart(rules_to_fix, policy, sys, input_file_name, tailoring, raw, output_fd); + } else if (strcmp(sys, "urn:xccdf:fix:script:bootc") == 0) { + ret = _xccdf_policy_generate_fix_bootc(rules_to_fix, policy, sys, output_fd); } else { ret = _xccdf_policy_generate_fix_other(rules_to_fix, policy, sys, output_fd); } diff --git a/src/common/debug.c b/src/common/debug.c index 30d37845dc..dc56874fb2 100644 --- a/src/common/debug.c +++ b/src/common/debug.c @@ -311,6 +311,7 @@ void oscap_print_env_vars() "OSCAP_PROBE_MEMORY_USAGE_RATIO", "OSCAP_PROBE_MAX_COLLECTED_ITEMS", "OSCAP_PROBE_IGNORE_PATHS", + "OSCAP_PREFERRED_ENGINE", NULL }; dI("Using environment variables:"); diff --git a/tests/API/XCCDF/unittests/CMakeLists.txt b/tests/API/XCCDF/unittests/CMakeLists.txt index 25f6f79689..6b557d0837 100644 --- a/tests/API/XCCDF/unittests/CMakeLists.txt +++ b/tests/API/XCCDF/unittests/CMakeLists.txt @@ -112,3 +112,5 @@ add_oscap_test("test_skip_rule.sh") add_oscap_test("test_no_newline_between_select_elements.sh") add_oscap_test("test_single_line_tailoring.sh") add_oscap_test("test_reference.sh") +add_oscap_test("test_remediation_bootc.sh") +add_oscap_test("test_oscap_bootc_pass_down.sh") diff --git a/tests/API/XCCDF/unittests/test_oscap_bootc_pass_down.ds.xml b/tests/API/XCCDF/unittests/test_oscap_bootc_pass_down.ds.xml new file mode 100644 index 0000000000..660575d55e --- /dev/null +++ b/tests/API/XCCDF/unittests/test_oscap_bootc_pass_down.ds.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + 5.11.1 + 2009-01-12T10:41:00-05:00 + + + + + FAIL + fail + + + + + + + + + + + + + + oval:x:var:1 + + + + + 100 + + + + + + + accepted + 1.0 + + This rule always fails + + if [[ "$OSCAP_BOOTC_BUILD" == "YES" ]] ; then + printf "WE ARE BUILDING BOOTABLE CONTAINER IMAGE NOW" + fi + + + + + + + + diff --git a/tests/API/XCCDF/unittests/test_oscap_bootc_pass_down.sh b/tests/API/XCCDF/unittests/test_oscap_bootc_pass_down.sh new file mode 100755 index 0000000000..09783de1d3 --- /dev/null +++ b/tests/API/XCCDF/unittests/test_oscap_bootc_pass_down.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +. $builddir/tests/test_common.sh + +set -e -o pipefail + +function test_pass_env_var_down() { + stdout=$(mktemp) + stderr=$(mktemp) + result=$(mktemp) + + OSCAP_BOOTC_BUILD=YES $OSCAP xccdf eval --remediate --results "$result" "$srcdir/test_oscap_bootc_pass_down.ds.xml" > "$stdout" 2> "$stderr" || ret=$? + assert_exists 1 '//rule-result/message[text()="WE ARE BUILDING BOOTABLE CONTAINER IMAGE NOW"]' + + rm -rf "$stdout" "$stderr" "$result" +} + +function test_no_env_var() { + stdout=$(mktemp) + stderr=$(mktemp) + result=$(mktemp) + + $OSCAP xccdf eval --remediate --results "$result" "$srcdir/test_oscap_bootc_pass_down.ds.xml" > "$stdout" 2> "$stderr" || ret=$? + assert_exists 0 '//rule-result/message[text()="WE ARE BUILDING BOOTABLE CONTAINER IMAGE NOW"]' + + rm -rf "$stdout" "$stderr" "$result" +} + + +test_pass_env_var_down +test_no_env_var diff --git a/tests/API/XCCDF/unittests/test_remediation_bootc.ds.xml b/tests/API/XCCDF/unittests/test_remediation_bootc.ds.xml new file mode 100644 index 0000000000..6134381d4c --- /dev/null +++ b/tests/API/XCCDF/unittests/test_remediation_bootc.ds.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + 5.11.2 + 2021-02-01T08:07:06+01:00 + + + + + PASS + pass + + + + + + + + + + + + + + oval:org.openscap.www:var:1 + + + + + 100 + + + + + + + accepted + 1.0 + + Common hardening profile + This is a very cool profile + + + + + Rule 1: Install rsyslog package + + dnf install rsyslog + + + + Rule 2: Remove USBGuard + + dnf remove usbguard + + + + Rule 3: Install reboot package + + dnf install reboot + + + + Rule 4: Install podman package + + dnf install podman + + + + + diff --git a/tests/API/XCCDF/unittests/test_remediation_bootc.sh b/tests/API/XCCDF/unittests/test_remediation_bootc.sh new file mode 100755 index 0000000000..cf193e75a5 --- /dev/null +++ b/tests/API/XCCDF/unittests/test_remediation_bootc.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +. $builddir/tests/test_common.sh + +set -e +set -o pipefail + +name=$(basename $0 .sh) +result=$(mktemp) +stderr=$(mktemp) + +echo "Result file = $result" +echo "Stderr file = $stderr" + +$OSCAP xccdf generate fix --fix-type bootc --profile common "$srcdir/test_remediation_bootc.ds.xml" > "$result" 2> "$stderr" +[ -e $stderr ] + +diff -u "$srcdir/test_remediation_bootc_expected_output.sh" "$result" + +rm -rf "$stdout" "$stderr" "$result" diff --git a/tests/API/XCCDF/unittests/test_remediation_bootc_expected_output.sh b/tests/API/XCCDF/unittests/test_remediation_bootc_expected_output.sh new file mode 100644 index 0000000000..57a7ffb3df --- /dev/null +++ b/tests/API/XCCDF/unittests/test_remediation_bootc_expected_output.sh @@ -0,0 +1,8 @@ +#!/bin/bash +dnf -y install \ + rsyslog \ + reboot \ + podman + +dnf -y remove \ + usbguard diff --git a/tests/probes/rpm/rpm_common.sh b/tests/probes/rpm/rpm_common.sh index c8b4661f87..eb96f76d80 100755 --- a/tests/probes/rpm/rpm_common.sh +++ b/tests/probes/rpm/rpm_common.sh @@ -11,10 +11,7 @@ RPMBUILD="${RPMBASE}/build" # Since Fedora 36 RPM database location changed, see # https://fedoraproject.org/wiki/Changes/RelocateRPMToUsr -# However, /var/lib/rpm/ still works as it is a symlink to -# the new path, /usr/lib/sysimage/rpm/, in Fedora >= 36 -# Therefore, always use /var/lib/rpm/ as it always works. -RPMDB_PATH="/var/lib/rpm/" +RPMDB_PATH="/usr/lib/sysimage/rpm/" function rpm_build { require "rpmbuild" || return 255 diff --git a/tests/probes/rpm/rpmverifypackage/rpmverifypackage_common.sh b/tests/probes/rpm/rpmverifypackage/rpmverifypackage_common.sh index c03bd2e169..0ae994ccbc 100755 --- a/tests/probes/rpm/rpmverifypackage/rpmverifypackage_common.sh +++ b/tests/probes/rpm/rpmverifypackage/rpmverifypackage_common.sh @@ -30,7 +30,7 @@ function test_probes_rpmverifypackage { rm -f $RF - $OSCAP oval eval --results $RF $DF + $OSCAP oval eval --verbose INFO --results $RF $DF result=$RF diff --git a/tests/sce/CMakeLists.txt b/tests/sce/CMakeLists.txt index 18c65bc79e..f9d945f0ba 100644 --- a/tests/sce/CMakeLists.txt +++ b/tests/sce/CMakeLists.txt @@ -1,4 +1,5 @@ if(ENABLE_SCE) + add_oscap_test("test_prefer_sce.sh") add_oscap_test("test_sce.sh") add_oscap_test("test_passing_vars.sh") add_oscap_test("test_check_engine_results.sh") diff --git a/tests/sce/test_prefer_sce.ds.xml b/tests/sce/test_prefer_sce.ds.xml new file mode 100644 index 0000000000..e95c666397 --- /dev/null +++ b/tests/sce/test_prefer_sce.ds.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + 5.11.2 + 2021-02-01T08:07:06+01:00 + + + + + OVAL check for rule 1 + pass + + + + + + + + + + + + + + oval:org.openscap.www:var:1 + + + + + 100 + + + + + + + accepted + 1.0 + + Common hardening profile + This is a very cool profile +