class NipperParser::SecurityAudit

SecurityAudit parses the 'Security Audit' part including all it's sections.

Security Audit part contains the following sections:
  - introduction
  - findings
  - Conclusions
  - Recommendations
  - Mitigation Classification

@example Basic Usage

require 'nokogiri'
require 'pp'
config = Nokogiri::XML open(ARGV[0])
security_audit = NipperParser::SecurityAudit.new(config)
pp security_audit.introduction.class
pp security_audit.introduction.index
pp security_audit.introduction.title
pp security_audit.introduction.devices

@example Dealing with findings

finding = security_audit.findings[0]
pp finding.class
pp finding.index
pp finding.title
pp finding.ref
pp finding.affected_devices
pp finding.finding
pp finding.impact
pp finding.recommendation

@example Dealing with report summaries

pp security_audit.conclusions.class
pp security_audit.conclusions.per_device
pp security_audit.conclusions.list_critical
pp security_audit.recommendations.class
pp security_audit.recommendations.list
pp security_audit.mitigation_classification.class
pp security_audit.mitigation_classification.list_by.fixing[:involved]
pp security_audit.mitigation_classification.list_by.fixing[:involved][0].rating[:rating]
pp security_audit.mitigation_classification.list_by.rating[:high]
pp security_audit.mitigation_classification.list_by.rating[:high][0].rating[:fix]
pp security_audit.mitigation_classification.statistics.class
pp security_audit.mitigation_classification.statistics.critical
pp security_audit.mitigation_classification.statistics.quick
pp security_audit.mitigation_classification.statistics.report

@param config [Nokogiri::XML] parsed XML @attr_reader title the report title @attr_reader config a parsed XML [Nokogiri::XML] object

Constants

Conclusion
Finding
Introduction

Skeleton for SecurityAudit parts

ListBy
MitigationClassification
Recommendations
Statistics

Attributes

config[R]
title[R]

Public Class Methods

new(config) click to toggle source

@param config [Nokogiri::XML::Document]

# File lib/nipper_parser/parsers/security_audit.rb, line 102
def initialize(config)
  part    = config.xpath("//report/part[@ref='SECURITYAUDIT']")
  @config = part[0].elements
  @title  = part[0].attributes['title'].text

  introduction
  findings
end

Public Instance Methods

conclusions() click to toggle source

Conclusions

# File lib/nipper_parser/parsers/security_audit.rb, line 155
def conclusions
  conc = @config.search("section[@ref='SECURITY.CONCLUSIONS']")[0]
  index     = attributes(conc).index
  title     = attributes(conc).title
  reference = attributes(conc).ref
  per_device = generate_table(conc.elements[1].elements)
  per_rating = {
      critical: conc.elements[3].elements.map(&:text),
      high:     conc.elements[5].elements.map(&:text),
      medium:   conc.elements[7].elements.map(&:text),
      low:      conc.elements[9].elements.map(&:text),
      info:     conc.elements[11].elements.map(&:text)
  }

  Conclusion.new(
      index, title, reference, per_device, per_rating,
      per_rating[:critical], per_rating[:high],
      per_rating[:medium], per_rating[:low], per_rating[:info],
  )
end
findings() click to toggle source

Parse findings from given configurations @return [Array<Finding>]

# File lib/nipper_parser/parsers/security_audit.rb, line 134
def findings
  findings = @config.to_a.clone
  findings.shift  # pop first item, the introduction
  findings.pop(3) # pop last 3 item, conclusion, recommendations, Mitigation Classification

  @findings = findings.map do |finding|
    Finding.new(
        attributes(finding).index,
        attributes(finding).title,
        attributes(finding).ref,
        finding.elements[0]&.elements[0].elements.map(&:attributes),            # affected_devices
        rating_table(finding.elements[0].elements[1].elements),                 # Rating table
        finding.elements[2]&.elements&.first(2).map(&:text).join("\n"),         # finding
        finding.elements[3]&.elements&.text,                                    # impact
        finding.elements[4]&.elements&.text,                                    # ease
        finding.elements[5]&.elements&.text                                     # recommendation
    )
  end
end
introduction() click to toggle source

Introduction of the Security Audit report

