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.
@@ -79,6 +79,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
79
79
  log_message("Loading helper: #{file}")
80
80
  require_relative file
81
81
  end
82
+ log_message("Ticket mode: #{@options[:ticket_mode]}.")
83
+
82
84
  log_message("Enabling helper: #{@helper_data[:helper_name]}.")
83
85
  @helper = eval(@helper_data[:helper_name]).new(@helper_data, @options)
84
86
 
@@ -117,15 +119,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
117
119
 
118
120
  # Generates a full site(s) report ticket(s).
119
121
  def all_site_report(ticket_repository, options, helper)
120
-
121
- sites_to_query = Array.new
122
- if options[:sites].empty?
123
- log_message('No site(s) specified, generating full vulnerability report.')
124
- @ticket_repository.all_site_details.each { |site| sites_to_query << site.id }
125
- else
126
- log_message('Generating full vulnerability report on user entered sites.')
127
- sites_to_query = Array(options[:sites])
128
- end
122
+ log_message('Generating full vulnerability report on user entered sites.')
123
+ sites_to_query = Array(options[:sites])
129
124
 
130
125
  log_message("Generating full vulnerability report on the following sites: #{sites_to_query.join(', ')}")
131
126
 
@@ -133,7 +128,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
133
128
  log_message("Running full vulnerability report on site #{site}")
134
129
  all_vulns_file = ticket_repository.all_vulns(options, site)
135
130
  log_message('Preparing tickets.')
136
- ticket_rate_limiter(options, all_vulns_file, Proc.new { |ticket_batch| helper.prepare_create_tickets(ticket_batch) }, Proc.new { |tickets| helper.create_tickets(tickets) })
131
+ ticket_rate_limiter(options, all_vulns_file, Proc.new { |ticket_batch| helper.prepare_create_tickets(ticket_batch, site) }, Proc.new { |tickets| helper.create_tickets(tickets) })
137
132
  }
138
133
  log_message('Finished process all vulnerabilities.')
139
134
  end
@@ -162,66 +157,107 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
162
157
  # There's a new site we haven't seen before.
163
158
  def full_new_site_report(site_id, ticket_repository, options, helper)
164
159
  log_message("New site id: #{site_id} detected. Generating report.")
165
- new_site_vuln_file = ticket_repository.all_vulns(sites: [site_id], severity: options[:severity])
160
+ new_site_vuln_file = ticket_repository.all_vulns(options, site_id)
166
161
  log_message('Report generated, preparing tickets.')
167
- ticket_rate_limiter(options, new_site_vuln_file, Proc.new {|ticket_batch| helper.prepare_create_tickets(ticket_batch)}, Proc.new {|tickets| helper.create_tickets(tickets)})
162
+ ticket_rate_limiter(options, new_site_vuln_file, Proc.new {|ticket_batch| helper.prepare_create_tickets(ticket_batch, site_id)}, Proc.new {|tickets| helper.create_tickets(tickets)})
168
163
  end
169
164
 
170
165
  # There's a new scan with possibly new vulnerabilities.
171
166
  def delta_site_new_scan(ticket_repository, site_id, options, helper, file_site_histories)
172
167
  log_message("New scan detected for site: #{site_id}. Generating report.")
173
168
 
174
- if options[:ticket_mode] == 'I'
175
- # I-mode tickets require updating the tickets in the target system.
169
+ if options[:ticket_mode] == 'I' || options[:ticket_mode] == 'V'
170
+ # I-mode and V-mode tickets require updating the tickets in the target system.
176
171
  log_message("Scan id for new scan: #{file_site_histories[site_id]}.")
177
172
  all_scan_vuln_file = ticket_repository.all_vulns_sites(scan_id: file_site_histories[site_id],
178
- site_id: site_id,
179
- severity: options[:severity])
180
- if helper.respond_to?("prepare_update_tickets") && helper.respond_to?("update_tickets")
181
- ticket_rate_limiter(options, all_scan_vuln_file, Proc.new {|ticket_batch| helper.prepare_update_tickets(ticket_batch)}, Proc.new {|tickets| helper.update_tickets(tickets)})
173
+ site_id: site_id,
174
+ severity: options[:severity],
175
+ ticket_mode: options[:ticket_mode],
176
+ riskScore: options[:riskScore],
177
+ vulnerabilityCategories: options[:vulnerabilityCategories],
178
+ tags: options[:tags])
179
+
180
+ if helper.respond_to?('prepare_update_tickets') && helper.respond_to?('update_tickets')
181
+ ticket_rate_limiter(options, all_scan_vuln_file, Proc.new {|ticket_batch| helper.prepare_update_tickets(ticket_batch, site_id)}, Proc.new {|tickets| helper.update_tickets(tickets)})
182
182
  else
