require 'digest/sha2' require 'openscap/ds/sds' require 'openscap/source' require 'openscap/xccdf/benchmark' require 'scaptimony/engine' module Scaptimony class DataStreamValidator < ActiveModel::Validator def validate(scap_content) return unless scap_content.scap_file_changed? allowed_type = 'SCAP Source Datastream' if scap_content.source.try(:type) != allowed_type scap_content.errors[:base] << _("Uploaded file is not #{allowed_type}.") return false end begin scap_content.source.validate! rescue OpenSCAP::OpenSCAPError => e scap_content.errors[:base] << e.message end unless (scap_content.scap_content_profiles.map(&:profile_id) - scap_content.benchmark_profiles.profiles.keys).empty? scap_content.errors[:base] << _('Changed file does not include existing SCAP Content profiles.') return false end end end class ScapContent < ActiveRecord::Base attr_accessible :original_filename, :scap_file, :title has_many :scap_content_profiles, :dependent => :destroy has_many :policies before_destroy EnsureNotUsedBy.new(:policies) validates_with Scaptimony::DataStreamValidator validates :title, :presence => true validates :digest, :presence => true validates :scap_file, :presence => true after_save :create_profiles scoped_search :on => :title, :complete_value => true scoped_search :on => :original_filename, :complete_value => true, :rename => :filename def to_label title end def source @source ||= source_init end def digest self[:digest] ||= Digest::SHA256.hexdigest "#{scap_file}" end # returns OpenSCAP::Xccdf::Benchmark with profiles. def benchmark_profiles sds = ::OpenSCAP::DS::Sds.new(source) bench_source = sds.select_checklist! benchmark = ::OpenSCAP::Xccdf::Benchmark.new(bench_source) sds.destroy benchmark end private def source_init OpenSCAP.oscap_init OpenSCAP::Source.new(:content => scap_file) end def create_profiles bench = benchmark_profiles bench.profiles.each { |key, profile| scap_content_profiles.find_or_create_by_profile_id_and_title(key, profile.title) } bench.destroy end end end