abide_dev_utils 0.9.5 → 0.10.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.
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'abide_dev_utils/files'
4
+ require 'abide_dev_utils/xccdf/parser/objects'
5
+
6
+ module AbideDevUtils
7
+ module XCCDF
8
+ # Contains methods and classes for parsing XCCDF files,
9
+ module Parser
10
+ def self.parse(file_path)
11
+ doc = AbideDevUtils::Files::Reader.read(file_path)
12
+ benchmark = AbideDevUtils::XCCDF::Parser::Objects::Benchmark.new(doc)
13
+ Linker.resolve_links(benchmark)
14
+ benchmark
15
+ end
16
+
17
+ # Links XCCDF objects by reference.
18
+ # Each link is resolved and then a bidirectional link is established
19
+ # between the two objects.
20
+ module Linker
21
+ def self.resolve_links(benchmark)
22
+ link_profile_rules(benchmark)
23
+ link_rule_values(benchmark)
24
+ end
25
+
26
+ def self.link_profile_rules(benchmark)
27
+ rules = benchmark.find_children_by_class(AbideDevUtils::XCCDF::Parser::Objects::Rule, recurse: true)
28
+ benchmark.profile.each do |profile|
29
+ profile.xccdf_select.each do |sel|
30
+ rules.select { |rule| rule.id == sel.idref }.each do |rule|
31
+ rule.add_link(profile)
32
+ profile.add_link(rule)
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ def self.link_rule_values(benchmark)
39
+ rules = benchmark.find_children_by_class(AbideDevUtils::XCCDF::Parser::Objects::Rule, recurse: true)
40
+ benchmark.value.each do |value|
41
+ rules.each do |rule|
42
+ unless rule.find_children_by_attribute_value('value-id', value.id, recurse: true).empty?
43
+ rule.add_link(value)
44
+ value.add_link(rule)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -34,21 +34,17 @@ module AbideDevUtils
34
34
 
35
35
  # Diffs two xccdf files
36
36
  def self.diff(file1, file2, opts)
37
+ require 'abide_dev_utils/xccdf/diff'
37
38
  bm1 = Benchmark.new(file1)
38
39
  bm2 = Benchmark.new(file2)
39
- profile = opts.fetch(:profile, nil)
40
- profile_diff = if profile.nil?
41
- bm1.diff_profiles(bm2).each do |_, v|
42
- v.transform_values! { |x| x.map!(&:to_s) }
43
- end
44
- else
45
- bm1.diff_profiles(bm2)[profile].transform_values! { |x| x.map!(&:to_s) }
46
- end
47
- profile_key = profile.nil? ? 'all_profiles' : profile
48
- {
49
- 'benchmark' => bm1.diff_title_version(bm2),
50
- profile_key => profile_diff
51
- }
40
+ AbideDevUtils::XCCDF::Diff.diff_benchmarks(bm1, bm2, opts)
41
+ end
42
+
43
+ # Use new-style diff
44
+ def self.new_style_diff(file1, file2, opts)
45
+ require 'abide_dev_utils/xccdf/diff/benchmark'
46
+ bm_diff = AbideDevUtils::XCCDF::Diff::BenchmarkDiff.new(file1, file2, opts)
47
+ bm_diff.diff
52
48
  end
53
49
 
54
50
  # Common constants and methods included by nearly everything else
@@ -164,25 +160,6 @@ module AbideDevUtils
164
160
  diff_properties.map { |x| send(x) } == other.diff_properties.map { |x| other.send(x) }
165
161
  end
166
162
 
167
- def default_diff_opts
168
- {
169
- similarity: 1,
170
- strict: true,
171
- strip: true,
172
- array_path: true,
173
- delimiter: '//',
174
- use_lcs: false
175
- }
176
- end
177
-
178
- def diff(other, **opts)
179
- Hashdiff.diff(
180
- to_h,
181
- other.to_h,
182
- default_diff_opts.merge(opts)
183
- )
184
- end
185
-
186
163
  def abide_object?
187
164
  true
188
165
  end
@@ -231,9 +208,12 @@ module AbideDevUtils
231
208
  profiles.select { |x| x.title == profile_title }.controls
232
209
  end
233
210
 
234
- def gen_map(dir: nil, type: 'CIS', parent_key_prefix: '', **_)
211
+ def gen_map(dir: nil, type: 'cis', parent_key_prefix: '', version_output_dir: false, **_)
235
212
  os, ver = facter_platform
236
- mapping_dir = dir ? File.expand_path(File.join(dir, type, os, ver)) : ''
213
+ output_path = [type, os, ver]
214
+ output_path.unshift(File.expand_path(dir)) if dir
215
+ output_path << version if version_output_dir
216
+ mapping_dir = File.expand_path(File.join(output_path))
237
217
  parent_key_prefix = '' if parent_key_prefix.nil?
