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.
@@ -6,17 +6,14 @@ require 'csv'
6
6
  require 'savon'
7
7
  require 'nexpose_ticketing/nx_logger'
8
8
  require 'nexpose_ticketing/version'
9
- require 'nexpose_ticketing/common_helper'
9
+ require_relative './base_helper'
10
10
 
11
11
  # Serves as the Remedy interface for creating/updating issues from
12
12
  # vulnelrabilities found in Nexpose.
13
- class RemedyHelper
14
- attr_accessor :remedy_data, :options, :log, :client
15
- def initialize(remedy_data, options)
16
- @remedy_data = remedy_data
17
- @options = options
18
- @log = NexposeTicketing::NxLogger.instance
19
- @common_helper = NexposeTicketing::CommonHelper.new(@options)
13
+ class RemedyHelper < BaseHelper
14
+ attr_accessor :log, :client
15
+ def initialize(service_data, options, mode)
16
+ super(service_data, options, mode)
20
17
  end
21
18
 
22
19
  # Generates a savon-based ticket object.
@@ -26,9 +23,9 @@ class RemedyHelper
26
23
  #
27
24
  def generate_new_ticket(extra_fields=nil)
28
25
  base_ticket = {
29
- 'First_Name' => "#{@remedy_data[:first_name]}",
26
+ 'First_Name' => "#{@service_data[:first_name]}",
30
27
  'Impact' => '1-Extensive/Widespread',
31
- 'Last_Name' => "#{@remedy_data[:last_name]}",
28
+ 'Last_Name' => "#{@service_data[:last_name]}",
32
29
  'Reported_Source' => 'Other',
33
30
  'Service_Type' => 'Infrastructure Event',
34
31
  'Status' => 'New',
@@ -52,13 +49,13 @@ class RemedyHelper
52
49
  Savon.client(wsdl: File.join(File.dirname(__FILE__), "../config/remedy_wsdl/#{wdsl}"),
53
50
  adapter: :net_http,
54
51
  ssl_verify_mode: :none,
55
- open_timeout: @remedy_data[:open_timeout],
56
- read_timeout: @remedy_data[:read_timeout],
57
- endpoint: @remedy_data[endpoint.intern],
52
+ open_timeout: @service_data[:open_timeout],
53
+ read_timeout: @service_data[:read_timeout],
54
+ endpoint: @service_data[endpoint.intern],
58
55
  soap_header: { 'AuthenticationInfo' =>
59
- { 'userName' => "#{@remedy_data[:username]}",
60
- 'password' => "#{@remedy_data[:password]}",
61
- 'authentication' => "#{@remedy_data[:authentication]}"
56
+ { 'userName' => "#{@service_data[:username]}",
57
+ 'password' => "#{@service_data[:password]}",
58
+ 'authentication' => "#{@service_data[:authentication]}"
62
59
  }
63
60
  })
64
61
  end
@@ -95,6 +92,7 @@ class RemedyHelper
95
92
  #
96
93
  def create_tickets(tickets)
97
94
  fail 'Ticket(s) cannot be empty' if tickets.nil? || tickets.empty?
95
+ @metrics.created tickets.count
98
96
  client = get_client('HPD_IncidentInterface_Create_WS.xml', :create_soap_endpoint)
99
97
  send_tickets(client, :help_desk_submit_service, tickets)
100
98
  end
@@ -110,6 +108,7 @@ class RemedyHelper
110
108
  @log.log_message("No tickets to update.")
111
109
  return
112
110
  end
111
+ @metrics.updated tickets.count - @metrics.get_created
113
112
  client = get_client('HPD_IncidentInterface_WS.xml', :query_modify_soap_endpoint)
114
113
  send_tickets(client, :help_desk_modify_service, tickets)
115
114
  end
@@ -125,6 +124,7 @@ class RemedyHelper
125
124
  @log.log_message("No tickets to close.")
126
125
  return
127
126
  end
127
+ @metrics.closed tickets.count
128
128
  client = get_client('HPD_IncidentInterface_WS.xml', :query_modify_soap_endpoint)
129
129
  send_tickets(client, :help_desk_modify_service, tickets)
130
130
  end
@@ -164,19 +164,9 @@ class RemedyHelper
164
164
  # - List of savon-formated (hash) tickets for creating within Remedy.
165
165
  #
166
166
  def prepare_create_tickets(vulnerability_list, nexpose_identifier_id)
167
+ @metrics.start
167
168
  @log.log_message('Preparing ticket requests...')
168
- case @options[:ticket_mode]
169
- # 'D' Default IP *-* Vulnerability
170
- when 'D' then matching_fields = ['ip_address', 'vulnerability_id']
171
- # 'I' IP address -* Vulnerability
172
- when 'I' then matching_fields = ['ip_address']
173
- # 'V' Vulnerability -* Assets
174
- when 'V' then matching_fields = ['vulnerability_id']
175
- else
176
- fail 'Unsupported ticketing mode selected.'
177
- end
178
-
179
- prepare_tickets(vulnerability_list, nexpose_identifier_id, matching_fields)
169
+ prepare_tickets(vulnerability_list, nexpose_identifier_id)
180
170
  end
181
171
 
182
172
  # Prepare to update tickets from the CSV of vulnerabilities exported from Nexpose. This method determines
@@ -189,18 +179,8 @@ class RemedyHelper
189
179
  # - List of savon-formated (hash) tickets for creating within Remedy.
190
180
  #
191
181
  def prepare_update_tickets(vulnerability_list, nexpose_identifier_id)
192
- case @options[:ticket_mode]
193
- # 'D' Default IP *-* Vulnerability
194
- when 'D' then fail 'Ticket updates are not supported in Default mode.'
195
- # 'I' IP address -* Vulnerability
196
- when 'I' then matching_fields = ['ip_address']
197
- # 'V' Vulnerability -* Assets
198
- when 'V' then matching_fields = ['vulnerability_id']
199
- else
200
- fail 'Unsupported ticketing mode selected.'
201
- end
202
-
203
- prepare_tickets(vulnerability_list, nexpose_identifier_id, matching_fields)
182
+ @metrics.start
183
+ prepare_tickets(vulnerability_list, nexpose_identifier_id)
204
184
  end
205
185
 
206
186
  # Prepares a list of vulnerabilities into a list of savon-formatted tickets (incidents) for
@@ -212,7 +192,8 @@ class RemedyHelper
212
192
  # * *Returns* :
213
193
  # - List of savon-formated (hash) tickets for creating within Remedy.
214
194
  #
215
- def prepare_tickets(vulnerability_list, nexpose_identifier_id, matching_fields)
195
+ def prepare_tickets(vulnerability_list, nexpose_identifier_id)
196
+ matching_fields = @mode_helper.get_matching_fields
216
197
  @ticket = Hash.new(-1)
217
198
 
218
199
  @log.log_message("Preparing tickets for #{@options[:ticket_mode]} mode.")
@@ -222,19 +203,21 @@ class RemedyHelper
222
203
  CSV.parse(vulnerability_list.chomp, headers: :first_row) do |row|
223
204
  if previous_row.nil?
224
205
  previous_row = row.dup
225
- description = @common_helper.get_description(nexpose_identifier_id, row)
226
- @ticket = generate_new_ticket({'Summary' => "#{@common_helper.get_title(row, 100)}",
206
+ description = @mode_helper.get_description(nexpose_identifier_id, row)
207
+ @ticket = generate_new_ticket({'Summary' => "#{@mode_helper.get_title(row)}"[0...100],
227
208
  'Notes' => ""})
228
209
  #Skip querying for ticket if it's the initial scan
229
210
  next if row['comparison'].nil?
230
211
 
231
212
  # Query Remedy for the incident by unique id (generated NXID)
232
- queried_incident = query_for_ticket("NXID: #{@common_helper.generate_nxid(nexpose_identifier_id, row)}")
213
+ queried_incident = query_for_ticket("NXID: #{@mode_helper.get_nxid(nexpose_identifier_id, row)}")
233
214
  if !queried_incident.nil? && queried_incident.first.is_a?(Hash)
234
215
  queried_incident.select! { |t| !['Closed', 'Resolved', 'Cancelled'].include?(t[:status]) }
235
216
  end
217
+
236
218
  if queried_incident.nil? || queried_incident.empty?
237
- @log.log_message("No incident found for NXID: #{@common_helper.generate_nxid(nexpose_identifier_id, row)}. Creating...")
219
+ @log.log_message("No incident found for NXID: #{@mode_helper.get_nxid(nexpose_identifier_id, row)}. Creating...")
220
+
238
221
  new_ticket_csv = vulnerability_list.split("\n").first
239
222
  new_ticket_csv += "\n#{row.to_s}"
240
223
 
@@ -250,28 +233,30 @@ class RemedyHelper
250
233
  previous_row = nil
251
234
  redo
252
235
  else
253
- info = @common_helper.get_field_info(matching_fields, previous_row)
236
+ info = @mode_helper.get_field_info(matching_fields, previous_row)
254
237
  @log.log_message("Creating ticket update with #{info} for Nexpose Identifier with ID: #{nexpose_identifier_id}")
255
238
  @log.log_message("Ticket status #{row['comparison']}")
256
239
  # Remedy incident updates require populating all fields.
257
240
  @ticket = extract_queried_incident(queried_incident, "")
258
241
  end
259
242
  elsif matching_fields.any? { |x| previous_row[x].nil? || previous_row[x] != row[x] }
260
- info = @common_helper.get_field_info(matching_fields, previous_row)
243
+ info = @mode_helper.get_field_info(matching_fields, previous_row)
261
244
  @log.log_message("Generated ticket with #{info}")
262
245
 
263
- @ticket['Notes'] = @common_helper.print_description(description)
246
+ @ticket['Notes'] = @mode_helper.print_description(description)
264
247
  tickets.push(@ticket)
265
248
  previous_row = nil
266
249
  description = nil
267
250
  redo
268
251
  else
269
- description = @common_helper.update_description(description, row)
252
+ description = @mode_helper.update_description(description, row)
270
253
  end
271
254
  end
272
255
 
273
256
  unless @ticket.nil? || @ticket.empty?
274
- @ticket['Notes'] = @common_helper.print_description(description)
257
+ info = @mode_helper.get_field_info(matching_fields, previous_row)
258
+ @log.log_message("Creating ticket update with #{info} for Nexpose Identifier with ID: #{nexpose_identifier_id}")
259
+ @ticket['Notes'] = @mode_helper.print_description(description)
275
260
  tickets.push(@ticket)
276
261
  end
277
262
 
@@ -351,7 +336,7 @@ class RemedyHelper
351
336
  return ticket_from_queried_incident(queried_incident, notes_header, nil)
352
337
  end
353
338
 
354
- fail "Multiple tickets returned for same NXID" if queried_incidents.count > 1
339
+ fail "Multiple tickets returned for same NXID" if queried_incident.count > 1
355
340
  ticket_from_queried_incident(queried_incident.first, notes_header, nil)
356
341
  end
357
342
 
@@ -368,7 +353,7 @@ class RemedyHelper
368
353
  @nxid = nil
369
354
  tickets = []
370
355
  CSV.parse(vulnerability_list.chomp, headers: :first_row) do |row|
371
- @nxid = @common_helper.generate_nxid(nexpose_identifier_id, row)
356
+ @nxid = @mode_helper.get_nxid(nexpose_identifier_id, row)
372
357
 
373
358
  # Query Remedy for the incident by unique id (generated NXID)
374
359
  queried_incident = query_for_ticket("NXID: #{@nxid}")
@@ -1,22 +1,19 @@
1
1
  require 'net/http'
2
2
  require 'nokogiri'
3
3
  require 'dbm'
4
- require 'nexpose_ticketing/common_helper'
4
+ require_relative './base_helper'
5
5
  require 'nexpose_ticketing/nx_logger'
6
6
  require 'nexpose_ticketing/version'
7
7
 
8
- class ServiceDeskHelper
9
- attr_accessor :servicedesk_data, :options, :log
8
+ class ServiceDeskHelper < BaseHelper
9
+ attr_accessor :log
10
10
 
11
- def initialize(servicedesk_data, options)
12
- @servicedesk_data = servicedesk_data
13
- @options = options
14
- @log = NexposeTicketing::NxLogger.instance
11
+ def initialize(service_data, options, mode)
12
+ super(service_data, options, mode)
15
13
 
16
- @rest_uri = servicedesk_data[:rest_uri]
17
- @api_key = servicedesk_data[:api_key]
18
- @ticket_db_path = servicedesk_data[:ticket_db_path]
19
- @common_helper = NexposeTicketing::CommonHelper.new(@options)
14
+ @rest_uri = service_data[:rest_uri]
15
+ @api_key = service_data[:api_key]
16
+ @ticket_db_path = service_data[:ticket_db_path]
20
17
  end
21
18
 
22
19
 
@@ -62,26 +59,17 @@ class ServiceDeskHelper
62
59
 
63
60
  def prepare_create_tickets(vulnerability_list, nexpose_identifier_id)
64
61
  @log.log_message('Preparing ticket creation...')
65
- case @options[:ticket_mode]
66
- # 'D' Default IP *-* Vulnerability
67
- when 'D' then matching_fields = ['ip_address', 'vulnerability_id']
68
- # 'I' IP address -* Vulnerability
69
- when 'I' then matching_fields = ['ip_address']
70
- # 'V' Vulnerability -* Assets
71
- when 'V' then matching_fields = ['vulnerability_id']
72
- else
73
- fail 'Unsupported ticketing mode selected.'
74
- end
75
-
76
- tickets = prepare_tickets(vulnerability_list, nexpose_identifier_id, matching_fields)
62
+ tickets = prepare_tickets(vulnerability_list, nexpose_identifier_id)
77
63
 
78
64
  tickets.each { |ticket| @log.log_message("Prepared ticket: #{ticket}")}
79
65
  tickets
80
66
  end
81
67
 
82
68
 
83
- def prepare_tickets(vulnerability_list, nexpose_identifier_id, matching_fields)
69
+ def prepare_tickets(vulnerability_list, nexpose_identifier_id)
70
+ @metrics.start
84
71
  @log.log_message("Preparing ticket for #{@options[:ticket_mode]} mode.")
72
+ matching_fields = @mode_helper.get_matching_fields
85
73
  tickets = []
86
74
  host_vulns={}
87
75
  previous_row = nil
@@ -94,39 +82,40 @@ class ServiceDeskHelper
94
82
  initial_scan = initial_scan || row['comparison'].nil?
95
83
 
96
84
  if previous_row.nil?
97
- nxid = @common_helper.generate_nxid(nexpose_identifier_id, row)
85
+ nxid = @mode_helper.get_nxid(nexpose_identifier_id, row)
98
86
  previous_row = row.dup
99
- description = @common_helper.get_description(nexpose_identifier_id, row)
87
+ description = @mode_helper.get_description(nexpose_identifier_id, row)
100
88
 
101
89
  host_vulns[nxid] = { :ip => row['ip_address'],
102
90
  :description => "",
103
- :title => @common_helper.get_title(row) }
91
+ :title => @mode_helper.get_title(row) }
104
92
  elsif matching_fields.any? { |x| previous_row[x].nil? || previous_row[x] != row[x] }
105
- nxid = @common_helper.generate_nxid(nexpose_identifier_id, previous_row)
106
- info = @common_helper.get_field_info(matching_fields, previous_row)
93
+ info = @mode_helper.get_field_info(matching_fields, previous_row)
107
94
  @log.log_message("Generated ticket with #{info}")
108
95
 
109
- host_vulns[nxid][:description] = @common_helper.print_description(description)
96
+ host_vulns[nxid][:description] = @mode_helper.print_description(description)
110
97
  previous_row = nil
111
98
  description = nil
112
99
  redo
113
100
  else
114
- description = @common_helper.update_description(description, row)
101
+ description = @mode_helper.update_description(description, row)
115
102
  end
116
103
  end
117
104
 
118
105
  unless host_vulns[nxid].nil? || host_vulns[nxid].empty?
119
- host_vulns[nxid][:description] = @common_helper.print_description(description)
106
+ host_vulns[nxid][:description] = @mode_helper.print_description(description)
120
107
  end
121
108
 
122
109
  host_vulns.each do |nxid, vuln_info|
123
110
  workorderid = initial_scan ? nil : find_ticket_in_database(nxid)
124
111
  if workorderid.nil? || workorderid.empty?
125
112
  @log.log_message("Creating new incident for assetid #{nxid}")
113
+ @metrics.created
126
114
  tickets << { :action => :create, :nxid => nxid,
127
115
  :description => create_ticket_request(vuln_info[:title], vuln_info[:description]) }
128
116
  else
129
117
  @log.log_message("Updating incident for assetid #{nxid}")
118
+ @metrics.updated
130
119
  tickets << { :action => :modify, :nxid => nxid,
131
120
  :workorderid => workorderid,
132
121
  :description => modify_ticket_request(vuln_info[:description]) }
@@ -145,7 +134,7 @@ class ServiceDeskHelper
145
134
  xml.text 'requester'
146
135
  }
147
136
  xml.value {
148
- xml.text @servicedesk_data[:requester]
137
+ xml.text @service_data[:requester]
149
138
  }
150
139
  }
151
140
  xml.parameter {
@@ -153,7 +142,7 @@ class ServiceDeskHelper
153
142
  xml.text 'Group'
154
143
  }
155
144
  xml.value {
156
- xml.text @servicedesk_data[:group]
145
+ xml.text @service_data[:group]
157
146
  }
158
147
  }
