Skip to content

(MODULES-11857) Scaffold OWASP CRS v4 support on EL10 via crs_source enum#2637

Merged
SugatD merged 8 commits into
mainfrom
MODULES-11857
Jul 15, 2026
Merged

(MODULES-11857) Scaffold OWASP CRS v4 support on EL10 via crs_source enum#2637
SugatD merged 8 commits into
mainfrom
MODULES-11857

Conversation

@SugatD

@SugatD SugatD commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Scaffolds OWASP Core Rule Set (CRS) v4 support on EL10, where there is no mod_security_crs package, while preserving the existing package-based behaviour on EL7/8/9. Implements the design locked in the SPIKE MODULES-11852 (air-gapped customer with internal mirrors → mirror-first, no required internet call).

Introduces a crs_source enum on apache::mod::security:

crs_source Behaviour Default for
package install mod_security_crs + per-rule symlinks (v2/v3 layout) — unchanged EL7/8/9
archive fetch CRS v4 tarball via puppet/archive from a configurable crs_archive_source (e.g. an internal mirror) + checksum, extract, wire v4 includes opt-in
path use a pre-staged CRS v4 directory (crs_path), no download opt-in
none engine only, no CRS EL10

Changes

  • manifests/params.ppcrs_source defaults (none on EL10, package elsewhere); archive source/checksum default to undef (user-pinned, no module-shipped version → avoids the CRS version/CVE treadmill).
  • manifests/mod/security.pp — new params + case $crs_source for acquisition; rule activation branches between legacy per-rule symlinks (package) and the v4 include layout (archive/path); fail-fast validation when required inputs are missing. Extract dir is kept outside the purged modsec_dir.
  • templates/mod/security_crs_v4.conf.epp — emits IncludeOptional <dir>/crs-setup.conf + rules/*.conf, auto-loaded via the existing IncludeOptional ${modsec_dir}/*.conf.
  • metadata.json / .fixtures.yml — add puppetlabs/archive dependency.
  • spec/classes/mod/security_spec.rb — cover none/archive/path modes + fail-fast cases.

Validation

  • puppet parser validate, epp validate, puppet-lint, rubocop, metadata_lint: clean
  • Unit specs: 282 examples, 0 failures (all crs_source values, with/without-checksum archive, fail-fast)
  • Acceptance (CI): passes on all EL platforms incl. RedHat-10 / 10-arm (new spec/acceptance/mod_security_crs_v4_spec.rb exercises path + archive)
  • Both modes also validated end-to-end on a RHEL 10.1 VM (apply, idempotency, configtest, SQLi/XSS/LFI → 403)

Known limitation / follow-up

  • v4 tuning params — the CRS tuning parameters (paranoia_level, *_anomaly_threshold, allowed_methods, DOS knobs, …) currently feed only the legacy security_crs.conf (package mode). In archive/path (v4) modes the CRS-shipped crs-setup.conf is used as-is, so those params are not applied. Operators can edit crs-setup.conf directly (preserved by the creates guard). Tracked as follow-up MODULES-11895 — not a blocker for this PR.

CI note

The only red checks are Debian-13, SLES-12, SLES-15 acceptance — pre-existing platform failures (Debian-13 systemd start; SLES missing apache2ctl), unrelated to this change (same set is red on main nightly; this PR does not touch those code paths).

Relates to MODULES-11852 (design SPIKE), MODULES-11851 (engine restore), MODULES-11739 (parent), MODULES-11895 (follow-up).

🤖 Generated with Claude Code

…enum

Add a crs_source enum (package/archive/path/none) to apache::mod::security
so CRS can be deployed on EL10, which has no mod_security_crs package, while
preserving the package-based behaviour on EL7/8/9.

- params.pp: crs_source defaults to none on EL10, package elsewhere; archive
  source/checksum default to undef (user-pinned, no version treadmill).
- security.pp: case $crs_source selects acquisition (package install /
  puppet-archive fetch+extract / pre-staged path / none) and branches rule
  activation between legacy per-rule symlinks (package) and the v4 include
  layout (archive/path). Extract dir kept outside the purged modsec_dir.
- templates/mod/security_crs_v4.conf.epp: emits the v4 crs-setup.conf +
  rules/*.conf includes, auto-loaded via modsec_dir/*.conf.
- metadata.json/.fixtures.yml: add puppetlabs/archive dependency.
- spec: cover none/archive/path modes and fail-fast validation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread metadata.json Outdated
SugatD and others added 5 commits June 30, 2026 11:52
The puppet-archive module is published as puppet/archive (Vox Pupuli), not
puppetlabs/archive, which does not exist on the Forge. The wrong name made
dependency-checker crash in CI and the fixture clone fail. Point both
metadata.json and .fixtures.yml at the correct module/repo.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Latest published puppet/archive is 8.1.0; the dependency-checker requires the
current Forge version to satisfy the declared range. Bump the upper bound to
< 9.0.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Make crs_source => archive work end-to-end:
- Add crs_version param (user-pinned). CRS tarballs unpack to a versioned
  coreruleset-<version>/ dir, so pinning the version makes the extract path
  and includes deterministic. Extract into a base dir (default /usr/share).
- Create the active crs-setup.conf from the shipped crs-setup.conf.example
  via an exec guarded by creates (preserves later user edits).
- Update unit specs for the versioned layout and the new fail-fast on
  missing crs_version.

Resolves the extraction TODO from the initial scaffold.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Covers crs_source => path and archive on EL10 with a self-contained,
internet-free CRS fixture (built on the target) that also stands in for an
internal mirror. Asserts idempotent apply, the v4 include wiring, that
crs-setup.conf is created from the example in archive mode, and that
apachectl configtest passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Archive mode passed checksum_type unconditionally, so with no crs_archive_checksum
puppet/archive verified against an empty expected checksum and failed
("Download file checksum mismatch (expected: ...)"). A trusted internal mirror
may legitimately be used without a checksum. Set checksum_verify only when a
checksum is supplied. Caught by the new EL10 acceptance test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@SugatD SugatD marked this pull request as ready for review July 9, 2026 11:11
@SugatD SugatD requested review from a team, bastelfreak, ekohl and smortex as code owners July 9, 2026 11:11
@SugatD

SugatD commented Jul 10, 2026

Copy link
Copy Markdown
Contributor Author

Acceptance tests now pass on all Enterprise Linux platforms (RedHat-7/8/9/10 + 10-arm, Rocky, CentOS), including the new spec/acceptance/mod_security_crs_v4_spec.rb which exercises both crs_source => path and archive on EL10. Both modes were also validated end-to-end on a RHEL 10.1 VM (apply, idempotency, apachectl configtest, and SQLi/XSS/LFI requests returning 403).

@kenyon — as requested, holding until acceptance passed; it now does, so this is ready for review.

The only red checks are Debian-13, SLES-12, and SLES-15 acceptance. These are pre-existing, unrelated platform failures (Debian-13 systemd start; SLES missing /usr/sbin/apache2ctl) — the same set is red on main's nightly and this PR does not touch those code paths.

Follow-up captured as MODULES-11895 (wiring the ModSecurity tuning params into the CRS v4 crs-setup.conf) — not a blocker here.

Adds a README usage section with examples for each crs_source mode
(package/archive/path/none) so external users know how to configure
CRS v4 on EL10, including the internal-mirror archive path. REFERENCE.md
was stale and missing the new crs_source/crs_archive_*/crs_version/crs_path
params, so it's regenerated via puppet-strings.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
amitkarsale
amitkarsale previously approved these changes Jul 15, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR scaffolds OWASP Core Rule Set (CRS) v4 support for apache::mod::security on EL10 by introducing a crs_source enum that preserves existing package-based CRS behavior on EL7/8/9 while enabling mirror-first, offline-friendly CRS acquisition on EL10.

