inspec_tools 2.0.3 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,35 @@
1
+ module InspecTools
2
+ class GenerateMap
3
+ attr_accessor :text
4
+
5
+ def initialize(text = nil)
6
+ @text = text.nil? ? default_text : text
7
+ end
8
+
9
+ def generate_example(file)
10
+ File.write(file, @text)
11
+ end
12
+
13
+ private
14
+
15
+ def default_text
16
+ <<~YML
17
+ # Setting csv_header to true will skip the csv file header
18
+ skip_csv_header: true
19
+ width : 80
20
+
21
+
22
+ control.id: 0
23
+ control.title: 15
24
+ control.desc: 16
25
+ control.tags:
26
+ severity: 1
27
+ rid: 8
28
+ stig_id: 3
29
+ cci: 2
30
+ check: 12
31
+ fix: 10
32
+ YML
33
+ end
34
+ end
35
+ end
@@ -9,17 +9,14 @@ require_relative '../happy_mapper_tools/stig_checklist'
9
9
  require_relative '../happy_mapper_tools/benchmark'
10
10
  require_relative '../utilities/inspec_util'
11
11
  require_relative 'csv'
12
-
13
- # rubocop:disable Metrics/ClassLength
14
- # rubocop:disable Metrics/AbcSize
15
- # rubocop:disable Metrics/BlockLength
16
- # rubocop:disable Style/GuardClause
12
+ require_relative '../utilities/xccdf/from_inspec'
13
+ require_relative '../utilities/xccdf/to_xccdf'
17
14
 
18
15
  module InspecTools
19
- class Inspec
20
- def initialize(inspec_json, metadata = '{}')
16
+ class Inspec # rubocop:disable Metrics/ClassLength
17
+ def initialize(inspec_json, metadata = {})
21
18
  @json = JSON.parse(inspec_json.gsub(/\\+u0000/, ''))
22
- @metadata = JSON.parse(metadata)
19
+ @metadata = metadata
23
20
  end
24
21
 
25
22
  def to_ckl(title = nil, date = nil, cklist = nil)
@@ -36,16 +33,15 @@ module InspecTools
36
33
  @checklist.to_xml.encode('UTF-8').gsub('<?xml version="1.0"?>', '<?xml version="1.0" encoding="UTF-8"?>').chomp
37
34
  end
38
35
 
36
+ # Convert Inspec result data to XCCDF
37
+ #
38
+ # @param attributes [Hash] Optional input attributes
39
+ # @return [String] XML formatted String
39
40
  def to_xccdf(attributes, verbose = false)
40
- @data = Utils::InspecUtil.parse_data_for_xccdf(@json)
41
- @attribute = attributes
42
- @attribute = {} if @attribute.eql? false
41
+ data = Utils::FromInspec.new.parse_data_for_xccdf(@json)
43
42
  @verbose = verbose
44
- @benchmark = HappyMapperTools::Benchmark::Benchmark.new
45
- populate_header
46
- # populate_profiles @todo populate profiles; not implemented now because its use is deprecated
47
- populate_groups
48
- @benchmark.to_xml
43
+
44
+ Utils::ToXCCDF.new(attributes || {}, data).to_xml(@metadata)
49
45
  end
50
46
 
51
47
  ####
@@ -70,7 +66,7 @@ module InspecTools
70
66
  #
71
67
  # @param inspec_json : an inspec profile formatted as a json object
72
68
  ###
73
- def inspec_json_to_array(inspec_json)
69
+ def inspec_json_to_array(inspec_json) # rubocop:disable Metrics/CyclomaticComplexity
74
70
  data = []
75
71
  headers = {}
76
72
  inspec_json['controls'].each do |control|
@@ -97,10 +93,11 @@ module InspecTools
97
93
  @data['controls'] << control
98
94
  end
99
95
  end
100
- if json['profiles'].nil?
101
- json['controls'].each do |control|
102
- @data['controls'] << control
103
- end
96
+
97
+ return unless json['profiles'].nil?
98
+
99
+ json['controls'].each do |control|
100
+ @data['controls'] << control
104
101
  end
