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')