Skip to content

Commit

Permalink
Fixes #31685 - Add treshold for ds policies
Browse files Browse the repository at this point in the history
  • Loading branch information
Ondrej Prazak committed Nov 26, 2021
1 parent c861502 commit 9fe38de
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module Foreman::Controller::Parameters::PolicyApi

class_methods do
def filter_params_list
[:description, :name, :period, :scap_content_id, :scap_content_profile_id, :deploy_by,
[:description, :name, :treshold, :period, :scap_content_id, :scap_content_profile_id, :deploy_by,
:weekday, :day_of_month, :cron_line, :tailoring_file_id, :tailoring_file_profile_id,
:location_ids => [], :organization_ids => [], :hostgroup_ids => [], :host_ids => []]
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ def search_by_not_comply_with(_key, _operator, policy_name)
search_by_policy_results policy_name, &:failed
end

def search_by_inconclusive_with(_key, _operator, policy_name)
search_by_policy_results policy_name, &:othered
end

def search_by_policy_results(policy_name, &selection)
scope = ArfReport.of_policy(Policy.find_by(:name => policy_name).id)
.instance_eval(&selection)
Expand Down Expand Up @@ -67,8 +63,6 @@ def search_by_compliance_status(key, operator, value)
ArfReport.passed
when 'incompliant'
ArfReport.failed
when 'inconclusive'
ArfReport.othered
end
query_conditions_from_scope scope
end
Expand Down Expand Up @@ -131,9 +125,6 @@ def apply_condition(scope, negate, conditions)
scoped_search :relation => :policy, :on => :name, :complete_value => true, :rename => :not_comply_with,
:only_explicit => true, :operators => ['= '], :ext_method => :search_by_not_comply_with

scoped_search :relation => :policy, :on => :name, :complete_value => true, :rename => :inconclusive_with,
:only_explicit => true, :operators => ['= '], :ext_method => :search_by_inconclusive_with

scoped_search :relation => :openscap_proxy, :on => :name, :complete_value => true, :only_explicit => true, :rename => :openscap_proxy

scoped_search :relation => :sources, :on => :value, :rename => :xccdf_rule_name,
Expand All @@ -151,9 +142,8 @@ def apply_condition(scope, negate, conditions)
scoped_search :on => :status, :rename => :compliance_status, :operators => ['= '],
:ext_method => :search_by_compliance_status,
:complete_value => { :compliant => ::ForemanOpenscap::ComplianceStatus::COMPLIANT,
:incompliant => ::ForemanOpenscap::ComplianceStatus::INCOMPLIANT,
:inconclusive => ::ForemanOpenscap::ComplianceStatus::INCONCLUSIVE },
:validator => ->(value) { ['compliant', 'incompliant', 'inconclusive'].reduce(false) { |memo, item| memo || (item == value) } }
:incompliant => ::ForemanOpenscap::ComplianceStatus::INCOMPLIANT },
:validator => ->(value) { ['compliant', 'incompliant'].reduce(false) { |memo, item| memo || (item == value) } }
end
end
end
25 changes: 7 additions & 18 deletions app/models/foreman_openscap/arf_report.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,9 @@ class ArfReport < ::Report
ON reports.id = latest.id")
}

scope :failed, lambda { where("(#{report_status_column} >> #{bit_mask 'failed'}) > 0") }
scope :not_failed, lambda { where("(#{report_status_column} >> #{bit_mask 'failed'}) = 0") }

scope :othered, lambda { where("(#{report_status_column} >> #{bit_mask 'othered'}) > 0").merge(not_failed) }
scope :not_othered, lambda { where("(#{report_status_column} >> #{bit_mask 'othered'}) = 0") }

scope :passed, lambda { where("(#{report_status_column} >> #{bit_mask 'passed'}) > 0").merge(not_failed).merge(not_othered) }
scope :with_score, lambda { where.not(:score => nil) }
scope :passed, lambda { with_score.includes(:policy).where('foreman_openscap_policies.treshold <= reports.score') }
scope :failed, lambda { where.not(:id => ArfReport.passed.pluck(:id)) }

scope :by_rule_result, lambda { |rule_name, rule_result| joins(:sources).where(:sources => { :value => rule_name }, :logs => { :result => rule_result }) }

Expand Down Expand Up @@ -93,11 +89,7 @@ def passed
end

def failed
status_of "failed"
end

def othered
status_of "othered"
status_of("failed") + status_of("othered")
end

