abide_dev_utils 0.9.7 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +7 -1
  4. data/Gemfile.lock +82 -64
  5. data/Rakefile +28 -0
  6. data/abide_dev_utils.gemspec +3 -1
  7. data/lib/abide_dev_utils/cem/benchmark.rb +291 -0
  8. data/lib/abide_dev_utils/cem/coverage_report.rb +348 -0
  9. data/lib/abide_dev_utils/cem/generate/reference.rb +116 -0
  10. data/lib/abide_dev_utils/cem/generate.rb +10 -0
  11. data/lib/abide_dev_utils/cem/mapping/mapper.rb +155 -0
  12. data/lib/abide_dev_utils/cem.rb +74 -0
  13. data/lib/abide_dev_utils/cli/cem.rb +153 -0
  14. data/lib/abide_dev_utils/cli/jira.rb +1 -1
  15. data/lib/abide_dev_utils/cli/xccdf.rb +15 -1
  16. data/lib/abide_dev_utils/cli.rb +2 -0
  17. data/lib/abide_dev_utils/errors/cem.rb +22 -0
  18. data/lib/abide_dev_utils/errors/general.rb +8 -2
  19. data/lib/abide_dev_utils/errors/ppt.rb +4 -0
  20. data/lib/abide_dev_utils/errors.rb +6 -0
  21. data/lib/abide_dev_utils/files.rb +34 -0
  22. data/lib/abide_dev_utils/markdown.rb +104 -0
  23. data/lib/abide_dev_utils/ppt/facter_utils.rb +140 -0
  24. data/lib/abide_dev_utils/ppt/hiera.rb +297 -0
  25. data/lib/abide_dev_utils/ppt/puppet_module.rb +74 -0
  26. data/lib/abide_dev_utils/ppt.rb +3 -5
  27. data/lib/abide_dev_utils/validate.rb +14 -0
  28. data/lib/abide_dev_utils/version.rb +1 -1
  29. data/lib/abide_dev_utils/xccdf/diff/benchmark/number_title.rb +270 -0
  30. data/lib/abide_dev_utils/xccdf/diff/benchmark/profile.rb +104 -0
  31. data/lib/abide_dev_utils/xccdf/diff/benchmark/property.rb +127 -0
  32. data/lib/abide_dev_utils/xccdf/diff/benchmark/property_existence.rb +47 -0
  33. data/lib/abide_dev_utils/xccdf/diff/benchmark.rb +267 -0
  34. data/lib/abide_dev_utils/xccdf/diff/utils.rb +30 -0
  35. data/lib/abide_dev_utils/xccdf/diff.rb +233 -0
  36. data/lib/abide_dev_utils/xccdf/parser/objects/digest_object.rb +118 -0
  37. data/lib/abide_dev_utils/xccdf/parser/objects/numbered_object.rb +104 -0
  38. data/lib/abide_dev_utils/xccdf/parser/objects.rb +741 -0
  39. data/lib/abide_dev_utils/xccdf/parser.rb +52 -0
  40. data/lib/abide_dev_utils/xccdf.rb +14 -124
  41. data/new_diff.rb +48 -0
  42. metadata +60 -9
  43. data/lib/abide_dev_utils/ppt/coverage.rb +0 -86
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'yaml'
5
+ require 'abide_dev_utils/markdown'
6
+ require 'abide_dev_utils/ppt'
7
+ require 'abide_dev_utils/cem/benchmark'
8
+
9
+ module AbideDevUtils
10
+ module CEM
11
+ module Generate
12
+ # Holds objects and methods for generating a reference doc
13
+ module Reference
14
+ MAPPING_PATH_KEY = 'Mapping Data'
15
+ RESOURCE_DATA_PATH_KEY = 'Resource Data'
16
+
17
+ def self.generate(data = {})
18
+ pupmod = AbideDevUtils::Ppt::PuppetModule.new
19
+ doc_title = case pupmod.name
20
+ when 'puppetlabs-cem_linux'
21
+ 'CEM Linux Reference'
22
+ when 'puppetlabs-cem_windows'
23
+ 'CEM Windows Reference'
24
+ else
25
+ 'Reference'
26
+ end
27
+ benchmarks = AbideDevUtils::CEM::Benchmark.benchmarks_from_puppet_module(pupmod)
28
+ case data.fetch(:format, 'markdown')
29
+ when 'markdown'
30
+ MarkdownGenerator.new(benchmarks).generate(doc_title)
31
+ else
32
+ raise "Format #{data[:format]} is unsupported! Only `markdown` format supported"
33
+ end
34
+ end
35
+
36
+ def self.generate_markdown
37
+ AbideDevUtils::Markdown.new('REFERENCE.md').generate
38
+ end
39
+
40
+ def self.config_example(control, params_array)
41
+ out_str = ['cem_windows::config:', ' control_configs:', " \"#{control}\":"]
42
+ indent = ' '
43
+ params_array.each do |param_hash|
44
+ val = case param_hash[:type]
45
+ when 'String'
46
+ "'#{param_hash[:default]}'"
47
+ else
48
+ param_hash[:default]
49
+ end
50
+
51
+ out_str << "#{indent}#{param_hash[:name]}: #{val}"
52
+ end
53
+ out_str.join("\n")
54
+ end
55
+
56
+ # Generates a markdown reference doc
57
+ class MarkdownGenerator
58
+ def initialize(benchmarks)
59
+ @benchmarks = benchmarks
60
+ @md = AbideDevUtils::Markdown.new('REFERENCE.md')
61
+ end
62
+
63
+ def generate(doc_title = 'Reference')
64
+ md.add_title(doc_title)
65
+ benchmarks.each do |benchmark|
66
+ md.add_h1(benchmark.title_key)
67
+ benchmark.rules.each do |title, rule|
68
+ md.add_h2("#{rule['number']} #{title}")
69
+ md.add_ul('Parameters:')
70
+ rule['params'].each do |p|
71
+ md.add_ul("#{md.code(p[:name])} - [ #{md.code(p[:type])} ] - #{md.italic('Default:')} #{md.code(p[:default])}", indent: 1)
72
+ end
73
+ md.add_ul('Config Example:')
74
+ example = config_example(benchmark.module_name, title, rule['params'])
75
+ md.add_code_block(example, language: 'yaml')
76
+ md.add_ul('Supported Levels:')
77
+ rule['level'].each do |l|
78
+ md.add_ul(md.code(l), indent: 1)
79
+ end
80
+ md.add_ul('Supported Profiles:')
81
+ rule['profile'].each do |l|
82
+ md.add_ul(md.code(l), indent: 1)
83
+ end
84
+ md.add_ul('Alternate Config IDs:')
85
+ rule['alternate_ids'].each do |l|
86
+ md.add_ul(md.code(l), indent: 1)
87
+ end
88
+ md.add_ul("Resource: #{md.code(rule['resource'].capitalize)}")
89
+ end
90
+ end
91
+ md.to_file
92
+ end
93
+
94
+ private
95
+
96
+ attr_reader :benchmarks, :md
97
+
98
+ def config_example(module_name, control, params_array)
99
+ out_str = ["#{module_name}::config:", ' control_configs:', " \"#{control}\":"]
100
+ indent = ' '
101
+ params_array.each do |param_hash|
102
+ val = case param_hash[:type]
103
+ when 'String'
104
+ "'#{param_hash[:default]}'"
105
+ else
106
+ param_hash[:default]
107
+ end
108
+ out_str << "#{indent}#{param_hash[:name]}: #{val}"
109
+ end
110
+ out_str.join("\n")
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AbideDevUtils
4
+ module CEM
5
+ # Holds objects and methods for `abide cem generate` subcommands
6
+ module Generate
7
+ require 'abide_dev_utils/cem/generate/reference'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AbideDevUtils
4
+ module CEM
5
+ module Mapping
6
+ # Handles interacting with mapping data
7
+ class Mapper
8
+ MAP_TYPES = %w[hiera_title_num number hiera_title vulnid title].freeze
9
+
10
+ attr_reader :module_name, :framework, :map_data
11
+
12
+ def initialize(module_name, framework, map_data)
13
+ @module_name = module_name
14
+ @framework = framework
15
+ load_framework(@framework)
16
+ @map_data = map_data
17
+ @cache = {}
18
+ @rule_cache = {}
19
+ end
20
+
21
+ def title
22
+ @title ||= benchmark_data['title']
23
+ end
24
+
25
+ def version
26
+ @version ||= benchmark_data['version']
27
+ end
28
+
29
+ def each_like(identifier)
30
+ mtype, mtop = map_type_and_top_key(identifier)
31
+ map_data[mtype][mtop].each { |key, val| yield key, val }
32
+ end
33
+
34
+ def each_with_array_like(identifier)
35
+ mtype, mtop = map_type_and_top_key(identifier)
36
+ map_data[mtype][mtop].each_with_object([]) { |(key, val), ary| yield [key, val], ary }
37
+ end
38
+
39
+ def get(control_id, level: nil, profile: nil)
40
+ return cache_get(control_id, level, profile) if cached?(control_id, level, profile)
41
+
42
+ value = get_map(control_id, level: level, profile: profile)
43
+ return if value.nil? || value.empty?
44
+
45
+ cache_set(value, control_id, level, profile)
46
+ value
47
+ end
48
+
49
+ def map_type(control_id)
50
+ return control_id if MAP_TYPES.include?(control_id)
51
+
52
+ case control_id
53
+ when %r{^c[0-9_]+$}
54
+ 'hiera_title_num'
55
+ when %r{^[0-9][0-9.]*$}
56
+ 'number'
57
+ when %r{^[a-z][a-z0-9_]+$}
58
+ 'hiera_title'
59
+ when %r{^V-[0-9]{6}$}
60
+ 'vulnid'
61
+ else
62
+ 'title'
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def load_framework(framework)
69
+ case framework.downcase
70
+ when 'cis'
71
+ self.class.include AbideDevUtils::CEM::Mapping::MixinCIS
72
+ extend AbideDevUtils::CEM::Mapping::MixinCIS
73
+ when 'stig'
74
+ self.class.include AbideDevUtils::CEM::Mapping::MixinSTIG
75
+ extend AbideDevUtils::CEM::Mapping::MixinSTIG
76
+ else
77
+ raise "Invalid framework: #{framework}"
78
+ end
79
+ end
80
+
81
+ def map_type_and_top_key(identifier)
82
+ mtype = MAP_TYPES.include?(identifier) ? identifier : map_type(identifier)
83
+ [mtype, map_top_key(mtype)]
84
+ end
85
+
86
+ def cached?(control_id, *args)
87
+ @cache.key?(cache_key(control_id, *args))
88
+ end
89
+
90
+ def cache_get(control_id, *args)
91
+ ckey = cache_key(control_id, *args)
92
+ @cache[ckey] if cached?(control_id, *args)
93
+ end
94
+
95
+ def cache_set(value, control_id, *args)
96
+ @cache[cache_key(control_id, *args)] = value unless value.nil?
97
+ end
98
+
99
+ def default_map_type
100
+ @default_map_type ||= (framework == 'stig' ? 'vulnid' : map_data.keys.first)
101
+ end
102
+
103
+ def benchmark_data
104
+ @benchmark_data ||= map_data[default_map_type][map_top_key(default_map_type)]['benchmark']
105
+ end
106
+
107
+ def cache_key(control_id, *args)
108
+ args.unshift(control_id).compact.join('-')
109
+ end
110
+
111
+ def map_top_key(mtype)
112
+ [module_name, 'mappings', framework, mtype].join('::')
113
+ end
114
+ end
115
+
116
+ # Mixin module used by Mapper to implement CIS-specific mapping behavior
117
+ module MixinCIS
118
+ def get_map(control_id, level: nil, profile: nil, **_)
119
+ mtype, mtop = map_type_and_top_key(control_id)
120
+ return if mtype == 'vulnid'
121
+
122
+ return map_data[mtype][mtop][level][profile][control_id] unless level.nil? || profile.nil?
123
+
124
+ map_data[mtype][mtop].each do |lvl, profile_hash|
125
+ next if lvl == 'benchmark'
126
+
127
+ profile_hash.each do |prof, control_hash|
128
+ return map_data[mtype][mtop][lvl][prof][control_id] if control_hash.key?(control_id)
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ # Mixin module used by Mapper to implement STIG-specific mapping behavior
135
+ module MixinSTIG
136
+ def get_map(control_id, level: nil, **_)
137
+ mtype, mtop = map_type_and_top_key(control_id)
138
+ return map_data[mtype][mtop][level][control_id] unless level.nil?
139
+
140
+ begin
141
+ map_data[mtype][mtop].each do |lvl, control_hash|
142
+ next if lvl == 'benchmark'
143
+
144
+ return control_hash[control_id] if control_hash.key?(control_id)
145
+ end
146
+ rescue NoMethodError => e
147
+ require 'pry'
148
+ binding.pry
149
+ #raise "Control ID: #{control_id}, Level: #{level}, #{e.message}"
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'abide_dev_utils/xccdf'
4
+ require 'abide_dev_utils/cem/coverage_report'
5
+ require 'abide_dev_utils/cem/generate'
6
+
7
+ module AbideDevUtils
8
+ # Methods for working with Compliance Enforcement Modules (CEM)
9
+ module CEM
10
+ def self.xccdf
11
+ return @xccdf if defined?(@xccdf)
12
+
13
+ xccdf = Object.new
14
+ xccdf.extend AbideDevUtils::XCCDF::Common
15
+ @xccdf = xccdf
16
+ @xccdf
17
+ end
18
+
19
+ def self.rule_id_format(rule_id)
20
+ case rule_id
21
+ when /^c[0-9_]+$/
22
+ :hiera_title_num
23
+ when /^[a-z][a-z0-9_]+$/
24
+ :hiera_title
25
+ when /^[0-9.]+$/
26
+ :number
27
+ else
28
+ :title
29
+ end
30
+ end
31
+
32
+ def self.rule_identifiers(rule_id)
33
+ {
34
+ number: xccdf.control_parts(rule_id).first,
35
+ hiera_title: xccdf.name_normalize_control(rule_id),
36
+ hiera_title_num: xccdf.number_normalize_control(rule_id),
37
+ }
38
+ end
39
+
40
+ def self.update_legacy_config_from_diff(config_hiera, diff)
41
+ new_config_hiera = config_hiera.dup
42
+ new_control_configs = {}
43
+ change_report = []
44
+ changes = diff.select { |d| d[:type][0] == :number }
45
+ config_hiera['config']['control_configs'].each do |key, val_hash|
46
+ key_id_format = rule_id_format(key)
47
+ changed = false
48
+ changes.each do |change|
49
+ if key_id_format == :title
50
+ next unless change[:title] == key
51
+ else
52
+ next unless rule_identifiers(change[:self].id)[key_id_format] == key
53
+ end
54
+
55
+ changed = true
56
+ new_key = if key_id_format == :title
57
+ change[:other_title]
58
+ else
59
+ rule_identifiers(change[:other].id)[key_id_format]
60
+ end
61
+ new_control_configs[new_key] = val_hash
62
+ change_report << {
63
+ type: :identifier_update,
64
+ from: key,
65
+ to: new_key,
66
+ }
67
+ end
68
+ new_control_configs[key] = val_hash unless changed
69
+ end
70
+ new_config_hiera['config']['control_configs'] = new_control_configs
71
+ [new_config_hiera, change_report]
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'abide_dev_utils/cem'
4
+ require 'abide_dev_utils/files'
5
+ require 'abide_dev_utils/output'
6
+ require 'abide_dev_utils/validate'
7
+ require 'abide_dev_utils/xccdf/diff/benchmark'
8
+ require 'abide_dev_utils/cli/abstract'
9
+
10
+ module Abide
11
+ module CLI
12
+ class CemCommand < AbideCommand
13
+ CMD_NAME = 'cem'
14
+ CMD_SHORT = 'Commands related to Puppet CEM'
15
+ CMD_LONG = 'Namespace for commands related to Puppet CEM'
16
+ def initialize
17
+ super(CMD_NAME, CMD_SHORT, CMD_LONG, takes_commands: true)
18
+ add_command(CemGenerate.new)
19
+ add_command(CemUpdateConfig.new)
20
+ end
21
+ end
22
+
23
+ class CemGenerate < AbideCommand
24
+ CMD_NAME = 'generate'
25
+ CMD_SHORT = 'Holds subcommands for generating objects / files'
26
+ CMD_LONG = 'Holds subcommands for generating objects / files'
27
+ def initialize
28
+ super(CMD_NAME, CMD_SHORT, CMD_LONG, takes_commands: true)
29
+ add_command(CemGenerateCoverageReport.new)
30
+ add_command(CemGenerateReference.new)
31
+ end
32
+ end
33
+
34
+ class CemGenerateCoverageReport < AbideCommand
35
+ CMD_NAME = 'coverage-report'
36
+ CMD_SHORT = 'Generates control coverage report'
37
+ CMD_LONG = <<-EOLC.chomp
38
+ Generates report of resources that are associated with controls in mapping data. This command must
39
+ be run from a module directory.
40
+ EOLC
41
+ def initialize
42
+ super(CMD_NAME, CMD_SHORT, CMD_LONG, takes_commands: false)
43
+ options.on('-o [FILE]', '--out-file [FILE]', 'Path to save the coverage report') { |f| @data[:file] = f }
44
+ options.on('-f [FORMAT]', '--format [FORMAT]', 'The format to output the report in (hash, json, yaml)') do |f|
45
+ @data[:format] = f
46
+ end
47
+ options.on('-I', '--ignore-benchmark-errors', 'Ignores errors while generating benchmark reports') do
48
+ @data[:ignore_all] = true
49
+ end
50
+ options.on('-v', '--verbose', 'Will output the report to the console') { @data[:verbose] = true }
51
+ options.on('-q', '--quiet', 'Will not output anything to the console') { @data[:quiet] = true }
52
+ end
53
+
54
+ def execute
55
+ file_name = @data.fetch(:file, 'coverage_report')
56
+ out_format = @data.fetch(:format, 'yaml')
57
+ quiet = @data.fetch(:quiet, false)
58
+ console = @data.fetch(:verbose, false) && !quiet
59
+ ignore_all = @data.fetch(:ignore_all, false)
60
+ AbideDevUtils::Output.simple('Generating coverage report...') unless quiet
61
+ coverage = AbideDevUtils::CEM::CoverageReport.basic_coverage(format_func: :to_h, ignore_benchmark_errors: ignore_all)
62
+ AbideDevUtils::Output.simple("Saving coverage report to #{file_name}...")
63
+ case out_format
64
+ when /yaml/i
65
+ AbideDevUtils::Output.yaml(coverage, console: console, file: file_name)
66
+ when /json/i
67
+ AbideDevUtils::Output.json(coverage, console: console, file: file_name)
68
+ else
69
+ File.open(file_name, 'w') do |f|
70
+ AbideDevUtils::Output.simple(coverage.to_s, stream: f)
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ class CemGenerateReference < AbideCommand
77
+ CMD_NAME = 'reference'
78
+ CMD_SHORT = 'Generates a reference doc for the module'
79
+ CMD_LONG = 'Generates a reference doc for the module'
80
+ def initialize
81
+ super(CMD_NAME, CMD_SHORT, CMD_LONG, takes_commands: false)
82
+ options.on('-o [FILE]', '--out-file [FILE]', 'Path to save the updated config file') do |o|
83
+ @data[:out_file] = o
84
+ end
85
+ options.on('-f [FORMAT]', '--format [FORMAT]', 'Format to save reference as') do |f|
86
+ @data[:format] = f
87
+ end
88
+ options.on('-v', '--verbose', 'Verbose output') do
89
+ @data[:verbose] = true
90
+ end
91
+ options.on('-q', '--quiet', 'Quiet output') do
92
+ @data[:quiet] = true
93
+ end
94
+ end
95
+
96
+ def execute
97
+ AbideDevUtils::Validate.puppet_module_directory
98
+ AbideDevUtils::CEM::Generate::Reference.generate(@data)
99
+ end
100
+ end
101
+
102
+ class CemUpdateConfig < AbideCommand
103
+ CMD_NAME = 'update-config'
104
+ CMD_SHORT = 'Updates the Puppet CEM config'
105
+ CMD_LONG = 'Updates the Puppet CEM config'
106
+ def initialize
107
+ super(CMD_NAME, CMD_SHORT, CMD_LONG, takes_commands: true)
108
+ add_command(CemUpdateConfigFromDiff.new)
109
+ end
110
+ end
111
+
112
+ class CemUpdateConfigFromDiff < AbideCommand
113
+ CMD_NAME = 'from-diff'
114
+ CMD_SHORT = 'Update by diffing two XCCDF files'
115
+ CMD_LONG = 'Update by diffing two XCCDF files'
116
+ CMD_CONFIG_FILE = 'Path to the Puppet CEM config file'
117
+ CMD_CURRENT_XCCDF = 'Path to the current XCCDF file'
118
+ CMD_NEW_XCCDF = 'Path to the new XCCDF file'
119
+ def initialize
120
+ super(CMD_NAME, CMD_SHORT, CMD_LONG, takes_commands: false)
121
+ argument_desc(CONFIG_FILE: CMD_CONFIG_FILE, CURRENT_XCCDF: CMD_CURRENT_XCCDF, NEW_XCCDF: CMD_NEW_XCCDF)
122
+ options.on('-o [FILE]', '--out-file [FILE]', 'Path to save the updated config file') do |o|
123
+ @data[:out_file] = o
124
+ end
125
+ options.on('-v', '--verbose', 'Verbose output') do
126
+ @data[:verbose] = true
127
+ end
128
+ options.on('-q', '--quiet', 'Quiet output') do
129
+ @data[:quiet] = true
130
+ end
131
+ end
132
+
133
+ def help_arguments
134
+ <<~ARGHELP
135
+ Arguments:
136
+ CONFIG_FILE: #{CMD_CONFIG_FILE}
137
+ CURRENT_XCCDF: #{CMD_CURRENT_XCCDF}
138
+ NEW_XCCDF: #{CMD_NEW_XCCDF}
139
+ ARGHELP
140
+ end
141
+
142
+ def execute(config_file, cur_xccdf, new_xccdf)
143
+ AbideDevUtils::Validate.file(config_file, extension: 'yaml')
144
+ AbideDevUtils::Validate.file(cur_xccdf, extension: 'xml')
145
+ config_hiera = AbideDevUtils::Files::Reader.read(config_file, safe: true)
146
+ diff = AbideDevUtils::XCCDF::Diff::BenchmarkDiff.new(cur_xccdf, new_xccdf).diff[:diff][:number_title]
147
+ new_config_hiera, change_report = AbideDevUtils::CEM.update_legacy_config_from_diff(config_hiera, diff)
148
+ AbideDevUtils::Output.yaml(new_config_hiera, console: @data[:verbose], file: @data[:out_file])
149
+ AbideDevUtils::Output.simple(change_report) unless @data[:quiet]
150
+ end
151
+ end
152
+ end
153
+ end
@@ -37,7 +37,7 @@ module Abide
37
37
 
38
38
  def execute
39
39
  client = JIRA.client
40
- myself = JIRA.get_myself(client)
40
+ myself = JIRA.myself(client)
41
41
  return if myself.attrs['name'].empty?
42
42
 
43
43
  Abide::CLI::OUTPUT.simple("Successfully authenticated user #{myself.attrs['name']}!")
@@ -34,6 +34,9 @@ module Abide
34
34
  options.on('-d [DIR]', '--files-output-directory [DIR]', 'Directory to save files data/mappings by default') do |d|
35
35
  @data[:dir] = d
36
36
  end
37
+ options.on('-V', '--version-output-dir', 'If saving to a directory, version the output directory') do
38
+ @data[:version_output_dir] = true
39
+ end
37
40
  options.on('-q', '--quiet', 'Show no output in the terminal') { @data[:quiet] = true }
38
41
  options.on('-p [PREFIX]', '--parent-key-prefix [PREFIX]', 'A prefix to append to the parent key') do |p|
39
42
  @data[:parent_key_prefix] = p
@@ -104,13 +107,24 @@ module Abide
104
107
  options.on('-p [PROFILE]', '--profile', 'Only diff and specific profile in the benchmarks') do |x|
105
108
  @data[:profile] = x
106
109
  end
110
+ options.on('-l [LEVEL]', '--level', 'Only diff the specific level in the benchmarks') do |x|
111
+ @data[:level] = x
112
+ end
113
+ options.on('-r', '--raw', 'Output the diff in raw hash format') { @data[:raw] = true }
107
114
  options.on('-q', '--quiet', 'Show no output in the terminal') { @data[:quiet] = false }
108
115
  options.on('--no-diff-profiles', 'Do not diff the profiles in the XCCDF files') { @data[:diff_profiles] = false }
109
116
  options.on('--no-diff-controls', 'Do not diff the controls in the XCCDF files') { @data[:diff_controls] = false }
117
+ options.on('--old-style', 'Use old-style diffs') { @data[:old_style] = true }
110
118
  end
111
119
 
112
120
  def execute(file1, file2)
113
- diffreport = AbideDevUtils::XCCDF.diff(file1, file2, @data)
121
+ diffreport = if @data[:old_style]
122
+ AbideDevUtils::XCCDF.diff(file1, file2, @data)
123
+ else
124
+ dr = AbideDevUtils::XCCDF.new_style_diff(file1, file2, @data)
125
+ dr[:diff][:number_title].map! { |d| d[:text] }
126
+ dr
127
+ end
114
128
  AbideDevUtils::Output.yaml(diffreport, console: @data.fetch(:quiet, true), file: @data.fetch(:outfile, nil))
115
129
  end
116
130
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'cmdparse'
4
4
  require 'abide_dev_utils/version'
5
+ require 'abide_dev_utils/cli/cem'
5
6
  require 'abide_dev_utils/constants'
6
7
  require 'abide_dev_utils/cli/comply'
7
8
  require 'abide_dev_utils/cli/puppet'
@@ -22,6 +23,7 @@ module Abide
22
23
  parser.main_options.banner = ROOT_CMD_BANNER
23
24
  parser.add_command(CmdParse::HelpCommand.new, default: true)
24
25
  parser.add_command(CmdParse::VersionCommand.new(add_switches: true))
26
+ parser.add_command(CemCommand.new)
25
27
  parser.add_command(ComplyCommand.new)
26
28
  parser.add_command(PuppetCommand.new)
27
29
  parser.add_command(XccdfCommand.new)
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'abide_dev_utils/errors/base'
4
+
5
+ module AbideDevUtils
6
+ module Errors
7
+ # Raised by Benchmark when mapping data cannot be loaded
8
+ class MappingFilesNotFoundError < GenericError
9
+ @default = 'Mapping files not found using facts:'
10
+ end
11
+
12
+ # Raised by Benchmark when mapping files are not found for the specified framework
13
+ class MappingDataFrameworkMismatchError < GenericError
14
+ @default = 'Mapping data could not be found for the specified framework:'
15
+ end
16
+
17
+ # Raised by Benchmark when resource data cannot be loaded
18
+ class ResourceDataNotFoundError < GenericError
19
+ @default = 'Resource data not found using facts:'
20
+ end
21
+ end
22
+ end
@@ -9,7 +9,12 @@ module AbideDevUtils
9
9
  @default = 'Object is empty and should not be:'
10
10
  end
11
11
 
12
- # Raised when a an object is initialized with a nil param
12
+ # Raised when something is not a string, or is an empty string
13
+ class NotPopulatedStringError < GenericError
14
+ @default = 'Object is either not a String or is empty:'
15
+ end
16
+
17
+ # Raised when an object is initialized with a nil param
13
18
  class NewObjectParamNilError < GenericError
14
19
  @default = 'Object init parameter is nil and should not be:'
15
20
  end
@@ -54,8 +59,9 @@ module AbideDevUtils
54
59
  @default = 'Object does not respond to #to_hash or #to_h:'
55
60
  end
56
61
 
62
+ # Raised when conflicting CLI options are specified for a command
57
63
  class CliOptionsConflict < GenericError
58
- @default = "Console options conflict."
64
+ @default = 'Console options conflict:'
59
65
  end
60
66
  end
61
67
  end
@@ -5,6 +5,10 @@ require 'abide_dev_utils/errors/base'
5
5
  module AbideDevUtils
6
6
  module Errors
7
7
  module Ppt
8
+ class NotModuleDirError < GenericError
9
+ @default = 'Path is not a Puppet module directory:'
10
+ end
11
+
8
12
  class ObjClassPathError < GenericError
9
13
  @default = 'Invalid path for class:'
10
14
  end
@@ -1,9 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'abide_dev_utils/errors/base'
4
+ require 'abide_dev_utils/errors/cem'
4
5
  require 'abide_dev_utils/errors/comply'
5
6
  require 'abide_dev_utils/errors/gcloud'
6
7
  require 'abide_dev_utils/errors/general'
7
8
  require 'abide_dev_utils/errors/jira'
8
9
  require 'abide_dev_utils/errors/xccdf'
9
10
  require 'abide_dev_utils/errors/ppt'
11
+
12
+ module AbideDevUtils
13
+ # Namespace for Error objects
14
+ module Errors; end
15
+ end