foreman_rh_cloud 2.0.7 → 2.0.8

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 (98) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/foreman_inventory_upload/accounts_controller.rb +1 -0
  3. data/app/controllers/foreman_inventory_upload/uploads_controller.rb +22 -3
  4. data/app/controllers/foreman_rh_cloud/react_controller.rb +3 -0
  5. data/app/controllers/insights_cloud/tasks_controller.rb +8 -0
  6. data/app/helpers/foreman_inventory_upload_host_helper.rb +11 -0
  7. data/app/models/insights_facet.rb +3 -0
  8. data/app/models/insights_hit.rb +6 -0
  9. data/app/models/setting/rh_cloud.rb +1 -0
  10. data/app/overrides/hosts_list.rb +13 -0
  11. data/app/views/foreman_rh_cloud/react/insights_cloud.html.erb +1 -0
  12. data/config/routes.rb +7 -0
  13. data/db/migrate/20191215104806_create_insights_hits.foreman_inventory_upload.rb +14 -0
  14. data/db/migrate/20191216062008_create_insights_facets.foreman_inventory_upload.rb +7 -0
  15. data/lib/foreman_inventory_upload/generators/fact_helpers.rb +1 -1
  16. data/lib/foreman_inventory_upload/generators/slice.rb +1 -0
  17. data/lib/foreman_inventory_upload/notifications/manifest_import_success_notification_override.rb +19 -0
  18. data/lib/foreman_rh_cloud/engine.rb +21 -9
  19. data/lib/foreman_rh_cloud/version.rb +1 -1
  20. data/lib/insights_cloud.rb +15 -0
  21. data/lib/insights_cloud/async/insights_full_sync.rb +92 -0
  22. data/test/jobs/insights_full_sync_test.rb +62 -0
  23. data/test/unit/slice_generator_test.rb +8 -1
  24. data/webpack/ForemanInventoryUpload/Components/AccountList/AccountList.fixtures.js +6 -0
  25. data/webpack/ForemanInventoryUpload/Components/AccountList/AccountListActions.js +2 -1
  26. data/webpack/ForemanInventoryUpload/Components/AccountList/AccountListReducer.js +9 -1
  27. data/webpack/ForemanInventoryUpload/Components/AccountList/AccountListSelectors.js +7 -0
  28. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/AccountListActions.test.js +8 -1
  29. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/AccountListReducer.test.js +11 -0
  30. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/AccountListSelectors.test.js +7 -2
  31. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountListActions.test.js.snap +20 -2
  32. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountListReducer.test.js.snap +10 -0
  33. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountListSelectors.test.js.snap +3 -0
  34. data/webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/AutoUploadSwitcher.js +6 -6
  35. data/webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/__tests__/__snapshots__/AutoUploadSwitcher.test.js.snap +9 -9
  36. data/webpack/ForemanInventoryUpload/Components/AutoUploadSwitcher/autoUploadSwitcher.scss +1 -1
  37. data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/DashboardActions.test.js +2 -2
  38. data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/DashboardSelectors.test.js +2 -2
  39. data/webpack/ForemanInventoryUpload/Components/HostObfuscationSwitcher/HostObfuscationSwitcher.fixtures.js +1 -0
  40. data/webpack/ForemanInventoryUpload/Components/HostObfuscationSwitcher/HostObfuscationSwitcher.js +29 -0
  41. data/webpack/ForemanInventoryUpload/Components/HostObfuscationSwitcher/HostObfuscationSwitcherActions.js +30 -0
  42. data/webpack/ForemanInventoryUpload/Components/HostObfuscationSwitcher/HostObfuscationSwitcherConstants.js +3 -0
  43. data/webpack/ForemanInventoryUpload/Components/HostObfuscationSwitcher/__tests__/HostObfuscationSwitcher.test.js +14 -0
  44. data/webpack/ForemanInventoryUpload/Components/HostObfuscationSwitcher/__tests__/HostObfuscationSwitcherActions.test.js +14 -0
  45. data/webpack/ForemanInventoryUpload/Components/HostObfuscationSwitcher/__tests__/__snapshots__/HostObfuscationSwitcher.test.js.snap +38 -0
  46. data/webpack/ForemanInventoryUpload/Components/HostObfuscationSwitcher/__tests__/__snapshots__/HostObfuscationSwitcherActions.test.js.snap +14 -0
  47. data/webpack/ForemanInventoryUpload/Components/HostObfuscationSwitcher/hostObfuscationSwitcher.scss +0 -0
  48. data/webpack/ForemanInventoryUpload/Components/HostObfuscationSwitcher/index.js +20 -0
  49. data/webpack/ForemanInventoryUpload/Components/InventoryFilter/__tests__/InventoryFilterSelectors.test.js +2 -2
  50. data/webpack/ForemanInventoryUpload/Components/InventorySettings/InventorySettings.js +15 -0
  51. data/webpack/ForemanInventoryUpload/Components/InventorySettings/__tests__/InventorySettings.test.js +13 -0
  52. data/webpack/ForemanInventoryUpload/Components/InventorySettings/__tests__/__snapshots__/InventorySettings.test.js.snap +13 -0
  53. data/webpack/ForemanInventoryUpload/Components/InventorySettings/index.js +1 -0
  54. data/webpack/ForemanInventoryUpload/Components/InventorySettings/inventorySettings.scss +15 -0
  55. data/webpack/ForemanInventoryUpload/Components/PageHeader/PageHeader.js +14 -4
  56. data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageHeader.test.js.snap +22 -3
  57. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/DocsButton/DocsButton.js +17 -0
  58. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/DocsButton/__tests__/DocsButton.test.js +12 -0
  59. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/DocsButton/__tests__/__snapshots__/DocsButton.test.js.snap +20 -0
  60. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/DocsButton/index.js +1 -0
  61. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/HistoryButton/HistoryButton.js +18 -0
  62. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/HistoryButton/__tests__/HistoryButton.test.js +12 -0
  63. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/HistoryButton/__tests__/__snapshots__/HistoryButton.test.js.snap +21 -0
  64. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/HistoryButton/index.js +1 -0
  65. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/PageDescription.js +24 -0
  66. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/__tests__/PageDescription.test.js +11 -0
  67. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/__tests__/__snapshots__/PageDescription.test.js.snap +17 -0
  68. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/index.js +1 -0
  69. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/ToolbarButtons.js +13 -0
  70. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/__tests__/ToolbarButtons.test.js +12 -0
  71. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/__tests__/__snapshots__/ToolbarButtons.test.js.snap +10 -0
  72. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/index.js +1 -0
  73. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/toolbarButtons.scss +7 -0
  74. data/webpack/ForemanInventoryUpload/ForemanInventoryConstants.js +4 -0
  75. data/webpack/ForemanInventoryUpload/ForemanInventoryHelpers.js +13 -0
  76. data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/SubscriptionsPageExtensionActions.js +34 -0
  77. data/webpack/ForemanInventoryUpload/__tests__/ForemanInventoryHelpers.test.js +2 -1
  78. data/webpack/ForemanInventoryUpload/__tests__/__snapshots__/ForemanInventoryHelpers.test.js.snap +2 -0
  79. data/webpack/ForemanRhCloudReducers.js +2 -0
  80. data/webpack/ForemanRhCloudSelectors.js +2 -0
  81. data/webpack/ForemanRhCloudTestHelpers.js +2 -1
  82. data/webpack/InsightsCloudSync/InsightsCloudSync.js +26 -0
  83. data/webpack/InsightsCloudSync/InsightsCloudSync.test.js +13 -0
  84. data/webpack/InsightsCloudSync/InsightsCloudSyncActions.js +23 -0
  85. data/webpack/InsightsCloudSync/InsightsCloudSyncConstants.js +6 -0
  86. data/webpack/InsightsCloudSync/InsightsCloudSyncHelpers.js +3 -0
  87. data/webpack/InsightsCloudSync/InsightsCloudSyncReducers.js +3 -0
  88. data/webpack/InsightsCloudSync/__snapshots__/InsightsCloudSync.test.js.snap +25 -0
  89. data/webpack/InsightsCloudSync/__tests__/InsightsCloudSyncHelpers.test.js +9 -0
  90. data/webpack/InsightsCloudSync/__tests__/__snapshots__/InsightsCloudSyncHelpers.test.js.snap +3 -0
  91. data/webpack/InsightsCloudSync/index.js +17 -0
  92. data/webpack/__tests__/ForemanRhCloudSelectors.test.js +4 -2
  93. data/webpack/__tests__/ForemanRhCloudTestHelpers.test.js +2 -2
  94. data/webpack/__tests__/__snapshots__/ForemanRhCloudSelectors.test.js.snap +9 -0
  95. data/webpack/__tests__/__snapshots__/ForemanRhCloudTestHelpers.test.js.snap +3 -0
  96. data/webpack/index.js +7 -0
  97. data/webpack/subscriptions_extension_index.js +8 -0
  98. metadata +59 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a9b4163dafd6baf15a6b8ffc04de58d1b0316114838e06ef3c3d28f043442a6c
4
- data.tar.gz: 9c8bf6874697a56d76e696397cfc11ed0f3f1379716d5b91bebc54fdc4be98a0
3
+ metadata.gz: 4b4d5750b4b0ff6361c7694fb3808a4c33d5ff12e37bd5d946c1baa454b805a1
4
+ data.tar.gz: 5e18ea289049d0525a82adb8f7cbeec66d5ac4abf2cae5867aa18c3aab753640
5
5
  SHA512:
6
- metadata.gz: 56d9d668982202c78267c8b3d2425a6b3f3695be21fe3bf993710990c0811438b7bf938298e5a5421a40374dbb862d48538811388d851621bb4dbba8a7dfa396
7
- data.tar.gz: e725d4ff38d466f6c1713822108ed9d04e08946f57fbd27032977b0ef7f4278c414d7d1c418f517a6d25b27b0e2131030ae8ba376ab27ac365729b9c60737f41
6
+ metadata.gz: 7e9b9c292ed88641c954bc79d665c7f3e77a0c04e426bde5e12d92e25d53b72ef7ade25a69b08da5f20442c3a4a41a7d8854dac529108376eae49b188c1eb839
7
+ data.tar.gz: 94998762071b568f438dd03c37f22c969a55cc2c71410bf60c2b4e21ebda259e1e20a85d6a821324014d98683f1b928cce4fe94e39a0a4f8f34dd338237252ed
@@ -22,6 +22,7 @@ module ForemanInventoryUpload
22
22
 
23
23
  render json: {
24
24
  autoUploadEnabled: Setting[:allow_auto_inventory_upload],
25
+ hostObfuscationEnabled: Setting[:obfuscate_inventory_hostnames],
25
26
  accounts: accounts,
26
27
  }, status: :ok
27
28
  end
@@ -26,13 +26,32 @@ module ForemanInventoryUpload
26
26
 
27
27
  def auto_upload
28
28
  Setting[:allow_auto_inventory_upload] = auto_upload_params
29
- render json: {
30
- autoUploadEnabled: Setting[:allow_auto_inventory_upload],
31
- }
29
+ render_setting(:autoUploadEnabled, :allow_auto_inventory_upload)
30
+ end
31
+
32
+ def show_auto_upload
33
+ render_setting(:autoUploadEnabled, :allow_auto_inventory_upload)
32
34
  end
33
35
 
34
36
  def auto_upload_params
35
37
  ActiveModel::Type::Boolean.new.cast(params.require(:value))
36
38
  end
39
+
40
+ def host_obfuscation
41
+ Setting[:obfuscate_inventory_hostnames] = host_obfuscation_params
42
+ render_setting(:hostObfuscationEnabled, :obfuscate_inventory_hostnames)
43
+ end
44
+
45
+ def host_obfuscation_params
46
+ ActiveModel::Type::Boolean.new.cast(params.require(:value))
47
+ end
48
+
49
+ private
50
+
51
+ def render_setting(node_name, setting)
52
+ render json: {
53
+ node_name => Setting[setting],
54
+ }
55
+ end
37
56
  end
38
57
  end
@@ -4,5 +4,8 @@ module ForemanRhCloud
4
4
 
5
5
  def inventory_upload
6
6
  end
7
+
8
+ def insights_cloud
9
+ end
7
10
  end
8
11
  end
@@ -0,0 +1,8 @@
1
+ module InsightsCloud
2
+ class TasksController < ::ApplicationController
3
+ def create
4
+ selected_org = Organization.current
5
+ InsightsCloud::Async::InsightsFullSync.perform_now(selected_org)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ module ForemanInventoryUploadHostHelper
2
+ def hits_counts
3
+ @hits_counts ||= InsightsHit.where(host_id: @hosts).group(:host_id).count
4
+ end
5
+
6
+ def hits_counts_cell(host)
7
+ host_hits = hits_counts[host.id]
8
+ content = n_('One recommendation', '%{hits} recommendations', host_hits) % { hits: host_hits } if host_hits
9
+ tag.td content, class: ['hidden-xs', 'ellipsis']
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ class InsightsFacet < HostFacets::Base
2
+ has_many :hits, foreign_key: :host_id, primary_key: :host_id, class_name: 'InsightsHit'
3
+ end
@@ -0,0 +1,6 @@
1
+ class InsightsHit < ApplicationRecord
2
+ has_one :host
3
+ # since the facet is one-to-one association with a host, we can connect
4
+ # through host_id column on both this model and facet.
5
+ has_one :insights_facet, foreign_key: 'host_id', primary_key: 'host_id'
6
+ end
@@ -5,6 +5,7 @@ class Setting::RhCloud < Setting
5
5
  [
6
6
  set('allow_auto_inventory_upload', N_('Allow automatic upload of the host inventory to the Red Hat cloud'), true),
7
7
  set('obfuscate_inventory_hostnames', N_('Obfuscate host names sent to Red Hat cloud'), false),
8
+ set('rh_cloud_token', N_('Authentication token to Red Hat cloud services. Used to authenticate requests to cloud APIs'), 'DEFAULT', N_('Red Hat Cloud token'), nil, encrypted: true),
8
9
  ]
9
10
  end
10
11
 
@@ -0,0 +1,13 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'hosts/_list',
3
+ name: 'insights_hits_header',
4
+ insert_before: 'thead tr th.hidden-xs:first-of-type',
5
+ text: '<th class="hidden-xs" width="10%"><%= _("Insights")%></th>'
6
+ )
7
+
8
+ Deface::Override.new(
9
+ virtual_path: 'hosts/_list',
10
+ name: 'insights_hits_cells',
11
+ insert_before: 'tbody tr td.hidden-xs:first-of-type',
12
+ text: '<%= hits_counts_cell(host) %>'
13
+ )
@@ -0,0 +1 @@
1
+ <%= mount_react_component('InsightsCloudSync', '#ForemanRhCloudReactRoot') %>
@@ -5,10 +5,17 @@ Rails.application.routes.draw do
5
5
  get ':organization_id/uploads/last', to: 'uploads#last', constraints: { organization_id: %r{[^\/]+} }
6
6
  get ':organization_id/uploads/file', to: 'uploads#download_file', constraints: { organization_id: %r{[^\/]+} }
7
7
  get 'accounts', to: 'accounts#index'
8
+ get 'auto_upload', to: 'uploads#show_auto_upload'
8
9
  post 'auto_upload', to: 'uploads#auto_upload'
10
+ post 'host_obfuscation', to: 'uploads#host_obfuscation'
11
+ end
12
+
13
+ namespace :insights_cloud do
14
+ resources :tasks, only: [:create]
9
15
  end
10
16
 
11
17
  namespace :foreman_rh_cloud do
12
18
  get 'inventory_upload', to: 'react#inventory_upload'
19
+ get 'insights_cloud', to: 'react#insights_cloud'
13
20
  end
14
21
  end
@@ -0,0 +1,14 @@
1
+ class CreateInsightsHits < ActiveRecord::Migration[5.2]
2
+ def change
3
+ create_table :insights_hits do |t|
4
+ t.references :host, foreign_key: true, null: false
5
+ t.datetime :last_seen
6
+ t.string :title
7
+ t.string :solution_url
8
+ t.integer :total_risk
9
+ t.integer :likelihood
10
+ t.datetime :publish_date
11
+ t.string :results_url
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ class CreateInsightsFacets < ActiveRecord::Migration[5.2]
2
+ def change
3
+ create_table :insights_facets do |t|
4
+ t.references :host, foreign_key: true, null: false
5
+ end
6
+ end
7
+ end
@@ -67,7 +67,7 @@ module ForemanInventoryUpload
67
67
  end
68
68
 
69
69
  def obfuscate_fqdn(fqdn)
70
- Base64.urlsafe_encode64(Digest::SHA1.digest(fqdn), padding: false)
70
+ Digest::SHA1.hexdigest(fqdn)
71
71
  end
72
72
  end
73
73
  end
@@ -157,6 +157,7 @@ module ForemanInventoryUpload
157
157
  @stream.simple_field('distribution_version', fact_value(host, 'distribution::version'))
158
158
  @stream.simple_field('satellite_instance_id', Foreman.try(:instance_id))
159
159
  @stream.simple_field('is_simple_content_access', golden_ticket?(host.organization))
160
+ @stream.simple_field('is_hostname_obfuscated', !!obfuscate_hostname?(host))
160
161
  @stream.simple_field('organization_id', host.organization_id, :last)
161
162
  end
162
163
 
@@ -0,0 +1,19 @@
1
+ module ForemanInventoryUpload
2
+ module Notifications
3
+ module ManifestImportSuccessNotificationOverride
4
+ extend ActiveSupport::Concern
5
+
6
+ def actions
7
+ {
8
+ :links => [
9
+ {
10
+ :href => Rails.application.routes.url_helpers.foreman_rh_cloud_inventory_upload_path,
11
+ :title => _('Enable inventory upload'),
12
+ :external => false,
13
+ },
14
+ ],
15
+ }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -30,13 +30,17 @@ module ForemanRhCloud
30
30
 
31
31
  # Add permissions
32
32
  security_block :foreman_rh_cloud do
33
- permission(:generate_foreman_rh_cloud, :'foreman_inventory_upload/reports' => [:generate])
34
- permission(:view_foreman_rh_cloud,
35
- 'foreman_inventory_upload/accounts': [:index],
36
- 'foreman_inventory_upload/reports': [:last],
37
- 'foreman_inventory_upload/uploads': [:auto_upload, :download_file, :last],
38
- 'foreman_rh_cloud/react': [:inventory_upload]
39
- )
33
+ permission(
34
+ :generate_foreman_rh_cloud,
35
+ 'foreman_inventory_upload/reports': [:generate]
36
+ )
37
+ permission(
38
+ :view_foreman_rh_cloud,
39
+ 'foreman_inventory_upload/accounts': [:index],
40
+ 'foreman_inventory_upload/reports': [:last],
41
+ 'foreman_inventory_upload/uploads': [:auto_upload, :show_auto_upload, :download_file, :last],
42
+ 'foreman_rh_cloud/react': [:inventory_upload]
43
+ )
40
44
  end
41
45
 
42
46
  plugin_permissions = [:view_foreman_rh_cloud, :generate_foreman_rh_cloud]
@@ -49,10 +53,18 @@ module ForemanRhCloud
49
53
  Role::SYSTEM_ADMIN => plugin_permissions
50
54
 
51
55
  # Adding a sub menu after hosts menu
52
- sub_menu :top_menu, :foreman_rh_cloud, :caption => N_('RH Cloud'), :icon => 'fa fa-cloud-upload' do
53
- menu :top_menu, :level1, :caption => N_('Inventory Upload'), :url_hash => { controller: :'foreman_rh_cloud/react', :action => :inventory_upload}
56
+ divider :top_menu, caption: N_('RH Cloud'), parent: :configure_menu
57
+ menu :top_menu, :inventory_upload, :caption => N_('Inventory Upload'), :url_hash => { controller: :'foreman_rh_cloud/react', :action => :inventory_upload}, parent: :configure_menu
58
+ menu :top_menu, :insights_hits_import, :caption => N_('Insights'), :url_hash => { controller: :'foreman_rh_cloud/react', :action => :insights_cloud }, parent: :configure_menu
59
+
60
+ register_facet InsightsFacet, :insights do
61
+ configure_host
54
62
  end
63
+
64
+ register_global_js_file 'subscriptions_extension'
55
65
  end
66
+
67
+ ::Katello::UINotifications::Subscriptions::ManifestImportSuccess.include ForemanInventoryUpload::Notifications::ManifestImportSuccessNotificationOverride if defined?(Katello)
56
68
  end
57
69
 
58
70
  initializer "foreman_rh_cloud.set_dynflow.config.on_init", :before => :finisher_hook do |_app|
@@ -1,3 +1,3 @@
1
1
  module ForemanRhCloud
2
- VERSION = '2.0.7'.freeze
2
+ VERSION = '2.0.8'.freeze
3
3
  end
