Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions lib/openscap_parser/fix.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# frozen_string_literal: true
require 'openscap_parser/xml_node'
require 'openscap_parser/subs'

module OpenscapParser
class Fix < XmlNode
include OpenscapParser::Subs

def id
@id ||= @parsed_xml['id']
end

def system
@system ||= @parsed_xml['system']
end

def complexity
@complexity ||= @parsed_xml['complexity']
end

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we include disruption and strategy?

def disruption
@disruption ||= @parsed_xml['disruption']
end

def strategy
@strategy ||= @parsed_xml['strategy']
end
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's put this on the XmlNode as it applies to any xml node.


def to_h
{
:id => id,
:system => system,
:complexity => complexity,
:disruption => disruption,
:strategy => strategy,
:text => text,
:subs => subs.map(&:to_h)
}
end
end
end
21 changes: 21 additions & 0 deletions lib/openscap_parser/fixes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

require 'openscap_parser/fix'

module OpenscapParser
module Fixes
def self.included(base)
base.class_eval do
def fixes
@fixes ||= fix_nodes.map do |fix_node|
OpenscapParser::Fix.new(parsed_xml: fix_node)
end
end

def fix_nodes(xpath = ".//fix")
xpath_nodes(xpath)
end
end
end
end
end
2 changes: 2 additions & 0 deletions lib/openscap_parser/rule.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

require 'openscap_parser/rule_identifier'
require 'openscap_parser/rule_references'
require 'openscap_parser/fixes'
require 'openscap_parser/xml_file'

# Mimics openscap-ruby Rule interface
module OpenscapParser
class Rule < XmlNode
include OpenscapParser::Util
include OpenscapParser::RuleReferences
include OpenscapParser::Fixes

def id
@id ||= parsed_xml['id']
Expand Down
10 changes: 10 additions & 0 deletions lib/openscap_parser/rule_result.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ def result
@result ||= parsed_xml.at_xpath('result') &&
parsed_xml.at_xpath('result').text || ''
end

def to_h
{
:id => id,
:time => time,
:severity => severity,
:weight => weight,
:result => result
}
end
end
end

18 changes: 18 additions & 0 deletions lib/openscap_parser/sub.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true
require 'openscap_parser/xml_node'

module OpenscapParser
class Sub < XmlNode
def id
@id ||= @parsed_xml['idref']
end

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add use here?

the xccdf:sub element MAY have a use attribute that indicates whether the xccdf:Value element's title or value should replace the xccdf:sub element.

def use
@use ||= @parsed_xml['use']
end

def to_h
{ :id => id, :text => text, :use => use }
end
end
end
22 changes: 22 additions & 0 deletions lib/openscap_parser/subs.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

require 'openscap_parser/sub'

module OpenscapParser
module Subs
def self.included(base)
base.class_eval do
def subs
return [] unless sub_nodes
@subs ||= sub_nodes.map do |xml|
Sub.new(parsed_xml: xml)
end
end

def sub_nodes(xpath = './/sub')
@sub_nodes ||= xpath_nodes(xpath)
end
end
end
end
end
4 changes: 4 additions & 0 deletions lib/openscap_parser/xml_node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ def parsed_xml(report_contents = '')
@parsed_xml.remove_namespaces!
end

def text
@parsed_xml.text
end

def xpath_node(xpath)
parsed_xml && parsed_xml.at_xpath(xpath)
end
Expand Down
57 changes: 57 additions & 0 deletions test/openscap_parser/test_result_file_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,63 @@ def setup
parse_set_values @arf_result_file
end
end

context 'fixes' do
test 'should parse fixes for xccdf report' do
parse_fixes @test_result_file
end

test 'should parse fixes for arf report' do
parse_fixes @arf_result_file
end

test 'should parse multiple fixes for one rule' do
rule = @arf_result_file.benchmark.rules.find { |rule| rule.id == "xccdf_org.ssgproject.content_rule_ensure_gpgcheck_globally_activated" }
fixes = rule.fixes
assert_equal 2, fixes.count
assert fixes.map(&:id).all? { |id| id == 'ensure_gpgcheck_globally_activated' }
refute_equal fixes.first.system, fixes.last.system
end

test "should parse one sub for fix" do
rule = @arf_result_file.benchmark.rules.find { |rule| rule.id == "xccdf_org.ssgproject.content_rule_ensure_gpgcheck_globally_activated" }
fix = rule.fixes.find { |fix| !fix.subs.empty? }
assert_equal 1, fix.subs.count
assert fix.subs.first.id
assert fix.subs.first.text
end

test "should parse attributes for fix" do
rule = @arf_result_file.benchmark.rules.find { |rule| rule.id == "xccdf_org.ssgproject.content_rule_enable_selinux_bootloader" }
fix = rule.fixes.find { |fx| fx.system == "urn:xccdf:fix:script:sh" }
assert_empty fix.subs
assert fix.text
assert fix.complexity
assert fix.disruption
assert fix.strategy
end

test "should parse multiple subs for fix" do
rule = @arf_result_file.benchmark.rules.find { |rule| rule.id == "xccdf_org.ssgproject.content_rule_selinux_state" }
fix = rule.fixes.find { |fix| !fix.subs.empty? }
assert_equal 2, fix.subs.count
sub = fix.subs.last
assert sub.id
assert sub.text
assert sub.use
end
end
end

private

def parse_fixes(result_file)
fixes = result_file.benchmark.rules.flat_map(&:fixes).map(&:to_h)
ids = fixes.map { |fix| fix[:id] }
systems = fixes.map { |fix| fix[:system] }
refute_empty fixes
assert_equal ids, ids.compact
assert_equal systems, systems.compact
end

def parse_set_values(result_file)
Expand Down