compliance_engine 0.5.0 → 0.6.0
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 +4 -4
- data/AGENTS.md +2 -0
- data/CHANGELOG.md +5 -0
- data/lib/compliance_engine/data.rb +27 -7
- data/lib/compliance_engine/environment_loader/zip.rb +8 -10
- data/lib/compliance_engine/environment_loader/zip_bytes.rb +27 -0
- data/lib/compliance_engine/sce-schema.json +3 -3
- data/lib/compliance_engine/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9f8203b0a0381216d9a1a91c318f0f162bde1d4835bc7731c954156371b6f9b8
|
|
4
|
+
data.tar.gz: 784264cbb1aba5772bbf97dafdd952c3b8823fa404236c372af87f1d6dad885b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1026ff097b4e46f31b59b2a584e9d25b94baa986014564fa6a0196d70224306956fd0499d923fa19b0c1035d248c490a3ffaaa1bbcf8f55bd222e7726fb25157
|
|
7
|
+
data.tar.gz: 588997e4f32f95f7d1edef560a16a09399c59d1b7aba4677ca6cf0bf9d97f38568d9d14c9349a5e489288d16dffe0abc2abc0147cecc9beb5127701270d3594a
|
data/AGENTS.md
CHANGED
|
@@ -91,6 +91,8 @@ A component can have multiple **fragments** (one per source file), which are dee
|
|
|
91
91
|
| CE→Control overlap | Any of `check.ces`' CEs has a control that also appears in `profile.controls` |
|
|
92
92
|
| Direct reference | `profile.checks[check_key]` is truthy |
|
|
93
93
|
|
|
94
|
+
An entry on the **profile side** with value `false` is treated as an **explicit exclusion** that overrides positive matches: `profile.checks[X] = false` hard-excludes check `X` from every route, and `profile.ces[X] = false` prevents CE `X` from being used as either a direct CE match or as a CE→Control bridge. On the **check side**, `false` is local-only (e.g. `check.controls[X] = false` simply means the check is not associated with control `X`); `check.ces` is an array, so no `false` handling applies.
|
|
95
|
+
|
|
94
96
|
`check_mapping` can also be called with CE objects (in addition to profiles). Results are cached by `"#{object.class}:#{object.key}"`.
|
|
95
97
|
|
|
96
98
|
### Loading Pipeline
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
### 0.6.0 / 2026-05-05
|
|
2
|
+
* Honor explicit `false` in profile `checks` and `ces` mappings as exclusions that override positive matches (#117)
|
|
3
|
+
* Coerce non-String `zipfile.name` to `-` for buffer-opened zips (#121)
|
|
4
|
+
* Replace `Zip::File` handoff with `open_environment_zip_bytes` (#124)
|
|
5
|
+
|
|
1
6
|
### 0.5.0 / 2026-04-29
|
|
2
7
|
* Add JSON Schema for SCE data, exposed via `ComplianceEngine.schema` (#49)
|
|
3
8
|
* Add `ComplianceEngine::Tolerance` constants for enforcement tolerance levels (#107)
|
|
@@ -125,13 +125,29 @@ class ComplianceEngine::Data
|
|
|
125
125
|
nil
|
|
126
126
|
end
|
|
127
127
|
|
|
128
|
-
# Scan a Puppet environment from a zip file
|
|
129
|
-
# @param path [String]
|
|
128
|
+
# Scan a Puppet environment from a zip file on disk
|
|
129
|
+
# @param path [String] filesystem path to the zip archive
|
|
130
|
+
# @param name [String, nil] stable string identifier used as the modulepath
|
|
131
|
+
# and cache-key prefix; defaults to the full path string passed as +path+.
|
|
130
132
|
# @return [NilClass]
|
|
131
|
-
def open_environment_zip(path)
|
|
133
|
+
def open_environment_zip(path, name: nil)
|
|
132
134
|
require 'compliance_engine/environment_loader/zip'
|
|
133
135
|
|
|
134
|
-
environment = ComplianceEngine::EnvironmentLoader::Zip.new(path)
|
|
136
|
+
environment = ComplianceEngine::EnvironmentLoader::Zip.new(path, name: name)
|
|
137
|
+
self.modulepath = environment.modulepath
|
|
138
|
+
open(environment)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Scan a Puppet environment from a raw zip byte string
|
|
142
|
+
#
|
|
143
|
+
# @param bytes [String] raw binary zip data (e.g. from File.binread or an HTTP body)
|
|
144
|
+
# @param name [String, nil] stable string identifier used as the modulepath
|
|
145
|
+
# and cache-key prefix; defaults to "-" when no filename is available.
|
|
146
|
+
# @return [NilClass]
|
|
147
|
+
def open_environment_zip_bytes(bytes, name: nil)
|
|
148
|
+
require 'compliance_engine/environment_loader/zip_bytes'
|
|
149
|
+
|
|
150
|
+
environment = ComplianceEngine::EnvironmentLoader::ZipBytes.new(bytes, name: name)
|
|
135
151
|
self.modulepath = environment.modulepath
|
|
136
152
|
open(environment)
|
|
137
153
|
end
|
|
@@ -439,6 +455,9 @@ class ComplianceEngine::Data
|
|
|
439
455
|
cache_key = [check.key, "#{profile_or_ce.class}:#{profile_or_ce.key}"].to_s
|
|
440
456
|
return @mapping[cache_key] if @mapping.key?(cache_key)
|
|
441
457
|
|
|
458
|
+
# An explicit `false` on the profile side hard-excludes the check, regardless of any other route.
|
|
459
|
+
return @mapping[cache_key] = false if profile_or_ce.is_a?(ComplianceEngine::Profile) && profile_or_ce.checks&.dig(check.key) == false
|
|
460
|
+
|
|
442
461
|
# Correlate based on controls
|
|
443
462
|
controls = check.controls&.select { |_, v| v }&.map { |k, _| k }
|
|
444
463
|
|
|
@@ -457,9 +476,10 @@ class ComplianceEngine::Data
|
|
|
457
476
|
# Correlate based on CEs
|
|
458
477
|
return @mapping[cache_key] = true if correlate(check.ces, profile_or_ce.ces)
|
|
459
478
|
|
|
460
|
-
# Correlate based on CEs and controls
|
|
461
|
-
|
|
462
|
-
return @mapping[cache_key] = true if
|
|
479
|
+
# Correlate based on CEs and controls. A CE explicitly set to `false` in the profile
|
|
480
|
+
# cannot be used as a bridge; absence (nil) still allows the bridge.
|
|
481
|
+
return @mapping[cache_key] = true if profile_or_ce.ces&.any? { |k, v| v && correlate(controls, ces[k]&.controls) }
|
|
482
|
+
return @mapping[cache_key] = true if check.ces&.any? { |ce| profile_or_ce.ces&.dig(ce) != false && ces[ce]&.controls&.any? { |k, v| v && profile_or_ce.controls&.dig(k) } }
|
|
463
483
|
|
|
464
484
|
@mapping[cache_key] = false
|
|
465
485
|
end
|
|
@@ -7,23 +7,21 @@ require 'zip/filesystem'
|
|
|
7
7
|
# Load compliance engine data from a zip file containing a Puppet environment
|
|
8
8
|
class ComplianceEngine::EnvironmentLoader::Zip < ComplianceEngine::EnvironmentLoader
|
|
9
9
|
# Initialize a ComplianceEngine::EnvironmentLoader::Zip object from a zip
|
|
10
|
-
# file and an optional root directory.
|
|
10
|
+
# file path and an optional root directory.
|
|
11
11
|
#
|
|
12
|
-
# @param input [String
|
|
13
|
-
# or an already-opened ::Zip::File (e.g. from Zip::File.open_buffer); when
|
|
14
|
-
# a ::Zip::File is passed, the caller owns its lifecycle
|
|
12
|
+
# @param input [String] filesystem path to a zip file
|
|
15
13
|
# @param root [String] a directory within the zip file to use as the root of the environment
|
|
16
14
|
# @param load_dotfiles [Boolean] whether to load dotfiles; defaults to true to
|
|
17
15
|
# preserve the historical zip-loader behaviour of including all files
|
|
18
16
|
# @param name [String, nil] identifier used for modulepath and downstream
|
|
19
|
-
# cache keys; defaults to the
|
|
20
|
-
# buffer-opened zips). Pass an explicit value when loading a buffer-opened
|
|
21
|
-
# zip to keep cache keys unique and logs informative.
|
|
17
|
+
# cache keys; defaults to the full path string passed as +input+.
|
|
22
18
|
def initialize(input, root: '/'.dup, load_dotfiles: true, name: nil)
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
raise ArgumentError, "input must be a String path, got #{input.class}" unless input.is_a?(String)
|
|
20
|
+
|
|
21
|
+
zipfile = ::Zip::File.open(input)
|
|
22
|
+
@modulepath = name || input.to_s
|
|
25
23
|
super(root, fileclass: zipfile.file, dirclass: zipfile.dir, zipfile_path: @modulepath, load_dotfiles: load_dotfiles)
|
|
26
24
|
ensure
|
|
27
|
-
zipfile
|
|
25
|
+
zipfile&.close
|
|
28
26
|
end
|
|
29
27
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../compliance_engine'
|
|
4
|
+
require_relative '../environment_loader'
|
|
5
|
+
# zip/filesystem must be required before any Zip::File instance is opened so
|
|
6
|
+
# that the per-instance dir/file accessors are wired up at open time.
|
|
7
|
+
require 'zip/filesystem'
|
|
8
|
+
require 'zip'
|
|
9
|
+
|
|
10
|
+
# Load compliance engine data from a raw zip byte string containing a Puppet environment
|
|
11
|
+
class ComplianceEngine::EnvironmentLoader::ZipBytes < ComplianceEngine::EnvironmentLoader
|
|
12
|
+
# @param bytes [String] raw binary zip data (e.g. from File.binread or an HTTP body)
|
|
13
|
+
# @param root [String] a directory within the zip file to use as the root of the environment
|
|
14
|
+
# @param load_dotfiles [Boolean] whether to load dotfiles; defaults to true to
|
|
15
|
+
# preserve the historical zip-loader behaviour of including all files
|
|
16
|
+
# @param name [String, nil] identifier used for modulepath and downstream
|
|
17
|
+
# cache keys; defaults to "-" when no filename is available.
|
|
18
|
+
def initialize(bytes, root: '/'.dup, load_dotfiles: true, name: nil)
|
|
19
|
+
raise ArgumentError, "bytes must be a String, got #{bytes.class}" unless bytes.is_a?(String)
|
|
20
|
+
|
|
21
|
+
zipfile = ::Zip::File.open_buffer(bytes)
|
|
22
|
+
@modulepath = name || '-'
|
|
23
|
+
super(root, fileclass: zipfile.file, dirclass: zipfile.dir, zipfile_path: @modulepath, load_dotfiles: load_dotfiles)
|
|
24
|
+
ensure
|
|
25
|
+
zipfile&.close
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"controlsMap": {
|
|
53
53
|
"type": "object",
|
|
54
|
-
"title": "References to top-level controls entries. Enforced when value is true.",
|
|
54
|
+
"title": "References to top-level controls entries. Enforced when value is true; explicitly excluded when value is false.",
|
|
55
55
|
"patternProperties": {
|
|
56
56
|
"^\\w(?:[\\w.-]*[\\w-])?(?::\\w(?:[\\w.-]*[\\w-])?)*$": {
|
|
57
57
|
"type": "boolean",
|
|
@@ -132,7 +132,7 @@
|
|
|
132
132
|
"ces": {
|
|
133
133
|
"type": "object",
|
|
134
134
|
"default": {},
|
|
135
|
-
"title": "CEs to include in this profile. Enforced when value is true.",
|
|
135
|
+
"title": "CEs to include in this profile. Enforced when value is true; explicitly excluded when value is false (overrides any positive mapping route).",
|
|
136
136
|
"patternProperties": {
|
|
137
137
|
"^\\w(?:[\\w.-]*[\\w-])?(?::\\w(?:[\\w.-]*[\\w-])?)*$": {
|
|
138
138
|
"type": "boolean",
|
|
@@ -151,7 +151,7 @@
|
|
|
151
151
|
"checks": {
|
|
152
152
|
"type": "object",
|
|
153
153
|
"default": {},
|
|
154
|
-
"title": "Checks to include in this profile. Enforced when value is true.",
|
|
154
|
+
"title": "Checks to include in this profile. Enforced when value is true; hard-excluded when value is false (overrides any positive mapping route).",
|
|
155
155
|
"patternProperties": {
|
|
156
156
|
"^\\w(?:[\\w.-]*[\\w-])?(?::\\w(?:[\\w.-]*[\\w-])?)*$": {
|
|
157
157
|
"type": "boolean",
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: compliance_engine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Steven Pritchard
|
|
@@ -145,6 +145,7 @@ files:
|
|
|
145
145
|
- lib/compliance_engine/data_version.rb
|
|
146
146
|
- lib/compliance_engine/environment_loader.rb
|
|
147
147
|
- lib/compliance_engine/environment_loader/zip.rb
|
|
148
|
+
- lib/compliance_engine/environment_loader/zip_bytes.rb
|
|
148
149
|
- lib/compliance_engine/module_loader.rb
|
|
149
150
|
- lib/compliance_engine/profile.rb
|
|
150
151
|
- lib/compliance_engine/profiles.rb
|
|
@@ -158,7 +159,7 @@ licenses:
|
|
|
158
159
|
metadata:
|
|
159
160
|
homepage_uri: https://simp-project.com/docs/sce/
|
|
160
161
|
source_code_uri: https://github.com/simp/rubygem-simp-compliance_engine
|
|
161
|
-
changelog_uri: https://github.com/simp/rubygem-simp-compliance_engine/releases/tag/0.
|
|
162
|
+
changelog_uri: https://github.com/simp/rubygem-simp-compliance_engine/releases/tag/0.6.0
|
|
162
163
|
bug_tracker_uri: https://github.com/simp/rubygem-simp-compliance_engine/issues
|
|
163
164
|
rdoc_options: []
|
|
164
165
|
require_paths:
|