Changes:

  • Adds crs_source (package|archive|path|none) plus supporting parameters, with EL10 defaulting to none and other platforms defaulting to package.
  • Implements CRS v4 wiring via IncludeOptional <dir>/crs-setup.conf + rules/*.conf for archive/path modes, and adds puppet/archive as a dependency for archive mode.
  • Expands unit and acceptance coverage for EL10 CRS v4 archive/path modes and fail-fast validation.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
manifests/mod/security.pp Introduces crs_source modes and implements archive/path acquisition + v4 include wiring.
manifests/params.pp Sets platform defaults for crs_source and archive-related params (no module-shipped URL/version).
templates/mod/security_crs_v4.conf.epp New template to load CRS v4 crs-setup.conf and rules/*.conf.
metadata.json Adds puppet/archive dependency for tarball-based CRS acquisition.
.fixtures.yml Adds puppet-archive fixture repo for specs.
spec/classes/mod/security_spec.rb Adds unit coverage for crs_source modes on RedHat 10, including validation cases.
spec/acceptance/mod_security_crs_v4_spec.rb Adds EL10 acceptance coverage for CRS v4 path and archive modes.
README.md Documents crs_source behaviors and provides usage examples for package/archive/path/none.
REFERENCE.md Updates reference docs to include new parameters and EL10 behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread manifests/mod/security.pp
Comment thread spec/acceptance/mod_security_crs_v4_spec.rb
Use exec's array command form for the crs-setup.conf copy to avoid
shell parsing of interpolated crs_path/crs_version, and stop masking
epel-release install failures with `|| true` in the CRS v4 acceptance
test so real EPEL setup errors surface instead of a confusing
downstream mod_security package-not-found failure.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@SugatD SugatD merged commit a2eaff9 into main Jul 15, 2026
22 of 25 checks passed
@SugatD SugatD deleted the MODULES-11857 branch July 15, 2026 18:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants