foreman_rh_cloud 5.0.35 → 5.0.38
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/app/controllers/api/v2/rh_cloud/cloud_request_controller.rb +1 -1
- data/app/controllers/foreman_inventory_upload/uploads_controller.rb +0 -7
- data/app/controllers/foreman_inventory_upload/uploads_settings_controller.rb +0 -1
- data/app/controllers/insights_cloud/hits_controller.rb +0 -1
- data/app/controllers/insights_cloud/settings_controller.rb +0 -8
- data/app/controllers/insights_cloud/tasks_controller.rb +1 -1
- data/app/models/insights_facet.rb +1 -0
- data/app/models/insights_hit.rb +1 -0
- data/app/models/insights_rule.rb +2 -0
- data/app/models/setting/rh_cloud.rb +1 -2
- data/app/services/foreman_rh_cloud/cert_auth.rb +22 -0
- data/app/services/foreman_rh_cloud/cloud_connector.rb +10 -1
- data/app/services/foreman_rh_cloud/cloud_ping_service.rb +0 -27
- data/app/services/foreman_rh_cloud/hit_remediations_retriever.rb +4 -0
- data/app/services/foreman_rh_cloud/remediations_retriever.rb +7 -3
- data/app/services/foreman_rh_cloud/template_renderer_helper.rb +4 -3
- data/app/services/foreman_rh_cloud/url_remediations_retriever.rb +6 -1
- data/app/views/job_templates/cloud_connector.erb +6 -0
- data/app/views/job_templates/rh_cloud_download_playbook.erb +5 -1
- data/config/routes.rb +0 -1
- data/db/migrate/20220321000001_add_unique_to_insights_rules.foreman_rh_cloud.rb +13 -0
- data/lib/foreman_inventory_upload.rb +1 -1
- data/lib/foreman_rh_cloud/engine.rb +1 -1
- data/lib/foreman_rh_cloud/version.rb +1 -1
- data/lib/foreman_rh_cloud.rb +0 -5
- data/lib/insights_cloud/async/cloud_connector_announce_task.rb +44 -0
- data/lib/insights_cloud/async/connector_playbook_execution_reporter_task.rb +7 -1
- data/lib/insights_cloud/async/insights_full_sync.rb +40 -24
- data/lib/insights_cloud/async/insights_resolutions_sync.rb +10 -13
- data/lib/insights_cloud/async/insights_rules_sync.rb +27 -19
- data/lib/insights_cloud/async/insights_scheduled_sync.rb +1 -1
- data/lib/insights_cloud.rb +4 -8
- data/lib/inventory_sync/async/host_result.rb +3 -2
- data/lib/inventory_sync/async/inventory_full_sync.rb +3 -3
- data/lib/inventory_sync/async/inventory_hosts_sync.rb +11 -10
- data/lib/inventory_sync/async/inventory_self_host_sync.rb +5 -6
- data/lib/inventory_sync/async/query_inventory_job.rb +40 -12
- data/lib/tasks/insights.rake +1 -1
- data/package.json +6 -6
- data/test/controllers/insights_cloud/api/cloud_request_controller_test.rb +0 -1
- data/test/controllers/inventory_upload/cloud_status_controller_test.rb +0 -6
- data/test/jobs/cloud_connector_announce_task_test.rb +125 -0
- data/test/jobs/insights_full_sync_test.rb +9 -5
- data/test/jobs/insights_resolutions_sync_test.rb +7 -1
- data/test/jobs/insights_rules_sync_test.rb +8 -4
- data/test/jobs/inventory_full_sync_test.rb +16 -5
- data/test/jobs/inventory_hosts_sync_test.rb +18 -4
- data/test/jobs/inventory_self_host_sync_test.rb +6 -1
- data/test/unit/services/foreman_rh_cloud/cloud_request_forwarder_test.rb +0 -1
- data/test/unit/services/foreman_rh_cloud/cloud_status_service_test.rb +1 -14
- data/test/unit/services/foreman_rh_cloud/template_renderer_helper_test.rb +5 -1
- data/test/unit/services/foreman_rh_cloud/url_remediations_retriever_test.rb +3 -1
- data/webpack/ForemanInventoryUpload/Components/InventorySettings/InventorySettingsSelectors.js +0 -2
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudPingModal/index.js +1 -10
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/SyncButton.js +3 -12
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/SyncButton.test.js +1 -1
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/SyncButton.test.js.snap +0 -4
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/index.js +0 -2
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableSelectors.js +0 -3
- data/webpack/InsightsCloudSync/Components/InsightsTable/Pagination.js +16 -0
- data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/InsightsTableSelectors.test.js +0 -2
- data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTableSelectors.test.js.snap +0 -2
- data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/fixtures.js +0 -1
- data/webpack/InsightsCloudSync/InsightsCloudSync.js +1 -17
- data/webpack/InsightsCloudSync/InsightsCloudSync.test.js +0 -7
- data/webpack/InsightsCloudSync/InsightsCloudSyncConstants.js +0 -4
- data/webpack/InsightsCloudSync/InsightsCloudSyncHelpers.js +0 -7
- data/webpack/InsightsCloudSync/__snapshots__/InsightsCloudSync.test.js.snap +0 -9
- data/webpack/InsightsCloudSync/index.js +1 -5
- metadata +7 -9
- data/app/services/foreman_rh_cloud/cloud_auth.rb +0 -44
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudPingModal/index.scss +0 -5
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/components/Modal.js +0 -63
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/components/modal.scss +0 -20
- data/webpack/InsightsCloudSync/Components/NoTokenEmptyState.js +0 -79
- data/webpack/InsightsCloudSync/Components/__tests__/NoTokenEmptyState.test.js +0 -19
- data/webpack/InsightsCloudSync/Components/__tests__/__snapshots__/NoTokenEmptyState.test.js.snap +0 -225
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7bb7932e40d6ef999b5266897539d444e9ab7a38606e6f66dff58fb568d70fdc
|
|
4
|
+
data.tar.gz: f6e6a8ae8ddfb3544fbe31c807f9917fe7aa2d5d1d05014055528bb193290109
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dcc37dffd7f108e1687b671ea0f5b157644c6a9576310d917daafefd4011ad01ccced6d48941823873a3da076ab20da2db33fe2c463cc0e962f69a79ea565400
|
|
7
|
+
data.tar.gz: 72f7a08cc3f30d0bddaaf63e0198df2761a40153c7185d1e30328a1c00b9496e7ce33b34ceec44ecf69989ab570001173524cfc49e5a9e127a540bf4684f9d02
|
|
@@ -40,7 +40,6 @@ module Api::V2::RhCloud
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def handle_run_playbook_request
|
|
43
|
-
logger.error("API token is not set, unable to fetch data from the cloud") && return if Setting[:rh_cloud_token].empty?
|
|
44
43
|
logger.error("Playbook URL is not valid: #{content}") && return unless valid_url?(content)
|
|
45
44
|
logger.error("Reporting URL is not valid: #{metadata['return_url']}") && return unless valid_url?(metadata['return_url'])
|
|
46
45
|
|
|
@@ -60,6 +59,7 @@ module Api::V2::RhCloud
|
|
|
60
59
|
host_ids,
|
|
61
60
|
{
|
|
62
61
|
playbook_url: content,
|
|
62
|
+
organization_id: org_id,
|
|
63
63
|
report_url: metadata['return_url'],
|
|
64
64
|
report_interval: metadata['response_interval'].to_i,
|
|
65
65
|
correlation_id: metadata['correlation_id'],
|
|
@@ -18,13 +18,6 @@ module ForemanInventoryUpload
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def enable_cloud_connector
|
|
21
|
-
Organization.unscoped.each do |org|
|
|
22
|
-
presence = ForemanRhCloud::CloudPresence.new(org, logger)
|
|
23
|
-
presence.announce_to_sources
|
|
24
|
-
rescue StandardError => ex
|
|
25
|
-
logger.warn(ex)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
21
|
cloud_connector = ForemanRhCloud::CloudConnector.new
|
|
29
22
|
render json: cloud_connector.install.to_json
|
|
30
23
|
end
|
|
@@ -7,7 +7,6 @@ module ForemanInventoryUpload
|
|
|
7
7
|
ipsObfuscationEnabled: Setting[:obfuscate_inventory_ips],
|
|
8
8
|
excludePackagesEnabled: Setting[:exclude_installed_packages],
|
|
9
9
|
CloudConnectorStatus: ForemanInventoryUpload::UploadsSettingsController.cloud_connector_status,
|
|
10
|
-
cloudToken: !Setting[:rh_cloud_token].empty?,
|
|
11
10
|
lastSyncTask: last_successful_inventory_sync_task,
|
|
12
11
|
}, status: :ok
|
|
13
12
|
end
|
|
@@ -6,7 +6,6 @@ module InsightsCloud
|
|
|
6
6
|
hits = resource_base_search_and_page.preload(:host, :rule)
|
|
7
7
|
|
|
8
8
|
render json: {
|
|
9
|
-
hasToken: !Setting[:rh_cloud_token].empty?,
|
|
10
9
|
hits: hits.map { |hit| hit.attributes.merge(hostname: hit.host&.name, has_playbook: hit.has_playbook?, host_uuid: hit.host_uuid) },
|
|
11
10
|
itemCount: hits.count,
|
|
12
11
|
}, status: :ok
|
|
@@ -9,14 +9,6 @@ module InsightsCloud
|
|
|
9
9
|
render_setting(:insightsSyncEnabled, :allow_auto_insights_sync)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
def save_token_and_sync
|
|
13
|
-
token = Setting::RhCloud.find_by_name("rh_cloud_token")
|
|
14
|
-
token.value = params.require(:value)
|
|
15
|
-
token.save!
|
|
16
|
-
ForemanTasks.sync_task(InsightsCloud::Async::InsightsFullSync)
|
|
17
|
-
redirect_to(:controller => "hits", :action => 'index')
|
|
18
|
-
end
|
|
19
|
-
|
|
20
12
|
private
|
|
21
13
|
|
|
22
14
|
def render_setting(node_name, setting)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module InsightsCloud
|
|
2
2
|
class TasksController < ::ApplicationController
|
|
3
3
|
def create
|
|
4
|
-
task = ForemanTasks.async_task(InsightsCloud::Async::InsightsFullSync)
|
|
4
|
+
task = ForemanTasks.async_task(InsightsCloud::Async::InsightsFullSync, Organization.authorized)
|
|
5
5
|
|
|
6
6
|
render json: {
|
|
7
7
|
task: task,
|
data/app/models/insights_hit.rb
CHANGED
|
@@ -8,6 +8,7 @@ class InsightsHit < ApplicationRecord
|
|
|
8
8
|
has_one :rule, class_name: 'InsightsRule', foreign_key: 'rule_id', primary_key: 'rule_id'
|
|
9
9
|
|
|
10
10
|
scope :with_playbook, -> { joins(:rule) }
|
|
11
|
+
scope :for_organizations, ->(organization_ids) { joins(:host).where(hosts: { organization_id: organization_ids}) }
|
|
11
12
|
|
|
12
13
|
scoped_search on: :title, complete_value: true
|
|
13
14
|
scoped_search on: :total_risk, complete_value: true
|
data/app/models/insights_rule.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
class InsightsRule < ApplicationRecord
|
|
2
2
|
has_many :resolutions, class_name: 'InsightsResolution', dependent: :destroy, foreign_key: 'rule_id', primary_key: 'rule_id', inverse_of: :rule
|
|
3
|
+
|
|
4
|
+
has_many :hits, class_name: 'InsightsHit', foreign_key: 'rule_id', primary_key: 'rule_id', inverse_of: :rule
|
|
3
5
|
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
class Setting::RhCloud < Setting
|
|
2
|
-
::Setting::BLANK_ATTRS.concat %w{
|
|
2
|
+
::Setting::BLANK_ATTRS.concat %w{rhc_instance_id}
|
|
3
3
|
|
|
4
4
|
def self.load_defaults
|
|
5
5
|
return false unless table_exists?
|
|
@@ -17,7 +17,6 @@ class Setting::RhCloud < Setting
|
|
|
17
17
|
set('allow_auto_insights_sync', N_('Enable automatic synchronization of Insights recommendations from the Red Hat cloud'), false, N_('Synchronize recommendations Automatically')),
|
|
18
18
|
set('obfuscate_inventory_hostnames', N_('Obfuscate host names sent to the Red Hat cloud'), false, N_('Obfuscate host names')),
|
|
19
19
|
set('obfuscate_inventory_ips', N_('Obfuscate ipv4 addresses sent to the Red Hat cloud'), false, N_('Obfuscate host ipv4 addresses')),
|
|
20
|
-
set('rh_cloud_token', N_('Authentication token to Red Hat cloud services. Used to authenticate requests to cloud APIs'), nil, N_('Red Hat Cloud token'), nil, encrypted: true),
|
|
21
20
|
set('exclude_installed_packages', N_('Exclude installed packages from being uploaded to the Red Hat cloud'), false, N_("Exclude installed Packages")),
|
|
22
21
|
set('include_parameter_tags', N_('Should import include parameter tags from Foreman?'), false, N_('Include parameters in insights-client reports')),
|
|
23
22
|
set('rhc_instance_id', N_('RHC daemon id'), nil, N_('ID of the RHC(Yggdrasil) daemon')),
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module ForemanRhCloud
|
|
2
|
+
module CertAuth
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
include CloudRequest
|
|
6
|
+
include InsightsCloud::CandlepinCache
|
|
7
|
+
|
|
8
|
+
def cert_auth_available?(organization)
|
|
9
|
+
!!candlepin_id_cert(organization)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def execute_cloud_request(params)
|
|
13
|
+
certs = candlepin_id_cert(params.delete(:organization))
|
|
14
|
+
final_params = {
|
|
15
|
+
ssl_client_cert: OpenSSL::X509::Certificate.new(certs[:cert]),
|
|
16
|
+
ssl_client_key: OpenSSL::PKey::RSA.new(certs[:key]),
|
|
17
|
+
}.deep_merge(params)
|
|
18
|
+
|
|
19
|
+
super(final_params)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -12,11 +12,20 @@ module ForemanRhCloud
|
|
|
12
12
|
target_host = foreman_host
|
|
13
13
|
composer = nil
|
|
14
14
|
|
|
15
|
+
input = {
|
|
16
|
+
:satellite_cloud_connector_user => service_user.login,
|
|
17
|
+
:satellite_cloud_connector_password => token_value,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (http_proxy = ForemanRhCloud.proxy_setting(logger: Foreman::Logging.logger('app')))
|
|
21
|
+
input[:satellite_cloud_connector_http_proxy] = http_proxy
|
|
22
|
+
end
|
|
23
|
+
|
|
15
24
|
Taxonomy.as_taxonomy(target_host.organization, target_host.location) do
|
|
16
25
|
composer = ::JobInvocationComposer.for_feature(
|
|
17
26
|
CLOUD_CONNECTOR_FEATURE,
|
|
18
27
|
[target_host.id],
|
|
19
|
-
|
|
28
|
+
input
|
|
20
29
|
)
|
|
21
30
|
composer.trigger!
|
|
22
31
|
end
|
|
@@ -2,28 +2,6 @@ require 'rest-client'
|
|
|
2
2
|
|
|
3
3
|
module ForemanRhCloud
|
|
4
4
|
class CloudPingService
|
|
5
|
-
class TokenPing
|
|
6
|
-
include ForemanRhCloud::CloudAuth
|
|
7
|
-
|
|
8
|
-
attr_accessor :logger
|
|
9
|
-
|
|
10
|
-
def initialize(logger)
|
|
11
|
-
@logger = logger
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def ping
|
|
15
|
-
execute_cloud_request(
|
|
16
|
-
method: :get,
|
|
17
|
-
url: ForemanRhCloud.base_url + "/api/inventory/v1/hosts?per_page=1",
|
|
18
|
-
headers: {
|
|
19
|
-
content_type: :json,
|
|
20
|
-
}
|
|
21
|
-
)
|
|
22
|
-
rescue StandardError => ex
|
|
23
|
-
ex
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
5
|
class CertPing
|
|
28
6
|
include ForemanRhCloud::CloudRequest
|
|
29
7
|
include InsightsCloud::CandlepinCache
|
|
@@ -62,12 +40,7 @@ module ForemanRhCloud
|
|
|
62
40
|
end
|
|
63
41
|
|
|
64
42
|
def ping
|
|
65
|
-
token_response = TokenPing.new(@logger).ping
|
|
66
43
|
{
|
|
67
|
-
token_auth: {
|
|
68
|
-
success: token_response.is_a?(RestClient::Response),
|
|
69
|
-
error: (token_response.is_a?(Exception) ? token_response.inspect : nil),
|
|
70
|
-
},
|
|
71
44
|
cert_auth: Hash[
|
|
72
45
|
@organizations.map do |org|
|
|
73
46
|
cert_response = CertPing.new(org, @logger).ping
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module ForemanRhCloud
|
|
2
2
|
class RemediationsRetriever
|
|
3
|
-
include
|
|
3
|
+
include CertAuth
|
|
4
4
|
|
|
5
5
|
attr_reader :logger
|
|
6
6
|
|
|
@@ -9,8 +9,8 @@ module ForemanRhCloud
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def create_playbook
|
|
12
|
-
unless
|
|
13
|
-
logger.debug('
|
|
12
|
+
unless cert_auth_available?(organization)
|
|
13
|
+
logger.debug('Manifest is not available, cannot continue')
|
|
14
14
|
return
|
|
15
15
|
end
|
|
16
16
|
|
|
@@ -25,6 +25,7 @@ module ForemanRhCloud
|
|
|
25
25
|
|
|
26
26
|
def query_playbook
|
|
27
27
|
execute_cloud_request(
|
|
28
|
+
organization: organization,
|
|
28
29
|
method: method,
|
|
29
30
|
url: playbook_url,
|
|
30
31
|
headers: headers,
|
|
@@ -47,5 +48,8 @@ module ForemanRhCloud
|
|
|
47
48
|
def method
|
|
48
49
|
:get
|
|
49
50
|
end
|
|
51
|
+
|
|
52
|
+
def organization
|
|
53
|
+
end
|
|
50
54
|
end
|
|
51
55
|
end
|
|
@@ -20,11 +20,12 @@ module ForemanRhCloud
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
apipie :method, 'Returns a Red Hat remediation playbook compiled on console.redhat.com' do
|
|
23
|
-
required :
|
|
23
|
+
required :playbook_url, String, desc: 'URL of the playbook on console.redhat.com'
|
|
24
|
+
required :organization_id, Integer, desc: 'Id of the organization that owns the playbook'
|
|
24
25
|
returns String, desc: 'Playbook downloaded from the cloud'
|
|
25
26
|
end
|
|
26
|
-
def download_rh_playbook(playbook_url)
|
|
27
|
-
retriever = ForemanRhCloud::UrlRemediationsRetriever.new(url: playbook_url, logger: template_logger)
|
|
27
|
+
def download_rh_playbook(playbook_url, organization_id)
|
|
28
|
+
retriever = ForemanRhCloud::UrlRemediationsRetriever.new(url: playbook_url, organization_id: organization_id, logger: template_logger)
|
|
28
29
|
|
|
29
30
|
cached("rh_playbook_#{playbook_url}") do
|
|
30
31
|
retriever.create_playbook
|
|
@@ -2,12 +2,13 @@ module ForemanRhCloud
|
|
|
2
2
|
class UrlRemediationsRetriever < RemediationsRetriever
|
|
3
3
|
attr_reader :url, :payload, :headers
|
|
4
4
|
|
|
5
|
-
def initialize(url:, payload: '', headers: {}, logger: Logger.new(IO::NULL))
|
|
5
|
+
def initialize(url:, organization_id:, payload: '', headers: {}, logger: Logger.new(IO::NULL))
|
|
6
6
|
super(logger: logger)
|
|
7
7
|
|
|
8
8
|
@url = url
|
|
9
9
|
@payload = payload
|
|
10
10
|
@headers = headers
|
|
11
|
+
@organization_id = organization_id
|
|
11
12
|
end
|
|
12
13
|
|
|
13
14
|
private
|
|
@@ -33,5 +34,9 @@ module ForemanRhCloud
|
|
|
33
34
|
def method
|
|
34
35
|
:get
|
|
35
36
|
end
|
|
37
|
+
|
|
38
|
+
def organization
|
|
39
|
+
Organization.find(@organization_id)
|
|
40
|
+
end
|
|
36
41
|
end
|
|
37
42
|
end
|
|
@@ -14,6 +14,12 @@ template_inputs:
|
|
|
14
14
|
advanced: false
|
|
15
15
|
value_type: plain
|
|
16
16
|
hidden_value: true
|
|
17
|
+
- name: satellite_cloud_connector_http_proxy
|
|
18
|
+
required: false
|
|
19
|
+
input_type: user
|
|
20
|
+
advanced: true
|
|
21
|
+
value_type: plain
|
|
22
|
+
hidden_value: false
|
|
17
23
|
model: JobTemplate
|
|
18
24
|
job_category: Maintenance Operations
|
|
19
25
|
description_format: "%{template_name}"
|
|
@@ -9,6 +9,10 @@ template_inputs:
|
|
|
9
9
|
description: URL of the playbook to run
|
|
10
10
|
input_type: user
|
|
11
11
|
required: true
|
|
12
|
+
- name: organization_id
|
|
13
|
+
description: Id of the organization that owns the playbook
|
|
14
|
+
input_type: user
|
|
15
|
+
required: true
|
|
12
16
|
- name: report_url
|
|
13
17
|
description: URL for calling the report callback
|
|
14
18
|
input_type: user
|
|
@@ -23,4 +27,4 @@ template_inputs:
|
|
|
23
27
|
required: true
|
|
24
28
|
provider_type: Ansible
|
|
25
29
|
%>
|
|
26
|
-
<%= download_rh_playbook(input('playbook_url')) %>
|
|
30
|
+
<%= download_rh_playbook(input('playbook_url'), input('organization_id')) %>
|
data/config/routes.rb
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class AddUniqueToInsightsRules < ActiveRecord::Migration[5.2]
|
|
2
|
+
def change
|
|
3
|
+
begin
|
|
4
|
+
# remove old index
|
|
5
|
+
remove_index :insights_rules, [:rule_id]
|
|
6
|
+
rescue ArgumentError
|
|
7
|
+
# noop, if the index is not there, it's OK.
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# add unique constraint
|
|
11
|
+
add_index :insights_rules, [:rule_id], unique: true
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -56,7 +56,7 @@ module ForemanRhCloud
|
|
|
56
56
|
'api/v2/rh_cloud/inventory': [:sync_inventory_status, :download_file, :generate_report, :enable_cloud_connector],
|
|
57
57
|
'foreman_inventory_upload/uploads': [:enable_cloud_connector],
|
|
58
58
|
'foreman_inventory_upload/uploads_settings': [:set_advanced_setting],
|
|
59
|
-
'insights_cloud/settings': [:
|
|
59
|
+
'insights_cloud/settings': [:update],
|
|
60
60
|
'insights_cloud/tasks': [:create]
|
|
61
61
|
)
|
|
62
62
|
permission(
|
data/lib/foreman_rh_cloud.rb
CHANGED
|
@@ -16,11 +16,6 @@ module ForemanRhCloud
|
|
|
16
16
|
@legacy_insights_url ||= ENV['SATELLITE_LEGACY_INSIGHTS_URL'] || 'https://cert-api.access.redhat.com'
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
def self.authentication_url
|
|
20
|
-
# https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token
|
|
21
|
-
@authentication_url ||= ENV['SATELLITE_RH_CLOUD_SSO_URL'] || 'https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token'
|
|
22
|
-
end
|
|
23
|
-
|
|
24
19
|
def self.verify_ssl_method
|
|
25
20
|
@verify_ssl_method ||= ENV['SATELLITE_RH_CLOUD_URL'] ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
|
|
26
21
|
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module InsightsCloud
|
|
2
|
+
module Async
|
|
3
|
+
class CloudConnectorAnnounceTask < ::Actions::EntryAction
|
|
4
|
+
def self.subscribe
|
|
5
|
+
Actions::RemoteExecution::RunHostsJob
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def self.connector_feature_id
|
|
9
|
+
@connector_feature_id ||= RemoteExecutionFeature.feature!(ForemanRhCloud::CloudConnector::CLOUD_CONNECTOR_FEATURE).id
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def plan(job_invocation)
|
|
13
|
+
return unless connector_playbook_job?(job_invocation)
|
|
14
|
+
|
|
15
|
+
plan_self
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def finalize
|
|
19
|
+
Organization.unscoped.each do |org|
|
|
20
|
+
presence = ForemanRhCloud::CloudPresence.new(org, logger)
|
|
21
|
+
presence.announce_to_sources
|
|
22
|
+
rescue StandardError => ex
|
|
23
|
+
logger.warn(ex)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def rescue_strategy_for_self
|
|
28
|
+
Dynflow::Action::Rescue::Skip
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def connector_playbook_job?(job_invocation)
|
|
32
|
+
job_invocation&.remote_execution_feature_id == connector_feature_id
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def connector_feature_id
|
|
36
|
+
self.class.connector_feature_id
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def logger
|
|
40
|
+
action_logger
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -2,7 +2,7 @@ module InsightsCloud
|
|
|
2
2
|
module Async
|
|
3
3
|
class ConnectorPlaybookExecutionReporterTask < ::Actions::EntryAction
|
|
4
4
|
include Dynflow::Action::Polling
|
|
5
|
-
include ForemanRhCloud::
|
|
5
|
+
include ForemanRhCloud::CertAuth
|
|
6
6
|
|
|
7
7
|
def self.subscribe
|
|
8
8
|
Actions::RemoteExecution::RunHostsJob
|
|
@@ -23,6 +23,7 @@ module InsightsCloud
|
|
|
23
23
|
correlation_id = invocation_inputs['correlation_id']
|
|
24
24
|
|
|
25
25
|
plan_self(
|
|
26
|
+
current_org_id: job_invocation.targeted_hosts.first.organization_id,
|
|
26
27
|
report_url: report_url,
|
|
27
28
|
report_interval: report_interval,
|
|
28
29
|
job_invocation_id: job_invocation.id,
|
|
@@ -159,6 +160,7 @@ module InsightsCloud
|
|
|
159
160
|
|
|
160
161
|
def send_report(report)
|
|
161
162
|
execute_cloud_request(
|
|
163
|
+
organization: current_org,
|
|
162
164
|
method: :post,
|
|
163
165
|
url: report_url,
|
|
164
166
|
content_type: 'application/vnd.redhat.playbook-sat.v3+jsonl',
|
|
@@ -188,6 +190,10 @@ module InsightsCloud
|
|
|
188
190
|
def logger
|
|
189
191
|
action_logger
|
|
190
192
|
end
|
|
193
|
+
|
|
194
|
+
def current_org
|
|
195
|
+
Organization.find(input[:current_org_id])
|
|
196
|
+
end
|
|
191
197
|
end
|
|
192
198
|
end
|
|
193
199
|
end
|
|
@@ -3,37 +3,48 @@ require 'rest-client'
|
|
|
3
3
|
module InsightsCloud
|
|
4
4
|
module Async
|
|
5
5
|
class InsightsFullSync < ::Actions::EntryAction
|
|
6
|
-
include ::ForemanRhCloud::
|
|
7
|
-
|
|
8
|
-
def plan
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
include ::ForemanRhCloud::CertAuth
|
|
7
|
+
|
|
8
|
+
def plan(organizations)
|
|
9
|
+
organizations = organizations.select do |organization|
|
|
10
|
+
if cert_auth_available?(organization)
|
|
11
|
+
true
|
|
12
|
+
else
|
|
13
|
+
logger.debug("Certificate is not available for org: #{organization.name}, skipping insights sync")
|
|
14
|
+
false
|
|
15
|
+
end
|
|
12
16
|
end
|
|
13
17
|
|
|
14
18
|
sequence do
|
|
15
19
|
# This can be turned off when we enable automatic status syncs
|
|
16
20
|
# This step will query cloud inventory to retrieve inventory uuids for each host
|
|
17
|
-
plan_hosts_sync
|
|
18
|
-
plan_self
|
|
21
|
+
plan_hosts_sync(organizations)
|
|
22
|
+
plan_self(organization_ids: organizations.map(&:id))
|
|
19
23
|
concurrence do
|
|
20
|
-
plan_rules_sync
|
|
24
|
+
plan_rules_sync(organizations)
|
|
21
25
|
plan_notifications
|
|
22
26
|
end
|
|
23
27
|
end
|
|
24
28
|
end
|
|
25
29
|
|
|
26
30
|
def run
|
|
27
|
-
|
|
31
|
+
organizations.each do |organization|
|
|
32
|
+
unless cert_auth_available?(organization)
|
|
33
|
+
logger.debug("Certificate is not available for org: #{organization.name}, skipping insights sync")
|
|
34
|
+
next
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
perform_hits_sync(organization)
|
|
38
|
+
end
|
|
28
39
|
end
|
|
29
40
|
|
|
30
|
-
def perform_hits_sync
|
|
31
|
-
hits = query_insights_hits
|
|
41
|
+
def perform_hits_sync(organization)
|
|
42
|
+
hits = query_insights_hits(organization)
|
|
32
43
|
|
|
33
44
|
uuids = hits.map { |hit| hit['uuid'] }
|
|
34
|
-
setup_host_ids(uuids)
|
|
45
|
+
setup_host_ids(uuids, organization)
|
|
35
46
|
|
|
36
|
-
replace_hits_data(hits)
|
|
47
|
+
replace_hits_data(hits, organization)
|
|
37
48
|
end
|
|
38
49
|
|
|
39
50
|
def logger
|
|
@@ -42,20 +53,21 @@ module InsightsCloud
|
|
|
42
53
|
|
|
43
54
|
private
|
|
44
55
|
|
|
45
|
-
def plan_hosts_sync
|
|
46
|
-
plan_action
|
|
56
|
+
def plan_hosts_sync(organizations)
|
|
57
|
+
plan_action(InventorySync::Async::InventoryHostsSync, organizations)
|
|
47
58
|
end
|
|
48
59
|
|
|
49
|
-
def plan_rules_sync
|
|
50
|
-
plan_action
|
|
60
|
+
def plan_rules_sync(organizations)
|
|
61
|
+
plan_action(InsightsRulesSync, organizations)
|
|
51
62
|
end
|
|
52
63
|
|
|
53
64
|
def plan_notifications
|
|
54
65
|
plan_action InsightsGenerateNotifications
|
|
55
66
|
end
|
|
56
67
|
|
|
57
|
-
def query_insights_hits
|
|
68
|
+
def query_insights_hits(organization)
|
|
58
69
|
hits_response = execute_cloud_request(
|
|
70
|
+
organization: organization,
|
|
59
71
|
method: :get,
|
|
60
72
|
url: InsightsCloud.hits_export_url
|
|
61
73
|
)
|
|
@@ -72,9 +84,9 @@ module InsightsCloud
|
|
|
72
84
|
JSON.parse(rules_response)
|
|
73
85
|
end
|
|
74
86
|
|
|
75
|
-
def setup_host_ids(uuids)
|
|
87
|
+
def setup_host_ids(uuids, organization)
|
|
76
88
|
@host_ids = Hash[
|
|
77
|
-
InsightsFacet.where(uuid: uuids).pluck(:uuid, :host_id)
|
|
89
|
+
InsightsFacet.for_organizations(organization.id).where(uuid: uuids).pluck(:uuid, :host_id)
|
|
78
90
|
]
|
|
79
91
|
end
|
|
80
92
|
|
|
@@ -82,11 +94,11 @@ module InsightsCloud
|
|
|
82
94
|
@host_ids[uuid]
|
|
83
95
|
end
|
|
84
96
|
|
|
85
|
-
def replace_hits_data(hits)
|
|
97
|
+
def replace_hits_data(hits, organization)
|
|
86
98
|
InsightsHit.transaction do
|
|
87
99
|
# Reset hit counters to 0, they will be recreated later
|
|
88
|
-
InsightsFacet.
|
|
89
|
-
InsightsHit.delete_all
|
|
100
|
+
InsightsFacet.for_organizations(organization.id).update_all(hits_count: 0)
|
|
101
|
+
InsightsHit.for_organizations(organization.id).delete_all
|
|
90
102
|
InsightsHit.create(hits.map { |hits_hash| to_model_hash(hits_hash) }.compact)
|
|
91
103
|
end
|
|
92
104
|
end
|
|
@@ -122,6 +134,10 @@ module InsightsCloud
|
|
|
122
134
|
def rescue_strategy_for_self
|
|
123
135
|
Dynflow::Action::Rescue::Fail
|
|
124
136
|
end
|
|
137
|
+
|
|
138
|
+
def organizations
|
|
139
|
+
@organizations ||= Organization.where(id: input[:organization_ids])
|
|
140
|
+
end
|
|
125
141
|
end
|
|
126
142
|
end
|
|
127
143
|
end
|
|
@@ -3,25 +3,20 @@ require 'rest-client'
|
|
|
3
3
|
module InsightsCloud
|
|
4
4
|
module Async
|
|
5
5
|
class InsightsResolutionsSync < ::Actions::EntryAction
|
|
6
|
-
include ::ForemanRhCloud::
|
|
6
|
+
include ::ForemanRhCloud::CertAuth
|
|
7
7
|
|
|
8
8
|
RULE_ID_REGEX = /[^:]*:(?<id>.*)/
|
|
9
9
|
|
|
10
|
-
def plan
|
|
11
|
-
unless cloud_auth_available?
|
|
12
|
-
logger.debug('Cloud authentication is not available, skipping resolutions sync')
|
|
13
|
-
return
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
plan_self
|
|
17
|
-
end
|
|
18
|
-
|
|
19
10
|
def run
|
|
20
11
|
InsightsResolution.transaction do
|
|
21
12
|
InsightsResolution.delete_all
|
|
22
13
|
rule_ids = relevant_rules
|
|
23
|
-
|
|
24
|
-
|
|
14
|
+
Organization.all.each do |organization|
|
|
15
|
+
next if !cert_auth_available?(organization) || organization.manifest_expired?
|
|
16
|
+
api_response = query_insights_resolutions(rule_ids, organization) unless rule_ids.empty?
|
|
17
|
+
written_rules = write_resolutions(api_response) if api_response
|
|
18
|
+
rule_ids -= Array(written_rules)
|
|
19
|
+
end
|
|
25
20
|
end
|
|
26
21
|
end
|
|
27
22
|
|
|
@@ -31,8 +26,9 @@ module InsightsCloud
|
|
|
31
26
|
|
|
32
27
|
private
|
|
33
28
|
|
|
34
|
-
def query_insights_resolutions(rule_ids)
|
|
29
|
+
def query_insights_resolutions(rule_ids, organization)
|
|
35
30
|
resolutions_response = execute_cloud_request(
|
|
31
|
+
organization: organization,
|
|
36
32
|
method: :post,
|
|
37
33
|
url: InsightsCloud.resolutions_url,
|
|
38
34
|
headers: {
|
|
@@ -66,6 +62,7 @@ module InsightsCloud
|
|
|
66
62
|
end.flatten
|
|
67
63
|
|
|
68
64
|
InsightsResolution.create(all_resolutions)
|
|
65
|
+
response.keys
|
|
69
66
|
end
|
|
70
67
|
|
|
71
68
|
def to_rule_id(resolution_rule_id)
|