Skip to content

Add NIST 800-53 Rev 5 control framework with OSCAL metadata and CIS mappings#14640

Draft
ggbecker wants to merge 2 commits intoComplianceAsCode:masterfrom
ggbecker:nist-800-53-control-final
Draft

Add NIST 800-53 Rev 5 control framework with OSCAL metadata and CIS mappings#14640
ggbecker wants to merge 2 commits intoComplianceAsCode:masterfrom
ggbecker:nist-800-53-control-final

Conversation

@ggbecker
Copy link
Copy Markdown
Member

Description:

  • Implement split-by-family control file architecture for NIST 800-53 Revision 5, replacing the monolithic control file format with modular family files. Each control includes enriched OSCAL metadata (description, parameters, guidance, related controls) extracted from the official NIST catalog.

Control File Structure:

  • Split 1,196 NIST controls into 21 family files (AC, AU, CM, IA, SC, etc.)
  • controls/nist_800_53.yml: Metadata file with controls_dir pointer
  • controls/nist_800_53/*.yml: Family files for human editing
  • shared/references/controls/nist_800_53_cis_reference/: Reference files for weekly sync

OSCAL Metadata Enhancement:

  • description: Full control statements with sub-parts (a, b, c...)
  • parameters: Organization-Defined Parameters (ODPs) with labels and guidelines
  • guidance: Implementation advice text (500-2000+ characters per control)
  • related_controls: Control dependency references
  • Jinja2 syntax escaped ({{ → [[) to prevent macro expansion conflicts

CIS Integration:

  • Automated NIST→CIS mappings from CIS benchmark references
  • Inverted index: NIST controls populated with CIS rule selections
  • Product guards: {{% if product.startswith('rhel') %}} for family-based filtering
  • Unmapped CIS items in other.yml family (102 rules without NIST mappings)
  • Variable assignments preserved with values (var_x=value format)

Synchronization Workflow:

  • Weekly GitHub Actions workflow (.github/workflows/cis-nist-sync.yml)
  • Automated OSCAL catalog download and extraction (sync_nist_split.py)
  • CIS control file scanning for rule/variable mappings
  • Product guard generation for RHEL family (rhel8, rhel9, rhel10)
  • Profile comparison to verify CIS coverage (compare_profile_rules.py)
  • Automatic PR creation with diff summary on changes

Scripts and Utilities:

  • sync_nist_split.py: Generate split control files with OSCAL metadata
  • harvest_cis_nist_mappings.py: Extract CIS→NIST mappings from benchmarks
  • generate_product_family_guards.py: Apply Jinja2 product guards
  • generate_variable_to_products.py: Build variable→products mapping
  • generate_cis_nist_workflow.sh: Complete workflow orchestration
  • compare_profile_rules.py: Validate CIS profile completeness

Build System Updates:

  • ssg/controls.py: Add OSCAL fields to allowed keys (parameters, guidance, related_controls)
  • Backward compatible: New fields loaded but not required for processing
  • Profiles use nist_800_53:all to reference control files directly

Testing:

  • Verified RHEL 9 datastream builds successfully
  • Profile comparisons show exact CIS coverage
  • Weekly sync prevents drift between reference and real control files

Review Hints:

  • Run the utils/nist/test_workflow_local.sh script

@ggbecker ggbecker added this to the 0.1.81 milestone Apr 10, 2026
@openshift-ci
Copy link
Copy Markdown

openshift-ci bot commented Apr 10, 2026

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Used by openshift-ci bot. label Apr 10, 2026
Implement infrastructure for NIST 800-53 Rev 5 split-by-family control files
with OSCAL metadata enrichment and automated CIS benchmark integration.

Build System Updates:
- ssg/controls.py: Add OSCAL fields to allowed keys
  - parameters: Organization-Defined Parameters (ODPs)
  - guidance: Implementation advice text
  - related_controls: Control dependency references
  - Backward compatible: New fields loaded but not required for processing

Synchronization Scripts:
- sync_nist_split.py: Generate split control files from OSCAL catalog
  - Extracts control metadata (description, parameters, guidance, related_controls)
  - Inverts CIS→NIST mappings to populate rule selections
  - Escapes Jinja2 syntax in OSCAL text ({{ → [[)
  - Outputs 21 family files + metadata file

- harvest_cis_nist_mappings.py: Extract CIS→NIST mappings from benchmarks
- generate_product_family_guards.py: Apply Jinja2 product guards
- generate_variable_to_products.py: Build variable→products mapping
- download_oscal.py: Download NIST OSCAL catalog JSON
- compare_profile_rules.py: Validate CIS profile coverage
- generate_nist_based_cis_profile.py: Generate CIS-NIST profiles
- generate_cis_nist_workflow.sh: Master workflow orchestration

Automation Workflow:
- .github/workflows/cis-nist-sync.yml: Weekly automation
  - Runs Sundays at 2 PM UTC
  - Downloads latest NIST OSCAL catalog
  - Regenerates reference control files
  - Applies product guards for RHEL family
  - Creates PR when changes detected

Documentation:
- controls/README_nist_800_53.md: Comprehensive guide for control files
  - Split-by-family architecture explained
  - OSCAL metadata documentation
  - Manual review process for automated PRs
  - Example scenarios and troubleshooting

- utils/nist_sync/README.md: Toolkit documentation
  - Script usage and workflows
  - Local development guide
  - Integration with CI/CD

Architecture:
- Split-by-family: 21 family files (AC, AU, CM, etc.) instead of monolithic
- OSCAL metadata: Enriched controls with official NIST documentation
- Product guards: Jinja2 conditionals for RHEL family (rhel8, rhel9, rhel10)
- Two file sets: Real files (human-edited) + Reference files (auto-generated)

Testing:
- Verified RHEL 9 datastream builds successfully
- Profile comparisons show exact CIS coverage
- Build system ignores new OSCAL fields (backward compatible)
Add 1,196 NIST 800-53 Revision 5 controls split into 21 family files with
enriched OSCAL metadata and automated CIS benchmark rule mappings.

Control File Structure:
- controls/nist_800_53.yml: Top-level metadata (15 lines, points to subdirectory)
- controls/nist_800_53/*.yml: 21 family files for human editing
  - ac.yml: Access Control (147 controls)
  - au.yml: Audit and Accountability (69 controls)
  - cm.yml: Configuration Management (66 controls)
  - ia.yml: Identification and Authentication (74 controls)
  - sc.yml: System and Communications Protection (162 controls)
  - si.yml: System and Information Integrity (119 controls)
  - other.yml: Unmapped CIS items (102 items)
  - 14 additional families (AT, CA, CP, IR, MA, MP, PE, PL, PM, PS, PT, RA, SA, SR)

- shared/references/controls/nist_800_53_cis_reference.yml: Reference metadata
- shared/references/controls/nist_800_53_cis_reference/*.yml: 21 reference family files
  - Auto-generated for weekly comparison
  - Same structure as real files
  - Used to detect CIS mapping changes

OSCAL Metadata (extracted from NIST catalog):
- description: Full control statements with sub-parts (a, b, c...)
  - Example AC-2: 12 sub-parts describing account management requirements
- parameters: Organization-Defined Parameters (ODPs)
  - Labels, guidelines, and choices for customization
  - Example AC-2: 10 parameters for account management criteria
- guidance: Implementation advice and discussion
  - 500-3000 characters per control
  - Security best practices and considerations
- related_controls: Control dependency references
  - Example AC-2: 28 related controls (AC-3, AC-5, IA-2, etc.)
- Jinja2 syntax: Escaped as [[ ]] to prevent macro expansion

CIS Integration:
- Automated NIST→CIS mappings from benchmark nist: references
- Inverted index: NIST controls populated with CIS rule selections
- Product guards: {{% if product.startswith('rhel') %}} for family-based filtering
- Variable variants: If/elif blocks for product-specific values
- Unmapped items: 102 CIS rules without NIST mappings in other.yml
- Complete coverage: 525 mapped + 102 unmapped = 627 total CIS items

Product Guards:
- Family-based: {{% if product.startswith('rhel') %}} for all RHEL versions
- Specific: {{% if product == "rhel9" %}} for single product
- Variables: {{% if/elif/endif %}} blocks for product-specific values

File Sizes:
- Real control files: 24KB-180KB per family (~1.5MB total)
- Reference files: Same size distribution
- Metadata overhead: ~3x increase from OSCAL enrichment

Integration:
- Profiles use nist_800_53:all to reference all controls
- Build system loads all 21 family files automatically
- Jinja2 guards evaluated at build time for target product

Testing:
- RHEL 9 datastream builds successfully
- Profile comparisons show exact CIS coverage
- All 1,196 controls have OSCAL metadata
- Product guards syntactically correct
@ggbecker ggbecker force-pushed the nist-800-53-control-final branch from a82094d to ab91dd6 Compare April 11, 2026 00:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do-not-merge/work-in-progress Used by openshift-ci bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant