From 156cedf5df0f307cf42e0021030e78935e364e30 Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Mon, 20 Jul 2026 22:46:37 -0500 Subject: [PATCH 1/6] Add CIS Level 2 hardening playbooks and ansible role requirements Ansible playbooks that apply CIS Level 2 hardening via RedHatOfficial CIS roles for RHEL 9 and RHEL 10. The playbooks override IP forwarding variables to prevent the role from disabling forwarding, which MicroShift OVN-Kubernetes requires for pod networking. The sudo NOPASSWD override preserves passwordless sudo needed by the CI test framework. Co-Authored-By: Claude Opus 4.6 --- test/assets/cis/cis-harden-el10.yml | 16 ++++++++++++++++ test/assets/cis/cis-harden.yml | 13 +++++++++++++ test/assets/cis/cis-requirements-el10.yml | 7 +++++++ test/assets/cis/cis-requirements.yml | 7 +++++++ 4 files changed, 43 insertions(+) create mode 100644 test/assets/cis/cis-harden-el10.yml create mode 100644 test/assets/cis/cis-harden.yml create mode 100644 test/assets/cis/cis-requirements-el10.yml create mode 100644 test/assets/cis/cis-requirements.yml diff --git a/test/assets/cis/cis-harden-el10.yml b/test/assets/cis/cis-harden-el10.yml new file mode 100644 index 0000000000..b70502fbf1 --- /dev/null +++ b/test/assets/cis/cis-harden-el10.yml @@ -0,0 +1,16 @@ +--- +- name: Apply CIS Level 2 hardening + hosts: localhost + connection: local + become: true + roles: + - role: ansible-role-rhel10-cis + vars: + # MicroShift OVN networking requires IP forwarding + sysctl_net_ipv4_ip_forward: false + sysctl_net_ipv4_conf_all_forwarding: false + sysctl_net_ipv4_conf_default_forwarding: false + sysctl_net_ipv6_conf_all_forwarding: false + sysctl_net_ipv6_conf_default_forwarding: false + # CI requires passwordless sudo + sudo_remove_nopasswd: false diff --git a/test/assets/cis/cis-harden.yml b/test/assets/cis/cis-harden.yml new file mode 100644 index 0000000000..7c6f050b1e --- /dev/null +++ b/test/assets/cis/cis-harden.yml @@ -0,0 +1,13 @@ +--- +- name: Apply CIS Level 2 hardening + hosts: localhost + connection: local + become: true + roles: + - role: ansible-role-rhel9-cis + vars: + # MicroShift OVN networking requires IP forwarding + sysctl_net_ipv4_ip_forward: false + sysctl_net_ipv6_conf_all_forwarding: false + # CI requires passwordless sudo + sudo_remove_nopasswd: false diff --git a/test/assets/cis/cis-requirements-el10.yml b/test/assets/cis/cis-requirements-el10.yml new file mode 100644 index 0000000000..fd2088ff6c --- /dev/null +++ b/test/assets/cis/cis-requirements-el10.yml @@ -0,0 +1,7 @@ +roles: + - name: ansible-role-rhel10-cis + src: https://github.com/RedHatOfficial/ansible-role-rhel10-cis + version: "0.1.80" +collections: + - community.general + - ansible.posix diff --git a/test/assets/cis/cis-requirements.yml b/test/assets/cis/cis-requirements.yml new file mode 100644 index 0000000000..d7930ad2e0 --- /dev/null +++ b/test/assets/cis/cis-requirements.yml @@ -0,0 +1,7 @@ +roles: + - name: ansible-role-rhel9-cis + src: https://github.com/RedHatOfficial/ansible-role-rhel9-cis + version: "0.1.80" +collections: + - community.general + - ansible.posix From ba58f7b1fb8ec6b445db7e68e8ae6c64eaeb232e Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Mon, 20 Jul 2026 22:47:05 -0500 Subject: [PATCH 2/6] Add CIS Level 2 delta test for MicroShift on RHEL 9 and 10 Test that MicroShift only introduces expected CIS rule changes on a hardened system. The Robot suite runs an OpenSCAP scan before and after installing MicroShift, computes the set difference, and asserts every new failure belongs to a known list of MicroShift-caused rules (IP forwarding, container file ownership, kubelet volume permissions, audit rules for new setuid binaries). This focuses the test on MicroShift's CIS impact rather than overall system compliance. Includes scenario scripts for RHEL 9.8 and RHEL 10.2 that provision a VM, configure repositories, and delegate hardening and scanning to the Robot suite. Co-Authored-By: Claude Opus 4.6 --- .../el10/periodics/el102-src@cis-lvl2.sh | 152 ++++++++++++ .../el9/periodics/el98-src@cis-lvl2.sh | 110 +++++++++ test/suites/cis/validate-cis-lvl2.robot | 218 ++++++++++++++++++ 3 files changed, 480 insertions(+) create mode 100644 test/scenarios-bootc/el10/periodics/el102-src@cis-lvl2.sh create mode 100644 test/scenarios-bootc/el9/periodics/el98-src@cis-lvl2.sh create mode 100644 test/suites/cis/validate-cis-lvl2.robot diff --git a/test/scenarios-bootc/el10/periodics/el102-src@cis-lvl2.sh b/test/scenarios-bootc/el10/periodics/el102-src@cis-lvl2.sh new file mode 100644 index 0000000000..3e42a53f66 --- /dev/null +++ b/test/scenarios-bootc/el10/periodics/el102-src@cis-lvl2.sh @@ -0,0 +1,152 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +# CIS hardening runs inside the Robot suite and takes ~20 minutes +TEST_EXECUTION_TIMEOUT=60m + +# The RPM-based image used to create the VM for this test does not +# include MicroShift or greenboot, so tell the framework not to wait +# for greenboot to finish when creating the VM. +export SKIP_GREENBOOT=true + +configure_microshift_mirror() { + local -r repo=$1 + + if [[ -z "${repo}" ]] ; then + return + fi + + if [[ ! "${repo}" =~ ^http ]]; then + return + fi + + local -r tmp_file=$(mktemp) + tee "${tmp_file}" >/dev/null </dev/null </dev/null </dev/null </dev/null </dev/null </dev/null < 0 + Fail MicroShift introduced unexpected CIS failures: ${unexpected} + END + +Setup Smoke Test + [Documentation] Create hello-microshift pod and expose via route + ${ns}= Create Unique Namespace + VAR ${NAMESPACE}= ${ns} scope=TEST + Create Hello MicroShift Pod + Expose Hello MicroShift + Oc Expose svc hello-microshift --hostname hello-microshift.cluster.local -n ${NAMESPACE} + +Teardown Smoke Test + [Documentation] Clean up smoke test resources + Run Keyword And Ignore Error Oc Delete route/hello-microshift -n ${NAMESPACE} + Run Keyword And Ignore Error Delete Hello MicroShift Pod And Service + Run Keyword And Ignore Error Remove Namespace ${NAMESPACE} From eaed9eed01ea3c3063275bcc2d56530e77129fd2 Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Mon, 20 Jul 2026 22:47:23 -0500 Subject: [PATCH 3/6] Add CIS Level 2 hardening guide for MicroShift User-facing documentation describing which CIS rules MicroShift affects and why: IP forwarding for OVN-Kubernetes, container file ownership from non-host UIDs/GIDs, kubelet volume permissions, and audit rules for new setuid binaries. Includes the required ansible playbook overrides and firewall configuration. Co-Authored-By: Claude Opus 4.6 --- docs/user/README.md | 1 + docs/user/howto_cis_hardening.md | 117 +++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 docs/user/howto_cis_hardening.md diff --git a/docs/user/README.md b/docs/user/README.md index fb004b73ef..6ac76eacab 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -10,6 +10,7 @@ List of the documents in alphabetical file name order. - [AMQ Broker on MicroShift](./howto_amq_broker.md) - [Cluster-to-Cluster Connectivity (C2CC)](./howto_c2cc.md) - [Encrypting C2CC Traffic with IPsec](./howto_c2cc_ipsec.md) +- [CIS Level 2 Hardening for MicroShift](./howto_cis_hardening.md) - [MicroShift Configuration](./howto_config.md) - [Firewall Configuration](./howto_firewall.md) - [Gateway API](./howto_gateway_api.md) diff --git a/docs/user/howto_cis_hardening.md b/docs/user/howto_cis_hardening.md new file mode 100644 index 0000000000..4f89830da6 --- /dev/null +++ b/docs/user/howto_cis_hardening.md @@ -0,0 +1,117 @@ +# CIS Level 2 Hardening for MicroShift + +This guide describes how to run MicroShift on a CIS Level 2 hardened RHEL system. It covers which CIS rules MicroShift affects, the required hardening playbook overrides, and how to verify compliance. + +## MicroShift's CIS Impact + +MicroShift introduces changes to a hardened system in three categories. These rules will fail on any system running Kubernetes containers and cannot be avoided without disabling core functionality. + +### IP Forwarding + +OVN-Kubernetes requires IP forwarding for pod networking. MicroShift enables `net.ipv4.ip_forward` and `net.ipv6.conf.all.forwarding` at startup. + +| Rule ID | OS | +|:--------|:---| +| `sysctl_net_ipv4_ip_forward` | RHEL 9, 10 | +| `sysctl_net_ipv6_conf_all_forwarding` | RHEL 9, 10 | +| `sysctl_net_ipv4_conf_all_forwarding` | RHEL 10 | +| `sysctl_net_ipv4_conf_default_forwarding` | RHEL 10 | +| `sysctl_net_ipv6_conf_default_forwarding` | RHEL 10 | + +### Container File Ownership + +Container images contain files owned by UIDs and GIDs that do not exist in the host's `/etc/passwd` and `/etc/group`. These are stored in `/var/lib/containers/storage/overlay/` and are an inherent characteristic of any container runtime. + +| Rule ID | OS | +|:--------|:---| +| `file_permissions_ungroupowned` | RHEL 9 | +| `no_files_unowned_by_user` | RHEL 9 | +| `no_files_or_dirs_ungroupowned` | RHEL 10 | +| `no_files_or_dirs_unowned_by_user` | RHEL 10 | + +### Kubelet Volume Permissions + +Kubelet creates 0777 directories for ConfigMap and EmptyDir volumes so that pods running as any UID can access their projected configuration. It also creates 0666 container termination log files. + +| Rule ID | OS | +|:--------|:---| +| `dir_perms_world_writable_sticky_bits` | RHEL 9, 10 | +| `file_permissions_unauthorized_world_writable` | RHEL 9, 10 | + +### Audit Rules + +CIS requires audit rules for all setuid/setgid binaries. If MicroShift is installed after running the CIS hardening role, the audit rules will not cover binaries added by MicroShift RPMs. + +| Rule ID | OS | +|:--------|:---| +| `audit_rules_privileged_commands` | RHEL 9, 10 | + +This rule can be resolved by regenerating audit rules after installing MicroShift: + +```bash +sudo find / -xdev \( -perm -4000 -o -perm -2000 \) -type f 2>/dev/null | \ + awk '{print "-a always,exit -F path=" $1 " -F perm=x -F auid>=1000 -F auid!=unset -k privileged"}' | \ + sudo tee /etc/audit/rules.d/99-privileged-post-install.rules > /dev/null +sudo augenrules --load +``` + +## Hardening Playbook Overrides + +When using the RedHatOfficial CIS ansible roles, the hardening playbook must override the IP forwarding variables to prevent the role from disabling forwarding before MicroShift starts. + +For RHEL 9: + +```yaml +--- +- name: Apply CIS Level 2 hardening + hosts: localhost + connection: local + become: true + roles: + - role: ansible-role-rhel9-cis + vars: + sysctl_net_ipv4_ip_forward: false + sysctl_net_ipv6_conf_all_forwarding: false +``` + +For RHEL 10, the CIS benchmark adds per-interface forwarding checks: + +```yaml +--- +- name: Apply CIS Level 2 hardening + hosts: localhost + connection: local + become: true + roles: + - role: ansible-role-rhel10-cis + vars: + sysctl_net_ipv4_ip_forward: false + sysctl_net_ipv4_conf_all_forwarding: false + sysctl_net_ipv4_conf_default_forwarding: false + sysctl_net_ipv6_conf_all_forwarding: false + sysctl_net_ipv6_conf_default_forwarding: false +``` + +> Each variable is set to `false` to tell the role **not** to disable forwarding. This does not enable forwarding — MicroShift does that at startup. + +## Firewall Configuration + +CIS hardening enables `firewalld` and locks down all traffic. MicroShift requires several ports and trusted network sources. See [Firewall Configuration](howto_firewall.md) for the full list. + +At minimum, the pod and service networks must be trusted: + +```bash +sudo firewall-cmd --permanent --zone=trusted --add-source=10.42.0.0/16 +sudo firewall-cmd --permanent --zone=trusted --add-source=169.254.169.1 +sudo firewall-cmd --permanent --zone=trusted --add-source=fd01::/48 +sudo firewall-cmd --permanent --zone=public --add-port=6443/tcp +sudo firewall-cmd --reload +``` + +## References + +- [RedHatOfficial ansible-role-rhel9-cis](https://github.com/RedHatOfficial/ansible-role-rhel9-cis) +- [RedHatOfficial ansible-role-rhel10-cis](https://github.com/RedHatOfficial/ansible-role-rhel10-cis) +- [OpenSCAP Project](https://www.open-scap.org/) +- [CIS Benchmarks](https://www.cisecurity.org/cis-benchmarks) +- [Firewall Configuration](howto_firewall.md) From 027f08451a89c0505f099d16f9c4ed9e2cccd025 Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Tue, 21 Jul 2026 08:52:27 -0500 Subject: [PATCH 4/6] Apply CodeRabbit suggestions from PR #7041 - Fix firewall doc wording: commands trust pod network and host-endpoint sources, not service networks (10.43.0.0/16 needs no firewall rules) - Resolve VM architecture on the VM, not the CI runner, for CDN repo URLs Co-Authored-By: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-Authored-By: Claude Opus 4.6 --- docs/user/howto_cis_hardening.md | 2 +- .../el10/periodics/el102-src@cis-lvl2.sh | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/user/howto_cis_hardening.md b/docs/user/howto_cis_hardening.md index 4f89830da6..736018cc83 100644 --- a/docs/user/howto_cis_hardening.md +++ b/docs/user/howto_cis_hardening.md @@ -98,7 +98,7 @@ For RHEL 10, the CIS benchmark adds per-interface forwarding checks: CIS hardening enables `firewalld` and locks down all traffic. MicroShift requires several ports and trusted network sources. See [Firewall Configuration](howto_firewall.md) for the full list. -At minimum, the pod and service networks must be trusted: +At minimum, the pod network and host-endpoint sources must be trusted: ```bash sudo firewall-cmd --permanent --zone=trusted --add-source=10.42.0.0/16 diff --git a/test/scenarios-bootc/el10/periodics/el102-src@cis-lvl2.sh b/test/scenarios-bootc/el10/periodics/el102-src@cis-lvl2.sh index 3e42a53f66..79acf42508 100644 --- a/test/scenarios-bootc/el10/periodics/el102-src@cis-lvl2.sh +++ b/test/scenarios-bootc/el10/periodics/el102-src@cis-lvl2.sh @@ -109,12 +109,12 @@ scenario_create_vms() { # after CIS hardening so the scan reveals what MicroShift changes. local -r source_reponame=$(basename "${LOCAL_REPO}") local -r source_repo_url="${WEB_SERVER_URL}/rpm-repos/${source_reponame}" - local -r arch=$(uname -m) + local -r arch=$(run_command_on_vm host1 "uname -m") - configure_rhocp_repo "${RHOCP_MINOR_Y}" "${MAJOR_VERSION}" "${MINOR_VERSION}" - configure_rhocp_repo "${RHOCP_MINOR_Y_BETA}" "${MAJOR_VERSION}" "${MINOR_VERSION}" - configure_rhocp_repo "${RHOCP_MINOR_Y1}" "${PREVIOUS_MAJOR_VERSION}" "${PREVIOUS_MINOR_VERSION}" - configure_rhocp_repo "${RHOCP_MINOR_Y1_BETA}" "${PREVIOUS_MAJOR_VERSION}" "${PREVIOUS_MINOR_VERSION}" + configure_rhocp_repo "${RHOCP_MINOR_Y}" "${MAJOR_VERSION}" "${MINOR_VERSION}" "${arch}" + configure_rhocp_repo "${RHOCP_MINOR_Y_BETA}" "${MAJOR_VERSION}" "${MINOR_VERSION}" "${arch}" + configure_rhocp_repo "${RHOCP_MINOR_Y1}" "${PREVIOUS_MAJOR_VERSION}" "${PREVIOUS_MINOR_VERSION}" "${arch}" + configure_rhocp_repo "${RHOCP_MINOR_Y1_BETA}" "${PREVIOUS_MAJOR_VERSION}" "${PREVIOUS_MINOR_VERSION}" "${arch}" configure_microshift_mirror "${PREVIOUS_RELEASE_REPO}" run_command_on_vm host1 "sudo subscription-manager release --set 10.2" configure_cdn_repo \ From 3403c0f90680b58a2259e6e3fbbf6b00a2c8bfbc Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Tue, 21 Jul 2026 11:26:31 -0500 Subject: [PATCH 5/6] Fix robocop lint violations in CIS test suite - LEN03: Extract Harden And Scan Baseline keyword to reduce Setup length - VAR11: Rename report_file arg to oscap_report to avoid reserved name - DEPR06: Use VAR instead of Create List for empty list init - MISC09: Replace multi-line IF with inline IF Co-Authored-By: Claude Opus 4.6 --- .../el10/periodics/el102-src@cis-lvl2.sh | 2 + .../el9/periodics/el98-src@cis-lvl2.sh | 2 + test/suites/cis/validate-cis-lvl2.robot | 73 ++++++++++--------- 3 files changed, 43 insertions(+), 34 deletions(-) diff --git a/test/scenarios-bootc/el10/periodics/el102-src@cis-lvl2.sh b/test/scenarios-bootc/el10/periodics/el102-src@cis-lvl2.sh index 79acf42508..835e59f2dc 100644 --- a/test/scenarios-bootc/el10/periodics/el102-src@cis-lvl2.sh +++ b/test/scenarios-bootc/el10/periodics/el102-src@cis-lvl2.sh @@ -3,6 +3,7 @@ # Sourced from scenario.sh and uses functions defined there. # CIS hardening runs inside the Robot suite and takes ~20 minutes +# shellcheck disable=SC2034 # used elsewhere TEST_EXECUTION_TIMEOUT=60m # The RPM-based image used to create the VM for this test does not @@ -143,6 +144,7 @@ scenario_remove_vms() { } scenario_run_tests() { + # shellcheck disable=SC2034 # used elsewhere TEST_RANDOMIZATION=none run_tests host1 \ --variable "SCAP_DS_FILE:/usr/share/xml/scap/ssg/content/ssg-rhel10-ds.xml" \ diff --git a/test/scenarios-bootc/el9/periodics/el98-src@cis-lvl2.sh b/test/scenarios-bootc/el9/periodics/el98-src@cis-lvl2.sh index a3fca3d7b4..3d78f03843 100644 --- a/test/scenarios-bootc/el9/periodics/el98-src@cis-lvl2.sh +++ b/test/scenarios-bootc/el9/periodics/el98-src@cis-lvl2.sh @@ -3,6 +3,7 @@ # Sourced from scenario.sh and uses functions defined there. # CIS hardening runs inside the Robot suite and takes ~20 minutes +# shellcheck disable=SC2034 # used elsewhere TEST_EXECUTION_TIMEOUT=60m # The RPM-based image used to create the VM for this test does not @@ -104,6 +105,7 @@ scenario_remove_vms() { } scenario_run_tests() { + # shellcheck disable=SC2034 # used elsewhere TEST_RANDOMIZATION=none run_tests host1 \ suites/cis/ diff --git a/test/suites/cis/validate-cis-lvl2.robot b/test/suites/cis/validate-cis-lvl2.robot index 12919ee73d..aa6356a963 100644 --- a/test/suites/cis/validate-cis-lvl2.robot +++ b/test/suites/cis/validate-cis-lvl2.robot @@ -19,32 +19,32 @@ Test Tags slow *** Variables *** -${USHIFT_HOST} ${EMPTY} -${USHIFT_USER} ${EMPTY} -${API_PORT} 6443 -${OSCAP_BASELINE_FILE} /tmp/cis-baseline-results.xml -${OSCAP_POST_FILE} /tmp/cis-post-results.xml -${OSCAP_REPORT_FILE} /tmp/cis-post-report.html -${OSCAP_PROFILE} xccdf_org.ssgproject.content_profile_cis -${SCAP_DS_FILE} /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml -${CIS_REQUIREMENTS_FILE} cis-requirements.yml -${CIS_HARDEN_FILE} cis-harden.yml +${USHIFT_HOST} ${EMPTY} +${USHIFT_USER} ${EMPTY} +${API_PORT} 6443 +${OSCAP_BASELINE_FILE} /tmp/cis-baseline-results.xml +${OSCAP_POST_FILE} /tmp/cis-post-results.xml +${OSCAP_REPORT_FILE} /tmp/cis-post-report.html +${OSCAP_PROFILE} xccdf_org.ssgproject.content_profile_cis +${SCAP_DS_FILE} /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml +${CIS_REQUIREMENTS_FILE} cis-requirements.yml +${CIS_HARDEN_FILE} cis-harden.yml # Rules that MicroShift is known to cause. Any new failure outside this # set means MicroShift introduced an unexpected CIS regression. @{KNOWN_MICROSHIFT_RULES} -... sysctl_net_ipv4_ip_forward -... sysctl_net_ipv6_conf_all_forwarding -... sysctl_net_ipv4_conf_all_forwarding -... sysctl_net_ipv4_conf_default_forwarding -... sysctl_net_ipv6_conf_default_forwarding -... file_permissions_ungroupowned -... no_files_unowned_by_user -... no_files_or_dirs_ungroupowned -... no_files_or_dirs_unowned_by_user -... dir_perms_world_writable_sticky_bits -... file_permissions_unauthorized_world_writable -... audit_rules_privileged_commands +... sysctl_net_ipv4_ip_forward +... sysctl_net_ipv6_conf_all_forwarding +... sysctl_net_ipv4_conf_all_forwarding +... sysctl_net_ipv4_conf_default_forwarding +... sysctl_net_ipv6_conf_default_forwarding +... file_permissions_ungroupowned +... no_files_unowned_by_user +... no_files_or_dirs_ungroupowned +... no_files_or_dirs_unowned_by_user +... dir_perms_world_writable_sticky_bits +... file_permissions_unauthorized_world_writable +... audit_rules_privileged_commands *** Test Cases *** @@ -77,14 +77,12 @@ Setup ... run a post-install scan, and prepare for functional tests. Check Required Env Variables Login MicroShift Host - Apply CIS Hardening - Reboot And Reconnect - Run CIS Scan ${OSCAP_BASELINE_FILE} + Harden And Scan Baseline Install And Enable MicroShift Reboot And Reconnect Configure Firewall After Hardening Wait Until Greenboot Health Check Exited - Run CIS Scan ${OSCAP_POST_FILE} report_file=${OSCAP_REPORT_FILE} + Run CIS Scan ${OSCAP_POST_FILE} oscap_report=${OSCAP_REPORT_FILE} Setup Kubeconfig Teardown @@ -100,6 +98,12 @@ Teardown Run Keyword And Ignore Error ... Logout MicroShift Host +Harden And Scan Baseline + [Documentation] Apply CIS hardening, reboot, and run the baseline scan. + Apply CIS Hardening + Reboot And Reconnect + Run CIS Scan ${OSCAP_BASELINE_FILE} + Apply CIS Hardening [Documentation] Install prerequisites, upload assets, and run the CIS hardening playbook Command Should Work dnf install -y openscap-scanner scap-security-guide ansible-core @@ -157,9 +161,9 @@ Configure Firewall Trusted Sources Run CIS Scan [Documentation] Execute the OpenSCAP CIS Level 2 scan and save results. - [Arguments] ${results_file} ${report_file}=${EMPTY} - ${report_arg}= Set Variable If "${report_file}" != "${EMPTY}" - ... --report ${report_file} ${EMPTY} + [Arguments] ${results_file} ${oscap_report}=${EMPTY} + ${report_arg}= Set Variable If "${oscap_report}" != "${EMPTY}" + ... --report ${oscap_report} ${EMPTY} ${stdout} ${stderr} ${rc}= Execute Command ... oscap xccdf eval --profile ${OSCAP_PROFILE} --results ${results_file} ${report_arg} ${SCAP_DS_FILE} ... sudo=True @@ -176,7 +180,10 @@ Get Failing Rule IDs Verify Remote File Exists With Sudo ${results_file} ${stdout} ${stderr} ${rc}= Execute Command ... python3 -c "import xml.etree.ElementTree as ET; ns={'x':'http://checklists.nist.gov/xccdf/1.2'}; tree=ET.parse('${results_file}'); rules=[rr.get('idref').replace('xccdf_org.ssgproject.content_rule_','') for rr in tree.findall('.//x:rule-result',ns) if rr.find('x:result',ns).text=='fail']; print('\\n'.join(sorted(rules)))" - ... sudo=True return_rc=True return_stdout=True return_stderr=True + ... sudo=True + ... return_rc=True + ... return_stdout=True + ... return_stderr=True Should Be Equal As Integers ${rc} 0 msg=Failed to parse results: ${stderr} @{rules}= Split String ${stdout.strip()} \n RETURN ${rules} @@ -191,12 +198,10 @@ Should Only Contain Expected Rules [Documentation] Assert every rule in the delta is in the known MicroShift set. ... Logs each unexpected rule and fails if any exist. [Arguments] ${delta} - @{unexpected}= Create List + VAR @{unexpected}= @{EMPTY} FOR ${rule} IN @{delta} ${is_known}= Evaluate $rule in $KNOWN_MICROSHIFT_RULES - IF not ${is_known} - Append To List ${unexpected} ${rule} - END + IF not ${is_known} Append To List ${unexpected} ${rule} END Log Known MicroShift rules in delta: ${delta} IF len($unexpected) > 0 From b943da2ae7c2360a87c14a2fffee65d1ab43efd3 Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Tue, 21 Jul 2026 14:05:35 -0500 Subject: [PATCH 6/6] Address reviewer feedback on CIS hardening docs and test assets Reformat CIS rule tables with per-OS columns, replace duplicated firewall commands with a reference to howto_firewall.md, and rename cis-harden.yml / cis-requirements.yml with -el9 suffix for consistency with the el10 variants. Co-Authored-By: Claude Opus 4.6 --- docs/user/howto_cis_hardening.md | 52 ++++++++----------- .../{cis-harden.yml => cis-harden-el9.yml} | 0 ...uirements.yml => cis-requirements-el9.yml} | 0 test/suites/cis/validate-cis-lvl2.robot | 4 +- 4 files changed, 23 insertions(+), 33 deletions(-) rename test/assets/cis/{cis-harden.yml => cis-harden-el9.yml} (100%) rename test/assets/cis/{cis-requirements.yml => cis-requirements-el9.yml} (100%) diff --git a/docs/user/howto_cis_hardening.md b/docs/user/howto_cis_hardening.md index 736018cc83..36be22be50 100644 --- a/docs/user/howto_cis_hardening.md +++ b/docs/user/howto_cis_hardening.md @@ -10,41 +10,41 @@ MicroShift introduces changes to a hardened system in three categories. These ru OVN-Kubernetes requires IP forwarding for pod networking. MicroShift enables `net.ipv4.ip_forward` and `net.ipv6.conf.all.forwarding` at startup. -| Rule ID | OS | -|:--------|:---| -| `sysctl_net_ipv4_ip_forward` | RHEL 9, 10 | -| `sysctl_net_ipv6_conf_all_forwarding` | RHEL 9, 10 | -| `sysctl_net_ipv4_conf_all_forwarding` | RHEL 10 | -| `sysctl_net_ipv4_conf_default_forwarding` | RHEL 10 | -| `sysctl_net_ipv6_conf_default_forwarding` | RHEL 10 | +| Rule ID | RHEL 9 | RHEL 10 | +|:--------|:------:|:-------:| +| `sysctl_net_ipv4_ip_forward` | x | x | +| `sysctl_net_ipv6_conf_all_forwarding` | x | x | +| `sysctl_net_ipv4_conf_all_forwarding` | | x | +| `sysctl_net_ipv4_conf_default_forwarding` | | x | +| `sysctl_net_ipv6_conf_default_forwarding` | | x | ### Container File Ownership Container images contain files owned by UIDs and GIDs that do not exist in the host's `/etc/passwd` and `/etc/group`. These are stored in `/var/lib/containers/storage/overlay/` and are an inherent characteristic of any container runtime. -| Rule ID | OS | -|:--------|:---| -| `file_permissions_ungroupowned` | RHEL 9 | -| `no_files_unowned_by_user` | RHEL 9 | -| `no_files_or_dirs_ungroupowned` | RHEL 10 | -| `no_files_or_dirs_unowned_by_user` | RHEL 10 | +| Rule ID | RHEL 9 | RHEL 10 | +|:--------|:------:|:-------:| +| `file_permissions_ungroupowned` | x | | +| `no_files_unowned_by_user` | x | | +| `no_files_or_dirs_ungroupowned` | | x | +| `no_files_or_dirs_unowned_by_user` | | x | ### Kubelet Volume Permissions Kubelet creates 0777 directories for ConfigMap and EmptyDir volumes so that pods running as any UID can access their projected configuration. It also creates 0666 container termination log files. -| Rule ID | OS | -|:--------|:---| -| `dir_perms_world_writable_sticky_bits` | RHEL 9, 10 | -| `file_permissions_unauthorized_world_writable` | RHEL 9, 10 | +| Rule ID | RHEL 9 | RHEL 10 | +|:--------|:------:|:-------:| +| `dir_perms_world_writable_sticky_bits` | x | x | +| `file_permissions_unauthorized_world_writable` | x | x | ### Audit Rules CIS requires audit rules for all setuid/setgid binaries. If MicroShift is installed after running the CIS hardening role, the audit rules will not cover binaries added by MicroShift RPMs. -| Rule ID | OS | -|:--------|:---| -| `audit_rules_privileged_commands` | RHEL 9, 10 | +| Rule ID | RHEL 9 | RHEL 10 | +|:--------|:------:|:-------:| +| `audit_rules_privileged_commands` | x | x | This rule can be resolved by regenerating audit rules after installing MicroShift: @@ -96,17 +96,7 @@ For RHEL 10, the CIS benchmark adds per-interface forwarding checks: ## Firewall Configuration -CIS hardening enables `firewalld` and locks down all traffic. MicroShift requires several ports and trusted network sources. See [Firewall Configuration](howto_firewall.md) for the full list. - -At minimum, the pod network and host-endpoint sources must be trusted: - -```bash -sudo firewall-cmd --permanent --zone=trusted --add-source=10.42.0.0/16 -sudo firewall-cmd --permanent --zone=trusted --add-source=169.254.169.1 -sudo firewall-cmd --permanent --zone=trusted --add-source=fd01::/48 -sudo firewall-cmd --permanent --zone=public --add-port=6443/tcp -sudo firewall-cmd --reload -``` +CIS hardening enables `firewalld` and locks down all traffic. MicroShift requires several ports and trusted network sources to be opened as described in [Firewall Configuration](howto_firewall.md). ## References diff --git a/test/assets/cis/cis-harden.yml b/test/assets/cis/cis-harden-el9.yml similarity index 100% rename from test/assets/cis/cis-harden.yml rename to test/assets/cis/cis-harden-el9.yml diff --git a/test/assets/cis/cis-requirements.yml b/test/assets/cis/cis-requirements-el9.yml similarity index 100% rename from test/assets/cis/cis-requirements.yml rename to test/assets/cis/cis-requirements-el9.yml diff --git a/test/suites/cis/validate-cis-lvl2.robot b/test/suites/cis/validate-cis-lvl2.robot index aa6356a963..5d1c294a74 100644 --- a/test/suites/cis/validate-cis-lvl2.robot +++ b/test/suites/cis/validate-cis-lvl2.robot @@ -27,8 +27,8 @@ ${OSCAP_POST_FILE} /tmp/cis-post-results.xml ${OSCAP_REPORT_FILE} /tmp/cis-post-report.html ${OSCAP_PROFILE} xccdf_org.ssgproject.content_profile_cis ${SCAP_DS_FILE} /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml -${CIS_REQUIREMENTS_FILE} cis-requirements.yml -${CIS_HARDEN_FILE} cis-harden.yml +${CIS_REQUIREMENTS_FILE} cis-requirements-el9.yml +${CIS_HARDEN_FILE} cis-harden-el9.yml # Rules that MicroShift is known to cause. Any new failure outside this # set means MicroShift introduced an unexpected CIS regression.