foreman_rh_cloud 12.1.3 → 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.
- checksums.yaml +4 -4
- data/README.md +3 -5
- data/app/controllers/concerns/insights_cloud/package_profile_upload_extensions.rb +33 -0
- data/app/controllers/insights_cloud/api/machine_telemetries_controller.rb +1 -2
- data/app/controllers/insights_cloud/ui_requests_controller.rb +99 -0
- data/app/services/foreman_rh_cloud/cert_auth.rb +9 -1
- data/app/services/foreman_rh_cloud/cloud_request_forwarder.rb +12 -13
- data/app/services/foreman_rh_cloud/gateway_request.rb +26 -0
- data/app/services/foreman_rh_cloud/insights_api_forwarder.rb +116 -0
- data/app/services/foreman_rh_cloud/tags_auth.rb +55 -0
- data/app/views/api/v2/hosts/insights/base.rabl +6 -0
- data/config/routes.rb +2 -0
- data/lib/foreman_inventory_upload/async/generate_report_job.rb +11 -5
- data/lib/foreman_inventory_upload/async/upload_report_job.rb +15 -4
- data/lib/foreman_inventory_upload/generators/archived_report.rb +2 -2
- data/lib/foreman_inventory_upload/generators/fact_helpers.rb +65 -13
- data/lib/foreman_inventory_upload/generators/queries.rb +7 -5
- data/lib/foreman_inventory_upload/generators/slice.rb +0 -1
- data/lib/foreman_inventory_upload.rb +2 -2
- data/lib/foreman_rh_cloud/engine.rb +5 -3
- data/lib/foreman_rh_cloud/version.rb +1 -1
- data/lib/insights_cloud.rb +8 -0
- data/lib/inventory_sync/async/inventory_hosts_sync.rb +2 -0
- data/lib/tasks/rh_cloud_inventory.rake +3 -2
- data/package.json +5 -1
- data/test/controllers/insights_cloud/ui_requests_controller_test.rb +169 -0
- data/test/unit/archived_report_generator_test.rb +1 -1
- data/test/unit/fact_helpers_test.rb +267 -2
- data/test/unit/services/foreman_rh_cloud/cloud_request_forwarder_test.rb +20 -3
- data/test/unit/services/foreman_rh_cloud/insights_api_forwarder_test.rb +176 -0
- data/test/unit/services/foreman_rh_cloud/tags_auth_test.rb +29 -0
- data/test/unit/slice_generator_test.rb +69 -10
- data/webpack/CVEsHostDetailsTab/CVEsHostDetailsTab.js +30 -10
- data/webpack/CVEsHostDetailsTab/__tests__/CVEsHostDetailsTab.test.js +18 -11
- data/webpack/CVEsHostDetailsTab/index.js +2 -2
- data/webpack/ForemanColumnExtensions/index.js +51 -0
- data/webpack/ForemanInventoryUpload/Components/InventoryFilter/InventoryFilter.js +1 -0
- data/webpack/ForemanInventoryUpload/Components/InventoryFilter/__tests__/__snapshots__/InventoryFilter.test.js.snap +1 -0
- data/webpack/ForemanInventoryUpload/Components/InventorySettings/MinimalInventoryDropdown.js +2 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/PageTitle.js +8 -1
- data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageTitle.test.js.snap +4 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/CloudConnectorButton.js +3 -3
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/__tests__/__snapshots__/CloudConnectorButton.test.js.snap +3 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudPingModal/index.js +10 -4
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/PageDescription.js +6 -6
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SettingsWarning/SettingsWarning.js +2 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SettingsWarning/__snapshots__/SettingsWarning.test.js.snap +2 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/SyncButton.js +1 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/SyncButton.test.js.snap +1 -0
- data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/InventoryAutoUpload.js +3 -1
- data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/__tests__/__snapshots__/InventoryAutoUpload.test.js.snap +3 -0
- data/webpack/ForemanRhCloudFills.js +6 -3
- data/webpack/ForemanRhCloudPages.js +6 -3
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTable.js +1 -0
- data/webpack/InsightsCloudSync/Components/InsightsTable/SelectAllAlert.js +2 -0
- data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTable.test.js.snap +1 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.js +3 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModalFooter.js +12 -2
- data/webpack/InsightsCloudSync/Components/RemediationModal/Resolutions.js +1 -0
- data/webpack/InsightsCloudSync/Components/ToolbarDropdown.js +6 -1
- data/webpack/InsightsVulnerability/InsightsVulnerabilityListPage.js +21 -0
- data/webpack/InsightsVulnerability/InsightsVulnerabilityListPage.test.js +20 -0
- data/webpack/InsightsVulnerabilityHostIndexExtensions/CVECountCell.js +45 -0
- data/webpack/InsightsVulnerabilityHostIndexExtensions/__tests__/CVECountCell.test.js +28 -0
- data/webpack/common/DropdownToggle.js +1 -0
- data/webpack/common/ScalprumModule/ScalprumContext.js +63 -0
- data/webpack/common/Switcher/SwitcherPF4.js +1 -0
- data/webpack/common/Switcher/__tests__/__snapshots__/SwitcherPF4.test.js.snap +1 -0
- data/webpack/common/Switcher/index.js +1 -0
- data/webpack/global_index.js +3 -0
- metadata +19 -4
- data/webpack/InsightsVulnerability/InsightsVulnerability.js +0 -13
- data/webpack/InsightsVulnerability/InsightsVulnerability.test.js +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: abf912ff1170fb60a3b10a6d1178f71ad7a92662c2272a883179eb30a62e2c2e
|
4
|
+
data.tar.gz: 3ff64877a61a50890423e1d25980ea37e9fc3ae949f875be344b299f5580ab24
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5792bc34bf4e7a254cacc14cd014b9e008378d695ddc5ae00afcbd5f10371840a53ecdd106f2a845531a2c174fab3c7d1b931ba0a6f766c749124adcbcff742f
|
7
|
+
data.tar.gz: dffa948ae7cca41a839be2c07f26193ccc11c9af71d84c07d4b0f256a0ad0e5763ce107cf69a22ecb6436212a5e68d09512a4043eb8eb5b01a2268c88d0d44fd
|
data/README.md
CHANGED
@@ -1,18 +1,16 @@
|
|
1
1
|
[](https://github.com/theforeman/foreman_rh_cloud/actions/workflows/ruby_tests.yml)
|
2
2
|
[](https://github.com/theforeman/foreman_rh_cloud/actions/workflows/js_tests.yml)
|
3
|
+
[](https://deepwiki.com/theforeman/foreman_rh_cloud)
|
3
4
|
|
4
5
|
# ForemanRhCloud
|
5
6
|
|
6
|
-
*Introduction here*
|
7
|
-
|
8
7
|
## Installation
|
9
8
|
|
10
9
|
See [How_to_Install_a_Plugin](http://projects.theforeman.org/projects/foreman/wiki/How_to_Install_a_Plugin)
|
11
10
|
for how to install Foreman plugins
|
12
11
|
|
13
|
-
##
|
14
|
-
|
15
|
-
*Usage here*
|
12
|
+
## Project overview
|
13
|
+
See our [wiki](https://deepwiki.com/theforeman/foreman_rh_cloud)
|
16
14
|
|
17
15
|
### In Satellite
|
18
16
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module InsightsCloud
|
2
|
+
module PackageProfileUploadExtensions
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
# This method explicitly listens on Katello actions
|
7
|
+
# rubocop:disable Rails/LexicallyScopedActionFilter
|
8
|
+
after_action :generate_host_report, only: [:upload_package_profile, :upload_profiles]
|
9
|
+
# rubocop:enable Rails/LexicallyScopedActionFilter
|
10
|
+
end
|
11
|
+
|
12
|
+
def generate_host_report
|
13
|
+
return unless ForemanRhCloud.with_local_advisor_engine?
|
14
|
+
|
15
|
+
logger.debug("Generating host-specific report for host #{@host.name}")
|
16
|
+
|
17
|
+
ForemanTasks.async_task(
|
18
|
+
ForemanInventoryUpload::Async::GenerateReportJob,
|
19
|
+
ForemanInventoryUpload.generated_reports_folder,
|
20
|
+
@host.organization_id,
|
21
|
+
false,
|
22
|
+
"id=#{@host.id}"
|
23
|
+
)
|
24
|
+
|
25
|
+
# in IoP case, the hosts are identified by the sub-man ID, and we can assume they already
|
26
|
+
# exist in the local inventory. This will also handle facet creation for new hosts.
|
27
|
+
return if @host.insights
|
28
|
+
|
29
|
+
insights_facet = @host.build_insights(uuid: @host.subscription_facet.uuid)
|
30
|
+
insights_facet.save
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -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,
|
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
|
@@ -10,7 +10,8 @@ module ForemanRhCloud
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def execute_cloud_request(params)
|
13
|
-
|
13
|
+
organization = params.delete(:organization)
|
14
|
+
certs = ForemanRhCloud.with_local_advisor_engine? ? foreman_certificate : candlepin_id_cert(organization)
|
14
15
|
final_params = {
|
15
16
|
ssl_client_cert: OpenSSL::X509::Certificate.new(certs[:cert]),
|
16
17
|
ssl_client_key: OpenSSL::PKey.read(certs[:key]),
|
@@ -18,5 +19,12 @@ module ForemanRhCloud
|
|
18
19
|
|
19
20
|
super(final_params)
|
20
21
|
end
|
22
|
+
|
23
|
+
def foreman_certificate
|
24
|
+
@foreman_certificate ||= {
|
25
|
+
cert: File.read(Setting[:ssl_certificate]),
|
26
|
+
key: File.read(Setting[:ssl_priv_key]),
|
27
|
+
}
|
28
|
+
end
|
21
29
|
end
|
22
30
|
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,
|
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,
|
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,
|
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,
|
@@ -28,11 +30,12 @@ module ForemanRhCloud
|
|
28
30
|
params: forward_params,
|
29
31
|
user_agent: http_user_agent(original_request),
|
30
32
|
content_type: original_request.media_type.presence || original_request.format.to_s,
|
33
|
+
Forwarded: prepare_forwarded_header(host),
|
31
34
|
}
|
32
35
|
),
|
33
36
|
}
|
34
37
|
requested_url = original_request.original_fullpath.end_with?('/') ? original_request.path + '/' : original_request.path
|
35
|
-
params = path_params(requested_url
|
38
|
+
params = path_params(requested_url)
|
36
39
|
|
37
40
|
if ForemanRhCloud.with_local_advisor_engine?
|
38
41
|
params[:ssl_ca_file] = ForemanRhCloud.ca_cert
|
@@ -65,31 +68,23 @@ module ForemanRhCloud
|
|
65
68
|
forward_params
|
66
69
|
end
|
67
70
|
|
68
|
-
def path_params(request_path
|
71
|
+
def path_params(request_path)
|
69
72
|
case request_path
|
70
73
|
when lightspeed?
|
71
74
|
{
|
72
75
|
url: ForemanRhCloud.cert_base_url + request_path,
|
73
|
-
ssl_client_cert: OpenSSL::X509::Certificate.new(certs[:cert]),
|
74
|
-
ssl_client_key: OpenSSL::PKey.read(certs[:key]),
|
75
76
|
}
|
76
77
|
when platform_request?
|
77
78
|
{
|
78
79
|
url: ForemanRhCloud.cert_base_url + request_path.sub('/redhat_access/r/insights/platform', '/api'),
|
79
|
-
ssl_client_cert: OpenSSL::X509::Certificate.new(certs[:cert]),
|
80
|
-
ssl_client_key: OpenSSL::PKey.read(certs[:key]),
|
81
80
|
}
|
82
81
|
when connection_test_request?
|
83
82
|
{
|
84
83
|
url: ForemanRhCloud.cert_base_url + '/api/apicast-tests/ping',
|
85
|
-
ssl_client_cert: OpenSSL::X509::Certificate.new(certs[:cert]),
|
86
|
-
ssl_client_key: OpenSSL::PKey.read(certs[:key]),
|
87
84
|
}
|
88
85
|
else # Legacy insights API
|
89
86
|
{
|
90
87
|
url: ForemanRhCloud.legacy_insights_url + request_path.sub('/redhat_access/r/insights', '/r/insights'),
|
91
|
-
ssl_client_cert: OpenSSL::X509::Certificate.new(certs[:cert]),
|
92
|
-
ssl_client_key: OpenSSL::PKey.read(certs[:key]),
|
93
88
|
ssl_ca_file: ForemanRhCloud.legacy_insights_ca,
|
94
89
|
}
|
95
90
|
end
|
@@ -105,6 +100,10 @@ module ForemanRhCloud
|
|
105
100
|
headers
|
106
101
|
end
|
107
102
|
|
103
|
+
def prepare_forwarded_header(host)
|
104
|
+
"for=\"_#{host.subscription_facet.uuid}\""
|
105
|
+
end
|
106
|
+
|
108
107
|
def lightspeed?
|
109
108
|
->(request_path) { request_path.include? '/lightspeed' }
|
110
109
|
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
|
@@ -3,3 +3,9 @@ attributes :uuid
|
|
3
3
|
node :insights_hit_details do |facet|
|
4
4
|
facet&.host&.facts('insights::hit_details')&.values&.first
|
5
5
|
end
|
6
|
+
node :insights_hits_count do |facet|
|
7
|
+
facet.hits&.count
|
8
|
+
end
|
9
|
+
node :use_local_advisor_engine do |_facet|
|
10
|
+
ForemanRhCloud.with_local_advisor_engine?
|
11
|
+
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
|
@@ -5,18 +5,19 @@ module ForemanInventoryUpload
|
|
5
5
|
"report_for_#{label}"
|
6
6
|
end
|
7
7
|
|
8
|
-
def plan(base_folder, organization_id, disconnected)
|
8
|
+
def plan(base_folder, organization_id, disconnected, hosts_filter = nil)
|
9
9
|
sequence do
|
10
10
|
super(
|
11
|
-
GenerateReportJob.output_label(organization_id),
|
11
|
+
GenerateReportJob.output_label("#{organization_id}#{hosts_filter.empty? ? nil : "[#{hosts_filter.to_s.parameterize}]"}"),
|
12
12
|
organization_id: organization_id,
|
13
|
-
base_folder: base_folder
|
13
|
+
base_folder: base_folder,
|
14
|
+
hosts_filter: hosts_filter
|
14
15
|
)
|
15
16
|
|
16
17
|
plan_action(
|
17
18
|
QueueForUploadJob,
|
18
19
|
base_folder,
|
19
|
-
ForemanInventoryUpload.facts_archive_name(organization_id),
|
20
|
+
ForemanInventoryUpload.facts_archive_name(organization_id, hosts_filter),
|
20
21
|
organization_id,
|
21
22
|
disconnected
|
22
23
|
)
|
@@ -34,7 +35,8 @@ module ForemanInventoryUpload
|
|
34
35
|
def env
|
35
36
|
super.merge(
|
36
37
|
'target' => base_folder,
|
37
|
-
'organization_id' => organization_id
|
38
|
+
'organization_id' => organization_id,
|
39
|
+
'hosts_filter' => hosts_filter
|
38
40
|
)
|
39
41
|
end
|
40
42
|
|
@@ -45,6 +47,10 @@ module ForemanInventoryUpload
|
|
45
47
|
def organization_id
|
46
48
|
input[:organization_id]
|
47
49
|
end
|
50
|
+
|
51
|
+
def hosts_filter
|
52
|
+
input[:hosts_filter]
|
53
|
+
end
|
48
54
|
end
|
49
55
|
end
|
50
56
|
end
|
@@ -33,8 +33,8 @@ module ForemanInventoryUpload
|
|
33
33
|
end
|
34
34
|
|
35
35
|
Tempfile.create([organization.name, '.pem']) do |cer_file|
|
36
|
-
cer_file.write(
|
37
|
-
cer_file.write(
|
36
|
+
cer_file.write(certificate[:cert])
|
37
|
+
cer_file.write(certificate[:key])
|
38
38
|
cer_file.flush
|
39
39
|
@cer_path = cer_file.path
|
40
40
|
super
|
@@ -59,8 +59,12 @@ module ForemanInventoryUpload
|
|
59
59
|
env_vars
|
60
60
|
end
|
61
61
|
|
62
|
-
def
|
63
|
-
|
62
|
+
def certificate
|
63
|
+
ForemanRhCloud.with_local_advisor_engine? ? foreman_certificate : manifest_certificate
|
64
|
+
end
|
65
|
+
|
66
|
+
def manifest_certificate
|
67
|
+
@manifest_certificate ||= begin
|
64
68
|
candlepin_id_certificate = organization.owner_details['upstreamConsumer']['idCert']
|
65
69
|
{
|
66
70
|
cert: candlepin_id_certificate['cert'],
|
@@ -69,6 +73,13 @@ module ForemanInventoryUpload
|
|
69
73
|
end
|
70
74
|
end
|
71
75
|
|
76
|
+
def foreman_certificate
|
77
|
+
@foreman_certificate ||= {
|
78
|
+
cert: File.read(Setting[:ssl_certificate]),
|
79
|
+
key: File.read(Setting[:ssl_priv_key]),
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
72
83
|
def filename
|
73
84
|
input[:filename]
|
74
85
|
end
|
@@ -6,10 +6,10 @@ module ForemanInventoryUpload
|
|
6
6
|
@logger = logger
|
7
7
|
end
|
8
8
|
|
9
|
-
def render(organization:)
|
9
|
+
def render(organization:, filter: nil)
|
10
10
|
Dir.mktmpdir do |tmpdir|
|
11
11
|
@logger.info "Started generating hosts report in #{tmpdir}"
|
12
|
-
host_batches = ForemanInventoryUpload::Generators::Queries.for_org(organization)
|
12
|
+
host_batches = ForemanInventoryUpload::Generators::Queries.for_org(organization, hosts_query: filter || '')
|
13
13
|
File.open(File.join(tmpdir, 'metadata.json'), 'w') do |metadata_out|
|
14
14
|
metadata_generator = ForemanInventoryUpload::Generators::Metadata.new(metadata_out)
|
15
15
|
metadata_generator.render do |inner_generator|
|