nexpose_ticketing 0.3.1 → 0.5.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.
@@ -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