diff --git a/.rubocop.yml b/.rubocop.yml index 4f795fe..01f6a0f 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -21,6 +21,22 @@ Metrics/BlockLength: Exclude: - 'test/**/*' - 'spec/**/*' + - 'openscap_parser.gemspec' + +Metrics/MethodLength: + AllowedMethods: ['included'] + +Metrics/AbcSize: + AllowedMethods: ['included'] + +Metrics/CyclomaticComplexity: + AllowedMethods: ['included'] + +Metrics/PerceivedComplexity: + AllowedMethods: ['included'] + +Gemspec/DevelopmentDependencies: + EnforcedStyle: gemspec Layout/LineEndStringConcatenationIndentation: Enabled: false diff --git a/lib/openscap_parser/benchmark.rb b/lib/openscap_parser/benchmark.rb index dd4435b..5835ac2 100644 --- a/lib/openscap_parser/benchmark.rb +++ b/lib/openscap_parser/benchmark.rb @@ -10,6 +10,7 @@ # Mimics openscap-ruby Benchmark interface module OpenscapParser + # A class for parsing Benchmark information class Benchmark < XmlNode include OpenscapParser::Util include OpenscapParser::Rules @@ -23,8 +24,7 @@ def id end def title - @title ||= @parsed_xml.xpath('title') && - @parsed_xml.xpath('title').text + @title ||= @parsed_xml.xpath('title')&.text end def description @@ -35,8 +35,7 @@ def description end def version - @version ||= @parsed_xml.xpath('version') && - @parsed_xml.xpath('version').text + @version ||= @parsed_xml.xpath('version')&.text end end end diff --git a/lib/openscap_parser/benchmarks.rb b/lib/openscap_parser/benchmarks.rb index 58065c6..ef4736c 100644 --- a/lib/openscap_parser/benchmarks.rb +++ b/lib/openscap_parser/benchmarks.rb @@ -12,7 +12,7 @@ def benchmark @benchmark ||= OpenscapParser::Benchmark.new(parsed_xml: benchmark_node) end - def benchmark_node(xpath = ".//Benchmark") + def benchmark_node(xpath = './/Benchmark') xpath_node(xpath) end end diff --git a/lib/openscap_parser/datastream_file.rb b/lib/openscap_parser/datastream_file.rb index 8de0f4e..3ce499f 100644 --- a/lib/openscap_parser/datastream_file.rb +++ b/lib/openscap_parser/datastream_file.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require 'openscap_parser/xml_file' require 'openscap_parser/benchmarks' @@ -9,6 +10,7 @@ class DatastreamFile < XmlFile def valid? return true if @parsed_xml.root.name == 'data-stream-collection' && namespaces.keys.include?('xmlns:ds') + false end end diff --git a/lib/openscap_parser/fix.rb b/lib/openscap_parser/fix.rb index 1aa2650..8089da8 100644 --- a/lib/openscap_parser/fix.rb +++ b/lib/openscap_parser/fix.rb @@ -1,8 +1,10 @@ # frozen_string_literal: true + require 'openscap_parser/xml_node' require 'openscap_parser/subs' module OpenscapParser + # A class for parsing Fix information class Fix < XmlNode include OpenscapParser::Subs @@ -27,7 +29,7 @@ def strategy end def full_text(set_values) - full_text_lines(set_values).join('') + full_text_lines(set_values).join end def full_text_lines(set_values) @@ -42,13 +44,13 @@ def map_child_nodes(set_values = []) def to_h { - :id => id, - :system => system, - :complexity => complexity, - :disruption => disruption, - :strategy => strategy, - :text => text, - :subs => subs.map(&:to_h) + id:, + system:, + complexity:, + disruption:, + strategy:, + text:, + subs: subs.map(&:to_h) } end end diff --git a/lib/openscap_parser/fixes.rb b/lib/openscap_parser/fixes.rb index 9183463..b5fac2c 100644 --- a/lib/openscap_parser/fixes.rb +++ b/lib/openscap_parser/fixes.rb @@ -3,6 +3,7 @@ require 'openscap_parser/fix' module OpenscapParser + # Methods related to finding and saving Fixes module Fixes def self.included(base) base.class_eval do @@ -12,7 +13,7 @@ def fixes end end - def fix_nodes(xpath = ".//fix") + def fix_nodes(xpath = './/fix') xpath_nodes(xpath) end end diff --git a/lib/openscap_parser/group.rb b/lib/openscap_parser/group.rb index 44e74b6..50f8260 100644 --- a/lib/openscap_parser/group.rb +++ b/lib/openscap_parser/group.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true + module OpenscapParser + # A class for parsing Group information class Group < XmlNode include OpenscapParser::Util @@ -8,8 +10,7 @@ def id end def title - @title ||= parsed_xml.at_css('title') && - parsed_xml.at_css('title').text + @title ||= parsed_xml.at_css('title')&.text end def description @@ -28,16 +29,16 @@ def rationale def requires @requires ||= parsed_xml.xpath('./requires') && - parsed_xml.xpath('./requires/@idref').flat_map do |r| - r.to_s&.split - end + parsed_xml.xpath('./requires/@idref').flat_map do |r| + r.to_s&.split + end end def conflicts @conflicts ||= parsed_xml.xpath('./conflicts') && - parsed_xml.xpath('./conflicts/@idref').flat_map do |c| - c.to_s&.split - end + parsed_xml.xpath('./conflicts/@idref').flat_map do |c| + c.to_s&.split + end end def selected @@ -53,24 +54,23 @@ def parent_ids end def parent_type - if parsed_xml.xpath("name(..)='Group'") - @parent_type = 'Group' - else - @parent_type = 'Benchmark' - end + @parent_type = if parsed_xml.xpath("name(..)='Group'") + 'Group' + else + 'Benchmark' + end end def to_h { - :id => id, - :title => title, - :description => description, - :requires => requires, - :conflicts => conflicts, - :rationale => rationale, - :selected => selected, - :parent_id => parent_id, - :parent_type => parent_type + id:, title:, + description:, + requires:, + conflicts:, + rationale:, + selected:, + parent_id:, + parent_type: } end end diff --git a/lib/openscap_parser/groups.rb b/lib/openscap_parser/groups.rb index f1899ce..28fc4f5 100644 --- a/lib/openscap_parser/groups.rb +++ b/lib/openscap_parser/groups.rb @@ -3,7 +3,7 @@ require 'openscap_parser/group' module OpenscapParser - # Methods related to finding and saving rule references + # Methods related to finding and saving Groups module Groups def self.included(base) base.class_eval do diff --git a/lib/openscap_parser/oval_report.rb b/lib/openscap_parser/oval_report.rb index 4ba52d0..e829dc1 100644 --- a/lib/openscap_parser/oval_report.rb +++ b/lib/openscap_parser/oval_report.rb @@ -1,15 +1,17 @@ # frozen_string_literal: true + require 'openscap_parser/xml_file' require 'oval/definition_result' require 'oval/definition' module OpenscapParser + # A class for parsing Oval report information class OvalReport < XmlFile def definition_results @definition_results ||= definition_result_nodes.map { |node| ::Oval::DefinitionResult.new parsed_xml: node } end - def definition_result_nodes(xpath = "./oval_results/results/system/definitions/definition") + def definition_result_nodes(xpath = './oval_results/results/system/definitions/definition') xpath_nodes(xpath) end @@ -17,7 +19,7 @@ def definitions @definitions ||= definition_nodes.map { |node| Oval::Definition.new parsed_xml: node } end - def definition_nodes(xpath = "./oval_results/oval_definitions/definitions/definition") + def definition_nodes(xpath = './oval_results/oval_definitions/definitions/definition') xpath_nodes(xpath) end end diff --git a/lib/openscap_parser/profile.rb b/lib/openscap_parser/profile.rb index cb47c6c..7b8e789 100644 --- a/lib/openscap_parser/profile.rb +++ b/lib/openscap_parser/profile.rb @@ -1,53 +1,47 @@ +# frozen_string_literal: true + require 'openscap_parser/regex_handler' module OpenscapParser + # A class for parsing Profile information class Profile < XmlNode def id @id ||= @parsed_xml['id'] end def extends_profile_id - @extends ||= @parsed_xml['extends'] + @extends_profile_id ||= @parsed_xml['extends'] end def title - @title ||= @parsed_xml.at_css('title') && - @parsed_xml.at_css('title').text + @title ||= @parsed_xml.at_css('title')&.text end - alias :name :title + alias name title def description - @description ||= @parsed_xml.at_css('description') && - @parsed_xml.at_css('description').text + @description ||= @parsed_xml.at_css('description')&.text end def selected_rule_ids # Look for selected rule ids where the idref contains '_rule_' that is not preceded by 'group' @selected_rule_ids ||= @parsed_xml.xpath("select[@selected='true'] [regex(@idref, '^((?!_group_).)*?(_rule_).*$')] - /@idref", RegexHandler) && - @parsed_xml.xpath("select[@selected='true'] - [regex(@idref, '^((?!_group_).)*?(_rule_).*$')] - /@idref", RegexHandler).map(&:text) + /@idref", RegexHandler)&.map(&:text) end def unselected_group_ids # Look for group ids that are not selected where the idref contains '_group_' that is not preceded by 'rule' @unselected_group_ids ||= @parsed_xml.xpath("select[@selected='false'] [regex(@idref, '^((?!_rule_).)*?(_group_).*$')] - /@idref", RegexHandler) && - @parsed_xml.xpath("select[@selected='false'] - [regex(@idref, '^((?!_rule_).)*?(_group_).*$')] - /@idref", RegexHandler).map(&:text) + /@idref", RegexHandler)&.map(&:text) end def selected_entity_ids - @selected_entity_ids ||= @parsed_xml.xpath("select[@selected='true']/@idref") && - @parsed_xml.xpath("select[@selected='true']/@idref").map(&:text) + @selected_entity_ids ||= @parsed_xml.xpath("select[@selected='true']/@idref")&.map(&:text) end def refined_values - @refined_values ||= @parsed_xml.xpath("refine-value").each_with_object({}) do |element, rv| + @refined_values ||= @parsed_xml.xpath('refine-value').each_with_object({}) do |element, rv| rv[element.at_xpath('@idref').text] = element.at_xpath('@selector').text end end @@ -72,13 +66,13 @@ def refined_rule_weight def to_h { - :id => id, - :title => title, - :description => description, - :refined_values => refined_values, - :refined_rule_severity => refined_rule_severity, - :refined_rule_role => refined_rule_role, - :refined_rule_weight => refined_rule_weight + id:, + title:, + description:, + refined_values:, + refined_rule_severity:, + refined_rule_role:, + refined_rule_weight: } end end diff --git a/lib/openscap_parser/profiles.rb b/lib/openscap_parser/profiles.rb index bc2084a..e6cfdbb 100644 --- a/lib/openscap_parser/profiles.rb +++ b/lib/openscap_parser/profiles.rb @@ -14,7 +14,7 @@ def profiles end end - def profile_nodes(xpath = ".//Profile") + def profile_nodes(xpath = './/Profile') xpath_nodes(xpath) end end diff --git a/lib/openscap_parser/regex_handler.rb b/lib/openscap_parser/regex_handler.rb index d694ada..c49cdca 100644 --- a/lib/openscap_parser/regex_handler.rb +++ b/lib/openscap_parser/regex_handler.rb @@ -1,8 +1,9 @@ # frozen_string_literal: true module OpenscapParser + # Methods for handling regex class RegexHandler < XmlNode - def self.regex node_set, regex + def self.regex(node_set, regex) node_set.find_all { |node| node.to_s =~ /#{regex}/ } end end diff --git a/lib/openscap_parser/rule.rb b/lib/openscap_parser/rule.rb index 32c554a..4541da4 100644 --- a/lib/openscap_parser/rule.rb +++ b/lib/openscap_parser/rule.rb @@ -7,6 +7,7 @@ # Mimics openscap-ruby Rule interface module OpenscapParser + # A class for parsing Rule information class Rule < XmlNode include OpenscapParser::Util include OpenscapParser::RuleReferences @@ -25,22 +26,21 @@ def severity end def title - @title ||= parsed_xml.at_css('title') && - parsed_xml.at_css('title').text + @title ||= parsed_xml.at_css('title')&.text end def requires @requires ||= parsed_xml.xpath('./requires') && - parsed_xml.xpath('./requires/@idref').flat_map do |r| - r.to_s&.split - end + parsed_xml.xpath('./requires/@idref').flat_map do |r| + r.to_s&.split + end end def conflicts @conflicts ||= parsed_xml.xpath('./conflicts') && - parsed_xml.xpath('./conflicts/@idref').flat_map do |c| - c.to_s&.split - end + parsed_xml.xpath('./conflicts/@idref').flat_map do |c| + c.to_s&.split + end end def description @@ -57,15 +57,15 @@ def rationale ) end - alias :rule_reference_nodes_old :rule_reference_nodes - def rule_reference_nodes(xpath = "reference") + alias rule_reference_nodes_old rule_reference_nodes + def rule_reference_nodes(xpath = 'reference') rule_reference_nodes_old(xpath) end def rule_identifier - @identifier ||= identifier_node && RuleIdentifier.new(parsed_xml: identifier_node) + @rule_identifier ||= identifier_node && RuleIdentifier.new(parsed_xml: identifier_node) end - alias :identifier :rule_identifier + alias identifier rule_identifier def identifier_node @identifier_node ||= parsed_xml.at_xpath('ident') @@ -76,31 +76,27 @@ def parent_id end def parent_type - if parsed_xml.xpath("name(..)='Group'") - @parent_type = 'Group' - else - @parent_type = 'Benchmark' - end + @parent_type = if parsed_xml.xpath("name(..)='Group'") + 'Group' + else + 'Benchmark' + end end def values - parsed_xml.xpath("check/check-export").map { |r| r.at_xpath('@value-id')&.text } + parsed_xml.xpath('check/check-export').map { |r| r.at_xpath('@value-id')&.text } end def to_h { - :id => id, - :selected => selected, - :severity => severity, - :title => title, - :requires => requires, - :conflicts => conflicts, - :description => description, - :rationale => rationale, - :identifier => rule_identifier.to_h, - :parent_id => parent_id, - :parent_type => parent_type, - :values => values + id:, selected:, + severity:, title:, + requires:, conflicts:, + description:, rationale:, + identifier: rule_identifier.to_h, + parent_id:, + parent_type:, + values: } end end diff --git a/lib/openscap_parser/rule_identifier.rb b/lib/openscap_parser/rule_identifier.rb index a441c84..6dc4fc9 100644 --- a/lib/openscap_parser/rule_identifier.rb +++ b/lib/openscap_parser/rule_identifier.rb @@ -2,9 +2,10 @@ # RuleIdentifier interface as an object module OpenscapParser + # A class for parsing RuleIdentifier information class RuleIdentifier < XmlNode def label - @label ||= @parsed_xml && @parsed_xml.text + @label ||= @parsed_xml&.text end def system @@ -13,8 +14,8 @@ def system def to_h { - :label => label, - :system => system + label:, + system: } end end diff --git a/lib/openscap_parser/rule_reference.rb b/lib/openscap_parser/rule_reference.rb index df8dee3..5a0211e 100644 --- a/lib/openscap_parser/rule_reference.rb +++ b/lib/openscap_parser/rule_reference.rb @@ -2,19 +2,20 @@ # RuleReference interface as an object module OpenscapParser + # A class for parsing RuleReference information class RuleReference < XmlNode def href @href ||= @parsed_xml && @parsed_xml['href'] end def label - @label ||= @parsed_xml && @parsed_xml.text + @label ||= @parsed_xml&.text end def to_h { - href: href, - label: label + href:, + label: } end end diff --git a/lib/openscap_parser/rule_references.rb b/lib/openscap_parser/rule_references.rb index 2fda4ad..44b81b2 100644 --- a/lib/openscap_parser/rule_references.rb +++ b/lib/openscap_parser/rule_references.rb @@ -15,15 +15,16 @@ def rule_reference_strings end def rule_references - @rule_references ||= rule_reference_nodes.map do |node| + nodes = rule_reference_nodes.map do |node| OpenscapParser::RuleReference.new(parsed_xml: node) - end.uniq do |reference| + end + @rule_references ||= nodes.uniq do |reference| [reference.label, reference.href] end end - alias :references :rule_references + alias_method :references, :rule_references - def rule_reference_nodes(xpath = ".//Rule/reference") + def rule_reference_nodes(xpath = './/Rule/reference') xpath_nodes(xpath) end end diff --git a/lib/openscap_parser/rule_result.rb b/lib/openscap_parser/rule_result.rb index 5f7d386..06f32c6 100644 --- a/lib/openscap_parser/rule_result.rb +++ b/lib/openscap_parser/rule_result.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true module OpenscapParser + # A class for parsing RuleResult information class RuleResult < XmlNode def id @id ||= parsed_xml['idref'] @@ -19,19 +20,17 @@ def weight end def result - @result ||= parsed_xml.at_xpath('result') && - parsed_xml.at_xpath('result').text || '' + @result ||= parsed_xml.at_xpath('result')&.text || '' end def to_h { - :id => id, - :time => time, - :severity => severity, - :weight => weight, - :result => result + id:, + time:, + severity:, + weight:, + result: } end end end - diff --git a/lib/openscap_parser/rule_results.rb b/lib/openscap_parser/rule_results.rb index b775a9a..68c7e51 100644 --- a/lib/openscap_parser/rule_results.rb +++ b/lib/openscap_parser/rule_results.rb @@ -3,6 +3,7 @@ require 'openscap_parser/rule_result' module OpenscapParser + # Methods related to finding and saving Rule Results module RuleResults def self.included(base) base.class_eval do diff --git a/lib/openscap_parser/rules.rb b/lib/openscap_parser/rules.rb index f91d11b..3b56e72 100644 --- a/lib/openscap_parser/rules.rb +++ b/lib/openscap_parser/rules.rb @@ -12,9 +12,9 @@ def rule_objects Rule.new(parsed_xml: rule_node) end end - alias :rules :rule_objects + alias_method :rules, :rule_objects - def rule_nodes(xpath = ".//Rule") + def rule_nodes(xpath = './/Rule') xpath_nodes(xpath) end end diff --git a/lib/openscap_parser/set_value.rb b/lib/openscap_parser/set_value.rb index 1ffa5af..169003b 100644 --- a/lib/openscap_parser/set_value.rb +++ b/lib/openscap_parser/set_value.rb @@ -1,7 +1,9 @@ # frozen_string_literal: true + require 'openscap_parser/xml_node' module OpenscapParser + # A class for parsing SetValue information class SetValue < XmlNode def id @id ||= @parsed_xml['idref'] @@ -12,7 +14,7 @@ def text end def to_h - { :id => id, :text => text } + { id:, text: } end end end diff --git a/lib/openscap_parser/set_values.rb b/lib/openscap_parser/set_values.rb index f0a7bad..a0e1c12 100644 --- a/lib/openscap_parser/set_values.rb +++ b/lib/openscap_parser/set_values.rb @@ -3,6 +3,7 @@ require 'openscap_parser/set_value' module OpenscapParser + # Methods related to finding and saving SetValues module SetValues def self.included(base) base.class_eval do @@ -12,7 +13,7 @@ def set_values end end - def set_value_nodes(xpath = ".//set-value") + def set_value_nodes(xpath = './/set-value') xpath_nodes(xpath) end end diff --git a/lib/openscap_parser/sub.rb b/lib/openscap_parser/sub.rb index 42957f4..8de813a 100644 --- a/lib/openscap_parser/sub.rb +++ b/lib/openscap_parser/sub.rb @@ -1,7 +1,9 @@ # frozen_string_literal: true + require 'openscap_parser/xml_node' module OpenscapParser + # A class for parsing Sub information class Sub < XmlNode def id @id ||= @parsed_xml['idref'] @@ -12,7 +14,7 @@ def use end def to_h - { :id => id, :text => text, :use => use } + { id:, text:, use: } end end end diff --git a/lib/openscap_parser/subs.rb b/lib/openscap_parser/subs.rb index 865147a..3734671 100644 --- a/lib/openscap_parser/subs.rb +++ b/lib/openscap_parser/subs.rb @@ -3,11 +3,13 @@ require 'openscap_parser/sub' module OpenscapParser + # Methods related to finding and saving Subs 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 @@ -21,6 +23,7 @@ def map_sub_nodes(children, set_values) children.map do |child| next child if child.name == 'text' next replace_sub(Sub.new(parsed_xml: child), set_values) if child.name == 'sub' + child end end @@ -28,8 +31,9 @@ def map_sub_nodes(children, set_values) private def replace_sub(sub, set_values) - set_value = set_values.find { |set_value| set_value.id == sub.id } + set_value = set_values.find { |sv| sv.id == sub.id } return unless set_value + set_value.parsed_xml.children.first end end diff --git a/lib/openscap_parser/tailoring.rb b/lib/openscap_parser/tailoring.rb index f8ac544..6305759 100644 --- a/lib/openscap_parser/tailoring.rb +++ b/lib/openscap_parser/tailoring.rb @@ -2,6 +2,7 @@ # Mimics openscap-ruby Rule interface module OpenscapParser + # A class for parsing Tailoring information class Tailoring < XmlNode include OpenscapParser::Profiles @@ -10,18 +11,15 @@ def id end def benchmark - @benchmark ||= @parsed_xml.at_xpath('benchmark/@href') && - @parsed_xml.at_xpath('benchmark/@href').text + @benchmark ||= @parsed_xml.at_xpath('benchmark/@href')&.text end def version - @version ||= @parsed_xml.at_xpath('version') && - @parsed_xml.at_xpath('version').text + @version ||= @parsed_xml.at_xpath('version')&.text end def version_time - @version_time ||= @parsed_xml.at_xpath('version/@time') && - @parsed_xml.at_xpath('version/@time').text + @version_time ||= @parsed_xml.at_xpath('version/@time')&.text end end end diff --git a/lib/openscap_parser/tailoring_file.rb b/lib/openscap_parser/tailoring_file.rb index 8a6568b..76bbe34 100644 --- a/lib/openscap_parser/tailoring_file.rb +++ b/lib/openscap_parser/tailoring_file.rb @@ -9,6 +9,7 @@ class TailoringFile < XmlFile def valid? return true if @parsed_xml.root.name == 'Tailoring' && namespaces.keys.include?('xmlns:xccdf') + false end end diff --git a/lib/openscap_parser/tailorings.rb b/lib/openscap_parser/tailorings.rb index 23b7479..5f35252 100644 --- a/lib/openscap_parser/tailorings.rb +++ b/lib/openscap_parser/tailorings.rb @@ -13,7 +13,7 @@ def tailoring ) end - def tailoring_node(xpath = ".//Tailoring") + def tailoring_node(xpath = './/Tailoring') xpath_node(xpath) end end diff --git a/lib/openscap_parser/test_result.rb b/lib/openscap_parser/test_result.rb index 1d765d6..8487c1f 100644 --- a/lib/openscap_parser/test_result.rb +++ b/lib/openscap_parser/test_result.rb @@ -4,15 +4,15 @@ require 'openscap_parser/selectors' module OpenscapParser + # A class for parsing TestResult information class TestResult < XmlNode include OpenscapParser::RuleResults include OpenscapParser::Selectors def target - @target ||= parsed_xml.at_xpath('target') && - parsed_xml.at_xpath('target').text || '' + @target ||= parsed_xml.at_xpath('target')&.text || '' end - alias :host :target + alias host target def target_fact_nodes @target_fact_nodes ||= parsed_xml.xpath('target-facts/fact') @@ -23,23 +23,21 @@ def platform_nodes end def title - @title ||= parsed_xml.at_xpath('title') && - parsed_xml.at_xpath('title').text || '' + @title ||= parsed_xml.at_xpath('title')&.text || '' end def identity - @identity ||= parsed_xml.at_xpath('identity') && - parsed_xml.at_xpath('identity').text || '' + @identity ||= parsed_xml.at_xpath('identity')&.text || '' end def profile_id @profile_id ||= parsed_xml.at_xpath('profile') && - parsed_xml.at_xpath('profile')['idref'] || '' + parsed_xml.at_xpath('profile')['idref'] || '' end def benchmark_id @benchmark_id ||= parsed_xml.at_xpath('benchmark') && - parsed_xml.at_xpath('benchmark')['id'] || '' + parsed_xml.at_xpath('benchmark')['id'] || '' end def set_value_nodes @@ -48,7 +46,7 @@ def set_value_nodes def score @score ||= parsed_xml.at_xpath('score') && - parsed_xml.at_xpath('score').text.to_f + parsed_xml.at_xpath('score').text.to_f end def start_time diff --git a/lib/openscap_parser/test_result_file.rb b/lib/openscap_parser/test_result_file.rb index 211a44b..ceb45e4 100644 --- a/lib/openscap_parser/test_result_file.rb +++ b/lib/openscap_parser/test_result_file.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require 'openscap_parser/xml_file' require 'openscap_parser/benchmarks' require 'openscap_parser/test_results' diff --git a/lib/openscap_parser/test_results.rb b/lib/openscap_parser/test_results.rb index ce01340..2c45df5 100644 --- a/lib/openscap_parser/test_results.rb +++ b/lib/openscap_parser/test_results.rb @@ -3,6 +3,7 @@ require 'openscap_parser/test_result' module OpenscapParser + # Methods related to finding and saving TestResults module TestResults def self.included(base) base.class_eval do diff --git a/lib/openscap_parser/util.rb b/lib/openscap_parser/util.rb index d3b7b05..1e89f13 100644 --- a/lib/openscap_parser/util.rb +++ b/lib/openscap_parser/util.rb @@ -1,10 +1,10 @@ # frozen_string_literal: true -# Utility functions for OpenscapParser module OpenscapParser + # Utility functions for OpenscapParser module Util def newline_to_whitespace(string) - string.gsub(/ *\n+/, " ").strip + string.gsub(/ *\n+/, ' ').strip end end end diff --git a/lib/openscap_parser/value.rb b/lib/openscap_parser/value.rb index eaabc08..7add444 100644 --- a/lib/openscap_parser/value.rb +++ b/lib/openscap_parser/value.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true + module OpenscapParser + # A class for parsing Value information class Value < XmlNode include OpenscapParser::Util @@ -23,11 +25,7 @@ def generic_selector(type, selector = nil) cache = instance_variable_get("@#{type}") unless cache - element_name = type.to_s.sub('_', '-') - - cache = parsed_xml.xpath(element_name).each_with_object({}) do |element, elements| - elements[element.at_xpath('@selector')&.text] = element&.text - end + cache = cache_for_element(type) instance_variable_set("@#{type}", cache) end @@ -48,14 +46,22 @@ def value(selector = nil) generic_selector(:value, selector) end + def cache_for_element(type) + element_name = type.to_s.sub('_', '-') + + parsed_xml.xpath(element_name).each_with_object({}) do |element, elements| + elements[element.at_xpath('@selector')&.text] = element&.text + end + end + def to_h { - :id => id, - :title => title, - :description => description, - :type => type, - :lower_bound => lower_bound, - :upper_bound => upper_bound + id:, + title:, + description:, + type:, + lower_bound:, + upper_bound: } end end diff --git a/lib/openscap_parser/values.rb b/lib/openscap_parser/values.rb index 21f42db..e6bb099 100644 --- a/lib/openscap_parser/values.rb +++ b/lib/openscap_parser/values.rb @@ -13,7 +13,7 @@ def values end end - def value_nodes(xpath = ".//Value") + def value_nodes(xpath = './/Value') xpath_nodes(xpath) end end diff --git a/lib/openscap_parser/version.rb b/lib/openscap_parser/version.rb index f838a34..bffdc06 100644 --- a/lib/openscap_parser/version.rb +++ b/lib/openscap_parser/version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module OpenscapParser - VERSION = "1.7.0" + VERSION = '1.7.0' end diff --git a/lib/openscap_parser/xml_file.rb b/lib/openscap_parser/xml_file.rb index b56b0cf..fcbd18c 100644 --- a/lib/openscap_parser/xml_file.rb +++ b/lib/openscap_parser/xml_file.rb @@ -4,8 +4,8 @@ require 'openscap_parser/xml_node' module OpenscapParser + # Represents methods used to initialize xml file class XmlFile < XmlNode - def initialize(raw_xml) parsed_xml(raw_xml) end diff --git a/lib/openscap_parser/xml_node.rb b/lib/openscap_parser/xml_node.rb index 553067c..c1d9fb3 100644 --- a/lib/openscap_parser/xml_node.rb +++ b/lib/openscap_parser/xml_node.rb @@ -13,8 +13,10 @@ def initialize(parsed_xml: nil) def parsed_xml(report_contents = '') return @parsed_xml if @parsed_xml + @parsed_xml = ::Nokogiri::XML.parse( - report_contents, nil, nil, Nokogiri::XML::ParseOptions.new.norecover) + report_contents, nil, nil, Nokogiri::XML::ParseOptions.new.norecover + ) @namespaces = @parsed_xml.namespaces.clone @parsed_xml.remove_namespaces! end @@ -24,13 +26,13 @@ def text end def xpath_node(xpath) - parsed_xml && parsed_xml.at_xpath(xpath) + parsed_xml&.at_xpath(xpath) end - alias :at_xpath :xpath_node + alias at_xpath xpath_node def xpath_nodes(xpath) - parsed_xml && parsed_xml.xpath(xpath) || [] + parsed_xml&.xpath(xpath) || [] end - alias :xpath :xpath_nodes + alias xpath xpath_nodes end end diff --git a/lib/oval/definition.rb b/lib/oval/definition.rb index a88724c..704c83a 100644 --- a/lib/oval/definition.rb +++ b/lib/oval/definition.rb @@ -1,7 +1,10 @@ -require "openscap_parser/xml_node" -require "oval/reference" +# frozen_string_literal: true + +require 'openscap_parser/xml_node' +require 'oval/reference' module Oval + # Methods related to finding and saving Oval Defintions class Definition < ::OpenscapParser::XmlNode def id @id ||= @parsed_xml['id'] @@ -16,17 +19,17 @@ def klass end def title - xml = @parsed_xml.at_xpath("./metadata/title") - @title ||= xml && xml.text + xml = @parsed_xml.at_xpath('./metadata/title') + @title ||= xml&.text end def description - xml = @parsed_xml.at_xpath("./metadata/description") - @description ||= xml && xml.text + xml = @parsed_xml.at_xpath('./metadata/description') + @description ||= xml&.text end def reference_nodes - @reference_nodes ||= @parsed_xml.xpath("./metadata/reference") + @reference_nodes ||= @parsed_xml.xpath('./metadata/reference') end def references @@ -35,12 +38,12 @@ def references def to_h { - :id => id, - :version => version, - :klass => klass, - :title => title, - :description => description, - :references => references.map(&:to_h) + id:, + version:, + klass:, + title:, + description:, + references: references.map(&:to_h) } end end diff --git a/lib/oval/definition_result.rb b/lib/oval/definition_result.rb index 4de8809..f3f2077 100644 --- a/lib/oval/definition_result.rb +++ b/lib/oval/definition_result.rb @@ -1,6 +1,9 @@ +# frozen_string_literal: true + require 'openscap_parser/xml_node' module Oval + # Methods related to finding and saving Oval Definition Results class DefinitionResult < ::OpenscapParser::XmlNode def definition_id @definition_id ||= @parsed_xml['definition_id'] @@ -11,7 +14,7 @@ def result end def to_h - { :id => definition_id, :result => result } + { id: definition_id, result: } end end end diff --git a/lib/oval/reference.rb b/lib/oval/reference.rb index 73c87fe..25d0be3 100644 --- a/lib/oval/reference.rb +++ b/lib/oval/reference.rb @@ -1,6 +1,9 @@ -require "openscap_parser/xml_node" +# frozen_string_literal: true + +require 'openscap_parser/xml_node' module Oval + # A class for parsing Oval Reference information class Reference < ::OpenscapParser::XmlNode def source @source ||= @parsed_xml['source'] @@ -15,7 +18,7 @@ def ref_url end def to_h - { :source => source, :ref_id => ref_id, :ref_url => ref_url } + { source:, ref_id:, ref_url: } end end end diff --git a/lib/railtie.rb b/lib/railtie.rb index 7c077e1..f988600 100644 --- a/lib/railtie.rb +++ b/lib/railtie.rb @@ -1,8 +1,11 @@ +# frozen_string_literal: true + # lib/railtie.rb require 'openscap_parser' if defined?(Rails) module OpenscapParser + # Methods related to RailTie class Railtie < Rails::Railtie railtie_name :openscap_parser diff --git a/lib/ssg.rb b/lib/ssg.rb index d1840a9..0abd728 100644 --- a/lib/ssg.rb +++ b/lib/ssg.rb @@ -1,5 +1,8 @@ +# frozen_string_literal: true + require 'ssg/downloader' require 'ssg/unarchiver' +# Methods related to Ssg module Ssg end diff --git a/lib/ssg/downloader.rb b/lib/ssg/downloader.rb index bd2e7d1..4eeea07 100644 --- a/lib/ssg/downloader.rb +++ b/lib/ssg/downloader.rb @@ -7,7 +7,7 @@ module Ssg # Downloads SCAP datastreams from the SCAP Security Guide # https://github.com/ComplianceAsCode/content class Downloader - RELEASES_API = 'https://api.github.com/repos'\ + RELEASES_API = 'https://api.github.com/repos' \ '/ComplianceAsCode/content/releases/' SSG_DS_REGEX = /scap-security-guide-(\d+\.)+zip$/ @@ -44,29 +44,29 @@ def download_urls end end - def fetch(request, &block) + def fetch(request, &) Net::HTTP.start( request.uri.host, request.uri.port, use_ssl: request.uri.scheme['https'] ) do |http| - check_response(http.request(request, &block), &block) + check_response(http.request(request, &), &) end end - def get(uri, &block) - fetch(Net::HTTP::Get.new(uri), &block) + def get(uri, &) + fetch(Net::HTTP::Get.new(uri), &) end - def head(uri, &block) - fetch(Net::HTTP::Head.new(uri), &block) + def head(uri, &) + fetch(Net::HTTP::Head.new(uri), &) end - def check_response(response, &block) + def check_response(response, &) case response when Net::HTTPSuccess response when Net::HTTPRedirection - get(URI(response['location']), &block) + get(URI(response['location']), &) else response.value end @@ -74,8 +74,9 @@ def check_response(response, &block) def get_chunked(uri, filename: datastream_filename) head(uri) do |response| - next unless Net::HTTPSuccess === response - open(filename, 'wb') do |file| + next unless response.is_a?(Net::HTTPSuccess) + + File.open(filename, 'wb') do |file| response.read_body do |chunk| file.write(chunk) end diff --git a/lib/ssg/unarchiver.rb b/lib/ssg/unarchiver.rb index 114a69e..9ce142a 100644 --- a/lib/ssg/unarchiver.rb +++ b/lib/ssg/unarchiver.rb @@ -1,6 +1,9 @@ +# frozen_string_literal: true + module Ssg + # Methods for unarchiving class Unarchiver - UNZIP_CMD = ['unzip', '-o'] + UNZIP_CMD = ['unzip', '-o'].freeze def initialize(ds_zip_filename, datastreams) @ds_zip_filename = ds_zip_filename diff --git a/lib/tasks/ssg.rake b/lib/tasks/ssg.rake index 3329cef..11257a7 100644 --- a/lib/tasks/ssg.rake +++ b/lib/tasks/ssg.rake @@ -1,33 +1,32 @@ +# frozen_string_literal: true + desc 'Import or update SCAP datastreams from the SCAP Security Guide' namespace :ssg do desc 'Import or update SCAP datastreams for RHEL 6, 7, and 8' - task :sync_rhel do |task| - RHEL_SSG_VERSIONS = ( - 'v0.1.28:rhel6,'\ - 'v0.1.43:rhel7,'\ + task :sync_rhel do |_task| + RHEL_SSG_VERSIONS = + 'v0.1.28:rhel6,' \ + 'v0.1.43:rhel7,' \ 'v0.1.42:rhel8' - ) ENV['DATASTREAMS'] = RHEL_SSG_VERSIONS Rake::Task['ssg:sync'].invoke end - desc 'Import or update SCAP datastreams, '\ - 'provided as a comma separated list: '\ + desc 'Import or update SCAP datastreams, ' \ + 'provided as a comma separated list: ' \ '`rake ssg:sync DATASTREAMS=v0.1.43:rhel7,latest:fedora`' - task :sync do |task| + task :sync do |_task| DATASTREAMS = ENV.fetch('DATASTREAMS', '').split(',') - .inject({}) do |datastreams, arg| + .each_with_object({}) do |arg, datastreams| version, datastream = arg.split(':') datastreams[version] = (datastreams[version] || []).push(datastream) - - datastreams end require 'ssg' ds_zip_filenames = Ssg::Downloader.download!(DATASTREAMS.keys) - DATASTREAM_FILENAMES = Ssg::Unarchiver. - unarchive!(ds_zip_filenames, DATASTREAMS) + DATASTREAM_FILENAMES = Ssg::Unarchiver + .unarchive!(ds_zip_filenames, DATASTREAMS) end end diff --git a/openscap_parser.gemspec b/openscap_parser.gemspec index 0957236..adec656 100644 --- a/openscap_parser.gemspec +++ b/openscap_parser.gemspec @@ -1,7 +1,8 @@ +# frozen_string_literal: true -lib = File.expand_path("../lib", __FILE__) +lib = File.expand_path('lib', __dir__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require "openscap_parser/version" +require 'openscap_parser/version' Gem::Specification.new do |spec| spec.name = 'openscap_parser' @@ -9,42 +10,45 @@ Gem::Specification.new do |spec| spec.authors = ['Daniel Lobato Garcia', 'Andrew Kofink'] spec.email = ['me@daniellobato.me', 'ajkofink@gmail.com'] - spec.summary = %q{Parse OpenSCAP content} - spec.description = %q{This gem is a Ruby interface into SCAP content. It can parse SCAP datastream files (i.e. ssg-rhel7-ds.xml), scan result files output by oscap eval, and tailoring files.} + spec.summary = 'Parse OpenSCAP content' + spec.description = 'This gem is a Ruby interface into SCAP content. It can parse SCAP datastream files + (i.e. ssg-rhel7-ds.xml), scan result files output by oscap eval, and tailoring files.' spec.homepage = 'https://github.com/OpenSCAP/openscap_parser' spec.license = 'MIT' # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host' # to allow pushing to a single host or delete this section to allow pushing to any host. - #if spec.respond_to?(:metadata) - # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'" + # if spec.respond_to?(:metadata) + # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'" - # spec.metadata["homepage_uri"] = spec.homepage - # spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here." - # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here." - #else + # spec.metadata["homepage_uri"] = spec.homepage + # spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here." + # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here." + # else # raise "RubyGems 2.0 or newer is required to protect against " \ # "public gem pushes." - #end + # end # Specify which files should be added to the gem when it is released. # The `git ls-files -z` loads the files in the RubyGem that have been added into git. - spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do + spec.files = Dir.chdir(File.expand_path(__dir__)) do `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } end - spec.bindir = "bin" + spec.bindir = 'bin' spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] + spec.require_paths = ['lib'] + spec.required_ruby_version = '>= 3.1' - spec.add_dependency "nokogiri", "~> 1.6" - spec.add_development_dependency "bundler" - spec.add_development_dependency "rake" - spec.add_development_dependency "minitest", "~> 5.0" - spec.add_development_dependency "mocha", "~> 1.0" - spec.add_development_dependency "shoulda-context" - spec.add_development_dependency "pry" - spec.add_development_dependency "pry-byebug" - spec.add_development_dependency "rubocop", "~> 1.53.1" - spec.add_development_dependency "simplecov" - spec.add_development_dependency "simplecov-cobertura" + spec.add_dependency 'nokogiri', '~> 1.6' + spec.add_development_dependency 'bundler' + spec.add_development_dependency 'minitest', '~> 5.0' + spec.add_development_dependency 'mocha', '~> 1.0' + spec.add_development_dependency 'pry' + spec.add_development_dependency 'pry-byebug' + spec.add_development_dependency 'rake' + spec.add_development_dependency 'rubocop', '~> 1.53.1' + spec.add_development_dependency 'shoulda-context' + spec.add_development_dependency 'simplecov' + spec.add_development_dependency 'simplecov-cobertura' + spec.metadata['rubygems_mfa_required'] = 'true' end diff --git a/test/datastream_file_test.rb b/test/datastream_file_test.rb index 51bacff..9bd98ff 100644 --- a/test/datastream_file_test.rb +++ b/test/datastream_file_test.rb @@ -7,19 +7,19 @@ class DatastreamFileTest < MiniTest::Test should 'be able to parse profiles' do parser = create_parser('ssg-rhel7-ds.xml') profile_ref_ids = [ - "xccdf_org.ssgproject.content_profile_standard", - "xccdf_org.ssgproject.content_profile_nist-800-171-cui", - "xccdf_org.ssgproject.content_profile_rht-ccp", - "xccdf_org.ssgproject.content_profile_C2S", - "xccdf_org.ssgproject.content_profile_cjis", - "xccdf_org.ssgproject.content_profile_hipaa", - "xccdf_org.ssgproject.content_profile_ospp", - "xccdf_org.ssgproject.content_profile_ospp42", - "xccdf_org.ssgproject.content_profile_pci-dss", - "xccdf_org.ssgproject.content_profile_stig-rhel7-disa", - "xccdf_org.ssgproject.content_profile_rhelh-vpp" + 'xccdf_org.ssgproject.content_profile_standard', + 'xccdf_org.ssgproject.content_profile_nist-800-171-cui', + 'xccdf_org.ssgproject.content_profile_rht-ccp', + 'xccdf_org.ssgproject.content_profile_C2S', + 'xccdf_org.ssgproject.content_profile_cjis', + 'xccdf_org.ssgproject.content_profile_hipaa', + 'xccdf_org.ssgproject.content_profile_ospp', + 'xccdf_org.ssgproject.content_profile_ospp42', + 'xccdf_org.ssgproject.content_profile_pci-dss', + 'xccdf_org.ssgproject.content_profile_stig-rhel7-disa', + 'xccdf_org.ssgproject.content_profile_rhelh-vpp' ] - assert_equal(profile_ref_ids, parser.benchmark.profiles.map { |profile| profile.id }) + assert_equal(profile_ref_ids, parser.benchmark.profiles.map(&:id)) end end diff --git a/test/openscap_parser/oval_report_test.rb b/test/openscap_parser/oval_report_test.rb index 80f84d1..fc59e40 100644 --- a/test/openscap_parser/oval_report_test.rb +++ b/test/openscap_parser/oval_report_test.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require 'test_helper' class OvalReportTest < Minitest::Test diff --git a/test/openscap_parser/profiles_test.rb b/test/openscap_parser/profiles_test.rb index f8f1b9c..efd855e 100644 --- a/test/openscap_parser/profiles_test.rb +++ b/test/openscap_parser/profiles_test.rb @@ -10,7 +10,7 @@ class ProfilesTest < Minitest::Test ) assert_equal 'xccdf_org.ssgproject.content_profile_standard', - test_result_file.test_result.profile_id + test_result_file.test_result.profile_id end test 'test result file ospp42 rhel' do @@ -19,7 +19,7 @@ class ProfilesTest < Minitest::Test ) assert_equal 'xccdf_org.ssgproject.content_profile_rht-ccp', - test_result_file.test_result.profile_id + test_result_file.test_result.profile_id end end end diff --git a/test/openscap_parser/test_result_file_test.rb b/test/openscap_parser/test_result_file_test.rb index 76d15a2..4e322f5 100644 --- a/test/openscap_parser/test_result_file_test.rb +++ b/test/openscap_parser/test_result_file_test.rb @@ -25,7 +25,7 @@ def setup test 'be able to parse it' do assert_equal 'xccdf_org.ssgproject.content_profile_standard', - @test_result_file.benchmark.profiles.first.id + @test_result_file.benchmark.profiles.first.id end context 'profiles' do @@ -36,18 +36,26 @@ def setup test 'profile_selected_rule_ids' do assert_equal(238, @test_result_file2.benchmark.profiles.first.selected_rule_ids.length) - refute_includes(@test_result_file2.benchmark.profiles.first.selected_rule_ids, "xccdf_org.ssgproject.rules_group_crypto") - refute_includes(@test_result_file2.benchmark.profiles.first.selected_rule_ids, "xccdf_org.ssgproject.content_group_rule_crypto") - refute_includes(@test_result_file2.benchmark.profiles.first.selected_rule_ids, "xccdf_org.ssgproject.contentrule_group_crypto") - refute_includes(@test_result_file2.benchmark.profiles.first.selected_rule_ids, "xccdf_org.ssgproject.content_group_rule_group_crypto") + refute_includes(@test_result_file2.benchmark.profiles.first.selected_rule_ids, + 'xccdf_org.ssgproject.rules_group_crypto') + refute_includes(@test_result_file2.benchmark.profiles.first.selected_rule_ids, + 'xccdf_org.ssgproject.content_group_rule_crypto') + refute_includes(@test_result_file2.benchmark.profiles.first.selected_rule_ids, + 'xccdf_org.ssgproject.contentrule_group_crypto') + refute_includes(@test_result_file2.benchmark.profiles.first.selected_rule_ids, + 'xccdf_org.ssgproject.content_group_rule_group_crypto') end test 'profile_unselected_group_ids' do assert_equal(186, @test_result_file.benchmark.profiles.first.unselected_group_ids.count) - assert_includes(@test_result_file.benchmark.profiles.first.unselected_group_ids, "xccdf_org.ssgproject.content_group_mcafee_security_software") - assert_includes(@test_result_file.benchmark.profiles.first.unselected_group_ids, "xccdf_org.ssgproject.content_group_mcafee_hbss_software") - assert_includes(@test_result_file.benchmark.profiles.first.unselected_group_ids, "xccdf_org.ssgproject.content_group_certified-vendor") - assert_includes(@test_result_file.benchmark.profiles.first.unselected_group_ids, "xccdf_org.ssgproject.content_group_restrictions") + assert_includes(@test_result_file.benchmark.profiles.first.unselected_group_ids, + 'xccdf_org.ssgproject.content_group_mcafee_security_software') + assert_includes(@test_result_file.benchmark.profiles.first.unselected_group_ids, + 'xccdf_org.ssgproject.content_group_mcafee_hbss_software') + assert_includes(@test_result_file.benchmark.profiles.first.unselected_group_ids, + 'xccdf_org.ssgproject.content_group_certified-vendor') + assert_includes(@test_result_file.benchmark.profiles.first.unselected_group_ids, + 'xccdf_org.ssgproject.content_group_restrictions') end test 'profile_selected_entity_ids' do @@ -55,48 +63,48 @@ def setup end test 'profile_refined_values' do - assert_equal({"xccdf_org.ssgproject.content_value_var_selinux_state"=>"enforcing", - "xccdf_org.ssgproject.content_value_var_selinux_policy_name"=>"targeted", - "xccdf_org.ssgproject.content_value_login_banner_text"=>"usgcb_default", - "xccdf_org.ssgproject.content_value_var_auditd_max_log_file"=>"6", - "xccdf_org.ssgproject.content_value_var_auditd_action_mail_acct"=>"root", - "xccdf_org.ssgproject.content_value_var_auditd_admin_space_left_action"=>"single", - "xccdf_org.ssgproject.content_value_var_sshd_set_keepalive"=>"0", - "xccdf_org.ssgproject.content_value_var_password_pam_minlen"=>"14", - "xccdf_org.ssgproject.content_value_var_accounts_passwords_pam_faillock_unlock_time"=>"900", - "xccdf_org.ssgproject.content_value_var_accounts_passwords_pam_faillock_deny"=>"5", - "xccdf_org.ssgproject.content_value_var_password_pam_unix_remember"=>"5", - "xccdf_org.ssgproject.content_value_var_accounts_maximum_age_login_defs"=>"90", - "xccdf_org.ssgproject.content_value_var_accounts_minimum_age_login_defs"=>"7", - "xccdf_org.ssgproject.content_value_var_accounts_password_warn_age_login_defs"=>"7", - "xccdf_org.ssgproject.content_value_var_account_disable_post_pw_expiration"=>"30"}, - @test_result_file2.benchmark.profiles.first.refined_values) + assert_equal({ 'xccdf_org.ssgproject.content_value_var_selinux_state' => 'enforcing', + 'xccdf_org.ssgproject.content_value_var_selinux_policy_name' => 'targeted', + 'xccdf_org.ssgproject.content_value_login_banner_text' => 'usgcb_default', + 'xccdf_org.ssgproject.content_value_var_auditd_max_log_file' => '6', + 'xccdf_org.ssgproject.content_value_var_auditd_action_mail_acct' => 'root', + 'xccdf_org.ssgproject.content_value_var_auditd_admin_space_left_action' => 'single', + 'xccdf_org.ssgproject.content_value_var_sshd_set_keepalive' => '0', + 'xccdf_org.ssgproject.content_value_var_password_pam_minlen' => '14', + 'xccdf_org.ssgproject.content_value_var_accounts_passwords_pam_faillock_unlock_time' => '900', + 'xccdf_org.ssgproject.content_value_var_accounts_passwords_pam_faillock_deny' => '5', + 'xccdf_org.ssgproject.content_value_var_password_pam_unix_remember' => '5', + 'xccdf_org.ssgproject.content_value_var_accounts_maximum_age_login_defs' => '90', + 'xccdf_org.ssgproject.content_value_var_accounts_minimum_age_login_defs' => '7', + 'xccdf_org.ssgproject.content_value_var_accounts_password_warn_age_login_defs' => '7', + 'xccdf_org.ssgproject.content_value_var_account_disable_post_pw_expiration' => '30' }, + @test_result_file2.benchmark.profiles.first.refined_values) end test 'profile_refined_rule_severity' do - profile = @test_result_file2.benchmark.profiles.find do |profile| - profile.id == 'xccdf_org.ssgproject.content_profile_stig_gui' - end - assert_equal({"xccdf_org.ssgproject.content_rule_sssd_ldap_start_tls"=>"medium", - "xccdf_org.ssgproject.content_rule_prefer_64bit_os2"=>"high"}, - profile.refined_rule_severity) + profile = @test_result_file2.benchmark.profiles.find do |p| + p.id == 'xccdf_org.ssgproject.content_profile_stig_gui' + end + assert_equal({ 'xccdf_org.ssgproject.content_rule_sssd_ldap_start_tls' => 'medium', + 'xccdf_org.ssgproject.content_rule_prefer_64bit_os2' => 'high' }, + profile.refined_rule_severity) end test 'profile_refined_rule_role' do - profile = @test_result_file2.benchmark.profiles.find do |profile| - profile.id == 'xccdf_org.ssgproject.content_profile_stig_gui' - end - assert_equal({"xccdf_org.ssgproject.content_rule_sssd_ldap_start_tls"=>"full", - "xccdf_org.ssgproject.content_rule_prefer_64bit_os2"=>"full"}, - profile.refined_rule_role) + profile = @test_result_file2.benchmark.profiles.find do |p| + p.id == 'xccdf_org.ssgproject.content_profile_stig_gui' + end + assert_equal({ 'xccdf_org.ssgproject.content_rule_sssd_ldap_start_tls' => 'full', + 'xccdf_org.ssgproject.content_rule_prefer_64bit_os2' => 'full' }, + profile.refined_rule_role) end test 'profile_refined_rule_weight' do - profile = @test_result_file2.benchmark.profiles.find do |profile| - profile.id == 'xccdf_org.ssgproject.content_profile_stig_gui' - end - assert_equal({"xccdf_org.ssgproject.content_rule_prefer_64bit_os2"=>"10"}, - profile.refined_rule_weight) + profile = @test_result_file2.benchmark.profiles.find do |p| + p.id == 'xccdf_org.ssgproject.content_profile_stig_gui' + end + assert_equal({ 'xccdf_org.ssgproject.content_rule_prefer_64bit_os2' => '10' }, + profile.refined_rule_weight) end end @@ -111,8 +119,8 @@ def setup end test 'group_with_conflicts' do - assert_equal(["xccdf_org.ssgproject.content_rule_selinux_state", - "xccdf_org.ssgproject.content_group_mcafee_security_software"], + assert_equal(['xccdf_org.ssgproject.content_rule_selinux_state', + 'xccdf_org.ssgproject.content_group_mcafee_security_software'], @test_result_file2.benchmark.groups[1].conflicts) end @@ -121,7 +129,7 @@ def setup end test 'group_with_requires' do - assert_equal(['A', 'B', 'C'], @test_result_file2.benchmark.groups.first.requires) + assert_equal(%w[A B C], @test_result_file2.benchmark.groups.first.requires) end test 'group_description' do @@ -167,18 +175,18 @@ def setup end test 'removes newlines from rule description' do - rule = @test_result_file.benchmark.rules.find do |rule| - rule.id == 'xccdf_org.ssgproject.content_rule_service_atd_disabled' + rule = @test_result_file.benchmark.rules.find do |r| + r.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 + 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 @@ -192,17 +200,17 @@ def setup assert_equal([], @test_result_file2.benchmark.rules[1].conflicts) end test 'rule_with_conflicts' do - assert_equal(["xccdf_org.ssgproject.content_group_system", - "xccdf_org.ssgproject.content_rule_selinux_state"], + assert_equal(['xccdf_org.ssgproject.content_group_system', + 'xccdf_org.ssgproject.content_rule_selinux_state'], @test_result_file2.benchmark.rules.first.conflicts) end test 'rule_no_requires' do assert_equal([], @test_result_file2.benchmark.rules.first.requires) end test 'rule_with_requires' do - assert_equal(["xccdf_org.ssgproject.content_rule_package_audit_installed", - "xccdf_org.ssgproject.content_group_integrity", - "xccdf_org.ssgproject.content_group_software-integrity"], + assert_equal(['xccdf_org.ssgproject.content_rule_package_audit_installed', + 'xccdf_org.ssgproject.content_group_integrity', + 'xccdf_org.ssgproject.content_group_software-integrity'], @test_result_file2.benchmark.rules[1].requires) end test 'rule_description' do @@ -227,8 +235,11 @@ def setup end test 'values' do - rule = @test_result_file2.benchmark.rules.select { |r| r.id == "xccdf_org.ssgproject.content_rule_accounts_password_pam_pwhistory_remember_password_auth" } - assert_equal(["xccdf_org.ssgproject.content_value_var_password_pam_remember_control_flag", "xccdf_org.ssgproject.content_value_var_password_pam_remember"], + rule = @test_result_file2.benchmark.rules.select do |r| + r.id == 'xccdf_org.ssgproject.content_rule_accounts_password_pam_pwhistory_remember_password_auth' + end + assert_equal(['xccdf_org.ssgproject.content_value_var_password_pam_remember_control_flag', + 'xccdf_org.ssgproject.content_value_var_password_pam_remember'], rule[0].values) assert_equal([], @test_result_file2.benchmark.rules[1].values) end @@ -236,14 +247,15 @@ def setup context 'values' do test 'value_description' do - assert_match(/^Specify the email address for designated personnel if baseline configurations are changed in an unauthorized manner./, + assert_equal('Specify the email address for designated personnel if ' \ + 'baseline configurations are changed in an unauthorized manner.', @test_result_file2.benchmark.values.first.description) end test 'type' do - assert_equal("string", @test_result_file2.benchmark.values[0].type) - assert_equal("string", @test_result_file2.benchmark.values[1].type) - assert_equal("number", @test_result_file2.benchmark.values[4].type) + assert_equal('string', @test_result_file2.benchmark.values[0].type) + assert_equal('string', @test_result_file2.benchmark.values[1].type) + assert_equal('number', @test_result_file2.benchmark.values[4].type) end test 'lower bound' do @@ -259,15 +271,15 @@ def setup end test 'value' do - assert_equal("51882M", @test_result_file2.benchmark.values[0].value) - assert_equal("512M", @test_result_file2.benchmark.values[1].value) - assert_equal("3h", @test_result_file2.benchmark.values[2].value) - assert_equal("DEFAULT", @test_result_file2.benchmark.values[3].value) - assert_equal("212M", @test_result_file2.benchmark.values[0].value('512M')) + assert_equal('51882M', @test_result_file2.benchmark.values[0].value) + assert_equal('512M', @test_result_file2.benchmark.values[1].value) + assert_equal('3h', @test_result_file2.benchmark.values[2].value) + assert_equal('DEFAULT', @test_result_file2.benchmark.values[3].value) + assert_equal('212M', @test_result_file2.benchmark.values[0].value('512M')) assert_equal('1G', @test_result_file2.benchmark.values[1].value('1G')) - assert_equal("1h", @test_result_file2.benchmark.values[2].value('1hour')) - assert_equal("3h", @test_result_file2.benchmark.values[2].value('3hour')) - assert_equal("DEFAULT2", @test_result_file2.benchmark.values[3].value('default_policy')) + assert_equal('1h', @test_result_file2.benchmark.values[2].value('1hour')) + assert_equal('3h', @test_result_file2.benchmark.values[2].value('3hour')) + assert_equal('DEFAULT2', @test_result_file2.benchmark.values[3].value('default_policy')) end end @@ -278,12 +290,12 @@ def setup end references = [ - ["http://iase.disa.mil/stigs/cci/Pages/index.aspx", "CCI-000381"], - ['http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.'\ - '800-53r4.pdf', "CM-7"] + ['http://iase.disa.mil/stigs/cci/Pages/index.aspx', 'CCI-000381'], + ['http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.' \ + '800-53r4.pdf', 'CM-7'] ] - assert_equal references, rule.references.map { |rr| [rr.href, rr.label] } + assert_equal(references, rule.references.map { |rr| [rr.href, rr.label] }) end end end @@ -291,7 +303,7 @@ def setup context 'test result' do test 'report_host' do assert_match @test_result_file.test_result.host, - 'lenovolobato.lobatolan.home' + 'lenovolobato.lobatolan.home' end test 'score can be parsed' do @@ -301,7 +313,7 @@ def setup context 'profiles' do test 'test_result profile_id' do assert_equal 'xccdf_org.ssgproject.content_profile_standard', - @test_result_file.test_result.profile_id + @test_result_file.test_result.profile_id end end @@ -335,24 +347,30 @@ def setup 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" } + rule = @arf_result_file.benchmark.rules.find do |r| + r.id == 'xccdf_org.ssgproject.content_rule_ensure_gpgcheck_globally_activated' + end fixes = rule.fixes assert_equal 2, fixes.count - assert fixes.map(&:id).all? { |id| id == 'ensure_gpgcheck_globally_activated' } + 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? } + test 'should parse one sub for fix' do + rule = @arf_result_file.benchmark.rules.find do |r| + r.id == 'xccdf_org.ssgproject.content_rule_ensure_gpgcheck_globally_activated' + end + fix = rule.fixes.find { |f| !f.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" } + test 'should parse attributes for fix' do + rule = @arf_result_file.benchmark.rules.find do |r| + r.id == 'xccdf_org.ssgproject.content_rule_enable_selinux_bootloader' + end + fix = rule.fixes.find { |fx| fx.system == 'urn:xccdf:fix:script:sh' } assert_empty fix.subs assert fix.text assert fix.complexity @@ -360,9 +378,11 @@ def setup 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? } + test 'should parse multiple subs for fix' do + rule = @arf_result_file.benchmark.rules.find do |r| + r.id == 'xccdf_org.ssgproject.content_rule_selinux_state' + end + fix = rule.fixes.find { |f| !f.subs.empty? } assert_equal 2, fix.subs.count sub = fix.subs.last assert sub.id @@ -370,21 +390,27 @@ def setup assert sub.use end - test "should resolve set-values for subs" do + test 'should resolve set-values for subs' do set_values = @arf_result_file.test_result.set_values - rule = @arf_result_file.benchmark.rules.find { |rule| rule.id == "xccdf_org.ssgproject.content_rule_selinux_state" } + rule = @arf_result_file.benchmark.rules.find do |r| + r.id == 'xccdf_org.ssgproject.content_rule_selinux_state' + end rule.fixes.first.map_child_nodes(set_values).all? { |node| node.is_a? Nokogiri::XML::Text } end - test "should parse full fix text lines" do + test 'should parse full fix text lines' do set_values = @arf_result_file.test_result.set_values - rule = @arf_result_file.benchmark.rules.find { |rule| rule.id == "xccdf_org.ssgproject.content_rule_selinux_state" } + rule = @arf_result_file.benchmark.rules.find do |r| + r.id == 'xccdf_org.ssgproject.content_rule_selinux_state' + end assert_equal 5, rule.fixes.first.full_text_lines(set_values).count end - test "should compose full fix" do + test 'should compose full fix' do set_values = @arf_result_file.test_result.set_values - rule = @arf_result_file.benchmark.rules.find { |rule| rule.id == "xccdf_org.ssgproject.content_rule_selinux_state" } + rule = @arf_result_file.benchmark.rules.find do |r| + r.id == 'xccdf_org.ssgproject.content_rule_selinux_state' + end assert_equal file_fixture('selinux_full_fix.sh').read, rule.fixes.first.full_text(set_values) end end @@ -404,7 +430,7 @@ def parse_fixes(result_file) def parse_set_values(result_file) set_values = result_file.test_result.set_values.map(&:to_h) idrefs = set_values.map { |val| val[:id] } - texts = set_values.map { | val| val[:text] } + texts = set_values.map { |val| val[:text] } refute_empty set_values assert_equal idrefs, idrefs.compact assert_equal texts, texts.compact @@ -415,6 +441,10 @@ def parse_rules(result_file) ids = rules.map { |rule| rule[:id] } titles = rules.map { |rule| rule[:title] } selected = rules.map { |rule| rule[:selected] } + test_parsed_rule_info(rules, ids, titles, selected) + end + + def test_parsed_rule_info(rules, ids, titles, selected) refute_empty rules assert_equal ids, ids.compact assert_equal titles, titles.compact diff --git a/test/openscap_parser/xml_file_test.rb b/test/openscap_parser/xml_file_test.rb index 2880743..ac00bb9 100644 --- a/test/openscap_parser/xml_file_test.rb +++ b/test/openscap_parser/xml_file_test.rb @@ -10,7 +10,7 @@ def setup test 'parsed_xml parses a valid XML report' do assert_equal OpenscapParser::XmlFile.new(@valid_report).parsed_xml.class, - Nokogiri::XML::Document + Nokogiri::XML::Document end test 'parsed_xml handles an invalid XML report' do diff --git a/test/ssg/downloader_test.rb b/test/ssg/downloader_test.rb index 75ad7ea..57bef1e 100644 --- a/test/ssg/downloader_test.rb +++ b/test/ssg/downloader_test.rb @@ -10,8 +10,8 @@ class DownloaderTest < MiniTest::Test FILE = 'scap-security-guide-0.0.0.zip' uri = URI("https://example.com/#{FILE}") downloader = Downloader.new - downloader.expects(:datastream_uri). - at_least_once.returns(uri) + downloader.expects(:datastream_uri) + .at_least_once.returns(uri) downloader.expects(:get_chunked).with uri assert_equal FILE, downloader.fetch_datastream_file diff --git a/test/ssg/unarchiver_test.rb b/test/ssg/unarchiver_test.rb index 21018c7..8d28345 100644 --- a/test/ssg/unarchiver_test.rb +++ b/test/ssg/unarchiver_test.rb @@ -8,17 +8,17 @@ class UnarchiverTest < MiniTest::Test context 'datastream_files' do test 'properly shells out to unzip' do ZIP_FILE = 'scap-security-guide-0.0.0.zip' - DATASTREAMS = ['rhel6'] - FILES = [] + DATASTREAMS = ['rhel6'].freeze + FILES = [].freeze unarchiver = Unarchiver.new(ZIP_FILE, DATASTREAMS) unarchiver.expects(:system).with( - "unzip", "-o", - "scap-security-guide-0.0.0.zip", - "scap-security-guide-0.0.0/ssg-rhel6-ds.xml" + 'unzip', '-o', + 'scap-security-guide-0.0.0.zip', + 'scap-security-guide-0.0.0/ssg-rhel6-ds.xml' ).returns(true) assert_equal ['scap-security-guide-0.0.0/ssg-rhel6-ds.xml'], - unarchiver.datastream_files + unarchiver.datastream_files end end end diff --git a/test/test_helper.rb b/test/test_helper.rb index f06d7b1..5d0170c 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,23 +1,26 @@ -$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__) -require "openscap_parser" +# frozen_string_literal: true + +$LOAD_PATH.unshift File.expand_path('../lib', __dir__) +require 'openscap_parser' require 'pathname' -require "minitest/autorun" +require 'minitest/autorun' require 'shoulda-context' require 'mocha/minitest' -require "simplecov" +require 'simplecov' SimpleCov.start require 'simplecov-cobertura' SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter -def test(name, &block) +def test(name, &) test_name = "test_#{name.gsub(/\s+/, '_')}".to_sym defined = method_defined? test_name raise "#{test_name} is already defined in #{self}" if defined + if block_given? - define_method(test_name, &block) + define_method(test_name, &) else define_method(test_name) do flunk "No implementation provided for #{name}" @@ -33,6 +36,6 @@ def file_fixture(fixture_name) path else msg = "the directory '%s' does not contain a file named '%s'" - raise ArgumentError, msg % [file_fixture_path, fixture_name] + raise ArgumentError, format(msg, file_fixture_path, fixture_name) end end