nexpose_ticketing 0.3.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,6 +4,25 @@ module NexposeTicketing
4
4
  # for Nexpose.
5
5
  # Copyright:: Copyright (c) 2014 Rapid7, LLC.
6
6
  module Queries
7
+
8
+ # Formats SQL query for riskscore based on user config options.
9
+ #
10
+ # * *Args* :
11
+ # - +riskScore+ - riskscore for assets to match in results of query.
12
+ #
13
+ # * *Returns* :
14
+ # - Returns String - Formatted SQL string for inserting into queries.
15
+ #
16
+ def self.createRiskString(riskScore)
17
+ if riskScore.nil?
18
+ riskString = ""
19
+ else
20
+ riskString = "WHERE fa.riskscore >= #{riskScore}"
21
+ end
22
+ return riskString
23
+ end
24
+
25
+
7
26
  # Gets all the latests scans.
8
27
  # Returns |site.id| |last_scan_id| |finished|
9
28
  def self.last_scans
@@ -12,15 +31,16 @@ module NexposeTicketing
12
31
  JOIN dim_scan dsc ON ds.last_scan_id = dsc.scan_id'
13
32
  end
14
33
 
15
- # Gets all delta vulns for all sites.
34
+
35
+ # Gets all delta vulns for all sites sorted by IP.
16
36
  #
17
37
  # * *Returns* :
18
38
  # -Returns |asset_id| |ip_address| |current_scan| |vulnerability_id||solution_id| |nexpose_id|
19
39
  # |url| |summary| |fix|
20
40
  #
21
- def self.all_new_vulns
41
+ def self.all_new_vulns(options = {})
22
42
  "SELECT DISTINCT on (da.ip_address, davs.solution_id) subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, davs.solution_id, ds.nexpose_id,
23
- ds.url,proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix
43
+ ds.url,proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, fa.riskscore
24
44
  FROM (SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan
25
45
  FROM fact_asset_scan_vulnerability_finding fasv
26
46
  JOIN
@@ -34,8 +54,38 @@ module NexposeTicketing
34
54
  JOIN dim_asset_vulnerability_solution davs USING (vulnerability_id)
35
55
  JOIN dim_solution ds USING (solution_id)
36
56
  JOIN dim_asset da ON subs.asset_id = da.asset_id
57
+ JOIN fact_asset fa ON fa.asset_id = da.asset_id
58
+ #{createRiskString( options[:riskScore])}
37
59
  ORDER BY da.ip_address, davs.solution_id"
38
- end
60
+ end
61
+
62
+ # Gets all delta vulns for all sites sorted by vuln ID.
63
+ #
64
+ # * *Returns* :
65
+ # -Returns |asset_id| |ip_address| |current_scan| |vulnerability_id||solution_id| |nexpose_id|
66
+ # |url| |summary| |fix|
67
+ #
68
+ def self.all_new_vulns_by_vuln_id(options = {})
69
+ "SELECT DISTINCT on (subs.vulnerability_id, subs.asset_id, davs.solution_id) subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, dv.title, davs.solution_id, ds.nexpose_id,
70
+ ds.url,proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, fa.riskscore
71
+ FROM (SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan
72
+ FROM fact_asset_scan_vulnerability_finding fasv
73
+ JOIN
74
+ (
75
+ SELECT asset_id, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
76
+ FROM dim_asset) s
77
+ ON s.asset_id = fasv.asset_id AND (fasv.scan_id = s.baseline_scan OR fasv.scan_id = s.current_scan)
78
+ GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan, fasv.scan_id
79
+ HAVING NOT baselineComparison(fasv.scan_id, current_scan) = 'Old'
80
+ ) subs
81
+ JOIN dim_asset_vulnerability_solution davs USING (vulnerability_id)
82
+ JOIN dim_solution ds USING (solution_id)
83
+ JOIN dim_asset da ON subs.asset_id = da.asset_id
84
+ JOIN dim_vulnerability dv ON subs.vulnerability_id = dv.vulnerability_id
85
+ JOIN fact_asset fa ON fa.asset_id = da.asset_id
86
+ #{createRiskString(options[:riskScore])}
87
+ ORDER BY subs.vulnerability_id, subs.asset_id, davs.solution_id"
88
+ end
39
89
 
40
90
  # Gets all new vulnerabilities happening after a reported scan id.
41
91
  #
@@ -46,26 +96,61 @@ module NexposeTicketing
46
96
  # - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
47
97
  # |url| |summary| |fix|
48
98
  #
49
- def self.new_vulns_since_scan(reported_scan)
99
+ def self.new_vulns_since_scan(options = {})
50
100
  "SELECT subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, davs.solution_id, ds.nexpose_id,
51
- ds.url, proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix
101
+ ds.url, proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, fa.riskscore
52
102
  FROM (SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan
53
103
  FROM fact_asset_scan_vulnerability_finding fasv
54
104
  JOIN
55
105
  (
56
106
  SELECT asset_id, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
57
107
  FROM dim_asset) s
58
- ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{reported_scan} OR fasv.scan_id = s.current_scan)
108
+ ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
59
109
  GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
60
110
  HAVING baselineComparison(fasv.scan_id, current_scan) = 'New'
61
111
  ) subs