@@ -0,0 +1,15 @@
1
+ module InsightsCloud
2
+ def self.base_url
3
+ # for testing set ENV to 'https://ci.cloud.redhat.com'
4
+ @base_url ||= ENV['SATELLITE_INSIGHTS_CLOUD_URL'] || 'https://cloud.redhat.com'
5
+ end
6
+
7
+ def self.authentication_url
8
+ # https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token
9
+ @authentication_url ||= ENV['SATELLITE_INSIGHTS_CLOUD_SSO_URL'] || 'https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token'
10
+ end
11
+
12
+ def self.hits_export_url
13
+ base_url + '/api/insights/v1/export/hits/'
14
+ end
15
+ end
@@ -0,0 +1,92 @@
1
+ require 'rest-client'
2
+
3
+ module InsightsCloud
4
+ module Async
5
+ class InsightsFullSync < ::ApplicationJob
6
+ def perform(organization)
7
+ @organization = organization
8
+
9
+ hits = query_insights_hits
10
+
11
+ host_names = hits.map { |hit| hit['hostname'] }.uniq
12
+ setup_host_names(host_names)
13
+
14
+ replace_hits_data(hits)
15
+ end
16
+
17
+ def logger
18
+ Foreman::Logging.logger('background')
19
+ end
20
+
21
+ def rh_credentials
22
+ @rh_credentials ||= query_refresh_token
23
+ end
24
+
25
+ private
26
+
27
+ def query_insights_hits
28
+ hits_response = RestClient::Request.execute(
29
+ method: :get,
30
+ url: InsightsCloud.hits_export_url,
31
+ verify_ssl: ENV['SATELLITE_INSIGHTS_CLOUD_URL'] ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER,
32
+ headers: {
33
+ Authorization: "Bearer #{rh_credentials}",
34
+ }
35
+ )
36
+
37
+ JSON.parse(hits_response)
38
+ end
39
+
40
+ def query_refresh_token
41
+ token_response = RestClient::Request.execute(
42
+ method: :post,
43
+ url: InsightsCloud.authentication_url,
44
+ verify_ssl: ENV['SATELLITE_INSIGHTS_CLOUD_URL'] ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER,
45
+ payload: {
46
+ grant_type: 'refresh_token',
47
+ client_id: 'rhsm-api',
48
+ refresh_token: Setting[:rh_cloud_token],
49
+ }
50
+ )
51
+
52
+ JSON.parse(token_response)['access_token']
53
+ rescue RestClient::ExceptionWithResponse => e
54
+ Foreman::Logging.exception('Unable to authenticate using rh_cloud_token setting', e)
55
+ raise ::Foreman::WrappedException.new(e, N_('Unable to authenticate using rh_cloud_token setting'))
56
+ end
57
+
58
+ def setup_host_names(host_names)
59
+ @host_ids = Hash[
60
+ Host.where(name: host_names).pluck(:name, :id)
61
+ ]
62
+ end
63
+
64
+ def host_id(host_name)
65
+ @host_ids[host_name]
66
+ end
67
+
68
+ def replace_hits_data(hits)
69
+ InsightsHit.transaction do
70
+ InsightsHit.delete_all
71
+ InsightsHit.create(hits.map { |hits_hash| to_model_hash(hits_hash) })
72
+ # create new facets for hosts that are missing one
73
+ hosts_with_existing_facets = InsightsFacet.where(host_id: @host_ids.values).pluck(:host_id)
74
+ InsightsFacet.create((@host_ids.values - hosts_with_existing_facets).map { |id| {host_id: id} })
75
+ end
76
+ end
77
+
78
+ def to_model_hash(hit_hash)
79
+ {
80
+ host_id: host_id(hit_hash['hostname']),
81
+ last_seen: DateTime.parse(hit_hash['last_seen']),
82
+ publish_date: DateTime.parse(hit_hash['publish_date']),
83
+ title: hit_hash['title'],
84
+ solution_url: hit_hash['solution_url'],
85
+ total_risk: hit_hash['total_risk'].to_i,
86
+ likelihood: hit_hash['likelihood'].to_i,
87
+ results_url: hit_hash['results_url'],
88
+ }
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,62 @@
1
+ require 'test_helper'
2
+
3
+ class InsightsFullSyncTest < ActiveJob::TestCase
4
+ setup do
5
+ @host1 = FactoryBot.create(:host, :managed, name: 'host1')
6
+ @host2 = FactoryBot.create(:host, :managed, name: 'host2')
7
+
8
+ hits_json = <<-HITS_JSON
9
+ [
10
+ {
11
+ "hostname": "#{@host1.name}",
12
+ "rhel_version": "7.5",
13
+ "uuid": "accdf444-5628-451d-bf3e-cf909ad72756",
14
+ "last_seen": "2019-11-22T08:41:42.447244Z",
15
+ "title": "New Ansible Engine packages are inaccessible when dedicated Ansible repo is not enabled",
16
+ "solution_url": "",
17
+ "total_risk": 2,
18
+ "likelihood": 2,
19
+ "publish_date": "2018-04-16T10:03:16Z",
20
+ "results_url": "https://cloud.redhat.com/insights/overview/stability/ansible_deprecated_repo%7CANSIBLE_DEPRECATED_REPO/accdf444-5628-451d-bf3e-cf909ad72756/"
21
+ },
22
+ {
23
+ "hostname": "#{@host1.name}",
24
+ "rhel_version": "7.5",
25
+ "uuid": "accdf444-5628-451d-bf3e-cf909ad72756",
26
+ "last_seen": "2019-11-22T08:41:42.447244Z",
27
+ "title": "CPU vulnerable to side-channel attacks using Microarchitectural Data Sampling (CVE-2018-12130, CVE-2018-12126, CVE-2018-12127, CVE-2019-11091)",
28
+ "solution_url": "https://access.redhat.com/node/4134081",
29
+ "total_risk": 2,
30
+ "likelihood": 2,
31
+ "publish_date": "2019-05-14T17:00:00Z",
32
+ "results_url": "https://cloud.redhat.com/insights/overview/security/CVE_2018_12130_cpu_kernel%7CCVE_2018_12130_CPU_KERNEL_NEED_UPDATE/accdf444-5628-451d-bf3e-cf909ad72756/"
33
+ },
34
+ {
35
+ "hostname": "#{@host2.name}",
36
+ "rhel_version": "7.5",
37
+ "uuid": "accdf444-5628-451d-bf3e-cf909ad72757",
38
+ "last_seen": "2019-11-22T08:41:42.447244Z",
39
+ "title": "CPU vulnerable to side-channel attacks using L1 Terminal Fault (CVE-2018-3620)",
40
+ "solution_url": "https://access.redhat.com/node/3560291",
41
+ "total_risk": 2,
42
+ "likelihood": 2,
43
+ "publish_date": "2018-08-14T17:00:00Z",
44
+ "results_url": "https://cloud.redhat.com/insights/overview/security/CVE_2018_3620_cpu_kernel%7CCVE_2018_3620_CPU_KERNEL_NEED_UPDATE/accdf444-5628-451d-bf3e-cf909ad72756/"
45
+ }
46
+ ]
47
+ HITS_JSON
48
+ @hits = JSON.parse(hits_json)
49
+ end
50
+
51
+ test 'Hits data is replaced with data from cloud' do
52
+ InsightsCloud::Async::InsightsFullSync.any_instance.expects(:query_insights_hits).returns(@hits)
53
+
54
+ InsightsCloud::Async::InsightsFullSync.perform_now(@host1.organization)
55
+
56
+ @host1.reload
57
+ @host2.reload
58
+
59
+ assert_equal 2, @host1.insights.hits.count
60
+ assert_equal 1, @host2.insights.hits.count
61
+ end
62
+ end
@@ -82,6 +82,8 @@ class ReportGeneratorTest < ActiveSupport::TestCase
82
82
  assert_not_nil(actual_host = actual['hosts'].first)