238
218
  MAP_INDICES.each_with_object({}) do |idx, h|
239
219
  map_file_path = "#{mapping_dir}/#{idx}.yaml"
@@ -257,33 +237,6 @@ module AbideDevUtils
257
237
  }
258
238
  end
259
239
 
260
- def diff_title_version(other)
261
- Hashdiff.diff(
262
- to_h.reject { |k, _| k.to_s == 'profiles' },
263
- other.to_h.reject { |k, _| k.to_s == 'profiles' },
264
- default_diff_opts
265
- )
266
- end
267
-
268
- def diff_profiles(other)
269
- this_diff = {}
270
- other_hash = other.to_h[:profiles]
271
- to_h[:profiles].each do |name, data|
272
- diff_h = Hashdiff.diff(data, other_hash[name], default_diff_opts).each_with_object({}) do |x, a|
273
- val_to = x.length == 4 ? x[3] : nil
274
- a_key = x[2].is_a?(Hash) ? x[2][:title] : x[2]
275
- a[a_key] = [] unless a.key?(a_key)
276
- a[a_key] << ChangeSet.new(change: x[0], key: x[1], value: x[2], value_to: val_to)
277
- end
278
- this_diff[name] = diff_h
279
- end
280
- this_diff
281
- end
282
-
283
- def diff_controls(other)
284
- controls.diff(other.controls)
285
- end
286
-
287
240
  def map_indexed(index: 'title', framework: 'cis', key_prefix: '')
288
241
  c_map = profiles.each_with_object({}) do |profile, obj|
289
242
  obj[profile.level.downcase] = {} unless obj[profile.level.downcase].is_a?(Hash)
@@ -298,7 +251,16 @@ module AbideDevUtils
298
251
 
299
252
  def facter_platform
300
253
  cpe = xpath('xccdf:Benchmark/xccdf:platform')[0]['idref'].split(':')
301
- [cpe[4].split('_')[0], cpe[5].split('.')[0]]
254
+ if cpe.length > 4
255
+ product_name = cpe[4].split('_')
256
+ product_version = cpe[5].split('.') unless cpe[5].nil?
257
+ return [product_name[0], product_version[0]] unless product_version[0] == '-'
258
+
259
+ return [product_name[0], product_name[-1]] if product_version[0] == '-'
260
+ end
261
+
262
+ product = cpe[3].split('_')
263
+ [product[0], product[-1]] # This should wrap the name i.e 'Windows' and the version '10'
302
264
  end
303
265
 
304
266
  # Converts object to Hiera-formatted YAML
@@ -387,69 +349,6 @@ module AbideDevUtils
387
349
  end
388
350
  end
389
351
 
390
- class ChangeSet
391
- attr_reader :change, :key, :value, :value_to
392
-
393
- def initialize(change:, key:, value:, value_to: nil)
394
- validate_change(change)
395
- @change = change
396
- @key = key
397
- @value = value
398
- @value_to = value_to
399
- end
400
-
401
- def to_s
402
- val_to_str = value_to.nil? ? ' ' : " to #{value_to} "
403
- "#{change_string} value #{value}#{val_to_str}at #{key}"
404
- end
405
-
406
- def can_merge?(other)
407
- return false unless (change == '-' && other.change == '+') || (change == '+' && other.change == '-')
408
- return false unless key == other.key || value_hash_equality(other)
409
-
410
- true
411
- end
412
-
413
- def merge(other)
414
- unless can_merge?(other)
415
- raise ArgumentError, 'Cannot merge. Possible causes: change is identical; key or value do not match'
416
- end
417
-
418
- new_to_value = value == other.value ? nil : other.value
419
- ChangeSet.new(
420
- change: '~',
421
- key: key,
422
- value: value,
423
- value_to: new_to_value
424
- )
425
- end
426
-
427
- private
428
-
429
- def value_hash_equality(other)
430
- equality = false
431
- value.each do |k, v|
432
- equality = true if v == other.value[k]
433
- end
434
- equality
435
- end
436
-
437
- def validate_change(change)
438
- raise ArgumentError, "Change type #{change} in invalid" unless ['+', '-', '~'].include?(change)
439
- end
440
-
441
- def change_string
442
- case change
443
- when '-'
444
- 'remove'
445
- when '+'
446
- 'add'
447
- else
448
- 'change'
449
- end
450
- end
451
- end
452
-
453
352
  class ObjectContainer
454
353
  include AbideDevUtils::XCCDF::Common
455
354
 
data/new_diff.rb ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'yaml'
5
+ require 'pry'
6
+ require 'abide_dev_utils/xccdf/diff/benchmark'
7
+
8
+ xml_file1 = File.expand_path(ARGV[0])
9
+ xml_file2 = File.expand_path(ARGV[1])
10
+ legacy_config = ARGV.length > 2 ? YAML.load_file(File.expand_path(ARGV[2])) : nil
11
+
12
+ def convert_legacy_config(config, num_title_diff, key_format: :hiera_num)
13
+ nt_diff = num_title_diff.diff(key: :number)
14
+ updated_config = config['config']['control_configs'].each_with_object({}) do |(key, value), h|
15
+ next if value.nil?
16
+
17
+ diff_key = key.to_s.gsub(/^c/, '').tr('_', '.') if key_format == :hiera_num
18
+ if nt_diff.key?(diff_key)
19
+ if nt_diff[diff_key][0][:diff] == :number
20
+ new_key = "c#{nt_diff[diff_key][0][:other_number].to_s.tr('.', '_')}"
21
+ h[new_key] = value
22
+ puts "Converted #{key} to #{new_key}"
23
+ elsif nt_diff[diff_key][0][:diff] == :title
24
+
25
+ h[key] = value
26
+ end
27
+ else
28
+ h[key] = value
29
+ end
30
+ end
31
+ { 'config' => { 'control_configs' => updated_config } }.to_yaml
32
+ end
33
+
34
+ start_time = Time.now
35
+
36
+ bm_diff = AbideDevUtils::XCCDF::Diff::BenchmarkDiff.new(xml_file1, xml_file2)
37
+ self_nc_count, other_nc_count = bm_diff.numbered_children_counts
38
+ puts "Benchmark numbered children count: #{self_nc_count}"
39
+ puts "Other benchmark numbered children count: #{other_nc_count}"
40
+ puts "Rule count difference: #{bm_diff.numbered_children_count_diff}"
41
+ num_diff = bm_diff.number_title_diff
42
+ binding.pry if legacy_config.nil?
43
+ File.open('/tmp/legacy_converted.yaml', 'w') do |f|
44
+ converted = convert_legacy_config(legacy_config, num_diff)
45
+ f.write(converted)
46
+ end
47
+
48
+ puts "Computation time: #{Time.now - start_time}"
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.9.5
4
+ version: 0.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - abide-team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-02-10 00:00:00.000000000 Z
11
+ date: 2022-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.11'
19
+ version: '1.13'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.11'
26
+ version: '1.13'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: cmdparse
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: '1.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: amatch
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.4'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.4'
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: bundler
127
141
  requirement: !ruby/object:Gem::Requirement
@@ -330,8 +344,10 @@ files:
330
344
  - bin/setup
331
345
  - exe/abide
332
346
  - lib/abide_dev_utils.rb
347
+ - lib/abide_dev_utils/cem.rb
333
348
  - lib/abide_dev_utils/cli.rb
334
349
  - lib/abide_dev_utils/cli/abstract.rb
350
+ - lib/abide_dev_utils/cli/cem.rb
335
351
  - lib/abide_dev_utils/cli/comply.rb
336
352
  - lib/abide_dev_utils/cli/jira.rb
337
353
  - lib/abide_dev_utils/cli/puppet.rb
@@ -364,6 +380,18 @@ files:
364
380
  - lib/abide_dev_utils/validate.rb
365
381
  - lib/abide_dev_utils/version.rb
366
382
  - lib/abide_dev_utils/xccdf.rb
383
+ - lib/abide_dev_utils/xccdf/diff.rb
384
+ - lib/abide_dev_utils/xccdf/diff/benchmark.rb
385
+ - lib/abide_dev_utils/xccdf/diff/benchmark/number_title.rb
386
+ - lib/abide_dev_utils/xccdf/diff/benchmark/profile.rb
387
+ - lib/abide_dev_utils/xccdf/diff/benchmark/property.rb
388
+ - lib/abide_dev_utils/xccdf/diff/benchmark/property_existence.rb
389
+ - lib/abide_dev_utils/xccdf/diff/utils.rb
390
+ - lib/abide_dev_utils/xccdf/parser.rb
391
+ - lib/abide_dev_utils/xccdf/parser/objects.rb
392
+ - lib/abide_dev_utils/xccdf/parser/objects/digest_object.rb
393
+ - lib/abide_dev_utils/xccdf/parser/objects/numbered_object.rb
394
+ - new_diff.rb
367
395
  homepage: https://github.com/puppetlabs/abide_dev_utils
368
396
  licenses:
369
397
  - MIT
@@ -386,7 +414,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
386
414
  - !ruby/object:Gem::Version
387
415
  version: '0'
388
416
  requirements: []
389
- rubygems_version: 3.1.6
417
+ rubygems_version: 3.1.4
390
418
  signing_key:
391
419
  specification_version: 4
392
420
  summary: Helper utilities for developing compliance Puppet code