105
102
  end
106
103
 
@@ -161,7 +158,7 @@ module InspecTools
161
158
  vuln
162
159
  end
163
160
 
164
- def generate_asset
161
+ def generate_asset # rubocop:disable Metrics/AbcSize
165
162
  asset = HappyMapperTools::StigChecklist::Asset.new
166
163
  asset.role = !@metadata['role'].nil? ? @metadata['role'] : 'Workstation'
167
164
  asset.type = !@metadata['type'].nil? ? @metadata['type'] : 'Computing'
@@ -223,75 +220,6 @@ module InspecTools
223
220
  ip
224
221
  end
225
222
 
226
- def populate_header
227
- @benchmark.title = @attribute['benchmark.title']
228
- @benchmark.id = @attribute['benchmark.id']
229
- @benchmark.description = @attribute['benchmark.description']
230
- @benchmark.version = @attribute['benchmark.version']
231
-
232
- @benchmark.status = HappyMapperTools::Benchmark::Status.new
233
- @benchmark.status.status = @attribute['benchmark.status']
234
- @benchmark.status.date = @attribute['benchmark.status.date']
235
-
236
- @benchmark.notice = HappyMapperTools::Benchmark::Notice.new
237
- @benchmark.notice.id = @attribute['benchmark.notice.id']
238
-
239
- @benchmark.plaintext = HappyMapperTools::Benchmark::Plaintext.new
240
- @benchmark.plaintext.plaintext = @attribute['benchmark.plaintext']
241
- @benchmark.plaintext.id = @attribute['benchmark.plaintext.id']
242
-
243
- @benchmark.reference = HappyMapperTools::Benchmark::ReferenceBenchmark.new
244
- @benchmark.reference.href = @attribute['reference.href']
245
- @benchmark.reference.dc_publisher = @attribute['reference.dc.publisher']
246
- @benchmark.reference.dc_source = @attribute['reference.dc.source']
247
- end
248
-
249
- def populate_groups
250
- group_array = []
251
- @data['controls'].each do |control|
252
- group = HappyMapperTools::Benchmark::Group.new
253
- group.id = control['id']
254
- group.title = control['gtitle']
255
- group.description = "<GroupDescription>#{control['gdescription']}</GroupDescription>"
256
-
257
- group.rule = HappyMapperTools::Benchmark::Rule.new
258
- group.rule.id = control['rid']
259
- group.rule.severity = control['severity']
260
- group.rule.weight = control['rweight']
261
- group.rule.version = control['rversion']
262
- group.rule.title = control['title'].tr("\n", ' ')
263
- group.rule.description = "<VulnDiscussion>#{control['desc'].tr("\n", ' ')}</VulnDiscussion><FalsePositives></FalsePositives><FalseNegatives></FalseNegatives><Documentable>false</Documentable><Mitigations></Mitigations><SeverityOverrideGuidance></SeverityOverrideGuidance><PotentialImpacts></PotentialImpacts><ThirdPartyTools></ThirdPartyTools><MitigationControl></MitigationControl><Responsibility></Responsibility><IAControls></IAControls>"
264
-
265
- group.rule.reference = HappyMapperTools::Benchmark::ReferenceGroup.new
266
- group.rule.reference.dc_publisher = @attribute['reference.dc.publisher']
267
- group.rule.reference.dc_title = @attribute['reference.dc.title']
268
- group.rule.reference.dc_subject = @attribute['reference.dc.subject']
269
- group.rule.reference.dc_type = @attribute['reference.dc.type']
270
- group.rule.reference.dc_identifier = @attribute['reference.dc.identifier']
271
-
272
- group.rule.ident = HappyMapperTools::Benchmark::Ident.new
273
- group.rule.ident.system = 'https://public.cyber.mil/stigs/cci/'
274
- group.rule.ident.ident = control['cci']
275
-
276
- group.rule.fixtext = HappyMapperTools::Benchmark::Fixtext.new
277
- group.rule.fixtext.fixref = control['fixref']
278
- group.rule.fixtext.fixtext = control['fix']
279
-
280
- group.rule.fix = HappyMapperTools::Benchmark::Fix.new
281
- group.rule.fix.id = control['fixref']
282
-
283
- group.rule.check = HappyMapperTools::Benchmark::Check.new
284
- group.rule.check.system = control['checkref']
285
- group.rule.check.content_ref = HappyMapperTools::Benchmark::ContentRef.new
286
- group.rule.check.content_ref.name = @attribute['content_ref.name']
287
- group.rule.check.content_ref.href = @attribute['content_ref.href']
288
- group.rule.check.content = control['check']
289
-
290
- group_array << group
291
- end
292
- @benchmark.group = group_array
293
- end
294
-
295
223
  def generate_title(title, json, date)