# File lib/nipper_parser/parsers/security_audit.rb, line 112
def introduction
  intro = @config[0]
  attribute = attributes(intro)
  index     = attribute.index
  title     = attribute.title
  reference = attribute.ref
  date      = Date.parse(intro.elements[0].text).to_s
  devices   = generate_table(intro.elements[1].elements)
  security_issue_overview = {}
  intro.elements[2].elements[1..4].map do |issue|
    security_issue_overview[issue['title']] = issue.text
  end
  rating    = generate_table(intro.elements[3].elements[2].elements[1].elements)

  Introduction.new(
      index, title, reference, date, devices,
      security_issue_overview, rating
  )
end
mitigation_classification() click to toggle source
# File lib/nipper_parser/parsers/security_audit.rb, line 190
def mitigation_classification
  @mitigation = @config.search("section[@ref='SECURITY.MITIGATIONS']")[0]  # @config[-1]

  index     = attributes(@mitigation).index
  title     = attributes(@mitigation).title
  reference = attributes(@mitigation).ref
  MitigationClassification.new(
      index, title, reference,
      list_by,
      statistics
  )

end
recommendations() click to toggle source

Recommendations

# File lib/nipper_parser/parsers/security_audit.rb, line 177
def recommendations
  recom = @config.search("section[@ref='SECURITY.RECOMMENDATIONS']")[0]
  index     = attributes(recom).index
  title     = attributes(recom).title
  reference = attributes(recom).ref
  list      = generate_table(recom.elements[1].elements)

  Recommendations.new(
      index, title, reference,
      list
  )
end

Private Instance Methods

by_fixing() click to toggle source

finding_objects maps finding listitems text with the findings object

# File lib/nipper_parser/parsers/security_audit.rb, line 233
def by_fixing
  findings = @findings.dup
  @fixing_lists.map do |_class|
    _class.search('listitem').map do |item|
      # if 'finding' reference = item mentioned index (extracted from text 'See section' ),
      # then return the finding object
      findings.select{|finding| finding.index == item.text.match(/\d+\.\d+/).to_s.to_f}[0]
    end
  end
end
by_rating() click to toggle source

search in all finding by rating

# File lib/nipper_parser/parsers/security_audit.rb, line 245
def by_rating
  findings = @findings.dup
  rating = {critical: nil, high: nil, medium: nil, low: nil, informational: nil}
  rating.keys.each do |rate|
    rating[rate] = findings.select {|finding| finding.rating[:rating].downcase == rate.to_s}
  end

  rating
end
list_by() click to toggle source

list_by list different type of mitigation, by fixing type, and by rating type.

@example:

list_by.fixing              # @return [Hash]
list_by.fixing[:quick]      # @return [Array<Findings>]
list_by.rating              # @return [Hash]
list_by.rating[:critical]   # @return [Array<Findings>]
list_by.all                 # @return [Hash]

@return [ListBy]

# File lib/nipper_parser/parsers/security_audit.rb, line 215
def list_by
  @fixing_lists = @mitigation.search('list')
  _by_fixing  = by_fixing   # @see by_fixing
  _by_rating  = by_rating   # @see by_rating
  fixing      = {quick: _by_fixing[0], planned: _by_fixing[1], involved: _by_fixing[2]}
  rating      = {critical: _by_rating[:critical], high: _by_rating[:high],
                 medium: _by_rating[:medium], low: _by_rating[:low],
                 informational: _by_rating[:informational]}
  _by_all     = {fixing: fixing, rating: rating}

  ListBy.new(
    _by_all[:fixing],
    _by_all[:rating],
    _by_all
  )
end
statistics() click to toggle source

mitigation statistics regarding to number of:

- findings
- findings by rating
- findings by fixing

@return [Statistics]

# File lib/nipper_parser/parsers/security_audit.rb, line 260
def statistics
  findings = @findings.size
  ratings = {critical: nil, high: nil, medium: nil, low: nil, informational: nil}
  ratings.keys.each do |rating|
    ratings[rating] = {total: list_by.rating[rating].size,
                       perce: ( (list_by.rating[rating].size/@findings.size.to_f) * 100.0 ).round(2)}
  end
  fixing = {quick: nil, involved: nil, planned: nil}
  fixing.keys.each do |fix|
    fixing[fix] = {total: list_by.fixing[fix].size,
                   perce: ( (list_by.fixing[fix].size/@findings.size.to_f) * 100.0 ).round(2)}
  end
  report   = {ratings: ratings, fixing: fixing}
  Statistics.new(
      findings,
      ratings[:critical],
      ratings[:high],
      ratings[:medium],
      ratings[:low],
      ratings[:informational],
      fixing[:quick],
      fixing[:involved],
      fixing[:planned],
      report
  )
end