cem_acpt 0.12.0 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b82bc3c9709dc1486de6675c33508a532f8c036fde480e6fd967e5a2e7dfdae8
4
- data.tar.gz: 4fad921e96175030f521ac21a898ee3488a57b109e309f696980e044efc28123
3
+ metadata.gz: c9db8e060c748eb655248cac9a3a00d67802081d0d63b31f9f3a5daa6385c13f
4
+ data.tar.gz: 365a1e9551b3721869e7b9dc649408f544be47eddc84cccb3b8cf0f0ab025178
5
5
  SHA512:
6
- metadata.gz: b711d5b4ee1cf1f4c712d38b12c68fd3e20939a69e161004b1b2ecc0256838c04473bf089b86e1c78097db848197b6218617cbc31fb53ba52a2bd7dc84910b07
7
- data.tar.gz: bd425c7655b89ce251c32d239b0dd7ac1333d0d17f262e08a8c997b388a065a900f6849404e31fbdd969d3e8042aeb934b276b2b002611c72e190e4094245a83
6
+ metadata.gz: e33957643fc4601962aff311034849f6840972ba8d47860ebabcaef9b42cab1e8cf874aa06be1f0e3743d8511c494a2ec92d57d92f74ef0f3cfa673d08e14b39
7
+ data.tar.gz: 9fadc4795a4b18a1ad889719c69b2962c70c19b54775cebafd00c67f3d876e118913a06267b973d17080942a67937deab2b00bee6bec97b7c36741910fa1e488
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cem_acpt (0.12.0)
4
+ cem_acpt (0.12.1)
5
5
  async-http (>= 0.60, < 0.70)
6
6
  bcrypt_pbkdf (>= 1.0, < 2.0)
7
7
  deep_merge (>= 1.2, < 2.0)
@@ -53,6 +53,9 @@ module CemAcpt
53
53
  benchmarks: {
54
54
  cis_cat: {},
55
55
  },
56
+ datastreams: {
57
+ openscap: {},
58
+ },
56
59
  },
57
60
  ci_mode: false,
58
61
  config_file: nil,
@@ -40,5 +40,14 @@ module CemAcpt
40
40
  super("No benchmark configured for test case '#{test_case}' (scanner: #{scanner}). Set '#{config_key}' in cem_acpt config.")
41
41
  end
42
42
  end
43
+
44
+ # Raised when a test case has no entry in `cem_acpt_scan.datastreams.openscap`
45
+ # and so no datastream path can be resolved. The message carries the missing
46
+ # config key so the operator can fix it without re-running.
47
+ class DatastreamNotFoundError < StandardError
48
+ def initialize(test_case, scanner, config_key)
49
+ super("No datastream configured for test case '#{test_case}' (scanner: #{scanner}). Set '#{config_key}' in cem_acpt config.")
50
+ end
51
+ end
43
52
  end
44
53
  end
@@ -117,11 +117,24 @@ module CemAcpt
117
117
  end
118
118
  end
119
119
 
120
+ datastream = nil
121
+ if scanner == :openscap
122
+ datastreams = @config.get('cem_acpt_scan.datastreams.openscap') || {}
123
+ datastream = datastreams[test_data[:test_name]] || datastreams[test_data[:test_name].to_sym]
124
+ if datastream.nil? || datastream.to_s.empty?
125
+ raise CemAcpt::Scan::DatastreamNotFoundError.new(
126
+ test_data[:test_name], scanner,
127
+ "cem_acpt_scan.datastreams.openscap.#{test_data[:test_name]}"
128
+ )
129
+ end
130
+ end
131
+
120
132
  test_data[:scan] = {
121
- scanner: scanner,
122
- profile: profile,
123
- level: test_data[:level] || test_data['level'],
124
- benchmark: benchmark,
133
+ scanner: scanner,
134
+ profile: profile,
135
+ level: test_data[:level] || test_data['level'],
136
+ benchmark: benchmark,
137
+ datastream: datastream,
125
138
  }
126
139
  end
127
140
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CemAcpt
4
- VERSION = '0.12.0'
4
+ VERSION = '0.12.1'
5
5
  end