296
224
  title ||= "Untitled - Checklist Created from Automated InSpec Results JSON; Profiles: #{json['profiles'].map { |x| x['name'] }.join(' | ')}"
297
225
  title + " Checklist Date: #{date || Date.today.to_s}"
@@ -2,9 +2,9 @@ require 'digest'
2
2
 
3
3
  require_relative '../utilities/inspec_util'
4
4
  require_relative '../utilities/extract_pdf_text'
5
- require_relative '../utilities/extract_nist_cis_mapping'
6
5
  require_relative '../utilities/parser'
7
6
  require_relative '../utilities/text_cleaner'
7
+ require_relative '../utilities/cis_to_nist'
8
8
 
9
9
  # rubocop:disable Metrics/AbcSize
10
10
  # rubocop:disable Metrics/PerceivedComplexity
@@ -24,7 +24,7 @@ module InspecTools
24
24
  @controls = []
25
25
  @csv_handle = nil
26
26
  @cci_xml = nil
27
- @nist_mapping = nil
27
+ @nist_mapping = Utils::CisToNist.get_mapping('cis_to_nist_critical_controls')
28
28
  @pdf_text = ''
29
29
  @clean_text = ''
30
30
  @transformed_data = ''
@@ -33,7 +33,6 @@ module InspecTools
33
33
  @title ||= extract_title
34
34
  clean_pdf_text
35
35
  transform_data
36
- read_excl
37
36
  insert_json_metadata
38
37
  @profile['controls'] = parse_controls
39
38
  @profile['sha256'] = Digest::SHA256.hexdigest @profile.to_s
@@ -122,15 +121,5 @@ module InspecTools
122
121
  def write_clean_text
123
122
  File.write('debug_text', @clean_text)
124
123
  end
125
-
126
- def read_excl
127
- nist_map_path = File.join(File.dirname(__FILE__), '../data/NIST_Map_09212017B_CSC-CIS_Critical_Security_Controls_VER_6.1_Excel_9.1.2016.xlsx')
128
- excel = Util::ExtractNistMappings.new(nist_map_path)
129
- @nist_mapping = excel.full_excl
130
- rescue StandardError => e
131
- puts "Exception: #{e.message}"
132
- puts 'Existing...'
133
- exit
134
- end
135
124
  end
136
125
  end
@@ -15,6 +15,7 @@ module InspecTools
15
15
  autoload :Summary, 'inspec_tools/summary'
16
16
  autoload :Threshold, 'inspec_tools/threshold'
17
17
  autoload :XLSXTool, 'inspec_tools/xlsx_tool'
18
+ autoload :GenerateMap, 'inspec_tools/generate_map'
18
19
  end
19
20
 
20
21
  # rubocop:disable Style/GuardClause
@@ -23,7 +24,7 @@ module InspecPlugins
23
24
  class CliCommand < Inspec.plugin(2, :cli_command) # rubocop:disable Metrics/ClassLength
24
25
  POSSIBLE_LOG_LEVELS = %w{debug info warn error fatal}.freeze
25
26
 
26
- class_option :log_directory, type: :string, aliases: :l, desc: 'Provie log location'
27
+ class_option :log_directory, type: :string, aliases: :l, desc: 'Provide log location'
27
28
  class_option :log_level, type: :string, desc: "Set the logging level: #{POSSIBLE_LOG_LEVELS}"
28
29
 
