foreman_rh_cloud 12.1.4 → 12.1.5

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/insights_cloud/api/machine_telemetries_controller.rb +1 -2
  3. data/app/controllers/insights_cloud/ui_requests_controller.rb +99 -0
  4. data/app/services/foreman_rh_cloud/cloud_request_forwarder.rb +7 -13
  5. data/app/services/foreman_rh_cloud/gateway_request.rb +26 -0
  6. data/app/services/foreman_rh_cloud/insights_api_forwarder.rb +116 -0
  7. data/app/services/foreman_rh_cloud/tags_auth.rb +55 -0
  8. data/config/routes.rb +2 -0
  9. data/lib/foreman_rh_cloud/engine.rb +2 -1
  10. data/lib/foreman_rh_cloud/version.rb +1 -1
  11. data/lib/insights_cloud.rb +8 -0
  12. data/package.json +5 -1
  13. data/test/controllers/insights_cloud/ui_requests_controller_test.rb +169 -0
  14. data/test/unit/services/foreman_rh_cloud/cloud_request_forwarder_test.rb +3 -3
  15. data/test/unit/services/foreman_rh_cloud/insights_api_forwarder_test.rb +176 -0
  16. data/test/unit/services/foreman_rh_cloud/tags_auth_test.rb +29 -0
  17. data/webpack/CVEsHostDetailsTab/CVEsHostDetailsTab.js +30 -10
  18. data/webpack/CVEsHostDetailsTab/__tests__/CVEsHostDetailsTab.test.js +18 -11
  19. data/webpack/CVEsHostDetailsTab/index.js +2 -2
  20. data/webpack/ForemanColumnExtensions/index.js +16 -6
  21. data/webpack/ForemanInventoryUpload/Components/InventoryFilter/InventoryFilter.js +1 -0
  22. data/webpack/ForemanInventoryUpload/Components/InventoryFilter/__tests__/__snapshots__/InventoryFilter.test.js.snap +1 -0
  23. data/webpack/ForemanInventoryUpload/Components/InventorySettings/MinimalInventoryDropdown.js +2 -0
  24. data/webpack/ForemanInventoryUpload/Components/PageHeader/PageTitle.js +8 -1
  25. data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageTitle.test.js.snap +4 -0
  26. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/CloudConnectorButton.js +3 -3
  27. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/__tests__/__snapshots__/CloudConnectorButton.test.js.snap +3 -0
  28. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudPingModal/index.js +10 -4
  29. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/PageDescription.js +6 -6
  30. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SettingsWarning/SettingsWarning.js +2 -0
  31. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SettingsWarning/__snapshots__/SettingsWarning.test.js.snap +2 -0
  32. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/SyncButton.js +1 -0
  33. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/SyncButton.test.js.snap +1 -0
  34. data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/InventoryAutoUpload.js +3 -1
  35. data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/__tests__/__snapshots__/InventoryAutoUpload.test.js.snap +3 -0
  36. data/webpack/ForemanRhCloudFills.js +6 -3
  37. data/webpack/ForemanRhCloudPages.js +6 -3
  38. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTable.js +1 -0
  39. data/webpack/InsightsCloudSync/Components/InsightsTable/SelectAllAlert.js +2 -0
  40. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTable.test.js.snap +1 -0
  41. data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.js +3 -0
  42. data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModalFooter.js +12 -2
  43. data/webpack/InsightsCloudSync/Components/RemediationModal/Resolutions.js +1 -0
  44. data/webpack/InsightsCloudSync/Components/ToolbarDropdown.js +6 -1
  45. data/webpack/InsightsVulnerability/InsightsVulnerabilityListPage.js +21 -0
  46. data/webpack/InsightsVulnerability/InsightsVulnerabilityListPage.test.js +20 -0
  47. data/webpack/InsightsVulnerabilityHostIndexExtensions/CVECountCell.js +45 -0
  48. data/webpack/InsightsVulnerabilityHostIndexExtensions/__tests__/CVECountCell.test.js +28 -0
  49. data/webpack/common/DropdownToggle.js +1 -0
  50. data/webpack/common/ScalprumModule/ScalprumContext.js +63 -0
  51. data/webpack/common/Switcher/SwitcherPF4.js +1 -0
  52. data/webpack/common/Switcher/__tests__/__snapshots__/SwitcherPF4.test.js.snap +1 -0
  53. data/webpack/common/Switcher/index.js +1 -0
  54. metadata +17 -4
  55. data/webpack/InsightsVulnerability/InsightsVulnerability.js +0 -13
  56. data/webpack/InsightsVulnerability/InsightsVulnerability.test.js +0 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7ed52afd2a65d3cc87c3ae660716ca1044af88b359f84f108cbe005c01a37a42
