foreman_rh_cloud 1.0.7 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
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 +13 -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 +14 -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 +8 -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 +11 -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: cf631b63f0110a4a5d39aa664905fef695e8b402d458fe20704db84880bdf33f
4
- data.tar.gz: ac49f7073bf0e2828964587434f84275029ca0aef285f963d00ddc7e569b8197
3
+ metadata.gz: 90a809c493cd6f251d29d9e126c7e2ee3e9bf2b63cd6f9e723da166764f47502
4
+ data.tar.gz: 13118ce2cc5c2580485b148842b2d972445ad2f1032bfb1bc27e5ecaeac29a54
5
5
  SHA512:
6
- metadata.gz: 9d9015a4931ab563c5d56cc38c1ea9ba54df04ebf9305f4077d5b88284b84b78da02f9dfed267192a8ce7ed49e98bf4b89e884eda8eae08a68fe8699771a9f69
7
- data.tar.gz: 45a135ff52da1cedacb37b84a70b3f73347d741e62beb95a96e0fed7cf022928649ca470b6d9242c9bfe55b790e28f2fb734f76fa0524f6548351fcc81d7b580
6
+ metadata.gz: 63a34e66722cb135b56609eb61897c0ac567eb036e0cc7ef8515b0439876b300ecac26835bb881033b22dd18885357a89e743bdf4e9fb50331611b866f483749
7
+ data.tar.gz: f6a402750f8bf71ecdedecb5a2548fd74048e8a1c83a6d31e4ca094e3d034546d6d598c7901396cca8a0c690abf5cf9c947e7aa60ef14d6c6dc4c616bb70e6a7
@@ -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, :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 = '1.0.7'.freeze
2
+ VERSION = '1.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)