foreman_openscap 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|