nexpose_servicenow 0.6.2 → 0.7.1

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.
@@ -1,5 +1,7 @@
1
+ require_relative './queries_base'
2
+
1
3
  module NexposeServiceNow
2
- class Queries
4
+ class NexposeQueries < QueriesBase
3
5
  def self.vulnerabilities(options={})
4
6
  "SELECT
5
7
  concat('R7_', vulnerability_id) as ID,
@@ -78,9 +80,9 @@ module NexposeServiceNow
78
80
  def self.vulnerability_references(options={})
79
81
  "SELECT concat('R7_', vulnerability_id) as ID, dvr.Source, dvr.Reference
80
82
  FROM dim_vulnerability
81
- LEFT OUTER JOIN
82
- (SELECT vulnerability_id, dvr.Source, dvr.Reference
83
- FROM dim_vulnerability_reference dvr) dvr USING (vulnerability_id)
83
+ JOIN
84
+ (SELECT vulnerability_id, dvr.Source, dvr.Reference
85
+ FROM dim_vulnerability_reference dvr) dvr USING (vulnerability_id)
84
86
  WHERE date_modified >= '#{options[:vuln_query_date]}'"
85
87
  end
86
88
 
@@ -125,7 +127,7 @@ module NexposeServiceNow
125
127
  WHERE scan_id = lastScan(asset_id)"
126
128
  end
127
129
 
128
- def self.service_definition(options={})
130
+ def self.service_definition(options={})
129
131
  "SELECT DISTINCT on(dsf.name, ds.name, dp.name, port)
130
132
  dsf.name, ds.name as service_name, dp.name as protocol, port
131
133
 
@@ -268,63 +270,56 @@ module NexposeServiceNow
268
270
  end
269
271
 
270
272
  def self.vulnerable_new_items(options={})
271
- standard_filter = if options[:id_type] == 'site'
272
- "MIN(fasv.scan_id) > #{options[:delta]}"
273
- else
274
- "MIN(fasv.date) > '#{options[:delta]}'"
275
- end
276
-
277
273
  cve_filter = self.generate_cve_filter(options[:filters][:cve])
278
274
  date_filter = self.generate_date_filter(options[:filters][:date], false)
279
275
  cvss_filter = self.generate_cvss_filter(options[:filters][:cvss])
280
276
 
281
- "SELECT
282
- CAST(subq.asset_id as text) Configuration_Item,
283
- TRUE as Active,
284
- concat('R7_', subq.vulnerability_id) as Vulnerability,
285
- fasva.first_discovered as First_Found,
286
- fasva.most_recently_discovered as Last_Found,
287
- subq.vulnerability_instances as Times_Found,
288
- subq.ip_address as IP_Address,
289
- coalesce(NULLIF(CONCAT('\"', favi.proof ,'\"'), '\"\"'), 'None') as Proof,
290
- favi.stat_desc as Status,
291
- array_to_string(favi.ports, ' ', '') as Ports,
292
- coalesce(NULLIF(concat(favi.pro_desc, ' (', favi.name, ')') ,'N/A ()'), 'None') as Protocol,
293
- array_to_string(favi.solution_ids, ',', '') as Solutions
294
- FROM (
295
- SELECT fasv.asset_id, fasv.vulnerability_id, vulnerability_instances,
296
- MIN(fasv.scan_id) as first_found, MAX(fasv.scan_id) as latest_found,
297
- s.current_scan, s.host_name, s.ip_address
298
- FROM fact_asset_scan_vulnerability_finding fasv
299
-
300
- #{cve_filter}
301
- #{cvss_filter}
302
-
303
- JOIN (SELECT asset_id, host_name, ip_address, lastScan(asset_id) AS current_scan
304
- FROM dim_asset
305
- ) s ON s.asset_id = fasv.asset_id
306
- GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan, s.host_name, s.ip_address, vulnerability_instances
307
- HAVING MAX(fasv.scan_id)=current_scan AND #{standard_filter}
308
- ) subq
309
-
310
- JOIN (SELECT asset_id, vulnerability_id,
311
- first_discovered, most_recently_discovered
312
- FROM fact_asset_vulnerability_age
313
- #{date_filter}) fasva USING (asset_id, vulnerability_id)
314
-
315
- JOIN (SELECT DISTINCT on(asset_id, vulnerability_id, scan_id)
316
- asset_id, scan_id, vulnerability_id,
317
- proofAsText(proof) as proof, vs.description as stat_desc,
318
- array_agg(DISTINCT port) as ports, dp.name,
319
- dp.description as pro_desc,
320
- array_agg(DISTINCT dvs.solution_id) as solution_ids
321
- FROM fact_asset_vulnerability_instance
322
- INNER JOIN dim_protocol dp USING (protocol_id)
323
- INNER JOIN dim_vulnerability_status vs using (status_id)
324
- LEFT JOIN dim_asset_vulnerability_solution dvs USING (asset_id, vulnerability_id)
325
- GROUP BY asset_id, scan_id, vulnerability_id, proof, stat_desc, port, dp.name, pro_desc
326
- ) favi ON favi.asset_id = subq.asset_id AND favi.scan_id = subq.current_scan AND favi.vulnerability_id = subq.vulnerability_id
327
- ORDER BY fasva.asset_id, vulnerability"
277
+ "SELECT CAST(asset_id as text) Configuration_Item,
278
+ TRUE as Active,
279
+ concat('R7_', vulnerability_id) as Vulnerability,
280
+ first_discovered as First_Found,
281
+ most_recently_discovered as Last_Found,
282
+ vulnerability_instances as Times_Found,
283
+ ip_address as IP_Address,
284
+ proof as Proof,
285
+ status as Status,
286
+ ports as Ports,
287
+ protocol as Protocol,
288
+ array_to_string(dvsol.solution_ids, ',', '') as Solutions
289
+ FROM
290
+ (SELECT asset_id, scan_id, vulnerability_id, vulnerability_instances
291
+ FROM fact_asset_vulnerability_finding
292
+ WHERE (asset_id, vulnerability_id) NOT IN
293
+ (SELECT asset_id, vulnerability_id
294
+ FROM fact_asset_scan_vulnerability_finding
295
+ WHERE scan_id=#{options[:delta]})) favf
296
+ #{cve_filter}
297
+ #{cvss_filter}
298
+ JOIN (SELECT asset_id, vulnerability_id,
299
+ first_discovered, most_recently_discovered
300
+ FROM fact_asset_vulnerability_age #{date_filter}) fasva USING (asset_id, vulnerability_id)
301
+ JOIN (SELECT asset_id,
302
+ vulnerability_id,
303
+ string_agg(proof, E'\n') as proof,
304
+ array_to_string(array_agg(DISTINCT port), ' ', '') as ports,
305
+ string_agg(DISTINCT status, ',') as status,
306
+ string_agg(DISTINCT protocol, ',') as protocol
307
+ FROM (SELECT asset_id, vulnerability_id,
308
+ proofAsText(proof) as proof,
309
+ status_id as status_id,
310
+ port,
311
+ dp.description as protocol,
312
+ dvs.description as status
313
+ FROM fact_asset_vulnerability_instance
314
+ JOIN dim_protocol dp USING (protocol_id)
315
+ JOIN dim_vulnerability_status dvs USING (status_id)) favi
316
+ GROUP BY asset_id, vulnerability_id) favi USING (asset_id, vulnerability_id)
317
+ JOIN (SELECT asset_id, ip_address
318
+ FROM dim_asset) s USING (asset_id)
319
+ LEFT JOIN (SELECT asset_id, vulnerability_id,
320
+ array_agg(DISTINCT solution_id) as solution_ids
321
+ FROM dim_asset_vulnerability_solution
322
+ GROUP BY asset_id, vulnerability_id) dvsol USING (asset_id, vulnerability_id)"
328
323
  end
329
324
 
330
325
  def self.vulnerable_old_items(options={})
@@ -346,33 +341,31 @@ module NexposeServiceNow
346
341
  'MIN(fasv.scan_id) as first_found,'
347
342
  end
348
343
 
349
- "SELECT
344
+ "SELECT
350
345
  CAST(da.asset_id as text) Configuration_Item,
351
346
  FALSE as Active,
352
- concat('R7_', subq.vulnerability_id) as Vulnerability,
353
- da.ip_address as IP_Address
347
+ concat('R7_', subq.vulnerability_id) as Vulnerability
354
348
  FROM (
355
349
  SELECT fasv.asset_id, fasv.vulnerability_id,
356
350
  #{date_field}
357
351
  MAX(fasv.scan_id) as latest_found,
358
- s.current_scan, s.host_name, s.ip_address
359
- FROM fact_asset_scan_vulnerability_finding fasv
352
+ s.current_scan
353
+ FROM fact_asset_scan_vulnerability_finding fasv
360
354
 
361
355
  #{cve_filter}
362
356
  #{cvss_filter}
363
357
 
364
358
  JOIN (
365
- SELECT asset_id, host_name, ip_address, lastScan(asset_id) AS current_scan FROM dim_asset
359
+ SELECT asset_id, lastScan(asset_id) AS current_scan FROM dim_asset
366
360
  ) s ON s.asset_id = fasv.asset_id
367
- GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan, s.host_name, s.ip_address, vulnerability_instances
361
+ GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
368
362
 
369
363
  HAVING MAX(fasv.scan_id) < current_scan
370
364
  AND #{standard_filter}
371
365
  ) subq
372
366
 
373
367
  JOIN dim_asset da ON subq.asset_id = da.asset_id
374
- #{date_filter}
375
- ORDER BY da.ip_address"
368
+ #{date_filter}"
376
369
 
377
370
  end
378
371
 
@@ -424,31 +417,9 @@ module NexposeServiceNow
424
417
  end
425
418
 
426
419
  def self.latest_scans(options={})
427
- 'SELECT ds.site_id, ds.last_scan_id, dsc.finished
420
+ 'SELECT ds.site_id, ds.name, ds.last_scan_id, dsc.finished
428
421
  FROM dim_site ds
429
422
  JOIN dim_scan dsc ON ds.last_scan_id = dsc.scan_id'
430
423
  end
431
-
432
- def self.multiple_reports?(query_name)
433
- single_queries = %w(vulnerabilities vulnerability_category
434
- asset_groups latest_scans
435
- vulnerability_solutions vulnerability_references
436
- )
437
- return !(single_queries.include? query_name.to_s)
438
- end
439
-
440
- def self.csv_diff_required?(query_name)
441
- diff_required = %w(asset_groups asset_group_memberships)
442
- return (diff_required.include? query_name.to_s)
443
- end
444
-
445
- # TODO: Refactor this.
446
- def self.query_keys(query_name)
447
- if query_name.to_s == 'asset_groups'
448
- [0]
449
- else
450
- [0,1]
451
- end
452
- end
453
424
  end
454
425
  end
@@ -0,0 +1,25 @@
1
+ module NexposeServiceNow
2
+ class QueriesBase
3
+ def self.single_report?(query_name)
4
+ single_queries = %w(vulnerabilities vulnerability_category
5
+ asset_groups latest_scans
6
+ vulnerability_solutions vulnerability_references
7
+ )
8
+ return single_queries.include? query_name.to_s
9
+ end
10
+
11
+ def self.csv_diff_required?(query_name)
12
+ diff_required = %w(asset_groups asset_group_memberships)
13
+ return (diff_required.include? query_name.to_s)
14
+ end
15
+
16
+ # TODO: Refactor this.
17
+ def self.query_keys(query_name)
18
+ if query_name.to_s == 'asset_groups'
19
+ [0]
20
+ else
21
+ [0,1]
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,330 @@
1
+ require_relative './queries_base'
2
+ require_relative '../nx_logger'
3
+
4
+ module NexposeServiceNow
5
+ class WarehouseQueries < QueriesBase
6
+ def self.latest_scans(options={})
7
+ 'SELECT ds.site_id, ds.name, ds.last_scan_id, dsc.finished
8
+ FROM dim_site ds
9
+ JOIN dim_scan dsc ON ds.last_scan_id = dsc.scan_id'
10
+ end
11
+
12
+ def self.vulnerabilities(options={})
13
+ "SELECT
14
+ concat('R7_', vulnerability_id) AS ID,
15
+ cve.ref AS CVE,
16
+ cwe.ref AS CWE,
17
+ concat('Rapid7 Nexpose') AS Source,
18
+ to_char(date_published, 'yyyy-MM-dd hh:mm:ss') AS date_published,
19
+ to_char(date_modified, 'yyyy-MM-dd hh:mm:ss') AS Last_Modified,
20
+ dvc.category,
21
+ severity AS Severity_Rating,
22
+ severity_score AS Severity,
23
+ pci_status,
24
+ pci_adjusted_cvss_score AS PCI_Severity,
25
+ coalesce(NULLIF(CONCAT('\"',regexp_replace(title, '\"','''', 'g'),'\"'), '\"\"'), 'None') AS Summary,
26
+ coalesce(NULLIF(CONCAT('\"',regexp_replace(htmltotext(description), '\"','''', 'g'),'\"'), '\"\"'), 'None') AS Threat,
27
+ ROUND(risk_score :: NUMERIC, 2) AS Riskscore,
28
+ cvss_vector,
29
+ ROUND(cvss_impact_score :: NUMERIC, 2) AS Impact_Score,
30
+ ROUND(cvss_exploit_score :: NUMERIC, 2) AS Exploit_Score,
31
+ cvss_access_complexity AS Access_Complexity,
32
+ cvss_access_vector AS Access_Vector,
33
+ cvss_authentication AS Authentication,
34
+ ROUND(cvss_score :: NUMERIC, 2) AS Vulnerability_Score,
35
+ cvss_integrity_impact AS Integrity_Impact,
36
+ cvss_confidentiality_impact AS Confidentiality_Impact,
37
+ cvss_availability_impact AS Availability_Impact,
38
+ (CASE
39
+ WHEN exploits > 0
40
+ THEN 'true'
41
+ ELSE 'false'
42
+ END) AS Exploitability,
43
+ (CASE
44
+ WHEN malware_kits > 0
45
+ THEN 'true'
46
+ ELSE 'false'
47
+ END) AS Malware_Kits,
48
+ NULLIF(CONCAT('\"', array_to_string(sol.solutions, ',', ''), '\"'), '\"\"') AS Solution
49
+ FROM
50
+ dim_vulnerability
51
+ LEFT OUTER JOIN
52
+ (SELECT DISTINCT ON (vulnerability_id)
53
+ vulnerability_id,
54
+ dvr.reference AS ref
55
+ FROM dim_vulnerability_reference dvr
56
+ WHERE source = 'CWE'
57
+ GROUP BY dvr.vulnerability_id, dvr.reference
58
+ ) cwe USING (vulnerability_id)
59
+ LEFT OUTER JOIN
60
+ (SELECT DISTINCT ON (vulnerability_id)
61
+ vulnerability_id,
62
+ dvr.reference AS ref
63
+ FROM dim_vulnerability_reference dvr
64
+ WHERE source = 'CVE'
65
+ GROUP BY dvr.vulnerability_id, dvr.reference
66
+ ) cve USING (vulnerability_id)
67
+ LEFT OUTER JOIN (SELECT DISTINCT ON (dvc.vulnerability_id)
68
+ dvc.vulnerability_id,
69
+ dvc.category_name AS category
70
+ FROM dim_vulnerability_category dvc
71
+ GROUP BY dvc.vulnerability_id, dvc.category_name) dvc USING (vulnerability_id)
72
+ LEFT OUTER JOIN (SELECT
73
+ dvr.vulnerability_id,
74
+ string_agg(dvr.source || ': ' || dvr.reference, '|') AS references
75
+ FROM dim_vulnerability_reference dvr
76
+ GROUP BY dvr.vulnerability_id) ref USING (vulnerability_id)
77
+ LEFT OUTER JOIN (SELECT
78
+ vulnerability_id,
79
+ array_agg(solution_id) AS solutions
80
+ FROM dim_vulnerability_solution
81
+ GROUP BY vulnerability_id) sol USING (vulnerability_id)
82
+ WHERE date_modified >= '#{options[:vuln_query_date]}'"
83
+ end
84
+
85
+ def self.vulnerability_references(options={})
86
+ "SELECT concat('R7_', vulnerability_id) as ID,
87
+ Source,
88
+ Reference
89
+ FROM (SELECT vulnerability_id
90
+ FROM dim_vulnerability
91
+ WHERE date_modified >= '#{options[:vuln_query_date]}') dv
92
+ JOIN (SELECT vulnerability_id, Source, Reference
93
+ FROM dim_vulnerability_reference) dvr USING (vulnerability_id)"
94
+ end
95
+
96
+ def self.vulnerability_category(options={})
97
+ "SELECT concat('R7_', vulnerability_id) as ID, dvc.Category
98
+ FROM dim_vulnerability
99
+ LEFT OUTER JOIN
100
+ (SELECT vulnerability_id, category_name as Category
101
+ FROM dim_vulnerability_category dvc) dvc USING (vulnerability_id)
102
+ WHERE date_modified >= '#{options[:vuln_query_date]}'"
103
+ end
104
+
105
+ def self.assets(options={})
106
+ last_import_date = options[:delta]
107
+ site_id = options[:site_id]
108
+
109
+ "WITH scan_found AS (
110
+ SELECT DISTINCT (asset_id)
111
+ asset_id,
112
+ MIN(scan_id) AS scan_found
113
+ FROM fact_asset_event
114
+ WHERE type = 'SCAN'
115
+ GROUP BY asset_id
116
+ ), new_assets AS (
117
+ SELECT
118
+ sf.asset_id
119
+ FROM dim_scan ds
120
+ JOIN scan_found sf ON (ds.scan_id = sf.scan_found)
121
+ WHERE ds.finished > '#{last_import_date}'
122
+ AND ds.site_id = #{site_id}
123
+ )
124
+ SELECT
125
+ coalesce(host_name, CAST(dim_asset.asset_id AS TEXT)) AS Name,
126
+ dim_asset.ip_address,
127
+ dim_asset.mac_address,
128
+ concat('Rapid7 Nexpose') AS Discovery_Source,
129
+ CAST(CASE
130
+ WHEN dim_asset.host_type = 'Virtual Machine' OR dim_asset.host_type = 'Hypervisor'
131
+ THEN 1
132
+ ELSE 0
133
+ END AS BIT) AS Is_Virtual,
134
+ CONCAT('\"', dim_asset.os_description, '\"') AS Operating_System,
135
+ dim_asset.last_assessed_for_vulnerabilities AS Most_Recent_Discovery,
136
+ dim_asset.asset_id AS Nexpose_ID,
137
+ fact_asset.pci_status,
138
+ dim_asset.credential_status
139
+ FROM dim_asset
140
+ JOIN fact_asset USING (asset_id)
141
+ WHERE dim_asset.asset_id IN (
142
+ SELECT asset_id
143
+ FROM new_assets
144
+ )"
145
+ end
146
+
147
+ def self.generate_vulnerability_filter(cves, cvss_range)
148
+ return '' if cves.to_a.empty? && cvss_range.to_a.empty?
149
+ vuln_filter = ''
150
+ vuln_filter += cves.map { |c| "reference='#{c}'" }.join(' OR ') unless cves.nil?
151
+
152
+ cvss_min = cvss_range.first || '0'
153
+ cvss_max = cvss_range.last || '10'
154
+ unless cvss_min.to_s == '0' && cvss_max.to_s == '10'
155
+ vuln_filter += ' AND ' unless vuln_filter.empty?
156
+ vuln_filter += "cvss_score >= #{cvss_min} AND cvss_score <= #{cvss_max}"
157
+ end
158
+ return '' if vuln_filter.empty?
159
+
160
+ "AND favi.vulnerability_id IN (
161
+ SELECT dvr.vulnerability_id
162
+ FROM dim_vulnerability_reference dvr
163
+ JOIN dim_vulnerability dv ON dv.vulnerability_id = dvr.vulnerability_id
164
+ WHERE dvr.vulnerability_id IN (SELECT av.vulnerability_id FROM asset_vulns av)
165
+ AND #{vuln_filter})"
166
+ end
167
+
168
+ def self.generate_date_filter(dates)
169
+ return '' if dates.to_a.empty?
170
+ filters = []
171
+ filters << "first_found > '#{dates.first}'" unless dates.first.nil?
172
+ filters << "first_found < '#{dates.last}'" unless dates.last.nil?
173
+ filters.empty? ? '' : " AND #{filters.join(' AND ')}"
174
+ end
175
+
176
+ def self.vulnerable_new_items(options={})
177
+ site_id = options[:site_id]
178
+ last_import_date = options[:delta]
179
+ vuln_filter = self.generate_vulnerability_filter(
180
+ options[:filters][:cve], options[:filters][:cvss]
181
+ )
182
+ date_filters = self.generate_date_filter(options[:filters][:date])
183
+
184
+ "WITH asset_vulns AS (
185
+ SELECT DISTINCT ON (favf.asset_id, favf.vulnerability_id)
186
+ favf.asset_id,
187
+ favf.vulnerability_id,
188
+ favf.date AS first_found,
189
+ favf.vulnerability_instances,
190
+ ip_address,
191
+ (SELECT max(date)
192
+ FROM fact_asset_event fae
193
+ WHERE type = 'SCAN'
194
+ AND fae.asset_id = favf.asset_id
195
+ GROUP BY fae.asset_id) AS last_found
196
+ FROM fact_asset_vulnerability_finding favf
197
+ JOIN dim_site_asset dsa ON favf.asset_id = dsa.asset_id AND dsa.site_id = #{site_id}
198
+ JOIN dim_asset da ON favf.asset_id = da.asset_id
199
+ WHERE date > '#{last_import_date}'
200
+ ), valid_vulns AS (
201
+ SELECT DISTINCT ON (favi.asset_id, favi.vulnerability_id)
202
+ favi.asset_id,
203
+ favi.vulnerability_id,
204
+ array_agg(DISTINCT favi.port) AS ports,
205
+ array_agg(DISTINCT davs.solution_id) AS solutions,
206
+ favi.protocol,
207
+ regexp_replace(htmltotext(favi.proof), '\"','''', 'g') AS proof,
208
+ favi.status
209
+ FROM fact_asset_vulnerability_instance favi
210
+ LEFT JOIN dim_asset_vulnerability_finding_solution davs ON
211
+ davs.asset_id = favi.asset_id AND davs.vulnerability_id = favi.vulnerability_id
212
+ WHERE (favi.vulnerability_id, favi.asset_id) IN (SELECT av.vulnerability_id, av.asset_id FROM asset_vulns av)
213
+ #{vuln_filter}
214
+ GROUP BY favi.asset_id, favi.vulnerability_id, protocol, proof, status
215
+ )
216
+ SELECT
217
+ CAST(nv.asset_id AS TEXT) AS Configuration_Item,
218
+ 'true' AS Active,
219
+ concat('R7_', nv.vulnerability_id) AS Vulnerability,
220
+ nv.first_found AS First_Found,
221
+ nv.last_found AS Last_Found,
222
+ nv.vulnerability_instances AS Times_Found,
223
+ nv.ip_address AS IP_Address,
224
+ coalesce(NULLIF(CONCAT('\"', vv.proof, '\"'), '\"\"'), 'None') AS Proof,
225
+ vv.status AS Status,
226
+ array_to_string(vv.ports, ' ', '') AS Ports,
227
+ coalesce(vv.protocol, 'None') AS Protocol,
228
+ NULLIF(CONCAT('\"', array_to_string(vv.solutions, ',', ''), '\"'), '\"\"') AS Solutions
229
+ FROM asset_vulns nv
230
+ JOIN valid_vulns vv ON vv.asset_id = nv.asset_id AND vv.vulnerability_id = nv.vulnerability_id
231
+ #{date_filters}
232
+ ORDER BY nv.asset_id, Vulnerability"
233
+ end
234
+
235
+ def self.vulnerable_old_items(options={})
236
+ site_id = options[:site_id]
237
+ last_import_date = options[:delta]
238
+ vuln_filter = self.generate_vulnerability_filter(
239
+ options[:filters][:cve], options[:filters][:cvss]
240
+ )
241
+ date_filters = self.generate_date_filter(options[:filters][:date])
242
+
243
+ "WITH site_assets AS (
244
+ SELECT asset_id
245
+ FROM dim_site_asset
246
+ WHERE site_id = #{site_id}
247
+ ), asset_vulns AS (
248
+ -- Asset vulns at last import
249
+ SELECT asset_id, vulnerability_id, date AS first_found
250
+ FROM fact_asset_vulnerability_finding_date
251
+ WHERE asset_id IN (SELECT asset_id FROM site_assets)
252
+ AND DAY = (SELECT periodbefore('#{last_import_date}'))
253
+ ), current_vulns AS (
254
+ SELECT asset_id, vulnerability_id
255
+ FROM fact_asset_vulnerability_finding
256
+ WHERE asset_id IN (SELECT asset_id FROM site_assets)
257
+ )
258
+ SELECT
259
+ CAST(da.asset_id AS TEXT) AS Configuration_Item,
260
+ 'false' AS Active,
261
+ concat('R7_', favi.vulnerability_id) AS Vulnerability,
262
+ da.ip_address AS IP_Address
263
+ FROM dim_asset da
264
+ -- Name this table favi to use the vulnerability ID with the vuln filter.
265
+ JOIN asset_vulns favi ON (da.asset_id = favi.asset_id)
266
+ LEFT JOIN current_vulns cv ON (cv.asset_id = da.asset_id) AND (cv.vulnerability_id = favi.vulnerability_id)
267
+ WHERE da.asset_id IN (SELECT asset_id FROM site_assets)
268
+ AND cv.vulnerability_id IS NULL
269
+ #{vuln_filter}
270
+ #{date_filters}
271
+ ORDER BY da.asset_id, Vulnerability"
272
+ end
273
+
274
+ def self.vulnerability_solutions(options={})
275
+ "SELECT DISTINCT (solution_id)
276
+ solution_id,
277
+ nexpose_id,
278
+ coalesce(NULLIF(CONCAT('\"',regexp_replace(htmltotext(fix), '\"','''', 'g'),'\"'), '\"\"'), 'None') as fix,
279
+ estimate,
280
+ coalesce(NULLIF(CONCAT('\"',regexp_replace(htmltotext(summary), '\"','''', 'g'),'\"'), '\"\"'), 'None') as summary,
281
+ solution_type,
282
+ coalesce(NULLIF(CONCAT('\"',regexp_replace(htmltotext(applies_to), '\"','''', 'g'),'\"'), '\"\"'), 'None') as applies_to,
283
+ coalesce(NULLIF(CONCAT('\"', url, '\"'), '\"\"'), 'None') as url,
284
+ coalesce(NULLIF(CONCAT('\"',regexp_replace(htmltotext(additional_data), '\"','''', 'g'),'\"'), '\"\"'), 'None') as additional_data,
285
+ CONCAT('\"', array_to_string(req_solutions, ',', ''), '\"') as required_solutions,
286
+ CONCAT('\"', array_to_string(super_solutions, ',', ''), '\"') as superceding_solutions
287
+ FROM dim_solution
288
+ RIGHT OUTER JOIN (
289
+ SELECT DISTINCT (solution_id) solution_id
290
+ FROM (
291
+ SELECT solution_id, vulnerability_id, date_modified
292
+ FROM dim_vulnerability
293
+ LEFT JOIN dim_vulnerability_solution idvs USING (vulnerability_id)
294
+ ) dvs
295
+ WHERE date_modified >= '#{options[:vuln_query_date]}'
296
+ UNION
297
+ SELECT DISTINCT (solution_id) solution_id
298
+ FROM dim_solution
299
+ LEFT JOIN (
300
+ SELECT solution_id, vulnerability_id, date_modified
301
+ FROM dim_vulnerability
302
+ LEFT JOIN dim_vulnerability_solution idvs USING (vulnerability_id)
303
+ ) ndvs USING (solution_id)
304
+ WHERE vulnerability_id IS NULL
305
+ ) dvs USING (solution_id)
306
+ LEFT JOIN (
307
+ SELECT DISTINCT (solution_id) solution_id,
308
+ array_agg(required_solution_id) as req_solutions
309
+ FROM dim_solution_prerequisite
310
+ GROUP BY solution_id
311
+ ) dsp USING (solution_id)
312
+ JOIN (
313
+ SELECT DISTINCT (solution_id) solution_id,
314
+ array_agg(superceding_solution_id) as super_solutions
315
+ FROM dim_solution_highest_supercedence
316
+ GROUP BY solution_id
317
+ ) dshs USING (solution_id)
318
+ ORDER BY solution_id"
319
+ end
320
+
321
+ def self.method_missing(m, *args, &block)
322
+ msg = "Method #{m} is not yet available for data warehouse mode."
323
+
324
+ log = NexposeServiceNow::NxLogger.instance
325
+ log.log_message(msg)
326
+ puts "#{msg} Exiting..."
327
+ exit 0
328
+ end
329
+ end
330
+ end