62
112
  JOIN dim_asset_vulnerability_solution davs USING (vulnerability_id)
63
113
  JOIN dim_solution ds USING (solution_id)
64
114
  JOIN dim_asset da ON subs.asset_id = da.asset_id
65
- AND subs.current_scan > #{reported_scan}
115
+ AND subs.current_scan > #{options[:scan_id]}
116
+ JOIN fact_asset fa ON fa.asset_id = da.asset_id
117
+ #{createRiskString(options[:riskScore])}
66
118
  ORDER BY da.ip_address"
67
119
  end
68
-
120
+
121
+
122
+ # Gets all new vulnerabilities happening after a reported scan id. Sorted by vuln ID.
123
+ #
124
+ # * *Args* :
125
+ # - +reported_scan+ - Last reported scan id.
126
+ #
127
+ # * *Returns* :
128
+ # - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
129
+ # |url| |summary| |fix|
130
+ #
131
+ def self.new_vulns_by_vuln_id_since_scan(options = {})
132
+ "SELECT DISTINCT on (subs.vulnerability_id, subs.asset_id, davs.solution_id) subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, davs.solution_id, ds.nexpose_id,
133
+ ds.url, proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, fa.riskscore
134
+ FROM (SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan
135
+ FROM fact_asset_scan_vulnerability_finding fasv
136
+ JOIN
137
+ (
138
+ SELECT asset_id, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
139
+ FROM dim_asset) s
140
+ ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
141
+ GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
142
+ HAVING baselineComparison(fasv.scan_id, current_scan) = 'New'
143
+ ) subs
144
+ JOIN dim_asset_vulnerability_solution davs USING (vulnerability_id)
145
+ JOIN dim_solution ds USING (solution_id)
146
+ JOIN dim_asset da ON subs.asset_id = da.asset_id
147
+ AND subs.current_scan > #{options[:scan_id]}
148
+ JOIN fact_asset fa ON fa.asset_id = da.asset_id
149
+ #{createRiskString(options[:riskScore])}
150
+ ORDER BY subs.vulnerability_id, subs.asset_id, davs.solution_id"
151
+ end
152
+
153
+
69
154
  # Gets all old vulnerabilities happening after a reported scan id.
70
155
  #
71
156
  # * *Args* :
@@ -75,26 +160,29 @@ module NexposeTicketing
75
160
  # - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
76
161
  # |url| |summary| |fix|
77
162
  #
78
- def self.old_vulns_since_scan(reported_scan)
163
+ def self.old_vulns_since_scan(options = {})
79
164
  "SELECT subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, dvs.solution_id, ds.nexpose_id, ds.url,
80
- proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison
165
+ proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison, fa.riskscore
81
166
  FROM (
82
167
  SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
83
168
  FROM fact_asset_scan_vulnerability_finding fasv
84
169
  JOIN (
85
170
  SELECT asset_id, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
86
171
  FROM dim_asset
87
- ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{reported_scan} OR fasv.scan_id = s.current_scan)
172
+ ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
88
173
  GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
89
174
  HAVING baselineComparison(fasv.scan_id, current_scan) = 'Old'
90
175
  ) subs
91
176
  JOIN dim_vulnerability_solution dvs USING (vulnerability_id)
92
177
  JOIN dim_solution ds USING (solution_id)
93
178
  JOIN dim_asset da ON subs.asset_id = da.asset_id
94
- AND subs.current_scan > #{reported_scan}
179
+ AND subs.current_scan > #{options[:scan_id]}
180
+ JOIN fact_asset fa ON fa.asset_id = da.asset_id
181
+ #{createRiskString(options[:riskScore])}
95
182
  ORDER BY da.ip_address"
96
183
  end
97
-
184
+
185
+
98
186
  # Gets all vulnerabilities happening after a reported scan id. This result set also includes the
99
187
  # baseline comparision ("Old", "New", or "Same") allowing for IP-based ticket updating.
100
188
  #
@@ -105,28 +193,30 @@ module NexposeTicketing
105
193
  # - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
106
194
  # |url| |summary| |fix| |comparison|
107
195
  #
108
- def self.all_vulns_since_scan(reported_scan)
196
+ def self.all_vulns_since_scan(options = {})
109
197
  "SELECT subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, dvs.solution_id, ds.nexpose_id, ds.url,
110
- proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison
198
+ proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison, fa.riskscore
111
199
  FROM (
112
- SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
200
+ SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
113
201
  FROM fact_asset_scan_vulnerability_finding fasv
114
202
  JOIN (
115
203
  SELECT asset_id, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
116
204
  FROM dim_asset
117
- ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{reported_scan} OR fasv.scan_id = s.current_scan)
205
+ ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
118
206
  GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
119
207
  HAVING baselineComparison(fasv.scan_id, current_scan) = 'Old'
120
208
  ) subs
121
209
  JOIN dim_vulnerability_solution dvs USING (vulnerability_id)
122
210
  JOIN dim_solution ds USING (solution_id)
123
211
  JOIN dim_asset da ON subs.asset_id = da.asset_id
124
- AND subs.current_scan > #{reported_scan}
212
+ JOIN fact_asset fa ON fa.asset_id = subs.asset_id
213
+ #{createRiskString(options[:riskScore])}
214
+ AND subs.current_scan > #{options[:scan_id]}
125
215
 
126
216
  UNION
127
217
 
128
218
  SELECT subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, davs.solution_id, ds.nexpose_id, ds.url,
129
- proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison
219
+ proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison, fa.riskscore
130
220
  FROM
131
221
  (
132
222
  SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
@@ -135,17 +225,155 @@ module NexposeTicketing
135
225
  (
136
226
  SELECT asset_id,lastScan(asset_id) AS current_scan
137
227
  FROM dim_asset
138
- ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{reported_scan} OR fasv.scan_id = s.current_scan)
228
+ ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
139
229
  GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
140
230
  HAVING baselineComparison(fasv.scan_id, current_scan) IN ('Same','New')
141
231
  ) subs
142
232
  JOIN dim_asset_vulnerability_solution davs USING (vulnerability_id)
143
233
  JOIN dim_solution ds USING (solution_id)
144
234
  JOIN dim_asset da ON subs.asset_id = da.asset_id
145
- AND subs.current_scan > #{reported_scan}
235
+ JOIN fact_asset fa ON fa.asset_id = subs.asset_id
236
+ #{createRiskString(options[:riskScore])}
237
+ AND subs.current_scan > #{options[:scan_id]}
146
238
 
147
239
  ORDER BY ip_address, comparison"
148
240
  end
