foreman_rh_cloud 14.1.2 → 14.2.0

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 (130) hide show
  1. checksums.yaml +4 -4
  2. data/app/services/foreman_rh_cloud/insights_api_forwarder.rb +157 -5
  3. data/lib/foreman_inventory_upload/generators/fact_helpers.rb +26 -4
  4. data/lib/foreman_inventory_upload.rb +8 -1
  5. data/lib/foreman_rh_cloud/plugin.rb +16 -5
  6. data/lib/foreman_rh_cloud/version.rb +1 -1
  7. data/lib/foreman_rh_cloud.rb +36 -9
  8. data/lib/insights_cloud/async/insights_generate_notifications.rb +10 -1
  9. data/lib/inventory_sync/async/inventory_self_host_sync.rb +12 -2
  10. data/package.json +1 -1
  11. data/test/jobs/insights_generate_notifications_test.rb +26 -0
  12. data/test/jobs/inventory_self_host_sync_test.rb +9 -0
  13. data/test/unit/foreman_rh_cloud_self_host_test.rb +50 -2
  14. data/test/unit/metadata_generator_test.rb +24 -1
  15. data/test/unit/services/foreman_rh_cloud/insights_api_forwarder_test.rb +240 -4
  16. data/webpack/ForemanInventoryUpload/Components/AccountList/AccountList.fixtures.js +0 -6
  17. data/webpack/ForemanInventoryUpload/Components/AccountList/AccountListReducer.js +0 -2
  18. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/EmptyResults/__tests__/EmptyResults.test.js +10 -9
  19. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/EmptyState/__tests__/EmptyState.test.js +13 -9
  20. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ErrorState/__tests__/ErrorState.test.js +20 -9
  21. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/__tests__/ListItem.test.js +31 -8
  22. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItemStatus/__tests__/ListItemStatus.test.js +26 -10
  23. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/AccountList.test.js +33 -9
  24. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/AccountListReducer.test.js +53 -35
  25. data/webpack/ForemanInventoryUpload/Components/FileDownload/__tests__/FileDownload.test.js +13 -9
  26. data/webpack/ForemanInventoryUpload/Components/InventoryFilter/__tests__/InventoryFilter.test.js +12 -15
  27. data/webpack/ForemanInventoryUpload/Components/InventoryFilter/__tests__/integration.test.js +32 -12
  28. data/webpack/ForemanInventoryUpload/Components/PageHeader/PageHeader.js +0 -2
  29. data/webpack/ForemanInventoryUpload/Components/PageHeader/PageHeader.scss +1 -2
  30. data/webpack/ForemanInventoryUpload/Components/PageHeader/PageTitle.js +13 -7
  31. data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/PageHeader.test.js +0 -5
  32. data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/PageTitle.test.js +47 -7
  33. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/SyncButton.test.js +23 -9
  34. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/SyncButtonSelectors.test.js +19 -17
  35. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/integrations.test.js +25 -37
  36. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/ToolbarButtons.js +0 -4
  37. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/__tests__/ToolbarButtons.test.js +18 -47
  38. data/webpack/ForemanInventoryUpload/Components/ScheduledRun/__tests__/ScheduledRun.test.js +28 -8
  39. data/webpack/ForemanInventoryUpload/Components/StatusChart/__tests__/StatusChart.test.js +25 -8
  40. data/webpack/ForemanInventoryUpload/Components/TabContainer/__tests__/TabContainer.test.js +11 -9
  41. data/webpack/ForemanInventoryUpload/Components/TabFooter/__tests__/TabFooter.test.js +11 -9
  42. data/webpack/ForemanInventoryUpload/ForemanInventoryHelpers.js +4 -4
  43. data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/__tests__/InventoryAutoUpload.test.js +33 -12
  44. data/webpack/ForemanInventoryUpload/__tests__/ForemanInventoryHelpers.test.js +36 -8
  45. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/InsightsSettingsActions.test.js +61 -47
  46. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/InsightsTable.test.js +48 -4
  47. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/InsightsTableActions.test.js +126 -35
  48. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/InsightsTableSelectors.test.js +90 -24
  49. data/webpack/InsightsCloudSync/InsightsCloudSync.test.js +79 -21
  50. data/webpack/InsightsCloudSync/__tests__/InsightsCloudSyncActions.test.js +31 -6
  51. data/webpack/InsightsHostDetailsTab/__tests__/InsightsTab.test.js +42 -9
  52. data/webpack/__tests__/ForemanRhCloudHelpers.test.js +91 -53
  53. data/webpack/common/Switcher/__tests__/HelpLabel.test.js +25 -10
  54. data/webpack/common/Switcher/__tests__/SwitcherPF4.test.js +41 -10
  55. metadata +4 -77
  56. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/EmptyResults/__tests__/__snapshots__/EmptyResults.test.js.snap +0 -18
  57. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/EmptyState/__tests__/__snapshots__/EmptyState.test.js.snap +0 -25
  58. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ErrorState/__tests__/__snapshots__/ErrorState.test.js.snap +0 -20
  59. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/__tests__/__snapshots__/ListItem.test.js.snap +0 -47
  60. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItemStatus/__tests__/__snapshots__/ListItemStatus.test.js.snap +0 -59
  61. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/AccountListActions.test.js +0 -34
  62. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/AccountListIntegration.test.js +0 -14
  63. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/AccountListSelectors.test.js +0 -25
  64. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountList.test.js.snap +0 -49
  65. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountListActions.test.js.snap +0 -86
  66. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountListReducer.test.js.snap +0 -75
  67. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountListSelectors.test.js.snap +0 -46
  68. data/webpack/ForemanInventoryUpload/Components/FileDownload/__tests__/__snapshots__/FileDownload.test.js.snap +0 -26
  69. data/webpack/ForemanInventoryUpload/Components/InventoryFilter/__tests__/InventoryFilterActions.test.js +0 -14
  70. data/webpack/ForemanInventoryUpload/Components/InventoryFilter/__tests__/InventoryFilterReducer.test.js +0 -28
  71. data/webpack/ForemanInventoryUpload/Components/InventoryFilter/__tests__/InventoryFilterSelectors.test.js +0 -21
  72. data/webpack/ForemanInventoryUpload/Components/InventoryFilter/__tests__/__snapshots__/InventoryFilter.test.js.snap +0 -21
  73. data/webpack/ForemanInventoryUpload/Components/InventoryFilter/__tests__/__snapshots__/InventoryFilterActions.test.js.snap +0 -17
  74. data/webpack/ForemanInventoryUpload/Components/InventoryFilter/__tests__/__snapshots__/InventoryFilterReducer.test.js.snap +0 -19
  75. data/webpack/ForemanInventoryUpload/Components/InventoryFilter/__tests__/__snapshots__/InventoryFilterSelectors.test.js.snap +0 -9
  76. data/webpack/ForemanInventoryUpload/Components/InventoryFilter/__tests__/__snapshots__/integration.test.js.snap +0 -43
  77. data/webpack/ForemanInventoryUpload/Components/InventorySettings/AdvancedSetting/__tests__/AdvancedSettingActions.test.js +0 -9
  78. data/webpack/ForemanInventoryUpload/Components/InventorySettings/AdvancedSetting/__tests__/__snapshots__/AdvancedSettingActions.test.js.snap +0 -18
  79. data/webpack/ForemanInventoryUpload/Components/InventorySettings/__tests__/InventorySettingsActions.test.js +0 -14
  80. data/webpack/ForemanInventoryUpload/Components/InventorySettings/__tests__/__snapshots__/InventorySettingsActions.test.js.snap +0 -26
  81. data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageTitle.test.js.snap +0 -68
  82. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/CloudConnectorActions.js +0 -21
  83. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/CloudConnectorButton.js +0 -59
  84. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/CloudConnectorConstants.js +0 -6
  85. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/CloudConnectorSelectors.js +0 -19
  86. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/__tests__/CloudConnectorActions.test.js +0 -9
  87. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/__tests__/CloudConnectorButton.test.js +0 -22
  88. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/__tests__/__snapshots__/CloudConnectorActions.test.js.snap +0 -11
  89. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/__tests__/__snapshots__/CloudConnectorButton.test.js.snap +0 -59
  90. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudConnectorButton/index.js +0 -34
  91. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SettingsWarning/SettingsWarning.js +0 -66
  92. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SettingsWarning/SettingsWarning.test.js +0 -18
  93. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SettingsWarning/__snapshots__/SettingsWarning.test.js.snap +0 -32
  94. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SettingsWarning/index.js +0 -25
  95. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/SyncButton.test.js.snap +0 -15
  96. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/SyncButtonSelectors.test.js.snap +0 -3
  97. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/integrations.test.js.snap +0 -58
  98. data/webpack/ForemanInventoryUpload/Components/ScheduledRun/__tests__/__snapshots__/ScheduledRun.test.js.snap +0 -23
  99. data/webpack/ForemanInventoryUpload/Components/StatusChart/__tests__/__snapshots__/StatusChart.test.js.snap +0 -74
  100. data/webpack/ForemanInventoryUpload/Components/TabContainer/__tests__/__snapshots__/TabContainer.test.js.snap +0 -18
  101. data/webpack/ForemanInventoryUpload/Components/TabFooter/__tests__/__snapshots__/TabFooter.test.js.snap +0 -12
  102. data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/__tests__/__snapshots__/InventoryAutoUpload.test.js.snap +0 -96
  103. data/webpack/ForemanInventoryUpload/__tests__/ForemanInventoryUpload.test.js +0 -10
  104. data/webpack/ForemanInventoryUpload/__tests__/__snapshots__/ForemanInventoryHelpers.test.js.snap +0 -5
  105. data/webpack/ForemanInventoryUpload/__tests__/__snapshots__/ForemanInventoryUpload.test.js.snap +0 -14
  106. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/InsightsSettingsReducer.test.js +0 -33
  107. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/InsightsSettingsSelectors.test.js +0 -21
  108. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/__snapshots__/InsightsSettingsActions.test.js.snap +0 -65
  109. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/__snapshots__/InsightsSettingsReducer.test.js.snap +0 -19
  110. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/__snapshots__/InsightsSettingsSelectors.test.js.snap +0 -9
  111. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTableActions.test.js.snap +0 -131
  112. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTableSelectors.test.js.snap +0 -87
  113. data/webpack/InsightsCloudSync/__snapshots__/InsightsCloudSync.test.js.snap +0 -10
  114. data/webpack/InsightsCloudSync/__tests__/InsightsCloudSyncHelpers.test.js +0 -9
  115. data/webpack/InsightsCloudSync/__tests__/__snapshots__/InsightsCloudSyncActions.test.js.snap +0 -15
  116. data/webpack/InsightsCloudSync/__tests__/__snapshots__/InsightsCloudSyncHelpers.test.js.snap +0 -3
  117. data/webpack/InsightsHostDetailsTab/__tests__/InsightsTabActions.test.js +0 -19
  118. data/webpack/InsightsHostDetailsTab/__tests__/InsightsTabReducer.test.js +0 -26
  119. data/webpack/InsightsHostDetailsTab/__tests__/InsightsTabSelectors.test.js +0 -13
  120. data/webpack/InsightsHostDetailsTab/__tests__/__snapshots__/InsightsTab.test.js.snap +0 -34
  121. data/webpack/InsightsHostDetailsTab/__tests__/__snapshots__/InsightsTabActions.test.js.snap +0 -56
  122. data/webpack/InsightsHostDetailsTab/__tests__/__snapshots__/InsightsTabReducer.test.js.snap +0 -32
  123. data/webpack/InsightsHostDetailsTab/__tests__/__snapshots__/InsightsTabSelectors.test.js.snap +0 -18
  124. data/webpack/__tests__/ForemanRhCloudSelectors.test.js +0 -22
  125. data/webpack/__tests__/ForemanRhCloudTestHelpers.test.js +0 -20
  126. data/webpack/__tests__/__snapshots__/ForemanRhCloudHelpers.test.js.snap +0 -19
  127. data/webpack/__tests__/__snapshots__/ForemanRhCloudSelectors.test.js.snap +0 -25
  128. data/webpack/__tests__/__snapshots__/ForemanRhCloudTestHelpers.test.js.snap +0 -39
  129. data/webpack/common/Switcher/__tests__/__snapshots__/HelpLabel.test.js.snap +0 -16
  130. data/webpack/common/Switcher/__tests__/__snapshots__/SwitcherPF4.test.js.snap +0 -24
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8561ef219578d2be3678f2576fba36e1cb3f2a91aab82b5438369aa08ddd0a05
4
- data.tar.gz: 6abcf201d049e27b6dc90fef6f5094a0f6f72d337f49aa6cdf328d8aa92e3516
3
+ metadata.gz: 91157d5050744236651134413110454e4d595e1e25644eb1676d58e4990476d1
4
+ data.tar.gz: acb8689d93c1d2aedf280049ff18075ad7989693ef75fea5a8b1babef63b447c
5
5
  SHA512:
