app/models/openscap_result.rb
class OpenscapResult < ApplicationRecord
belongs_to :container_image
belongs_to :resource, :polymorphic => true
has_one :binary_blob, :dependent => :destroy, :autosave => true, :as => :resource, :required => true
has_many :openscap_rule_results, :dependent => :destroy, :autosave => true
before_save :create_rule_results
def self.openscap_available?
# needed only for CI
require 'openscap'
require 'openscap/ds/arf'
require 'openscap/xccdf/benchmark'
true
rescue LoadError
false
end
def attach_raw_result(openscap_arf)
self.binary_blob = BinaryBlob.new(:name => 'openscap_compliance_arf', :data_type => 'XML')
binary_blob.binary = openscap_arf
end
def html
with_openscap_arf(binary_blob.binary) do |arf|
ascii8bit_to_utf8(arf.html)
end
end
private
def create_rule_results
with_openscap_objects(binary_blob.binary) do |rule_results, benchmark_items|
create_results(rule_results, benchmark_items)
end
end
def create_results(rule_results, benchmark_items)
openscap_rule_results.delete_all
rule_results.each do |openscap_id, result|
idents = []
benchmark_items[openscap_id].idents.each do |ident|
idents << ident.id
end
openscap_rule_results << OpenscapRuleResult.new(
:name => ascii8bit_to_utf8(openscap_id),
:result => ascii8bit_to_utf8(result.result),
:openscap_result => self,
:severity => ascii8bit_to_utf8(benchmark_items[openscap_id].severity),
:title => ascii8bit_to_utf8(benchmark_items[openscap_id].title),
:cves => idents.join(",")
)
end
end
def ascii8bit_to_utf8(string)
string.to_s.encode('utf-8', :invalid => :replace, :undef => :replace, :replace => '_')
end
def with_openscap_arf(raw)
return unless self.class.openscap_available?
begin
OpenSCAP.oscap_init
# ARF - nist standardized 'Asset Reporting Format' Full representation if a scap scan result.
arf = OpenSCAP::DS::Arf.new(:content => raw, :length => raw.length, :path => 'incoming_arf.xml')
yield arf
ensure
OpenSCAP.oscap_cleanup
arf.try(:destroy)
end
end
def with_openscap_objects(raw)
raise "no block given" unless block_given?
with_openscap_arf(raw) do |arf|
begin
test_results = arf.test_result
source_datastream = arf.report_request
bench_source = source_datastream.select_checklist!
benchmark = OpenSCAP::Xccdf::Benchmark.new(bench_source)
yield(test_results.rr, benchmark.items)
ensure
[benchmark, source_datastream, test_results].each { |obj| obj.try(:destroy) }
end
end
end
end