inspec_tools 2.0.4 → 2.2.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.
- checksums.yaml +4 -4
- data/README.md +25 -17
- data/Rakefile +82 -8
- data/lib/data/cis_to_nist_critical_controls +0 -0
- data/lib/data/cis_to_nist_mapping +0 -0
- data/lib/happy_mapper_tools/benchmark.rb +83 -0
- data/lib/happy_mapper_tools/stig_attributes.rb +68 -48
- data/lib/inspec_tools/csv.rb +42 -39
- data/lib/inspec_tools/generate_map.rb +35 -0
- data/lib/inspec_tools/inspec.rb +19 -91
- data/lib/inspec_tools/pdf.rb +2 -13
- data/lib/inspec_tools/plugin_cli.rb +22 -53
- data/lib/inspec_tools/summary.rb +108 -76
- data/lib/inspec_tools/xccdf.rb +1 -0
- data/lib/inspec_tools/xlsx_tool.rb +4 -16
- data/lib/utilities/cci_xml.rb +13 -0
- data/lib/utilities/cis_to_nist.rb +11 -0
- data/lib/utilities/inspec_util.rb +10 -74
- data/lib/utilities/mapping_validator.rb +10 -0
- data/lib/utilities/xccdf/from_inspec.rb +89 -0
- data/lib/utilities/xccdf/to_xccdf.rb +388 -0
- data/lib/utilities/xccdf/xccdf_score.rb +116 -0
- metadata +48 -29
- data/CHANGELOG.md +0 -714
- data/lib/data/NIST_Map_02052020_CIS_Controls_Version_7.1_Implementation_Groups_1.2.xlsx +0 -0
- data/lib/data/NIST_Map_09212017B_CSC-CIS_Critical_Security_Controls_VER_6.1_Excel_9.1.2016.xlsx +0 -0
- data/lib/utilities/extract_nist_cis_mapping.rb +0 -57
data/lib/inspec_tools/csv.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'csv'
|
2
|
-
require 'nokogiri'
|
3
|
-
require 'word_wrap'
|
4
2
|
require 'yaml'
|
5
3
|
require 'digest'
|
6
4
|
|
7
5
|
require_relative '../utilities/inspec_util'
|
6
|
+
require_relative '../utilities/cci_xml'
|
7
|
+
require_relative '../utilities/mapping_validator'
|
8
8
|
|
9
9
|
# rubocop:disable Metrics/AbcSize
|
10
10
|
# rubocop:disable Metrics/PerceivedComplexity
|
@@ -16,34 +16,25 @@ module InspecTools
|
|
16
16
|
def initialize(csv, mapping, name, verbose = false)
|
17
17
|
@name = name
|
18
18
|
@csv = csv
|
19
|
-
@mapping = mapping
|
19
|
+
@mapping = Utils::MappingValidator.validate(mapping)
|
20
20
|
@verbose = verbose
|
21
21
|
@csv.shift if @mapping['skip_csv_header']
|
22
22
|
end
|
23
23
|
|
24
|
-
def
|
25
|
-
# TODO
|
26
|
-
end
|
27
|
-
|
28
|
-
def to_xccdf
|
29
|
-
# TODO
|
30
|
-
end
|
31
|
-
|
32
|
-
def to_inspec
|
24
|
+
def to_inspec(control_name_prefix: nil)
|
33
25
|
@controls = []
|
34
|
-
@cci_xml = nil
|
35
26
|
@profile = {}
|
36
|
-
|
37
|
-
|
38
|
-
parse_controls
|
27
|
+
@cci_xml = Utils::CciXml.get_cci_list('U_CCI_List.xml')
|
28
|
+
insert_metadata
|
29
|
+
parse_controls(control_name_prefix)
|
39
30
|
@profile['controls'] = @controls
|
40
|
-
@profile['sha256'] = Digest::SHA256.hexdigest
|
31
|
+
@profile['sha256'] = Digest::SHA256.hexdigest(@profile.to_s)
|
41
32
|
@profile
|
42
33
|
end
|
43
34
|
|
44
35
|
private
|
45
36
|
|
46
|
-
def
|
37
|
+
def insert_metadata
|
47
38
|
@profile['name'] = @name
|
48
39
|
@profile['title'] = 'InSpec Profile'
|
49
40
|
@profile['maintainer'] = 'The Authors'
|
@@ -60,35 +51,37 @@ module InspecTools
|
|
60
51
|
}
|
61
52
|
end
|
62
53
|
|
63
|
-
def read_cci_xml
|
64
|
-
cci_list_path = File.join(File.dirname(__FILE__), '../data/U_CCI_List.xml')
|
65
|
-
@cci_xml = Nokogiri::XML(File.open(cci_list_path))
|
66
|
-
@cci_xml.remove_namespaces!
|
67
|
-
rescue StandardError => e
|
68
|
-
puts "Exception: #{e.message}"
|
69
|
-
end
|
70
|
-
|
71
54
|
def get_nist_reference(cci_number)
|
72
55
|
item_node = @cci_xml.xpath("//cci_list/cci_items/cci_item[@id='#{cci_number}']")[0] unless @cci_xml.nil?
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
end
|
77
|
-
[nist_ref, nist_ver]
|
56
|
+
return nil if item_node.nil?
|
57
|
+
|
58
|
+
[] << item_node.xpath('./references/reference[not(@version <= preceding-sibling::reference/@version) and not(@version <=following-sibling::reference/@version)]/@index').text
|
78
59
|
end
|
79
60
|
|
80
|
-
def
|
61
|
+
def get_cci_number(cell)
|
62
|
+
# Return nil if a mapping to the CCI was not provided or if there is not content in the CSV cell.
|
63
|
+
return nil if cell.nil? || @mapping['control.tags']['cci'].nil?
|
64
|
+
|
65
|
+
# If the content has been exported from STIG Viewer, the cell will have extra information
|
66
|
+
cell.split("\n").first
|
67
|
+
end
|
68
|
+
|
69
|
+
def parse_controls(prefix)
|
81
70
|
@csv.each do |row|
|
82
|
-
print '.'
|
83
71
|
control = {}
|
84
|
-
control['id'] = row[@mapping['control.id']]
|
85
|
-
control['title'] = row[@mapping['control.title']]
|
86
|
-
control['desc'] = row[@mapping['control.desc']]
|
72
|
+
control['id'] = generate_control_id(prefix, row[@mapping['control.id']]) unless @mapping['control.id'].nil? || row[@mapping['control.id']].nil?
|
73
|
+
control['title'] = row[@mapping['control.title']] unless @mapping['control.title'].nil? || row[@mapping['control.title']].nil?
|
74
|
+
control['desc'] = row[@mapping['control.desc']] unless @mapping['control.desc'].nil? || row[@mapping['control.desc']].nil?
|
87
75
|
control['tags'] = {}
|
88
|
-
|
89
|
-
|
76
|
+
cci_number = get_cci_number(row[@mapping['control.tags']['cci']])
|
77
|
+
nist = get_nist_reference(cci_number) unless cci_number.nil?
|
78
|
+
control['tags']['nist'] = nist unless nist.nil? || nist.include?(nil)
|
90
79
|
@mapping['control.tags'].each do |tag|
|
91
|
-
|
80
|
+
if tag.first == 'cci'
|
81
|
+
control['tags'][tag.first] = cci_number
|
82
|
+
next
|
83
|
+
end
|
84
|
+
control['tags'][tag.first] = row[tag.last] unless row[tag.last].nil?
|
92
85
|
end
|
93
86
|
unless @mapping['control.tags']['severity'].nil? || row[@mapping['control.tags']['severity']].nil?
|
94
87
|
control['impact'] = Utils::InspecUtil.get_impact(row[@mapping['control.tags']['severity']])
|
@@ -97,5 +90,15 @@ module InspecTools
|
|
97
90
|
@controls << control
|
98
91
|
end
|
99
92
|
end
|
93
|
+
|
94
|
+
def generate_control_id(prefix, id)
|
95
|
+
return id if prefix.nil?
|
96
|
+
|
97
|
+
"#{prefix}-#{id}"
|
98
|
+
end
|
100
99
|
end
|
101
100
|
end
|
101
|
+
|
102
|
+
# rubocop:enable Metrics/AbcSize
|
103
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
104
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
@@ -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
|
data/lib/inspec_tools/inspec.rb
CHANGED
@@ -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
|
-
|
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 =
|
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
|
-
|
41
|
-
@attribute = attributes
|
42
|
-
@attribute = {} if @attribute.eql? false
|
41
|
+
data = Utils::FromInspec.new.parse_data_for_xccdf(@json)
|
43
42
|
@verbose = verbose
|
44
|
-
|
45
|
-
|
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
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
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}"
|
data/lib/inspec_tools/pdf.rb
CHANGED
@@ -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 =
|
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
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'yaml'
|
2
1
|
require 'json'
|
3
2
|
require 'roo'
|
4
3
|
require_relative '../utilities/inspec_util'
|
@@ -13,8 +12,8 @@ module InspecTools
|
|
13
12
|
autoload :CKL, 'inspec_tools/ckl'
|
14
13
|
autoload :Inspec, 'inspec_tools/inspec'
|
15
14
|
autoload :Summary, 'inspec_tools/summary'
|
16
|
-
autoload :Threshold, 'inspec_tools/threshold'
|
17
15
|
autoload :XLSXTool, 'inspec_tools/xlsx_tool'
|
16
|
+
autoload :GenerateMap, 'inspec_tools/generate_map'
|
18
17
|
end
|
19
18
|
|
20
19
|
# rubocop:disable Style/GuardClause
|
@@ -23,7 +22,7 @@ module InspecPlugins
|
|
23
22
|
class CliCommand < Inspec.plugin(2, :cli_command) # rubocop:disable Metrics/ClassLength
|
24
23
|
POSSIBLE_LOG_LEVELS = %w{debug info warn error fatal}.freeze
|
25
24
|
|
26
|
-
class_option :log_directory, type: :string, aliases: :l, desc: '
|
25
|
+
class_option :log_directory, type: :string, aliases: :l, desc: 'Provide log location'
|
27
26
|
class_option :log_level, type: :string, desc: "Set the logging level: #{POSSIBLE_LOG_LEVELS}"
|
28
27
|
|
29
28
|
subcommand_desc 'tools [COMMAND]', 'Runs inspec_tools commands through Inspec'
|
@@ -54,12 +53,18 @@ module InspecPlugins
|
|
54
53
|
|
55
54
|
desc 'inspec2xccdf', 'inspec2xccdf translates an inspec profile and attributes files to an xccdf file'
|
56
55
|
long_desc InspecTools::Help.text(:inspec2xccdf)
|
57
|
-
option :inspec_json, required: true, aliases: '-j'
|
58
|
-
|
59
|
-
option :
|
56
|
+
option :inspec_json, required: true, aliases: '-j',
|
57
|
+
desc: 'path to InSpec JSON file created'
|
58
|
+
option :attributes, required: true, aliases: '-a',
|
59
|
+
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.'
|
60
|
+
option :output, required: true, aliases: '-o',
|
61
|
+
desc: 'name or path to create the XCCDF and title to give the XCCDF'
|
62
|
+
option :metadata, required: false, type: :string, aliases: '-m',
|
63
|
+
desc: 'path to JSON file with additional host metadata for the XCCDF file'
|
60
64
|
def inspec2xccdf
|
61
65
|
json = File.read(options[:inspec_json])
|
62
|
-
|
66
|
+
metadata = options[:metadata] ? JSON.parse(File.read(options[:metadata])) : {}
|
67
|
+
inspec_tool = InspecTools::Inspec.new(json, metadata)
|
63
68
|
attr_hsh = YAML.load_file(options[:attributes])
|
64
69
|
xccdf = inspec_tool.to_xccdf(attr_hsh)
|
65
70
|
File.write(options[:output], xccdf)
|
@@ -73,10 +78,11 @@ module InspecPlugins
|
|
73
78
|
option :output, required: false, aliases: '-o', default: 'profile'
|
74
79
|
option :format, required: false, aliases: '-f', enum: %w{ruby hash}, default: 'ruby'
|
75
80
|
option :separate_files, required: false, type: :boolean, default: true, aliases: '-s'
|
81
|
+
option :control_name_prefix, required: false, type: :string, aliases: '-p'
|
76
82
|
def csv2inspec
|
77
83
|
csv = CSV.read(options[:csv], encoding: 'ISO8859-1')
|
78
84
|
mapping = YAML.load_file(options[:mapping])
|
79
|
-
profile = InspecTools::CSVTool.new(csv, mapping, options[:csv].split('/')[-1].split('.')[0], options[:verbose]).to_inspec
|
85
|
+
profile = InspecTools::CSVTool.new(csv, mapping, options[:csv].split('/')[-1].split('.')[0], options[:verbose]).to_inspec(control_name_prefix: options[:control_name_prefix])
|
80
86
|
Utils::InspecUtil.unpack_inspec_json(options[:output], profile, options[:separate_files], options[:format])
|
81
87
|
end
|
82
88
|
|
@@ -136,26 +142,8 @@ module InspecPlugins
|
|
136
142
|
|
137
143
|
desc 'generate_map', 'Generates mapping template from CSV to Inspec Controls'
|
138
144
|
def generate_map
|
139
|
-
|
140
|
-
|
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
|
145
|
+
generator = InspecTools::GenerateMap.new
|
146
|
+
generator.generate_example('mapping.yml')
|
159
147
|
end
|
160
148
|
|
161
149
|
desc 'generate_ckl_metadata', 'Generate metadata file that can be passed to inspec2ckl'
|
@@ -200,26 +188,14 @@ module InspecPlugins
|
|
200
188
|
desc 'summary', 'summary parses an inspec results json to create a summary json'
|
201
189
|
long_desc InspecTools::Help.text(:summary)
|
202
190
|
option :inspec_json, required: true, aliases: '-j'
|
203
|
-
option :verbose, type: :boolean, aliases: '-V'
|
204
191
|
option :json_full, type: :boolean, required: false, aliases: '-f'
|
205
192
|
option :json_counts, type: :boolean, required: false, aliases: '-k'
|
193
|
+
option :threshold_file, required: false, aliases: '-t'
|
194
|
+
option :threshold_inline, required: false, aliases: '-i'
|
206
195
|
|
207
196
|
def summary
|
208
|
-
summary = InspecTools::Summary.new(
|
209
|
-
|
210
|
-
unless options.include?('json_full') || options.include?('json_counts')
|
211
|
-
puts "\nOverall compliance: #{summary[:compliance]}%\n\n"
|
212
|
-
summary[:status].keys.each do |category|
|
213
|
-
puts category
|
214
|
-
summary[:status][category].keys.each do |impact|
|
215
|
-
puts "\t#{impact} : #{summary[:status][category][impact]}"
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
json_summary = summary.to_json
|
221
|
-
puts json_summary if options[:json_full]
|
222
|
-
puts summary[:status].to_json if options[:json_counts]
|
197
|
+
summary = InspecTools::Summary.new(options: options)
|
198
|
+
summary.output_summary
|
223
199
|
end
|
224
200
|
|
225
201
|
desc 'compliance', 'compliance parses an inspec results json to check if the compliance level meets a specified threshold'
|
@@ -227,17 +203,10 @@ module InspecPlugins
|
|
227
203
|
option :inspec_json, required: true, aliases: '-j'
|
228
204
|
option :threshold_file, required: false, aliases: '-f'
|
229
205
|
option :threshold_inline, required: false, aliases: '-i'
|
230
|
-
option :verbose, type: :boolean, aliases: '-V'
|
231
206
|
|
232
207
|
def compliance
|
233
|
-
|
234
|
-
|
235
|
-
exit(1)
|
236
|
-
end
|
237
|
-
threshold = YAML.load_file(options[:threshold_file]) unless options[:threshold_file].nil?
|
238
|
-
threshold = YAML.safe_load(options[:threshold_inline]) unless options[:threshold_inline].nil?
|
239
|
-
compliance = InspecTools::Summary.new(File.read(options[:inspec_json])).threshold(threshold)
|
240
|
-
compliance ? exit(0) : exit(1)
|
208
|
+
compliance = InspecTools::Summary.new(options: options)
|
209
|
+
compliance.results_meet_threshold? ? exit(0) : exit(1)
|
241
210
|
end
|
242
211
|
end
|
243
212
|
end
|