6
- metadata.gz: cf0448da7b88a0ddca0e2726805b9c0fb6e5356651e64ac09d0a18cd16d05a393dab07f4a19c445948a39fd1a4111e17c275c8ffaf33df974cc80a9af1693ba0
7
- data.tar.gz: 7e780f06f64dc1f5042a10ec48f3c397d5b767bc5b6ac2c08ac7d9cc059518df4415ee442b37216777a471a0286d59a73a56142a6b80cb10b04213d477a9c4d7
6
+ metadata.gz: 5f2378f058fde9220f4fa8ca17a094dfe6e32f3f33456304c0178ca3b5023abf8b6bfd09fdcbff064e914e063c4fc6a9b66536d6703e259a4f28569202c37813
7
+ data.tar.gz: 1d0adbd1839a3e73eada13ca910522407af5a66e838934ad327f8c36cb41058f5693c7d5d646caa3b7b1fba71670e184f24df1ee90b122d4fdd7f05338a845de
@@ -8,6 +8,30 @@ module ForemanRhCloud
8
8
  #
9
9
  # Foreman Permission | Paths
10
10
  # ---------------------|--------------------------------------------------
11
+ # view_compliance | GET /api/inventory/v1/hosts(/*)
12
+ # view_compliance | GET /api/compliance/v2/systems
13
+ # view_compliance | GET /api/compliance/v2/systems/{system_id}
14
+ # view_compliance | GET /api/compliance/v2/systems/os_versions
15
+ # view_compliance | GET /api/compliance/v2/systems/{system_id}/policies
16
+ # view_compliance | GET /api/compliance/v2/systems/{system_id}/reports
17
+ # view_compliance | GET /api/compliance/v2/reports/{report_id}/systems
18
+ # view_compliance | GET /api/compliance/v2/reports/{report_id}/systems/{system_id}
19
+ # view_compliance | GET /api/compliance/v2/reports/{report_id}/systems/os_versions
20
+ # view_compliance | GET /api/compliance/v2/policies/{policy_id}/systems/os_versions
21
+ # view_compliance | GET /api/compliance/v2/*
22
+ # edit_compliance | POST /api/compliance/v2/policies
23
+ # edit_compliance | DELETE /api/compliance/v2/policies/{policy_id}
24
+ # edit_compliance | PATCH /api/compliance/v2/policies/{policy_id}
25
+ # edit_compliance | POST /api/compliance/v2/policies/{policy_id}/systems
26
+ # edit_compliance | DELETE /api/compliance/v2/policies/{policy_id}/systems/{system_id}
27
+ # edit_compliance | PATCH /api/compliance/v2/policies/{policy_id}/systems/{system_id}
28
+ # edit_compliance | POST /api/compliance/v2/policies/{policy_id}/tailorings
29
+ # edit_compliance | PATCH /api/compliance/v2/policies/{policy_id}/tailorings/{tailoring_id}
30
+ # edit_compliance | POST /api/compliance/v2/policies/{policy_id}/tailorings/{tailoring_id}/rules
31
+ # edit_compliance | DELETE /api/compliance/v2/policies/{policy_id}/tailorings/{tailoring_id}/rules/{rule_id}
32
+ # edit_compliance | PATCH /api/compliance/v2/policies/{policy_id}/tailorings/{tailoring_id}/rules/{rule_id}
33
+ # edit_compliance | DELETE /api/compliance/v2/reports/{report_id}
34
+ #
11
35
  # view_vulnerability | GET /api/inventory/v1/hosts(/*)
