nexpose_ticketing 1.0.2 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,39 @@
1
+ module NexposeTicketing
2
+ class TicketMetrics
3
+ attr_accessor :ticket_counts
4
+
5
+ #Create the specific metric collecting methods
6
+ @@ticket_counts = {}
7
+ [:created, :updated, :closed].each do |action|
8
+ @@ticket_counts[action] = 0
9
+ define_method(action) do |increment=nil|
10
+ @@ticket_counts[action] += increment || 1
11
+ end
12
+
13
+ define_method("get_#{action}") do
14
+ @@ticket_counts[action]
15
+ end
16
+ end
17
+
18
+ def initialize
19
+ @start_time = nil
20
+ @log = NexposeTicketing::NxLogger.instance
21
+ end
22
+
23
+ def start
24
+ return if @start_time != nil
25
+ @start_time = Time.now
26
+ end
27
+
28
+ def finish
29
+ return if @start_time == nil
30
+ @time_taken = Time.at(Time.now - @start_time).utc.strftime("%H:%M:%S")
31
+ @start_time = nil
32
+
33
+ @log.log_message("Ticket processing took #{@time_taken} to complete.")
34
+ @@ticket_counts.keys.each do |action|
35
+ @log.log_message("Metrics: #{@@ticket_counts[action]} tickets were #{action}.")
36
+ end
37
+ end
38
+ end
39
+ end
@@ -12,10 +12,24 @@ module NexposeTicketing
12
12
 
13
13
  def initialize(options = nil)
14
14
  @timeout = options[:timeout]
15
+
16
+ # Gets the suffix of the query method signatures based on the mode
17
+ @method_suffix = options[:query_suffix]
18
+
19
+ define_query_methods
15
20
  end
16
21
 
17
- def nexpose_login(nexpose_data)
22
+ def define_query_methods
23
+ methods = Queries.methods.grep Regexp.new (@method_suffix+'$')
18
24
 
25
+ methods.each do |m|
26
+ define_singleton_method m do |options, override=nil|
27
+ request_query(m, options, override)
28
+ end
29
+ end
30
+ end
31
+
32
+ def nexpose_login(nexpose_data)
19
33
  @nsc = Nexpose::Connection.new(nexpose_data[:nxconsole], nexpose_data[:nxuser], nexpose_data[:nxpasswd])
20
34
  @nsc.login
21
35
  @log = NexposeTicketing::NxLogger.instance
@@ -67,8 +81,9 @@ module NexposeTicketing
67
81
  #
68
82
  def load_last_scans(options = {}, report_config = Nexpose::AdhocReportConfig.new(nil, 'sql'))
69
83
  report_config.add_filter('version', '1.2.0')
70
- sites = Array(options[:sites])
71
- tags = Array(options[:tags])
84
+ sites = Array(options[:sites]).map!(&:to_s)
85
+ tags = Array(options[:tags]).map!(&:to_s)
86
+
72
87
  if(options[:tag_run])
73
88
  report_config.add_filter('query', Queries.last_tag_scans)
74
89
  tags.each do |tag|
@@ -84,7 +99,7 @@ module NexposeTicketing
84
99
  #We only care about sites we are monitoring.
85
100
  trimmed_csv = []
86
101
  if(options[:tag_run])
87
- trimmed_csv << 'tag_id, last_scan_fingerprint'
102
+ trimmed_csv << 'tag_id,last_scan_fingerprint'
88
103
  current_tag_id = nil
89
104
  tag_finger_print = ''
90
105
  csv_output.each do |row|
@@ -94,7 +109,7 @@ module NexposeTicketing
94
109
  current_tag_id = row[0].to_i
95
110
  else
96
111
  #New tag ID, finish off the old fingerprint and start on the new one
97
- trimmed_csv << CSV::Row.new('tag_id, last_scan_fingerprint'.split(','), "#{current_tag_id},#{Digest::MD5::hexdigest(tag_finger_print)}".split(','))
112
+ trimmed_csv << CSV::Row.new('tag_id,last_scan_fingerprint'.split(','), "#{current_tag_id},#{Digest::MD5::hexdigest(tag_finger_print)}".split(','))
98
113
  tag_finger_print.clear
99
114
  current_tag_id = row[0].to_i
100
115
  end
@@ -107,7 +122,7 @@ module NexposeTicketing
107
122
  end
108
123
  end
109
124
  unless tag_finger_print.empty?
110
- trimmed_csv << CSV::Row.new('tag_id, last_scan_fingerprint'.split(','), "#{current_tag_id},#{Digest::MD5::hexdigest(tag_finger_print)}".split(','))
125
+ trimmed_csv << CSV::Row.new('tag_id,last_scan_fingerprint'.split(','), "#{current_tag_id},#{Digest::MD5::hexdigest(tag_finger_print)}".split(','))
111
126
  end
112
127
  else
113
128
  trimmed_csv << report_output.lines.first
@@ -117,6 +132,7 @@ module NexposeTicketing
117
132
  end
118
133
  end
119
134
  end
135
+
120
136
  trimmed_csv
121
137
  end
122
138
 
@@ -130,18 +146,17 @@ module NexposeTicketing
130
146
  # - Returns String @vulnerability_categories
131
147
  #
132
148
  def createVulnerabilityFilter(options = {})
133
- @vulnerability_categories = nil
134
- if options.has_key?(:vulnerabilityCategories)
135
- if not options[:vulnerabilityCategories].nil? and not options[:vulnerabilityCategories].empty?
136
- @vulnerability_categories = options[:vulnerabilityCategories].strip.split(',').map {|category| "include:#{category}"}.join(',')
137
- end
149
+ if options[:vulnerabilityCategories].nil? || options[:vulnerabilityCategories].empty?
150
+ return nil
138
151
  end
139
- @vulnerability_categories
152
+
153
+ filter = options[:vulnerabilityCategories].strip.split(',')
154
+ filter.map { |category| "include:#{category}" }.join(',')
140
155
  end
141
156
 
142
- def read_tag_asset_list(cvs_file_name)
157
+ def read_tag_asset_list(csv_file_name)
143
158
  file_identifier_histories = Hash.new(-1)
144
- CSV.foreach(cvs_file_name, headers: true) do |row|
159
+ CSV.foreach(csv_file_name, headers: true) do |row|
145
160
  file_identifier_histories[row[0]] = row[1]
146
161
  end
147
162
  file_identifier_histories
@@ -150,10 +165,8 @@ module NexposeTicketing
150
165
  def generate_tag_asset_list(options = {}, report_config = Nexpose::AdhocReportConfig.new(nil, 'sql'))
151
166
  report_config.add_filter('version', '1.2.0')
152
167
  tags = Array(options[:tags])
153
- report_config.add_filter('query', Queries.last_tag_scans)
154
- tags.each do |tag|
155
- report_config.add_filter('tag', tag)
156
- end
168
+ report_config.add_filter('query', Queries.last_tag_scans)
169
+ tags.each { |tag| report_config.add_filter('tag', tag) }
157
170
 
158
171
  report_output = report_config.generate(@nsc, @timeout)
159
172
  csv_output = CSV.parse(report_output.chomp, headers: :first_row)
@@ -170,6 +183,9 @@ module NexposeTicketing
170
183
  save_to_file(options[:csv_file], trimmed_csv)
171
184
  current_tag_id = row[0].to_i
172
185
  trimmed_csv = []
186
+
187
+ # TODO: test this change
188
+ trimmed_csv << 'asset_id, last_scan_id'
173
189
  end
174
190
  end
175
191
 
@@ -186,14 +202,14 @@ module NexposeTicketing
186
202
  # - +csv_file_name+ - CSV File name.
187
203
  #
188
204
  def save_to_file(csv_file_name, trimmed_csv, saved_file = nil)
189
- saved_file.open(csv_file_name, 'w') { |file| file.puts(trimmed_csv) } unless saved_file.nil?
190
- if saved_file.nil?
191
- dir = File.dirname(csv_file_name)
192
- unless File.directory?(dir)
193
- FileUtils.mkdir_p(dir)
194
- end
195
- File.open(csv_file_name, 'w') { |file| file.puts(trimmed_csv) }
205
+ unless saved_file.nil?
206
+ saved_file.open(csv_file_name, 'w') { |file| file.puts(trimmed_csv) }
207
+ return
196
208
  end
209
+
210
+ dir = File.dirname(csv_file_name)
211
+ FileUtils.mkdir_p(dir) unless File.directory?(dir)
212
+ File.open(csv_file_name, 'w') { |file| file.puts(trimmed_csv) }
197
213
  end
198
214
 
199
215
  # Gets the last scan information from nexpose sans the CSV headers.
@@ -210,212 +226,55 @@ module NexposeTicketing
210
226
  nexpose_ids
211
227
  end
212
228
 
213
- # Gets all the vulnerabilities for a new site or fresh install.
214
- #
215
- # * *Args* :
216
- # - +options+ - A Hash with user configuration information.
217
- # - +nexpose_item_override+ - Override for user-configured tag/site options
218
- #
219
- # * *Returns* :
220
- # - Returns CSV |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
221
- # |url| |summary| |fix|
222
- #
223
- def all_vulns(options = {}, nexpose_item_override = nil)
224
- report_config = @report_helper.generate_sql_report_config()
225
- severity = options[:severity].nil? ? 0 : options[:severity]
226
- report_config.add_filter('version', '1.2.0')
227
- if options[:ticket_mode] == 'V'
228
- report_config.add_filter('query', Queries.all_new_vulns_by_vuln_id(options))
229
- else
230
- report_config.add_filter('query', Queries.all_new_vulns(options))
231
- end
232
-
233
- if nexpose_item_override.nil?
234
- if(options[:tag_run])
235
- nexpose_items = Array(options[:tags])
236
- else
237
- nexpose_items = Array(options[:sites])
238
- end
239
- else
240
- nexpose_items = Array(nexpose_item_override)
241
- end
242
-
243
- if options[:tag_run]
244
- unless nexpose_items.nil? || nexpose_items.empty?
245
- nexpose_items.each do |tag_id|
246
- report_config.add_filter('tag', tag_id)
247
- end
248
- end
249
- else
250
- unless nexpose_items.nil? || nexpose_items.empty?
251
- nexpose_items.each do |site_id|
252
- report_config.add_filter('site', site_id)
253
- end
254
- end
255
- end
256
-
257
- report_config.add_filter('vuln-severity', severity)
258
-
259
- vuln_filter_cats = createVulnerabilityFilter(options)
260
-
261
- if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
262
- report_config.add_filter('vuln-categories', vuln_filter_cats)
263
- end
264
-
265
- @report_helper.save_generate_cleanup_report_config(report_config)
229
+ def request_query(query_name, options = {}, nexpose_items = nil)
230
+ items = Array(nexpose_items || options["#{options[:scan_mode]}s".intern])
231
+
232
+ report_config = generate_config(query_name, options, items)
266
233
  end
267
234
 
268
- # Gets the new vulns from base scan reported_scan_id and the newest / latest scan from a site.
269
- #
270
- # * *Args* :
271
- # - +options+ - A Hash with user configuration information.
272
- #
273
- # * *Returns* :
274
- # - Returns CSV |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
275
- # |url| |summary| |fix|
276
- #
277
- def new_vulns(options = {})
235
+ def generate_config(query_name, options, nexpose_items)
278
236
  report_config = @report_helper.generate_sql_report_config()
279
237
  nexpose_item = options[:nexpose_item]
280
238
  reported_scan_id = options[:scan_id]
281
- fail 'Nexpose item cannot be null or empty' if nexpose_item.nil? || reported_scan_id.nil?
282
- severity = options[:severity].nil? ? 0 : options[:severity]
283
- report_config.add_filter('version', '1.2.0')
284
- if options[:ticket_mode] == 'V'
285
- report_config.add_filter('query', Queries.new_vulns_by_vuln_id_since_scan(options))
286
- else
287
- report_config.add_filter('query', Queries.new_vulns_since_scan(options))
288
- end
289
239
 
290
- if(options[:tag_run])
291
- report_config.add_filter('tag', options[:tag])
292
- else
293
- report_config.add_filter('site', nexpose_item)
240
+ # If it's a non-initial run, we need the last scan ID
241
+ unless options[:initial_run]
242
+ fail 'Nexpose item cannot be null or empty' if nexpose_item.nil? || reported_scan_id.nil?
294
243
  end
295
244
 
296
- report_config.add_filter('vuln-severity', severity)
297
-
298
- vuln_filter_cats = createVulnerabilityFilter(options)
299
-
300
- if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
301
- report_config.add_filter('vuln-categories', vuln_filter_cats)
302
- end
303
-
304
- @report_helper.save_generate_cleanup_report_config(report_config)
305
- end
306
-
307
- # Gets the old vulns from base scan reported_scan_id and the newest / latest scan from a site.
308
- #
309
- # * *Args* :
310
- # - +options+ - A Hash with user configuration information.
311
- #
312
- # * *Returns* :
313
- # - Returns CSV |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
314
- # |url| |summary| |fix|
315
- #
316
- def old_vulns(options = {})
317
- report_config = @report_helper.generate_sql_report_config()
318
- nexpose_item = options[:nexpose_item]
319
- reported_scan_id = options[:scan_id]
320
- fail 'Nexpose item cannot be null or empty' if nexpose_item.nil? || reported_scan_id.nil?
321
- severity = options[:severity].nil? ? 0 : options[:severity]
322
245
  report_config.add_filter('version', '1.2.0')
323
- report_config.add_filter('query', Queries.old_vulns_since_scan(options))
324
-
325
- if(options[:tag_run])
326
- report_config.add_filter('tag', options[:tag])
327
- else
328
- report_config.add_filter('site', nexpose_item)
329
- end
330
-
331
- report_config.add_filter('vuln-severity', severity)
332
-
333
- vuln_filter_cats = createVulnerabilityFilter(options)
246
+ report_config.add_filter('query', Queries.send(query_name, options))
334
247
 
