lib/utilities/inspec_util.rb in inspec_tools-1.4.2 vs lib/utilities/inspec_util.rb in inspec_tools-1.7.1

- old
+ new

@@ -1,13 +1,43 @@ require 'inspec/objects' -require 'inspec/impact' require 'word_wrap' require 'pp' require 'uri' require 'net/http' require 'fileutils' +# Add rails style blank? method to all classes +class NilClass + def blank? + true + end +end + +class String + def blank? + self.strip.empty? + end +end + +class FalseClass + def blank? + true + end +end + +class TrueClass + def blank? + false + end +end + +class Object + def blank? + respond_to?(:empty?) ? empty? : !self + end +end + # rubocop:disable Metrics/ClassLength # rubocop:disable Metrics/AbcSize # rubocop:disable Metrics/PerceivedComplexity # rubocop:disable Metrics/CyclomaticComplexity # rubocop:disable Metrics/BlockLength @@ -15,11 +45,20 @@ module Utils class InspecUtil DATA_NOT_FOUND_MESSAGE = 'N/A'.freeze WIDTH = 80 + IMPACT_SCORES = { + "none" => 0.0, + "low" => 0.1, + "medium" => 0.4, + "high" => 0.7, + "critical" => 0.9, + }.freeze + class ImpactError; end + def self.parse_data_for_xccdf(json) data = {} controls = [] if json['profiles'].nil? @@ -95,14 +134,18 @@ data[c_id][:status] = [] data[c_id][:message] = [] if control.key?('results') control['results'].each do |result| + if !result['backtrace'].nil? + result['status'] = 'error' + end data[c_id][:status].push(result['status']) data[c_id][:message].push("SKIPPED -- Test: #{result['code_desc']}\nMessage: #{result['skip_message']}\n") if result['status'] == 'skipped' data[c_id][:message].push("FAILED -- Test: #{result['code_desc']}\nMessage: #{result['message']}\n") if result['status'] == 'failed' data[c_id][:message].push("PASS -- #{result['code_desc']}\n") if result['status'] == 'passed' + data[c_id][:message].push("PROFILE_ERROR -- Test: #{result['code_desc']}\nMessage: #{result['backtrace']}\n") if result['status'] == 'error' end end if data[c_id][:impact].to_f.zero? data[c_id][:message].unshift("NOT_APPLICABLE -- Description: #{control['desc']}\n\n") end @@ -126,32 +169,32 @@ end end def self.control_status(control) status_list = control[:status].uniq - if status_list.include?('failed') + if status_list.include?('error') + result = 'Profile_Error' + elsif control[:impact].to_f.zero? + result = 'Not_Applicable' + elsif status_list.include?('failed') result = 'Open' - elsif status_list.include?('skipped') - result = 'Not_Reviewed' elsif status_list.include?('passed') result = 'NotAFinding' - else - # result = 'Not_Tested' ## STIGViewer does not allow Not_Tested as a possible status. + elsif status_list.include?('skipped') result = 'Not_Reviewed' + else + result = 'Profile_Error' end - if control[:impact].to_f.zero? - result = 'Not_Applicable' - end result end def self.control_finding_details(control, control_clk_status) result = "One or more of the automated tests failed or was inconclusive for the control \n\n #{control[:message].sort.join}" if control_clk_status == 'Open' result = "All Automated tests passed for the control \n\n #{control[:message].join}" if control_clk_status == 'NotAFinding' result = "Automated test skipped due to known accepted condition in the control : \n\n#{control[:message].join}" if control_clk_status == 'Not_Reviewed' result = "Justification: \n #{control[:message].join}" if control_clk_status == 'Not_Applicable' - result = 'No test available for this control' if control_clk_status == 'Not_Tested' + result = 'No test available or some test errors occurred for this control' if control_clk_status == 'Profile_Error' result end # @!method get_impact(severity) # Takes in the STIG severity tag and converts it to the InSpec #{impact} @@ -177,11 +220,17 @@ else severity end end def self.get_impact_string(impact) - Inspec::Impact.string_from_impact(impact) unless impact.nil? + return if impact.nil? + value = impact.to_f + raise ImpactError, "'#{value}' is not a valid impact score. Valid impact scores: [0.0 - 1.0]." if value < 0 || value > 1 + + IMPACT_SCORES.reverse_each do |name, impact| + return name if value >= impact + end end def self.unpack_inspec_json(directory, inspec_json, separated, output_format) if directory == 'id' directory = inspec_json['name'] @@ -202,41 +251,51 @@ end private_class_method def self.generate_controls(inspec_json) controls = [] inspec_json['controls'].each do |json_control| - control = Inspec::Control.new + control = ::Inspec::Object::Control.new if (defined? control.desc).nil? control.descriptions[:default] = json_control['desc'] + control.descriptions[:rationale] = json_control['tags']['rationale'] + control.descriptions[:check] = json_control['tags']['check'] + control.descriptions[:fix] = json_control['tags']['fix'] else control.desc = json_control['desc'] end control.id = json_control['id'] control.title = json_control['title'] control.impact = get_impact(json_control['impact']) - control.add_tag(Inspec::Tag.new('severity', json_control['tags']['severity'])) - control.add_tag(Inspec::Tag.new('gtitle', json_control['tags']['gtitle'])) - control.add_tag(Inspec::Tag.new('satisfies', json_control['tags']['satisfies'])) if json_control['tags']['satisfies'] - control.add_tag(Inspec::Tag.new('gid', json_control['tags']['gid'])) - control.add_tag(Inspec::Tag.new('rid', json_control['tags']['rid'])) - control.add_tag(Inspec::Tag.new('stig_id', json_control['tags']['stig_id'])) - control.add_tag(Inspec::Tag.new('fix_id', json_control['tags']['fix_id'])) - control.add_tag(Inspec::Tag.new('cci', json_control['tags']['cci'])) - control.add_tag(Inspec::Tag.new('nist', json_control['tags']['nist'])) - control.add_tag(Inspec::Tag.new('false_negatives', json_control['tags']['false_negatives'])) if json_control['tags']['false_positives'] != '' - control.add_tag(Inspec::Tag.new('false_positives', json_control['tags']['false_positives'])) if json_control['tags']['false_positives'] != '' - control.add_tag(Inspec::Tag.new('documentable', json_control['tags']['documentable'])) if json_control['tags']['documentable'] != '' - control.add_tag(Inspec::Tag.new('mitigations', json_control['tags']['mitigations'])) if json_control['tags']['mitigations'] != '' - control.add_tag(Inspec::Tag.new('severity_override_guidance', json_control['tags']['documentable'])) if json_control['tags']['severity_override_guidance'] != '' - control.add_tag(Inspec::Tag.new('potential_impacts', json_control['tags']['potential_impacts'])) if json_control['tags']['potential_impacts'] != '' - control.add_tag(Inspec::Tag.new('third_party_tools', json_control['tags']['third_party_tools'])) if json_control['tags']['third_party_tools'] != '' - control.add_tag(Inspec::Tag.new('mitigation_controls', json_control['tags']['mitigation_controls'])) if json_control['tags']['mitigation_controls'] != '' - control.add_tag(Inspec::Tag.new('responsibility', json_control['tags']['responsibility'])) if json_control['tags']['responsibility'] != '' - control.add_tag(Inspec::Tag.new('ia_controls', json_control['tags']['ia_controls'])) if json_control['tags']['ia_controls'] != '' - control.add_tag(Inspec::Tag.new('check', json_control['tags']['check'])) - control.add_tag(Inspec::Tag.new('fix', json_control['tags']['fix'])) + #json_control['tags'].each do |tag| + # control.add_tag(Inspec::Object::Tag.new(tag.key, tag.value) + #end + + control.add_tag(::Inspec::Object::Tag.new('severity', json_control['tags']['severity'])) + control.add_tag(::Inspec::Object::Tag.new('gtitle', json_control['tags']['gtitle'])) + control.add_tag(::Inspec::Object::Tag.new('satisfies', json_control['tags']['satisfies'])) if json_control['tags']['satisfies'] + control.add_tag(::Inspec::Object::Tag.new('gid', json_control['tags']['gid'])) + control.add_tag(::Inspec::Object::Tag.new('rid', json_control['tags']['rid'])) + control.add_tag(::Inspec::Object::Tag.new('stig_id', json_control['tags']['stig_id'])) + control.add_tag(::Inspec::Object::Tag.new('fix_id', json_control['tags']['fix_id'])) + control.add_tag(::Inspec::Object::Tag.new('cci', json_control['tags']['cci'])) + control.add_tag(::Inspec::Object::Tag.new('nist', json_control['tags']['nist'])) + control.add_tag(::Inspec::Object::Tag.new('cis_level', json_control['tags']['cis_level'])) unless json_control['tags']['cis_level'].blank? + control.add_tag(::Inspec::Object::Tag.new('cis_controls', json_control['tags']['cis_controls'])) unless json_control['tags']['cis_controls'].blank? + control.add_tag(::Inspec::Object::Tag.new('cis_rid', json_control['tags']['cis_rid'])) unless json_control['tags']['cis_rid'].blank? + control.add_tag(::Inspec::Object::Tag.new('ref', json_control['tags']['ref'])) unless json_control['tags']['ref'].blank? + control.add_tag(::Inspec::Object::Tag.new('false_negatives', json_control['tags']['false_negatives'])) unless json_control['tags']['false_positives'].blank? + control.add_tag(::Inspec::Object::Tag.new('false_positives', json_control['tags']['false_positives'])) unless json_control['tags']['false_positives'].blank? + control.add_tag(::Inspec::Object::Tag.new('documentable', json_control['tags']['documentable'])) unless json_control['tags']['documentable'].blank? + control.add_tag(::Inspec::Object::Tag.new('mitigations', json_control['tags']['mitigations'])) unless json_control['tags']['mitigations'].blank? + control.add_tag(::Inspec::Object::Tag.new('severity_override_guidance', json_control['tags']['documentable'])) unless json_control['tags']['severity_override_guidance'].blank? + control.add_tag(::Inspec::Object::Tag.new('potential_impacts', json_control['tags']['potential_impacts'])) unless json_control['tags']['potential_impacts'].blank? + control.add_tag(::Inspec::Object::Tag.new('third_party_tools', json_control['tags']['third_party_tools'])) unless json_control['tags']['third_party_tools'].blank? + control.add_tag(::Inspec::Object::Tag.new('mitigation_controls', json_control['tags']['mitigation_controls'])) unless json_control['tags']['mitigation_controls'].blank? + control.add_tag(::Inspec::Object::Tag.new('responsibility', json_control['tags']['responsibility'])) unless json_control['tags']['responsibility'].blank? + control.add_tag(::Inspec::Object::Tag.new('ia_controls', json_control['tags']['ia_controls'])) unless json_control['tags']['ia_controls'].blank? + controls << control end controls end @@ -266,10 +325,10 @@ if response.code == '200' license_content = response.body else license_content = inspec_json['license'] end - rescue StandardError => e + rescue StandardError => _e license_content = inspec_json['license'] end end myfile = File.new("#{directory}/LICENSE", 'w')