149
-
241
+
242
+ # Gets all vulnerabilities happening after a reported scan id. Sorted by vuln ID. This result set also includes the
243
+ # baseline comparision ("Old", "New", or "Same") allowing for IP-based ticket updating.
244
+ #
245
+ # * *Args* :
246
+ # - +reported_scan+ - Last reported scan id.
247
+ #
248
+ # * *Returns* :
249
+ # - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
250
+ # |url| |summary| |fix| |comparison|
251
+ #
252
+ def self.all_vulns_by_vuln_id_since_scan(options = {})
253
+ "SELECT subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, dv.title, dvs.solution_id, ds.nexpose_id, ds.url,
254
+ proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison, fa.riskscore
255
+ FROM (
256
+ SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
257
+ FROM fact_asset_scan_vulnerability_finding fasv
258
+ JOIN (
259
+ SELECT asset_id, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
260
+ FROM dim_asset
261
+ ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
262
+ GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
263
+ HAVING baselineComparison(fasv.scan_id, current_scan) = 'Old'
264
+ ) subs
265
+ JOIN dim_vulnerability_solution dvs USING (vulnerability_id)
266
+ JOIN dim_solution ds USING (solution_id)
267
+ JOIN dim_asset da ON subs.asset_id = da.asset_id
268
+ JOIN dim_vulnerability dv ON subs.vulnerability_id = dv.vulnerability_id
269
+ JOIN fact_asset fa ON fa.asset_id = subs.asset_id
270
+ #{createRiskString(options[:riskScore])}
271
+ AND subs.current_scan > #{options[:scan_id]}
272
+
273
+ UNION
274
+
275
+ SELECT subs.asset_id, da.ip_address, subs.current_scan, subs.vulnerability_id, dv.title, davs.solution_id, ds.nexpose_id, ds.url,
276
+ proofAsText(ds.summary) as summary, proofAsText(ds.fix) as fix, subs.comparison, fa.riskscore
277
+ FROM
278
+ (
279
+ SELECT fasv.asset_id, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
280
+ FROM fact_asset_scan_vulnerability_finding fasv
281
+ JOIN
282
+ (
283
+ SELECT asset_id,lastScan(asset_id) AS current_scan
284
+ FROM dim_asset
285
+ ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
286
+ GROUP BY fasv.asset_id, fasv.vulnerability_id, s.current_scan
287
+ HAVING baselineComparison(fasv.scan_id, current_scan) IN ('Same','New')
288
+ ) subs
289
+ JOIN dim_asset_vulnerability_solution davs USING (vulnerability_id)
290
+ JOIN dim_solution ds USING (solution_id)
291
+ JOIN dim_asset da ON subs.asset_id = da.asset_id
292
+ JOIN dim_vulnerability dv ON subs.vulnerability_id = dv.vulnerability_id
293
+ JOIN fact_asset fa ON fa.asset_id = subs.asset_id
294
+ #{createRiskString(options[:riskScore])}
295
+ AND subs.current_scan > #{options[:scan_id]}
296
+
297
+ ORDER BY vulnerability_id, comparison, asset_id, solution_id"
298
+ end
299
+
300
+
301
+ # Gets all IP addresses that have only old vulnerabilities i.e. any open tickets can be closed.
302
+ #
303
+ # * *Args* :
304
+ # - +reported_scan+ - Last reported scan id.
305
+ #
306
+ # * *Returns* :
307
+ # - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |comparison|
308
+ #
309
+ def self.old_tickets_by_ip(options = {})
310
+ "SELECT subs.asset_id, subs.ip_address, subs.current_scan, subs.vulnerability_id, subs.comparison
311
+ FROM (
312
+ SELECT fasv.asset_id, s.ip_address, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison
313
+ FROM fact_asset_scan_vulnerability_finding fasv
314
+ JOIN (
315
+ SELECT asset_id, ip_address, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
316
+ FROM dim_asset
317
+ ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
318
+ GROUP BY fasv.asset_id, fasv.vulnerability_id, s.ip_address, s.current_scan
319
+ HAVING baselineComparison(fasv.scan_id, current_scan) = 'Old'
320
+ ) AS subs
321
+ WHERE subs.ip_address NOT IN (
322
+
323
+ SELECT s.ip_address
324
+ FROM fact_asset_scan_vulnerability_finding fasv
325
+ JOIN
326
+ (
327
+ SELECT asset_id, ip_address, lastScan(asset_id) AS current_scan
328
+ FROM dim_asset
329
+ ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
330
+ GROUP BY s.ip_address, s.current_scan
331
+ HAVING baselineComparison(fasv.scan_id, current_scan) IN ('Same','New')
332
+ )
333
+ AND subs.current_scan > #{options[:scan_id]}
334
+ ORDER BY subs.ip_address"
335
+ end
336
+
337
+
338
+ # Gets all old vulns that have no active IPs i.e. any open tickets in vuln mode ('V') can be closed.
339
+ #
340
+ # * *Args* :
341
+ # - +reported_scan+ - Last reported scan id.
342
+ #
343
+ # * *Returns* :
344
+ # - Returns |asset_id| |ip_address| |current_scan| |vulnerability_id| |comparison|
345
+ #
346
+ def self.old_tickets_by_vuln_id(options = {})
347
+ "SELECT subs.vulnerability_id, subs.asset_id, subs.ip_address, subs.current_scan, subs.comparison
348
+ FROM (
349
+ SELECT fasv.asset_id, s.ip_address, fasv.vulnerability_id, s.current_scan, baselineComparison(fasv.scan_id, s.current_scan) as comparison, fa.riskscore
350
+ FROM fact_asset_scan_vulnerability_finding fasv
351
+ JOIN (
352
+ SELECT asset_id, ip_address, previousScan(asset_id) AS baseline_scan, lastScan(asset_id) AS current_scan
353
+ FROM dim_asset
354
+ ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
355
+ JOIN fact_asset fa ON fa.asset_id = fasv.asset_id
356
+ #{createRiskString(options[:riskScore])}
357
+ GROUP BY fasv.asset_id, fasv.vulnerability_id, s.ip_address, s.current_scan, fa.riskscore
358
+ HAVING baselineComparison(fasv.scan_id, current_scan) = 'Old'
359
+ ) AS subs
360
+ WHERE subs.vulnerability_id NOT IN (
361
+
362
+ SELECT fasv.vulnerability_id
363
+ FROM fact_asset_scan_vulnerability_finding fasv
364
+ JOIN
365
+ (
366
+ SELECT da.asset_id, da.ip_address, lastScan(da.asset_id) AS current_scan, fa.riskscore
367
+ FROM dim_asset da
368
+ JOIN fact_asset fa ON fa.asset_id = da.asset_id
369
+ #{createRiskString(options[:riskScore])}
370
+ ) s ON s.asset_id = fasv.asset_id AND (fasv.scan_id >= #{options[:scan_id]} OR fasv.scan_id = s.current_scan)
371
+ GROUP BY fasv.vulnerability_id, s.ip_address, s.current_scan
372
+ HAVING baselineComparison(fasv.scan_id, current_scan) IN ('Same','New')
373
+
374
+ )
375
+ AND subs.current_scan > #{options[:scan_id]}
376
+ ORDER BY subs.vulnerability_id"
377
+ end
150
378
  end
151
379
  end
@@ -71,7 +71,7 @@ module NexposeTicketing
71
71
  trimmed_csv = []
72
72
  trimmed_csv << report_output.lines.first
73
73
  csv_output.each do |row|
74
- if sites.include? row.to_s[0]
74
+ if sites.include? row[0].to_s
75
75
  trimmed_csv << row
76
76
  end
77
77
  end
@@ -118,18 +118,34 @@ module NexposeTicketing
118
118
  if site_override.nil?
119
119
  sites = Array(options[:sites])
120
120
  else
121
- sites = site_override
121
+ sites = Array(site_override)
122
122
  end
123
123
  report_config = @report_helper.generate_sql_report_config()
124
124
  severity = options[:severity].nil? ? 0 : options[:severity]
125
125
  report_config.add_filter('version', '1.2.0')
126
- report_config.add_filter('query', Queries.all_new_vulns)
127
- unless sites.empty?
126
+ if options[:ticket_mode] == 'V'
127
+ report_config.add_filter('query', Queries.all_new_vulns_by_vuln_id(options))
128
+ else
129
+ report_config.add_filter('query', Queries.all_new_vulns(options))
130
+ end
131
+ unless sites.nil? || sites.empty?
128
132
  Array(sites).each do |site_id|
129
133
  report_config.add_filter('site', site_id)
130
134
  end
131
135
  end
132
136
  report_config.add_filter('vuln-severity', severity)
137
+
138
+ vuln_filter_cats = createVulnerabilityFilter(options)
139
+ vuln_filer_tags = createTagFilters(options)
140
+
141
+ if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
142
+ report_config.add_filter('vuln-categories', vuln_filter_cats)
143
+ end
144
+
145
+ if not vuln_filer_tags.nil? and not vuln_filer_tags.empty?
146
+ vuln_filer_tags.map {|tag| report_config.add_filter('tag', tag.id) }
147
+ end
148
+
133
149
  @report_helper.save_generate_cleanup_report_config(report_config)
134
150
  end
135
151
 
@@ -149,9 +165,25 @@ module NexposeTicketing
149
165
  fail 'Site cannot be null or empty' if site.nil? || reported_scan_id.nil?
150
166
  severity = site_options[:severity].nil? ? 0 : site_options[:severity]
151
167
  report_config.add_filter('version', '1.2.0')
152
- report_config.add_filter('query', Queries.new_vulns_since_scan(reported_scan_id))
168
+ if site_options[:ticket_mode] == 'V'
169
+ report_config.add_filter('query', Queries.new_vulns_by_vuln_id_since_scan(site_options))
170
+ else
171
+ report_config.add_filter('query', Queries.new_vulns_since_scan(site_options))
172
+ end
153
173
  report_config.add_filter('site', site)
154
174
  report_config.add_filter('vuln-severity', severity)
175
+
176
+ vuln_filter_cats = createVulnerabilityFilter(site_options)
177
+ vuln_filer_tags = createTagFilters(site_options)
178
+
179
+ if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
180
+ report_config.add_filter('vuln-categories', vuln_filter_cats)
181
+ end
182
+
183
+ if not vuln_filer_tags.nil? and not vuln_filer_tags.empty?
184
+ vuln_filer_tags.map {|tag| report_config.add_filter('tag', tag.id) }
185
+ end
186
+
155
187
  @report_helper.save_generate_cleanup_report_config(report_config)
156
188
  end
157
189
 
@@ -171,12 +203,63 @@ module NexposeTicketing
171
203
  fail 'Site cannot be null or empty' if site.nil? || reported_scan_id.nil?
172
204
  severity = site_options[:severity].nil? ? 0 : site_options[:severity]
173
205
  report_config.add_filter('version', '1.2.0')
174
- report_config.add_filter('query', Queries.old_vulns_since_scan(reported_scan_id))
206
+ report_config.add_filter('query', Queries.old_vulns_since_scan(site_options))
175
207
  report_config.add_filter('site', site)
176
208
  report_config.add_filter('vuln-severity', severity)
209
+
210
+ vuln_filter_cats = createVulnerabilityFilter(site_options)
211
+ vuln_filer_tags = createTagFilters(site_options)
212
+
213
+ if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
214
+ report_config.add_filter('vuln-categories', vuln_filter_cats)
215
+ end
216
+
217
+ if not vuln_filer_tags.nil? and not vuln_filer_tags.empty?
218
+ vuln_filer_tags.map {|tag| report_config.add_filter('tag', tag.id) }
219
+ end
220
+
177
221
  @report_helper.save_generate_cleanup_report_config(report_config)
178
222
  end
179
-
223
+
224
+ # Gets information on possible tickets to close based on only having old vulns/IPs and no new/same ones.
225
+ # Based on IP address (for 'I' mode) or vuln ID ('V' mode).
226
+ #
227
+ # * *Args* :
228
+ # - +site_options+ - A Hash with site(s), reported_scan_id and severity level.
229
+ #
230
+ # * *Returns* :
231
+ # - Returns CSV |asset_id| |ip_address| |current_scan| |vulnerability_id| |comparison|
232
+ #
233
+ def tickets_to_close(site_options = {})
234
+ report_config = @report_helper.generate_sql_report_config()
235
+ site = site_options[:site_id]
236
+ reported_scan_id = site_options[:scan_id]
237
+ fail 'Site cannot be null or empty' if site.nil? || reported_scan_id.nil?
238
+ severity = site_options[:severity].nil? ? 0 : site_options[:severity]
239
+ report_config.add_filter('version', '1.2.0')
240
+ if site_options[:ticket_mode] == 'V'
241
+ report_config.add_filter('query', Queries.old_tickets_by_vuln_id(site_options))
242
+ else
243
+ report_config.add_filter('query', Queries.old_tickets_by_ip(site_options))
244
+ end
245
+ report_config.add_filter('site', site)
246
+ report_config.add_filter('vuln-severity', severity)
247
+
248
+ vuln_filter_cats = createVulnerabilityFilter(site_options)
249
+ vuln_filer_tags = createTagFilters(site_options)
250
+
251
+ if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
252
+ report_config.add_filter('vuln-categories', vuln_filter_cats)
253
+ end
254
+
255
+ if not vuln_filer_tags.nil? and not vuln_filer_tags.empty?
256
+ vuln_filer_tags.map {|tag| report_config.add_filter('tag', tag.id) }
257
+ end
258
+
259
+ @report_helper.save_generate_cleanup_report_config(report_config)
260
+ end
261
+
262
+
180
263
  # Gets all vulns from base scan reported_scan_id and the newest / latest scan from a site. This is
181
264
  # used for IP-based issue updating. Includes the baseline comparision value ('Old','New', or 'Same').
182
265
  #
@@ -194,10 +277,70 @@ module NexposeTicketing
194
277
  fail 'Site cannot be null or empty' if site.nil? || reported_scan_id.nil?
195
278
  severity = site_options[:severity].nil? ? 0 : site_options[:severity]
196
279
  report_config.add_filter('version', '1.2.0')
197
- report_config.add_filter('query', Queries.all_vulns_since_scan(reported_scan_id))
280
+ if site_options[:ticket_mode] == 'V'
281
+ report_config.add_filter('query', Queries.all_vulns_by_vuln_id_since_scan(site_options))
282
+ else
283
+ report_config.add_filter('query', Queries.all_vulns_since_scan(site_options))
284
+ end
198
285
  report_config.add_filter('site', site)
199
286
  report_config.add_filter('vuln-severity', severity)
287
+
288
+ vuln_filter_cats = createVulnerabilityFilter(site_options)
289
+ vuln_filer_tags = createTagFilters(site_options)
290
+
291
+ if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
292
+ report_config.add_filter('vuln-categories', vuln_filter_cats)
293
+ end
294
+
295
+ if not vuln_filer_tags.nil? and not vuln_filer_tags.empty?
296
+ vuln_filer_tags.map {|tag| report_config.add_filter('tag', tag.id) }
297
+ end
298
+
200
299
  @report_helper.save_generate_cleanup_report_config(report_config)
201
300
  end
301
+
302
+
303
+ # Parses user-configured vulnerability filter categories and returns aforementioned categories in a
304
+ # format used by the Nexpose::AdhocReportConfig class.
305
+ #
306
+ # * *Args* :
307
+ # - +site_options+ - A Hash with site(s), reported_scan_id and severity level.
308
+ #
309
+ # * *Returns* :
310
+ # - Returns String @vulnerability_categories
311
+ #
312
+ def createVulnerabilityFilter(options = {})
313
+ @vulnerability_categories = nil
314
+ if options.has_key?(:vulnerabilityCategories)
315
+ if not options[:vulnerabilityCategories].nil? and not options[:vulnerabilityCategories].empty?
316
+ @vulnerability_categories = options[:vulnerabilityCategories].strip.split(',').map {|category| "include:#{category}"}.join(',')
317
+ end
318
+ end
319
+ @vulnerability_categories
320
+ end
321
+
322
+ # Parses user-configured tags and returns aforementioned tags in an array containing
323
+ # strings in the format used by the Nexpose::AdhocReportConfig class.
324
+ #
325
+ # * *Args* :
326
+ # - +site_options+ - A Hash with site(s), reported_scan_id and severity level.
327
+ #
328
+ # * *Returns* :
329
+ # - Returns Array @definedTags
330
+ #
331
+ def createTagFilters(options = {})
332
+ @defined_tags = nil
333
+ if options.has_key?(:tags)
334
+ if not options[:tags].nil? and not options[:tags].empty?
335
+ ## Split the tags into an array
336
+ tag_strings = options[:tags].strip.split(',')
337
+
338
+ ## Grab the tag info for the ones we are looking for (if the exist in Nexpose).
339
+ @defined_tags = @nsc.list_tags.select {|nexposeTag| tag_strings.include?(nexposeTag.name)}
340
+ end
341
+ end
342
+ @defined_tags
343
+ end
344
+
202
345
  end
203
346
  end