abide_dev_utils 0.9.7 → 0.11.0

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.
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