4
- data.tar.gz: b00def287ae973805693edaf6b9eb13e72846992bcb7e5432073ff722458d565
3
+ metadata.gz: abf912ff1170fb60a3b10a6d1178f71ad7a92662c2272a883179eb30a62e2c2e
4
+ data.tar.gz: 3ff64877a61a50890423e1d25980ea37e9fc3ae949f875be344b299f5580ab24
5
5
  SHA512:
6
- metadata.gz: 3ba0a99ac74b2b311f3569cc6dee79a5043be05abdfe41ca25e36f9c4a6e1d903732e8e38ae580c01634842ec493e8ab350f0b3d04b680e032aba9e730bd1935
7
- data.tar.gz: 147d7da2c6352b9333bf1a5c8537c1468d2246d7bd656846ff515170b7c3841c55c73ae4e7fef690c39f56d893721efa994e271b4214d154f9542e03da43c808
6
+ metadata.gz: 5792bc34bf4e7a254cacc14cd014b9e008378d695ddc5ae00afcbd5f10371840a53ecdd106f2a845531a2c174fab3c7d1b931ba0a6f766c749124adcbcff742f
7
+ data.tar.gz: dffa948ae7cca41a839be2c07f26193ccc11c9af71d84c07d4b0f256a0ad0e5763ce107cf69a22ecb6436212a5e68d09512a4043eb8eb5b01a2268c88d0d44fd
@@ -15,9 +15,8 @@ module InsightsCloud::Api
15
15
 
16
16
  # The method that "proxies" requests over to Cloud
17
17
  def forward_request
18
- certs = candlepin_id_cert @organization
19
18
  begin
20
- @cloud_response = ::ForemanRhCloud::CloudRequestForwarder.new.forward_request(request, controller_name, @branch_id, certs, @host)
19
+ @cloud_response = ::ForemanRhCloud::CloudRequestForwarder.new.forward_request(request, controller_name, @branch_id, @host)
21
20
  rescue RestClient::Exceptions::Timeout => e
22
21
  response_obj = e.response.presence || e.exception
23
22
  return render json: { message: response_obj.to_s, error: response_obj.to_s }, status: :gateway_timeout
@@ -0,0 +1,99 @@
1
+ module InsightsCloud
2
+ class UIRequestsController < ::ApplicationController
3
+ layout false
4
+
5
+ before_action :ensure_org, :ensure_loc, :only => [:forward_request]
6
+
7
+ # The method that "proxies" requests over to Cloud
8
+ def forward_request
9
+ begin
10
+ path_match = request.original_fullpath.match(%r{^/insights_cloud/(?<path>[^?]*)})&.[](:path)
11
+ path_to_forward = path_match || params.require(:path)
12
+
13
+ @cloud_response = ::ForemanRhCloud::InsightsApiForwarder.new.forward_request(
14
+ request,
15
+ path_to_forward,
16
+ controller_name,
17
+ User.current,
18
+ @organization,
19
+ @location
20
+ )
21
+ rescue RestClient::Exceptions::Timeout => e
22
+ response_obj = e.response.presence || e.exception
23
+ return render json: { message: response_obj.to_s, error: response_obj.to_s }, status: :gateway_timeout
24
+ rescue RestClient::Unauthorized => e
25
+ logger.warn("Forwarding request auth error: #{e}")
26
+ message = 'Authentication to the Insights Service failed.'
27
+ return render json: { message: message, error: message }, status: :unauthorized
28
+ rescue RestClient::NotModified => e
29
+ logger.info("Forwarding request not modified: #{e}")
30
+ message = 'Cloud request not modified'
31
+ return render json: { message: message, error: message }, status: :not_modified
32
+ rescue RestClient::ExceptionWithResponse => e
33
+ response_obj = e.response.presence || e.exception
34
+ code = response_obj.try(:code) || response_obj.try(:http_code) || 500
35
+ message = 'Cloud request failed'
36
+
37
+ return render json: {
38
+ :message => message,
39
+ :error => response_obj.to_s,
40
+ :headers => {},
41
+ :response => response_obj,
42
+ }, status: code
43
+ rescue StandardError => e
44
+ # Catch any other exceptions here, such as Errno::ECONNREFUSED
45
+ logger.warn("Cloud request failed with exception: #{e}")
46
+ return render json: { error: e.to_s }, status: :bad_gateway
47
+ end
48
+
49
+ # Append redhat-specific headers
50
+ @cloud_response.headers.each do |key, _value|
51
+ assign_header(response, @cloud_response, key, false) if key.to_s.start_with?('x_rh_')
52
+ end
53
+
54
+ # Append general headers
55
+ assign_header(response, @cloud_response, :x_resource_count, true)
56
+ headers[Rack::ETAG] = @cloud_response.headers[:etag]
57
+
58
+ if @cloud_response.headers[:content_disposition]
59
+ # If there is a Content-Disposition header, it means we are forwarding binary data, send the raw data with proper
60
+ # content type
61
+ send_data @cloud_response, disposition: @cloud_response.headers[:content_disposition], type: @cloud_response.headers[:content_type]
62
+ elsif @cloud_response.headers[:content_type] =~ /zip/
63
+ # If there is no Content-Disposition, but the content type is binary according to Content-Type, send the raw data
64
+ # with proper content type
65
+ send_data @cloud_response, type: @cloud_response.headers[:content_type]
66
+ else
67
+ render json: @cloud_response, status: @cloud_response.code
68
+ end
69
+ end
70
+
71
+ def assign_header(res, cloud_res, header, transform)
72
+ header_content = cloud_res.headers[header]
73
+ return unless header_content
74
+ new_header = transform ? header.to_s.tr('_', '-') : header.to_s
75
+ res.headers[new_header] = header_content
76
+ end
77
+
78
+ private
79
+
80
+ def ensure_org
81
+ @organization = Organization.current
82
+ return render_message 'Organization not found or invalid', :status => 400 unless @organization
83
+ end
84
+
85
+ def ensure_loc
86
+ @location = Location.current
87
+ return render_message 'Location not found or invalid', :status => 400 unless @location
88
+ end
89
+
90
+ def base_url
91
+ InsightsCloud.ui_base_url
92
+ end
93
+
94
+ def render_message(msg, render_options = {})
95
+ render_options[:json] = { :message => msg }
96
+ render render_options
97
+ end
98
+ end
99
+ end
@@ -3,8 +3,9 @@ require 'rest-client'
3
3
  module ForemanRhCloud
