nexpose_ticketing 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/README.md +14 -1
- data/bin/nexpose_jira +4 -0
- data/bin/nexpose_remedy +4 -0
- data/bin/nexpose_servicedesk +4 -0
- data/bin/nexpose_servicenow +4 -0
- data/lib/nexpose_ticketing/helpers/jira_helper.rb +63 -49
- data/lib/nexpose_ticketing/helpers/servicenow_helper.rb +7 -5
- data/lib/nexpose_ticketing/nx_logger.rb +1 -1
- data/lib/nexpose_ticketing/report_helper.rb +1 -0
- data/lib/nexpose_ticketing/version.rb +1 -1
- metadata +21 -21
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
NGJlOWNhNmE5NGJiZDAwYjFkYjJhZDBiODhjNWY5NmNjMTk4Mjk3Zg==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f87999035739237fdbbb5c978292fb1327b95d35
|
4
|
+
data.tar.gz: 6d917864b7f2a5d9246fc2214bbea37b464323e1
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
YTFjNWQ2OGFjNWM0NWFmMDVlODMxNjA0MWFlYzI2Y2FjOWIxNDA1NzUxNDZi
|
11
|
-
ODUwNWI4YTkzMzY2MTk1NTMyYzJjNzRmMjQ0MTAzNWQyMGQ1ZjI=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
NTE4ZDZlY2I5NDFhMmM2YTMxMjcwZWY2MDcxZTU4NzVlNDZjNDRjODI4OGZm
|
14
|
-
ODM0YWIzZGMyMTRlZWU1YzlhNTkxYmQyNTVmMzNjMTY1Yjg5YTRmMjI5Zjhm
|
15
|
-
ZWI2ZmI1MjcyMmM5MmIxNzgwYjc5Y2JlMGU3YzM0MDJlMGFjYjk=
|
6
|
+
metadata.gz: 3f8f1a3907e9ba7c3e556b75253c8833946a65c59efd62e06816f54853d894796f1bfd733323f94459ff0e2dada0d6d17a86549cc0e53a3fe1182ef5647a236f
|
7
|
+
data.tar.gz: 374e3350847992ee22d5abc9377d64867f2670da2b6f5c48f256ef02e0d6906cc3e33af87ad5cf23aaeb9f397228364d1f3bf0c945065842228cc67d784d30ad
|
data/README.md
CHANGED
@@ -72,8 +72,21 @@ We welcome contributions to this package. We ask only that pull requests and pat
|
|
72
72
|
|
73
73
|
##Changelog
|
74
74
|
|
75
|
+
###1.0.2
|
76
|
+
08-02-2016
|
77
|
+
- Encoding is now enforced as UTF-8 when parsing CSV files - fixes environment-specific errors.
|
78
|
+
|
79
|
+
Jira Helper:
|
80
|
+
- Non-200 return codes are now logged when creating or updating tickets.
|
81
|
+
|
82
|
+
NX Logger:
|
83
|
+
- Fixed Windows-specific, input-related errors.
|
84
|
+
|
85
|
+
ServiceNow:
|
86
|
+
- No longer queries for existing incident if ticket is new.
|
87
|
+
|
75
88
|
###1.0.1
|
76
|
-
19-01-
|
89
|
+
19-01-2016
|
77
90
|
|
78
91
|
ServiceNow Helper:
|
79
92
|
- New update set.
|
data/bin/nexpose_jira
CHANGED
@@ -12,6 +12,8 @@ log.setup_logging(true, 'info')
|
|
12
12
|
JIRA_CONFIG_PATH = File.join(File.dirname(__FILE__),
|
13
13
|
'../lib/nexpose_ticketing/config/jira.config')
|
14
14
|
|
15
|
+
current_encoding = Encoding.default_external=Encoding.find("UTF-8")
|
16
|
+
|
15
17
|
# Read in JIRA options from jira.config.
|
16
18
|
jira_options = begin
|
17
19
|
YAML.load_file(JIRA_CONFIG_PATH)
|
@@ -19,5 +21,7 @@ rescue ArgumentError => e
|
|
19
21
|
raise "Could not parse YAML #{JIRA_CONFIG_PATH} : #{e.message}"
|
20
22
|
end
|
21
23
|
|
24
|
+
log.log_message("Current Encoding set to: #{current_encoding}")
|
25
|
+
|
22
26
|
# Initialize Ticket Service using JIRA.
|
23
27
|
NexposeTicketing.start(jira_options)
|
data/bin/nexpose_remedy
CHANGED
@@ -12,6 +12,8 @@ log.setup_logging(true, 'info')
|
|
12
12
|
REMEDY_CONFIG_PATH = File.join(File.dirname(__FILE__),
|
13
13
|
'../lib/nexpose_ticketing/config/remedy.config')
|
14
14
|
|
15
|
+
current_encoding = Encoding.default_external=Encoding.find("UTF-8")
|
16
|
+
|
15
17
|
# Read in ServiceNow options from servicenow.config
|
16
18
|
remedy_options = begin
|
17
19
|
YAML.load_file(REMEDY_CONFIG_PATH)
|
@@ -19,5 +21,7 @@ rescue ArgumentError => e
|
|
19
21
|
raise "Could not parse YAML #{REMEDY_CONFIG_PATH} : #{e.message}"
|
20
22
|
end
|
21
23
|
|
24
|
+
log.log_message("Current Encoding set to: #{current_encoding}")
|
25
|
+
|
22
26
|
# Initialize Nexpose Ticket Service using Remedy
|
23
27
|
NexposeTicketing.start(remedy_options)
|
data/bin/nexpose_servicedesk
CHANGED
@@ -12,6 +12,8 @@ log.setup_logging(true, 'info')
|
|
12
12
|
SERVICEDESK_CONFIG_PATH = File.join(File.dirname(__FILE__),
|
13
13
|
'../lib/nexpose_ticketing/config/servicedesk.config')
|
14
14
|
|
15
|
+
current_encoding = Encoding.default_external=Encoding.find("UTF-8")
|
16
|
+
|
15
17
|
# Read in ServiceDesk options from servicenow.config
|
16
18
|
servicedesk_options = begin
|
17
19
|
YAML.load_file(SERVICEDESK_CONFIG_PATH)
|
@@ -19,5 +21,7 @@ rescue ArgumentError => e
|
|
19
21
|
raise "Could not parse YAML #{SERVICEDESK_CONFIG_PATH} : #{e.message}"
|
20
22
|
end
|
21
23
|
|
24
|
+
log.log_message("Current Encoding set to: #{current_encoding}")
|
25
|
+
|
22
26
|
# Initialize Nexpose Ticket Service using ServiceDesk
|
23
27
|
NexposeTicketing.start(servicedesk_options)
|
data/bin/nexpose_servicenow
CHANGED
@@ -12,6 +12,8 @@ log.setup_logging(true, 'info')
|
|
12
12
|
SERVICENOW_CONFIG_PATH = File.join(File.dirname(__FILE__),
|
13
13
|
'../lib/nexpose_ticketing/config/servicenow.config')
|
14
14
|
|
15
|
+
current_encoding = Encoding.default_external=Encoding.find("UTF-8")
|
16
|
+
|
15
17
|
# Read in ServiceNow options from servicenow.config
|
16
18
|
servicenow_options = begin
|
17
19
|
YAML.load_file(SERVICENOW_CONFIG_PATH)
|
@@ -19,5 +21,7 @@ rescue ArgumentError => e
|
|
19
21
|
raise "Could not parse YAML #{SERVICENOW_CONFIG_PATH} : #{e.message}"
|
20
22
|
end
|
21
23
|
|
24
|
+
log.log_message("Current Encoding set to: #{current_encoding}")
|
25
|
+
|
22
26
|
# Initialize Nexpose Ticket Service using ServiceNow
|
23
27
|
NexposeTicketing.start(servicenow_options)
|
@@ -37,15 +37,7 @@ class JiraHelper
|
|
37
37
|
uri = URI.parse(("#{@jira_data[:jira_url]}".split("/")[0..-2].join('/') + '/search'))
|
38
38
|
uri.query = [uri.query, URI.escape(jql_query)].compact.join('&')
|
39
39
|
req = Net::HTTP::Get.new(uri.to_s, headers)
|
40
|
-
|
41
|
-
resp = Net::HTTP.new(uri.host, uri.port)
|
42
|
-
|
43
|
-
# Enable this line for debugging the https call.
|
44
|
-
# resp.set_debug_output(@log)
|
45
|
-
|
46
|
-
resp.use_ssl = true if uri.scheme == 'https'
|
47
|
-
resp.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
48
|
-
response = resp.request(req)
|
40
|
+
response = send_jira_request(uri, req)
|
49
41
|
|
50
42
|
issues = JSON.parse(response.body)['issues']
|
51
43
|
if issues.nil? || !issues.any? || issues.size > 1
|
@@ -54,7 +46,62 @@ class JiraHelper
|
|
54
46
|
@log.log_message("Jira returned no key or too many keys for query result! Response was <#{issues}>")
|
55
47
|
return nil
|
56
48
|
end
|
57
|
-
|
49
|
+
return issues[0]['key']
|
50
|
+
end
|
51
|
+
|
52
|
+
# Sends a HTTP request to the JIRA console.
|
53
|
+
#
|
54
|
+
# * *Args* :
|
55
|
+
# - +uri+ - Address of the JIRA endpoint.
|
56
|
+
# - +request+ - Request containing the query or ticket object.
|
57
|
+
#
|
58
|
+
# * *Returns* :
|
59
|
+
# - HTTPResponse containing result from the JIRA console.
|
60
|
+
#
|
61
|
+
def send_request(uri, request, ticket=false)
|
62
|
+
request.basic_auth @jira_data[:username], @jira_data[:password]
|
63
|
+
resp = Net::HTTP.new(uri.host, uri.port)
|
64
|
+
|
65
|
+
# Enable this line for debugging the https call.
|
66
|
+
# resp.set_debug_output(@log)
|
67
|
+
|
68
|
+
resp.use_ssl = uri.scheme == 'https'
|
69
|
+
resp.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
70
|
+
|
71
|
+
return resp.request(request) unless ticket
|
72
|
+
|
73
|
+
resp.start do |http|
|
74
|
+
res = http.request(request)
|
75
|
+
next if res.code.to_i.between?(200,299)
|
76
|
+
@log.log_error_message("Error submitting ticket data: #{res.message}, #{res.body}")
|
77
|
+
res
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Sends a request to the JIRA console.
|
82
|
+
#
|
83
|
+
# * *Args* :
|
84
|
+
# - +uri+ - Address of the JIRA endpoint.
|
85
|
+
# - +request+ - Request containing the query.
|
86
|
+
#
|
87
|
+
# * *Returns* :
|
88
|
+
# - HTTPResponse containing result from the JIRA console.
|
89
|
+
#
|
90
|
+
def send_jira_request(uri, request)
|
91
|
+
send_request(uri, request)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Sends a ticket object to the JIRA console.
|
95
|
+
#
|
96
|
+
# * *Args* :
|
97
|
+
# - +uri+ - Address of the JIRA endpoint.
|
98
|
+
# - +request+ - Request containing the ticket object.
|
99
|
+
#
|
100
|
+
# * *Returns* :
|
101
|
+
# - HTTPResponse containing result from the JIRA console.
|
102
|
+
#
|
103
|
+
def send_ticket(uri, request)
|
104
|
+
send_request(uri, request, true)
|
58
105
|
end
|
59
106
|
|
60
107
|
# Fetches the Jira ticket transition details for the given Jira ticket key. Tries to match the response to the
|
@@ -75,16 +122,7 @@ class JiraHelper
|
|
75
122
|
|
76
123
|
uri = URI.parse(("#{@jira_data[:jira_url]}#{jira_key}/transitions?expand=transitions.fields."))
|
77
124
|
req = Net::HTTP::Get.new(uri.to_s, headers)
|
78
|
-
|
79
|
-
resp = Net::HTTP.new(uri.host, uri.port)
|
80
|
-
|
81
|
-
# Enable this line for debugging the https call.
|
82
|
-
# resp.set_debug_output(@log)
|
83
|
-
|
84
|
-
resp.use_ssl = true if uri.scheme == 'https'
|
85
|
-
resp.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
86
|
-
|
87
|
-
response = resp.request(req)
|
125
|
+
response = send_jira_request(uri, req)
|
88
126
|
|
89
127
|
transitions = JSON.parse(response.body)
|
90
128
|
|
@@ -108,16 +146,8 @@ class JiraHelper
|
|
108
146
|
|
109
147
|
uri = URI.parse("#{@jira_data[:jira_url]}")
|
110
148
|
req = Net::HTTP::Post.new(@jira_data[:jira_url], headers)
|
111
|
-
req.basic_auth @jira_data[:username], @jira_data[:password]
|
112
149
|
req.body = ticket
|
113
|
-
|
114
|
-
|
115
|
-
# Enable this line for debugging the https call.
|
116
|
-
#resp.set_debug_output(@log)
|
117
|
-
|
118
|
-
resp.use_ssl = true if uri.scheme == 'https'
|
119
|
-
resp.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
120
|
-
resp.start { |http| http.request(req) }
|
150
|
+
send_ticket(uri, req)
|
121
151
|
end
|
122
152
|
end
|
123
153
|
|
@@ -196,10 +226,9 @@ class JiraHelper
|
|
196
226
|
headers = { 'Content-Type' => 'application/json',
|
197
227
|
'Accept' => 'application/json' }
|
198
228
|
|
199
|
-
tickets.each
|
229
|
+
tickets.each do |ticket|
|
200
230
|
uri = URI.parse(("#{@jira_data[:jira_url]}#{ticket}/transitions"))
|
201
231
|
req = Net::HTTP::Post.new(uri.to_s, headers)
|
202
|
-
req.basic_auth @jira_data[:username], @jira_data[:password]
|
203
232
|
|
204
233
|
transition = get_jira_transition_details(ticket, @jira_data[:close_step_id])
|
205
234
|
if transition.nil?
|
@@ -227,15 +256,8 @@ class JiraHelper
|
|
227
256
|
end
|
228
257
|
|
229
258
|
req.body = "{\"transition\" : {\"id\" : #{transition['id']}}, \"fields\" : { #{required_fields.join(",")}}}"
|
230
|
-
|
231
|
-
|
232
|
-
# Enable this line for debugging the https call.
|
233
|
-
#resp.set_debug_output(@log)
|
234
|
-
|
235
|
-
resp.use_ssl = true if uri.scheme == 'https'
|
236
|
-
resp.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
237
|
-
resp.start { |http| http.request(req) }
|
238
|
-
}
|
259
|
+
send_ticket(uri, req)
|
260
|
+
end
|
239
261
|
end
|
240
262
|
end
|
241
263
|
|
@@ -287,19 +309,11 @@ class JiraHelper
|
|
287
309
|
|
288
310
|
send_whole_ticket ? req = Net::HTTP::Post.new(uri.to_s, headers) : req = Net::HTTP::Put.new(uri.to_s, headers)
|
289
311
|
|
290
|
-
req.basic_auth @jira_data[:username], @jira_data[:password]
|
291
312
|
send_whole_ticket ?
|
292
313
|
req.body = ticket_details.last :
|
293
314
|
req.body = {'update' => {'description' => [{'set' => "#{JSON.parse(ticket_details[1])['fields']['description']}"}]}}.to_json
|
294
315
|
|
295
|
-
|
296
|
-
|
297
|
-
# Enable this line for debugging the https call.
|
298
|
-
#resp.set_debug_output(@log)
|
299
|
-
|
300
|
-
resp.use_ssl = true if uri.scheme == 'https'
|
301
|
-
resp.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
302
|
-
resp.start { |http| http.request(req) }
|
316
|
+
send_ticket(uri, req)
|
303
317
|
end
|
304
318
|
end
|
305
319
|
end
|
@@ -188,7 +188,7 @@ class ServiceNowHelper
|
|
188
188
|
#
|
189
189
|
def prepare_tickets(vulnerability_list, nexpose_identifier_id, matching_fields)
|
190
190
|
@ticket = Hash.new(-1)
|
191
|
-
|
191
|
+
|
192
192
|
@log.log_message("Preparing tickets in #{options[:ticket_mode]} address.")
|
193
193
|
tickets = []
|
194
194
|
previous_row = nil
|
@@ -200,10 +200,10 @@ class ServiceNowHelper
|
|
200
200
|
previous_row = row.dup
|
201
201
|
nxid = @common_helper.generate_nxid(nexpose_identifier_id, row)
|
202
202
|
|
203
|
-
action =
|
204
|
-
'update'
|
205
|
-
else
|
203
|
+
action = if row['comparison'].nil? || row['comparison'] == 'New'
|
206
204
|
'insert'
|
205
|
+
else
|
206
|
+
'update'
|
207
207
|
end
|
208
208
|
|
209
209
|
@ticket = {
|
@@ -229,7 +229,9 @@ class ServiceNowHelper
|
|
229
229
|
description = nil
|
230
230
|
redo
|
231
231
|
else
|
232
|
-
|
232
|
+
unless row['comparison'].nil? || row['comparison'] == 'New'
|
233
|
+
@ticket['sysparm_action'] = 'update'
|
234
|
+
end
|
233
235
|
description = @common_helper.update_description(description, row)
|
234
236
|
end
|
235
237
|
end
|
@@ -46,7 +46,7 @@ module NexposeTicketing
|
|
46
46
|
require 'logger'
|
47
47
|
directory = File.dirname(@logger_file)
|
48
48
|
FileUtils.mkdir_p(directory) unless File.directory?(directory)
|
49
|
-
io = IO.for_fd(IO.sysopen(@logger_file, 'a'))
|
49
|
+
io = IO.for_fd(IO.sysopen(@logger_file, 'a'), 'a')
|
50
50
|
io.autoclose = false
|
51
51
|
io.sync = true
|
52
52
|
@log = Logger.new(io, 'weekly')
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nexpose_ticketing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Damian Finol
|
@@ -10,94 +10,94 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2016-
|
13
|
+
date: 2016-02-08 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: nexpose
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
18
18
|
requirements:
|
19
|
-
- - ~>
|
19
|
+
- - "~>"
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: '2.1'
|
22
|
-
- -
|
22
|
+
- - ">="
|
23
23
|
- !ruby/object:Gem::Version
|
24
24
|
version: 2.1.0
|
25
25
|
type: :runtime
|
26
26
|
prerelease: false
|
27
27
|
version_requirements: !ruby/object:Gem::Requirement
|
28
28
|
requirements:
|
29
|
-
- - ~>
|
29
|
+
- - "~>"
|
30
30
|
- !ruby/object:Gem::Version
|
31
31
|
version: '2.1'
|
32
|
-
- -
|
32
|
+
- - ">="
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: 2.1.0
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: savon
|
37
37
|
requirement: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- - ~>
|
39
|
+
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '2.1'
|
42
42
|
type: :runtime
|
43
43
|
prerelease: false
|
44
44
|
version_requirements: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- - ~>
|
46
|
+
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
48
|
version: '2.1'
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
50
|
name: nokogiri
|
51
51
|
requirement: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
|
-
- - ~>
|
53
|
+
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '1.6'
|
56
56
|
type: :runtime
|
57
57
|
prerelease: false
|
58
58
|
version_requirements: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
|
-
- - ~>
|
60
|
+
- - "~>"
|
61
61
|
- !ruby/object:Gem::Version
|
62
62
|
version: '1.6'
|
63
63
|
- !ruby/object:Gem::Dependency
|
64
64
|
name: rspec
|
65
65
|
requirement: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
|
-
- - ~>
|
67
|
+
- - "~>"
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: '3.2'
|
70
|
-
- -
|
70
|
+
- - ">="
|
71
71
|
- !ruby/object:Gem::Version
|
72
72
|
version: 3.2.0
|
73
73
|
type: :development
|
74
74
|
prerelease: false
|
75
75
|
version_requirements: !ruby/object:Gem::Requirement
|
76
76
|
requirements:
|
77
|
-
- - ~>
|
77
|
+
- - "~>"
|
78
78
|
- !ruby/object:Gem::Version
|
79
79
|
version: '3.2'
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 3.2.0
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: rspec-mocks
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - ~>
|
87
|
+
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '3.2'
|
90
|
-
- -
|
90
|
+
- - ">="
|
91
91
|
- !ruby/object:Gem::Version
|
92
92
|
version: 3.2.0
|
93
93
|
type: :development
|
94
94
|
prerelease: false
|
95
95
|
version_requirements: !ruby/object:Gem::Requirement
|
96
96
|
requirements:
|
97
|
-
- - ~>
|
97
|
+
- - "~>"
|
98
98
|
- !ruby/object:Gem::Version
|
99
99
|
version: '3.2'
|
100
|
-
- -
|
100
|
+
- - ">="
|
101
101
|
- !ruby/object:Gem::Version
|
102
102
|
version: 3.2.0
|
103
103
|
description: This gem provides a Ruby implementation of different integrations with
|
@@ -149,17 +149,17 @@ require_paths:
|
|
149
149
|
- lib
|
150
150
|
required_ruby_version: !ruby/object:Gem::Requirement
|
151
151
|
requirements:
|
152
|
-
- -
|
152
|
+
- - ">="
|
153
153
|
- !ruby/object:Gem::Version
|
154
154
|
version: '1.9'
|
155
155
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
156
156
|
requirements:
|
157
|
-
- -
|
157
|
+
- - ">="
|
158
158
|
- !ruby/object:Gem::Version
|
159
159
|
version: '0'
|
160
160
|
requirements: []
|
161
161
|
rubyforge_project:
|
162
|
-
rubygems_version: 2.
|
162
|
+
rubygems_version: 2.4.8
|
163
163
|
signing_key:
|
164
164
|
specification_version: 4
|
165
165
|
summary: Ruby Nexpose Ticketing Engine.
|