12
36
  # view_vulnerability | GET /api/vulnerability/v1/*
13
37
  # | POST /api/vulnerability/v1/vulnerabilities/cves
@@ -24,12 +48,140 @@ module ForemanRhCloud
24
48
  # | POST /api/insights/v1/rule/{rule_id}/unack_hosts/
25
49
  #
26
50
  SCOPED_REQUESTS = [
27
- # Inventory hosts - requires view_vulnerability for GET
51
+ # Inventory hosts - shared dependency;
52
+ # - requires view_compliance or view_vulnerability for GET
28
53
  {
29
54
  test: %r{api/inventory/v1/hosts(/.*)?$},
30
55
  tag_name: :tags,
31
56
  permissions: {
32
- 'GET' => :view_vulnerability,
57
+ 'GET' => [:view_compliance, :view_vulnerability],
58
+ },
59
+ },
60
+ # Policies - requires view_compliance for GET, edit_compliance for POST/DELETE/PATCH
61
+ {
62
+ test: %r{api/compliance/v2/policies(/[^/]*)?$},
63
+ permissions: {
64
+ 'GET' => :view_compliance,
65
+ 'POST' => :edit_compliance,
66
+ 'DELETE' => :edit_compliance,
67
+ 'PATCH' => :edit_compliance,
68
+ },
69
+ },
70
+ # System and policies assigned to them - requires view_compliance for GET, edit_compliance for POST/DELETE/PATCH
71
+ {
72
+ test: %r{api/compliance/v2/policies/[^/]+/systems(/[^/]*)?$},
73
+ tag_name: :tags,
74
+ permissions: {
75
+ 'GET' => :view_compliance,
76
+ 'POST' => :edit_compliance,
77
+ 'DELETE' => :edit_compliance,
78
+ 'PATCH' => :edit_compliance,
79
+ },
80
+ },
81
+ # Tailorings of assigned policies - requires view_compliance for GET, edit_compliance for POST/PATCH
82
+ {
83
+ test: %r{api/compliance/v2/policies/[^/]+/tailorings(/[^/]*)?$},
84
+ permissions: {
85
+ 'GET' => :view_compliance,
86
+ 'POST' => :edit_compliance,
87
+ 'PATCH' => :edit_compliance,
88
+ },
89
+ },
90
+ # Rules of Tailorings - requires view_compliance for GET, edit_compliance for POST/DELETE/PATCH
91
+ {
92
+ test: %r{api/compliance/v2/policies/[^/]+/tailorings/[^/]+/rules(/[^/]*)?$},
93
+ permissions: {
94
+ 'GET' => :view_compliance,
95
+ 'POST' => :edit_compliance,
96
+ 'DELETE' => :edit_compliance,
97
+ 'PATCH' => :edit_compliance,
98
+ },
99
+ },
100
+ # Compliance Reports - requires view_compliance for GET, edit_compliance for DELETE
101
+ {
102
+ test: %r{api/compliance/v2/reports(/[^/]*)?$},
103
+ permissions: {
104
+ 'GET' => :view_compliance,
105
+ 'DELETE' => :edit_compliance,
106
+ },
107
+ },
108
+ # Systems assigned to a report - requires view_compliance for GET
109
+ {
110
+ test: %r{api/compliance/v2/reports/[^/]+/systems$},
111
+ tag_name: :tags,
112
+ permissions: {
113
+ 'GET' => :view_compliance,
114
+ },
115
+ },
116
+ # Individual system in a report - requires view_compliance for GET
117
+ {
118
+ test: %r{api/compliance/v2/reports/[^/]+/systems/[^/]+$},
119
+ tag_name: :tags,
120
+ permissions: {
121
+ 'GET' => :view_compliance,
122
+ },
123
+ },
124
+ # OS versions for systems in a report - requires view_compliance for GET
125
+ {
126
+ test: %r{api/compliance/v2/reports/[^/]+/systems/os_versions$},
127
+ tag_name: :tags,
128
+ permissions: {
129
+ 'GET' => :view_compliance,
130
+ },
131
+ },
132
+ # OS versions for systems in a policy - requires view_compliance for GET
133
+ {
134
+ test: %r{api/compliance/v2/policies/[^/]+/systems/os_versions$},
135
+ tag_name: :tags,
136
+ permissions: {
137
+ 'GET' => :view_compliance,
138
+ },
139
+ },
140
+ # Compliance Systems list - requires view_compliance for GET
141
+ {
142
+ test: %r{api/compliance/v2/systems$},
143
+ tag_name: :tags,
144
+ permissions: {
145
+ 'GET' => :view_compliance,
146
+ },
147
+ },
148
+ # Individual compliance system - requires view_compliance for GET
149
+ {
150
+ test: %r{api/compliance/v2/systems/[^/]+$},
151
+ tag_name: :tags,
152
+ permissions: {
153
+ 'GET' => :view_compliance,
154
+ },
155
+ },
156
+ # OS versions for all systems - requires view_compliance for GET
157
+ {
158
+ test: %r{api/compliance/v2/systems/os_versions$},
159
+ tag_name: :tags,
160
+ permissions: {
161
+ 'GET' => :view_compliance,
162
+ },
163
+ },
164
+ # Policies for a specific system - requires view_compliance for GET
165
+ {
166
+ test: %r{api/compliance/v2/systems/[^/]+/policies$},
167
+ tag_name: :tags,
168
+ permissions: {
169
+ 'GET' => :view_compliance,
170
+ },
171
+ },
172
+ # Reports for a specific system - requires view_compliance for GET
173
+ {
174
+ test: %r{api/compliance/v2/systems/[^/]+/reports$},
175
+ tag_name: :tags,
176
+ permissions: {
177
+ 'GET' => :view_compliance,
178
+ },
179
+ },
180
+ # Other compliance endpoints - GET requires view_compliance
181
+ {
182
+ test: %r{api/compliance/v2/.*},
183
+ permissions: {
184
+ 'GET' => :view_compliance,
33
185
  },
34
186
  },
35
187
  # Vulnerability CVEs list - POST requires view_vulnerability (no tags support per OpenAPI spec)
@@ -136,9 +288,9 @@ module ForemanRhCloud
136
288
 
137
289
  def forward_request(original_request, path, controller_name, user, organization, location)
138
290
  # Check permissions before forwarding
139
- permission = required_permission_for(path, original_request.request_method)
140
- if permission && !user&.can?(permission)
141
- logger.warn("User #{user&.login || 'anonymous'} lacks permission #{permission} for #{original_request.request_method} #{path}")
291
+ permissions = required_permission_for(path, original_request.request_method)
292
+ if permissions && Array(permissions).none? { |p| user&.can?(p) }
293
+ logger.warn("User #{user&.login || 'anonymous'} lacks permissions #{Array(permissions).join(', ')} for #{original_request.request_method} #{path}")
142
294
  raise ::Foreman::PermissionMissingException.new(N_("You do not have permission to perform this action"))
143
295
  end
144
296
 
@@ -106,6 +106,7 @@ module ForemanInventoryUpload
106
106
 
107
107
  def host_ips(host)
108
108
  # Determines and returns the IP addresses associated with a host, applying obfuscation if enabled.
109
+ return {} if host.nil?
109
110
 
110
111
  # If IP obfuscation is enabled for the host return a representation of obfuscated IP addresses.
111
112
  return obfuscated_ips(host) if obfuscate_ips?(host)
@@ -155,10 +156,29 @@ module ForemanInventoryUpload
155
156
 
156
157
  def hostname_match
157
158
  bash_hostname = `uname -n`.chomp
158
- foreman_hostname = ForemanRhCloud.foreman_host&.name
159
- if bash_hostname == foreman_hostname
160
- fqdn(ForemanRhCloud.foreman_host)
161
- elsif Setting[:obfuscate_inventory_hostnames]
159
+ foreman_host = ForemanRhCloud.foreman_host
160
+
161
+ # If bash hostname matches foreman_host, use fqdn
162
+ if foreman_host && bash_hostname == foreman_host.name
163
+ return fqdn(foreman_host)
164
+ end
165
+
166
+ # If no foreman_host, try foreman_host_name from Setting[:foreman_url]
167
+ unless foreman_host
168
+ foreman_hostname_from_setting = ForemanRhCloud.foreman_host_name
169
+ if foreman_hostname_from_setting
170
+ # Apply obfuscation if enabled
171
+ return obfuscate_fqdn(foreman_hostname_from_setting) if Setting[:obfuscate_inventory_hostnames]
172
+
173
+ return foreman_hostname_from_setting
174
+ end
175
+ # Otherwise fall through to bash_hostname below
176
+ # NOTE: Containerized foremanctl setups must configure Setting[:foreman_url]
177
+ # as bash hostname may not be available or meaningful in containers
178
+ end
179
+
180
+ # Fallback to bash hostname (with obfuscation if enabled)
181
+ if Setting[:obfuscate_inventory_hostnames]
162
182
  obfuscate_fqdn(bash_hostname)
163
183
  else
164
184
  bash_hostname
@@ -166,6 +186,8 @@ module ForemanInventoryUpload
166
186
  end
167
187
 
168
188
  def bios_uuid(host)
189
+ return nil if host.nil?
190
+
169
191
  value = fact_value(host, 'dmi::system::uuid') || ''
170
192
  uuid_value(value)
171
193
  end
@@ -96,7 +96,14 @@ module ForemanInventoryUpload
96
96
  end
97
97
 
98
98
  def self.inventory_self_url
99
- inventory_base_url + "?hostname_or_id=#{ForemanRhCloud.foreman_host.fqdn}"
99
+ host = ForemanRhCloud.foreman_host
100
+ hostname = host ? host.fqdn : ForemanRhCloud.foreman_host_name
101
+ if hostname.nil?
102
+ Rails.logger.warn("Cannot determine Foreman hostname for inventory sync. " \
103
+ "Please configure Setting[:foreman_url]. " \
104
+ "Containerized setups must explicitly set this.")
105
+ end
106
+ inventory_base_url + "?hostname_or_id=#{hostname}"
100
107
  end
101
108
 
102
109
  def self.host_by_id_url(host_uuid)
@@ -71,6 +71,17 @@ module ForemanRhCloud
71
71
  :control_organization_insights,
72
72
  'insights_cloud/settings': [:set_org_parameter]
73
73
  )