335
- if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
336
- report_config.add_filter('vuln-categories', vuln_filter_cats)
337
- end
338
-
339
- @report_helper.save_generate_cleanup_report_config(report_config)
340
- end
341
-
342
- # Gets information on possible tickets to close based on only having old vulns/IPs and no new/same ones.
343
- # Based on IP address (for 'I' mode) or vuln ID ('V' mode).
344
- #
345
- # * *Args* :
346
- # - +options+ - A Hash with user configuration information.
347
- #
348
- # * *Returns* :
349
- # - Returns CSV |asset_id| |ip_address| |current_scan| |vulnerability_id| |comparison|
350
- #
351
- def tickets_to_close(options = {})
352
- report_config = @report_helper.generate_sql_report_config()
353
- nexpose_item = options[:nexpose_item]
354
- reported_scan_id = options[:scan_id]
355
- fail 'Nexpose item cannot be null or empty' if nexpose_item.nil? || reported_scan_id.nil?
356
- severity = options[:severity].nil? ? 0 : options[:severity]
357
- report_config.add_filter('version', '1.2.0')
358
- if options[:ticket_mode] == 'V'
359
- report_config.add_filter('query', Queries.old_tickets_by_vuln_id(options))
360
- else
361
- report_config.add_filter('query', Queries.old_tickets_by_ip(options))
362
- end
248
+ id_type = options[:tag_run] ? 'tag' : 'site'
363
249
 
364
- if(options[:tag_run])
365
- report_config.add_filter('tag', options[:tag])
250
+ if nexpose_items != nil && !nexpose_items.empty?
251
+ nexpose_items.each { |id| report_config.add_filter(id_type, id) }
366
252
  else
367
- report_config.add_filter('site', nexpose_item)
253
+ item = options[:tag_run] ? options[:tag] : nexpose_item
254
+ report_config.add_filter(id_type, item)
368
255
  end
369
256
 
370
- report_config.add_filter('vuln-severity', severity)
257
+ report_config.add_filter('vuln-severity', options[:severity] || 0)
371
258
 
372
259
  vuln_filter_cats = createVulnerabilityFilter(options)
373
260
 
374
- if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
261
+ unless vuln_filter_cats.nil? || vuln_filter_cats.empty?
375
262
  report_config.add_filter('vuln-categories', vuln_filter_cats)
376
263
  end
377
264
 
378
265
  @report_helper.save_generate_cleanup_report_config(report_config)
379
266
  end
380
267
 
381
-
382
- # Gets all vulns from base scan reported_scan_id and the newest / latest scan from a site. This is
383
- # used for IP-based issue updating. Includes the baseline comparision value ('Old','New', or 'Same').
384
- #
385
- # * *Args* :
386
- # - +options+ - A Hash with user configuration information.
387
- #
388
- # * *Returns* :
389
- # - Returns CSV |asset_id| |ip_address| |current_scan| |vulnerability_id| |solution_id| |nexpose_id|
390
- # |url| |summary| |fix| |comparison|
391
- #
392
- def all_vulns_since(options = {})
393
- report_config = @report_helper.generate_sql_report_config()
394
- nexpose_item = options[:nexpose_item]
395
- reported_scan_id = options[:scan_id]
396
- fail 'Nexpose item cannot be null or empty' if nexpose_item.nil? || reported_scan_id.nil?
397
- severity = options[:severity].nil? ? 0 : options[:severity]
398
- report_config.add_filter('version', '1.2.0')
399
- if options[:ticket_mode] == 'V'
400
- report_config.add_filter('query', Queries.all_vulns_by_vuln_id_since_scan(options))
401
- else
402
- report_config.add_filter('query', Queries.all_vulns_since_scan(options))
403
- end
404
-
405
- if(options[:tag_run])
406
- report_config.add_filter('tag', options[:tag])
407
- else
408
- report_config.add_filter('site', nexpose_item)
409
- end
410
- report_config.add_filter('vuln-severity', severity)
411
-
412
- vuln_filter_cats = createVulnerabilityFilter(options)
413
-
414
- if not vuln_filter_cats.nil? and not vuln_filter_cats.empty?
415
- report_config.add_filter('vuln-categories', vuln_filter_cats)
268
+ def method_missing(name, *args, &block)
269
+ full_method_name = "#{name}#{@method_suffix}"
270
+
271
+ unless Queries.respond_to? full_method_name
272
+ fail %Q{Query request "#{full_method_name}" not understood}
416
273
  end
417
274
 
418
- @report_helper.save_generate_cleanup_report_config(report_config)
275
+ @log.log_message %Q{Creating query request "#{full_method_name}".}
276
+ request_query(full_method_name, args[0], args[1])
419
277
  end
278
+
420
279
  end
421
280
  end