inspec_tools 0.0.0.1.ENOTAG → 1.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 +5 -5
- data/CHANGELOG.md +12 -657
- data/Guardfile +4 -0
- data/README.md +65 -132
- data/Rakefile +0 -6
- data/exe/inspec_tools +1 -1
- data/lib/data/README.TXT +1 -1
- data/lib/data/debug_text +5941 -0
- data/lib/happy_mapper_tools/cci_attributes.rb +22 -12
- data/lib/happy_mapper_tools/stig_checklist.rb +1 -6
- data/lib/inspec_tools.rb +2 -1
- data/lib/inspec_tools/cli.rb +140 -24
- data/lib/inspec_tools/command.rb +50 -0
- data/lib/inspec_tools/csv.rb +4 -6
- data/lib/inspec_tools/help/summary.md +2 -2
- data/lib/inspec_tools/inspec.rb +34 -133
- data/lib/inspec_tools/pdf.rb +2 -3
- data/lib/inspec_tools/summary.rb +2 -2
- data/lib/inspec_tools/version.rb +1 -6
- data/lib/inspec_tools/xccdf.rb +8 -22
- data/lib/utilities/inspec_util.rb +59 -208
- data/test/unit/inspec_tools/csv_test.rb +30 -0
- data/test/unit/inspec_tools/inspec_test.rb +54 -0
- data/test/unit/inspec_tools/pdf_test.rb +24 -0
- data/test/unit/inspec_tools/summary_test.rb +42 -0
- data/test/unit/inspec_tools/xccdf_test.rb +50 -0
- data/test/unit/inspec_tools_test.rb +7 -0
- data/test/unit/test_helper.rb +5 -0
- data/test/unit/utils/inspec_util_test.rb +43 -0
- metadata +70 -125
- data/lib/data/NIST_Map_02052020_CIS_Controls_Version_7.1_Implementation_Groups_1.2.xlsx +0 -0
- data/lib/exceptions/impact_input_error.rb +0 -6
- data/lib/exceptions/severity_input_error.rb +0 -6
- data/lib/inspec_tools/plugin.rb +0 -15
- data/lib/inspec_tools/plugin_cli.rb +0 -278
- data/lib/inspec_tools/xlsx_tool.rb +0 -148
- data/lib/inspec_tools_plugin.rb +0 -7
- data/lib/overrides/false_class.rb +0 -5
- data/lib/overrides/nil_class.rb +0 -5
- data/lib/overrides/object.rb +0 -5
- data/lib/overrides/string.rb +0 -5
- data/lib/overrides/true_class.rb +0 -5
Binary file
|
data/lib/inspec_tools/plugin.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module InspecToolsPlugin
|
4
|
-
class Plugin < Inspec.plugin(2)
|
5
|
-
# Metadata
|
6
|
-
# Must match entry in plugins.json
|
7
|
-
plugin_name :'inspec-tools_plugin'
|
8
|
-
|
9
|
-
# Activation hooks (CliCommand as an example)
|
10
|
-
cli_command :tools do
|
11
|
-
require_relative 'plugin_cli'
|
12
|
-
InspecPlugins::InspecToolsPlugin::CliCommand
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,278 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require 'json'
|
3
|
-
require 'roo'
|
4
|
-
require_relative '../utilities/inspec_util'
|
5
|
-
require_relative '../utilities/csv_util'
|
6
|
-
|
7
|
-
module InspecTools
|
8
|
-
autoload :Help, 'inspec_tools/help'
|
9
|
-
autoload :Command, 'inspec_tools/command'
|
10
|
-
autoload :XCCDF, 'inspec_tools/xccdf'
|
11
|
-
autoload :PDF, 'inspec_tools/pdf'
|
12
|
-
autoload :CSVTool, 'inspec_tools/csv'
|
13
|
-
autoload :CKL, 'inspec_tools/ckl'
|
14
|
-
autoload :Inspec, 'inspec_tools/inspec'
|
15
|
-
autoload :Summary, 'inspec_tools/summary'
|
16
|
-
autoload :Threshold, 'inspec_tools/threshold'
|
17
|
-
autoload :XLSXTool, 'inspec_tools/xlsx_tool'
|
18
|
-
end
|
19
|
-
|
20
|
-
# rubocop:disable Style/GuardClause
|
21
|
-
module InspecPlugins
|
22
|
-
module InspecToolsPlugin
|
23
|
-
class CliCommand < Inspec.plugin(2, :cli_command) # rubocop:disable Metrics/ClassLength
|
24
|
-
POSSIBLE_LOG_LEVELS = %w{debug info warn error fatal}.freeze
|
25
|
-
|
26
|
-
class_option :log_directory, type: :string, aliases: :l, desc: 'Provie log location'
|
27
|
-
class_option :log_level, type: :string, desc: "Set the logging level: #{POSSIBLE_LOG_LEVELS}"
|
28
|
-
|
29
|
-
subcommand_desc 'tools [COMMAND]', 'Runs inspec_tools commands through Inspec'
|
30
|
-
|
31
|
-
desc 'xccdf2inspec', 'xccdf2inspec translates an xccdf file to an inspec profile'
|
32
|
-
long_desc InspecTools::Help.text(:xccdf2inspec)
|
33
|
-
option :xccdf, required: true, aliases: '-x'
|
34
|
-
option :attributes, required: false, aliases: '-a'
|
35
|
-
option :output, required: false, aliases: '-o', default: 'profile'
|
36
|
-
option :format, required: false, aliases: '-f', enum: %w{ruby hash}, default: 'ruby'
|
37
|
-
option :separate_files, required: false, type: :boolean, default: true, aliases: '-s'
|
38
|
-
option :replace_tags, type: :array, required: false, aliases: '-r'
|
39
|
-
option :metadata, required: false, aliases: '-m'
|
40
|
-
def xccdf2inspec
|
41
|
-
xccdf = InspecTools::XCCDF.new(File.read(options[:xccdf]), options[:replace_tags])
|
42
|
-
profile = xccdf.to_inspec
|
43
|
-
|
44
|
-
if !options[:metadata].nil?
|
45
|
-
xccdf.inject_metadata(File.read(options[:metadata]))
|
46
|
-
end
|
47
|
-
|
48
|
-
Utils::InspecUtil.unpack_inspec_json(options[:output], profile, options[:separate_files], options[:format])
|
49
|
-
if !options[:attributes].nil?
|
50
|
-
attributes = xccdf.to_attributes
|
51
|
-
File.write(options[:attributes], YAML.dump(attributes))
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
desc 'inspec2xccdf', 'inspec2xccdf translates an inspec profile and attributes files to an xccdf file'
|
56
|
-
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'
|
60
|
-
def inspec2xccdf
|
61
|
-
json = File.read(options[:inspec_json])
|
62
|
-
inspec_tool = InspecTools::Inspec.new(json)
|
63
|
-
attr_hsh = YAML.load_file(options[:attributes])
|
64
|
-
xccdf = inspec_tool.to_xccdf(attr_hsh)
|
65
|
-
File.write(options[:output], xccdf)
|
66
|
-
end
|
67
|
-
|
68
|
-
desc 'csv2inspec', 'csv2inspec translates CSV to Inspec controls using a mapping file'
|
69
|
-
long_desc InspecTools::Help.text(:csv2inspec)
|
70
|
-
option :csv, required: true, aliases: '-c'
|
71
|
-
option :mapping, required: true, aliases: '-m'
|
72
|
-
option :verbose, required: false, type: :boolean, aliases: '-V'
|
73
|
-
option :output, required: false, aliases: '-o', default: 'profile'
|
74
|
-
option :format, required: false, aliases: '-f', enum: %w{ruby hash}, default: 'ruby'
|
75
|
-
option :separate_files, required: false, type: :boolean, default: true, aliases: '-s'
|
76
|
-
def csv2inspec
|
77
|
-
csv = CSV.read(options[:csv], encoding: 'ISO8859-1')
|
78
|
-
mapping = YAML.load_file(options[:mapping])
|
79
|
-
profile = InspecTools::CSVTool.new(csv, mapping, options[:csv].split('/')[-1].split('.')[0], options[:verbose]).to_inspec
|
80
|
-
Utils::InspecUtil.unpack_inspec_json(options[:output], profile, options[:separate_files], options[:format])
|
81
|
-
end
|
82
|
-
|
83
|
-
desc 'xlsx2inspec', 'xlsx2inspec translates CIS XLSX to Inspec controls using a mapping file'
|
84
|
-
long_desc InspecTools::Help.text(:xlsx2inspec)
|
85
|
-
option :xlsx, required: true, aliases: '-x'
|
86
|
-
option :mapping, required: true, aliases: '-m'
|
87
|
-
option :control_name_prefix, required: true, aliases: '-p'
|
88
|
-
option :verbose, required: false, type: :boolean, aliases: '-V'
|
89
|
-
option :output, required: false, aliases: '-o', default: 'profile'
|
90
|
-
option :format, required: false, aliases: '-f', enum: %w{ruby hash}, default: 'ruby'
|
91
|
-
option :separate_files, required: false, type: :boolean, default: true, aliases: '-s'
|
92
|
-
def xlsx2inspec
|
93
|
-
xlsx = Roo::Spreadsheet.open(options[:xlsx])
|
94
|
-
mapping = YAML.load_file(options[:mapping])
|
95
|
-
profile = InspecTools::XLSXTool.new(xlsx, mapping, options[:xlsx].split('/')[-1].split('.')[0], options[:verbose]).to_inspec(options[:control_name_prefix])
|
96
|
-
Utils::InspecUtil.unpack_inspec_json(options[:output], profile, options[:separate_files], options[:format])
|
97
|
-
end
|
98
|
-
|
99
|
-
desc 'inspec2csv', 'inspec2csv translates Inspec controls to CSV'
|
100
|
-
long_desc InspecTools::Help.text(:inspec2csv)
|
101
|
-
option :inspec_json, required: true, aliases: '-j'
|
102
|
-
option :output, required: true, aliases: '-o'
|
103
|
-
option :verbose, required: false, type: :boolean, aliases: '-V'
|
104
|
-
def inspec2csv
|
105
|
-
csv = InspecTools::Inspec.new(File.read(options[:inspec_json])).to_csv
|
106
|
-
Utils::CSVUtil.unpack_csv(csv, options[:output])
|
107
|
-
end
|
108
|
-
|
109
|
-
desc 'inspec2ckl', 'inspec2ckl translates an inspec json file to a Checklist file'
|
110
|
-
long_desc InspecTools::Help.text(:inspec2ckl)
|
111
|
-
option :inspec_json, required: true, aliases: '-j'
|
112
|
-
option :output, required: true, aliases: '-o'
|
113
|
-
option :verbose, type: :boolean, aliases: '-V'
|
114
|
-
option :metadata, required: false, aliases: '-m'
|
115
|
-
def inspec2ckl
|
116
|
-
metadata = '{}'
|
117
|
-
if !options[:metadata].nil?
|
118
|
-
metadata = File.read(options[:metadata])
|
119
|
-
end
|
120
|
-
ckl = InspecTools::Inspec.new(File.read(options[:inspec_json]), metadata).to_ckl
|
121
|
-
File.write(options[:output], ckl)
|
122
|
-
end
|
123
|
-
|
124
|
-
desc 'pdf2inspec', 'pdf2inspec translates a PDF Security Control Speficication to Inspec Security Profile'
|
125
|
-
long_desc InspecTools::Help.text(:pdf2inspec)
|
126
|
-
option :pdf, required: true, aliases: '-p'
|
127
|
-
option :output, required: false, aliases: '-o', default: 'profile'
|
128
|
-
option :debug, required: false, aliases: '-d', type: :boolean, default: false
|
129
|
-
option :format, required: false, aliases: '-f', enum: %w{ruby hash}, default: 'ruby'
|
130
|
-
option :separate_files, required: false, type: :boolean, default: true, aliases: '-s'
|
131
|
-
def pdf2inspec
|
132
|
-
pdf = File.open(options[:pdf])
|
133
|
-
profile = InspecTools::PDF.new(pdf, options[:output], options[:debug]).to_inspec
|
134
|
-
Utils::InspecUtil.unpack_inspec_json(options[:output], profile, options[:separate_files], options[:format])
|
135
|
-
end
|
136
|
-
|
137
|
-
desc 'generate_map', 'Generates mapping template from CSV to Inspec Controls'
|
138
|
-
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
|
159
|
-
end
|
160
|
-
|
161
|
-
desc 'generate_ckl_metadata', 'Generate metadata file that can be passed to inspec2ckl'
|
162
|
-
def generate_ckl_metadata
|
163
|
-
metadata = {}
|
164
|
-
|
165
|
-
metadata['stigid'] = ask('STID ID: ')
|
166
|
-
metadata['role'] = ask('Role: ')
|
167
|
-
metadata['type'] = ask('Type: ')
|
168
|
-
metadata['hostname'] = ask('Hostname: ')
|
169
|
-
metadata['ip'] = ask('IP Address: ')
|
170
|
-
metadata['mac'] = ask('MAC Address: ')
|
171
|
-
metadata['fqdn'] = ask('FQDN: ')
|
172
|
-
metadata['tech_area'] = ask('Tech Area: ')
|
173
|
-
metadata['target_key'] = ask('Target Key: ')
|
174
|
-
metadata['web_or_database'] = ask('Web or Database: ')
|
175
|
-
metadata['web_db_site'] = ask('Web DB Site: ')
|
176
|
-
metadata['web_db_instance'] = ask('Web DB Instance: ')
|
177
|
-
|
178
|
-
metadata.delete_if { |_key, value| value.empty? }
|
179
|
-
File.open('metadata.json', 'w') do |f|
|
180
|
-
f.write(metadata.to_json)
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
desc 'generate_inspec_metadata', 'Generate mapping file that can be passed to xccdf2inspec'
|
185
|
-
def generate_inspec_metadata
|
186
|
-
metadata = {}
|
187
|
-
|
188
|
-
metadata['maintainer'] = ask('Maintainer: ')
|
189
|
-
metadata['copyright'] = ask('Copyright: ')
|
190
|
-
metadata['copyright_email'] = ask('Copyright Email: ')
|
191
|
-
metadata['license'] = ask('License: ')
|
192
|
-
metadata['version'] = ask('Version: ')
|
193
|
-
|
194
|
-
metadata.delete_if { |_key, value| value.empty? }
|
195
|
-
File.open('metadata.json', 'w') do |f|
|
196
|
-
f.write(metadata.to_json)
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
desc 'summary', 'summary parses an inspec results json to create a summary json'
|
201
|
-
long_desc InspecTools::Help.text(:summary)
|
202
|
-
option :inspec_json, required: true, aliases: '-j'
|
203
|
-
option :output, required: false, aliases: '-o'
|
204
|
-
option :cli, type: :boolean, required: false, aliases: '-c'
|
205
|
-
option :verbose, type: :boolean, aliases: '-V'
|
206
|
-
option :json_full, type: :boolean, required: false, aliases: '-f'
|
207
|
-
option :json_counts, type: :boolean, required: false, aliases: '-k'
|
208
|
-
|
209
|
-
def summary
|
210
|
-
summary = InspecTools::Summary.new(File.read(options[:inspec_json])).to_summary
|
211
|
-
|
212
|
-
if options[:cli]
|
213
|
-
puts "\nOverall compliance: #{summary[:compliance]}%\n\n"
|
214
|
-
summary[:status].keys.each do |category|
|
215
|
-
puts category
|
216
|
-
summary[:status][category].keys.each do |impact|
|
217
|
-
puts "\t#{impact} : #{summary[:status][category][impact]}"
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
json_summary = summary.to_json
|
223
|
-
File.write(options[:output], json_summary) if options[:output]
|
224
|
-
puts json_summary if options[:json_full]
|
225
|
-
puts summary[:status].to_json if options[:json_counts]
|
226
|
-
end
|
227
|
-
|
228
|
-
desc 'compliance', 'compliance parses an inspec results json to check if the compliance level meets a specified threshold'
|
229
|
-
long_desc InspecTools::Help.text(:compliance)
|
230
|
-
option :inspec_json, required: true, aliases: '-j'
|
231
|
-
option :threshold_file, required: false, aliases: '-f'
|
232
|
-
option :threshold_inline, required: false, aliases: '-i'
|
233
|
-
option :verbose, type: :boolean, aliases: '-V'
|
234
|
-
|
235
|
-
def compliance
|
236
|
-
if options[:threshold_file].nil? && options[:threshold_inline].nil?
|
237
|
-
puts 'Please provide threshold as a yaml file or inline yaml'
|
238
|
-
exit(1)
|
239
|
-
end
|
240
|
-
threshold = YAML.load_file(options[:threshold_file]) unless options[:threshold_file].nil?
|
241
|
-
threshold = YAML.safe_load(options[:threshold_inline]) unless options[:threshold_inline].nil?
|
242
|
-
compliance = InspecTools::Summary.new(File.read(options[:inspec_json])).threshold(threshold)
|
243
|
-
compliance ? exit(0) : exit(1)
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
#=====================================================================#
|
250
|
-
# Pre-Flight Code
|
251
|
-
#=====================================================================#
|
252
|
-
help_commands = ['-h', '--help', 'help']
|
253
|
-
log_commands = ['-l', '--log-directory']
|
254
|
-
version_commands = ['-v', '--version', 'version']
|
255
|
-
|
256
|
-
#---------------------------------------------------------------------#
|
257
|
-
# Adjustments for non-required version commands
|
258
|
-
#---------------------------------------------------------------------#
|
259
|
-
unless (version_commands & ARGV).empty?
|
260
|
-
puts InspecTools::VERSION
|
261
|
-
exit 0
|
262
|
-
end
|
263
|
-
|
264
|
-
#---------------------------------------------------------------------#
|
265
|
-
# Adjustments for non-required log-directory
|
266
|
-
#---------------------------------------------------------------------#
|
267
|
-
ARGV.push("--log-directory=#{Dir.pwd}/logs") if (log_commands & ARGV).empty? && (help_commands & ARGV).empty?
|
268
|
-
|
269
|
-
# Push help to front of command so thor recognizes subcommands are called with help
|
270
|
-
if help_commands.any? { |cmd| ARGV.include? cmd }
|
271
|
-
help_commands.each do |cmd|
|
272
|
-
if (match = ARGV.delete(cmd))
|
273
|
-
ARGV.unshift match
|
274
|
-
end
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
# rubocop:enable Style/GuardClause
|
@@ -1,148 +0,0 @@
|
|
1
|
-
require 'nokogiri'
|
2
|
-
require 'inspec-objects'
|
3
|
-
require 'word_wrap'
|
4
|
-
require 'yaml'
|
5
|
-
require 'digest'
|
6
|
-
require 'roo'
|
7
|
-
|
8
|
-
require_relative '../utilities/inspec_util'
|
9
|
-
|
10
|
-
# rubocop:disable Metrics/AbcSize
|
11
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
12
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
13
|
-
|
14
|
-
module InspecTools
|
15
|
-
# Methods for converting from XLS to various formats
|
16
|
-
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
|
-
LATEST_NIST_REV = 'Rev_4'.freeze
|
19
|
-
|
20
|
-
def initialize(xlsx, mapping, name, verbose = false)
|
21
|
-
@name = name
|
22
|
-
@xlsx = xlsx
|
23
|
-
@mapping = mapping
|
24
|
-
@verbose = verbose
|
25
|
-
@cis_to_nist = get_cis_to_nist_control_mapping(CIS_2_NIST_XLSX)
|
26
|
-
end
|
27
|
-
|
28
|
-
def to_ckl
|
29
|
-
# TODO
|
30
|
-
end
|
31
|
-
|
32
|
-
def to_xccdf
|
33
|
-
# TODO
|
34
|
-
end
|
35
|
-
|
36
|
-
def to_inspec(control_prefix)
|
37
|
-
@controls = []
|
38
|
-
@cci_xml = nil
|
39
|
-
@profile = {}
|
40
|
-
insert_json_metadata
|
41
|
-
parse_cis_controls(control_prefix)
|
42
|
-
@profile['controls'] = @controls
|
43
|
-
@profile['sha256'] = Digest::SHA256.hexdigest @profile.to_s
|
44
|
-
@profile
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
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
|
-
def insert_json_metadata
|
62
|
-
@profile['name'] = @name
|
63
|
-
@profile['title'] = 'InSpec Profile'
|
64
|
-
@profile['maintainer'] = 'The Authors'
|
65
|
-
@profile['copyright'] = 'The Authors'
|
66
|
-
@profile['copyright_email'] = 'you@example.com'
|
67
|
-
@profile['license'] = 'Apache-2.0'
|
68
|
-
@profile['summary'] = 'An InSpec Compliance Profile'
|
69
|
-
@profile['version'] = '0.1.0'
|
70
|
-
@profile['supports'] = []
|
71
|
-
@profile['attributes'] = []
|
72
|
-
@profile['generator'] = {
|
73
|
-
'name': 'inspec_tools',
|
74
|
-
'version': ::InspecTools::VERSION
|
75
|
-
}
|
76
|
-
end
|
77
|
-
|
78
|
-
def parse_cis_controls(control_prefix)
|
79
|
-
[1, 2].each do |level|
|
80
|
-
@xlsx.sheet(level).each_row_streaming do |row|
|
81
|
-
if row[@mapping['control.id']].nil? || !/^\d+(\.?\d)*$/.match(row[@mapping['control.id']].formatted_value)
|
82
|
-
next
|
83
|
-
end
|
84
|
-
|
85
|
-
tag_pos = @mapping['control.tags']
|
86
|
-
control = {}
|
87
|
-
control['tags'] = {}
|
88
|
-
control['id'] = control_prefix + '-' + row[@mapping['control.id']].formatted_value unless cell_empty?(@mapping['control.id']) || cell_empty?(row[@mapping['control.id']])
|
89
|
-
control['title'] = row[@mapping['control.title']].formatted_value unless cell_empty?(@mapping['control.title']) || cell_empty?(row[@mapping['control.title']])
|
90
|
-
control['desc'] = ''
|
91
|
-
control['desc'] = row[@mapping['control.desc']].formatted_value unless cell_empty?(row[@mapping['control.desc']])
|
92
|
-
control['tags']['rationale'] = row[tag_pos['rationale']].formatted_value unless cell_empty?(row[tag_pos['rationale']])
|
93
|
-
|
94
|
-
control['tags']['severity'] = level == 1 ? 'medium' : 'high'
|
95
|
-
control['impact'] = Utils::InspecUtil.get_impact(control['tags']['severity'])
|
96
|
-
control['tags']['ref'] = row[@mapping['control.ref']].formatted_value unless cell_empty?(@mapping['control.ref']) || cell_empty?(row[@mapping['control.ref']])
|
97
|
-
control['tags']['cis_level'] = level unless level.nil?
|
98
|
-
|
99
|
-
unless cell_empty?(row[tag_pos['cis_controls']])
|
100
|
-
# cis_control must be extracted from CIS control column via regex
|
101
|
-
cis_tags_array = row[tag_pos['cis_controls']].formatted_value.scan(/CONTROL:v(\d) (\d+)\.?(\d*)/).flatten
|
102
|
-
cis_tags = %i(revision section sub_section).zip(cis_tags_array).to_h
|
103
|
-
control = apply_cis_and_nist_controls(control, cis_tags)
|
104
|
-
end
|
105
|
-
|
106
|
-
control['tags']['cis_rid'] = row[@mapping['control.id']].formatted_value unless cell_empty?(@mapping['control.id']) || cell_empty?(row[@mapping['control.id']])
|
107
|
-
control['tags']['check'] = row[tag_pos['check']].formatted_value unless cell_empty?(tag_pos['check']) || cell_empty?(row[tag_pos['check']])
|
108
|
-
control['tags']['fix'] = row[tag_pos['fix']].formatted_value unless cell_empty?(tag_pos['fix']) || cell_empty?(row[tag_pos['fix']])
|
109
|
-
|
110
|
-
@controls << control
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def cell_empty?(cell)
|
116
|
-
return cell.empty? if cell.respond_to?(:empty?)
|
117
|
-
|
118
|
-
cell.nil?
|
119
|
-
end
|
120
|
-
|
121
|
-
def apply_cis_and_nist_controls(control, cis_tags)
|
122
|
-
control['tags']['cis_controls'], control['tags']['nist'] = [], []
|
123
|
-
|
124
|
-
if cis_tags[:sub_section].nil? || cis_tags[:sub_section].blank?
|
125
|
-
control['tags']['cis_controls'] << cis_tags[:section]
|
126
|
-
control['tags']['nist'] << get_nist_control_for_cis(cis_tags[:section])
|
127
|
-
else
|
128
|
-
control['tags']['cis_controls'] << "#{cis_tags[:section]}.#{cis_tags[:sub_section]}"
|
129
|
-
control['tags']['nist'] << get_nist_control_for_cis(cis_tags[:section], cis_tags[:sub_section])
|
130
|
-
end
|
131
|
-
|
132
|
-
control['tags']['nist'] << LATEST_NIST_REV unless control['tags']['nist'].nil?
|
133
|
-
control['tags']['cis_controls'] << "Rev_#{cis_tags[:revision]}" unless cis_tags[:revision].nil?
|
134
|
-
|
135
|
-
control
|
136
|
-
end
|
137
|
-
|
138
|
-
def get_nist_control_for_cis(section, sub_section = nil)
|
139
|
-
return @cis_to_nist[section] if sub_section.nil?
|
140
|
-
|
141
|
-
@cis_to_nist["#{section}.#{sub_section}"]
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
# rubocop:enable Metrics/AbcSize
|
147
|
-
# rubocop:enable Metrics/PerceivedComplexity
|
148
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|