foreman_openscap 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/foreman_openscap/arf_reports.js +16 -0
- data/app/assets/javascripts/foreman_openscap/openscap_proxy.js +52 -0
- data/app/assets/javascripts/foreman_openscap/reports.js +6 -0
- data/app/assets/stylesheets/foreman_openscap/policy.css +2 -1
- data/app/assets/stylesheets/foreman_openscap/reports.css +3 -0
- data/app/controllers/api/v2/compliance/arf_reports_controller.rb +2 -2
- data/app/controllers/api/v2/compliance/policies_controller.rb +6 -6
- data/app/controllers/api/v2/compliance/scap_contents_controller.rb +2 -2
- data/app/controllers/arf_reports_controller.rb +41 -5
- data/app/controllers/concerns/foreman_openscap/hostgroups_controller_extensions.rb +20 -0
- data/app/controllers/concerns/foreman_openscap/hosts_common_controller_extensions.rb +45 -0
- data/app/controllers/concerns/foreman_openscap/hosts_controller_extensions.rb +17 -0
- data/app/controllers/policies_controller.rb +4 -4
- data/app/helpers/arf_report_dashboard_helper.rb +5 -5
- data/app/helpers/arf_reports_helper.rb +28 -0
- data/app/helpers/compliance_hosts_helper.rb +5 -3
- data/app/helpers/policies_helper.rb +3 -3
- data/app/helpers/policy_dashboard_helper.rb +2 -2
- data/app/lib/proxy_api/available_proxy.rb +7 -7
- data/app/lib/proxy_api/openscap.rb +10 -0
- data/app/mailers/foreman_openscap/policy_mailer.rb +2 -2
- data/app/models/concerns/foreman_openscap/compliance_status_scoped_search.rb +5 -5
- data/app/models/concerns/foreman_openscap/host_extensions.rb +22 -14
- data/app/models/concerns/foreman_openscap/hostgroup_extensions.rb +12 -0
- data/app/models/concerns/foreman_openscap/log_extensions.rb +8 -0
- data/app/models/concerns/foreman_openscap/openscap_proxy_core_extensions.rb +55 -0
- data/app/models/concerns/foreman_openscap/openscap_proxy_extensions.rb +17 -0
- data/app/models/concerns/foreman_openscap/smart_proxy_extensions.rb +23 -0
- data/app/models/foreman_openscap/arf_report.rb +42 -21
- data/app/models/foreman_openscap/policy.rb +38 -38
- data/app/models/foreman_openscap/scap_content.rb +9 -9
- data/app/overrides/hostgroups/form/select_openscap_proxy.rb +4 -0
- data/app/overrides/hosts/form/select_openscap_proxy.rb +4 -0
- data/app/services/foreman_openscap/host_report_dashboard/data.rb +5 -5
- data/app/services/foreman_openscap/report_dashboard/data.rb +5 -5
- data/app/views/arf_reports/_detailed_message.html.erb +9 -0
- data/app/views/arf_reports/_list.html.erb +29 -9
- data/app/views/arf_reports/_output.html.erb +12 -8
- data/app/views/arf_reports/delete_multiple.html.erb +29 -0
- data/app/views/arf_reports/index.html.erb +1 -1
- data/app/views/arf_reports/show.html.erb +3 -1
- data/app/views/compliance_hosts/_openscap_proxy.html.erb +8 -0
- data/app/views/policies/_form.html.erb +1 -1
- data/app/views/policies/steps/_schedule_form.html.erb +1 -1
- data/config/routes.rb +17 -1
- data/db/migrate/20141013172051_create_scaptimony_policies.rb +1 -1
- data/db/migrate/20141014105333_create_scaptimony_assets.rb +2 -2
- data/db/migrate/20141015092642_create_scaptimony_arf_reports.rb +4 -4
- data/db/migrate/20141104164201_create_scaptimony_scap_contents.rb +1 -3
- data/db/migrate/20141104171545_create_scaptimony_policy_revisions.rb +2 -2
- data/db/migrate/20141105174834_add_columns_to_scaptimony_policies.rb +1 -1
- data/db/migrate/20141113221054_create_scaptimony_scap_content_profiles.rb +1 -1
- data/db/migrate/20141116171305_add_profile_to_scaptimony_policies.rb +1 -1
- data/db/migrate/20141119182606_create_scaptimony_xccdf_rule_results.rb +3 -3
- data/db/migrate/20150821100137_migrate_from_scaptimony.rb +2 -2
- data/db/migrate/20150929152345_move_arf_reports_to_reports_table.rb +1 -1
- data/db/migrate/20151023131950_link_arf_report_directly_to_host.rb +12 -8
- data/db/migrate/20151118165125_add_size_to_scap_content.rb +5 -0
- data/db/migrate/20151119155419_add_arf_fields_to_message.rb +8 -0
- data/db/migrate/20151120090851_add_openscap_proxy_to_host_and_hostgroup.rb +25 -0
- data/db/seeds.d/openscap_feature.rb +1 -1
- data/db/seeds.d/openscap_scap_default.rb +1 -1
- data/lib/foreman_openscap/bulk_upload.rb +11 -12
- data/lib/foreman_openscap/engine.rb +22 -11
- data/lib/foreman_openscap/helper.rb +1 -1
- data/lib/foreman_openscap/version.rb +1 -1
- data/lib/tasks/foreman_openscap_tasks.rake +3 -2
- data/test/factories/arf_report_factory.rb +2 -1
- data/test/factories/compliance_host_factory.rb +1 -0
- data/test/factories/scap_content_related.rb +1 -1
- data/test/functional/api/v2/compliance/arf_reports_controller_test.rb +3 -3
- data/test/functional/api/v2/compliance/policies_controller_test.rb +1 -1
- data/test/functional/api/v2/compliance/scap_contents_controller_test.rb +2 -2
- data/test/functional/arf_reports_controller_test.rb +21 -0
- data/test/lib/foreman_openscap/bulk_upload_test.rb +2 -2
- data/test/test_plugin_helper.rb +2 -2
- data/test/unit/arf_report_test.rb +12 -1
- data/test/unit/compliance_status_test.rb +6 -5
- data/test/unit/openscap_host_test.rb +4 -0
- data/test/unit/policy_mailer_test.rb +1 -1
- data/test/unit/scap_content_test.rb +1 -1
- metadata +29 -8
@@ -26,9 +26,9 @@ module PolicyDashboardHelper
|
|
26
26
|
[:incompliant_hosts, _('Incompliant hosts')],
|
27
27
|
[:inconclusive_hosts, _('Inconclusive')],
|
28
28
|
[:report_missing, _('Not audited')],
|
29
|
-
].each
|
29
|
+
].each do |i|
|
30
30
|
data << {:label => i[1], :data => report[i[0]], :color => COLORS[i[0]]}
|
31
|
-
|
31
|
+
end
|
32
32
|
flot_pie_chart 'overview', _('Compliance Status'), data, options
|
33
33
|
end
|
34
34
|
|
@@ -2,13 +2,13 @@ module ::ProxyAPI
|
|
2
2
|
class AvailableProxy
|
3
3
|
|
4
4
|
HTTP_ERRORS = [
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
EOFError,
|
6
|
+
Errno::ECONNRESET,
|
7
|
+
Errno::EINVAL,
|
8
|
+
Net::HTTPBadResponse,
|
9
|
+
Net::HTTPHeaderSyntaxError,
|
10
|
+
Net::ProtocolError,
|
11
|
+
Timeout::Error
|
12
12
|
]
|
13
13
|
|
14
14
|
def initialize(args)
|
@@ -36,5 +36,15 @@ module ::ProxyAPI
|
|
36
36
|
raise ::ProxyAPI::ProxyException.new(url, e, N_("Unable to get xml version of requested report from Smart Proxy"))
|
37
37
|
end
|
38
38
|
end
|
39
|
+
|
40
|
+
def destroy_report(report, cname)
|
41
|
+
begin
|
42
|
+
parse(delete("arf/#{report.id}/#{cname}/#{report.reported_at.to_i}/#{report.policy_arf_report.digest}"))
|
43
|
+
rescue => e
|
44
|
+
logger.error "Failed to destroy arf report with id #{report.id} on Smart Proxy"
|
45
|
+
logger.debug e.backtrace.join("\n\t")
|
46
|
+
false
|
47
|
+
end
|
48
|
+
end
|
39
49
|
end
|
40
50
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module ForemanOpenscap
|
2
|
-
class PolicyMailer
|
2
|
+
class PolicyMailer < ::ApplicationMailer
|
3
3
|
|
4
4
|
def policy_summary(options = {})
|
5
5
|
set_url
|
6
6
|
user = ::User.find(options[:user])
|
7
7
|
@time = options[:time] || 1.day.ago
|
8
8
|
|
9
|
-
@policies = ::ForemanOpenscap::Policy.all.reject {|policy| policy.assets.map(&:host).compact.empty?}
|
9
|
+
@policies = ::ForemanOpenscap::Policy.all.reject { |policy| policy.assets.map(&:host).compact.empty? }
|
10
10
|
@compliant_hosts = @policies.map { |policy| Host.where(:id => policy.assets.comply_with(policy).map(&:assetable_id)) }.flatten
|
11
11
|
@incompliant_hosts = @policies.map { |policy| Host.where(:id => policy.assets.incomply_with(policy).map(&:assetable_id)) }.flatten
|
12
12
|
changed_hosts_of_policies(@policies)
|
@@ -11,9 +11,9 @@ module ForemanOpenscap
|
|
11
11
|
def search_by_policy_name(_key, _operator, policy_name)
|
12
12
|
cond = sanitize_policy_name(policy_name)
|
13
13
|
{ :conditions => ArfReport.arel_table[:id].in(
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
PolicyArfReport.select(PolicyArfReport.arel_table[:arf_report_id])
|
15
|
+
.of_policy(Policy.find_by_name(cond).id).ast
|
16
|
+
).to_sql
|
17
17
|
}
|
18
18
|
end
|
19
19
|
|
@@ -29,12 +29,12 @@ module ForemanOpenscap
|
|
29
29
|
search_by_policy_results policy_name, &:othered
|
30
30
|
end
|
31
31
|
|
32
|
-
|
32
|
+
def search_by_policy_results(policy_name, &selection)
|
33
33
|
cond = sanitize_policy_name(policy_name)
|
34
34
|
{ :conditions => ArfReport.arel_table[:id].in(
|
35
35
|
ArfReport.select(ArfReport.arel_table[:id])
|
36
36
|
.latest_of_policy(Policy.find_by_name cond).instance_eval(&selection).ast
|
37
|
-
|
37
|
+
).to_sql
|
38
38
|
}
|
39
39
|
end
|
40
40
|
|
@@ -10,16 +10,17 @@ module ForemanOpenscap
|
|
10
10
|
has_many :arf_reports, :class_name => '::ForemanOpenscap::ArfReport', :foreign_key => :host_id
|
11
11
|
has_one :compliance_status_object, :class_name => '::ForemanOpenscap::ComplianceStatus', :foreign_key => 'host_id'
|
12
12
|
|
13
|
-
scoped_search :in => :policies, :on => :name, :complete_value => true, :rename => :
|
13
|
+
scoped_search :in => :policies, :on => :name, :complete_value => true, :rename => :compliance_policy,
|
14
14
|
:only_explicit => true, :operators => ['= ', '!= '], :ext_method => :search_by_policy_name
|
15
15
|
|
16
|
-
scoped_search :in => :policies, :on => :name, :complete_value => true, :rename => :
|
16
|
+
scoped_search :in => :policies, :on => :name, :complete_value => true, :rename => :compliance_report_missing_for,
|
17
17
|
:only_explicit => true, :operators => ['= ', '!= '], :ext_method => :search_by_missing_arf
|
18
18
|
|
19
19
|
scoped_search :in => :compliance_status_object, :on => :status, :rename => :compliance_status,
|
20
20
|
:complete_value => {:compliant => ::ForemanOpenscap::ComplianceStatus::COMPLIANT,
|
21
21
|
:incompliant => ::ForemanOpenscap::ComplianceStatus::INCOMPLIANT,
|
22
22
|
:inconclusive => ::ForemanOpenscap::ComplianceStatus::INCONCLUSIVE}
|
23
|
+
after_save :puppetrun!, :if => :openscap_proxy_id_changed?
|
23
24
|
|
24
25
|
scope :comply_with, lambda { |policy|
|
25
26
|
joins(:arf_reports).merge(ArfReport.latest_of_policy policy).merge(ArfReport.passed)
|
@@ -44,6 +45,14 @@ module ForemanOpenscap
|
|
44
45
|
WHERE foreman_openscap_assets.assetable_type = 'Host::Base'
|
45
46
|
AND foreman_openscap_asset_policies.policy_id = '#{policy.id}')")
|
46
47
|
}
|
48
|
+
|
49
|
+
alias_method_chain :set_hostgroup_defaults, :openscap
|
50
|
+
end
|
51
|
+
|
52
|
+
def set_hostgroup_defaults_with_openscap
|
53
|
+
set_hostgroup_defaults_without_openscap
|
54
|
+
return unless hostgroup
|
55
|
+
assign_hostgroup_attributes %w(openscap_proxy_id)
|
47
56
|
end
|
48
57
|
|
49
58
|
def get_asset
|
@@ -91,25 +100,24 @@ module ForemanOpenscap
|
|
91
100
|
def search_by_policy_name(key, operator, policy_name)
|
92
101
|
cond = sanitize_sql_for_conditions(["foreman_openscap_policies.name #{operator} ?", value_to_sql(operator, policy_name)])
|
93
102
|
{ :conditions => Host::Managed.arel_table[:id].in(
|
94
|
-
|
95
|
-
|
103
|
+
Host::Managed.select(Host::Managed.arel_table[:id]).joins(:policies).where(cond).ast
|
104
|
+
).to_sql }
|
96
105
|
end
|
97
106
|
|
98
107
|
def search_by_missing_arf(key, operator, policy_name)
|
99
108
|
cond = sanitize_sql_for_conditions(["foreman_openscap_policies.name #{operator} ?", value_to_sql(operator, policy_name)])
|
100
109
|
{ :conditions => Host::Managed.arel_table[:id].in(
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
+
Host::Managed.select(Host::Managed.arel_table[:id])
|
111
|
+
.joins(:policies)
|
112
|
+
.where(cond)
|
113
|
+
.where("foreman_openscap_assets.id NOT IN (
|
114
|
+
SELECT DISTINCT foreman_openscap_arf_reports.asset_id
|
115
|
+
FROM foreman_openscap_arf_reports
|
116
|
+
WHERE foreman_openscap_arf_reports.asset_id = foreman_openscap_assets.id
|
117
|
+
AND foreman_openscap_arf_reports.policy_id = foreman_openscap_policies.id)
|
118
|
+
").ast).to_sql
|
110
119
|
}
|
111
120
|
end
|
112
|
-
|
113
121
|
end
|
114
122
|
end
|
115
123
|
end
|
@@ -7,5 +7,17 @@ module ForemanOpenscap
|
|
7
7
|
has_many :asset_policies, :through => :asset, :class_name => "::ForemanOpenscap::AssetPolicy"
|
8
8
|
has_many :policies, :through => :asset_policies, :class_name => "::ForemanOpenscap::Policy"
|
9
9
|
end
|
10
|
+
|
11
|
+
unless defined?(Katello::System)
|
12
|
+
private
|
13
|
+
|
14
|
+
def inherited_ancestry_attribute(attribute)
|
15
|
+
if ancestry.present?
|
16
|
+
self[attribute] || self.class.sort_by_ancestry(ancestors.where("#{attribute} is not NULL")).last.try(attribute)
|
17
|
+
else
|
18
|
+
self.send(attribute)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
10
22
|
end
|
11
23
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module ForemanOpenscap
|
2
|
+
module OpenscapProxyCoreExtensions
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
validate :openscap_proxy_has_feature
|
7
|
+
end
|
8
|
+
|
9
|
+
def update_scap_client_params(proxy_id)
|
10
|
+
new_proxy = SmartProxy.find proxy_id
|
11
|
+
model_match = self.class.name.underscore.match(/\Ahostgroup\z/) ? "hostgroup" : "fqdn"
|
12
|
+
puppetclass = Puppetclass.find_by_name("foreman_scap_client")
|
13
|
+
fail _("Puppetclass 'foreman_scap_client' not found, make sure it is imported form Puppetmaster") if puppetclass.nil?
|
14
|
+
scap_params = puppetclass.class_params
|
15
|
+
server_lookup_key = scap_params.find { |param| param.key == "server" }
|
16
|
+
port_lookup_key = scap_params.find { |param| param.key == "port" }
|
17
|
+
pairs = scap_client_lookup_values_for([server_lookup_key, port_lookup_key], model_match)
|
18
|
+
mapping = { "server" => new_proxy.hostname, "port" => new_proxy.port }
|
19
|
+
update_scap_client_lookup_values(pairs, model_match, mapping)
|
20
|
+
end
|
21
|
+
|
22
|
+
def inherited_openscap_proxy_id
|
23
|
+
inherited_ancestry_attribute(:openscap_proxy_id)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def scap_client_lookup_values_for(lookup_keys, model_match)
|
29
|
+
lookup_keys.inject({}) do |result, key|
|
30
|
+
result[key] = key.lookup_values.find { |value| value.match == "#{lookup_matcher(model_match)}" }
|
31
|
+
result
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def update_scap_client_lookup_values(pairs, model_match, mapping)
|
36
|
+
pairs.each do |k, v|
|
37
|
+
if v.nil?
|
38
|
+
LookupValue.create(:match => lookup_matcher(model_match), :value => mapping[k.key], :lookup_key_id => k.id)
|
39
|
+
else
|
40
|
+
v.value = mapping[k.key]
|
41
|
+
v.save
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def lookup_matcher(model_match)
|
47
|
+
model_match == "fqdn" ? "#{model_match}=#{name}" : "#{model_match}=#{title}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def openscap_proxy_has_feature
|
51
|
+
return true unless openscap_proxy_id
|
52
|
+
openscap_proxy.has_feature? "Openscap"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ForemanOpenscap
|
2
|
+
module OpenscapProxyExtensions
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
belongs_to :openscap_proxy, :class_name => "SmartProxy"
|
7
|
+
attr_accessible :openscap_proxy_id
|
8
|
+
end
|
9
|
+
|
10
|
+
def openscap_proxy_api
|
11
|
+
return @openscap_api if @openscap_api
|
12
|
+
proxy_url = openscap_proxy.url if openscap_proxy
|
13
|
+
fail(_("No openscap proxy found for %s") % id) unless proxy_url
|
14
|
+
@openscap_api = ::ProxyAPI::Openscap.new(:url => proxy_url)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ForemanOpenscap
|
2
|
+
module SmartProxyExtensions
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
has_many :openscap_hostgroups, :foreign_key => 'openscap_proxy_id', :class_name => "::Hostgroup"
|
7
|
+
has_many :openscap_hosts, :foreign_key => 'openscap_proxy_id', :class_name => "::Host"
|
8
|
+
has_many :arf_reports, :foreign_key => 'openscap_proxy_id', :class_name => "ForemanOpenscap::ArfReport"
|
9
|
+
PORT_MATCH = /:(\d+)\z/
|
10
|
+
after_destroy :delete_associated_arf_reports
|
11
|
+
end
|
12
|
+
|
13
|
+
def port
|
14
|
+
url.match(PORT_MATCH)[1]
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def delete_associated_arf_reports
|
20
|
+
ForemanOpenscap::ArfReport.where(:openscap_proxy_id => id).delete_all
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -3,7 +3,9 @@ require 'foreman_openscap/helper'
|
|
3
3
|
module ForemanOpenscap
|
4
4
|
class ArfReport < ::Report
|
5
5
|
include Taxonomix
|
6
|
+
include OpenscapProxyExtensions
|
6
7
|
|
8
|
+
# attr_accessible :host_id, :reported_at, :status, :metrics
|
7
9
|
RESULT = %w(pass fail error unknown notapplicable notchecked notselected informational fixed)
|
8
10
|
METRIC = %w(passed othered failed)
|
9
11
|
BIT_NUM = 10
|
@@ -11,15 +13,15 @@ module ForemanOpenscap
|
|
11
13
|
|
12
14
|
has_one :policy_arf_report, :dependent => :destroy
|
13
15
|
has_one :policy, :through => :policy_arf_report
|
14
|
-
has_one :asset, :through => :host, :class_name => 'ForemanOpenscap::Asset'
|
16
|
+
has_one :asset, :through => :host, :class_name => 'ForemanOpenscap::Asset', :as => :assetable
|
15
17
|
after_save :assign_locations_organizations
|
16
18
|
validate :result, :inclusion => { :in => RESULT }
|
17
19
|
|
18
|
-
default_scope
|
20
|
+
default_scope do
|
19
21
|
with_taxonomy_scope do
|
20
22
|
order("#{self.table_name}.created_at DESC")
|
21
23
|
end
|
22
|
-
|
24
|
+
end
|
23
25
|
|
24
26
|
scope :hosts, lambda { includes(:policy) }
|
25
27
|
scope :of_policy, lambda { |policy_id| joins(:policy_arf_report).merge(PolicyArfReport.of_policy(policy_id)) }
|
@@ -40,13 +42,13 @@ module ForemanOpenscap
|
|
40
42
|
ON reports.id = latest.id")
|
41
43
|
}
|
42
44
|
|
43
|
-
scope :failed, lambda { where("(#{report_status_column} >> #{
|
44
|
-
scope :not_failed, lambda { where("(#{report_status_column} >> #{
|
45
|
+
scope :failed, lambda { where("(#{report_status_column} >> #{bit_mask 'failed'}) > 0") }
|
46
|
+
scope :not_failed, lambda { where("(#{report_status_column} >> #{bit_mask 'failed'}) = 0") }
|
45
47
|
|
46
|
-
scope :othered, lambda { where("(#{report_status_column} >> #{
|
47
|
-
scope :not_othered, lambda { where("(#{report_status_column} >> #{
|
48
|
+
scope :othered, lambda { where("(#{report_status_column} >> #{bit_mask 'othered'}) > 0").merge(not_failed) }
|
49
|
+
scope :not_othered, lambda { where("(#{report_status_column} >> #{bit_mask 'othered'}) = 0") }
|
48
50
|
|
49
|
-
scope :passed, lambda { where("(#{report_status_column} >> #{
|
51
|
+
scope :passed, lambda { where("(#{report_status_column} >> #{bit_mask 'passed'}) > 0").merge(not_failed).merge(not_othered) }
|
50
52
|
|
51
53
|
def self.bit_mask(status)
|
52
54
|
ComplianceStatus.bit_mask(status)
|
@@ -97,21 +99,25 @@ module ForemanOpenscap
|
|
97
99
|
policy = Policy.find(params[:policy_id])
|
98
100
|
ArfReport.transaction do
|
99
101
|
# TODO:RAILS-4.0: This should become arf_report = ArfReport.find_or_create_by! ...
|
100
|
-
arf_report = ArfReport.create!(:
|
102
|
+
arf_report = ArfReport.create!(:host => asset.host,
|
101
103
|
:reported_at => Time.at(params[:date].to_i),
|
102
104
|
:status => params[:metrics],
|
103
|
-
:metrics => params[:metrics]
|
105
|
+
:metrics => params[:metrics],
|
106
|
+
:openscap_proxy => asset.host.openscap_proxy)
|
104
107
|
PolicyArfReport.where(:arf_report_id => arf_report.id, :policy_id => policy.id, :digest => params[:digest]).first_or_create!
|
105
108
|
if params[:logs]
|
106
109
|
params[:logs].each do |log|
|
107
110
|
src = Source.find_or_create(log[:source])
|
108
|
-
|
111
|
+
digest = Digest::SHA1.hexdigest(log[:title])
|
112
|
+
msg = Message.where(:value => N_(log[:title]), :digest => digest, :severity => log[:severity],
|
113
|
+
:description => newline_to_space(log[:description]), :rationale => newline_to_space(log[:rationale]),
|
114
|
+
:scap_references => references_links(log[:references])).first_or_create
|
109
115
|
#TODO: log level
|
110
116
|
Log.create!(:source_id => src.id,
|
111
117
|
:message_id => msg.id,
|
112
|
-
:
|
118
|
+
:level => :info,
|
113
119
|
:result => log[:result],
|
114
|
-
:
|
120
|
+
:report => arf_report)
|
115
121
|
end
|
116
122
|
end
|
117
123
|
end
|
@@ -138,11 +144,11 @@ module ForemanOpenscap
|
|
138
144
|
end
|
139
145
|
|
140
146
|
def to_html
|
141
|
-
|
147
|
+
openscap_proxy_api.arf_report_html(self, ForemanOpenscap::Helper::find_name_or_uuid_by_host(host))
|
142
148
|
end
|
143
149
|
|
144
150
|
def to_bzip
|
145
|
-
|
151
|
+
openscap_proxy_api.arf_report_bzip(self, ForemanOpenscap::Helper::find_name_or_uuid_by_host(host))
|
146
152
|
end
|
147
153
|
|
148
154
|
def equal?(other)
|
@@ -154,12 +160,27 @@ module ForemanOpenscap
|
|
154
160
|
policy.id == other.policy.id
|
155
161
|
end
|
156
162
|
|
157
|
-
def
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
+
def destroy
|
164
|
+
if openscap_proxy_api.destroy_report(self, ForemanOpenscap::Helper::find_name_or_uuid_by_host(host))
|
165
|
+
super
|
166
|
+
else
|
167
|
+
false
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def self.newline_to_space(string)
|
172
|
+
string.gsub(/ *\n+/, " ")
|
173
|
+
end
|
174
|
+
|
175
|
+
def self.references_links(references)
|
176
|
+
return if references.nil?
|
177
|
+
html_links = []
|
178
|
+
references.each do |reference|
|
179
|
+
next if reference['title'] == 'test_attestation' # A blank url created by OpenSCAP
|
180
|
+
reference['html_link'] = "<a href='#{reference['href']}'>#{reference['href']}</a>" if reference['title'].blank?
|
181
|
+
html_links << reference['html_link']
|
182
|
+
end
|
183
|
+
html_links.join(', ')
|
163
184
|
end
|
164
185
|
end
|
165
186
|
end
|
@@ -21,9 +21,9 @@ module ForemanOpenscap
|
|
21
21
|
SERVER_CLASS_PARAMETER = 'server'
|
22
22
|
PORT_CLASS_PARAMETER = 'port'
|
23
23
|
|
24
|
-
validates :name, :presence => true, :uniqueness => true, :format => {without
|
24
|
+
validates :name, :presence => true, :uniqueness => true, :format => { :without => /\s/ }
|
25
25
|
validate :ensure_needed_puppetclasses
|
26
|
-
validates :period, :inclusion => {:in => %w
|
26
|
+
validates :period, :inclusion => {:in => %w(weekly monthly custom)},
|
27
27
|
:if => Proc.new { |policy| policy.new_record? ? policy.step_index > 3 : !policy.id.blank? }
|
28
28
|
validates :weekday, :inclusion => {:in => Date::DAYNAMES.map(&:downcase)},
|
29
29
|
:if => Proc.new { |policy| policy.period == 'weekly' && (policy.new_record? ? policy.step_index > 3 : !policy.id.blank?) }
|
@@ -36,11 +36,11 @@ module ForemanOpenscap
|
|
36
36
|
after_save :assign_policy_to_hostgroups
|
37
37
|
# before_destroy - ensure that the policy has no hostgroups, or classes
|
38
38
|
|
39
|
-
default_scope
|
39
|
+
default_scope do
|
40
40
|
with_taxonomy_scope do
|
41
41
|
order("foreman_openscap_policies.name")
|
42
42
|
end
|
43
|
-
|
43
|
+
end
|
44
44
|
|
45
45
|
def assign_assets(a)
|
46
46
|
self.asset_ids = (self.asset_ids + a.collect(&:id)).uniq
|
@@ -138,14 +138,14 @@ module ForemanOpenscap
|
|
138
138
|
|
139
139
|
def used_location_ids
|
140
140
|
Location.joins(:taxable_taxonomies).where(
|
141
|
-
|
142
|
-
|
141
|
+
'taxable_taxonomies.taxable_type' => 'ForemanOpenscap::Policy',
|
142
|
+
'taxable_taxonomies.taxable_id' => id).pluck("#{Location.arel_table.name}.id")
|
143
143
|
end
|
144
144
|
|
145
145
|
def used_organization_ids
|
146
146
|
Organization.joins(:taxable_taxonomies).where(
|
147
|
-
|
148
|
-
|
147
|
+
'taxable_taxonomies.taxable_type' => 'ForemanOpenscap::Policy',
|
148
|
+
'taxable_taxonomies.taxable_id' => id).pluck("#{Location.arel_table.name}.id")
|
149
149
|
end
|
150
150
|
|
151
151
|
def used_hostgroup_ids
|
@@ -163,10 +163,10 @@ module ForemanOpenscap
|
|
163
163
|
|
164
164
|
def to_enc
|
165
165
|
{
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
166
|
+
'id' => self.id,
|
167
|
+
'profile_id' => self.scap_content_profile.try(:profile_id) || '',
|
168
|
+
'content_path' => "/var/lib/openscap/content/#{self.scap_content.digest}.xml",
|
169
|
+
'download_path' => "/compliance/policies/#{self.id}/content" # default to proxy path
|
170
170
|
}.merge(period_enc)
|
171
171
|
end
|
172
172
|
|
@@ -175,22 +175,22 @@ module ForemanOpenscap
|
|
175
175
|
def period_enc
|
176
176
|
# get crontab expression as an array (minute hour day_of_month month day_of_week)
|
177
177
|
cron_parts = case period
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
178
|
+
when 'weekly'
|
179
|
+
['0', '1', '*', '*', weekday_number.to_s]
|
180
|
+
when 'monthly'
|
181
|
+
['0', '1', day_of_month.to_s, '*', '*']
|
182
|
+
when 'custom'
|
183
|
+
cron_line_split
|
184
|
+
else
|
185
|
+
fail 'invalid period specification'
|
186
186
|
end
|
187
187
|
|
188
188
|
{
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
189
|
+
'minute' => cron_parts[0],
|
190
|
+
'hour' => cron_parts[1],
|
191
|
+
'monthday' => cron_parts[2],
|
192
|
+
'month' => cron_parts[3],
|
193
|
+
'weekday' => cron_parts[4],
|
194
194
|
}
|
195
195
|
end
|
196
196
|
|
@@ -205,7 +205,7 @@ module ForemanOpenscap
|
|
205
205
|
return false
|
206
206
|
end
|
207
207
|
|
208
|
-
unless policies_param = puppetclass.class_params.
|
208
|
+
unless policies_param = puppetclass.class_params.find_by_key(POLICIES_CLASS_PARAMETER)
|
209
209
|
errors[:base] << _("Puppet class %{class} does not have %{parameter} class parameter.") % {:class => SCAP_PUPPET_CLASS, :parameter => POLICIES_CLASS_PARAMETER}
|
210
210
|
return false
|
211
211
|
end
|
@@ -257,18 +257,18 @@ module ForemanOpenscap
|
|
257
257
|
end
|
258
258
|
|
259
259
|
def populate_overrides(puppetclass, hostgroup)
|
260
|
-
puppetclass.class_params.where(:override => true).
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
260
|
+
puppetclass.class_params.where(:override => true).find_each do |override|
|
261
|
+
next unless hostgroup.puppet_proxy && (url = hostgroup.puppet_proxy.url).present?
|
262
|
+
|
263
|
+
case override.key
|
264
|
+
when SERVER_CLASS_PARAMETER
|
265
|
+
lookup_value = LookupValue.where(:match => "hostgroup=#{hostgroup.to_label}", :lookup_key_id => override.id).first_or_initialize
|
266
|
+
puppet_proxy_fqdn = URI.parse(url).host
|
267
|
+
lookup_value.update_attribute(:value, puppet_proxy_fqdn)
|
268
|
+
when PORT_CLASS_PARAMETER
|
269
|
+
lookup_value = LookupValue.where(:match => "hostgroup=#{hostgroup.to_label}", :lookup_key_id => override.id).first_or_initialize
|
270
|
+
puppet_proxy_port = URI.parse(url).port
|
271
|
+
lookup_value.update_attribute(:value, puppet_proxy_port)
|
272
272
|
end
|
273
273
|
end
|
274
274
|
end
|