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.
- checksums.yaml +4 -4
- data/bin/nexpose_servicedesk +17 -0
- data/lib/nexpose_ticketing/config/servicedesk.config +19 -0
- data/lib/nexpose_ticketing/config/servicenow.config +1 -1
- data/lib/nexpose_ticketing/config/ticket_service.config +15 -5
- data/lib/nexpose_ticketing/helpers/jira_helper.rb +5 -5
- data/lib/nexpose_ticketing/helpers/remedy_helper.rb +401 -78
- data/lib/nexpose_ticketing/helpers/servicedesk_helper.rb +337 -0
- data/lib/nexpose_ticketing/helpers/servicenow_helper.rb +68 -52
- data/lib/nexpose_ticketing/queries.rb +251 -23
- data/lib/nexpose_ticketing/ticket_repository.rb +151 -8
- data/lib/nexpose_ticketing/ticket_service.rb +80 -37
- metadata +20 -2
@@ -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 =
|
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(
|
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
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
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(
|
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],
|
189
|
-
|
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?(
|
199
|
-
old_scan_vuln_file = ticket_repository.old_vulns_sites(scan_id: file_site_histories[site_id],
|
200
|
-
|
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
|
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
|
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
|
-
|
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
|
233
|
-
|
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[
|
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(
|
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
|
-
|
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
|
-
|
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.
|
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
|
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
|