lib/inspec_tools/csv.rb in inspec_tools-2.0.7 vs lib/inspec_tools/csv.rb in inspec_tools-2.1.0
- old
+ new
@@ -1,12 +1,12 @@
require 'csv'
-require 'nokogiri'
-require 'word_wrap'
require 'yaml'
require 'digest'
require_relative '../utilities/inspec_util'
+require_relative '../utilities/cci_xml'
+require_relative '../utilities/mapping_validator'
# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/PerceivedComplexity
# rubocop:disable Metrics/CyclomaticComplexity
@@ -14,38 +14,29 @@
# Methods for converting from CSV to various formats
class CSVTool
def initialize(csv, mapping, name, verbose = false)
@name = name
@csv = csv
- @mapping = mapping
+ @mapping = Utils::MappingValidator.validate(mapping)
@verbose = verbose
@csv.shift if @mapping['skip_csv_header']
end
- def to_ckl
- # TODO
- end
-
- def to_xccdf
- # TODO
- end
-
def to_inspec
@controls = []
- @cci_xml = nil
@profile = {}
- read_cci_xml
- insert_json_metadata
+ @cci_xml = Utils::CciXml.get_cci_list('U_CCI_List.xml')
+ insert_metadata
parse_controls
@profile['controls'] = @controls
- @profile['sha256'] = Digest::SHA256.hexdigest @profile.to_s
+ @profile['sha256'] = Digest::SHA256.hexdigest(@profile.to_s)
@profile
end
private
- def insert_json_metadata
+ def insert_metadata
@profile['name'] = @name
@profile['title'] = 'InSpec Profile'
@profile['maintainer'] = 'The Authors'
@profile['copyright'] = 'The Authors'
@profile['copyright_email'] = 'you@example.com'
@@ -58,38 +49,40 @@
'name': 'inspec_tools',
'version': VERSION
}
end
- def read_cci_xml
- cci_list_path = File.join(File.dirname(__FILE__), '../data/U_CCI_List.xml')
- @cci_xml = Nokogiri::XML(File.open(cci_list_path))
- @cci_xml.remove_namespaces!
- rescue StandardError => e
- puts "Exception: #{e.message}"
- end
-
def get_nist_reference(cci_number)
item_node = @cci_xml.xpath("//cci_list/cci_items/cci_item[@id='#{cci_number}']")[0] unless @cci_xml.nil?
- unless item_node.nil?
- nist_ref = item_node.xpath('./references/reference[not(@version <= preceding-sibling::reference/@version) and not(@version <=following-sibling::reference/@version)]/@index').text
- nist_ver = item_node.xpath('./references/reference[not(@version <= preceding-sibling::reference/@version) and not(@version <=following-sibling::reference/@version)]/@version').text
- end
- [nist_ref, nist_ver]
+ return nil if item_node.nil?
+
+ [] << item_node.xpath('./references/reference[not(@version <= preceding-sibling::reference/@version) and not(@version <=following-sibling::reference/@version)]/@index').text
end
+ def get_cci_number(cell)
+ # Return nil if a mapping to the CCI was not provided or if there is not content in the CSV cell.
+ return nil if cell.nil? || @mapping['control.tags']['cci'].nil?
+
+ # If the content has been exported from STIG Viewer, the cell will have extra information
+ cell.split("\n").first
+ end
+
def parse_controls
@csv.each do |row|
- print '.'
control = {}
control['id'] = row[@mapping['control.id']] unless @mapping['control.id'].nil? || row[@mapping['control.id']].nil?
control['title'] = row[@mapping['control.title']] unless @mapping['control.title'].nil? || row[@mapping['control.title']].nil?
control['desc'] = row[@mapping['control.desc']] unless @mapping['control.desc'].nil? || row[@mapping['control.desc']].nil?
control['tags'] = {}
- nist, nist_rev = get_nist_reference(row[@mapping['control.tags']['cci']]) unless @mapping['control.tags']['cci'].nil? || row[@mapping['control.tags']['cci']].nil?
- control['tags']['nist'] = [nist, 'Rev_' + nist_rev] unless nist.nil? || nist_rev.nil?
+ cci_number = get_cci_number(row[@mapping['control.tags']['cci']])
+ nist = get_nist_reference(cci_number) unless cci_number.nil?
+ control['tags']['nist'] = nist unless nist.nil? || nist.include?(nil)
@mapping['control.tags'].each do |tag|
- control['tags'][tag.first.to_s] = row[tag.last] unless row[tag.last].nil?
+ if tag.first == 'cci'
+ control['tags'][tag.first] = cci_number
+ next
+ end
+ control['tags'][tag.first] = row[tag.last] unless row[tag.last].nil?
end
unless @mapping['control.tags']['severity'].nil? || row[@mapping['control.tags']['severity']].nil?
control['impact'] = Utils::InspecUtil.get_impact(row[@mapping['control.tags']['severity']])
control['tags']['severity'] = Utils::InspecUtil.get_impact_string(control['impact'])
end