4
4
  class CloudRequestForwarder
5
5
  include ForemanRhCloud::CloudRequest
6
+ include ForemanRhCloud::CertAuth
6
7
 
7
- def forward_request(original_request, controller_name, branch_id, certs, host)
8
+ def forward_request(original_request, controller_name, branch_id, host)
8
9
  forward_params = prepare_forward_params(original_request, branch_id)
9
10
  logger.debug("Request parameters for telemetry request: #{forward_params}")
10
11
 
@@ -12,14 +13,15 @@ module ForemanRhCloud
12
13
 
13
14
  logger.debug("User agent for telemetry is: #{http_user_agent original_request}")
14
15
 
15
- request_opts = prepare_request_opts(original_request, forward_payload, forward_params, certs, host)
16
+ request_opts = prepare_request_opts(original_request, forward_payload, forward_params, host)
17
+ request_opts[:organization] = host.organization
16
18
 
17
19
  logger.debug("Sending request to: #{request_opts[:url]}")
18
20
 
19
21
  execute_cloud_request(request_opts)
20
22
  end
21
23
 
22
- def prepare_request_opts(original_request, forward_payload, forward_params, certs, host)
24
+ def prepare_request_opts(original_request, forward_payload, forward_params, host)
23
25
  base_params = {
24
26
  method: original_request.method,
25
27
  payload: forward_payload,
@@ -33,7 +35,7 @@ module ForemanRhCloud
33
35
  ),
34
36
  }
35
37
  requested_url = original_request.original_fullpath.end_with?('/') ? original_request.path + '/' : original_request.path
36
- params = path_params(requested_url, certs)
38
+ params = path_params(requested_url)
37
39
 
38
40
  if ForemanRhCloud.with_local_advisor_engine?
39
41
  params[:ssl_ca_file] = ForemanRhCloud.ca_cert
@@ -66,31 +68,23 @@ module ForemanRhCloud
66
68
  forward_params
67
69
  end
68
70
 
69
- def path_params(request_path, certs)
71
+ def path_params(request_path)
70
72
  case request_path
71
73
  when lightspeed?
72
74
  {
73
75
  url: ForemanRhCloud.cert_base_url + request_path,
74
- ssl_client_cert: OpenSSL::X509::Certificate.new(certs[:cert]),
75
- ssl_client_key: OpenSSL::PKey.read(certs[:key]),
76
76
  }
77
77
  when platform_request?