29
30
  subcommand_desc 'tools [COMMAND]', 'Runs inspec_tools commands through Inspec'
@@ -54,12 +55,18 @@ module InspecPlugins
54
55
 
55
56
  desc 'inspec2xccdf', 'inspec2xccdf translates an inspec profile and attributes files to an xccdf file'
56
57
  long_desc InspecTools::Help.text(:inspec2xccdf)
57
- option :inspec_json, required: true, aliases: '-j'
58
- option :attributes, required: true, aliases: '-a'
59
- option :output, required: true, aliases: '-o'
58
+ option :inspec_json, required: true, aliases: '-j',
59
+ desc: 'path to InSpec JSON file created'
60
+ option :attributes, required: true, aliases: '-a',
61
+ desc: 'path to yml file that provides the required attributes for the XCCDF document. These attributes are parts of XCCDF document which do not fit into the InSpec schema.'
62
+ option :output, required: true, aliases: '-o',
63
+ desc: 'name or path to create the XCCDF and title to give the XCCDF'
64
+ option :metadata, required: false, type: :string, aliases: '-m',
65
+ desc: 'path to JSON file with additional host metadata for the XCCDF file'
60
66
  def inspec2xccdf
61
67
  json = File.read(options[:inspec_json])
62
- inspec_tool = InspecTools::Inspec.new(json)
68
+ metadata = options[:metadata] ? JSON.parse(File.read(options[:metadata])) : {}
69
+ inspec_tool = InspecTools::Inspec.new(json, metadata)
63
70
  attr_hsh = YAML.load_file(options[:attributes])
64
71
  xccdf = inspec_tool.to_xccdf(attr_hsh)
65
72
  File.write(options[:output], xccdf)
@@ -136,26 +143,8 @@ module InspecPlugins
136
143
 
137
144
  desc 'generate_map', 'Generates mapping template from CSV to Inspec Controls'
138
145
  def generate_map
139
- template = '
140
- # Setting csv_header to true will skip the csv file header
141
- skip_csv_header: true
142
- width : 80
143
-
144
-
145
- control.id: 0
146
- control.title: 15
147
- control.desc: 16
148
- control.tags:
149
- severity: 1
150
- rid: 8
151
- stig_id: 3
152
- cci: 2
153
- check: 12
154
- fix: 10
155
- '
156
- myfile = File.new('mapping.yml', 'w')
157
- myfile.puts template
158
- myfile.close
146
+ generator = InspecTools::GenerateMap.new
147
+ generator.generate_example('mapping.yml')
159
148
  end
160
149
 
161
150
  desc 'generate_ckl_metadata', 'Generate metadata file that can be passed to inspec2ckl'
@@ -140,6 +140,7 @@ module InspecTools
140
140
  control['tags']['documentable'] = group.rule.description.documentable if group.rule.description.documentable != ''
141
141
  control['tags']['mitigations'] = group.rule.description.false_negatives if group.rule.description.mitigations != ''
142
142
  control['tags']['severity_override_guidance'] = group.rule.description.severity_override_guidance if group.rule.description.severity_override_guidance != ''
143
+ control['tags']['security_override_guidance'] = group.rule.description.security_override_guidance if group.rule.description.security_override_guidance != ''
143
144
  control['tags']['potential_impacts'] = group.rule.description.potential_impacts if group.rule.description.potential_impacts != ''
144
145
  control['tags']['third_party_tools'] = group.rule.description.third_party_tools if group.rule.description.third_party_tools != ''
145
146
  control['tags']['mitigation_controls'] = group.rule.description.mitigation_controls if group.rule.description.mitigation_controls != ''
@@ -3,9 +3,10 @@ require 'inspec-objects'
3
3
  require 'word_wrap'
4
4
  require 'yaml'
5
5
  require 'digest'
6
- require 'roo'
7
6
 
8
7
  require_relative '../utilities/inspec_util'
8
+ require_relative '../utilities/cis_to_nist'
9
+ require_relative '../utilities/mapping_validator'
9
10
 
10
11
  # rubocop:disable Metrics/AbcSize
11
12
  # rubocop:disable Metrics/PerceivedComplexity
