Skip to content

USHIFT-6973 Add CIS Level2 Smoke Testing#7041

Open
copejon wants to merge 3 commits into
openshift:mainfrom
copejon:ushift-6973-cis-testing
Open

USHIFT-6973 Add CIS Level2 Smoke Testing#7041
copejon wants to merge 3 commits into
openshift:mainfrom
copejon:ushift-6973-cis-testing

Conversation

@copejon

@copejon copejon commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Introduce a periodic CI scenario that installs MicroShift on a
CIS Level 2 hardened system and validates it functions correctly.

The test provisions a VM from the source image-installer ISO,
registers it with subscription-manager, installs OpenSCAP and
Ansible, applies CIS Level 2 hardening via ansible-role-rhel9-cis,
then runs four validation checks: OpenSCAP scan produces a report,
CIS failure count stays within threshold, all pods are running,
and a smoke test route is accessible.

New files:

  • test/scenarios/periodics/el98-src@cis-lvl2.sh
  • test/suites/cis/validate-cis-lvl2.robot
  • test/assets/cis/cis-harden.yml
  • test/assets/cis/cis-requirements.yml
  • test/image-blueprints/layer2-presubmit/group1/rhel98-source.image-installer

The .image-installer marker enables build_images.sh to produce
rhel-9.8-microshift-source.iso, which is required for the liveimg
kickstart pattern (mutable RPM-based system needed for post-boot
CIS.

Summary by CodeRabbit

  • New Features

    • Added an automated CIS Level 2 hardening scenario for RHEL/MicroShift environments.
    • Added OpenSCAP-based compliance validation with configurable failure thresholds.
    • Added post-hardening checks for MicroShift workloads and application route connectivity.
  • Tests

    • Added automated provisioning, hardening, reboot, validation, and cleanup coverage.
    • Added collection of compliance scan reports and results for review.

copejon added 2 commits July 7, 2026 11:53
Signed-off-by: Jonathan H. Cope <jcope@redhat.com>
Introduce a periodic CI scenario that installs MicroShift on a
CIS Level 2 hardened system and validates it functions correctly.

The test provisions a VM from the source image-installer ISO,
registers it with subscription-manager, installs OpenSCAP and
Ansible, applies CIS Level 2 hardening via ansible-role-rhel9-cis,
then runs four validation checks: OpenSCAP scan produces a report,
CIS failure count stays within threshold, all pods are running,
and a smoke test route is accessible.

New files:
- test/scenarios/periodics/el98-src@cis-lvl2.sh
- test/suites/cis/validate-cis-lvl2.robot
- test/assets/cis/cis-harden.yml
- test/assets/cis/cis-requirements.yml
- test/image-blueprints/layer2-presubmit/group1/rhel98-source.image-installer

The .image-installer marker enables build_images.sh to produce
rhel-9.8-microshift-source.iso, which is required for the liveimg
kickstart pattern (mutable RPM-based system needed for post-boot
CIS.
@openshift-ci openshift-ci Bot requested review from agullon and jogeo July 13, 2026 14:10
@openshift-ci

openshift-ci Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: copejon

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jul 13, 2026
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 8f58a4fd-f3b1-4f36-a60f-0b893b708e22

📥 Commits

Reviewing files that changed from the base of the PR and between 5196251 and 6690cdc.

📒 Files selected for processing (1)
  • test/scenarios/periodics/el98-src@cis-lvl2.sh
🚧 Files skipped from review as they are similar to previous changes (1)

Walkthrough

Adds a CIS Level 2 test scenario that provisions a VM, applies the pinned RHEL 9 CIS Ansible role, runs OpenSCAP validation, checks MicroShift readiness and networking, and cleans up test resources and artifacts.

Changes

CIS Level 2 compliance

Layer / File(s) Summary
CIS hardening assets
test/assets/cis/*
Adds pinned Ansible role and collection requirements plus a playbook with CIS-specific variable overrides.
VM scenario orchestration
test/scenarios/periodics/el98-src@cis-lvl2.sh
Adds VM provisioning, hardening execution, completion polling, reboot handling, cleanup, and CIS suite invocation.
CIS and MicroShift validation
test/suites/cis/validate-cis-lvl2.robot
Adds OpenSCAP result validation, pod readiness checks, route smoke testing, setup, teardown, and artifact collection.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Scenario
  participant VM
  participant Ansible
  participant OpenSCAP
  participant MicroShift
  Scenario->>VM: Provision and configure
  Scenario->>Ansible: Run CIS hardening
  Ansible-->>VM: Complete hardening
  Scenario->>OpenSCAP: Run Level 2 scan
  OpenSCAP-->>Scenario: Report and results
  Scenario->>MicroShift: Check pods and route access
  MicroShift-->>Scenario: Return validation status
Loading

Suggested reviewers: jogeo, agullon

🚥 Pre-merge checks | ✅ 13 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Ipv6 And Disconnected Network Test Compatibility ⚠️ Warning IPv6-safe route code, but test setup runs ansible-galaxy against a GitHub role source, so it needs public internet. Vendor/mirror the CIS role and dependencies locally or in an internal mirror, then verify in the IPv6 disconnected CI job.
✅ Passed checks (13 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is specific and matches the main change: adding CIS Level 2 smoke testing for MicroShift.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed No Ginkgo-style test titles were added; the new Robot test names are static and deterministic.
Test Structure And Quality ✅ Passed Not applicable: the PR adds Robot Framework/bash/Ansible tests, not Ginkgo; the new suite uses setup/teardown, bounded waits, and cleanup consistent with repo patterns.
Microshift Test Compatibility ✅ Passed No new Ginkgo tests were added; the new Robot suite uses only namespaces, pods, services, and Route, with no unsupported MicroShift APIs.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No Ginkgo e2e tests were added; the PR only adds shell/Robot assets and no It()/Describe() or SNO-unsafe node assumptions.
Topology-Aware Scheduling Compatibility ✅ Passed PASS: The PR only adds test/scenario assets and an Ansible CIS playbook; no deployment manifests/controllers or node-affinity/replica constraints were introduced.
Ote Binary Stdout Contract ✅ Passed PR only adds CI assets/scripts; no Go main/TestMain/suite setup code or stdout writes in OTE binary process-level code were introduced.
No-Weak-Crypto ✅ Passed Changed files only use ansible/OpenSCAP and a crypto-policies comment; no MD5/SHA1/DES/RC4/3DES/Blowfish/ECB, custom crypto, or secret comparisons found.
Container-Privileges ✅ Passed No added container/K8s manifest enables privileged mode, host namespaces, SYS_ADMIN, or escalation; the smoke-test pod is restricted.
No-Sensitive-Data-In-Logs ✅ Passed No sensitive values are logged: added outputs are status/error text and a CIS playbook log dump, with no passwords, tokens, PII, or real host data printed.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/suites/cis/validate-cis-lvl2.robot`:
- Around line 83-89: Update the grep command in Get CIS Failure Count to run
with sudo=True so the root-owned OSCAP_RESULTS_FILE is readable, and replace “||
echo 0” with “|| true” so zero matches preserve grep’s single 0 output without
causing conversion errors.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 8a8b0b74-4e7f-4bf5-8ca5-67d5fd5b23cf

📥 Commits

Reviewing files that changed from the base of the PR and between c92d95f and 5196251.

📒 Files selected for processing (5)
  • test/assets/cis/cis-harden.yml
  • test/assets/cis/cis-requirements.yml
  • test/image-blueprints/layer2-presubmit/group1/rhel98-source.image-installer
  • test/scenarios/periodics/el98-src@cis-lvl2.sh
  • test/suites/cis/validate-cis-lvl2.robot

Comment on lines +83 to +89
Get CIS Failure Count
[Documentation] Parse the OpenSCAP results XML and count failures
${stdout} ${stderr} ${rc}= Execute Command
... grep -c '<result>fail</result>' ${OSCAP_RESULTS_FILE} || echo 0
... sudo=False return_rc=True return_stdout=True return_stderr=True
${fail_count}= Convert To Integer ${stdout.strip()}
RETURN ${fail_count}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Get CIS Failure Count can produce false negatives and errors on zero failures.

Two issues in the grep command:

  1. sudo=False on a root-owned file: Run CIS Level 2 Scan creates the results file with sudo=True, so it's owned by root. On a CIS-hardened system (restrictive umask), the SSH user likely can't read it. When grep fails, || echo 0 outputs "0" — the test passes with zero failures even if the file was unreadable. The Verify Remote File Exists With Sudo keyword in the prior test case confirms these files require sudo.

  2. || echo 0 duplicates output on zero matches: grep -c already prints "0" and exits 1 when there are no matches. || echo 0 then appends another "0", producing stdout "0\n0". Convert To Integer fails on this, erroring the test in the best-case scenario (zero failures).

🐛 Proposed fix
 Get CIS Failure Count
     [Documentation]    Parse the OpenSCAP results XML and count failures
     ${stdout}    ${stderr}    ${rc}=    Execute Command
-    ...    grep -c '<result>fail</result>' ${OSCAP_RESULTS_FILE} || echo 0
-    ...    sudo=False    return_rc=True    return_stdout=True    return_stderr=True
+    ...    grep -c '<result>fail</result>' ${OSCAP_RESULTS_FILE} || true
+    ...    sudo=True    return_rc=True    return_stdout=True    return_stderr=True
     ${fail_count}=    Convert To Integer    ${stdout.strip()}
     RETURN    ${fail_count}

sudo=True ensures the root-owned file is readable. || true suppresses grep's non-zero exit on zero matches without adding duplicate output — grep -c already prints the count.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Get CIS Failure Count
[Documentation] Parse the OpenSCAP results XML and count failures
${stdout} ${stderr} ${rc}= Execute Command
... grep -c '<result>fail</result>' ${OSCAP_RESULTS_FILE} || echo 0
... sudo=False return_rc=True return_stdout=True return_stderr=True
${fail_count}= Convert To Integer ${stdout.strip()}
RETURN ${fail_count}
Get CIS Failure Count
[Documentation] Parse the OpenSCAP results XML and count failures
${stdout} ${stderr} ${rc}= Execute Command
... grep -c '<result>fail</result>' ${OSCAP_RESULTS_FILE} || true
... sudo=True return_rc=True return_stdout=True return_stderr=True
${fail_count}= Convert To Integer ${stdout.strip()}
RETURN ${fail_count}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/suites/cis/validate-cis-lvl2.robot` around lines 83 - 89, Update the
grep command in Get CIS Failure Count to run with sudo=True so the root-owned
OSCAP_RESULTS_FILE is readable, and replace “|| echo 0” with “|| true” so zero
matches preserve grep’s single 0 output without causing conversion errors.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should avoid creation of another ISO just for this test.
If we need RPM host, please follow the existing pattern of RPM scenarios

Comment on lines +24 to +27
run_command_on_vm host1 "sudo reboot" || true
sleep 10
local -r ip=$(get_vm_property host1 ip)
wait_for_ssh "${ip}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not reliable because we do not guarantee the host / ssh would go down in 10s.
Consider doing reboot in RF code where we have reliable sequences checking boot id.
Alternatively, check for some other scenarios for reboots.

@@ -0,0 +1,7 @@
roles:
- name: ansible-role-rhel9-cis
src: https://github.com/RedHatOfficial/ansible-role-rhel9-cis

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, create another set of tests for RHEL 10.
https://github.com/RedHatOfficial/ansible-role-rhel10-cis

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 note that this is going to require an additional iso. CIS hardening can't effectively be deployed against a bootc image. The blocker is that the playbook is written under the assumption of a mutable system and expects changes to persist across reboots. It wouldn't make sense to mutate the playbook (I tried) to fit the tests because it's likely to change over time. Another alternative I tried was to split the hardening process across build and runtime environs, but again that requires customizing the playbook, including reimplementing portions of it as in the scenario script. It's brittle, complex, and not maintainable.

@ggiguash ggiguash self-assigned this Jul 13, 2026
Switch the CIS scenario to use the existing rhel-9.8-microshift-source-isolated
ISO instead of building a dedicated rhel-9.8-microshift-source ISO. The isolated
ISO is already built for other periodic scenarios and is a functional superset.

Run the CIS hardening playbook detached (nohup) because update-crypto-policies
restarts sshd mid-run, killing the SSH session. Poll for PLAY RECAP in the log
to detect completion and check for failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@openshift-ci

openshift-ci Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

@copejon: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-aws-tests-bootc-el10 6690cdc link true /test e2e-aws-tests-bootc-el10

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants