foreman_openscap 4.2.0 → 4.3.0

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.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/compliance/oval_contents_controller.rb +72 -0
  3. data/app/controllers/api/v2/compliance/oval_policies_controller.rb +111 -0
  4. data/app/controllers/api/v2/compliance/oval_reports_controller.rb +47 -0
  5. data/app/controllers/concerns/foreman/controller/parameters/oval_content.rb +22 -0
  6. data/app/controllers/concerns/foreman/controller/parameters/oval_policy.rb +22 -0
  7. data/app/controllers/concerns/foreman_openscap/hosts_controller_extensions.rb +1 -1
  8. data/app/graphql/types/cve.rb +17 -0
  9. data/app/graphql/types/oval_content.rb +17 -0
  10. data/app/graphql/types/oval_policy.rb +21 -0
  11. data/app/helpers/arf_reports_helper.rb +0 -14
  12. data/app/mailers/foreman_openscap/policy_mailer.rb +2 -2
  13. data/app/models/concerns/foreman_openscap/compliance_status_scoped_search.rb +1 -1
  14. data/app/models/concerns/foreman_openscap/data_stream_content.rb +0 -17
  15. data/app/models/concerns/foreman_openscap/host_extensions.rb +11 -11
  16. data/app/models/concerns/foreman_openscap/hostgroup_extensions.rb +3 -5
  17. data/app/models/concerns/foreman_openscap/inherited_policies.rb +11 -0
  18. data/app/models/concerns/foreman_openscap/oval_facet_host_extensions.rb +38 -0
  19. data/app/models/concerns/foreman_openscap/oval_facet_hostgroup_extensions.rb +15 -0
  20. data/app/models/concerns/foreman_openscap/policy_common.rb +75 -0
  21. data/app/models/concerns/foreman_openscap/scap_file_content.rb +24 -0
  22. data/app/models/foreman_openscap/cve.rb +23 -0
  23. data/app/models/foreman_openscap/host/oval_facet.rb +14 -0
  24. data/app/models/foreman_openscap/host_cve.rb +7 -0
  25. data/app/models/foreman_openscap/hostgroup/oval_facet.rb +14 -0
  26. data/app/models/foreman_openscap/hostgroup_oval_facet_oval_policy.rb +6 -0
  27. data/app/models/foreman_openscap/oval_content.rb +26 -0
  28. data/app/models/foreman_openscap/oval_facet_oval_policy.rb +6 -0
  29. data/app/models/foreman_openscap/oval_policy.rb +54 -0
  30. data/app/models/foreman_openscap/oval_status.rb +45 -0
  31. data/app/models/foreman_openscap/policy.rb +7 -69
  32. data/app/models/foreman_openscap/scap_content.rb +1 -0
  33. data/app/models/foreman_openscap/tailoring_file.rb +1 -0
  34. data/app/services/foreman_openscap/client_config/ansible.rb +39 -6
  35. data/app/services/foreman_openscap/client_config/base.rb +5 -1
  36. data/app/services/foreman_openscap/client_config/puppet.rb +2 -1
  37. data/app/services/foreman_openscap/config_name_service.rb +1 -1
  38. data/app/services/foreman_openscap/hostgroup_overrider.rb +2 -24
  39. data/app/services/foreman_openscap/hostgroup_overrider_common.rb +28 -0
  40. data/app/services/foreman_openscap/lookup_key_overrider.rb +30 -62
  41. data/app/services/foreman_openscap/lookup_key_overrides_common.rb +63 -0
  42. data/app/services/foreman_openscap/oval/check_collection.rb +45 -0
  43. data/app/services/foreman_openscap/oval/configure.rb +80 -0
  44. data/app/services/foreman_openscap/oval/cves.rb +41 -0
  45. data/app/services/foreman_openscap/oval/setup.rb +93 -0
  46. data/app/services/foreman_openscap/oval/setup_check.rb +55 -0
  47. data/app/services/foreman_openscap/oval/sync_oval_contents.rb +42 -0
  48. data/app/views/api/v2/compliance/oval_contents/base.json.rabl +6 -0
  49. data/app/views/api/v2/compliance/oval_contents/create.json.rabl +3 -0
  50. data/app/views/api/v2/compliance/oval_contents/index.json.rabl +3 -0
  51. data/app/views/api/v2/compliance/oval_contents/show.json.rabl +3 -0
  52. data/app/views/api/v2/compliance/oval_contents/sync.json.rabl +3 -0
  53. data/app/views/api/v2/compliance/oval_contents/sync_result.json.rabl +11 -0
  54. data/app/views/api/v2/compliance/oval_contents/update.json.rabl +3 -0
  55. data/app/views/api/v2/compliance/oval_policies/create.json.rabl +3 -0
  56. data/app/views/api/v2/compliance/oval_policies/index.json.rabl +3 -0
  57. data/app/views/api/v2/compliance/oval_policies/main.json.rabl +15 -0
  58. data/app/views/api/v2/compliance/oval_policies/show.json.rabl +3 -0
  59. data/app/views/api/v2/compliance/policies/base.json.rabl +2 -2
  60. data/app/views/api/v2/compliance/policies_common/_attrs.json.rabl +2 -0
  61. data/app/views/arf_reports/_output.html.erb +9 -1
  62. data/app/views/job_templates/run_oval_scans.erb +24 -0
  63. data/app/views/policies/steps/_deployment_options_form.html.erb +2 -2
  64. data/config/initializers/inflections.rb +12 -0
  65. data/config/routes.rb +19 -0
  66. data/db/migrate/20201019074925_create_oval_policy.rb +13 -0
  67. data/db/migrate/20201020113801_create_oval_facet.rb +14 -0
  68. data/db/migrate/20201021084109_create_hostgroup_oval_facet.rb +14 -0
  69. data/db/migrate/20201106080924_create_oval_content.rb +12 -0
  70. data/db/migrate/20201116110256_add_oval_content_to_oval_policy.rb +5 -0
  71. data/db/migrate/20201120080329_create_cves.rb +13 -0
  72. data/db/migrate/20201202110213_update_puppet_port_param_type.rb +2 -6
  73. data/db/migrate/20201217130800_add_has_errata_to_cve.rb +8 -0
  74. data/db/migrate/20201217161511_add_url_to_oval_content.rb +5 -0
  75. data/db/migrate/20210409095625_add_oval_policy_reference_to_cve.rb +7 -0
  76. data/lib/foreman_openscap/engine.rb +67 -9
  77. data/lib/foreman_openscap/version.rb +1 -1
  78. data/lib/tasks/foreman_openscap_tasks.rake +14 -9
  79. data/locale/de/LC_MESSAGES/foreman_openscap.mo +0 -0
  80. data/locale/de/foreman_openscap.edit.po +0 -0
  81. data/locale/de/foreman_openscap.po +215 -17
  82. data/locale/en_GB/LC_MESSAGES/foreman_openscap.mo +0 -0
  83. data/locale/en_GB/foreman_openscap.edit.po +0 -0
  84. data/locale/en_GB/foreman_openscap.po +213 -15
  85. data/locale/es/LC_MESSAGES/foreman_openscap.mo +0 -0
  86. data/locale/es/foreman_openscap.edit.po +0 -0
  87. data/locale/es/foreman_openscap.po +239 -41
  88. data/locale/foreman_openscap.pot +395 -112
  89. data/locale/fr/LC_MESSAGES/foreman_openscap.mo +0 -0
  90. data/locale/fr/foreman_openscap.edit.po +0 -0
  91. data/locale/fr/foreman_openscap.po +243 -45
  92. data/locale/gl/LC_MESSAGES/foreman_openscap.mo +0 -0
  93. data/locale/gl/foreman_openscap.edit.po +0 -0
  94. data/locale/gl/foreman_openscap.po +213 -15
  95. data/locale/it/LC_MESSAGES/foreman_openscap.mo +0 -0
  96. data/locale/it/foreman_openscap.edit.po +0 -0
  97. data/locale/it/foreman_openscap.po +213 -15
  98. data/locale/ja/LC_MESSAGES/foreman_openscap.mo +0 -0
  99. data/locale/ja/foreman_openscap.edit.po +0 -0
  100. data/locale/ja/foreman_openscap.po +262 -66
  101. data/locale/ko/LC_MESSAGES/foreman_openscap.mo +0 -0
  102. data/locale/ko/foreman_openscap.edit.po +0 -0
  103. data/locale/ko/foreman_openscap.po +214 -16
  104. data/locale/pt_BR/LC_MESSAGES/foreman_openscap.mo +0 -0
  105. data/locale/pt_BR/foreman_openscap.edit.po +0 -0
  106. data/locale/pt_BR/foreman_openscap.po +252 -54
  107. data/locale/ru/LC_MESSAGES/foreman_openscap.mo +0 -0
  108. data/locale/ru/foreman_openscap.edit.po +0 -0
  109. data/locale/ru/foreman_openscap.po +214 -16
  110. data/locale/sv_SE/LC_MESSAGES/foreman_openscap.mo +0 -0
  111. data/locale/sv_SE/foreman_openscap.edit.po +0 -0
  112. data/locale/sv_SE/foreman_openscap.po +213 -15
  113. data/locale/zh_CN/LC_MESSAGES/foreman_openscap.mo +0 -0
  114. data/locale/zh_CN/foreman_openscap.edit.po +0 -0
  115. data/locale/zh_CN/foreman_openscap.po +369 -169
  116. data/locale/zh_TW/LC_MESSAGES/foreman_openscap.mo +0 -0
  117. data/locale/zh_TW/foreman_openscap.edit.po +0 -0
  118. data/locale/zh_TW/foreman_openscap.po +214 -16
  119. data/test/factories/compliance_host_factory.rb +12 -0
  120. data/test/factories/oval_content_factory.rb +7 -0
  121. data/test/factories/oval_policy_factory.rb +9 -0
  122. data/test/files/oval_contents/ansible-2.9.oval.xml.bz2 +0 -0
  123. data/test/fixtures/cve_fixtures.rb +104 -0
  124. data/test/functional/api/v2/compliance/oval_contents_controller_test.rb +39 -0
  125. data/test/functional/api/v2/compliance/oval_policies_controller_test.rb +141 -0
  126. data/test/functional/api/v2/compliance/oval_reports_controller_test.rb +32 -0
  127. data/test/graphql/queries/oval_contents_query_test.rb +35 -0
  128. data/test/graphql/queries/oval_policies_query_test.rb +35 -0
  129. data/test/test_plugin_helper.rb +4 -0
  130. data/test/unit/oval_host_test.rb +45 -0
  131. data/test/unit/oval_policy_test.rb +133 -0
  132. data/test/unit/oval_status_test.rb +47 -0
  133. data/test/unit/services/oval/cves_test.rb +81 -0
  134. data/test/unit/services/oval/setup_test.rb +87 -0
  135. metadata +97 -3
@@ -151,13 +151,13 @@ module ForemanOpenscap
151
151
  def search_by_removed_from_policy(key, operator, policy_name)
152
152
  policy = ForemanOpenscap::Policy.find_by :name => policy_name
153
153
  host_ids = policy ? removed_from_policy(policy).pluck(:id) : []
154
- { :conditions => Host::Managed.arel_table[:id].in(host_ids).to_sql }
154
+ { :conditions => ::Host::Managed.arel_table[:id].in(host_ids).to_sql }
155
155
  end
156
156
 
157
157
  def search_by_compliance(key, operator, policy_name, method)
158
158
  policy = ForemanOpenscap::Policy.find_by :name => policy_name
159
159
  host_ids = policy ? public_send(method, policy).pluck(:id) : []
160
- { :conditions => Host::Managed.arel_table[:id].in(host_ids).to_sql }
160
+ { :conditions => ::Host::Managed.arel_table[:id].in(host_ids).to_sql }
161
161
  end
162
162
 
163
163
  def search_by_comply_with(key, operator, policy_name)
@@ -185,12 +185,12 @@ module ForemanOpenscap
185
185
  end
186
186
 
187
187
  def search_by_rule(rule_name, rule_result)
188
- query = Host.joins(:arf_reports)
189
- .merge(ArfReport.latest
190
- .by_rule_result(rule_name, rule_result)
191
- .unscope(:order))
192
- .distinct
193
- .select(Host.arel_table[:id]).to_sql
188
+ query = ::Host.joins(:arf_reports)
189
+ .merge(ArfReport.latest
190
+ .by_rule_result(rule_name, rule_result)
191
+ .unscope(:order))
192
+ .distinct
193
+ .select(::Host.arel_table[:id]).to_sql
194
194
 
195
195
  query_conditions query
196
196
  end
@@ -208,7 +208,7 @@ module ForemanOpenscap
208
208
  else
209
209
  ''
210
210
  end
211
- { :conditions => Host::Managed.arel_table[:id].in(Host::Managed.select(Host::Managed.arel_table[:id]).joins(:policies).where(cond).pluck(:id)).to_sql + host_group_cond }
211
+ { :conditions => ::Host::Managed.arel_table[:id].in(::Host::Managed.select(::Host::Managed.arel_table[:id]).joins(:policies).where(cond).pluck(:id)).to_sql + host_group_cond }
212
212
  end
213
213
 
214
214
  def search_by_policy_id(key, operator, policy_id)
@@ -249,8 +249,8 @@ module ForemanOpenscap
249
249
  .joins(:policies)
250
250
  .where(condition)
251
251
  .pluck(:assetable_id)
252
- subtree_ids = Hostgroup.where(:id => hostgroup_with_policy_ids).flat_map(&:subtree_ids).uniq
253
- Host.where(:hostgroup_id => subtree_ids).where.not(:id => host_ids_from_arf).pluck(:id)
252
+ subtree_ids = ::Hostgroup.where(:id => hostgroup_with_policy_ids).flat_map(&:subtree_ids).uniq
253
+ ::Host.where(:hostgroup_id => subtree_ids).where.not(:id => host_ids_from_arf).pluck(:id)
254
254
  end
255
255
  end
256
256
  end
@@ -2,6 +2,8 @@ module ForemanOpenscap
2
2
  module HostgroupExtensions
3
3
  extend ActiveSupport::Concern
4
4
 
5
+ include InheritedPolicies
6
+
5
7
  included do
6
8
  has_one :asset, :as => :assetable, :class_name => "::ForemanOpenscap::Asset", dependent: :destroy
7
9
  has_many :asset_policies, :through => :asset, :class_name => "::ForemanOpenscap::AssetPolicy"
@@ -9,11 +11,7 @@ module ForemanOpenscap
9
11
  end
10
12
 
11
13
  def inherited_policies
12
- return [] unless parent
13
-
14
- ancestors.inject([]) do |policies, hostgroup|
15
- policies += hostgroup.policies
16
- end.uniq
14
+ find_inherited_policies :policies
17
15
  end
18
16
 
19
17
  def openscap_proxy
@@ -0,0 +1,11 @@
1
+ module ForemanOpenscap
2
+ module InheritedPolicies
3
+ def find_inherited_policies(policy_attr)
4
+ return [] unless parent
5
+
6
+ ancestors.reduce([]) do |policies, hostgroup|
7
+ policies += hostgroup.public_send(policy_attr)
8
+ end.uniq
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,38 @@
1
+ module ForemanOpenscap
2
+ module OvalFacetHostExtensions
3
+ extend ActiveSupport::Concern
4
+
5
+ ::Host::Managed::Jail.allow :oval_policies_enc, :oval_policies_enc_raw, :cves, :cves_without_errata
6
+
7
+ included do
8
+ has_many :oval_policies, :through => :oval_facet, :class_name => 'ForemanOpenscap::OvalPolicy'
9
+
10
+ has_many :host_cves, :class_name => 'ForemanOpenscap::HostCve', :foreign_key => :host_id
11
+ has_many :cves, :through => :host_cves, :class_name => 'ForemanOpenscap::Cve', :source => :cve
12
+
13
+ scoped_search :relation => :host_cves, :on => :cve_id, :rename => :cve_id, :complete_value => false
14
+ end
15
+
16
+ def cves_without_errata
17
+ cves.where(:has_errata => false)
18
+ end
19
+
20
+ def cves_with_errata
21
+ cves.where(:has_errata => true)
22
+ end
23
+
24
+ def combined_oval_policies
25
+ combined = oval_policies
26
+ combined += hostgroup.oval_policies + hostgroup.inherited_oval_policies if hostgroup
27
+ combined.uniq
28
+ end
29
+
30
+ def oval_policies_enc_raw
31
+ combined_oval_policies.map(&:to_enc)
32
+ end
33
+
34
+ def oval_policies_enc
35
+ oval_policies_enc_raw.to_json
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,15 @@
1
+ module ForemanOpenscap
2
+ module OvalFacetHostgroupExtensions
3
+ extend ActiveSupport::Concern
4
+
5
+ include InheritedPolicies
6
+
7
+ included do
8
+ has_many :oval_policies, :through => :oval_facet, :class_name => 'ForemanOpenscap::OvalPolicy'
9
+ end
10
+
11
+ def inherited_oval_policies
12
+ find_inherited_policies :oval_policies
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,75 @@
1
+ module ForemanOpenscap
2
+ module PolicyCommon
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ before_validation :update_period_attrs
7
+ end
8
+
9
+ def cron_line_split
10
+ cron_line.to_s.split(' ')
11
+ end
12
+
13
+ def valid_cron_line
14
+ if period == 'custom'
15
+ errors.add(:cron_line, _("does not consist of 5 parts separated by space")) unless cron_line_split.size == 5
16
+ end
17
+ end
18
+
19
+ def valid_weekday
20
+ if period == 'weekly'
21
+ errors.add(:weekday, _("is not a valid value")) unless Date::DAYNAMES.map(&:downcase).include? weekday
22
+ end
23
+ end
24
+
25
+ def valid_day_of_month
26
+ if period == 'monthly'
27
+ errors.add(:day_of_month, _("must be between 1 and 31")) if !day_of_month || (day_of_month < 1 || day_of_month > 31)
28
+ end
29
+ end
30
+
31
+ def update_period_attrs
32
+ case period
33
+ when 'monthly'
34
+ erase_period_attrs(%w[cron_line weekday])
35
+ when 'weekly'
36
+ erase_period_attrs(%w[cron_line day_of_month])
37
+ when 'custom'
38
+ erase_period_attrs(%w[weekday day_of_month])
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def erase_period_attrs(attrs)
45
+ attrs.each { |attr| self.public_send("#{attr}=", nil) }
46
+ end
47
+
48
+ def period_enc
49
+ # get crontab expression as an array (minute hour day_of_month month day_of_week)
50
+ cron_parts = case period
51
+ when 'weekly'
52
+ ['0', '1', '*', '*', weekday_number.to_s]
53
+ when 'monthly'
54
+ ['0', '1', day_of_month.to_s, '*', '*']
55
+ when 'custom'
56
+ cron_line_split
57
+ else
58
+ raise 'invalid period specification'
59
+ end
60
+
61
+ {
62
+ 'minute' => cron_parts[0],
63
+ 'hour' => cron_parts[1],
64
+ 'monthday' => cron_parts[2],
65
+ 'month' => cron_parts[3],
66
+ 'weekday' => cron_parts[4],
67
+ }
68
+ end
69
+
70
+ def weekday_number
71
+ # 0 is sunday, 1 is monday in cron, while DAYS_INTO_WEEK has 0 as monday, 6 as sunday
72
+ (Date::DAYS_INTO_WEEK.with_indifferent_access[weekday] + 1) % 7
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,24 @@
1
+ module ForemanOpenscap
2
+ module ScapFileContent
3
+ require 'digest/sha2'
4
+
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ validates :digest, :presence => true
9
+ validates :scap_file, :presence => true
10
+
11
+ before_validation :redigest, :if => lambda { |file_content| file_content.persisted? && file_content.scap_file_changed? }
12
+ end
13
+
14
+ def digest
15
+ self[:digest] ||= Digest::SHA256.hexdigest(scap_file.to_s)
16
+ end
17
+
18
+ private
19
+
20
+ def redigest
21
+ self[:digest] = Digest::SHA256.hexdigest(scap_file.to_s)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ module ForemanOpenscap
2
+ class Cve < ApplicationRecord
3
+ has_many :host_cves
4
+ has_many :hosts, :through => :host_cves
5
+ has_many :oval_policies, :through => :host_cves
6
+
7
+ scoped_search :relation => :host_cves, :on => :oval_policy_id, :rename => :oval_policy_id, :complete_value => false
8
+
9
+ scope :of_oval_policy, ->(policy_id) {
10
+ joins(:host_cves).where(:foreman_openscap_host_cves => { :oval_policy_id => policy_id })
11
+ }
12
+
13
+ scope :of_host, ->(host_id) {
14
+ joins(:host_cves).where(:foreman_openscap_host_cves => { :host_id => host_id })
15
+ }
16
+
17
+ validates :ref_id, :ref_url, :definition_id, :presence => true
18
+
19
+ class Jail < ::Safemode::Jail
20
+ allow :ref_id, :ref_url
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,14 @@
1
+ module ForemanOpenscap
2
+ module Host
3
+ class OvalFacet < ApplicationRecord
4
+ self.table_name = 'foreman_openscap_oval_facets'
5
+
6
+ include Facets::Base
7
+
8
+ validates :host, :presence => true, :allow_blank => false
9
+
10
+ has_many :oval_facet_oval_policies, :dependent => :destroy, :class_name => 'ForemanOpenscap::OvalFacetOvalPolicy'
11
+ has_many :oval_policies, :through => :oval_facet_oval_policies, :class_name => 'ForemanOpenscap::OvalPolicy'
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ module ForemanOpenscap
2
+ class HostCve < ApplicationRecord
3
+ belongs_to_host
4
+ belongs_to :cve
5
+ belongs_to :oval_policy
6
+ end
7
+ end
@@ -0,0 +1,14 @@
1
+ module ForemanOpenscap
2
+ module Hostgroup
3
+ class OvalFacet < ApplicationRecord
4
+ self.table_name = 'foreman_openscap_hostgroup_oval_facets'
5
+
6
+ include Facets::HostgroupFacet
7
+
8
+ validates :hostgroup, :presence => true, :allow_blank => false
9
+
10
+ has_many :hostgroup_oval_facet_oval_policies, :dependent => :destroy, :class_name => 'ForemanOpenscap::HostgroupOvalFacetOvalPolicy'
11
+ has_many :oval_policies, :through => :hostgroup_oval_facet_oval_policies, :class_name => 'ForemanOpenscap::OvalPolicy'
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,6 @@
1
+ module ForemanOpenscap
2
+ class HostgroupOvalFacetOvalPolicy < ApplicationRecord
3
+ belongs_to :oval_policy
4
+ belongs_to :oval_facet, :class_name => 'ForemanOpenscap::Hostgroup::OvalFacet'
5
+ end
6
+ end
@@ -0,0 +1,26 @@
1
+ module ForemanOpenscap
2
+ class OvalContent < ApplicationRecord
3
+ audited :except => [:scap_file]
4
+ include Authorizable
5
+ include Taxonomix
6
+ include ScapFileContent
7
+
8
+ scoped_search :on => :name, :complete_value => true
9
+
10
+ has_many :oval_policies
11
+ validates :name, :presence => true, :length => { :maximum => 255 }, uniqueness: true
12
+ validates :url, :format => { :with => %r{\Ahttps?://} }, :allow_blank => true
13
+
14
+ before_validation :fetch_remote_content, :if => lambda { |oval_content| oval_content.url.present? }
15
+
16
+ def to_h
17
+ { :id => id, :name => name, :original_filename => original_filename, :changed_at => changed_at }
18
+ end
19
+
20
+ private
21
+
22
+ def fetch_remote_content
23
+ ForemanOpenscap::Oval::SyncOvalContents.new.sync self
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,6 @@
1
+ module ForemanOpenscap
2
+ class OvalFacetOvalPolicy < ApplicationRecord
3
+ belongs_to :oval_policy
4
+ belongs_to :oval_facet, :class_name => 'ForemanOpenscap::Host::OvalFacet'
5
+ end
6
+ end
@@ -0,0 +1,54 @@
1
+ module ForemanOpenscap
2
+ class OvalPolicy < ApplicationRecord
3
+ graphql_type '::Types::OvalPolicy'
4
+
5
+ audited
6
+ include Authorizable
7
+ include Taxonomix
8
+
9
+ include PolicyCommon
10
+
11
+ belongs_to :oval_content
12
+
13
+ validates :name, :presence => true, :uniqueness => true, :length => { :maximum => 255 }
14
+ validates :period, :inclusion => { :in => %w[weekly monthly custom], :message => _('is not a valid value') }
15
+ validate :valid_cron_line, :valid_weekday, :valid_day_of_month
16
+ validates :oval_content, :presence => true
17
+
18
+ has_many :oval_facet_oval_policies, :class_name => 'ForemanOpenscap::OvalFacetOvalPolicy'
19
+ has_many :oval_facets, :through => :oval_facet_oval_policies, :class_name => 'ForemanOpenscap::Host::OvalFacet'
20
+ has_many :hosts, :through => :oval_facets
21
+
22
+ has_many :hostgroup_oval_facet_oval_policies, :class_name => 'ForemanOpenscap::HostgroupOvalFacetOvalPolicy'
23
+ has_many :hostgroup_oval_facets, :through => :hostgroup_oval_facet_oval_policies, :class_name => 'ForemanOpenscap::Hostgroup::OvalFacet', :source => :oval_facet
24
+ has_many :hostgroups, :through => :hostgroup_oval_facets
25
+
26
+ has_many :host_cves
27
+ has_many :cves, :through => :host_cves
28
+
29
+ def host_ids=(host_ids)
30
+ self.oval_facets = facets_to_assign(host_ids, :host_id, ForemanOpenscap::Host::OvalFacet)
31
+ end
32
+
33
+ def hostgroup_ids=(hostgroup_ids)
34
+ self.hostgroup_oval_facets = facets_to_assign(hostgroup_ids, :hostgroup_id, ForemanOpenscap::Hostgroup::OvalFacet)
35
+ end
36
+
37
+ def to_enc
38
+ {
39
+ :id => id,
40
+ :oval_content_path => "/var/lib/openscap/oval_content/#{oval_content.digest}.oval.xml.bz2",
41
+ :download_path => "/compliance/oval_policies/#{id}/oval_content/#{oval_content.digest}"
42
+ }.merge(period_enc).with_indifferent_access
43
+ end
44
+
45
+ private
46
+
47
+ def facets_to_assign(ids, key, facet_class)
48
+ filtered_ids = ids.uniq.reject { |id| respond_to?(:empty) && id.empty? }
49
+ existing_facets = facet_class.where(key => filtered_ids)
50
+ new_facets = (filtered_ids - existing_facets.pluck(key)).map { |id| facet_class.new(key => id) }
51
+ existing_facets + new_facets
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,45 @@
1
+ module ForemanOpenscap
2
+ class OvalStatus < ::HostStatus::Status
3
+ PATCHED = 0
4
+ VULNERABLE = 1
5
+ PATCH_AVAILABLE = 2
6
+
7
+ def self.status_name
8
+ N_('OVAL scan')
9
+ end
10
+
11
+ def to_label(options = {})
12
+ case to_status
13
+ when PATCHED
14
+ N_('No Vulnerabilities found')
15
+ when VULNERABLE
16
+ N_("%s vulnerabilities found") % host.cves_without_errata.count
17
+ when PATCH_AVAILABLE
18
+ N_("%s vulnerabilities with available patch found") % host.cves_with_errata.count
19
+ else
20
+ N_('Unknown OVAL status')
21
+ end
22
+ end
23
+
24
+ def to_global(options = {})
25
+ case to_status
26
+ when PATCHED
27
+ ::HostStatus::Global::OK
28
+ when VULNERABLE
29
+ ::HostStatus::Global::WARN
30
+ when PATCH_AVAILABLE
31
+ ::HostStatus::Global::ERROR
32
+ end
33
+ end
34
+
35
+ def relevant?(options = {})
36
+ host.combined_oval_policies.any?
37
+ end
38
+
39
+ def to_status(options = {})
40
+ return PATCH_AVAILABLE if host.cves_with_errata.any?
41
+ return VULNERABLE if host.cves_without_errata.any?
42
+ PATCHED
43
+ end
44
+ end
45
+ end