159
148
  xml.parameter {
@@ -197,7 +186,7 @@ class ServiceDeskHelper
197
186
  xml.text 'requester'
198
187
  }
199
188
  xml.value {
200
- xml.text @servicedesk_data[:requester]
189
+ xml.text @service_data[:requester]
201
190
  }
202
191
  }
203
192
  xml.parameter {
@@ -295,18 +284,7 @@ class ServiceDeskHelper
295
284
 
296
285
  def prepare_update_tickets(vulnerability_list, nexpose_identifier_id)
297
286
  @log.log_message('Preparing ticket updates...')
298
- case @options[:ticket_mode]
299
- # 'D' Default IP *-* Vulnerability
300
- when 'D' then fail 'Ticket updates are not supported in Default mode.'
301
- # 'I' IP address -* Vulnerability
302
- when 'I' then matching_fields = ['ip_address']
303
- # 'V' Vulnerability -* Assets
304
- when 'V' then matching_fields = ['vulnerability_id']
305
- else
306
- fail 'Unsupported ticketing mode selected.'
307
- end
308
-
309
- prepare_tickets(vulnerability_list, nexpose_identifier_id, matching_fields)
287
+ prepare_tickets(vulnerability_list, nexpose_identifier_id)
310
288
  end
311
289
 
312
290
 
@@ -336,7 +314,7 @@ class ServiceDeskHelper
336
314
  @nxid = nil
337
315
  tickets = []
338
316
  CSV.parse(vulnerability_list.chomp, headers: :first_row) do |row|
339
- @nxid = @common_helper.generate_nxid(nexpose_identifier_id, row)
317
+ @nxid = @mode_helper.get_nxid(nexpose_identifier_id, row)
340
318
 
341
319
  workorderid = find_ticket_in_database(@nxid)
342
320
  # Query ServiceDesk for the incident by unique id (generated NXID)
@@ -352,8 +330,11 @@ class ServiceDeskHelper
352
330
  end
353
331
 
354
332
 
333
+
355
334
  def close_tickets( tickets )
356
- tickets.each { |ticket| close_ticket(ticket) if ticket[:action] == :close && !ticket[:workorderid].nil?}
335
+ to_close = tickets.select { |t| t[:action] == :close && !t[:workorderid].nil? }
336
+ @metrics.closed to_close.count
337
+ to_close.each { |ticket| close_ticket(ticket) }
357
338
  remove_tickets_from_database(tickets)
358
339
  end
359
340
  end
@@ -5,18 +5,15 @@ require 'uri'
5
5
  require 'csv'
6
6
  require 'nexpose_ticketing/nx_logger'
7
7
  require 'nexpose_ticketing/version'
8
- require 'nexpose_ticketing/common_helper'
8
+ require_relative './base_helper'
9
9
  require 'securerandom'
10
10
 
11
11
  # Serves as the ServiceNow interface for creating/updating issues from
12
12
  # vulnelrabilities found in Nexpose.
13
- class ServiceNowHelper
14
- attr_accessor :servicenow_data, :options, :log, :transform
15
- def initialize(servicenow_data, options)
16
- @servicenow_data = servicenow_data
17
- @options = options
18
- @log = NexposeTicketing::NxLogger.instance
19
- @common_helper = NexposeTicketing::CommonHelper.new(@options)
13
+ class ServiceNowHelper < BaseHelper
14
+ attr_accessor :log, :transform
15
+ def initialize(service_data, options, mode)
16
+ super(service_data, options, mode)
20
17
  end
21
18
 
22
19
  # Sends a list of tickets (in JSON format) to ServiceNow individually (each ticket in the list
@@ -29,7 +26,7 @@ class ServiceNowHelper
29
26
  fail 'Ticket(s) cannot be empty' if tickets.nil? || tickets.empty?
30
27
 
31
28
  tickets.each do |ticket|
32
- send_ticket(ticket, @servicenow_data[:servicenow_url], @servicenow_data[:redirect_limit])
29
+ send_ticket(ticket, @service_data[:servicenow_url], @service_data[:redirect_limit])
33
30
  end
34
31
  end
35
32
 
@@ -42,10 +39,10 @@ class ServiceNowHelper
42
39
  def update_tickets(tickets)
43
40
  if tickets.nil? || tickets.empty?
44
41
  @log.log_message('No tickets to update.')
45
- else
46
- tickets.each do |ticket|
47
- send_ticket(ticket, @servicenow_data[:servicenow_url], @servicenow_data[:redirect_limit])
48
- end
42
+ return
43
+ end
44
+ tickets.each do |ticket|
45
+ send_ticket(ticket, @service_data[:servicenow_url], @service_data[:redirect_limit])
49
46
  end
50
47
  end
51
48
 
@@ -56,12 +53,14 @@ class ServiceNowHelper
56
53
  # - +tickets+ - List of JSON-formatted ticket closures.
57
54
  #
58
55
  def close_tickets(tickets)
56
+ @metrics.closed tickets.count
57
+
59
58
  if tickets.nil? || tickets.empty?
60
59
  @log.log_message('No tickets to close.')
61
- else
62
- tickets.each do |ticket|
63
- send_ticket(ticket, @servicenow_data[:servicenow_url], @servicenow_data[:redirect_limit])
64
- end
60
+ return
61
+ end
62
+ tickets.each do |ticket|
63
+ send_ticket(ticket, @service_data[:servicenow_url], @service_data[:redirect_limit])
65
64
  end
66
65
  end
67
66
 
@@ -76,10 +75,10 @@ class ServiceNowHelper
76
75
 
77
76
  #Get the address
78
77
  query = "incident.do?JSONv2&sysparm_query=active=true^u_nxid=#{nxid}"
79
- uri = URI.join(@servicenow_data[:servicenow_url], '/')
78
+ uri = URI.join(@service_data[:servicenow_url], '/')
80
79
  full_url = URI.join(uri, "/").to_s + query
81
80
  req = Net::HTTP::Get.new(full_url, headers)
82
- req.basic_auth @servicenow_data[:username], @servicenow_data[:password]
81
+ req.basic_auth @service_data[:username], @service_data[:password]
83
82
  resp = Net::HTTP.new(uri.host, uri.port)
84
83
 
85
84
  # Enable this line for debugging the https call.
@@ -132,12 +131,12 @@ class ServiceNowHelper
132
131
  headers = { 'Content-Type' => 'application/json',
133
132
  'Accept' => 'application/json' }
134
133
  req = Net::HTTP::Post.new(url, headers)
135
- req.basic_auth @servicenow_data[:username], @servicenow_data[:password]
134
+ req.basic_auth @service_data[:username], @service_data[:password]
136
135
  req.body = ticket
137
136
 
138
137
  resp = Net::HTTP.new(uri.host, uri.port)
139
138
  # Setting verbose_mode to 'Y' will debug the https call(s).
140
- resp.set_debug_output $stderr if @servicenow_data[:verbose_mode] == 'Y'
139
+ resp.set_debug_output $stderr if @service_data[:verbose_mode] == 'Y'
141
140
  resp.use_ssl = true if uri.scheme == 'https'
142
141
  # Currently, we do not verify SSL certificates (in case the local servicenow instance uses
143
142
  # and unsigned or expired certificate)
@@ -162,19 +161,7 @@ class ServiceNowHelper
162
161
  # - List of JSON-formated tickets for creating within ServiceNow.
163
162
  #
164
163
  def prepare_create_tickets(vulnerability_list, nexpose_identifier_id)
165
- @log.log_message('Preparing ticket requests...')
166
- case @options[:ticket_mode]
167
- # 'D' Default IP *-* Vulnerability
168
- when 'D' then matching_fields = ['ip_address', 'vulnerability_id']
169
- # 'I' IP address -* Vulnerability
170
- when 'I' then matching_fields = ['ip_address']
171
- # 'V' Vulnerability -* Assets
172
- when 'V' then matching_fields = ['vulnerability_id']
173
- else
174
- fail 'Unsupported ticketing mode selected.'
175
- end
176
-
177
- prepare_tickets(vulnerability_list, nexpose_identifier_id, matching_fields)
164
+ prepare_tickets(vulnerability_list, nexpose_identifier_id)
178
165
  end
179
166
 
180
167
  # Prepares a list of vulnerabilities into a list of JSON-formatted tickets (incidents) for
@@ -186,7 +173,9 @@ class ServiceNowHelper
186
173
  # * *Returns* :
187
174
  # - List of JSON-formated tickets for creating within ServiceNow.
188
175
  #
189
- def prepare_tickets(vulnerability_list, nexpose_identifier_id, matching_fields)
176
+ def prepare_tickets(vulnerability_list, nexpose_identifier_id)
177
+ @metrics.start
178
+ matching_fields = @mode_helper.get_matching_fields
190
179
  @ticket = Hash.new(-1)
191
180
 
192
181
  @log.log_message("Preparing tickets in #{options[:ticket_mode]} address.")
@@ -198,7 +187,7 @@ class ServiceNowHelper
198
187
  CSV.parse(vulnerability_list.chomp, headers: :first_row) do |row|
199
188
  if previous_row.nil?
200
189
  previous_row = row.dup
201
- nxid = @common_helper.generate_nxid(nexpose_identifier_id, row)
190
+ nxid = @mode_helper.get_nxid(nexpose_identifier_id, row)
202
191
 
203
192
  action = if row['comparison'].nil? || row['comparison'] == 'New'
204
193
  'insert'
@@ -208,21 +197,21 @@ class ServiceNowHelper
208
197
 
209
198
  @ticket = {
210
199
  'sysparm_action' => action,
211
- 'caller_id' => "#{@servicenow_data[:username]}",
200
+ 'caller_id' => "#{@service_data[:username]}",
212
201
  'category' => 'Software',
213
202
  'impact' => '1',
214
203
  'urgency' => '1',
215
- 'short_description' => @common_helper.get_title(row),
204
+ 'short_description' => @mode_helper.get_title(row),
216
205
  'work_notes' => "",
217
206
  'u_nxid' => nxid,
218
207
  'u_rpd_id' => nil
219
208
  }
220
- description = @common_helper.get_description(nexpose_identifier_id, row)
209
+ description = @mode_helper.get_description(nexpose_identifier_id, row)
221
210
  elsif matching_fields.any? { |x| previous_row[x].nil? || previous_row[x] != row[x] }
222
- info = @common_helper.get_field_info(matching_fields, previous_row)
211
+ info = @mode_helper.get_field_info(matching_fields, previous_row)
223
212
  @log.log_message("Generated ticket with #{info}")
224
213
 
225
- @ticket['work_notes'] = @common_helper.print_description(description)
214
+ @ticket['work_notes'] = @mode_helper.print_description(description)
226
215
  tickets.push(@ticket)
227
216
 
228
217
  previous_row = nil
@@ -232,12 +221,14 @@ class ServiceNowHelper
232
221
  unless row['comparison'].nil? || row['comparison'] == 'New'
233
222
  @ticket['sysparm_action'] = 'update'
234
223
  end
235
- description = @common_helper.update_description(description, row)
224
+ description = @mode_helper.update_description(description, row)
236
225
  end
237
226
  end
238
227
 
239
228
  unless @ticket.nil? || @ticket.empty?
240
- @ticket['work_notes'] = @common_helper.print_description(description) unless (@ticket.size == 0)
229
+ info = @mode_helper.get_field_info(matching_fields, previous_row)
230
+ @log.log_message("Generated ticket with #{info}")
231
+ @ticket['work_notes'] = @mode_helper.print_description(description) unless (@ticket.size == 0)
241
232
  tickets.push(@ticket)
242
233
  end
243
234
  @log.log_message("Generated <#{tickets.count.to_s}> tickets.")
@@ -246,6 +237,9 @@ class ServiceNowHelper
246
237
  if t['sysparm_action'] == 'update'
247
238
  t['sysparm_action'] = 'insert'
248
239
  t['u_rpd_id'] = get_ticket_identifier(t['u_nxid'])
240
+ @metrics.updated
241
+ else
242
+ @metrics.created
249
243
  end
250
244
 
251
245
  t['u_rpd_id'] ||= SecureRandom.uuid
@@ -263,18 +257,7 @@ class ServiceNowHelper
263
257
  # - List of JSON-formated tickets for updating within ServiceNow.
264
258
  #
265
259
  def prepare_update_tickets(vulnerability_list, nexpose_identifier_id)
266
-
267
- case @options[:ticket_mode]
268
- when 'D' then fail 'Ticket updates are not supported in Default mode.'
269
- # 'I' IP address -* Vulnerability
270
- when 'I' then matching_fields = ['ip_address']
271
- # 'V' Vulnerability -* Assets
272
- when 'V' then matching_fields = ['vulnerability_id']
273
- else
274
- fail 'Unsupported ticketing mode selected.'
275
- end
276
-
277
- prepare_tickets(vulnerability_list, nexpose_identifier_id, matching_fields)
260
+ prepare_tickets(vulnerability_list, nexpose_identifier_id)
278
261
  end
279
262
 
280
263
 
@@ -292,7 +275,7 @@ class ServiceNowHelper
292
275
  tickets = []
293
276
  @nxid = nil
294
277
  CSV.parse(vulnerability_list.chomp, headers: :first_row) do |row|
295
- @nxid = @common_helper.generate_nxid(nexpose_identifier_id, row)
278
+ @nxid = @mode_helper.get_nxid(nexpose_identifier_id, row)
296
279
  # 'state' 7 is the "Closed" state within ServiceNow.
297
280
  ticket_id = get_ticket_identifier(@nxid)
298
281
  @log.log_message("Closing ticket with NXID: #{@nxid}.")