nexpose_ticketing 0.8.3 → 1.0.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_jira +7 -0
- data/bin/nexpose_remedy +6 -0
- data/bin/nexpose_servicedesk +6 -0
- data/bin/nexpose_servicenow +6 -0
- data/lib/nexpose_ticketing/common_helper.rb +344 -0
- data/lib/nexpose_ticketing/config/servicedesk.config +3 -3
- data/lib/nexpose_ticketing/config/ticket_service.config +2 -0
- data/lib/nexpose_ticketing/helpers/jira_helper.rb +53 -107
- data/lib/nexpose_ticketing/helpers/remedy_helper.rb +208 -594
- data/lib/nexpose_ticketing/helpers/servicedesk_helper.rb +302 -289
- data/lib/nexpose_ticketing/helpers/servicenow_helper.rb +74 -165
- data/lib/nexpose_ticketing/nx_logger.rb +139 -30
- data/lib/nexpose_ticketing/queries.rb +148 -59
- data/lib/nexpose_ticketing/ticket_repository.rb +6 -0
- data/lib/nexpose_ticketing/ticket_service.rb +28 -16
- data/lib/nexpose_ticketing/version.rb +3 -0
- metadata +14 -6
- data/Gemfile.lock +0 -67
@@ -4,6 +4,8 @@ require 'net/https'
|
|
4
4
|
require 'uri'
|
5
5
|
require 'csv'
|
6
6
|
require 'nexpose_ticketing/nx_logger'
|
7
|
+
require 'nexpose_ticketing/version'
|
8
|
+
require 'nexpose_ticketing/common_helper'
|
7
9
|
|
8
10
|
# Serves as the ServiceNow interface for creating/updating issues from
|
9
11
|
# vulnelrabilities found in Nexpose.
|
@@ -12,7 +14,8 @@ class ServiceNowHelper
|
|
12
14
|
def initialize(servicenow_data, options)
|
13
15
|
@servicenow_data = servicenow_data
|
14
16
|
@options = options
|
15
|
-
@log = NexposeTicketing::
|
17
|
+
@log = NexposeTicketing::NxLogger.instance
|
18
|
+
@common_helper = NexposeTicketing::CommonHelper.new(@options)
|
16
19
|
end
|
17
20
|
|
18
21
|
# Sends a list of tickets (in JSON format) to ServiceNow individually (each ticket in the list
|
@@ -73,7 +76,7 @@ class ServiceNowHelper
|
|
73
76
|
#
|
74
77
|
def send_ticket(ticket, url, limit)
|
75
78
|
raise ArgumentError, 'HTTP Redirect too deep' if limit == 0
|
76
|
-
|
79
|
+
|
77
80
|
uri = URI.parse(url)
|
78
81
|
headers = { 'Content-Type' => 'application/json',
|
79
82
|
'Accept' => 'application/json' }
|
@@ -108,64 +111,23 @@ class ServiceNowHelper
|
|
108
111
|
# - List of JSON-formated tickets for creating within ServiceNow.
|
109
112
|
#
|
110
113
|
def prepare_create_tickets(vulnerability_list, nexpose_identifier_id)
|
111
|
-
@ticket
|
114
|
+
@log.log_message('Preparing ticket requests...')
|
112
115
|
case @options[:ticket_mode]
|
113
|
-
# 'D' Default
|
114
|
-
when 'D'
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
116
|
+
# 'D' Default IP *-* Vulnerability
|
117
|
+
when 'D' then matching_fields = ['ip_address', 'vulnerability_id']
|
118
|
+
# 'I' IP address -* Vulnerability
|
119
|
+
when 'I' then matching_fields = ['ip_address']
|
120
|
+
# 'V' Vulnerability -* Assets
|
121
|
+
when 'V' then matching_fields = ['vulnerability_id']
|
119
122
|
else
|
120
|
-
|
123
|
+
fail 'Unsupported ticketing mode selected.'
|
121
124
|
end
|
122
|
-
end
|
123
|
-
|
124
|
-
|
125
|
-
# Prepares a list of vulnerabilities into a list of JSON-formatted tickets (incidents) for
|
126
|
-
# ServiceNow. The preparation by default means that each vulnerability within Nexpose is a
|
127
|
-
# separate incident within ServiceNow. This makes for smaller, more actionalble incidents but
|
128
|
-
# could lead to a very large total number of incidents.
|
129
|
-
#
|
130
|
-
# * *Args* :
|
131
|
-
# - +vulnerability_list+ - CSV of vulnerabilities within Nexpose.
|
132
|
-
#
|
133
|
-
# * *Returns* :
|
134
|
-
# - List of JSON-formated tickets for creating within ServiceNow.
|
135
|
-
#
|
136
|
-
def prepare_create_tickets_default(vulnerability_list, nexpose_identifier_id)
|
137
|
-
@log.log_message('Preparing tickets by default method.')
|
138
|
-
tickets = []
|
139
|
-
CSV.parse(vulnerability_list.chomp, headers: :first_row) do |row|
|
140
|
-
# ServiceNow doesn't allow new line characters in the incident short description.
|
141
|
-
summary = row['summary'].gsub(/\n/, ' ')
|
142
|
-
|
143
|
-
@log.log_message("Creating ticket with IP address: #{row['ip_address']}, Nexpose identifier id: #{nexpose_identifier_id} and summary: #{summary}")
|
144
|
-
# NXID in the u_work_notes is a unique identifier used to query incidents to update/resolve
|
145
|
-
# incidents as they are resolved in Nexpose.
|
146
125
|
|
147
|
-
|
148
|
-
'sysparm_action' => 'insert',
|
149
|
-
'u_caller_id' => "#{@servicenow_data[:username]}",
|
150
|
-
'u_category' => 'Software',
|
151
|
-
'u_impact' => '1',
|
152
|
-
'u_urgency' => '1',
|
153
|
-
'u_short_description' => "#{row['ip_address']} => #{summary}",
|
154
|
-
'u_work_notes' => "Summary: #{summary}
|
155
|
-
Fix: #{row['fix']}
|
156
|
-
----------------------------------------------------------------------------
|
157
|
-
URL: #{row['url']}
|
158
|
-
NXID: #{nexpose_identifier_id}#{row['asset_id']}#{row['vulnerability_id']}#{row['solution_id']}"
|
159
|
-
}.to_json
|
160
|
-
tickets.push(ticket)
|
161
|
-
end
|
162
|
-
tickets
|
126
|
+
prepare_tickets(vulnerability_list, nexpose_identifier_id, matching_fields)
|
163
127
|
end
|
164
128
|
|
165
129
|
# Prepares a list of vulnerabilities into a list of JSON-formatted tickets (incidents) for
|
166
|
-
# ServiceNow.
|
167
|
-
# address are consolidated into a single ServiceNow incident. This reduces the number of incidents
|
168
|
-
# within ServiceNow but greatly increases the size of the work notes.
|
130
|
+
# ServiceNow.
|
169
131
|
#
|
170
132
|
# * *Args* :
|
171
133
|
# - +vulnerability_list+ - CSV of vulnerabilities within Nexpose.
|
@@ -173,57 +135,65 @@ class ServiceNowHelper
|
|
173
135
|
# * *Returns* :
|
174
136
|
# - List of JSON-formated tickets for creating within ServiceNow.
|
175
137
|
#
|
176
|
-
def
|
177
|
-
@
|
138
|
+
def prepare_tickets(vulnerability_list, nexpose_identifier_id, matching_fields)
|
139
|
+
@ticket = Hash.new(-1)
|
140
|
+
|
141
|
+
@log.log_message("Preparing tickets in #{options[:ticket_mode]} address.")
|
178
142
|
tickets = []
|
179
|
-
|
143
|
+
previous_row = nil
|
144
|
+
description = nil
|
145
|
+
action = 'insert'
|
180
146
|
CSV.parse(vulnerability_list.chomp, headers: :first_row) do |row|
|
181
|
-
if
|
182
|
-
|
183
|
-
@
|
147
|
+
if previous_row.nil?
|
148
|
+
previous_row = row.dup
|
149
|
+
nxid = @common_helper.generate_nxid(nexpose_identifier_id, row)
|
150
|
+
action = unless row['comparison'].nil? || row['comparison'] == 'New'
|
151
|
+
'update'
|
152
|
+
else
|
153
|
+
'insert'
|
154
|
+
end
|
184
155
|
@ticket = {
|
185
|
-
'sysparm_action' =>
|
156
|
+
'sysparm_action' => action,
|
186
157
|
'u_caller_id' => "#{@servicenow_data[:username]}",
|
187
158
|
'u_category' => 'Software',
|
188
159
|
'u_impact' => '1',
|
189
160
|
'u_urgency' => '1',
|
190
|
-
'u_short_description' =>
|
191
|
-
'
|
192
|
-
|
193
|
-
+++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n"
|
161
|
+
'u_short_description' => @common_helper.get_title(row),
|
162
|
+
'sysparm_query' => "active=true^u_work_notesCONTAINSNXID: #{nxid}",
|
163
|
+
'u_work_notes' => ""
|
194
164
|
}
|
195
|
-
|
196
|
-
|
197
|
-
@
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
Fix: #{row['fix']}"
|
202
|
-
unless row['url'].nil?
|
203
|
-
@ticket['u_work_notes'] +=
|
204
|
-
"\n----------------------------------------------------------------------------
|
205
|
-
URL: #{row['url']}"
|
206
|
-
end
|
207
|
-
end
|
208
|
-
unless current_ip == row['ip_address']
|
209
|
-
# NXID in the u_work_notes is the unique identifier used to query incidents to update them.
|
210
|
-
@log.log_message("Found new IP address. Finishing ticket with with IP address: #{current_ip} and moving onto IP #{row['ip_address']}")
|
211
|
-
@ticket['u_work_notes'] += "\nNXID: #{nexpose_identifier_id}#{current_ip}"
|
212
|
-
@ticket = @ticket.to_json
|
165
|
+
description = @common_helper.get_description(nexpose_identifier_id, row)
|
166
|
+
elsif matching_fields.any? { |x| previous_row[x].nil? || previous_row[x] != row[x] }
|
167
|
+
info = @common_helper.get_field_info(matching_fields, previous_row)
|
168
|
+
@log.log_message("Generated ticket with #{info}")
|
169
|
+
|
170
|
+
@ticket['u_work_notes'] = @common_helper.print_description(description)
|
213
171
|
tickets.push(@ticket)
|
214
|
-
|
172
|
+
previous_row = nil
|
173
|
+
description = nil
|
215
174
|
redo
|
175
|
+
else
|
176
|
+
if !row['comparison'].nil? && row['comparison'] != 'New'
|
177
|
+
action = 'update'
|
178
|
+
end
|
179
|
+
description = @common_helper.update_description(description, row)
|
216
180
|
end
|
217
181
|
end
|
218
|
-
|
219
|
-
@ticket
|
220
|
-
|
221
|
-
|
182
|
+
|
183
|
+
unless @ticket.nil? || @ticket.empty?
|
184
|
+
@ticket['u_work_notes'] = @common_helper.print_description(description) unless (@ticket.size == 0)
|
185
|
+
tickets.push(@ticket)
|
186
|
+
end
|
187
|
+
@log.log_message("Generated <#{tickets.count.to_s}> tickets.")
|
188
|
+
|
189
|
+
tickets.map do |t|
|
190
|
+
t.delete('sysparm_query') if t['sysparm_action'] == 'insert'
|
191
|
+
t.to_json
|
192
|
+
end
|
222
193
|
end
|
223
|
-
|
224
|
-
# Prepare ticket updates from the CSV of vulnerabilities exported from Nexpose.
|
225
|
-
#
|
226
|
-
# are ordered by IP address and then by ticket_status, allowing the method to loop through and
|
194
|
+
|
195
|
+
# Prepare ticket updates from the CSV of vulnerabilities exported from Nexpose. The list of vulnerabilities
|
196
|
+
# are ordered depending on the ticketing mode and then by ticket_status, allowing the method to loop through and
|
227
197
|
# display new, old, and same vulnerabilities in that order.
|
228
198
|
#
|
229
199
|
# - +vulnerability_list+ - CSV of vulnerabilities within Nexpose.
|
@@ -232,67 +202,18 @@ class ServiceNowHelper
|
|
232
202
|
# - List of JSON-formated tickets for updating within ServiceNow.
|
233
203
|
#
|
234
204
|
def prepare_update_tickets(vulnerability_list, nexpose_identifier_id)
|
235
|
-
fail 'Ticket updates are only supported in IP-address mode.' if @options[:ticket_mode] == 'D'
|
236
|
-
@ticket = Hash.new(-1)
|
237
205
|
|
238
|
-
@
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
@log.log_message("Creating ticket update with IP address: #{row['ip_address']} and Nexpose identifier ID: #{nexpose_identifier_id}")
|
247
|
-
@log.log_message("Ticket status #{ticket_status}")
|
248
|
-
action = 'update'
|
249
|
-
if ticket_status == 'New'
|
250
|
-
action = 'insert'
|
251
|
-
end
|
252
|
-
@ticket = {
|
253
|
-
'sysparm_action' => action,
|
254
|
-
'sysparm_query' => "u_work_notesCONTAINSNXID: #{nexpose_identifier_id}#{row['ip_address']}",
|
255
|
-
'u_work_notes' =>
|
256
|
-
"\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
257
|
-
++ #{row['comparison']} Vulnerabilities +++++++++++++++++++++++++++++++++++++
|
258
|
-
+++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n"
|
259
|
-
}
|
260
|
-
end
|
261
|
-
if current_ip == row['ip_address']
|
262
|
-
# If the ticket_status is different, add a a new 'header' to signify a new block of tickets.
|
263
|
-
unless ticket_status == row['comparison']
|
264
|
-
@ticket['u_work_notes'] +=
|
265
|
-
"\n\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
266
|
-
++ #{row['comparison']} Vulnerabilities +++++++++++++++++++++++++++++++++++++
|
267
|
-
+++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n"
|
268
|
-
ticket_status = row['comparison']
|
269
|
-
end
|
270
|
-
|
271
|
-
@ticket['u_work_notes'] +=
|
272
|
-
"\n\n==========================================
|
273
|
-
Summary: #{row['summary']}
|
274
|
-
----------------------------------------------------------------------------
|
275
|
-
Fix: #{row['fix']}"
|
276
|
-
# Only add the URL block if data exists in the row.
|
277
|
-
unless row['url'].nil?
|
278
|
-
@ticket['u_work_notes'] +=
|
279
|
-
"----------------------------------------------------------------------------
|
280
|
-
URL: #{row['url']}"
|
281
|
-
end
|
282
|
-
end
|
283
|
-
unless current_ip == row['ip_address']
|
284
|
-
# NXID in the u_work_notes is the unique identifier used to query incidents to update them.
|
285
|
-
@ticket['u_work_notes'] += "\nNXID: #{nexpose_identifier_id}#{current_ip}"
|
286
|
-
@ticket = @ticket.to_json
|
287
|
-
tickets.push(@ticket)
|
288
|
-
current_ip = -1
|
289
|
-
redo
|
290
|
-
end
|
206
|
+
case @options[:ticket_mode]
|
207
|
+
when 'D' then fail 'Ticket updates are not supported in Default mode.'
|
208
|
+
# 'I' IP address -* Vulnerability
|
209
|
+
when 'I' then matching_fields = ['ip_address']
|
210
|
+
# 'V' Vulnerability -* Assets
|
211
|
+
when 'V' then matching_fields = ['vulnerability_id']
|
212
|
+
else
|
213
|
+
fail 'Unsupported ticketing mode selected.'
|
291
214
|
end
|
292
|
-
|
293
|
-
|
294
|
-
tickets.push(@ticket.to_json) unless @ticket.nil?
|
295
|
-
tickets
|
215
|
+
|
216
|
+
prepare_tickets(vulnerability_list, nexpose_identifier_id, matching_fields)
|
296
217
|
end
|
297
218
|
|
298
219
|
|
@@ -310,28 +231,16 @@ class ServiceNowHelper
|
|
310
231
|
tickets = []
|
311
232
|
@nxid = nil
|
312
233
|
CSV.parse(vulnerability_list.chomp, headers: :first_row) do |row|
|
313
|
-
|
314
|
-
# 'D' Default mode: IP *-* Vulnerability
|
315
|
-
when 'D'
|
316
|
-
@nxid = "#{nexpose_identifier_id}#{row['asset_id']}#{row['vulnerability_id']}#{row['solution_id']}"
|
317
|
-
# 'I' IP address mode: IP address -* Vulnerability
|
318
|
-
when 'I'
|
319
|
-
@nxid = "#{nexpose_identifier_id}#{row['ip_address']}"
|
320
|
-
# 'V' Vulnerability mode: Vulnerability -* IP address
|
321
|
-
## when 'V'
|
322
|
-
## @nxid = "#{nexpose_identifier_id}#{row['asset_id']}#{row['vulnerability_id']}"
|
323
|
-
else
|
324
|
-
fail 'Could not close tickets - do not understand the ticketing mode!'
|
325
|
-
end
|
234
|
+
@nxid = @common_helper.generate_nxid(nexpose_identifier_id, row)
|
326
235
|
# 'state' 7 is the "Closed" state within ServiceNow.
|
327
236
|
@log.log_message("Closing ticket with NXID: #{@nxid}.")
|
328
237
|
ticket = {
|
329
238
|
'sysparm_action' => 'update',
|
330
|
-
'sysparm_query' => "u_work_notesCONTAINSNXID: #{@nxid}",
|
239
|
+
'sysparm_query' => "active=true^u_work_notesCONTAINSNXID: #{@nxid}",
|
331
240
|
'state' => '7'
|
332
241
|
}.to_json
|
333
242
|
tickets.push(ticket)
|
334
243
|
end
|
335
244
|
tickets
|
336
245
|
end
|
337
|
-
end
|
246
|
+
end
|
@@ -1,41 +1,150 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'json'
|
3
|
+
require 'net/http'
|
4
|
+
require 'singleton'
|
5
|
+
|
1
6
|
module NexposeTicketing
|
2
|
-
class
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
class NxLogger
|
8
|
+
include Singleton
|
9
|
+
attr_accessor :options, :statistic_key, :product, :logger_file
|
10
|
+
LOG_PATH = "./logs/rapid7_%s.log"
|
11
|
+
KEY_FORMAT = "external.integration.%s"
|
12
|
+
PRODUCT_FORMAT = "%s_%s"
|
13
|
+
|
14
|
+
DEFAULT_LOG = 'integration'
|
15
|
+
PRODUCT_RANGE = 3..30
|
16
|
+
KEY_RANGE = 3..15
|
17
|
+
|
18
|
+
ENDPOINT = '/data/external/statistic/'
|
19
|
+
|
20
|
+
def initialize()
|
21
|
+
@logger_file = get_log_path product
|
22
|
+
setup_logging(true, 'info')
|
23
|
+
end
|
24
|
+
|
25
|
+
def setup_statistics_collection(vendor, product_name, gem_version)
|
26
|
+
#Remove illegal characters
|
27
|
+
vendor.to_s.gsub!('-', '_')
|
28
|
+
product_name.to_s.gsub!('-', '_')
|
29
|
+
|
30
|
+
begin
|
31
|
+
@statistic_key = get_statistic_key vendor
|
32
|
+
@product = get_product product_name, gem_version
|
33
|
+
rescue => e
|
34
|
+
#Continue
|
13
35
|
end
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
if enabled
|
21
|
-
require 'logger'
|
22
|
-
directory = File.dirname(LOGGER_FILE)
|
23
|
-
FileUtils.mkdir_p(directory) unless File.directory?(directory)
|
24
|
-
@log = Logger.new(LOGGER_FILE, 'monthly')
|
25
|
-
@log.level = Logger::INFO
|
26
|
-
log_message('Logging enabled for helper.')
|
36
|
+
end
|
37
|
+
|
38
|
+
def setup_logging(enabled, log_level = nil)
|
39
|
+
unless enabled || @log.nil?
|
40
|
+
log_message('Logging disabled.')
|
41
|
+
return
|
27
42
|
end
|
43
|
+
|
44
|
+
@logger_file = get_log_path product
|
45
|
+
|
46
|
+
require 'logger'
|
47
|
+
directory = File.dirname(@logger_file)
|
48
|
+
FileUtils.mkdir_p(directory) unless File.directory?(directory)
|
49
|
+
io = IO.for_fd(IO.sysopen(@logger_file, 'a'))
|
50
|
+
io.autoclose = false
|
51
|
+
io.sync = true
|
52
|
+
@log = Logger.new(io, 'weekly')
|
53
|
+
@log.level = if log_level.casecmp('info') == 0
|
54
|
+
Logger::INFO
|
55
|
+
else
|
56
|
+
Logger::DEBUG
|
57
|
+
end
|
58
|
+
log_message("Logging enabled at level <#{log_level}>")
|
28
59
|
end
|
29
60
|
|
30
|
-
# Logs
|
61
|
+
# Logs an info message
|
31
62
|
def log_message(message)
|
32
|
-
@log.info(message)
|
63
|
+
@log.info(message) unless @log.nil?
|
64
|
+
end
|
65
|
+
|
66
|
+
# Logs a debug message
|
67
|
+
def log_debug_message(message)
|
68
|
+
@log.debug(message) unless @log.nil?
|
69
|
+
end
|
70
|
+
|
71
|
+
# Logs an error message
|
72
|
+
def log_error_message(message)
|
73
|
+
@log.error(message) unless @log.nil?
|
74
|
+
end
|
75
|
+
|
76
|
+
# Logs a warn message
|
77
|
+
def log_warn_message(message)
|
78
|
+
@log.warn(message) unless @log.nil?
|
79
|
+
end
|
80
|
+
|
81
|
+
def log_stat_message(message)
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_log_path(product)
|
85
|
+
product.downcase! unless product.nil?
|
86
|
+
File.join(File.dirname(__FILE__), LOG_PATH % (product || DEFAULT_LOG))
|
87
|
+
end
|
88
|
+
|
89
|
+
def get_statistic_key(vendor)
|
90
|
+
if vendor.nil? || vendor.length < KEY_RANGE.min
|
91
|
+
log_stat_message("Vendor length is below minimum of <#{KEY_RANGE}>")
|
92
|
+
return nil
|
93
|
+
end
|
94
|
+
|
95
|
+
KEY_FORMAT % vendor[0...KEY_RANGE.max].downcase
|
33
96
|
end
|
34
97
|
|
35
|
-
|
36
|
-
|
37
|
-
|
98
|
+
def get_product(product, version)
|
99
|
+
return nil if (product.nil? || version.nil?)
|
100
|
+
product = (PRODUCT_FORMAT % [product, version])[0...PRODUCT_RANGE.max]
|
101
|
+
|
102
|
+
if product.length < PRODUCT_RANGE.min
|
103
|
+
log_stat_message("Product length below minimum <#{PRODUCT_RANGE.min}>.")
|
104
|
+
return nil
|
105
|
+
end
|
106
|
+
product.downcase
|
107
|
+
end
|
108
|
+
|
109
|
+
def generate_payload(statistic_value='')
|
110
|
+
payload = {'statistic-key' => @statistic_key,
|
111
|
+
'statistic-value' => statistic_value,
|
112
|
+
'product' => @product}
|
113
|
+
JSON.generate(payload)
|
114
|
+
end
|
115
|
+
|
116
|
+
def send(nexpose_address, nexpose_port, session_id, payload)
|
117
|
+
header = {'Content-Type' => 'application/json',
|
118
|
+
'nexposeCCSessionID' => session_id,
|
119
|
+
'Cookie' => "nexposeCCSessionID=#{session_id}"}
|
120
|
+
req = Net::HTTP::Put.new(ENDPOINT, header)
|
121
|
+
req.body = payload
|
122
|
+
http_instance = Net::HTTP.new(nexpose_address, nexpose_port)
|
123
|
+
http_instance.use_ssl = true
|
124
|
+
http_instance.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
125
|
+
response = http_instance.start { |http| http.request(req) }
|
126
|
+
log_stat_message "Received code #{response.code} from Nexpose console."
|
127
|
+
log_stat_message "Received message #{response.msg} from Nexpose console."
|
128
|
+
log_stat_message 'Finished sending statistics data to Nexpose.'
|
129
|
+
response.code
|
130
|
+
end
|
131
|
+
|
132
|
+
def on_connect(nexpose_address, nexpose_port, session_id, value)
|
133
|
+
log_stat_message 'Sending statistics data to Nexpose'
|
134
|
+
|
135
|
+
if @product.nil? || @statistic_key.nil?
|
136
|
+
log_stat_message('Invalid product name and/or statistics key.')
|
137
|
+
log_stat_message('Statistics collection not enabled.')
|
138
|
+
return
|
139
|
+
end
|
140
|
+
|
141
|
+
begin
|
142
|
+
payload = generate_payload value
|
143
|
+
send(nexpose_address, nexpose_port, session_id, payload)
|
144
|
+
rescue => e
|
145
|
+
#Let the program continue
|
146
|
+
end
|
38
147
|
end
|
39
148
|
|
40
149
|
end
|
41
|
-
end
|
150
|
+
end
|