foreman_openscap 0.4.3 → 0.5.0
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/load_report.js +1 -1
- data/app/assets/javascripts/foreman_openscap/policy_edit.js +0 -2
- data/app/controllers/api/v2/compliance/arf_reports_controller.rb +7 -22
- data/app/controllers/api/v2/compliance/policies_controller.rb +5 -5
- data/app/controllers/api/v2/compliance/scap_contents_controller.rb +3 -3
- data/app/controllers/arf_reports_controller.rb +62 -0
- data/app/controllers/{scaptimony_dashboard_controller.rb → compliance_dashboard_controller.rb} +1 -1
- data/app/controllers/compliance_hosts_controller.rb +5 -0
- data/app/controllers/{scaptimony_policies_controller.rb → policies_controller.rb} +13 -13
- data/app/controllers/{scaptimony_policy_dashboard_controller.rb → policy_dashboard_controller.rb} +3 -3
- data/app/controllers/{scaptimony_scap_contents_controller.rb → scap_contents_controller.rb} +11 -11
- data/app/helpers/{scaptimony_report_dashboard_helper.rb → arf_report_dashboard_helper.rb} +3 -5
- data/app/helpers/arf_reports_helper.rb +21 -0
- data/app/helpers/compliance_hosts_helper.rb +25 -0
- data/app/helpers/concerns/foreman_openscap/hosts_helper_extensions.rb +2 -32
- data/app/helpers/{scaptimony_policies_helper.rb → policies_helper.rb} +6 -2
- data/app/helpers/{scaptimony_policy_dashboard_helper.rb → policy_dashboard_helper.rb} +8 -8
- data/app/lib/proxy_api/available_proxy.rb +26 -0
- data/app/lib/proxy_api/openscap.rb +40 -0
- data/app/mailers/foreman_openscap/policy_mailer.rb +42 -0
- data/app/models/concerns/foreman_openscap/compliance_status_scoped_search.rb +91 -0
- data/app/models/concerns/foreman_openscap/host_extensions.rb +73 -17
- data/app/models/concerns/foreman_openscap/hostgroup_extensions.rb +3 -5
- data/app/models/foreman_openscap/arf_report.rb +165 -0
- data/app/models/foreman_openscap/asset.rb +27 -0
- data/app/models/foreman_openscap/asset_policy.rb +6 -0
- data/app/models/foreman_openscap/compliance_status.rb +50 -0
- data/app/models/{concerns/foreman_openscap/policy_extensions.rb → foreman_openscap/policy.rb} +72 -45
- data/app/models/foreman_openscap/policy_arf_report.rb +8 -0
- data/app/models/foreman_openscap/policy_revision.rb +6 -0
- data/app/models/foreman_openscap/scap_content.rb +112 -0
- data/app/models/foreman_openscap/scap_content_profile.rb +6 -0
- data/app/overrides/hosts/overview/host_compliance_status.rb +4 -4
- data/app/services/foreman_openscap/arf_report_status_calculator.rb +45 -0
- data/app/services/{scaptimony → foreman_openscap}/host_report_dashboard/data.rb +12 -6
- data/app/services/{scaptimony → foreman_openscap}/policy_dashboard/data.rb +5 -5
- data/app/services/{scaptimony → foreman_openscap}/report_dashboard/data.rb +4 -4
- data/app/views/api/v2/compliance/policies/create.json.rabl +3 -0
- data/app/views/{scaptimony_arf_reports → arf_reports}/_list.html.erb +4 -4
- data/app/views/arf_reports/_metrics.html.erb +37 -0
- data/app/views/arf_reports/_output.html.erb +23 -0
- data/app/views/{scaptimony_arf_reports → arf_reports}/index.html.erb +0 -0
- data/app/views/arf_reports/show.html.erb +14 -0
- data/app/views/{scaptimony_arf_reports/show.html.erb → arf_reports/show_html.html.erb} +2 -3
- data/app/views/compliance_hosts/_compliance_status.erb +6 -0
- data/app/views/{scaptimony_hosts → compliance_hosts}/show.html.erb +9 -2
- data/app/views/dashboard/{_foreman_openscap_host_reports_widget.html.erb → _compliance_host_reports_widget.html.erb} +3 -3
- data/app/views/dashboard/{_foreman_openscap_reports_breakdown_widget.html.erb → _compliance_reports_breakdown_widget.html.erb} +1 -1
- data/app/views/foreman_openscap/policy_mailer/_dashboard.erb +21 -0
- data/app/views/foreman_openscap/policy_mailer/_hosts.erb +44 -0
- data/app/views/foreman_openscap/policy_mailer/_list.erb +10 -0
- data/app/views/foreman_openscap/policy_mailer/_policy.erb +7 -0
- data/app/views/foreman_openscap/policy_mailer/policy_summary.erb +19 -0
- data/app/views/{scaptimony_policies → policies}/_form.html.erb +2 -8
- data/app/views/{scaptimony_policies → policies}/_list.html.erb +5 -5
- data/app/views/policies/_scap_content_results.html.erb +3 -0
- data/app/views/policies/create.html.erb +2 -0
- data/app/views/{scaptimony_policies → policies}/disassociate_multiple_hosts.html.erb +2 -2
- data/app/views/{scaptimony_policies → policies}/edit.html.erb +0 -0
- data/app/views/{scaptimony_policies → policies}/index.html.erb +1 -1
- data/app/views/policies/new.html.erb +2 -0
- data/app/views/{scaptimony_policies → policies}/select_multiple_hosts.html.erb +2 -2
- data/app/views/{scaptimony_policies → policies}/show.html.erb +1 -1
- data/app/views/{scaptimony_policies → policies}/steps/_create_policy_form.html.erb +0 -0
- data/app/views/{scaptimony_policies → policies}/steps/_hostgroups_form.html.erb +0 -0
- data/app/views/{scaptimony_policies → policies}/steps/_locations_form.html.erb +0 -0
- data/app/views/{scaptimony_policies → policies}/steps/_organizations_form.html.erb +0 -0
- data/app/views/policies/steps/_scap_content_form.html.erb +9 -0
- data/app/views/{scaptimony_policies → policies}/steps/_schedule_form.html.erb +1 -1
- data/app/views/{scaptimony_policies → policies}/steps/_step_form.html.erb +3 -3
- data/app/views/{scaptimony_policies → policies}/welcome.html.erb +2 -2
- data/app/views/{scaptimony_policy_dashboard → policy_dashboard}/_policy_chart_widget.html.erb +0 -0
- data/app/views/{scaptimony_policy_dashboard → policy_dashboard}/_policy_reports.html.erb +2 -2
- data/app/views/{scaptimony_policy_dashboard → policy_dashboard}/_policy_status_widget.html.erb +3 -3
- data/app/views/{scaptimony_policy_dashboard → policy_dashboard}/index.html.erb +0 -0
- data/app/views/{scaptimony_scap_contents → scap_contents}/_form.html.erb +5 -6
- data/app/views/{scaptimony_scap_contents → scap_contents}/_list.html.erb +3 -3
- data/app/views/{scaptimony_scap_contents → scap_contents}/edit.html.erb +0 -0
- data/app/views/{scaptimony_scap_contents → scap_contents}/index.html.erb +1 -1
- data/app/views/{scaptimony_scap_contents → scap_contents}/new.html.erb +0 -0
- data/app/views/{scaptimony_scap_contents → scap_contents}/welcome.html.erb +2 -2
- data/config/routes.rb +15 -11
- data/db/migrate/20141013172051_create_scaptimony_policies.rb +9 -0
- data/db/migrate/20141014105333_create_scaptimony_assets.rb +10 -0
- data/db/migrate/20141015092642_create_scaptimony_arf_reports.rb +13 -0
- data/db/migrate/20141015115511_add_arf_report_unique_constraint.rb +6 -0
- data/db/migrate/20141104164201_create_scaptimony_scap_contents.rb +7 -0
- data/db/migrate/20141104171545_create_scaptimony_policy_revisions.rb +14 -0
- data/db/migrate/20141105174625_add_description_to_scaptimony_policy_revisions.rb +5 -0
- data/db/migrate/20141105174834_add_columns_to_scaptimony_policies.rb +12 -0
- data/db/migrate/20141107091756_add_columns_to_scaptimony_scap_contents.rb +8 -0
- data/db/migrate/20141111104519_add_constraint_to_scaptimony_scap_contents.rb +5 -0
- data/db/migrate/20141113221054_create_scaptimony_scap_content_profiles.rb +12 -0
- data/db/migrate/20141116170632_remove_xccdf_profile_from_scaptimony_policies.rb +5 -0
- data/db/migrate/20141116171305_add_profile_to_scaptimony_policies.rb +6 -0
- data/db/migrate/20141118142954_add_constraint_to_scaptimony_policies.rb +5 -0
- data/db/migrate/20141119164918_create_scaptimony_xccdf_results.rb +8 -0
- data/db/migrate/20141119175434_create_scaptimony_xccdf_rules.rb +8 -0
- data/db/migrate/20141119182606_create_scaptimony_xccdf_rule_results.rb +9 -0
- data/db/migrate/20141121120326_create_scaptimony_arf_report_breakdowns.rb +24 -0
- data/db/migrate/20141121164042_replace_arf_report_breakdown_view.rb +25 -0
- data/db/migrate/20141206211151_create_scaptimony_assets_policies.rb +9 -0
- data/db/migrate/20141214112917_add_scap_file_to_scap_content.rb +5 -0
- data/db/migrate/20141216154502_rename_scaptimony_asset_policies.rb +5 -0
- data/db/migrate/20150111085317_polymorph_asset.rb +8 -0
- data/db/migrate/20150112152944_create_scaptimony_arf_report_raws.rb +10 -0
- data/db/migrate/20150114210634_rename_scaptimony_arf_report_raw_raw.rb +5 -0
- data/db/migrate/20150115155947_add_scaptimony_scap_content_digest.rb +21 -0
- data/db/migrate/20150116083129_add_day_of_month_and_cron_line_to_scaptimony_policy.rb +6 -0
- data/db/migrate/20150821100137_migrate_from_scaptimony.rb +59 -0
- data/db/migrate/20150827123826_remove_scaptimony_permissions.rb +21 -0
- data/db/migrate/20150925124959_create_policy_arf_reports.rb +13 -0
- data/db/migrate/20150929124853_add_result_to_logs.rb +9 -0
- data/db/migrate/20150929152345_move_arf_reports_to_reports_table.rb +179 -0
- data/db/migrate/20151023131950_link_arf_report_directly_to_host.rb +17 -0
- data/db/seeds.d/openscap_policy_notification.rb +9 -0
- data/lib/foreman_openscap/bulk_upload.rb +3 -1
- data/lib/foreman_openscap/engine.rb +53 -42
- data/lib/foreman_openscap/helper.rb +8 -0
- data/lib/foreman_openscap/version.rb +1 -1
- data/lib/tasks/foreman_openscap_tasks.rake +14 -0
- data/test/factories/arf_report_factory.rb +9 -6
- data/test/factories/asset_factory.rb +1 -1
- data/test/factories/compliance_host_factory.rb +9 -0
- data/test/factories/compliance_log_factory.rb +11 -0
- data/test/factories/policy_arf_report_factory.rb +6 -0
- data/test/factories/policy_factory.rb +3 -2
- data/test/factories/scap_content_related.rb +2 -2
- data/test/functional/api/v2/compliance/arf_reports_controller_test.rb +4 -3
- data/test/functional/api/v2/compliance/policies_controller_test.rb +2 -2
- data/test/functional/api/v2/compliance/scap_contents_controller_test.rb +3 -1
- data/test/lib/foreman_openscap/bulk_upload_test.rb +1 -1
- data/test/test_plugin_helper.rb +30 -0
- data/test/unit/arf_report_status_calculator_test.rb +11 -0
- data/test/unit/arf_report_test.rb +148 -0
- data/test/unit/compliance_status_test.rb +71 -0
- data/test/unit/openscap_host_test.rb +38 -7
- data/test/unit/policy_mailer_test.rb +38 -0
- data/test/unit/scap_content_test.rb +32 -0
- metadata +130 -74
- data/app/controllers/scaptimony_arf_reports_controller.rb +0 -34
- data/app/controllers/scaptimony_hosts_controller.rb +0 -5
- data/app/models/concerns/foreman_openscap/arf_report_extensions.rb +0 -50
- data/app/models/concerns/foreman_openscap/asset_extensions.rb +0 -34
- data/app/models/concerns/foreman_openscap/scap_content_extensions.rb +0 -40
- data/app/overrides/hosts/index/host_arf_report.rb +0 -5
- data/app/views/scaptimony_arf_reports/_host_report.html.erb +0 -8
- data/app/views/scaptimony_hosts/_host_status.html.erb +0 -17
- data/app/views/scaptimony_policies/_scap_content_results.html.erb +0 -7
- data/app/views/scaptimony_policies/create.html.erb +0 -2
- data/app/views/scaptimony_policies/new.html.erb +0 -2
- data/app/views/scaptimony_policies/steps/_scap_content_form.html.erb +0 -17
@@ -0,0 +1,25 @@
|
|
1
|
+
module ComplianceHostsHelper
|
2
|
+
|
3
|
+
def host_policy_breakdown_chart(report, options = {})
|
4
|
+
data = []
|
5
|
+
[[:passed, _('Passed')],
|
6
|
+
[:failed, _('Failed')],
|
7
|
+
[:othered, _('Other')],
|
8
|
+
].each { |i|
|
9
|
+
data << {:label => i[1], :data => report[i[0]], :color => ArfReportDashboardHelper::COLORS[i[0]]}
|
10
|
+
}
|
11
|
+
flot_pie_chart 'overview', _('Compliance reports breakdown'), data, options
|
12
|
+
end
|
13
|
+
|
14
|
+
def host_arf_reports_chart(policy_id)
|
15
|
+
passed, failed, othered, = [], [], []
|
16
|
+
@host.arf_reports.of_policy(policy_id).each do |report|
|
17
|
+
passed << [report.created_at.to_i*1000, report.passed]
|
18
|
+
failed << [report.created_at.to_i*1000, report.failed]
|
19
|
+
othered << [report.created_at.to_i*1000, report.othered]
|
20
|
+
end
|
21
|
+
[{:label => _("Passed"), :data => passed, :color => ArfReportDashboardHelper::COLORS[:passed]},
|
22
|
+
{:label => _("Failed"), :data => failed, :color => ArfReportDashboardHelper::COLORS[:failed]},
|
23
|
+
{:label => _("Othered"), :data => othered, :color => ArfReportDashboardHelper::COLORS[:othered]}]
|
24
|
+
end
|
25
|
+
end
|
@@ -7,39 +7,9 @@ module ForemanOpenscap
|
|
7
7
|
alias_method_chain :name_column, :scap
|
8
8
|
end
|
9
9
|
|
10
|
-
Colors = {
|
11
|
-
:passed => '#89A54E',
|
12
|
-
:failed => '#AA4643',
|
13
|
-
:othered => '#DB843D',
|
14
|
-
}
|
15
|
-
|
16
10
|
def multiple_actions_with_scap
|
17
|
-
multiple_actions_without_scap + [[_('Assign Compliance Policy'),
|
18
|
-
[_('Unassign Compliance Policy'),
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
def host_policy_breakdown_chart(report, options = {})
|
23
|
-
data = []
|
24
|
-
[[:passed, _('Passed')],
|
25
|
-
[:failed, _('Failed')],
|
26
|
-
[:othered, _('Other')],
|
27
|
-
].each { |i|
|
28
|
-
data << {:label => i[1], :data => report[i[0]], :color => Colors[i[0]]}
|
29
|
-
}
|
30
|
-
flot_pie_chart 'overview', _('Compliance reports breakdown'), data, options
|
31
|
-
end
|
32
|
-
|
33
|
-
def host_arf_reports_chart(policy_id)
|
34
|
-
passed, failed, othered, = [], [], []
|
35
|
-
@host.arf_reports.of_policy(policy_id).each do |report|
|
36
|
-
passed << [report.created_at.to_i*1000, report.passed]
|
37
|
-
failed << [report.created_at.to_i*1000, report.failed]
|
38
|
-
othered << [report.created_at.to_i*1000, report.othered]
|
39
|
-
end
|
40
|
-
[{:label => _("Passed"), :data => passed, :color => Colors[:passed]},
|
41
|
-
{:label => _("Failed"), :data => failed, :color => Colors[:failed]},
|
42
|
-
{:label => _("Othered"), :data => othered, :color => Colors[:othered]}]
|
11
|
+
multiple_actions_without_scap + [[_('Assign Compliance Policy'), select_multiple_hosts_policies_path],
|
12
|
+
[_('Unassign Compliance Policy'), disassociate_multiple_hosts_policies_path]]
|
43
13
|
end
|
44
14
|
|
45
15
|
def name_column_with_scap(record)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module PoliciesHelper
|
2
2
|
def profiles_selection
|
3
3
|
return @scap_content.scap_content_profiles unless @scap_content.blank?
|
4
4
|
return @policy.scap_content.scap_content_profiles unless @policy.scap_content.blank?
|
@@ -6,7 +6,7 @@ module ScaptimonyPoliciesHelper
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def scap_content_selector(form)
|
9
|
-
scap_contents =
|
9
|
+
scap_contents = ::ForemanOpenscap::ScapContent.all
|
10
10
|
if scap_contents.length > 1
|
11
11
|
select_f form, :scap_content_id, scap_contents, :id, :title,
|
12
12
|
{:include_blank => _("Choose existing SCAP Content")} ,
|
@@ -65,4 +65,8 @@ module ScaptimonyPoliciesHelper
|
|
65
65
|
link_to((previous).html_safe, '#', :class => 'btn btn-default', :onclick => "previous_step('#{@policy.previous_step}')")
|
66
66
|
end
|
67
67
|
end
|
68
|
+
|
69
|
+
def days_of_week_hash
|
70
|
+
Hash[*Date::DAYNAMES.map{ |day| [day.downcase, day]}.flatten]
|
71
|
+
end
|
68
72
|
end
|
@@ -8,16 +8,16 @@
|
|
8
8
|
# along with this software; if not, see http://www.gnu.org/licenses/gpl.txt
|
9
9
|
#
|
10
10
|
|
11
|
-
module
|
12
|
-
|
13
|
-
:compliant_hosts =>
|
14
|
-
:incompliant_hosts =>
|
15
|
-
:inconclusive_hosts =>
|
11
|
+
module PolicyDashboardHelper
|
12
|
+
COLORS = {
|
13
|
+
:compliant_hosts => ArfReportDashboardHelper::COLORS[:passed],
|
14
|
+
:incompliant_hosts => ArfReportDashboardHelper::COLORS[:failed],
|
15
|
+
:inconclusive_hosts => ArfReportDashboardHelper::COLORS[:othered],
|
16
16
|
:report_missing => '#92A8CD',
|
17
17
|
}
|
18
18
|
|
19
19
|
def policy_widget_list
|
20
|
-
|
20
|
+
ForemanOpenscap::PolicyDashboard::Manager.widgets
|
21
21
|
end
|
22
22
|
|
23
23
|
def host_breakdown_chart(report, options = {})
|
@@ -27,14 +27,14 @@ module ScaptimonyPolicyDashboardHelper
|
|
27
27
|
[:inconclusive_hosts, _('Inconclusive')],
|
28
28
|
[:report_missing, _('Not audited')],
|
29
29
|
].each { |i|
|
30
|
-
data << {:label => i[1], :data => report[i[0]], :color =>
|
30
|
+
data << {:label => i[1], :data => report[i[0]], :color => COLORS[i[0]]}
|
31
31
|
}
|
32
32
|
flot_pie_chart 'overview', _('Compliance Status'), data, options
|
33
33
|
end
|
34
34
|
|
35
35
|
def status_link(name, label, path)
|
36
36
|
content_tag :li do
|
37
|
-
content_tag(:i, raw(' '), :class=>'label', :style => 'background-color:' +
|
37
|
+
content_tag(:i, raw(' '), :class=>'label', :style => 'background-color:' + COLORS[label]) +
|
38
38
|
raw(' ') +
|
39
39
|
link_to(name, path, :class=>'dashboard-links') +
|
40
40
|
content_tag(:h4, @report[label])
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ::ProxyAPI
|
2
|
+
class AvailableProxy
|
3
|
+
|
4
|
+
HTTP_ERRORS = [
|
5
|
+
EOFError,
|
6
|
+
Errno::ECONNRESET,
|
7
|
+
Errno::EINVAL,
|
8
|
+
Net::HTTPBadResponse,
|
9
|
+
Net::HTTPHeaderSyntaxError,
|
10
|
+
Net::ProtocolError,
|
11
|
+
Timeout::Error
|
12
|
+
]
|
13
|
+
|
14
|
+
def initialize(args)
|
15
|
+
@features = ::ProxyAPI::Features.new(args).features
|
16
|
+
end
|
17
|
+
|
18
|
+
def available?
|
19
|
+
begin
|
20
|
+
return true if @features.include?('openscap')
|
21
|
+
rescue *HTTP_ERRORS
|
22
|
+
return false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ::ProxyAPI
|
2
|
+
class Openscap < ::ProxyAPI::Resource
|
3
|
+
def initialize(args)
|
4
|
+
@url = args[:url] + '/compliance/'
|
5
|
+
super args
|
6
|
+
@connect_params[:headers].merge!(:content_type => :xml)
|
7
|
+
end
|
8
|
+
|
9
|
+
def fetch_policies_for_scap_content(scap_file)
|
10
|
+
parse(post(scap_file, "scap_content/policies"))
|
11
|
+
end
|
12
|
+
|
13
|
+
def validate_scap_content(scap_file)
|
14
|
+
parse(post(scap_file, "scap_content/validator"))
|
15
|
+
end
|
16
|
+
|
17
|
+
def policy_html_guide(scap_file, policy)
|
18
|
+
guide = parse(post(scap_file, "scap_content/guide/#{policy}"))
|
19
|
+
guide['html']
|
20
|
+
end
|
21
|
+
|
22
|
+
def arf_report_html(report, cname)
|
23
|
+
begin
|
24
|
+
@connect_params[:headers] = { :accept => 'application/html' }
|
25
|
+
get "/arf/#{report.id}/#{cname}/#{report.reported_at.to_i}/#{report.policy_arf_report.digest}/html"
|
26
|
+
rescue => e
|
27
|
+
raise ::ProxyAPI::ProxyException.new(url, e, N_("Unable to get html version of requested report from Smart Proxy"))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def arf_report_bzip(report, cname)
|
32
|
+
begin
|
33
|
+
@connect_params[:headers] = { :content_type => 'application/arf-bzip2', :content_encoding => 'x-bzip2' }
|
34
|
+
get "/arf/#{report.id}/#{cname}/#{report.reported_at.to_i}/#{report.policy_arf_report.digest}/xml"
|
35
|
+
rescue => e
|
36
|
+
raise ::ProxyAPI::ProxyException.new(url, e, N_("Unable to get xml version of requested report from Smart Proxy"))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module ForemanOpenscap
|
2
|
+
class PolicyMailer < ::ApplicationMailer
|
3
|
+
|
4
|
+
def policy_summary(options = {})
|
5
|
+
set_url
|
6
|
+
user = ::User.find(options[:user])
|
7
|
+
@time = options[:time] || 1.day.ago
|
8
|
+
|
9
|
+
@policies = ::ForemanOpenscap::Policy.all.reject {|policy| policy.assets.map(&:host).compact.empty?}
|
10
|
+
@compliant_hosts = @policies.map { |policy| Host.where(:id => policy.assets.comply_with(policy).map(&:assetable_id)) }.flatten
|
11
|
+
@incompliant_hosts = @policies.map { |policy| Host.where(:id => policy.assets.incomply_with(policy).map(&:assetable_id)) }.flatten
|
12
|
+
changed_hosts_of_policies(@policies)
|
13
|
+
|
14
|
+
if user.nil? || user.mail.nil?
|
15
|
+
logger.warn "User with valid email not supplied, mail report will not be sent"
|
16
|
+
else
|
17
|
+
set_locale_for(user) do
|
18
|
+
subject = _("Scap policies summary")
|
19
|
+
mail(:to => user.mail, :subject => subject)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def changed_hosts_of_policies(policies)
|
27
|
+
hash = @policies.inject({}) do |result, policy|
|
28
|
+
result[policy.id] = policy.hosts
|
29
|
+
result
|
30
|
+
end
|
31
|
+
|
32
|
+
@changed_hosts = []
|
33
|
+
hash.each do |key, values|
|
34
|
+
values.each do |host|
|
35
|
+
@changed_hosts << host if host.scap_status_changed?(::ForemanOpenscap::Policy.find key)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
@changed_hosts.uniq
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module ForemanOpenscap
|
2
|
+
module ComplianceStatusScopedSearch
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def compliance_status_scoped_search(status, options = {})
|
7
|
+
options.merge!(:offset => ArfReport::METRIC.index(status.to_s), :word_size => ArfReport::BIT_NUM)
|
8
|
+
scoped_search options
|
9
|
+
end
|
10
|
+
|
11
|
+
def search_by_policy_name(_key, _operator, policy_name)
|
12
|
+
cond = sanitize_policy_name(policy_name)
|
13
|
+
{ :conditions => ArfReport.arel_table[:id].in(
|
14
|
+
PolicyArfReport.select(PolicyArfReport.arel_table[:arf_report_id])
|
15
|
+
.of_policy(Policy.find_by_name(cond).id).ast
|
16
|
+
).to_sql
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def search_by_comply_with(_key, _operator, policy_name)
|
21
|
+
search_by_policy_results policy_name, &:passed
|
22
|
+
end
|
23
|
+
|
24
|
+
def search_by_not_comply_with(_key, _operator, policy_name)
|
25
|
+
search_by_policy_results policy_name, &:failed
|
26
|
+
end
|
27
|
+
|
28
|
+
def search_by_inconclusive_with(_key, _operator, policy_name)
|
29
|
+
search_by_policy_results policy_name, &:othered
|
30
|
+
end
|
31
|
+
|
32
|
+
def search_by_policy_results(policy_name, &selection)
|
33
|
+
cond = sanitize_policy_name(policy_name)
|
34
|
+
{ :conditions => ArfReport.arel_table[:id].in(
|
35
|
+
ArfReport.select(ArfReport.arel_table[:id])
|
36
|
+
.latest_of_policy(Policy.find_by_name cond).instance_eval(&selection).ast
|
37
|
+
).to_sql
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def search_by_last_for(key, operator, by)
|
42
|
+
by.gsub!(/[^[:alnum:]]/, '')
|
43
|
+
case by.downcase
|
44
|
+
when 'host'
|
45
|
+
{ :conditions => 'reports.id IN (
|
46
|
+
SELECT MAX(id) FROM reports sub
|
47
|
+
WHERE sub.host_id = reports.host_id)' }
|
48
|
+
when 'policy'
|
49
|
+
{ :conditions => 'reports.id IN (
|
50
|
+
SELECT latest.id
|
51
|
+
FROM foreman_openscap_policies
|
52
|
+
INNER JOIN (SELECT policy_id, MAX(reports.id) AS id
|
53
|
+
FROM reports INNER JOIN foreman_openscap_policy_arf_reports
|
54
|
+
ON reports.id = foreman_openscap_policy_arf_reports.arf_report_id
|
55
|
+
GROUP BY policy_id
|
56
|
+
) latest
|
57
|
+
ON foreman_openscap_policies.id = latest.policy_id)' }
|
58
|
+
else
|
59
|
+
fail "Cannot search last by #{by}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def sanitize_policy_name(policy_name)
|
66
|
+
sanitize_sql_for_conditions('foreman_openscap_policies.name' => policy_name)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
included do
|
71
|
+
scoped_search :in => :policy, :on => :name, :complete_value => true, :rename => :compliance_policy,
|
72
|
+
:ext_method => :search_by_policy_name
|
73
|
+
|
74
|
+
scoped_search :on => :id, :rename => :last_for, :complete_value => { :host => 0, :policy => 1 },
|
75
|
+
:only_explicit => true, :ext_method => :search_by_last_for
|
76
|
+
|
77
|
+
scoped_search :in => :policy, :on => :name, :complete_value => true, :rename => :comply_with,
|
78
|
+
:only_explicit => true, :operators => ['= '], :ext_method => :search_by_comply_with
|
79
|
+
|
80
|
+
scoped_search :in => :policy, :on => :name, :complete_value => true, :rename => :not_comply_with,
|
81
|
+
:only_explicit => true, :operators => ['= '], :ext_method => :search_by_not_comply_with
|
82
|
+
|
83
|
+
scoped_search :in => :policy, :on => :name, :complete_value => true, :rename => :inconclusive_with,
|
84
|
+
:only_explicit => true, :operators => ['= '], :ext_method => :search_by_inconclusive_with
|
85
|
+
|
86
|
+
compliance_status_scoped_search 'passed', :on => :status, :rename => :compliance_passed
|
87
|
+
compliance_status_scoped_search 'failed', :on => :status, :rename => :compliance_failed
|
88
|
+
compliance_status_scoped_search 'othered', :on => :status, :rename => :compliance_othered
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -1,24 +1,53 @@
|
|
1
|
-
require 'scaptimony/asset'
|
2
|
-
|
3
1
|
module ForemanOpenscap
|
4
2
|
module HostExtensions
|
5
3
|
extend ActiveSupport::Concern
|
6
4
|
::Host::Managed::Jail.allow :policies_enc
|
7
5
|
|
8
6
|
included do
|
9
|
-
has_one :asset, :as => :assetable, :class_name => "::
|
10
|
-
has_many :asset_policies, :through => :asset, :class_name => "::
|
11
|
-
has_many :policies, :through => :asset_policies, :class_name => "::
|
12
|
-
has_many :arf_reports, :
|
7
|
+
has_one :asset, :as => :assetable, :class_name => "::ForemanOpenscap::Asset"
|
8
|
+
has_many :asset_policies, :through => :asset, :class_name => "::ForemanOpenscap::AssetPolicy"
|
9
|
+
has_many :policies, :through => :asset_policies, :class_name => "::ForemanOpenscap::Policy"
|
10
|
+
has_many :arf_reports, :class_name => '::ForemanOpenscap::ArfReport', :foreign_key => :host_id
|
11
|
+
has_one :compliance_status_object, :class_name => '::ForemanOpenscap::ComplianceStatus', :foreign_key => 'host_id'
|
13
12
|
|
14
13
|
scoped_search :in => :policies, :on => :name, :complete_value => true, :rename => :'compliance_policy',
|
15
14
|
:only_explicit => true, :operators => ['= ', '!= '], :ext_method => :search_by_policy_name
|
15
|
+
|
16
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
|
+
|
19
|
+
scoped_search :in => :compliance_status_object, :on => :status, :rename => :compliance_status,
|
20
|
+
:complete_value => {:compliant => ::ForemanOpenscap::ComplianceStatus::COMPLIANT,
|
21
|
+
:incompliant => ::ForemanOpenscap::ComplianceStatus::INCOMPLIANT,
|
22
|
+
:inconclusive => ::ForemanOpenscap::ComplianceStatus::INCONCLUSIVE}
|
23
|
+
|
24
|
+
scope :comply_with, lambda { |policy|
|
25
|
+
joins(:arf_reports).merge(ArfReport.latest_of_policy policy).merge(ArfReport.passed)
|
26
|
+
}
|
27
|
+
|
28
|
+
scope :incomply_with, lambda { |policy|
|
29
|
+
joins(:arf_reports).merge(ArfReport.latest_of_policy policy).merge(ArfReport.failed)
|
30
|
+
}
|
31
|
+
|
32
|
+
scope :inconclusive_with, lambda { |policy|
|
33
|
+
joins(:arf_reports).merge(ArfReport.latest_of_policy policy).merge(ArfReport.othered)
|
34
|
+
}
|
35
|
+
|
36
|
+
scope :policy_reports_missing, lambda { |policy|
|
37
|
+
where("id NOT IN (SELECT host_id
|
38
|
+
FROM reports INNER JOIN foreman_openscap_policy_arf_reports
|
39
|
+
ON reports.id = foreman_openscap_policy_arf_reports.arf_report_id
|
40
|
+
WHERE policy_id = #{policy.id})
|
41
|
+
AND id IN (SELECT assetable_id
|
42
|
+
FROM foreman_openscap_asset_policies INNER JOIN foreman_openscap_assets
|
43
|
+
ON foreman_openscap_asset_policies.asset_id = foreman_openscap_assets.id
|
44
|
+
WHERE foreman_openscap_assets.assetable_type = 'Host::Base'
|
45
|
+
AND foreman_openscap_asset_policies.policy_id = '#{policy.id}')")
|
46
|
+
}
|
18
47
|
end
|
19
48
|
|
20
49
|
def get_asset
|
21
|
-
|
50
|
+
ForemanOpenscap::Asset.where(:assetable_type => 'Host::Base', :assetable_id => id).first_or_create!
|
22
51
|
end
|
23
52
|
|
24
53
|
def policies_enc
|
@@ -30,30 +59,57 @@ module ForemanOpenscap
|
|
30
59
|
combined.uniq
|
31
60
|
end
|
32
61
|
|
62
|
+
def scap_status_changed?(policy)
|
63
|
+
last_reports = reports_for_policy(policy, 2)
|
64
|
+
return false if last_reports.length != 2
|
65
|
+
!last_reports.first.equal? last_reports.last
|
66
|
+
end
|
67
|
+
|
68
|
+
def last_report_for_policy(policy)
|
69
|
+
reports_for_policy(policy, 1)
|
70
|
+
end
|
71
|
+
|
72
|
+
def reports_for_policy(policy, limit = nil)
|
73
|
+
if limit
|
74
|
+
ForemanOpenscap::ArfReport.joins(:policy_arf_report)
|
75
|
+
.merge(ForemanOpenscap::PolicyArfReport.of_policy policy.id).where(:host_id => id).limit limit
|
76
|
+
else
|
77
|
+
ForemanOpenscap::ArfReport.joins(:policy_arf_report)
|
78
|
+
.merge(ForemanOpenscap::PolicyArfReport.of_policy policy.id).where(:host_id => id)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def compliance_status(options = {})
|
83
|
+
@compliance_status ||= get_status(ForemanOpenscap::ComplianceStatus).to_status(options)
|
84
|
+
end
|
85
|
+
|
86
|
+
def compliance_status_label(options = {})
|
87
|
+
@compliance_status_label ||= get_status(ForemanOpenscap::ComplianceStatus).to_label(options)
|
88
|
+
end
|
89
|
+
|
33
90
|
module ClassMethods
|
34
91
|
def search_by_policy_name(key, operator, policy_name)
|
35
|
-
cond = sanitize_sql_for_conditions(["
|
92
|
+
cond = sanitize_sql_for_conditions(["foreman_openscap_policies.name #{operator} ?", value_to_sql(operator, policy_name)])
|
36
93
|
{ :conditions => Host::Managed.arel_table[:id].in(
|
37
94
|
Host::Managed.select(Host::Managed.arel_table[:id]).joins(:policies).where(cond).ast
|
38
95
|
).to_sql }
|
39
96
|
end
|
40
97
|
|
41
98
|
def search_by_missing_arf(key, operator, policy_name)
|
42
|
-
cond = sanitize_sql_for_conditions(["
|
99
|
+
cond = sanitize_sql_for_conditions(["foreman_openscap_policies.name #{operator} ?", value_to_sql(operator, policy_name)])
|
43
100
|
{ :conditions => Host::Managed.arel_table[:id].in(
|
44
101
|
Host::Managed.select(Host::Managed.arel_table[:id])
|
45
102
|
.joins(:policies)
|
46
103
|
.where(cond)
|
47
|
-
.where(
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
.ast
|
54
|
-
).to_sql
|
104
|
+
.where("foreman_openscap_assets.id NOT IN (
|
105
|
+
SELECT DISTINCT foreman_openscap_arf_reports.asset_id
|
106
|
+
FROM foreman_openscap_arf_reports
|
107
|
+
WHERE foreman_openscap_arf_reports.asset_id = foreman_openscap_assets.id
|
108
|
+
AND foreman_openscap_arf_reports.policy_id = foreman_openscap_policies.id)
|
109
|
+
").ast).to_sql
|
55
110
|
}
|
56
111
|
end
|
112
|
+
|
57
113
|
end
|
58
114
|
end
|
59
115
|
end
|