183
- log_message("Helper does not implement update methods")
184
- fail "Helper using 'I' mode must implement prepare_updates and update_tickets"
183
+ log_message('Helper does not implement update methods')
184
+ fail "Helper using 'I' or 'V' mode must implement prepare_updates and update_tickets"
185
+ end
186
+
187
+ if options[:close_old_tickets_on_update] == 'Y'
188
+ tickets_to_close_file = ticket_repository.tickets_to_close(scan_id: file_site_histories[site_id],
189
+ site_id: site_id,
190
+ severity: options[:severity],
191
+ ticket_mode: options[:ticket_mode],
192
+ riskScore: options[:riskScore],
193
+ vulnerabilityCategories: options[:vulnerabilityCategories],
194
+ tags: options[:tags])
195
+
196
+ if helper.respond_to?('prepare_close_tickets') && helper.respond_to?('close_tickets')
197
+ ticket_rate_limiter(options, tickets_to_close_file, Proc.new {|ticket_batch| helper.prepare_close_tickets(ticket_batch, site_id)}, Proc.new {|tickets| helper.close_tickets(tickets)})
198
+ else
199
+ log_message('Helper does not implement close methods')
200
+ fail 'Helper using \'I\' or \'V\' mode must implement prepare_close_tickets and close_tickets'
201
+ end
185
202
  end
186
203
  else
187
204
  # D-mode tickets require creating new tickets and closing old tickets.
188
- new_scan_vuln_file = ticket_repository.new_vulns_sites(scan_id: file_site_histories[site_id], site_id: site_id,
189
- severity: options[:severity])
205
+ new_scan_vuln_file = ticket_repository.new_vulns_sites(scan_id: file_site_histories[site_id],
206
+ site_id: site_id,
207
+ severity: options[:severity],
208
+ ticket_mode: options[:ticket_mode],
209
+ riskScore: options[:riskScore],
210
+ vulnerabilityCategories: options[:vulnerabilityCategories],
211
+ tags: options[:tags])
212
+
190
213
  preparse = CSV.new(new_scan_vuln_file.path, headers: :first_row)
191
214
  empty_report = preparse.shift.nil?
192
215
  log_message("No new vulnerabilities found in new scan for site: #{site_id}.") if empty_report
193
216
  log_message("New vulnerabilities found in new scan for site #{site_id}, preparing tickets.") unless empty_report
194
217
  unless empty_report
195
- ticket_rate_limiter(options, new_scan_vuln_file, Proc.new {|ticket_batch| helper.prepare_create_tickets(ticket_batch)}, Proc.new {|tickets| helper.create_tickets(tickets)})
218
+ ticket_rate_limiter(options, new_scan_vuln_file, Proc.new {|ticket_batch| helper.prepare_create_tickets(ticket_batch, site_id)}, Proc.new {|tickets| helper.create_tickets(tickets)})
196
219
  end
197
220
 
198
- if helper.respond_to?("prepare_close_tickets") && helper.respond_to?("close_tickets")
199
- old_scan_vuln_file = ticket_repository.old_vulns_sites(scan_id: file_site_histories[site_id], site_id: site_id,
200
- severity: options[:severity])
221
+ if helper.respond_to?('prepare_close_tickets') && helper.respond_to?('close_tickets')
222
+ old_scan_vuln_file = ticket_repository.old_vulns_sites(scan_id: file_site_histories[site_id],
223
+ site_id: site_id,
224
+ severity: options[:severity],
225
+ riskScore: options[:riskScore],
226
+ vulnerabilityCategories: options[:vulnerabilityCategories],
227
+ tags: options[:tags])
228
+
201
229
  preparse = CSV.new(old_scan_vuln_file.path, headers: :first_row, :skip_blanks => true)
202
230
  empty_report = preparse.shift.nil?
203
231
  log_message("No old (closed) vulnerabilities found in new scan for site: #{site_id}.") if empty_report
204
232
  log_message("Old vulnerabilities found in new scan for site #{site_id}, preparing closures.") unless empty_report
205
233
  unless empty_report
206
- ticket_rate_limiter(options, old_scan_vuln_file, Proc.new {|ticket_batch| helper.prepare_close_tickets(ticket_batch)}, Proc.new {|tickets| helper.close_tickets(tickets)})
234
+ ticket_rate_limiter(options, old_scan_vuln_file, Proc.new {|ticket_batch| helper.prepare_close_tickets(ticket_batch, site_id)}, Proc.new {|tickets| helper.close_tickets(tickets)})
207
235
  end
208
236
  else
209
- # Create a log message but do not halt execution of the helper if ticket closeing is not
237
+ # Create a log message but do not halt execution of the helper if ticket closing is not
210
238
  # supported to allow legacy code to execute normally.
211
- log_message('Helper does not impelment close methods.')
239
+ log_message('Helper does not implement close methods.')
212
240
  end
213
241
  end
214
242
  end
215
243
 
244
+
216
245
  def ticket_rate_limiter(options, query_results_file, ticket_prepare_method, ticket_send_method)
217
246
  batch_size_max = (options[:batch_size] + 1)
218
247
  log_message("Batching tickets in sizes: #{options[:batch_size]}")
219
248
 
249
+ #Vulnerability mode is batched by vulnerability_id. The rest are batched by ip_address.
250
+ if @options[:ticket_mode] == 'V'
251
+ batching_field = 'vulnerability_id'
252
+ else
253
+ batching_field = 'ip_address'
254
+ end
255
+
220
256
  # Start the batching
