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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b4687964cd4b5d202b892c1fbcbc26bae0a4b7ca50892510e66aa1e2ba0a99bb
4
- data.tar.gz: e13bbfac5991052c33a8626eed6354454522a5bb3d9211a2d387aa1a5890f191
3
+ metadata.gz: 78c9c17693c37ea1fef9d03a39f7694a033a985c162e3c2df82ac3305491e747
4
+ data.tar.gz: f207165591c42fc17694f792ec17f0ce8e6bf502e14f326135a0bfb02a42a521
5
5
  SHA512:
6
- metadata.gz: 87c903786292eb538ae1e210734fa539b6b551d2cb5d29886175c234e196d29f9cce8627b08e72dedf661945bc8796980c5da5d737a63acfac8216265a7d06a5
7
- data.tar.gz: f8ba2cdcb7f2074990563c2791d82d51bd171142446410f5700a7c64bcb36c761034b2bb1a2324b756a66563bc8c18ab949d7fc3454a08cee44e74d9306d3743
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.2)
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.2.8)
212
- strscan (>= 3.0.9)
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', 'Ignores errors while generating benchmark reports') do
58
- @data[:ignore_all] = true
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: @data.fetch(:ignore_all, false),
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.ignore_all_errors
28
+ ignore_all_errors: opts.ignore_benchmark_errors
21
29
  )
22
- benchmarks.map do |b|
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
- ignore_all_errors: false,
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
- @report_type ||= (xccdf_dir.nil? ? :basic_coverage : :correlated_coverage)
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
- case @benchmark.framework
352
- when 'cis'
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
- raise "Cannot find controls for framework #{@benchmark.framework}"
358
- end
359
- end
360
- end
361
-
362
- def find_controls_in_mapping_data
363
- controls = @benchmark.map_data[0].each_with_object([]) do |(_, mapping), arr|
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AbideDevUtils
4
- VERSION = "0.18.2"
4
+ VERSION = "0.18.3"
5
5
  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.2
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-06-24 00:00:00.000000000 Z
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.4.19
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