78
78
  {
79
79
  url: ForemanRhCloud.cert_base_url + request_path.sub('/redhat_access/r/insights/platform', '/api'),
80
- ssl_client_cert: OpenSSL::X509::Certificate.new(certs[:cert]),
81
- ssl_client_key: OpenSSL::PKey.read(certs[:key]),
82
80
  }
83
81
  when connection_test_request?
84
82
  {
85
83
  url: ForemanRhCloud.cert_base_url + '/api/apicast-tests/ping',
86
- ssl_client_cert: OpenSSL::X509::Certificate.new(certs[:cert]),
87
- ssl_client_key: OpenSSL::PKey.read(certs[:key]),
88
84
  }
89
85
  else # Legacy insights API
90
86
  {
91
87
  url: ForemanRhCloud.legacy_insights_url + request_path.sub('/redhat_access/r/insights', '/r/insights'),
92
- ssl_client_cert: OpenSSL::X509::Certificate.new(certs[:cert]),
93
- ssl_client_key: OpenSSL::PKey.read(certs[:key]),
94
88
  ssl_ca_file: ForemanRhCloud.legacy_insights_ca,
95
89
  }
96
90
  end
@@ -0,0 +1,26 @@
1
+ module ForemanRhCloud
2
+ module GatewayRequest
3
+ extend ActiveSupport::Concern
4
+
5
+ include CloudRequest
6
+
7
+ def execute_cloud_request(params)
8
+ certs = params.delete(:certs) || foreman_certificates
9
+ final_params = {
10
+ ssl_client_cert: OpenSSL::X509::Certificate.new(certs[:cert]),
11
+ ssl_client_key: OpenSSL::PKey.read(certs[:key]),
12
+ ssl_ca_file: Setting[:ssl_ca_file],
13
+ verify_ssl: OpenSSL::SSL::VERIFY_PEER,
14
+ }.deep_merge(params)
15
+
16
+ super(final_params)
17
+ end
18
+
19
+ def foreman_certificates
20
+ {
21
+ cert: File.read(Setting[:ssl_certificate]),
22
+ key: File.read(Setting[:ssl_priv_key]),
23
+ }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,116 @@
1
+ require 'rest-client'
2
+
3
+ module ForemanRhCloud
4
+ class InsightsApiForwarder
5
+ include ForemanRhCloud::GatewayRequest
6
+
7
+ SCOPED_REQUESTS = [
8
+ %r{/api/vulnerability/v1/vulnerabilities/cves},
9
+ %r{/api/vulnerability/v1/dashbar},
10
+ %r{/api/vulnerability/v1/cves/[^/]+/affected_systems},
11
+ %r{/api/vulnerability/v1/systems/[^/]+/cves},
12
+ %r{/api/insights/.*},
13
+ %r{/api/inventory/.*},
14
+ %r{/api/tasks/.*},
15
+ ].freeze
16
+
17
+ def forward_request(original_request, path, controller_name, user, organization, location)
18
+ TagsAuth.new(user, organization, location, logger).update_tag if scope_request?(original_request, path)
19
+
20
+ forward_params = prepare_forward_params(original_request, path, user: user, organization: organization, location: location).to_a
21
+ logger.debug("Request parameters for UI request: #{forward_params}")
22
+
23
+ forward_payload = prepare_forward_payload(original_request, controller_name)
24
+
25
+ logger.debug("User agent for UI is: #{http_user_agent(original_request)}")
26
+
27
+ request_opts = prepare_request_opts(original_request, path, forward_payload, forward_params)
28
+
29
+ logger.debug("Sending request to: #{request_opts[:url]}")
30
+
31
+ execute_cloud_request(request_opts)
32
+ end
33
+
34
+ def prepare_tags(user, organization, location)
35
+ [
36
+ TagsAuth.auth_tag_for(user, organization, location),
37
+ ].map { |tag_value| [:tag, tag_value] }
38
+ end
39
+
40
+ def prepare_request_opts(original_request, path, forward_payload, forward_params)
41
+ base_params = {
42
+ method: original_request.method,
43
+ payload: forward_payload,
44
+ headers: original_headers(original_request).merge(
45
+ {
46
+ params: RestClient::ParamsArray.new(forward_params),
47
+ user_agent: http_user_agent(original_request),
48
+ content_type: original_request.media_type.presence || original_request.format.to_s,
49
+ }
50
+ ),
51
+ }
52
+ params = path_params(path)
53
+
54
+ base_params.merge(params)
55
+ end
56
+
57
+ def prepare_forward_payload(original_request, controller_name)
58
+ forward_payload = original_request.request_parameters[controller_name]
59
+
60
+ forward_payload = original_request.raw_post.clone if (original_request.post? || original_request.patch?) && original_request.raw_post
61
+ forward_payload = original_request.body.read if original_request.put?
62
+
63
+ forward_payload = original_request.params.slice(:file, :metadata) if original_request.params[:file]
64
+
65
+ # fix rails behaviour for http PATCH:
66
+ forward_payload = forward_payload.to_json if original_request.format.json? && original_request.patch? && forward_payload && !forward_payload.is_a?(String)
67
+ forward_payload
68
+ end
69
+
70
+ def prepare_forward_params(original_request, path, user:, organization:, location:)
71
+ forward_params = original_request.query_parameters.to_a
72
+
73
+ forward_params += prepare_tags(user, organization, location) if scope_request?(original_request, path)
74
+
75
+ forward_params
76
+ end
77
+
78
+ def path_params(path)
79
+ {
80
+ url: "#{InsightsCloud.ui_base_url}/#{path}",
81
+ }
82
+ end
83
+
84
+ def original_headers(original_request)
85
+ headers = {
86
+ if_none_match: original_request.if_none_match,
87
+ if_modified_since: original_request.if_modified_since,
88
+ }.compact
89
+
90
+ logger.debug("Sending headers: #{headers}")
91
+ headers
92
+ end
93
+
94
+ def scope_request?(original_request, path)
95
+ return false unless original_request.get?
96
+
97
+ SCOPED_REQUESTS.any? { |request_pattern| request_pattern.match?(path) }
98
+ end
99
+
100
+ def core_app_name
101
+ BranchInfo.new.core_app_name
102
+ end
103
+
104
+ def core_app_version
105
+ BranchInfo.new.core_app_version
106
+ end
107
+
108
+ def http_user_agent(original_request)
109
+ "#{core_app_name}/#{core_app_version};#{ForemanRhCloud::Engine.engine_name}/#{ForemanRhCloud::VERSION};#{original_request.env['HTTP_USER_AGENT']}"
110
+ end
111
+
112
+ def logger
113
+ Foreman::Logging.logger('app')
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,55 @@
1
+ module ForemanRhCloud
2
+ class TagsAuth
3
+ include GatewayRequest
4
+
5
+ TAG_NAMESPACE = 'sat_iam'.freeze
6
+ TAG_SHORT_NAME = 'scope'.freeze
7
+ TAG_NAME = "#{TAG_NAMESPACE}/#{TAG_SHORT_NAME}".freeze
8
+
9
+ def self.auth_tag_for(user, org, loc)
10
+ new(user, org, loc, nil).auth_tag
11
+ end
12
+
13
+ attr_reader :logger
14
+
15
+ def initialize(user, org, loc, logger)
16
+ @user = user
17
+ @org = org
18
+ @loc = loc
19
+ @logger = logger
20
+ end
21
+
22
+ def update_tag
23
+ logger.debug("Updating tags for user: #{@user}, org: #{@org.name}, loc: #{@loc.name}")
24
+
25
+ params = {
26
+ method: :post,
27
+ url: "#{InsightsCloud.gateway_url}/tags",
28
+ headers: {
29
+ content_type: :json,
30
+ },
31
+ payload: tags_query_payload.to_json,
32
+ }
33
+ execute_cloud_request(params)
34
+ end
35
+
36
+ def allowed_hosts
37
+ Host.authorized_as(@user, nil, nil).where(organization: @org, location: @loc).joins(:subscription_facet).pluck('katello_subscription_facets.uuid')
38
+ end
39
+
40
+ def tags_query_payload
41
+ {
42
+ tags: [{ "namespace": TAG_NAMESPACE, "key": TAG_SHORT_NAME, "value": tag_value }],
43
+ host_id_list: allowed_hosts,
44
+ }
45
+ end
46
+
47
+ def tag_value
48
+ "U:\"#{@user.login}\"O:\"#{@org.name}\"L:\"#{@loc.name}\""
49
+ end
50
+
51
+ def auth_tag
52
+ "#{TAG_NAME}=#{tag_value}"
53
+ end
54
+ end
55
+ end
data/config/routes.rb CHANGED
@@ -30,6 +30,8 @@ Rails.application.routes.draw do
30
30
  match 'hits/:host_id', to: 'hits#show', via: :get
