Class: HeimdallTools::XCCDFResultsMapper

Inherits:
Object
  • Object
show all
Defined in:
lib/heimdall_tools/xccdf_results_mapper.rb

Instance Method Summary collapse

Constructor Details

#initialize(scap_xml, _name = nil) ⇒ XCCDFResultsMapper

Returns a new instance of XCCDFResultsMapper.



32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/heimdall_tools/xccdf_results_mapper.rb', line 32

def initialize(scap_xml, _name = nil)
  @scap_xml = scap_xml
  read_cci_xml
  begin
    data = xml_to_hash(scap_xml)
    @results = data['Benchmark']['TestResult']
    @benchmarks = data['Benchmark']
    @groups = data['Benchmark']['Group']
  rescue StandardError => e
    raise "Invalid SCAP Client XCCDF output XML file provided Exception: #{e}"
  end
end

Instance Method Details

#cci_nist_tag(cci_refs) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
# File 'lib/heimdall_tools/xccdf_results_mapper.rb', line 71

def cci_nist_tag(cci_refs)
  nist_tags = []
  cci_refs.each do |cci_ref|
    item_node = @cci_xml.xpath("//cci_list/cci_items/cci_item[@id='#{cci_ref}']")[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
    end
    nist_tags << nist_ref
  end
  nist_tags
end

#collapse_duplicates(controls) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
# File 'lib/heimdall_tools/xccdf_results_mapper.rb', line 103

def collapse_duplicates(controls)
  unique_controls = []

  controls.map { |x| x['id'] }.uniq.each do |id|
    collapsed_results = controls.select { |x| x['id'].eql?(id) }.map { |x| x['results'] }
    unique_control = controls.find { |x| x['id'].eql?(id) }
    unique_control['results'] = collapsed_results.flatten
    unique_controls << unique_control
  end
  unique_controls
end

#desc_tags(data, label) ⇒ Object



99
100
101
# File 'lib/heimdall_tools/xccdf_results_mapper.rb', line 99

def desc_tags(data, label)
  { data: data || NA_STRING, label: label || NA_STRING }
end

#finding(issue, count) ⇒ Object

change for pass/fail based on output Benchmark.rule Pass/Fail are the only two options included in the output file



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/heimdall_tools/xccdf_results_mapper.rb', line 47

def finding(issue, count)
  finding = {}
  finding['status'] = issue['rule-result'][count]['result'].to_s
  if finding['status'] == 'pass'
    finding['status'] = 'passed'
  end
  if finding['status'] == 'fail'
    finding['status'] = 'failed'
  end
  finding['code_desc']      = NA_STRING
  finding['run_time']       = NA_FLOAT
  finding['start_time']     = issue['start-time']
  finding['message']        = NA_STRING
  finding['resource_class'] = NA_STRING
  [finding]
end

#get_impact(severity) ⇒ Object



83
84
85
# File 'lib/heimdall_tools/xccdf_results_mapper.rb', line 83

def get_impact(severity)
  IMPACT_MAPPING[severity.to_sym]
end

#parse_refs(refs) ⇒ Object



87
88
89
# File 'lib/heimdall_tools/xccdf_results_mapper.rb', line 87

def parse_refs(refs)
  refs.map { |ref| ref['text'] if ref['text'].match?(CCI_REGEX) }.reject!(&:nil?)
end

#read_cci_xmlObject



64
65
66
67
68
69
# File 'lib/heimdall_tools/xccdf_results_mapper.rb', line 64

def read_cci_xml
  @cci_xml = Nokogiri::XML(File.open(U_CCI_LIST))
  @cci_xml.remove_namespaces!
rescue StandardError => e
  puts "Exception: #{e.message}"
end

#satisfies_parse(satisf) ⇒ Object

Clean up output by removing the Satsifies block and the end of the description



92
93
94
95
96
97
# File 'lib/heimdall_tools/xccdf_results_mapper.rb', line 92

def satisfies_parse(satisf)
  temp_satisf = satisf.match('Satisfies: ([^;]*)<\/VulnDiscussion>')
  return temp_satisf[1].split(',') unless temp_satisf.nil?

  NA_ARRAY
end

#to_hdfObject



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/heimdall_tools/xccdf_results_mapper.rb', line 115

def to_hdf
  controls = []
  @groups.each_with_index do |group, i|
    @item = {}
    @item['id'] = group['Rule']['id'].split('.').last.split('_').drop(2).first.split('r').first.split('S')[1]
    @item['title']               = group['Rule']['title'].to_s
    @item['desc']                = group['Rule']['description'].to_s.split('Satisfies').first
    @item['descriptions']		 = []
    @item['descriptions']		 << desc_tags(group['Rule']['description'], 'default')
    @item['descriptions']		 << desc_tags('NA', 'rationale')
    @item['descriptions']		 << desc_tags(group['Rule']['check']['check-content-ref']['name'], 'check')
    @item['descriptions']		 << desc_tags(group['Rule']['fixtext']['text'], 'fix')
    @item['impact']				 = get_impact(group['Rule']['severity'])
    @item['refs']				 = NA_ARRAY
    @item['tags']				 = {}
    @item['tags']['severity']    = nil
    @item['tags']['gtitle']      = group['title']
    @item['tags']['satisfies']   = satisfies_parse(group['Rule']['description'])
    @item['tags']['gid']         = group['Rule']['id'].split('.').last.split('_').drop(2).first.split('r').first
    @item['tags']['legacy_id']   = group['Rule']['ident'][2]['text']
    @item['tags']['rid']         = group['Rule']['ident'][1]['text']
    @item['tags']['stig_id']     = @benchmarks['id']
    @item['tags']['fix_id']      = group['Rule']['fix']['id']
    @item['tags']['cci']         = parse_refs(group['Rule']['ident'])
    @item['tags']['nist']        = cci_nist_tag(@item['tags']['cci'])
    @item['code']                = NA_STRING
    @item['source_location'] = NA_HASH
    # results were in another location and using the top block "Benchmark" as a starting point caused odd issues. This works for now for the results.
    @item['results'] = finding(@results, i)
    controls << @item
  end

  controls = collapse_duplicates(controls)
  results = HeimdallDataFormat.new(profile_name: @benchmarks['id'],
                                   version: @benchmarks['style'],
                                   duration: NA_FLOAT,
                                   title: @benchmarks['title'],
                                   maintainer: @benchmarks['reference']['publisher'],
                                   summary: @benchmarks['description'],
                                   license: @benchmarks['notice']['id'],
                                   copyright: @benchmarks['metadata']['creator'],
                                   copyright_email: '[email protected]',
                                   controls: controls)
  results.to_hdf
end