fix: translate os-release distro IDs to SSG datastream short codes#110
fix: translate os-release distro IDs to SSG datastream short codes#110trevor-vaughan wants to merge 1 commit into
Conversation
✅ CRAP Load Analysis: PASSSummary
Quadrant Distribution
New Functions
|
hbraswelrh
left a comment
There was a problem hiding this comment.
PR Review: #110 — fix: translate os-release distro IDs to SSG datastream short codes
Verdict: APPROVE
Clean, well-tested bug fix. The io.Reader/fs.FS refactoring is the right approach for testability. All aliases are covered by tests. Documentation updated. All CI checks pass. No security, alignment, or constitution concerns.
Highlights
distroAliasesmap centralizes all ID-to-shortcode mappings in one location- Candidate-list approach with priority ordering is clearer and more correct than the previous
filepath.Walkscan - 287 new test lines covering every alias, per-distro parsing, error paths, and edge cases
- Regression test (
TestMatchDatastream_CentOSStream) directly reproduces the original failure scenario - Documentation correctly updated for expanded distro support
Linked Issue Coverage (#91)
| Criterion | Status |
|---|---|
Add centos → cs short-code alias |
COVERED |
Prefer exact-distro match before ID_LIKE fallback |
COVERED |
Unit test with ID="centos" and ssg-cs10-ds.xml fixture |
COVERED |
Surface 100% notapplicable as error/warning |
NOT IN SCOPE (tracked in complyctl#609) |
This review was generated by /review-pr (AI-assisted).
marcusburghardt
left a comment
There was a problem hiding this comment.
Design Concern: Static Alias Table + False-Match Risk on Multi-Datastream Systems
The refactoring to io.Reader/fs.FS interfaces and the candidate-list approach are clean improvements. However, the distroAliases static map has two structural issues that should be addressed before merging.
1. Static coupling to CaC/content naming conventions
CaC/content uses version-dependent short codes for CentOS derivatives (products/rhel8/CMakeLists.txt:32, products/rhel9/CMakeLists.txt:25, ssg/constants.py:512-515):
| RHEL parent | Derivative call | Output datastream |
|---|---|---|
rhel8 |
ssg_build_derivative_product(${PRODUCT} "centos" "centos8") |
ssg-centos8-ds.xml |
rhel9 |
ssg_build_derivative_product(${PRODUCT} "centos" "cs9") |
ssg-cs9-ds.xml |
rhel10 |
ssg_build_derivative_product(${PRODUCT} "centos" "cs10") |
ssg-cs10-ds.xml |
The blanket centos → cs alias assumes this mapping is version-independent, which CaC/content's own history proves false. Every time CaC/content adds or renames a product, this table requires a provider code change and release.
2. False-match risk on multi-datastream systems
Fedora's scap-security-guide package builds with SSG_PRODUCT_DEFAULT=TRUE (CMakeLists.txt:85), shipping all 38+ datastreams (Ubuntu, Debian, SUSE, etc.) in the same directory. On such systems, the ID_LIKE fallback in the candidate search can match an unrelated datastream. For example, a derivative distro with ID_LIKE="fedora" and no SSG content of its own would fall through to ssg-fedora-ds.xml, whose CPE platform check would then zero the scan — exactly the silent failure this PR aims to fix.
The auto-detection mechanism should be precise: better to fail with a clear error (the user can specify variables.datastream manually) than to silently select the wrong datastream.
Most distros need no alias at all
Only ~5 distro families have os-release ID values that differ from their SSG filename short code. The rest match directly:
| Works without alias | Needs alias |
|---|---|
rhel, fedora, debian, ubuntu, ol, almalinux, alinux, anolis, tencentos |
centos→cs (version-dependent), amzn→al, sles/sled→sle, sle-micro→slmicro, opensuse-leap→opensuse |
Suggested direction: CPE-based matching
Each SSG datastream embeds a CPE dictionary (<cpe-item name="cpe:/o:centos:centos:10">) that is the authoritative platform metadata — it's what oscap itself evaluates to determine applicability. Most Linux distros publish a matching CPE_NAME field in /etc/os-release. A hybrid approach could:
- Fast path: Try filename candidates from raw os-release IDs + version (no alias table — covers the majority)
- CPE fallback: If no filename match, parse the CPE dictionary from each
ssg-*-ds.xmland match against the system'sCPE_NAME(the provider already usesantchfx/xmlqueryfor datastream XML parsing inxccdf/datastream.go) - Manual override: The existing
variables.datastreamconfiguration already handles edge cases
This eliminates the alias table, automatically adapts to new CaC/content products, and prevents false matches because CPE comparison is platform-specific rather than filename-heuristic.
This review was generated by /review-pr (AI-assisted).
1785026 to
2ff8d40
Compare
CentOS Stream and other Enterprise Linux variants now correctly detect their SSG datastreams instead of falling back to RHEL or failing with "notapplicable" results. Root cause: the provider built datastream filenames from raw os-release ID values (e.g., "centos" -> ssg-centos-ds.xml), but SSG ships CentOS Stream as ssg-cs10-ds.xml. This caused a lookup miss, falling back to RHEL where every rule returned notapplicable. Solution: replace static distroAliases table with CPE-based matching. Parse CPE_NAME from /etc/os-release, extract CPE items from each SSG datastream's embedded dictionary, and match os-release CPE against datastream CPEs. Returns first matching datastream. Added environment variable overrides for non-standard deployments: - SSG_CONTENT_DIR: override /usr/share/xml/scap/ssg/content location - OS_RELEASE_FILE: override /etc/os-release location Fixes: #91 Assisted-by: Claude Sonnet 4.5 <noreply@anthropic.com> Signed-off-by: Trevor Vaughan <tvaughan@redhat.com>
2ff8d40 to
9a768da
Compare
|
@marcusburghardt I took a whack at a complete refactor based on detecting the CPE values. Overwrite since the old work is to be abandoned. |
CentOS Stream reports ID=centos in os-release, but SSG ships its
datastream as ssg-cs10-ds.xml. The old code built filenames from the
raw ID, so CentOS Stream fell through to the RHEL datastream where
every rule came back notapplicable.
sle-micro/sl-micro→slmicro, opensuse-leap/opensuse-tumbleweed→opensuse,
and amzn→al
their file-bound originals so tests can run without real filesystem
access
fs.ReadDir for clearer priority ordering
missing-field and I/O error paths, and ReadDir failure
Closes #91
Assisted-by: Claude Opus 4.6
Signed-off-by: Trevor Vaughan tvaughan@redhat.com