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.
- checksums.yaml +4 -4
- data/Gemfile.lock +80 -83
- data/abide_dev_utils.gemspec +2 -1
- data/lib/abide_dev_utils/cem.rb +72 -0
- data/lib/abide_dev_utils/cli/cem.rb +73 -0
- data/lib/abide_dev_utils/cli/jira.rb +1 -1
- data/lib/abide_dev_utils/cli/xccdf.rb +15 -1
- data/lib/abide_dev_utils/cli.rb +2 -0
- data/lib/abide_dev_utils/files.rb +34 -0
- data/lib/abide_dev_utils/version.rb +1 -1
- data/lib/abide_dev_utils/xccdf/diff/benchmark/number_title.rb +270 -0
- data/lib/abide_dev_utils/xccdf/diff/benchmark/profile.rb +104 -0
- data/lib/abide_dev_utils/xccdf/diff/benchmark/property.rb +127 -0
- data/lib/abide_dev_utils/xccdf/diff/benchmark/property_existence.rb +47 -0
- data/lib/abide_dev_utils/xccdf/diff/benchmark.rb +267 -0
- data/lib/abide_dev_utils/xccdf/diff/utils.rb +30 -0
- data/lib/abide_dev_utils/xccdf/diff.rb +233 -0
- data/lib/abide_dev_utils/xccdf/parser/objects/digest_object.rb +118 -0
- data/lib/abide_dev_utils/xccdf/parser/objects/numbered_object.rb +104 -0
- data/lib/abide_dev_utils/xccdf/parser/objects.rb +741 -0
- data/lib/abide_dev_utils/xccdf/parser.rb +52 -0
- data/lib/abide_dev_utils/xccdf.rb +24 -125
- data/new_diff.rb +48 -0
- metadata +33 -5
@@ -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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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: '
|
211
|
+
def gen_map(dir: nil, type: 'cis', parent_key_prefix: '', version_output_dir: false, **_)
|
235
212
|
os, ver = facter_platform
|
236
|
-
|
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
|
-
|
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.
|
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
|
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.
|
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.
|
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.
|
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
|