abide_dev_utils 0.18.2 → 0.18.3
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/Gemfile.lock +3 -3
- data/lib/abide_dev_utils/cli/sce.rb +6 -8
- data/lib/abide_dev_utils/sce/generate/coverage_report.rb +35 -112
- data/lib/abide_dev_utils/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 78c9c17693c37ea1fef9d03a39f7694a033a985c162e3c2df82ac3305491e747
|
4
|
+
data.tar.gz: f207165591c42fc17694f792ec17f0ce8e6bf502e14f326135a0bfb02a42a521
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0210948da62d9eecf039617acef3be3fe21143eacd0aa4593ec9d1f3fdfde7ca5d0cc0ef15d60e9dad12432ab170e010e6c28b54f31ca3fa8442820ce64b9cd9'
|
7
|
+
data.tar.gz: c332682a7c2a918ade7f6c8a84f9cb90ebd0d4ab5197f79b9a645db0b5610a37205f7b29797d039e58a27802909ab79303d755ea273d5407e7e77169c2cbe512
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
abide_dev_utils (0.18.
|
4
|
+
abide_dev_utils (0.18.3)
|
5
5
|
cmdparse (~> 3.0)
|
6
6
|
facterdb (~> 2.1.0)
|
7
7
|
google-cloud-storage (~> 1.34)
|
@@ -208,8 +208,8 @@ GEM
|
|
208
208
|
trailblazer-option (>= 0.1.1, < 0.2.0)
|
209
209
|
uber (< 0.2.0)
|
210
210
|
retriable (3.1.2)
|
211
|
-
rexml (3.
|
212
|
-
strscan
|
211
|
+
rexml (3.3.6)
|
212
|
+
strscan
|
213
213
|
rgen (0.9.1)
|
214
214
|
rspec (3.11.0)
|
215
215
|
rspec-core (~> 3.11.0)
|
@@ -54,12 +54,8 @@ module Abide
|
|
54
54
|
options.on('-L [LEVEL]', '--level [LEVEL]', 'Specify the level to show coverage for') do |l|
|
55
55
|
@data[:level] = l
|
56
56
|
end
|
57
|
-
options.on('-I', '--ignore-benchmark-errors', '
|
58
|
-
@data[:
|
59
|
-
end
|
60
|
-
options.on('-X [XCCDF_DIR]', '--xccdf-dir [XCCDF_DIR]',
|
61
|
-
'If specified, the coverage report will be correlated with info from the benchmark XCCDF files') do |d|
|
62
|
-
@data[:xccdf_dir] = d
|
57
|
+
options.on('-I', '--no-ignore-benchmark-errors', 'Does not ignore errors while generating benchmark reports') do
|
58
|
+
@data[:ignore_benchmark_errors] = false
|
63
59
|
end
|
64
60
|
options.on('-v', '--verbose', 'Will output the report to the console') { @data[:verbose] = true }
|
65
61
|
options.on('-q', '--quiet', 'Will not output anything to the console') { @data[:quiet] = true }
|
@@ -70,15 +66,17 @@ module Abide
|
|
70
66
|
out_format = @data.fetch(:format, 'yaml')
|
71
67
|
quiet = @data.fetch(:quiet, false)
|
72
68
|
console = @data.fetch(:verbose, false) && !quiet
|
69
|
+
ignore = @data.fetch(:ignore_benchmark_errors, true)
|
73
70
|
generate_opts = {
|
74
71
|
benchmark: @data[:benchmark],
|
75
72
|
profile: @data[:profile],
|
76
73
|
level: @data[:level],
|
77
|
-
ignore_benchmark_errors:
|
78
|
-
xccdf_dir: @data[:xccdf_dir]
|
74
|
+
ignore_benchmark_errors: ignore
|
79
75
|
}
|
80
76
|
AbideDevUtils::Output.simple('Generating coverage report...') unless quiet
|
81
77
|
coverage = AbideDevUtils::Sce::Generate::CoverageReport.generate(format_func: :to_h, opts: generate_opts)
|
78
|
+
raise 'No coverage data found' if coverage.empty?
|
79
|
+
|
82
80
|
AbideDevUtils::Output.simple("Saving coverage report to #{file_name}...")
|
83
81
|
case out_format
|
84
82
|
when /yaml/i
|
@@ -14,24 +14,36 @@ module AbideDevUtils
|
|
14
14
|
# Methods and objects used to construct a report of what SCE enforces versus what
|
15
15
|
# the various compliance frameworks expect to be enforced.
|
16
16
|
module CoverageReport
|
17
|
+
# Generate a coverage report for a Puppet module
|
18
|
+
# @param format_func [Symbol] the format function to use
|
19
|
+
# @param opts [Hash] options for generating the report
|
20
|
+
# @option opts [String] :benchmark the benchmark to generate the report for
|
21
|
+
# @option opts [String] :profile the profile to generate the report for
|
22
|
+
# @option opts [String] :level the level to generate the report for
|
23
|
+
# @option opts [Symbol] :format_func the format function to use
|
24
|
+
# @option opts [Boolean] :ignore_benchmark_errors ignore all errors when loading benchmarks
|
17
25
|
def self.generate(format_func: :to_h, opts: {})
|
18
26
|
opts = ReportOptions.new(opts)
|
19
27
|
benchmarks = AbideDevUtils::Sce::BenchmarkLoader.benchmarks_from_puppet_module(
|
20
|
-
ignore_all_errors: opts.
|
28
|
+
ignore_all_errors: opts.ignore_benchmark_errors
|
21
29
|
)
|
22
|
-
benchmarks.
|
30
|
+
benchmarks.filter_map do |b|
|
31
|
+
next if opts.benchmark && !Regexp.new(Regexp.escape(opts.benchmark)).match?(b.title_key)
|
32
|
+
next if opts.profile && b.mapper.profiles.none?(opts.profile)
|
33
|
+
next if opts.level && b.mapper.levels.none?(opts.level)
|
34
|
+
|
23
35
|
BenchmarkReport.new(b, opts).run.send(format_func)
|
24
36
|
end
|
25
37
|
end
|
26
38
|
|
39
|
+
# Holds options for generating a report
|
27
40
|
class ReportOptions
|
28
41
|
DEFAULTS = {
|
29
42
|
benchmark: nil,
|
30
43
|
profile: nil,
|
31
44
|
level: nil,
|
32
45
|
format_func: :to_h,
|
33
|
-
|
34
|
-
xccdf_dir: nil
|
46
|
+
ignore_benchmark_errors: false
|
35
47
|
}.freeze
|
36
48
|
|
37
49
|
attr_reader(*DEFAULTS.keys)
|
@@ -44,7 +56,7 @@ module AbideDevUtils
|
|
44
56
|
end
|
45
57
|
|
46
58
|
def report_type
|
47
|
-
|
59
|
+
:basic_coverage
|
48
60
|
end
|
49
61
|
end
|
50
62
|
|
@@ -150,94 +162,17 @@ module AbideDevUtils
|
|
150
162
|
end
|
151
163
|
end
|
152
164
|
|
153
|
-
class OldReport
|
154
|
-
def initialize(benchmarks)
|
155
|
-
@benchmarks = benchmarks
|
156
|
-
end
|
157
|
-
|
158
|
-
def self.generate
|
159
|
-
coverage = {}
|
160
|
-
coverage['classes'] = {}
|
161
|
-
all_cap = ClassUtils.find_all_classes_and_paths(puppet_class_dir)
|
162
|
-
invalid_classes = find_invalid_classes(all_cap)
|
163
|
-
valid_classes = find_valid_classes(all_cap, invalid_classes)
|
164
|
-
coverage['classes']['invalid'] = invalid_classes
|
165
|
-
coverage['classes']['valid'] = valid_classes
|
166
|
-
hiera = YAML.safe_load(File.open(hiera_path))
|
167
|
-
profile&.gsub!(/^profile_/, '') unless profile.nil?
|
168
|
-
|
169
|
-
matcher = profile.nil? ? /^profile_/ : /^profile_#{profile}/
|
170
|
-
hiera.each do |k, v|
|
171
|
-
key_base = k.split('::')[-1]
|
172
|
-
coverage['benchmark'] = v if key_base == 'title'
|
173
|
-
next unless key_base.match?(matcher)
|
174
|
-
|
175
|
-
coverage[key_base] = generate_uncovered_data(v, valid_classes)
|
176
|
-
end
|
177
|
-
coverage
|
178
|
-
end
|
179
|
-
|
180
|
-
def self.generate_uncovered_data(ctrl_list, valid_classes)
|
181
|
-
out_hash = {}
|
182
|
-
out_hash[:num_total] = ctrl_list.length
|
183
|
-
out_hash[:uncovered] = []
|
184
|
-
out_hash[:covered] = []
|
185
|
-
ctrl_list.each do |c|
|
186
|
-
if valid_classes.include?(c)
|
187
|
-
out_hash[:covered] << c
|
188
|
-
else
|
189
|
-
out_hash[:uncovered] << c
|
190
|
-
end
|
191
|
-
end
|
192
|
-
out_hash[:num_covered] = out_hash[:covered].length
|
193
|
-
out_hash[:num_uncovered] = out_hash[:uncovered].length
|
194
|
-
out_hash[:coverage] = Float(
|
195
|
-
(Float(out_hash[:num_covered]) / Float(out_hash[:num_total])) * 100.0
|
196
|
-
).floor(3)
|
197
|
-
out_hash
|
198
|
-
end
|
199
|
-
|
200
|
-
def self.find_valid_classes(all_cap, invalid_classes)
|
201
|
-
all_classes = all_cap.dup.transpose[0]
|
202
|
-
return [] if all_classes.nil?
|
203
|
-
|
204
|
-
return all_classes - invalid_classes unless invalid_classes.nil?
|
205
|
-
|
206
|
-
all_classes
|
207
|
-
end
|
208
|
-
|
209
|
-
def self.find_invalid_classes(all_cap)
|
210
|
-
invalid_classes = []
|
211
|
-
all_cap.each do |cap|
|
212
|
-
invalid_classes << cap[0] unless class_valid?(cap[1])
|
213
|
-
end
|
214
|
-
invalid_classes
|
215
|
-
end
|
216
|
-
|
217
|
-
def self.class_valid?(manifest_path)
|
218
|
-
compiler = Puppet::Pal::Compiler.new(nil)
|
219
|
-
ast = compiler.parse_file(manifest_path)
|
220
|
-
ast.body.body.statements.each do |s|
|
221
|
-
next unless s.respond_to?(:arguments)
|
222
|
-
next unless s.arguments.respond_to?(:each)
|
223
|
-
|
224
|
-
s.arguments.each do |i|
|
225
|
-
return false if i.value == 'Not implemented'
|
226
|
-
end
|
227
|
-
end
|
228
|
-
true
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
165
|
# Class manages organizing report data into various output formats
|
233
166
|
class ReportOutput
|
234
167
|
attr_reader :controls_in_resource_data, :rules_in_map, :timestamp,
|
235
168
|
:title
|
236
169
|
|
237
|
-
def initialize(benchmark, controls_in_resource_data, rules_in_map)
|
170
|
+
def initialize(benchmark, controls_in_resource_data, rules_in_map, profile: nil, level: nil)
|
238
171
|
@benchmark = benchmark
|
239
172
|
@controls_in_resource_data = controls_in_resource_data
|
240
173
|
@rules_in_map = rules_in_map
|
174
|
+
@profile = profile
|
175
|
+
@level = level
|
241
176
|
@timestamp = DateTime.now.iso8601
|
242
177
|
@title = "Coverage Report for #{@benchmark.title_key}"
|
243
178
|
end
|
@@ -287,7 +222,9 @@ module AbideDevUtils
|
|
287
222
|
{
|
288
223
|
title: @benchmark.title,
|
289
224
|
version: @benchmark.version,
|
290
|
-
framework: @benchmark.framework
|
225
|
+
framework: @benchmark.framework,
|
226
|
+
profile: @profile || 'all',
|
227
|
+
level: @level || 'all'
|
291
228
|
}
|
292
229
|
end
|
293
230
|
|
@@ -310,6 +247,8 @@ module AbideDevUtils
|
|
310
247
|
def initialize(benchmark, opts = ReportOptions.new)
|
311
248
|
@benchmark = benchmark
|
312
249
|
@opts = opts
|
250
|
+
@special_control_names = %w[sce_options sce_protected]
|
251
|
+
@stig_map_types = %w[vulnid ruleid]
|
313
252
|
end
|
314
253
|
|
315
254
|
def run
|
@@ -327,7 +266,7 @@ module AbideDevUtils
|
|
327
266
|
def basic_coverage(level: @opts.level, profile: @opts.profile)
|
328
267
|
map_type = @benchmark.map_type(controls_in_resource_data[0])
|
329
268
|
rules_in_map = @benchmark.rules_in_map(map_type, level: level, profile: profile)
|
330
|
-
ReportOutput.new(@benchmark, controls_in_resource_data, rules_in_map)
|
269
|
+
ReportOutput.new(@benchmark, controls_in_resource_data, rules_in_map, profile: profile, level: level)
|
331
270
|
end
|
332
271
|
|
333
272
|
# def correlated_coverage(level: @opts.level, profile: @opts.profile)
|
@@ -348,35 +287,19 @@ module AbideDevUtils
|
|
348
287
|
end
|
349
288
|
end
|
350
289
|
controls.flatten.uniq.select do |c|
|
351
|
-
|
352
|
-
|
353
|
-
@benchmark.map_type(c) != 'vulnid'
|
354
|
-
when 'stig'
|
355
|
-
@benchmark.map_type(c) == 'vulnid'
|
290
|
+
if @special_control_names.include? c
|
291
|
+
false
|
356
292
|
else
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
mapping.each do |level, profs|
|
365
|
-
next if level == 'benchmark'
|
366
|
-
|
367
|
-
profs.each do |_, ctrls|
|
368
|
-
arr << ctrls.keys
|
369
|
-
arr << ctrls.values
|
293
|
+
case @benchmark.framework
|
294
|
+
when 'cis'
|
295
|
+
@stig_map_types.none? @benchmark.map_type(c)
|
296
|
+
when 'stig'
|
297
|
+
@stig_map_types.include? @benchmark.map_type(c)
|
298
|
+
else
|
299
|
+
raise "Cannot find controls for framework #{@benchmark.framework}"
|
370
300
|
end
|
371
301
|
end
|
372
302
|
end
|
373
|
-
controls.flatten.uniq
|
374
|
-
end
|
375
|
-
end
|
376
|
-
|
377
|
-
class ReportOutputCorrelation
|
378
|
-
def initialize(cov_rep)
|
379
|
-
@cov_rep = cov_rep
|
380
303
|
end
|
381
304
|
end
|
382
305
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: abide_dev_utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.18.
|
4
|
+
version: 0.18.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- abide-team
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -486,7 +486,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
486
486
|
- !ruby/object:Gem::Version
|
487
487
|
version: '0'
|
488
488
|
requirements: []
|
489
|
-
rubygems_version: 3.
|
489
|
+
rubygems_version: 3.5.18
|
490
490
|
signing_key:
|
491
491
|
specification_version: 4
|
492
492
|
summary: Helper utilities for developing compliance Puppet code
|