83
83
  assert_equal 'obfuscated_name', actual_host['fqdn']
84
84
  assert_equal '1234', actual_host['account']
85
+ assert_not_nil(actual_facts = actual_host['facts'].first['facts'])
86
+ assert_equal true, actual_facts['is_hostname_obfuscated']
85
87
  assert_equal 1, generator.hosts_count
86
88
  end
87
89
 
@@ -94,12 +96,14 @@ class ReportGeneratorTest < ActiveSupport::TestCase
94
96
  json_str = generator.render
95
97
  actual = JSON.parse(json_str.join("\n"))
96
98
 
97
- obfuscated_fqdn = Base64.urlsafe_encode64(Digest::SHA1.digest(@host.fqdn), padding: false)
99
+ obfuscated_fqdn = Digest::SHA1.hexdigest(@host.fqdn)
98
100
 
99
101
  assert_equal 'slice_123', actual['report_slice_id']
100
102
  assert_not_nil(actual_host = actual['hosts'].first)
101
103
  assert_equal obfuscated_fqdn, actual_host['fqdn']
102
104
  assert_equal '1234', actual_host['account']
105
+ assert_not_nil(actual_facts = actual_host['facts'].first['facts'])
106
+ assert_equal true, actual_facts['is_hostname_obfuscated']
103
107
  assert_equal 1, generator.hosts_count
104
108
  end
105
109
 
@@ -117,6 +121,8 @@ class ReportGeneratorTest < ActiveSupport::TestCase
117
121
  assert_not_nil(actual_host = actual['hosts'].first)
118
122
  assert_equal @host.fqdn, actual_host['fqdn']
119
123
  assert_equal '1234', actual_host['account']
124
+ assert_not_nil(actual_facts = actual_host['facts'].first['facts'])
125
+ assert_equal false, actual_facts['is_hostname_obfuscated']
120
126
  assert_equal 1, generator.hosts_count
121
127
  end
122
128
 
@@ -141,6 +147,7 @@ class ReportGeneratorTest < ActiveSupport::TestCase
141
147
  org_id_tag = actual['hosts'].first['tags'].find { |tag| tag['namespace'] == 'satellite' && tag['key'] == 'organization_id' }
142
148
  assert_not_nil org_id_tag
143
149
  assert_equal @host.organization_id.to_s, org_id_tag['value']
150
+ assert_equal false, satellite_facts['is_hostname_obfuscated']
144
151
 
145
152
  version = satellite_facts['satellite_version']
146
153
  if defined?(ForemanThemeSatellite)