31
31
 
32
32
  post ':organization_id/parameter', to: 'settings#set_org_parameter', constraints: { organization_id: %r{[^\/]+} }
33
+
34
+ match '/*path', constraints: { path: %r{api/[^\?]+} }, to: 'ui_requests#forward_request', via: :all
33
35
  end
34
36
 
35
37
  namespace :foreman_rh_cloud do
@@ -84,6 +84,7 @@ module ForemanRhCloud
84
84
  '/foreman_rh_cloud/insights_cloud': [:index], # for bookmarks and later for showing the page
85
85
  'insights_cloud/hits': [:index, :show, :auto_complete_search, :resolutions],
86
86
  'insights_cloud/settings': [:index, :show],
87
+ 'insights_cloud/ui_requests': [:forward_request],
87
88
  'react': [:index],
88
89
  },
89
90
  :resource_type => ::InsightsHit.name
@@ -199,7 +200,7 @@ module ForemanRhCloud
199
200
  RemoteExecutionFeature.register(
200
201
  :rh_cloud_connector_run_playbook,
201
202
  N_('Run RH Cloud playbook'),
202
- description: N_('Run playbook genrated by Red Hat remediations app'),
203
+ description: N_('Run playbook generated by Red Hat remediations app'),
203
204
  host_action_button: false,
204
205
  provided_inputs: ['playbook_url', 'report_url', 'correlation_id', 'report_interval']
205
206
  )
