diff --git a/lib/openscap_parser.rb b/lib/openscap_parser.rb index c31c690..f94ea65 100644 --- a/lib/openscap_parser.rb +++ b/lib/openscap_parser.rb @@ -2,6 +2,7 @@ require 'openscap_parser/profiles' require 'openscap_parser/rule' require 'openscap_parser/rule_result' +require 'openscap_parser/rule_results' require 'openscap_parser/rules' require 'openscap_parser/version' require 'openscap_parser/xml_report' @@ -16,6 +17,7 @@ class Base include OpenscapParser::XMLReport include OpenscapParser::Profiles include OpenscapParser::Rules + include OpenscapParser::RuleResults def initialize(report) report_xml(report) @@ -32,14 +34,5 @@ def start_time def end_time @end_time ||= DateTime.parse(test_result_node['end-time']) end - - def rule_results - @rule_results ||= test_result_node.search('rule-result').map do |rr| - rule_result_oscap = RuleResult.new - rule_result_oscap.id = rr.attributes['idref'].value - rule_result_oscap.result = rr.search('result').first.text - rule_result_oscap - end - end end end diff --git a/lib/openscap_parser/profiles.rb b/lib/openscap_parser/profiles.rb index fffefd0..9cc2327 100644 --- a/lib/openscap_parser/profiles.rb +++ b/lib/openscap_parser/profiles.rb @@ -1,9 +1,12 @@ # frozen_string_literal: true +require 'openscap_parser/test_result' module OpenscapParser # Methods related to saving profiles and finding which hosts # they belong to module Profiles + include TestResult + def self.included(base) base.class_eval do def profiles @@ -18,10 +21,6 @@ def profile_node @report_xml.at_xpath(".//Profile\ [contains('#{test_result_node['id']}', @id)]") end - - def test_result_node - @test_result_node ||= @report_xml.at_css('TestResult') - end end end end diff --git a/lib/openscap_parser/rule.rb b/lib/openscap_parser/rule.rb index e21d130..fa0d4ab 100644 --- a/lib/openscap_parser/rule.rb +++ b/lib/openscap_parser/rule.rb @@ -20,11 +20,15 @@ def title end def description - @description ||= @rule_xml.at_css('description').text.delete("\n") + rule_node ||= @rule_xml.at_css('description') + @description ||= newline_to_whitespace(rule_node.text) if rule_node && rule_node.text end def rationale - @rationale ||= @rule_xml.at_css('rationale').children.text.delete("\n") + rationale_node ||= @rule_xml.at_css('rationale') + @rationale ||= newline_to_whitespace(rationale_node.children.text) if rationale_node && + rationale_node.children && + rationale_node.children.text end def references @@ -35,10 +39,15 @@ def references def identifier @identifier ||= { - label: @rule_xml.at_css('ident')&.text, + label: @rule_xml.at_css('ident') && @rule_xml.at_css('ident').text, system: (ident = @rule_xml.at_css('ident')) && ident['system'] } end + + private + + def newline_to_whitespace(string) + string.gsub(/ *\n+/, " ").strip + end end end - diff --git a/lib/openscap_parser/rule_results.rb b/lib/openscap_parser/rule_results.rb new file mode 100644 index 0000000..c0f467a --- /dev/null +++ b/lib/openscap_parser/rule_results.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true +require 'openscap_parser/test_result' + +module OpenscapParser + module RuleResults + include TestResult + + def self.included(base) + base.class_eval do + def rule_results + @rule_results ||= test_result_node.search('rule-result').map do |rr| + rule_result_oscap = RuleResult.new + rule_result_oscap.id = rr.attributes['idref'].value + rule_result_oscap.result = rr.search('result').first.text + rule_result_oscap + end + end + end + end + end +end diff --git a/lib/openscap_parser/test_result.rb b/lib/openscap_parser/test_result.rb new file mode 100644 index 0000000..5ab1ba4 --- /dev/null +++ b/lib/openscap_parser/test_result.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module OpenscapParser + module TestResult + def self.included(base) + base.class_eval do + private + + def test_result_node + @test_result_node ||= @report_xml.at_css('TestResult') + end + end + end + end +end diff --git a/openscap_parser.gemspec b/openscap_parser.gemspec index c9173b4..4ecf4c6 100644 --- a/openscap_parser.gemspec +++ b/openscap_parser.gemspec @@ -42,4 +42,5 @@ Gem::Specification.new do |spec| spec.add_development_dependency "minitest", "~> 5.0" spec.add_development_dependency "shoulda-context" spec.add_development_dependency "pry" + spec.add_development_dependency "pry-byebug" end diff --git a/test/openscap_parser_test.rb b/test/openscap_parser_test.rb index 97be664..a75516b 100644 --- a/test/openscap_parser_test.rb +++ b/test/openscap_parser_test.rb @@ -69,5 +69,23 @@ def setup assert_equal references, rule.references end + + should 'parse rule description without newlines' do + rule = @report_parser.rule_objects.find do |rule_obj| + rule_obj.id == 'xccdf_org.ssgproject.content_rule_service_atd_disabled' + end + + desc = <<~DESC.gsub("\n", ' ').strip + The at and batch commands can be used to + schedule tasks that are meant to be executed only once. This allows delayed + execution in a manner similar to cron, except that it is not + recurring. The daemon atd keeps track of tasks scheduled via + at and batch, and executes them at the specified time. + The atd service can be disabled with the following command: + $ sudo systemctl disable atd.service + DESC + + assert_equal desc, rule.description + end end end