moj-nessus-automation 0.0.1
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 +7 -0
- data/.gitignore +2 -0
- data/README.md +2 -0
- data/lib/example.rb +31 -0
- data/lib/nessus.rb +9 -0
- data/lib/nessus/scan.rb +125 -0
- data/lib/nessus/settings.rb +50 -0
- data/lib/nessus/version.rb +6 -0
- data/lib/nessus/xmlrpc.rb +315 -0
- data/moj-nessus-automation.gemspec +21 -0
- metadata +52 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bf73193651160ed38be74d9296150fc56d39ba07
|
4
|
+
data.tar.gz: d28ec9c8d573df1c2f7e89d528e5b4cb145fd63c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: be194d067c703bcba38afa28bce1ec3959bf1ac75114c722bcdee9f64f4ad845105cae223f959a883933a1783f789f81a2e523a51c99447f699e7726a624884c
|
7
|
+
data.tar.gz: 023fb8f527c1ad80de4d7b2fda71ff8d3af206495b24c5bac2533454b869ed7c9963a76d9076713127fa9a7ce3de36dcefc8616e3698b46b70a8402708b194c8
|
data/.gitignore
ADDED
data/README.md
ADDED
data/lib/example.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative 'nessus.rb'
|
4
|
+
|
5
|
+
# Create a new scan instance
|
6
|
+
scan = Nessus::Scan.new(
|
7
|
+
'webapp',
|
8
|
+
'https://preprod-prisonvisits.dsd.io/prisoner'
|
9
|
+
)
|
10
|
+
|
11
|
+
# Check details of scan created
|
12
|
+
scan.details
|
13
|
+
|
14
|
+
# Launch the scan
|
15
|
+
scan.launch!
|
16
|
+
|
17
|
+
# View scan result
|
18
|
+
scan.view
|
19
|
+
|
20
|
+
# Convenience methods for vulnerability management
|
21
|
+
scan.result.critical?
|
22
|
+
scan.result.high?
|
23
|
+
scan.result.medium?
|
24
|
+
|
25
|
+
# Export the scan as csv
|
26
|
+
scan.export_csv('/tmp/nessus.csv')
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
|
data/lib/nessus.rb
ADDED
data/lib/nessus/scan.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
require_relative './xmlrpc.rb'
|
2
|
+
require_relative './settings.rb'
|
3
|
+
|
4
|
+
module Nessus
|
5
|
+
class Scan
|
6
|
+
#
|
7
|
+
# Wrapper for XMLRPC client
|
8
|
+
#
|
9
|
+
# @attr_reader [String] uuid of scan template
|
10
|
+
# @attr_reader [Fixnum] scan id
|
11
|
+
# @attr_reader [Hash] full scan details
|
12
|
+
# @attr_reader [Result] full scan result
|
13
|
+
#
|
14
|
+
attr_reader :uuid, :id, :details, :result
|
15
|
+
#
|
16
|
+
# Create a new scan instance
|
17
|
+
#
|
18
|
+
# @param [String] nessus scan template name
|
19
|
+
# @param [Array<String>] target addresses e.g http://localhost:3000
|
20
|
+
#
|
21
|
+
# @return [Scan]
|
22
|
+
#
|
23
|
+
def initialize(name, targets)
|
24
|
+
set_uuid(name)
|
25
|
+
setup_scan(targets)
|
26
|
+
end
|
27
|
+
#
|
28
|
+
# Launches the scan
|
29
|
+
#
|
30
|
+
# @return [Result] the result hash from the scan
|
31
|
+
#
|
32
|
+
def launch!
|
33
|
+
client.scan_launch(@id)
|
34
|
+
|
35
|
+
loop do
|
36
|
+
raw = client.scan_details(@id)
|
37
|
+
status = raw['info']['status']
|
38
|
+
|
39
|
+
if status != 'running'
|
40
|
+
@result = Result.new(raw)
|
41
|
+
break
|
42
|
+
end
|
43
|
+
|
44
|
+
sleep Nessus::Settings.refresh_interval
|
45
|
+
end
|
46
|
+
end
|
47
|
+
#
|
48
|
+
# View the result of a finished scan
|
49
|
+
#
|
50
|
+
# @return [Hash] the raw result hash from the scan
|
51
|
+
#
|
52
|
+
def view
|
53
|
+
result && result.raw
|
54
|
+
end
|
55
|
+
#
|
56
|
+
# Export scan to csv file
|
57
|
+
#
|
58
|
+
# @param [String] output filepath
|
59
|
+
#
|
60
|
+
# @return [Fixnum] bytes written to file
|
61
|
+
#
|
62
|
+
def export_csv(filepath)
|
63
|
+
csv_id = client.scan_export(@id, 'csv')
|
64
|
+
csv_data = client.report_download(@id, csv_id['file'])
|
65
|
+
|
66
|
+
File.write(filepath, csv_data)
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def set_uuid(name)
|
72
|
+
@uuid = client
|
73
|
+
.list_template('scan')
|
74
|
+
.fetch('templates', [])
|
75
|
+
.find { |t| t['name'] == name }
|
76
|
+
.fetch('uuid')
|
77
|
+
end
|
78
|
+
|
79
|
+
def setup_scan(targets)
|
80
|
+
@details = client.scan_create(
|
81
|
+
@uuid,
|
82
|
+
"Automated Scan #{Time.now}",
|
83
|
+
"This scan was created by the Nessus ruby client as part of automated testing",
|
84
|
+
targets
|
85
|
+
)
|
86
|
+
|
87
|
+
@id = @details['scan']['id']
|
88
|
+
end
|
89
|
+
|
90
|
+
def client
|
91
|
+
@client ||= Nessus::Client.new(
|
92
|
+
Nessus::Settings.host,
|
93
|
+
Nessus::Settings.username,
|
94
|
+
Nessus::Settings.password,
|
95
|
+
Nessus::Settings.ssl_verify
|
96
|
+
)
|
97
|
+
end
|
98
|
+
|
99
|
+
class Result
|
100
|
+
attr_reader :raw
|
101
|
+
|
102
|
+
def initialize(raw)
|
103
|
+
@raw = raw
|
104
|
+
end
|
105
|
+
|
106
|
+
def critical?
|
107
|
+
check('critical')
|
108
|
+
end
|
109
|
+
|
110
|
+
def high?
|
111
|
+
check('high')
|
112
|
+
end
|
113
|
+
|
114
|
+
def medium?
|
115
|
+
check('medium')
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def check(severity)
|
121
|
+
raw['hosts'].any? { |h| h.fetch(severity) > 0 }
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#
|
2
|
+
# Define static scan settings
|
3
|
+
#
|
4
|
+
module Nessus
|
5
|
+
module Settings
|
6
|
+
extend self
|
7
|
+
#
|
8
|
+
# Host for Nessus instance
|
9
|
+
#
|
10
|
+
# @return [String]
|
11
|
+
#
|
12
|
+
def host
|
13
|
+
ENV.fetch('NESSUS_HOST', 'http://localhost:8834')
|
14
|
+
end
|
15
|
+
#
|
16
|
+
# Nessus username
|
17
|
+
#
|
18
|
+
# @return [String]
|
19
|
+
#
|
20
|
+
def username
|
21
|
+
ENV.fetch('NESSUS_USER', 'test_user')
|
22
|
+
end
|
23
|
+
#
|
24
|
+
# Nessus password
|
25
|
+
#
|
26
|
+
# @return [String]
|
27
|
+
#
|
28
|
+
def password
|
29
|
+
ENV.fetch('NESSUS_PASS', 'test_pass')
|
30
|
+
end
|
31
|
+
#
|
32
|
+
# SSL connection settings for Nessus instance
|
33
|
+
#
|
34
|
+
# @note set to 'ssl_verify' in PRODUCTION
|
35
|
+
#
|
36
|
+
# @return [String]
|
37
|
+
#
|
38
|
+
def ssl_verify
|
39
|
+
'none' # ssl_verify for secure connection
|
40
|
+
end
|
41
|
+
#
|
42
|
+
# Refresh interval when checking for job completion
|
43
|
+
#
|
44
|
+
# @return [Fixnum]
|
45
|
+
#
|
46
|
+
def refresh_interval
|
47
|
+
5
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,315 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'json'
|
3
|
+
require 'openssl'
|
4
|
+
#
|
5
|
+
# Nessus XML RPC Client
|
6
|
+
#
|
7
|
+
# @author Metasploit Framework
|
8
|
+
# @see https://github.com/rapid7/metasploit-framework/blob/master/lib/nessus/nessus-xmlrpc.rb
|
9
|
+
#
|
10
|
+
module Nessus
|
11
|
+
class Client
|
12
|
+
class << self
|
13
|
+
@connection
|
14
|
+
@token
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(host, username = nil, password = nil, ssl_option = nil)
|
18
|
+
uri = URI.parse(host)
|
19
|
+
@connection = Net::HTTP.new(uri.host, uri.port)
|
20
|
+
@connection.use_ssl = true
|
21
|
+
if ssl_option == "ssl_verify"
|
22
|
+
@connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
23
|
+
else
|
24
|
+
@connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
25
|
+
end
|
26
|
+
|
27
|
+
yield @connection if block_given?
|
28
|
+
authenticate(username, password) if username && password
|
29
|
+
end
|
30
|
+
|
31
|
+
def authenticate(username, password)
|
32
|
+
payload = {
|
33
|
+
:username => username,
|
34
|
+
:password => password,
|
35
|
+
:json => 1
|
36
|
+
}
|
37
|
+
res = http_post(:uri=>"/session", :data=>payload)
|
38
|
+
if res['token']
|
39
|
+
@token = "token=#{res['token']}"
|
40
|
+
return true
|
41
|
+
else
|
42
|
+
false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def x_cookie
|
47
|
+
{'X-Cookie'=>@token}
|
48
|
+
end
|
49
|
+
|
50
|
+
alias_method :login, :authenticate
|
51
|
+
|
52
|
+
def authenticated
|
53
|
+
if (@token && @token.include?('token='))
|
54
|
+
return true
|
55
|
+
else
|
56
|
+
return false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_server_properties
|
61
|
+
http_get(:uri=>"/server/properties", :fields=>x_cookie)
|
62
|
+
end
|
63
|
+
|
64
|
+
def user_add(username, password, permissions, type)
|
65
|
+
payload = {
|
66
|
+
:username => username,
|
67
|
+
:password => password,
|
68
|
+
:permissions => permissions,
|
69
|
+
:type => type,
|
70
|
+
:json => 1
|
71
|
+
}
|
72
|
+
http_post(:uri=>"/users", :fields=>x_cookie, :data=>payload)
|
73
|
+
end
|
74
|
+
|
75
|
+
def user_delete(user_id)
|
76
|
+
res = http_delete(:uri=>"/users/#{user_id}", :fields=>x_cookie)
|
77
|
+
return res.code
|
78
|
+
end
|
79
|
+
|
80
|
+
def user_chpasswd(user_id, password)
|
81
|
+
payload = {
|
82
|
+
:password => password,
|
83
|
+
:json => 1
|
84
|
+
}
|
85
|
+
res = http_put(:uri=>"/users/#{user_id}/chpasswd", :data=>payload, :fields=>x_cookie)
|
86
|
+
return res.code
|
87
|
+
end
|
88
|
+
|
89
|
+
def user_logout
|
90
|
+
res = http_delete(:uri=>"/session", :fields=>x_cookie)
|
91
|
+
return res.code
|
92
|
+
end
|
93
|
+
|
94
|
+
def list_policies
|
95
|
+
http_get(:uri=>"/policies", :fields=>x_cookie)
|
96
|
+
end
|
97
|
+
|
98
|
+
def list_users
|
99
|
+
http_get(:uri=>"/users", :fields=>x_cookie)
|
100
|
+
end
|
101
|
+
|
102
|
+
def list_folders
|
103
|
+
http_get(:uri=>"/folders", :fields=>x_cookie)
|
104
|
+
end
|
105
|
+
|
106
|
+
def list_scanners
|
107
|
+
http_get(:uri=>"/scanners", :fields=>x_cookie)
|
108
|
+
end
|
109
|
+
|
110
|
+
def list_families
|
111
|
+
http_get(:uri=>"/plugins/families", :fields=>x_cookie)
|
112
|
+
end
|
113
|
+
|
114
|
+
def list_plugins(family_id)
|
115
|
+
http_get(:uri=>"/plugins/families/#{family_id}", :fields=>x_cookie)
|
116
|
+
end
|
117
|
+
|
118
|
+
def list_template(type)
|
119
|
+
res = http_get(:uri=>"/editor/#{type}/templates", :fields=>x_cookie)
|
120
|
+
end
|
121
|
+
|
122
|
+
def plugin_details(plugin_id)
|
123
|
+
http_get(:uri=>"/plugins/plugin/#{plugin_id}", :fields=>x_cookie)
|
124
|
+
end
|
125
|
+
|
126
|
+
def is_admin
|
127
|
+
res = http_get(:uri=>"/session", :fields=>x_cookie)
|
128
|
+
if res['permissions'] == 128
|
129
|
+
return true
|
130
|
+
else
|
131
|
+
return false
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def server_properties
|
136
|
+
http_get(:uri=>"/server/properties", :fields=>x_cookie)
|
137
|
+
end
|
138
|
+
|
139
|
+
def scan_create(uuid, name, description, targets)
|
140
|
+
payload = {
|
141
|
+
:uuid => uuid,
|
142
|
+
:settings => {
|
143
|
+
:name => name,
|
144
|
+
:description => description,
|
145
|
+
:text_targets => targets
|
146
|
+
},
|
147
|
+
:json => 1
|
148
|
+
}.to_json
|
149
|
+
http_post(:uri=>"/scans", :body=>payload, :fields=>x_cookie, :ctype=>'application/json')
|
150
|
+
end
|
151
|
+
|
152
|
+
def scan_launch(scan_id)
|
153
|
+
http_post(:uri=>"/scans/#{scan_id}/launch", :fields=>x_cookie)
|
154
|
+
end
|
155
|
+
|
156
|
+
def server_status
|
157
|
+
http_get(:uri=>"/server/status", :fields=>x_cookie)
|
158
|
+
end
|
159
|
+
|
160
|
+
def scan_list
|
161
|
+
http_get(:uri=>"/scans", :fields=>x_cookie)
|
162
|
+
end
|
163
|
+
|
164
|
+
def scan_details(scan_id)
|
165
|
+
http_get(:uri=>"/scans/#{scan_id}", :fields=>x_cookie)
|
166
|
+
end
|
167
|
+
|
168
|
+
def scan_pause(scan_id)
|
169
|
+
http_post(:uri=>"/scans/#{scan_id}/pause", :fields=>x_cookie)
|
170
|
+
end
|
171
|
+
|
172
|
+
def scan_resume(scan_id)
|
173
|
+
http_post(:uri=>"/scans/#{scan_id}/resume", :fields=>x_cookie)
|
174
|
+
end
|
175
|
+
|
176
|
+
def scan_stop(scan_id)
|
177
|
+
http_post(:uri=>"/scans/#{scan_id}/stop", :fields=>x_cookie)
|
178
|
+
end
|
179
|
+
|
180
|
+
def scan_export(scan_id, format)
|
181
|
+
payload = {
|
182
|
+
:format => format
|
183
|
+
}.to_json
|
184
|
+
http_post(:uri=>"/scans/#{scan_id}/export", :body=>payload, :ctype=>'application/json', :fields=>x_cookie)
|
185
|
+
end
|
186
|
+
|
187
|
+
def scan_export_status(scan_id, file_id)
|
188
|
+
request = Net::HTTP::Get.new("/scans/#{scan_id}/export/#{file_id}/status")
|
189
|
+
request.add_field("X-Cookie", @token)
|
190
|
+
res = @connection.request(request)
|
191
|
+
if res.code == "200"
|
192
|
+
return "ready"
|
193
|
+
else
|
194
|
+
res = JSON.parse(res.body)
|
195
|
+
return res
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def policy_delete(policy_id)
|
200
|
+
res = http_delete(:uri=>"/policies/#{policy_id}", :fields=>x_cookie)
|
201
|
+
return res.code
|
202
|
+
end
|
203
|
+
|
204
|
+
def host_detail(scan_id, host_id)
|
205
|
+
res = http_get(:uri=>"/scans/#{scan_id}/hosts/#{host_id}", :fields=>x_cookie)
|
206
|
+
end
|
207
|
+
|
208
|
+
def report_download(scan_id, file_id)
|
209
|
+
res = http_get(:uri=>"/scans/#{scan_id}/export/#{file_id}/download", :raw_content=> true, :fields=>x_cookie)
|
210
|
+
end
|
211
|
+
|
212
|
+
private
|
213
|
+
|
214
|
+
def http_put(opts={})
|
215
|
+
uri = opts[:uri]
|
216
|
+
data = opts[:data]
|
217
|
+
fields = opts[:fields] || {}
|
218
|
+
res = nil
|
219
|
+
|
220
|
+
req = Net::HTTP::Put.new(uri)
|
221
|
+
req.set_form_data(data) unless data.blank?
|
222
|
+
fields.each_pair do |name, value|
|
223
|
+
req.add_field(name, value)
|
224
|
+
end
|
225
|
+
|
226
|
+
begin
|
227
|
+
res = @connection.request(req)
|
228
|
+
rescue URI::InvalidURIError
|
229
|
+
return res
|
230
|
+
end
|
231
|
+
|
232
|
+
res
|
233
|
+
end
|
234
|
+
|
235
|
+
def http_delete(opts={})
|
236
|
+
uri = opts[:uri]
|
237
|
+
fields = opts[:fields] || {}
|
238
|
+
res = nil
|
239
|
+
|
240
|
+
req = Net::HTTP::Delete.new(uri)
|
241
|
+
|
242
|
+
fields.each_pair do |name, value|
|
243
|
+
req.add_field(name, value)
|
244
|
+
end
|
245
|
+
|
246
|
+
begin
|
247
|
+
res = @connection.request(req)
|
248
|
+
rescue URI::InvalidURIError
|
249
|
+
return res
|
250
|
+
end
|
251
|
+
|
252
|
+
res
|
253
|
+
end
|
254
|
+
|
255
|
+
def http_get(opts={})
|
256
|
+
uri = opts[:uri]
|
257
|
+
fields = opts[:fields] || {}
|
258
|
+
raw_content = opts[:raw_content] || false
|
259
|
+
json = {}
|
260
|
+
|
261
|
+
req = Net::HTTP::Get.new(uri)
|
262
|
+
fields.each_pair do |name, value|
|
263
|
+
req.add_field(name, value)
|
264
|
+
end
|
265
|
+
|
266
|
+
begin
|
267
|
+
res = @connection.request(req)
|
268
|
+
rescue URI::InvalidURIError
|
269
|
+
return json
|
270
|
+
end
|
271
|
+
if !raw_content
|
272
|
+
parse_json(res.body)
|
273
|
+
else
|
274
|
+
res.body
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
def http_post(opts = {})
|
279
|
+
uri = opts[:uri]
|
280
|
+
data = opts[:data]
|
281
|
+
fields = opts[:fields] || {}
|
282
|
+
body = opts[:body]
|
283
|
+
ctype = opts[:ctype]
|
284
|
+
json = {}
|
285
|
+
|
286
|
+
req = Net::HTTP::Post.new(uri)
|
287
|
+
req.set_form_data(data) if data
|
288
|
+
req.body = body if body
|
289
|
+
req['Content-Type'] = ctype if ctype
|
290
|
+
fields.each_pair do |name, value|
|
291
|
+
req.add_field(name, value)
|
292
|
+
end
|
293
|
+
|
294
|
+
begin
|
295
|
+
res = @connection.request(req)
|
296
|
+
rescue URI::InvalidURIError
|
297
|
+
return json
|
298
|
+
end
|
299
|
+
|
300
|
+
parse_json(res.body)
|
301
|
+
end
|
302
|
+
|
303
|
+
def parse_json(body)
|
304
|
+
buf = {}
|
305
|
+
|
306
|
+
begin
|
307
|
+
buf = JSON.parse(body)
|
308
|
+
rescue JSON::ParserError
|
309
|
+
end
|
310
|
+
|
311
|
+
buf
|
312
|
+
end
|
313
|
+
|
314
|
+
end
|
315
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
lib = File.expand_path('./lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
require './lib/nessus/version.rb'
|
7
|
+
|
8
|
+
Gem::Specification.new do |s|
|
9
|
+
s.name = 'moj-nessus-automation'
|
10
|
+
s.version = Nessus::VERSION
|
11
|
+
s.date = '2014-09-24'
|
12
|
+
s.summary = 'Nessus Automation Gem'
|
13
|
+
s.description = 'A gem to automate nessus vulnerability scanning'
|
14
|
+
s.authors = ['Jeremy Fox']
|
15
|
+
s.email = 'jeremy.fox@digital.justice.gov.uk'
|
16
|
+
s.files = `git ls-files`.split($/)
|
17
|
+
s.require_paths = ['lib']
|
18
|
+
s.homepage =
|
19
|
+
'http://rubygems.org/gems/moj-nesssus-automation'
|
20
|
+
s.license = 'MIT'
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: moj-nessus-automation
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jeremy Fox
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-09-24 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A gem to automate nessus vulnerability scanning
|
14
|
+
email: jeremy.fox@digital.justice.gov.uk
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- ".gitignore"
|
20
|
+
- README.md
|
21
|
+
- lib/example.rb
|
22
|
+
- lib/nessus.rb
|
23
|
+
- lib/nessus/scan.rb
|
24
|
+
- lib/nessus/settings.rb
|
25
|
+
- lib/nessus/version.rb
|
26
|
+
- lib/nessus/xmlrpc.rb
|
27
|
+
- moj-nessus-automation.gemspec
|
28
|
+
homepage: http://rubygems.org/gems/moj-nesssus-automation
|
29
|
+
licenses:
|
30
|
+
- MIT
|
31
|
+
metadata: {}
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
requirements: []
|
47
|
+
rubyforge_project:
|
48
|
+
rubygems_version: 2.4.5
|
49
|
+
signing_key:
|
50
|
+
specification_version: 4
|
51
|
+
summary: Nessus Automation Gem
|
52
|
+
test_files: []
|