@@ -14,15 +15,14 @@ require_relative '../utilities/inspec_util'
14
15
  module InspecTools
15
16
  # Methods for converting from XLS to various formats
16
17
  class XLSXTool
17
- CIS_2_NIST_XLSX = Roo::Spreadsheet.open(File.join(File.dirname(__FILE__), '../data/NIST_Map_02052020_CIS_Controls_Version_7.1_Implementation_Groups_1.2.xlsx'))
18
18
  LATEST_NIST_REV = 'Rev_4'.freeze
19
19
 
20
20
  def initialize(xlsx, mapping, name, verbose = false)
21
21
  @name = name
22
22
  @xlsx = xlsx
23
- @mapping = mapping
23
+ @mapping = Utils::MappingValidator.validate(mapping)
24
24
  @verbose = verbose
25
- @cis_to_nist = get_cis_to_nist_control_mapping(CIS_2_NIST_XLSX)
25
+ @cis_to_nist = Utils::CisToNist.get_mapping('cis_to_nist_mapping')
26
26
  end
27
27
 
28
28
  def to_ckl
@@ -46,18 +46,6 @@ module InspecTools
46
46
 
47
47
  private
48
48
 
49
- def get_cis_to_nist_control_mapping(spreadsheet)
50
- cis_to_nist = {}
51
- spreadsheet.sheet(3).each do |row|
52
- if row[3].is_a? Numeric
53
- cis_to_nist[row[3].to_s] = row[0]
54
- else
55
- cis_to_nist[row[2].to_s] = row[0] unless (row[2] == '') || row[2].to_i.nil?
56
- end
57
- end
58
- cis_to_nist
59
- end
60
-
61
49
  def insert_json_metadata
62
50
  @profile['name'] = @name
63
51
  @profile['title'] = 'InSpec Profile'
@@ -0,0 +1,13 @@
1
+ require 'nokogiri'
2
+
3
+ module Utils
4
+ class CciXml
5
+ def self.get_cci_list(cci_list_file)
6
+ path = File.expand_path(File.join(File.expand_path(__dir__), '..', 'data', cci_list_file))
7
+ raise "CCI list does not exist at #{path}" unless File.exist?(path)
8
+
9
+ cci_list = Nokogiri::XML(File.open(path))
10
+ cci_list.remove_namespaces!
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ module Utils
2
+ class CisToNist
3
+ def self.get_mapping(mapping_file)
4
+ path = File.expand_path(File.join(File.expand_path(__dir__), '..', 'data', mapping_file))
5
+ raise "CIS to NIST control mapping does not exist at #{path}. Has it been generated?" unless File.exist?(path)
6
+
7
+ mapping = File.open(path)
8
+ Marshal.load(mapping)
9
+ end
10
+ end
11
+ end
@@ -11,16 +11,10 @@ require 'overrides/true_class'
11
11
  require 'overrides/nil_class'
12
12
  require 'overrides/object'
13
13
  require 'overrides/string'
14
-
15
- # rubocop:disable Metrics/ClassLength
16
- # rubocop:disable Metrics/AbcSize
17
- # rubocop:disable Metrics/PerceivedComplexity
18
- # rubocop:disable Metrics/CyclomaticComplexity
19
- # rubocop:disable Metrics/MethodLength
14
+ require 'rubocop'
20
15
 
21
16
  module Utils
22
- class InspecUtil
23
- DATA_NOT_FOUND_MESSAGE = 'N/A'.freeze
17
+ class InspecUtil # rubocop:disable Metrics/ClassLength
24
18
  WIDTH = 80
25
19
  IMPACT_SCORES = {
26
20
  'none' => 0.0,
@@ -30,56 +24,7 @@ module Utils
30
24
  'critical' => 0.9
31
25
  }.freeze
32
26
 
33
- def self.parse_data_for_xccdf(json)
34
- data = {}
35
-
36
- controls = []
37
- if json['profiles'].nil?
38
- controls = json['controls']
39
- elsif json['profiles'].length == 1
40
- controls = json['profiles'].last['controls']
41
- else
42
- json['profiles'].each do |profile|
43
- controls.concat(profile['controls'])
44
- end
45
- end
46
- c_data = {}
47
-
48
- controls.each do |control|
49
- c_id = control['id'].to_sym
50
- c_data[c_id] = {}
51
- c_data[c_id]['id'] = control['id'] || DATA_NOT_FOUND_MESSAGE
52
- c_data[c_id]['title'] = control['title'] || DATA_NOT_FOUND_MESSAGE
53
- c_data[c_id]['desc'] = control['desc'] || DATA_NOT_FOUND_MESSAGE
54
- c_data[c_id]['severity'] = control['tags']['severity'] || DATA_NOT_FOUND_MESSAGE
55
- c_data[c_id]['gid'] = control['tags']['gid'] || DATA_NOT_FOUND_MESSAGE
56
- c_data[c_id]['gtitle'] = control['tags']['gtitle'] || DATA_NOT_FOUND_MESSAGE
57
- c_data[c_id]['gdescription'] = control['tags']['gdescription'] || DATA_NOT_FOUND_MESSAGE
58
- c_data[c_id]['rid'] = control['tags']['rid'] || DATA_NOT_FOUND_MESSAGE
59
- c_data[c_id]['rversion'] = control['tags']['rversion'] || DATA_NOT_FOUND_MESSAGE
60
- c_data[c_id]['rweight'] = control['tags']['rweight'] || DATA_NOT_FOUND_MESSAGE
61
- c_data[c_id]['stig_id'] = control['tags']['stig_id'] || DATA_NOT_FOUND_MESSAGE
62
- c_data[c_id]['cci'] = control['tags']['cci'] || DATA_NOT_FOUND_MESSAGE
63
- c_data[c_id]['nist'] = control['tags']['nist'] || ['unmapped']
64
- c_data[c_id]['check'] = control['tags']['check'] || DATA_NOT_FOUND_MESSAGE
65
- c_data[c_id]['checkref'] = control['tags']['checkref'] || DATA_NOT_FOUND_MESSAGE
66
- c_data[c_id]['fix'] = control['tags']['fix'] || DATA_NOT_FOUND_MESSAGE
67
- c_data[c_id]['fixref'] = control['tags']['fixref'] || DATA_NOT_FOUND_MESSAGE
68
- c_data[c_id]['fix_id'] = control['tags']['fix_id'] || DATA_NOT_FOUND_MESSAGE
69
- c_data[c_id]['rationale'] = control['tags']['rationale'] || DATA_NOT_FOUND_MESSAGE
70
- c_data[c_id]['cis_family'] = control['tags']['cis_family'] || DATA_NOT_FOUND_MESSAGE
71
- c_data[c_id]['cis_rid'] = control['tags']['cis_rid'] || DATA_NOT_FOUND_MESSAGE
72
- c_data[c_id]['cis_level'] = control['tags']['cis_level'] || DATA_NOT_FOUND_MESSAGE
73
- c_data[c_id]['impact'] = control['impact'].to_s || DATA_NOT_FOUND_MESSAGE
74
- c_data[c_id]['code'] = control['code'].to_s || DATA_NOT_FOUND_MESSAGE
75
- end
76
-
77
- data['controls'] = c_data.values
78
- data['status'] = 'success'
79
- data
80
- end
81
-
82
- def self.parse_data_for_ckl(json)
27
+ def self.parse_data_for_ckl(json) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
83
28
  data = {}
84
29
 
85
30
  # Parse for inspec profile results json
@@ -220,7 +165,7 @@ module Utils
220
165
  end
221
166
 
222
167
  private_class_method def self.string_to_impact(severity, use_cvss_terms)
223
- if /none|na|n\/a|not[_|(\s*)]?applicable/i.match?(severity)
168
+ if %r{none|na|n/a|not[_|(\s*)]?applicable}i.match?(severity)
224
169
  impact = 0.0 # Informative
225
170
  elsif /low|cat(egory)?\s*(iii|3)/i.match?(severity)
226
171
  impact = 0.3 # Low Impact
@@ -247,13 +192,10 @@ module Utils
247
192
  end