def rules_count
Expand All @@ -114,6 +106,7 @@ def self.create_arf(asset, proxy, params)
:reported_at => Time.at(params[:date].to_i),
:status => params[:metrics],
:metrics => params[:metrics],
:score => params[:score],
:openscap_proxy => proxy)
return arf_report unless arf_report.persisted?
PolicyArfReport.where(:arf_report_id => arf_report.id, :policy_id => policy.id, :digest => params[:digest]).first_or_create!
Expand Down Expand Up @@ -162,15 +155,11 @@ def assign_locations_organizations
end

def failed?
failed > 0
!passed?
end

def passed?
passed > 0 && failed == 0 && othered == 0
end

def othered?
!passed? && !failed?
score && score >= policy.treshold
end

def to_html
Expand Down
1 change: 0 additions & 1 deletion app/models/foreman_openscap/compliance_status.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ def relevant?(options = {})
def to_status(options = {})
latest_reports = host.policies.map { |p| host.last_report_for_policy p }.flatten
return INCOMPLIANT if latest_reports.any?(&:failed?)
return INCONCLUSIVE if latest_reports.any?(&:othered?)
COMPLIANT
end
end
Expand Down
27 changes: 26 additions & 1 deletion app/models/foreman_openscap/policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ def self.deploy_by_variants

validates :name, :presence => true, :uniqueness => true, :length => { :maximum => 255 },
:if => Proc.new { |policy| policy.should_validate?('Policy Attributes') }
validates :treshold, :presence => true, :if => Proc.new { |policy| policy.should_validate?('Policy Attributes') }

validates :period, :inclusion => { :in => %w[weekly monthly custom], :message => _('is not a valid value') },
:if => Proc.new { |policy| policy.should_validate?('Schedule') }
validates :deploy_by, :inclusion => { :in => Policy.deploy_by_variants },
Expand All @@ -39,9 +41,10 @@ def self.deploy_by_variants
validates :scap_content_id, presence: true, if: Proc.new { |policy| policy.should_validate?('SCAP Content') }
validate :matching_content_profile, if: Proc.new { |policy| policy.should_validate?('SCAP Content') }

validate :valid_tailoring, :valid_tailoring_profile, :no_mixed_deployments
validate :valid_tailoring, :valid_tailoring_profile, :no_mixed_deployments, :treshold_value
validate :valid_cron_line, :valid_weekday, :valid_day_of_month, :if => Proc.new { |policy| policy.should_validate?('Schedule') }
after_save :assign_policy_to_hostgroups
after_save :refresh_compliance_status
# before_destroy - ensure that the policy has no hostgroups, or classes

default_scope do
Expand Down Expand Up @@ -107,6 +110,17 @@ def hosts=(hosts)
host_ids = hosts.map(&:id).map(&:to_s)
end

def all_hosts
hg_ids = hostgroups.flat_map(&:subtree_ids).uniq
(Host.where(:hostgroup_id => hg_ids) + hosts).uniq
end

def refresh_host_statuses
all_hosts.map do |host|
host.refresh_statuses([HostStatus.find_status_by_humanized_name("compliance")])
end
end

def step_to_i(step_name)
steps.index(step_name) + 1
end
Expand Down Expand Up @@ -272,5 +286,16 @@ def no_mixed_deployments
end
end
end

def treshold_value
if (100 < treshold || treshold < 0) && should_validate?('Policy Attributes')
errors.add(:treshold, _("must be between 0 and 100"))
end
end

def refresh_compliance_status
return if id_previously_changed?
refresh_host_statuses
end
end
end
1 change: 1 addition & 0 deletions app/views/policies/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<div class="tab-pane" id="primary">
<%= text_f(f, :name) %>
<%= textarea_f(f, :description, :rows => :auto ) %>
<%= counter_f(f, :treshold) %>
</div>
<div class="tab-pane" id="scap_content">
<%= scap_content_selector(f) %>
Expand Down
1 change: 1 addition & 0 deletions app/views/policies/steps/_policy_attributes_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
<%= wizard_header @policy.step_index, *translate_steps(@policy) %>
<%= text_f(f, :name) %>
<%= text_f(f, :description, :size => "col-md-8" ) %>
<%= counter_f(f, :treshold) %>
</div>
6 changes: 6 additions & 0 deletions db/migrate/20210126144230_add_treshold_to_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class AddTresholdToPolicy < ActiveRecord::Migration[6.0]
def change
add_column :foreman_openscap_policies, :treshold, :numeric, :null => false, :default => 100
add_column :reports, :score, :numeric
end
end

0 comments on commit 9fe38de

Please sign in to comment.