@@ -1,3 +1,3 @@
1
1
  module ForemanRhCloud
2
- VERSION = '12.1.4'.freeze
2
+ VERSION = '12.1.5'.freeze
3
3
  end
@@ -21,6 +21,14 @@ module InsightsCloud
21
21
  ForemanRhCloud.cert_base_url + '/api/remediations/v1/playbook'
22
22
  end
23
23
 
24
+ def self.gateway_url
25
+ ForemanRhCloud.cert_base_url
26
+ end
27
+
28
+ def self.ui_base_url
29
+ InsightsCloud.gateway_url
30
+ end
31
+
24
32
  def self.remediation_rule_id(rule_id)
25
33
  "advisor:#{rule_id}"
26
34
  end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foreman_rh_cloud",
3
- "version": "12.1.4",
3
+ "version": "12.1.5",
4
4
  "description": "Inventory Upload =============",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -21,6 +21,10 @@
21
21
  "peerDependencies": {
22
22
  "@theforeman/vendor": ">= 15.0.1"
23
23
  },
24
+ "dependencies": {
25
+ "@scalprum/react-core": "^0.9.3",
26
+ "@scalprum/core": "^0.8.1"
27
+ },
24
28
  "devDependencies": {
25
29
  "@babel/core": "^7.7.0",
26
30
  "@theforeman/builder": ">= 15.0.1",
@@ -0,0 +1,169 @@
1
+ require 'test_plugin_helper'
2
+ require 'rest-client'
3
+
4
+ module InsightsCloud
5
+ class UIRequestsControllerTest < ActionController::TestCase
6
+ include KatelloCVEHelper
7
+
8
+ setup do
9
+ FactoryBot.create(:common_parameter, name: InsightsCloud.enable_client_param, key_type: 'boolean', value: true)
10
+ end
11
+
12
+ context '#forward_request' do
13
+ include MockCerts
14
+
15
+ setup do
16
+ @body = 'Cloud response body'
17
+ @http_req = RestClient::Request.new(:method => 'GET', :url => 'http://test.theforeman.org')
18
+
19
+ @org = FactoryBot.create(:organization)
20
+ @loc = FactoryBot.create(:location)
21
+ host = FactoryBot.create(:host, :with_subscription, :organization => @org)
22
+ User.current = ::Katello::CpConsumerUser.new(:uuid => host.subscription_facet.uuid, :login => host.subscription_facet.uuid)
23
+ InsightsCloud::UIRequestsController.any_instance.stubs(:upstream_owner).returns({ 'uuid' => 'abcdefg' })
24
+ ForemanRhCloud::TagsAuth.any_instance.stubs(:execute_cloud_request)
25
+
26
+ setup_certs_expectation do
27
+ ForemanRhCloud::InsightsApiForwarder.any_instance.stubs(:foreman_certificates)
28
+ end
29
+ end
30
+
31
+ test "should respond with response from cloud" do
32
+ net_http_resp = Net::HTTPResponse.new(1.0, 200, "OK")
33
+ net_http_resp.add_field 'Set-Cookie', 'Monster'
34
+ res = RestClient::Response.create(@body, net_http_resp, @http_req)
35
+ ::ForemanRhCloud::InsightsApiForwarder.any_instance.stubs(:forward_request).returns(res)
36
+
37
+ get :forward_request, params: { "controller" => "vulnerabilities", "path" => "api/vulnerability/v1/cves" }, session: set_session
38
+ assert_equal @body, @response.body
39
+ end
40
+
41
+ test "should handle timeout from cloud" do
42
+ ::ForemanRhCloud::InsightsApiForwarder.any_instance.
43
+ stubs(:forward_request).
44
+ raises(RestClient::Exceptions::OpenTimeout.new("Timed out connecting to server"))
45
+
46
+ get :forward_request, params: { "controller" => "vulnerabilities", "path" => "api/vulnerability/v1/cves" }, session: set_session
47
+ request_response = JSON.parse(@response.body)
48
+ # I can't get @response.status to take a nil value so I'm not asserting for that
49
+
50
+ assert_equal 'Timed out connecting to server', request_response['error']
51
+ end
52
+
53
+ test "should add headers to response from cloud" do
54
+ x_resource_count = '101'
55
+ x_rh_insights_request_id = '202'
56
+ net_http_resp = Net::HTTPResponse.new(1.0, 200, "OK")
57
+ net_http_resp['x_resource_count'] = x_resource_count
58
+ net_http_resp['x_rh_insights_request_id'] = x_rh_insights_request_id
59
+ res = RestClient::Response.create(@body, net_http_resp, @http_req)
60
+ ::ForemanRhCloud::InsightsApiForwarder.any_instance.stubs(:forward_request).returns(res)
61
+
62
+ get :forward_request, params: { "controller" => "vulnerabilities", "path" => "api/vulnerability/v1/cves" }, session: set_session
63
+ assert_equal x_resource_count, @response.headers['x-resource-count']
64
+ assert_equal x_rh_insights_request_id, @response.headers['x_rh_insights_request_id']
65
+ end
66
+
67
+ test "should extract path from original_fullpath when URL starts with insights_cloud" do
68
+ net_http_resp = Net::HTTPResponse.new(1.0, 200, "OK")
69
+ # Simulate a request with insights_cloud in the path
70
+ @request.stubs(:original_fullpath).returns('/insights_cloud/api/vulnerability/v1/cves?search=test')
71
+
72
+ res = RestClient::Response.create(@body, net_http_resp, @http_req)
73
+ ::ForemanRhCloud::InsightsApiForwarder
74
+ .any_instance
75
+ .expects(:forward_request)
76
+ .returns(res)
77
+ .with { |_, path_to_forward| _(path_to_forward).must_equal('api/vulnerability/v1/cves') }
78
+
79
+ get :forward_request, params: { "controller" => "vulnerabilities", "path" => "api/vulnerability/v1/cves" }, session: set_session
80
+
81
+ assert_equal @body, @response.body
82
+ end
83
+
84
+ test "should set etag header to response from cloud" do
85
+ etag = '12345'
86
+ req = RestClient::Request.new(:method => 'GET', :url => 'http://test.theforeman.org', :headers => { "If-None-Match": etag })
87
+ net_http_resp = Net::HTTPResponse.new(1.0, 200, "OK")
88
+ net_http_resp[Rack::ETAG] = etag
89
+ res = RestClient::Response.create(@body, net_http_resp, req)
90
+ ::ForemanRhCloud::InsightsApiForwarder.any_instance.stubs(:forward_request).returns(res)
91
+
92
+ get :forward_request, params: { "controller" => "vulnerabilities", "path" => "api/vulnerability/v1/cves" }, session: set_session
93
+ assert_equal etag, @response.headers[Rack::ETAG]
94
+ end
95
+
96
+ test "should set content type header to response from cloud" do
97
+ req = RestClient::Request.new(:method => 'GET', :url => 'http://test.theforeman.org')
98
+ net_http_resp = Net::HTTPResponse.new(1.0, 200, "OK")
99
+ net_http_resp[:content_type] = 'application/zip'
100
+ res = RestClient::Response.create(@body, net_http_resp, req)
101
+ ::ForemanRhCloud::InsightsApiForwarder.any_instance.stubs(:forward_request).returns(res)
102
+
103
+ get :forward_request, params: { "controller" => "vulnerabilities", "path" => "api/vulnerability/v1/cves" }, session: set_session
104
+ assert_equal net_http_resp[:content_type], @response.headers['Content-Type']
105
+ end
106
+
107
+ test "should handle StandardError" do
108
+ error_message = "Connection refused"
109
+ ::ForemanRhCloud::InsightsApiForwarder.any_instance.stubs(:execute_cloud_request).raises(Errno::ECONNREFUSED.new)
110
+
111
+ get :forward_request, params: { "controller" => "vulnerabilities", "path" => "api/vulnerability/v1/cves" }, session: set_session
112
+ assert_equal 502, @response.status
113
+ body = JSON.parse(@response.body)
114
+ assert_equal error_message, body['error']
115
+ end
116
+
117
+ test "should handle 304 cloud" do
118
+ net_http_resp = Net::HTTPResponse.new(1.0, 304, "Not Modified")
119
+ res = RestClient::Response.create(@body, net_http_resp, @http_req)
120
+
121
+ ::ForemanRhCloud::InsightsApiForwarder.any_instance.stubs(:execute_cloud_request).raises(RestClient::NotModified.new(res))
122
+
123
+ get :forward_request, params: { "controller" => "vulnerabilities", "path" => "api/vulnerability/v1/cves" }, session: set_session
124
+ assert_equal 304, @response.status
125
+ assert_equal 'Cloud request not modified', JSON.parse(@response.body)['message']
126
+ end
127
+
128
+ test "should handle RestClient::Exceptions::Timeout" do
129
+ timeout_message = "execution expired"
130
+ ::ForemanRhCloud::InsightsApiForwarder.any_instance.stubs(:execute_cloud_request).raises(RestClient::Exceptions::Timeout.new(timeout_message))
131
+
132
+ get :forward_request, params: { "controller" => "vulnerabilities", "path" => "api/vulnerability/v1/cves" }, session: set_session
133
+ assert_equal 504, @response.status
134
+ body = JSON.parse(@response.body)
135
+ assert_equal timeout_message, body['message']
136
+ assert_equal timeout_message, body['error']
137
+ end
138
+
139
+ test "should handle failed authentication to cloud" do
140
+ net_http_resp = Net::HTTPResponse.new(1.0, 401, "Unauthorized")
141
+ res = RestClient::Response.create(@body, net_http_resp, @http_req)
142
+
143
+ ::ForemanRhCloud::InsightsApiForwarder.any_instance.stubs(:execute_cloud_request).raises(RestClient::Unauthorized.new(res))
144
+
145
+ get :forward_request, params: { "controller" => "vulnerabilities", "path" => "api/vulnerability/v1/cves" }, session: set_session
146
+ assert_equal 401, @response.status
147
+ assert_equal 'Authentication to the Insights Service failed.', JSON.parse(@response.body)['message']
148
+ end
149
+
150
+ test "should forward errors to the client" do
151
+ net_http_resp = Net::HTTPResponse.new(1.0, 500, "TEST_RESPONSE")
152
+ res = RestClient::Response.create(@body, net_http_resp, @http_req)
153
+ ::ForemanRhCloud::InsightsApiForwarder.any_instance.stubs(:execute_cloud_request).raises(RestClient::InternalServerError.new(res))
154
+
155
+ get :forward_request, params: { "controller" => "vulnerabilities", "path" => "api/vulnerability/v1/cves" }, session: set_session
156
+ assert_equal 500, @response.status
157
+ assert_equal 'Cloud request failed', JSON.parse(@response.body)['message']
158
+ assert_match(/#{@body}/, JSON.parse(@response.body)['response'])
159
+ end
160
+ end
161
+
162
+ def set_session
163
+ set_session_user.merge(
164
+ organization_id: @org.id,
165
+ location_id: @loc.id
166
+ )
167
+ end
168
+ end
169
+ end
@@ -42,7 +42,7 @@ class CloudRequestForwarderTest < ActiveSupport::TestCase
42
42
  }
43
43
 
44
44
  paths.each do |key, value|
45
- actual_params = @forwarder.path_params(key, generate_certs_hash)
45
+ actual_params = @forwarder.path_params(key)
46
46
  assert_equal value, actual_params[:url]
47
47
  end
48
48
  end
@@ -167,7 +167,7 @@ class CloudRequestForwarderTest < ActiveSupport::TestCase
167
167
  'action_dispatch.request.query_parameters' => params
168
168
  )
169
169
 
170
- actual = @forwarder.prepare_request_opts(req, 'TEST PAYLOAD', params, generate_certs_hash, @host)
170
+ actual = @forwarder.prepare_request_opts(req, 'TEST PAYLOAD', params, @host)
171
171
 
172
172
  assert_match /foo/, actual[:headers][:user_agent]
173
173
  assert_match /bar/, actual[:headers][:user_agent]
@@ -192,7 +192,7 @@ class CloudRequestForwarderTest < ActiveSupport::TestCase
192
192
  'action_dispatch.request.query_parameters' => params
193
193
  )
194
194
 
195
- actual = @forwarder.prepare_request_opts(req, 'TEST PAYLOAD', params, generate_certs_hash, @host)
195
+ actual = @forwarder.prepare_request_opts(req, 'TEST PAYLOAD', params, @host)
196
196
 
197
197
  assert_match /text\/html/, actual[:headers][:content_type]
198
198
  end