248
193
 
249
194
  IMPACT_SCORES.reverse_each do |name, impact_score|
250
- if name == 'critical' && value >= impact_score && use_cvss_terms
251
- return 'high'
252
- elsif value >= impact_score
253
- return name
254
- else
255
- next
256
- end
195
+ return 'high' if name == 'critical' && value >= impact_score && use_cvss_terms
196
+ return name if value >= impact_score
197
+
198
+ next
257
199
  end
258
200
  end
259
201
 
@@ -276,7 +218,7 @@ module Utils
276
218
  WordWrap.ww(str.to_s, width)
277
219
  end
278
220
 
279
- private_class_method def self.generate_controls(inspec_json)
221
+ private_class_method def self.generate_controls(inspec_json) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
280
222
  controls = []
281
223
  inspec_json['controls'].each do |json_control|
282
224
  control = ::Inspec::Object::Control.new
@@ -314,6 +256,7 @@ module Utils
314
256
  control.add_tag(::Inspec::Object::Tag.new('documentable', json_control['tags']['documentable'])) unless json_control['tags']['documentable'].blank?
315
257
  control.add_tag(::Inspec::Object::Tag.new('mitigations', json_control['tags']['mitigations'])) unless json_control['tags']['mitigations'].blank?
316
258
  control.add_tag(::Inspec::Object::Tag.new('severity_override_guidance', json_control['tags']['severity_override_guidance'])) unless json_control['tags']['severity_override_guidance'].blank?
259
+ control.add_tag(::Inspec::Object::Tag.new('security_override_guidance', json_control['tags']['security_override_guidance'])) unless json_control['tags']['security_override_guidance'].blank?
317
260
  control.add_tag(::Inspec::Object::Tag.new('potential_impacts', json_control['tags']['potential_impacts'])) unless json_control['tags']['potential_impacts'].blank?
318
261
  control.add_tag(::Inspec::Object::Tag.new('third_party_tools', json_control['tags']['third_party_tools'])) unless json_control['tags']['third_party_tools'].blank?
319
262
  control.add_tag(::Inspec::Object::Tag.new('mitigation_controls', json_control['tags']['mitigation_controls'])) unless json_control['tags']['mitigation_controls'].blank?
@@ -382,7 +325,7 @@ module Utils
382
325
  myfile.puts readme_contents
383
326
  end
384
327
 
385
- private_class_method def self.unpack_profile(directory, controls, separated, output_format)
328
+ private_class_method def self.unpack_profile(directory, controls, separated, output_format) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
386
329
  FileUtils.rm_rf(directory) if Dir.exist?(directory)
387
330
  Dir.mkdir directory unless Dir.exist?(directory)
388
331
  Dir.mkdir "#{directory}/controls" unless Dir.exist?("#{directory}/controls")
@@ -393,7 +336,7 @@ module Utils
393
336
  file_name = control.id.to_s
394
337
  myfile = File.new("#{directory}/controls/#{file_name}.rb", 'w')
395
338
  myfile.puts "# encoding: UTF-8\n\n"
396
- myfile.puts wrap(control.to_ruby.gsub('"', "\'"), WIDTH) + "\n"
339
+ myfile.puts wrap(control.to_ruby, WIDTH) + "\n"
397
340
  myfile.close
398
341
  end
399
342
  else
@@ -424,12 +367,10 @@ module Utils
424
367
  end
425
368
  myfile.close
426
369
  end
370
+ config_store = ::RuboCop::ConfigStore.new
371
+ config_store.options_config = File.join(File.dirname(__FILE__), '../data/rubocop.yml')
372
+ rubocop = ::RuboCop::Runner.new({ auto_correct: true }, config_store)
373
+ rubocop.run([directory])
427
374
  end
428
375
  end
429
376
  end
430
-
431
- # rubocop:enable Metrics/ClassLength
432
- # rubocop:enable Metrics/AbcSize
433
- # rubocop:enable Metrics/PerceivedComplexity
434
- # rubocop:enable Metrics/CyclomaticComplexity
435
- # rubocop:enable Metrics/MethodLength