221
257
  query_results_file.rewind
222
258
  csv_header = query_results_file.readline
223
259
  ticket_batch = []
224
- current_ip = -1
260
+ current_batching_value = -1
225
261
  current_csv_row = nil
226
262
 
227
263
  begin
@@ -229,15 +265,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
229
265
  ticket_batch << line
230
266
 
231
267
  CSV.parse(line.chomp, headers: csv_header) do |row|
232
- if current_ip == -1
233
- current_ip = row['ip_address'] unless row['ip_address'] == 'ip_address'
268
+ if current_batching_value == -1
269
+ current_batching_value = row[batching_field.to_s] unless row[batching_field.to_s] == 'current_batching_value'
234
270
  end
235
- current_csv_row = row unless row['ip_address'] == 'ip_address'
271
+ current_csv_row = row unless row[batching_field.to_s] == 'current_batching_value'
236
272
  end
237
273
 
238
274
  if ticket_batch.size >= batch_size_max
239
275
  #Batch target reached. Make sure we end with a complete IP address set (all tickets for a single IP in this batch)
240
- if(current_ip != current_csv_row['ip_address'])
276
+ if(current_batching_value != current_csv_row[batching_field.to_s])
241
277
  log_message('Batch size reached. Sending tickets.')
242
278
 
243
279
  #Move the mismatching line to the next batch
@@ -247,7 +283,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
247
283
  ticket_batch.clear
248
284
  ticket_batch << csv_header
249
285
  ticket_batch << line_holder
250
- current_ip = -1
286
+ current_batching_value = -1
251
287
  end
252
288
  end
253
289
  end
@@ -283,9 +319,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
283
319
  file_site_histories = prepare_historical_data(@ticket_repository, @options)
284
320
  historical_scan_file = File.join(File.dirname(__FILE__), "#{@options[:file_name]}")
285
321
  # If we didn't specify a site || first time run (no scan history), then it gets all the vulnerabilities.
286
- if @options[:sites].empty? || file_site_histories.nil?
322
+ if @options[:sites].nil? || @options[:sites].empty? || file_site_histories.nil?
287
323
  log_message('Storing current scan state before obtaining all vulnerabilities.')
288
- current_scan_state = ticket_repository.load_last_scans(options)
324
+
325
+ if options[:sites].nil? || options[:sites].empty?
326
+ log_message('No site(s) specified, generating for all sites.')
327
+ @ticket_repository.all_site_details.each { |site| (@options[:sites] ||= []) << site.id.to_s }
328
+ log_message("List of sites is now <#{@options[:sites]}>")
329
+ end
330
+
331
+ current_scan_state = ticket_repository.load_last_scans(@options)
289
332
 
290
333
  all_site_report(@ticket_repository, @options, @helper)
291
334
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nexpose_ticketing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Damian Finol
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-15 00:00:00.000000000 Z
11
+ date: 2014-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nexpose
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '2.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: nokogiri
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.6'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.6'
41
55
  description: This gem provides a Ruby implementation of different integrations with
42
56
  ticketing services for Nexpose.
43
57
  email:
@@ -46,6 +60,7 @@ executables:
46
60
  - nexpose_jira
47
61
  - nexpose_servicenow
48
62
  - nexpose_remedy
63
+ - nexpose_servicedesk
49
64
  extensions: []
50
65
  extra_rdoc_files:
51
66
  - README.md
@@ -53,17 +68,20 @@ files:
53
68
  - README.md
54
69
  - bin/nexpose_jira
55
70
  - bin/nexpose_remedy
71
+ - bin/nexpose_servicedesk
56
72
  - bin/nexpose_servicenow
57
73
  - lib/nexpose_ticketing.rb
58
74
  - lib/nexpose_ticketing/config/jira.config
59
75
  - lib/nexpose_ticketing/config/remedy.config
60
76
  - lib/nexpose_ticketing/config/remedy_wsdl/HPD_IncidentInterface_Create_WS.xml
61
77
  - lib/nexpose_ticketing/config/remedy_wsdl/HPD_IncidentInterface_WS.xml
78
+ - lib/nexpose_ticketing/config/servicedesk.config
62
79
  - lib/nexpose_ticketing/config/servicenow.config
63
80
  - lib/nexpose_ticketing/config/servicenow_updateset/Rapid7 Nexpose Ticketing.glide-calgary-02-15-2013__patch2-hotfix5.xml
64
81
  - lib/nexpose_ticketing/config/ticket_service.config
65
82
  - lib/nexpose_ticketing/helpers/jira_helper.rb
66
83
  - lib/nexpose_ticketing/helpers/remedy_helper.rb
84
+ - lib/nexpose_ticketing/helpers/servicedesk_helper.rb
67
85
  - lib/nexpose_ticketing/helpers/servicenow_helper.rb
68
86
  - lib/nexpose_ticketing/nx_logger.rb
69
87
  - lib/nexpose_ticketing/queries.rb