@@ -291,7 +291,7 @@ resource "null_resource" "cis_cat_pro_upload" {
291
291
  # `shopt -s dotglob`) up into /opt/cis-cat-pro/.
292
292
  provisioner "remote-exec" {
293
293
  inline = each.value.cis_cat_pro_format == "zip" ? [
294
- "sudo dnf install -y unzip || sudo apt-get install -y unzip",
294
+ "sudo dnf install -y unzip || sudo bash -c 'NEEDRESTART_MODE=a apt-get install -y unzip'",
295
295
  "sudo mkdir -p /opt/cis-cat-pro",
296
296
  "sudo rm -rf /tmp/cis-cat-pro-extract",
297
297
  "sudo unzip -q -o ${each.value.provision_dir_dest}/cis-cat-pro.zip -d /tmp/cis-cat-pro-extract",
@@ -320,7 +320,7 @@ resource "null_resource" "cis_cat_pro_upload" {
320
320
 
321
321
  provisioner "remote-exec" {
322
322
  inline = each.value.cis_cat_pro_license_format == "zip" ? [
323
- "sudo dnf install -y unzip || sudo apt-get install -y unzip",
323
+ "sudo dnf install -y unzip || sudo bash -c 'NEEDRESTART_MODE=a apt-get install -y unzip'",
324
324
  "sudo mkdir -p /opt/cis-cat-pro/license",
325
325
  "sudo unzip -q -o ${each.value.provision_dir_dest}/cis-cat-pro-license.zip -d /opt/cis-cat-pro/license",
326
326
  ] : [
@@ -119,7 +119,7 @@ def perform_scan
119
119
 
120
120
  case cfg['scanner']
121
121
  when 'openscap'
122
- run_openscap(cfg['profile'], cfg['datastream'] || '/usr/share/xml/scap/ssg/content/ssg-rhel8-ds.xml')
122
+ run_openscap(cfg['profile'], cfg['datastream'])
123
123
  when 'ciscat'
124
124
  run_ciscat(cfg['profile'], cfg['benchmark'])
125
125
  else
@@ -0,0 +1,170 @@
1
+ # CEM-6798 — Per-OS OpenSCAP datastream config (required, with DatastreamNotFoundError)
2
+
3
+ ## Summary
4
+
5
+ `scan_post_processing!` in `lib/cem_acpt/test_data.rb` never populates a `datastream` key in
6
+ the `:scan` hash it builds for each OpenSCAP test case. The on-node scan daemon's
7
+ `perform_scan` in `lib/terraform/gcp/linux/scan/scan_service.rb` fills the gap with a
8
+ hardcoded `|| '/usr/share/xml/scap/ssg/content/ssg-rhel8-ds.xml'` fallback, which silently
9
+ uses the wrong datastream on every non-RHEL 8 OS — confirmed when RHEL 9 provisioning failed
10
+ because `ssg-rhel8-ds.xml` does not exist on that OS.
11
+
12
+ Remove the hardcoded fallback. Add a `cem_acpt_scan.datastreams.openscap` config map (keyed
13
+ by test-case name, same pattern as `cem_acpt_scan.profiles.openscap`) and raise a new
14
+ `DatastreamNotFoundError` in `scan_post_processing!` when an OpenSCAP test case has no
15
+ datastream configured. CIS-CAT test cases are unaffected; their `datastream` key remains
16
+ `nil`.
17
+
18
+ ## Goals
19
+
20
+ - OpenSCAP scans receive the correct per-OS datastream file path from operator-supplied config.
21
+ - Misconfiguration is caught before any node is provisioned (early error in `scan_post_processing!`).
22
+ - The `ssg-rhel8-ds.xml` fallback is removed so it can never silently produce wrong scan results on non-RHEL 8 nodes.
23
+
24
+ ## Non-goals
25
+
26
+ - Automatic discovery or lookup of datastream paths by OS family or version at runtime.
27
+ - Changing the on-node `run_openscap` invocation or any OpenSCAP flags.
28
+ - Any changes to the CIS-CAT scan path.
29
+ - Removing the `level` key from `test_data[:scan]` or `scan_config.json`.
30
+
31
+ ## Proposed Design
32
+
33
+ ### `lib/cem_acpt/config/cem_acpt_scan.rb`
34
+
35
+ Add `datastreams: { openscap: {} }` alongside the existing `benchmarks` entry in `defaults`:
36
+
37
+ ```ruby
38
+ # before
39
+ benchmarks: {
40
+ cis_cat: {},
41
+ },
42
+
43
+ # after
44
+ benchmarks: {
45
+ cis_cat: {},
46
+ },
47
+ datastreams: {
48
+ openscap: {},
49
+ },
50
+ ```
51
+
52
+ ### `lib/cem_acpt/scan/errors.rb`
53
+
54
+ Add `DatastreamNotFoundError` following the same shape as `BenchmarkNotFoundError`:
55
+
56
+ ```ruby
57
+ # Raised when a test case has no entry in `cem_acpt_scan.datastreams.openscap`
58
+ # and so no datastream path can be resolved. The message carries the missing
59
+ # config key so the operator can fix it without re-running.
60
+ class DatastreamNotFoundError < StandardError
61
+ def initialize(test_case, scanner, config_key)
62
+ super("No datastream configured for test case '#{test_case}' (scanner: #{scanner}). Set '#{config_key}' in cem_acpt config.")
63
+ end
64
+ end
65
+ ```
66
+
67
+ ### `lib/cem_acpt/test_data.rb` — `scan_post_processing!`
68
+
69
+ After the `benchmark` lookup block (which is already gated to `scanner == :ciscat`), add a
70
+ symmetric `datastream` lookup gated to `scanner == :openscap`. Raise `DatastreamNotFoundError`
71
+ when the mapping is missing or empty. Pass `datastream` as a new key in `test_data[:scan]`.
72
+
73
+ ```ruby
74
+ datastream = nil
75
+ if scanner == :openscap
76
+ datastreams = @config.get('cem_acpt_scan.datastreams.openscap') || {}
77
+ datastream = datastreams[test_data[:test_name]] || datastreams[test_data[:test_name].to_sym]
78
+ if datastream.nil? || datastream.to_s.empty?
79
+ raise CemAcpt::Scan::DatastreamNotFoundError.new(
80
+ test_data[:test_name], scanner,
81
+ "cem_acpt_scan.datastreams.openscap.#{test_data[:test_name]}"
82
+ )
83
+ end
84
+ end
85
+
86
+ test_data[:scan] = {
87
+ scanner: scanner,
88
+ profile: profile,
89
+ level: test_data[:level] || test_data['level'],
90
+ benchmark: benchmark,
91
+ datastream: datastream,
92
+ }
93
+ ```
94
+
95
+ ### `lib/terraform/gcp/linux/scan/scan_service.rb` — `perform_scan`
96
+
97
+ Remove the hardcoded `|| '/usr/share/xml/scap/ssg/content/ssg-rhel8-ds.xml'` fallback:
98
+
99
+ ```ruby
100
+ # before
101
+ run_openscap(cfg['profile'], cfg['datastream'] || '/usr/share/xml/scap/ssg/content/ssg-rhel8-ds.xml')
102
+
103
+ # after
104
+ run_openscap(cfg['profile'], cfg['datastream'])
105
+ ```
106
+
107
+ The fixture mirror at `spec/fixtures/config_testing/user_config_dir/terraform/gcp/linux/scan/scan_service.rb`
108
+ is updated identically. `spec/fixtures/config_testing/user_config_dir/terraform_checksum.txt`
109
+ is regenerated.
110
+
111
+ ## Edge Cases
112
+
113
+ - **`datastream` is `nil` for CIS-CAT test cases** — `run_ciscat` does not receive a datastream argument; the `nil` assignment is harmless.
114
+ - **`datastream` key present but empty string** — treated as missing; `DatastreamNotFoundError` is raised.
115
+ - **`cem_acpt_scan.datastreams.openscap` key absent from config** — `@config.get(...)` returns `nil`; the `|| {}` guard prevents a `NoMethodError` on the subsequent lookup.
116
+
117
+ ## Constraints / Invariants
118
+
119
+ - `test_data[:scan]` hash shape gains one key (`datastream`) but is otherwise unchanged. All
120
+ existing callers that read `scanner`, `profile`, `level`, `benchmark` are unaffected.
121
+ - `DatastreamNotFoundError` is raised in `scan_post_processing!`, before any Terraform
122
+ provisioning begins — same as `ProfileNotFoundError` and `BenchmarkNotFoundError`.
123
+ - The on-node `scan_config.json` payload already passes `cfg['datastream']` through to
124
+ `run_openscap`; no change to `lib/cem_acpt/provision/terraform.rb` or the scan-config
125
+ serialization is needed.
126
+
127
+ ## Test Plan
128
+
129
+ ### `spec/cem_acpt/scan/errors_spec.rb`
130
+
131
+ Add a `DatastreamNotFoundError` describe block mirroring the existing `BenchmarkNotFoundError`
132
+ block: assert the message includes the test-case name and the config key path.
133
+
134
+ ### `spec/cem_acpt/scan/test_data_scan_spec.rb`
135
+
136
+ 1. Update the existing "does not require a benchmark for openscap test cases" example to
137
+ also supply a `datastreams` map and assert `scan[:datastream]` equals the configured value.
138
+ 2. Add a test that `DatastreamNotFoundError` is raised when the datastream mapping is absent
139
+ for an OpenSCAP test case, and that the error message includes the missing config key path.
140
+ 3. Add a test that CIS-CAT test cases still have `scan[:datastream]` set to `nil`.
141
+
142
+ ### `spec/terraform/gcp/linux/scan/scan_service_spec.rb`
143
+
144
+ Add a text-grep assertion that the hardcoded `ssg-rhel8-ds.xml` fallback string is absent
145
+ from `scan_service.rb` (mirrors the `-l` absence test added for CEM-6765).
146
+
147
+ ## Acceptance Criteria
148
+
149
+ - [ ] `cem_acpt_scan.datastreams.openscap` is a recognized config key with a default of `{}`.
150
+ - [ ] `DatastreamNotFoundError` is defined in `lib/cem_acpt/scan/errors.rb`; its message includes the test-case name and the missing config key path.
151
+ - [ ] `scan_post_processing!` populates `test_data[:scan][:datastream]` from the config map for OpenSCAP test cases.
152
+ - [ ] `scan_post_processing!` raises `DatastreamNotFoundError` when the datastream mapping is missing or empty for an OpenSCAP test case.
153
+ - [ ] `test_data[:scan][:datastream]` is `nil` for CIS-CAT test cases.
154
+ - [ ] The hardcoded `ssg-rhel8-ds.xml` fallback is removed from `perform_scan` in `scan_service.rb` and its fixture mirror.
155
+ - [ ] `spec/fixtures/config_testing/user_config_dir/terraform_checksum.txt` is updated.
156
+ - [ ] All existing specs pass.
157
+ - [ ] New unit tests for `DatastreamNotFoundError` and datastream lookup in `scan_post_processing!` pass.
158
+
159
+ ## Files Touched
160
+
161
+ - `lib/cem_acpt/config/cem_acpt_scan.rb` — add `datastreams: { openscap: {} }` default.
162
+ - `lib/cem_acpt/scan/errors.rb` — add `DatastreamNotFoundError`.
163
+ - `lib/cem_acpt/test_data.rb` — add datastream lookup and error raise in `scan_post_processing!`.
164
+ - `lib/terraform/gcp/linux/scan/scan_service.rb` — remove hardcoded fallback from `perform_scan`.
165
+ - `spec/fixtures/config_testing/user_config_dir/terraform/gcp/linux/scan/scan_service.rb` — mirror update.
166
+ - `spec/fixtures/config_testing/user_config_dir/terraform_checksum.txt` — checksum update.
167
+ - `spec/cem_acpt/scan/errors_spec.rb` — add `DatastreamNotFoundError` describe block.
168
+ - `spec/cem_acpt/scan/test_data_scan_spec.rb` — datastream lookup and error raise tests.
169
+ - `spec/terraform/gcp/linux/scan/scan_service_spec.rb` — absence of hardcoded fallback text-grep.
170
+ - `specifications/CEM-6798.md` — this file.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cem_acpt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.12.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - puppetlabs
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-06-08 00:00:00.000000000 Z
11
+ date: 2026-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async-http
@@ -348,6 +348,7 @@ files:
348
348
  - specifications/CEM-6761.md
349
349
  - specifications/CEM-6762.md
350
350
  - specifications/CEM-6765.md
351
+ - specifications/CEM-6798.md
351
352
  homepage: https://github.com/puppetlabs/cem_acpt
352
353
  licenses:
353
354
  - proprietary