74
+ # Insights Compliance permissions
75
+ permission(
76
+ :view_compliance,
77
+ {},
78
+ :resource_type => 'ForemanRhCloud'
79
+ )
80
+ permission(
81
+ :edit_compliance,
82
+ {},
83
+ :resource_type => 'ForemanRhCloud'
84
+ )
74
85
  # Insights Vulnerability permissions
75
86
  permission(
76
87
  :view_vulnerability,
@@ -98,19 +109,19 @@ module ForemanRhCloud
98
109
  # Core RH Cloud permissions for inventory upload and sync
99
110
  rh_cloud_permissions = [:view_foreman_rh_cloud, :generate_foreman_rh_cloud, :view_insights_hits, :dispatch_cloud_requests, :control_organization_insights]
100
111
 
101
- # Insights application permissions (Vulnerability, Advisor)
102
- insights_permissions = [:view_vulnerability, :edit_vulnerability, :view_advisor, :edit_advisor]
112
+ # Insights application permissions (Compliance, Vulnerability, Advisor)
113
+ insights_permissions = [:view_compliance, :edit_compliance, :view_vulnerability, :edit_vulnerability, :view_advisor, :edit_advisor]
103
114
 
104
115
  plugin_permissions = rh_cloud_permissions + insights_permissions
105
116
 
106
- read_only_permissions = [:view_foreman_rh_cloud, :view_insights_hits, :view_vulnerability, :view_advisor]
117
+ read_only_permissions = [:view_foreman_rh_cloud, :view_insights_hits, :view_compliance, :view_vulnerability, :view_advisor]
107
118
 
108
119
  role 'ForemanRhCloud', plugin_permissions, 'Role granting permissions to view the hosts inventory,
109
120
  generate a report, upload it to the cloud, download it locally,
110
- and manage Insights Vulnerability and Advisor features'
121
+ and manage Insights Compliance, Vulnerability and Advisor features'
111
122
 
112
123
  role 'ForemanRhCloud Read Only', read_only_permissions, 'Role granting read-only permissions to view
113
- Insights Vulnerability, Advisor, and host inventory'
124
+ Insights Compliance, Vulnerability, Advisor, and host inventory'
114
125
 
115
126
  add_permissions_to_default_roles Role::ORG_ADMIN => plugin_permissions,
116
127
  Role::MANAGER => plugin_permissions,
@@ -1,3 +1,3 @@
1
1
  module ForemanRhCloud
2
- VERSION = '14.1.2'.freeze
2
+ VERSION = '14.2.0'.freeze
3
3
  end
@@ -84,23 +84,50 @@ module ForemanRhCloud
84
84
 
85
85
  # For testing purposes we can override the default hostname with an environment variable SATELLITE_RH_CLOUD_FOREMAN_HOST
86
86
  def self.foreman_host
87
- @foreman_host ||= begin
88
- fullname = foreman_host_name
89
- ::Host.unscoped.friendly.find(fullname)
90
- rescue ActiveRecord::RecordNotFound
91
- # fullname didn't work. Let's try shortname
87
+ return @foreman_host if defined?(@foreman_host)
88
+
89
+ fullname = foreman_host_name
90
+ return @foreman_host = nil unless fullname
91
+
92
+ # Try fullname first
93
+ host = ::Host.unscoped.friendly.where(name: fullname).first
94
+
95
+ # If not found, try shortname
96
+ if host.nil?
92
97
  shortname = /(?<shortname>[^\.]*)\.?.*/.match(fullname)[:shortname]
93
- ::Host.unscoped.friendly.find(shortname)
98
+ host = ::Host.unscoped.friendly.where(name: shortname).first
94
99
  end
100
+
101
+ @foreman_host = host
95
102
  end
96
103
 
97
104
  def self.foreman_host_name
98
- ENV['SATELLITE_RH_CLOUD_FOREMAN_HOST'] || marked_foreman_host&.name || ::SmartProxy.default_capsule.name
105
+ ENV['SATELLITE_RH_CLOUD_FOREMAN_HOST'] || marked_foreman_host&.name || foreman_url_hostname
106
+ end
107
+
108
+ def self.foreman_url_hostname
109
+ return nil unless Setting[:foreman_url]
110
+
111
+ begin
112
+ # Ensure setting is a string to avoid TypeError from URI.parse
113
+ url = Setting[:foreman_url].to_s
114
+ URI.parse(url).host
115
+ rescue URI::InvalidURIError, ArgumentError, TypeError => e
116
+ Rails.logger.warn("Invalid foreman_url setting: #{e.message}")
117
+ nil
118
+ end
99
119
  end
100
120
 
101
121
  def self.marked_foreman_host
102
- ::Host.unscoped.search_for('infrastructure_facet.foreman = true').first
103
- rescue ScopedSearch::QueryNotSupported
122
+ # Find host with infrastructure_facet.foreman_instance = true
123
+ # Facets use a special mechanism in Foreman, so we query the facet table directly
124
+ return nil unless defined?(HostFacets::InfrastructureFacet)
125
+
126
+ facet = HostFacets::InfrastructureFacet.find_by(foreman_instance: true)
127
+ facet&.host
128
+ rescue ActiveRecord::StatementInvalid => e
129
+ # Table might not exist yet during migrations
130
+ Rails.logger.debug("Could not query marked foreman host: #{e.message}")
104
131
  nil
105
132
  end
106
133
 
@@ -13,7 +13,16 @@ module InsightsCloud
13
13
  end
14
14
 
15
15
  def add_satellite_notifications
16
- hits_count = InsightsHit.where(host_id: foreman_host.id).count
16
+ host = foreman_host
17
+
18
+ # Skip if no Foreman host record exists
19
+ unless host
20
+ logger.debug("Skipping Insights notifications: no Foreman host record found")
21
+ blueprint&.notifications&.destroy_all
22
+ return
23
+ end
24
+
25
+ hits_count = InsightsHit.where(host_id: host.id).count
17
26
 
18
27
  # Remove stale notifications
19
28
  blueprint.notifications.destroy_all
@@ -4,7 +4,14 @@ module InventorySync
4
4
  set_callback :step, :around, :create_facets
5
5
 
6
6
  def plan
7
- super(ForemanRhCloud.foreman_host.organization)
7
+ host = ForemanRhCloud.foreman_host
8
+
9
+ if host.nil?
10
+ logger.warn("Skipping self-host inventory sync: no Foreman host record found.")
11
+ return
12
+ end
13
+
14
+ super(host.organization)
8
15
  end
9
16
 
10
17
  def create_facets
@@ -22,7 +29,10 @@ module InventorySync
22
29
  private
23
30
 
24
31
  def add_missing_insights_facet(uuids_hash)
25
- facet = InsightsFacet.find_or_create_by(host_id: ForemanRhCloud.foreman_host.id) do |facet|
32
+ host = ForemanRhCloud.foreman_host
33
+ return unless host # Guard against nil
34
+
35
+ facet = InsightsFacet.find_or_create_by(host_id: host.id) do |facet|
26
36
  facet.uuid = uuids_hash.values.first
27
37
  end
28
38
 
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foreman_rh_cloud",
3
- "version": "14.1.2",
3
+ "version": "14.2.0",
4
4
  "description": "Inventory Upload =============",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -0,0 +1,26 @@
1
+ require 'test_plugin_helper'
2
+ require 'foreman_tasks/test_helpers'
3
+
4
+ class InsightsGenerateNotificationsTest < ActiveSupport::TestCase
5
+ include Dynflow::Testing::Factories
6
+
7
+ setup do
8
+ User.current = User.find_by(login: 'secret_admin')
9
+ end
10
+
11
+ test 'skips notifications when foreman_host is nil' do
12
+ ForemanRhCloud.stubs(:foreman_host).returns(nil)
13
+
14
+ # Ensure blueprint exists or create it
15
+ NotificationBlueprint.find_or_create_by(name: 'insights_satellite_hits') do |bp|
16
+ bp.message = 'Test message'
17
+ bp.level = 'info'
18
+ bp.expires_in = 7.days
19
+ end
20
+
21
+ plan = ForemanTasks.sync_task(InsightsCloud::Async::InsightsGenerateNotifications)
22
+
23
+ # Should not raise an error, task completes successfully
24
+ assert_includes ['success', 'stopped'], plan.state, "Task should complete without error"
25
+ end
26
+ end
@@ -106,4 +106,13 @@ class InventorySelfHostSyncTest < ActiveSupport::TestCase
106
106
 
107
107
  assert_equal @host1_inventory_id, @host1.insights.uuid
108
108
  end
109
+
110
+ test 'skips sync when foreman_host is nil' do
111
+ ForemanRhCloud.stubs(:foreman_host).returns(nil)
112
+
113
+ plan = ForemanTasks.sync_task(InventorySync::Async::InventorySelfHostSync)
114
+
115
+ # Task should be stopped (not executed) when host is nil, not failed
116
+ assert_equal 'stopped', plan.state
117
+ end
109
118
  end
@@ -2,8 +2,9 @@ require 'test_plugin_helper'
2
2
 
3
3
  class ForemanRhCloudSelfHostTest < ActiveSupport::TestCase
4
4
  setup do
5
- # reset cached value
6
- ForemanRhCloud.instance_variable_set(:@foreman_host, nil)
5
+ # reset cached value - must remove the variable entirely, not just set to nil
6
+ ForemanRhCloud.remove_instance_variable(:@foreman_host) if ForemanRhCloud.instance_variable_defined?(:@foreman_host)
7
+ ENV.delete('SATELLITE_RH_CLOUD_FOREMAN_HOST')
7
8
  end
8
9
 
9
10
  test 'finds host by fullname' do
@@ -32,4 +33,51 @@ class ForemanRhCloudSelfHostTest < ActiveSupport::TestCase
32
33
 
33
34
  assert_equal @host, actual
34
35
  end
36
+
37
+ test 'returns nil when host does not exist' do
38
+ ForemanRhCloud.expects(:foreman_host_name).returns('nonexistent.example.com')
39
+
40
+ actual = ForemanRhCloud.foreman_host
41
+
42
+ assert_nil actual
43
+ end
44
+
45
+ test 'returns nil and does not query Host when foreman_host_name is nil' do
46
+ ForemanRhCloud.stubs(:foreman_host_name).returns(nil)
47
+ ::Host.unscoped.friendly.expects(:where).never
48
+
49
+ assert_nil ForemanRhCloud.foreman_host
50
+ end
51
+
52
+ test 'caches nil value to avoid repeated lookups' do
53
+ ForemanRhCloud.expects(:foreman_host_name).once.returns('nonexistent.example.com')
54
+
55
+ 2.times { ForemanRhCloud.foreman_host }
56
+ end
57
+
58
+ test 'extracts hostname from foreman_url setting' do
59
+ Setting[:foreman_url] = 'https://satellite.example.com'
60
+
61
+ actual = ForemanRhCloud.foreman_url_hostname
62
+
63
+ assert_equal 'satellite.example.com', actual
64
+ end
65
+
66
+ test 'handles invalid foreman_url gracefully' do
67
+ # Stub Setting to return invalid URL without validation
68
+ Setting.stubs(:[]).with(:foreman_url).returns('not a valid url')
69
+
70
+ actual = ForemanRhCloud.foreman_url_hostname
71
+
72
+ assert_nil actual
73
+ end
74
+
75
+ test 'foreman_host_name uses foreman_url when marked_foreman_host is nil' do
76
+ ForemanRhCloud.expects(:marked_foreman_host).returns(nil)
77
+ ForemanRhCloud.expects(:foreman_url_hostname).returns('satellite.example.com')
78
+
79
+ actual = ForemanRhCloud.foreman_host_name
80
+
81
+ assert_equal 'satellite.example.com', actual
82
+ end
35
83
  end
@@ -2,7 +2,8 @@ require 'test_plugin_helper'
2
2
 
3
3
  class MetadataGeneratorTest < ActiveSupport::TestCase
4
4
  setup do
5
- ForemanRhCloud.instance_variable_set(:@foreman_host, nil)
5
+ # reset cached value - must remove the variable entirely, not just set to nil
6
+ ForemanRhCloud.remove_instance_variable(:@foreman_host) if ForemanRhCloud.instance_variable_defined?(:@foreman_host)
6
7
  end
7
8
 
8
9
  test 'generates an empty report' do
@@ -64,4 +65,26 @@ class MetadataGeneratorTest < ActiveSupport::TestCase
64
65
  assert_not_nil(slice = slices['test_12345'])
65
66
  assert_equal 3, slice['number_hosts']
66
67
  end
68
+
69
+ test 'generates metadata when foreman_host is nil' do
70
+ ForemanRhCloud.stubs(:foreman_host).returns(nil)
71
+ ForemanRhCloud.stubs(:foreman_host_name).returns('satellite.example.com')
72
+
73
+ generator = ForemanInventoryUpload::Generators::Metadata.new
74
+
75
+ # Should not raise an error
76
+ json_str = nil
77
+ assert_nothing_raised do
78
+ json_str = generator.render do
79
+ end
80
+ end
81
+
82
+ # Verify hostname is from foreman_host_name
83
+ actual = JSON.parse(json_str.join("\n"))
84
+ assert_equal 'satellite.example.com', actual['reporting_host_name']
85
+ # Verify IP and BIOS UUID fields are nil when host is nil
86
+ # This is acceptable per SAT-25889 - cloud services don't rely on these fields
87
+ assert_nil actual['reporting_host_ips']
88
+ assert_nil actual['reporting_host_bios_uuid']
89
+ end
67
90
  end