module ForemanOpenscap module HostExtensions extend ActiveSupport::Concern ::Host::Managed::Jail.allow :policies_enc included do has_one :asset, :as => :assetable, :class_name => "::ForemanOpenscap::Asset" has_many :asset_policies, :through => :asset, :class_name => "::ForemanOpenscap::AssetPolicy" has_many :policies, :through => :asset_policies, :class_name => "::ForemanOpenscap::Policy" has_many :arf_reports, :class_name => '::ForemanOpenscap::ArfReport', :foreign_key => :host_id has_one :compliance_status_object, :class_name => '::ForemanOpenscap::ComplianceStatus', :foreign_key => 'host_id' scoped_search :in => :policies, :on => :name, :complete_value => true, :rename => :compliance_policy, :only_explicit => true, :operators => ['= ', '!= '], :ext_method => :search_by_policy_name scoped_search :in => :policies, :on => :name, :complete_value => true, :rename => :compliance_report_missing_for, :only_explicit => true, :operators => ['= ', '!= '], :ext_method => :search_by_missing_arf scoped_search :in => :compliance_status_object, :on => :status, :rename => :compliance_status, :complete_value => {:compliant => ::ForemanOpenscap::ComplianceStatus::COMPLIANT, :incompliant => ::ForemanOpenscap::ComplianceStatus::INCOMPLIANT, :inconclusive => ::ForemanOpenscap::ComplianceStatus::INCONCLUSIVE} after_save :puppetrun!, :if => :openscap_proxy_id_changed? scope :comply_with, lambda { |policy| joins(:arf_reports).merge(ArfReport.latest_of_policy policy).merge(ArfReport.passed) } scope :incomply_with, lambda { |policy| joins(:arf_reports).merge(ArfReport.latest_of_policy policy).merge(ArfReport.failed) } scope :inconclusive_with, lambda { |policy| joins(:arf_reports).merge(ArfReport.latest_of_policy policy).merge(ArfReport.othered) } scope :policy_reports_missing, lambda { |policy| where("id NOT IN (SELECT host_id FROM reports INNER JOIN foreman_openscap_policy_arf_reports ON reports.id = foreman_openscap_policy_arf_reports.arf_report_id WHERE policy_id = #{policy.id}) AND id IN (SELECT assetable_id FROM foreman_openscap_asset_policies INNER JOIN foreman_openscap_assets ON foreman_openscap_asset_policies.asset_id = foreman_openscap_assets.id WHERE foreman_openscap_assets.assetable_type = 'Host::Base' AND foreman_openscap_asset_policies.policy_id = '#{policy.id}')") } alias_method_chain :set_hostgroup_defaults, :openscap end def set_hostgroup_defaults_with_openscap set_hostgroup_defaults_without_openscap return unless hostgroup assign_hostgroup_attributes %w(openscap_proxy_id) end def policies=(policies) self.create_asset(:assetable => self) if self.asset.blank? self.asset.policies = policies end def get_asset ForemanOpenscap::Asset.where(:assetable_type => 'Host::Base', :assetable_id => id).first_or_create! end def policies_enc combined_policies.map(&:to_enc).to_json end def combined_policies combined = self.hostgroup ? self.policies + self.hostgroup.policies : self.policies combined.uniq end def scap_status_changed?(policy) last_reports = reports_for_policy(policy, 2) return false if last_reports.length != 2 !last_reports.first.equal? last_reports.last end def last_report_for_policy(policy) reports_for_policy(policy, 1) end def reports_for_policy(policy, limit = nil) if limit ForemanOpenscap::ArfReport.joins(:policy_arf_report) .merge(ForemanOpenscap::PolicyArfReport.of_policy policy.id).where(:host_id => id).limit limit else ForemanOpenscap::ArfReport.joins(:policy_arf_report) .merge(ForemanOpenscap::PolicyArfReport.of_policy policy.id).where(:host_id => id) end end def compliance_status(options = {}) @compliance_status ||= get_status(ForemanOpenscap::ComplianceStatus).to_status(options) end def compliance_status_label(options = {}) @compliance_status_label ||= get_status(ForemanOpenscap::ComplianceStatus).to_label(options) end module ClassMethods def search_by_policy_name(key, operator, policy_name) cond = sanitize_sql_for_conditions(["foreman_openscap_policies.name #{operator} ?", value_to_sql(operator, policy_name)]) { :conditions => Host::Managed.arel_table[:id].in( Host::Managed.select(Host::Managed.arel_table[:id]).joins(:policies).where(cond).ast ).to_sql } end def search_by_missing_arf(key, operator, policy_name) cond = sanitize_sql_for_conditions(["foreman_openscap_policies.name #{operator} ?", value_to_sql(operator, policy_name)]) { :conditions => Host::Managed.arel_table[:id].in( Host::Managed.select(Host::Managed.arel_table[:id]) .joins(:policies) .where(cond) .where("foreman_openscap_assets.id NOT IN ( SELECT DISTINCT foreman_openscap_arf_reports.asset_id FROM foreman_openscap_arf_reports WHERE foreman_openscap_arf_reports.asset_id = foreman_openscap_assets.id AND foreman_openscap_arf_reports.policy_id = foreman_openscap_policies.id) ").ast).to_sql } end end end end