nexpose 6.1.1 → 7.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +772 -0
- data/COPYING +27 -31
- data/Gemfile.lock +72 -30
- data/README.markdown +3 -1
- data/Rakefile +9 -0
- data/lib/nexpose.rb +1 -0
- data/lib/nexpose/ajax.rb +8 -6
- data/lib/nexpose/api_request.rb +27 -26
- data/lib/nexpose/connection.rb +28 -20
- data/lib/nexpose/credential.rb +16 -218
- data/lib/nexpose/credential_helper.rb +169 -0
- data/lib/nexpose/dag.rb +3 -3
- data/lib/nexpose/filter.rb +3 -1
- data/lib/nexpose/scan.rb +5 -1
- data/lib/nexpose/shared_credential.rb +13 -5
- data/lib/nexpose/site_credentials.rb +55 -9
- data/lib/nexpose/version.rb +1 -1
- metadata +32 -2
data/COPYING
CHANGED
@@ -1,33 +1,29 @@
|
|
1
|
-
|
2
|
-
All rights reserved.
|
3
|
-
|
4
|
-
Redistribution and use in source and binary forms, with or without modification,
|
5
|
-
are permitted provided that the following conditions are met:
|
6
|
-
|
7
|
-
* Redistributions of source code must retain the above copyright notice,
|
8
|
-
this list of conditions and the following disclaimer.
|
9
|
-
|
10
|
-
* Redistributions in binary form must reproduce the above copyright notice,
|
11
|
-
this list of conditions and the following disclaimer in the documentation
|
12
|
-
and/or other materials provided with the distribution.
|
1
|
+
BSD 3-Clause License
|
13
2
|
|
14
|
-
|
15
|
-
|
16
|
-
without specific prior written permission.
|
17
|
-
|
18
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
19
|
-
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
20
|
-
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
21
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
22
|
-
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
23
|
-
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
24
|
-
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
25
|
-
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
26
|
-
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
27
|
-
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28
|
-
|
29
|
-
================================================================================
|
30
|
-
|
31
|
-
The nexpose-client gem is provided under the 3-clause BSD license above.
|
3
|
+
Copyright (c) 2014-2017, Rapid7, Inc.
|
4
|
+
All rights reserved.
|
32
5
|
|
33
|
-
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
8
|
+
|
9
|
+
* Redistributions of source code must retain the above copyright notice, this
|
10
|
+
list of conditions and the following disclaimer.
|
11
|
+
|
12
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
14
|
+
and/or other materials provided with the distribution.
|
15
|
+
|
16
|
+
* Neither the name of the copyright holder nor the names of its
|
17
|
+
contributors may be used to endorse or promote products derived from
|
18
|
+
this software without specific prior written permission.
|
19
|
+
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/Gemfile.lock
CHANGED
@@ -1,53 +1,93 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
nexpose (
|
4
|
+
nexpose (7.0.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
activesupport (4.2.8)
|
10
|
+
i18n (~> 0.7)
|
11
|
+
minitest (~> 5.1)
|
12
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
13
|
+
tzinfo (~> 1.1)
|
14
|
+
addressable (2.5.1)
|
15
|
+
public_suffix (~> 2.0, >= 2.0.2)
|
16
|
+
ast (2.3.0)
|
17
|
+
codeclimate-test-reporter (0.4.8)
|
14
18
|
simplecov (>= 0.7.1, < 1.0.0)
|
15
|
-
|
19
|
+
coderay (1.1.1)
|
20
|
+
crack (0.4.3)
|
16
21
|
safe_yaml (~> 1.0.0)
|
17
|
-
diff-lcs (1.
|
22
|
+
diff-lcs (1.3)
|
18
23
|
docile (1.1.5)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
24
|
+
faraday (0.12.0.1)
|
25
|
+
multipart-post (>= 1.2, < 3)
|
26
|
+
faraday-http-cache (2.0.0)
|
27
|
+
faraday (~> 0.8)
|
28
|
+
github_changelog_generator (1.14.3)
|
29
|
+
activesupport
|
30
|
+
faraday-http-cache
|
31
|
+
multi_json
|
32
|
+
octokit (~> 4.6)
|
33
|
+
rainbow (>= 2.1)
|
34
|
+
rake (>= 10.0)
|
35
|
+
retriable (~> 2.1)
|
36
|
+
i18n (0.8.1)
|
37
|
+
method_source (0.8.2)
|
38
|
+
minitest (5.10.1)
|
39
|
+
multi_json (1.12.1)
|
40
|
+
multipart-post (2.0.0)
|
41
|
+
octokit (4.7.0)
|
42
|
+
sawyer (~> 0.8.0, >= 0.5.3)
|
43
|
+
parallel (1.12.0)
|
44
|
+
parser (2.4.0.0)
|
45
|
+
ast (~> 2.2)
|
46
|
+
powerpack (0.1.1)
|
47
|
+
pry (0.9.12.6)
|
48
|
+
coderay (~> 1.0)
|
49
|
+
method_source (~> 0.8)
|
50
|
+
slop (~> 3.4)
|
51
|
+
public_suffix (2.0.5)
|
52
|
+
rainbow (2.2.2)
|
53
|
+
rake
|
54
|
+
rake (12.0.0)
|
55
|
+
retriable (2.1.0)
|
56
|
+
rspec (3.6.0)
|
57
|
+
rspec-core (~> 3.6.0)
|
58
|
+
rspec-expectations (~> 3.6.0)
|
59
|
+
rspec-mocks (~> 3.6.0)
|
60
|
+
rspec-core (3.6.0)
|
61
|
+
rspec-support (~> 3.6.0)
|
62
|
+
rspec-expectations (3.6.0)
|
32
63
|
diff-lcs (>= 1.2.0, < 2.0)
|
33
|
-
rspec-support (~> 3.
|
34
|
-
rspec-mocks (3.
|
64
|
+
rspec-support (~> 3.6.0)
|
65
|
+
rspec-mocks (3.6.0)
|
35
66
|
diff-lcs (>= 1.2.0, < 2.0)
|
36
|
-
rspec-support (~> 3.
|
37
|
-
rspec-support (3.
|
38
|
-
rubocop (0.
|
39
|
-
|
40
|
-
parser (>= 2.
|
67
|
+
rspec-support (~> 3.6.0)
|
68
|
+
rspec-support (3.6.0)
|
69
|
+
rubocop (0.49.1)
|
70
|
+
parallel (~> 1.10)
|
71
|
+
parser (>= 2.3.3.1, < 3.0)
|
41
72
|
powerpack (~> 0.1)
|
42
73
|
rainbow (>= 1.99.1, < 3.0)
|
43
|
-
ruby-progressbar (~> 1.
|
44
|
-
|
74
|
+
ruby-progressbar (~> 1.7)
|
75
|
+
unicode-display_width (~> 1.0, >= 1.0.1)
|
76
|
+
ruby-progressbar (1.8.1)
|
45
77
|
safe_yaml (1.0.4)
|
78
|
+
sawyer (0.8.1)
|
79
|
+
addressable (>= 2.3.5, < 2.6)
|
80
|
+
faraday (~> 0.8, < 1.0)
|
46
81
|
simplecov (0.9.2)
|
47
82
|
docile (~> 1.1.0)
|
48
83
|
multi_json (~> 1.0)
|
49
84
|
simplecov-html (~> 0.9.0)
|
50
85
|
simplecov-html (0.9.0)
|
86
|
+
slop (3.6.0)
|
87
|
+
thread_safe (0.3.6)
|
88
|
+
tzinfo (1.2.3)
|
89
|
+
thread_safe (~> 0.1)
|
90
|
+
unicode-display_width (1.3.0)
|
51
91
|
vcr (2.9.3)
|
52
92
|
webmock (1.20.4)
|
53
93
|
addressable (>= 2.3.6)
|
@@ -59,7 +99,9 @@ PLATFORMS
|
|
59
99
|
DEPENDENCIES
|
60
100
|
bundler (~> 1.3)
|
61
101
|
codeclimate-test-reporter (~> 0.4.6)
|
102
|
+
github_changelog_generator
|
62
103
|
nexpose!
|
104
|
+
pry (= 0.9.12.6)
|
63
105
|
rake
|
64
106
|
rspec (~> 3.2)
|
65
107
|
rubocop
|
data/README.markdown
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
This is the official gem package for the Ruby Nexpose API client library.
|
5
5
|
|
6
|
-
For assistance with using the gem
|
6
|
+
For assistance with using the gem or to discuss different approaches, please open an issue. To share or discuss scripts which use the gem head over to the [Nexpose Resources](https://github.com/rapid7/nexpose-resources) project.
|
7
7
|
|
8
8
|
Check out the [wiki](https://github.com/rapid7/nexpose-client/wiki) for walk-throughs and other documentation. Submit bugs and feature requests on the [issues](https://github.com/rapid7/nexpose-client/issues) page.
|
9
9
|
|
@@ -25,6 +25,8 @@ Our coding standards include:
|
|
25
25
|
* Unless otherwise noted, code should adhere to the Ruby Style Guide: https://github.com/bbatsov/ruby-style-guide
|
26
26
|
* Use YARDoc comment style to improve the API documentation of the gem.
|
27
27
|
|
28
|
+
Full usage examples or task-oriented scripts should be submitted to the [Nexpose Resources](https://github.com/rapid7/nexpose-resources) project. Smaller examples can be added to the [wiki](https://github.com/rapid7/nexpose-client/wiki).
|
29
|
+
|
28
30
|
## License
|
29
31
|
|
30
32
|
The nexpose-client gem is provided under the 3-Clause BSD License. See [COPYING](COPYING) for details.
|
data/Rakefile
CHANGED
@@ -4,3 +4,12 @@ require 'bundler/gem_tasks'
|
|
4
4
|
task :clean do
|
5
5
|
system "rm *.gem &> /dev/null"
|
6
6
|
end
|
7
|
+
|
8
|
+
|
9
|
+
require 'github_changelog_generator/task'
|
10
|
+
GitHubChangelogGenerator::RakeTask.new :changelog do |config|
|
11
|
+
token = ENV['CHANGELOG_GITHUB_TOKEN']
|
12
|
+
if token.nil?
|
13
|
+
warn "!!WARNING!! Missing Github Token Environment Variable. Fix before you run rake changelog. !!WARNING!!"
|
14
|
+
end
|
15
|
+
end
|
data/lib/nexpose.rb
CHANGED
data/lib/nexpose/ajax.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
|
2
3
|
module Nexpose
|
3
4
|
# Accessor to the Nexpose AJAX API.
|
4
5
|
# These core methods should allow direct access to underlying controllers
|
@@ -133,7 +134,8 @@ module Nexpose
|
|
133
134
|
# Use the Nexpose::Connection to establish a correct HTTPS object.
|
134
135
|
def https(nsc, timeout = nil)
|
135
136
|
http = Net::HTTP.new(nsc.host, nsc.port)
|
136
|
-
http.read_timeout = timeout
|
137
|
+
http.read_timeout = (timeout || nsc.timeout)
|
138
|
+
http.open_timeout = nsc.open_timeout
|
137
139
|
http.use_ssl = true
|
138
140
|
if nsc.trust_store.nil?
|
139
141
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
@@ -183,8 +185,8 @@ module Nexpose
|
|
183
185
|
def get_request_api_version(request)
|
184
186
|
matches = request.path.match(API_PATTERN)
|
185
187
|
matches[:version].to_f
|
186
|
-
|
187
|
-
|
188
|
+
rescue
|
189
|
+
0.0
|
188
190
|
end
|
189
191
|
|
190
192
|
# Get an error message from the response body if the request url api version
|
@@ -192,7 +194,7 @@ module Nexpose
|
|
192
194
|
def get_error_message(request, response)
|
193
195
|
version = get_request_api_version(request)
|
194
196
|
data_request = use_response_error_message?(request, response)
|
195
|
-
return_response = (version >= 2.1 || data_request
|
197
|
+
return_response = (version >= 2.1 || data_request)
|
196
198
|
(return_response && response.body) ? "response body: #{response.body}" : "request body: #{request.body}"
|
197
199
|
end
|
198
200
|
|
@@ -202,7 +204,7 @@ module Nexpose
|
|
202
204
|
if (request.path.include?('/data/') && !response.content_type.nil?)
|
203
205
|
response.content_type.include? 'text/plain'
|
204
206
|
else
|
205
|
-
|
207
|
+
false
|
206
208
|
end
|
207
209
|
end
|
208
210
|
|
@@ -253,7 +255,7 @@ module Nexpose
|
|
253
255
|
pref_key = "#{pref}.rows"
|
254
256
|
resp = get(nsc, uri)
|
255
257
|
json = JSON.parse(resp)
|
256
|
-
if json.
|
258
|
+
if json.key?(pref_key)
|
257
259
|
rows = json[pref_key].to_i
|
258
260
|
rows > 0 ? rows : 10
|
259
261
|
else
|
data/lib/nexpose/api_request.rb
CHANGED
@@ -42,17 +42,16 @@ module Nexpose
|
|
42
42
|
else
|
43
43
|
@http.cert_store = @trust_store
|
44
44
|
end
|
45
|
-
@headers = {'Content-Type' => 'text/xml'}
|
45
|
+
@headers = { 'Content-Type' => 'text/xml' }
|
46
46
|
@success = false
|
47
47
|
end
|
48
48
|
|
49
49
|
def execute(options = {})
|
50
50
|
@conn_tries = 0
|
51
|
-
|
52
51
|
begin
|
53
52
|
prepare_http_client
|
54
|
-
@http.read_timeout = options
|
55
|
-
@http.open_timeout = options.key?(:open_timeout) ? options[:open_timeout] :
|
53
|
+
@http.read_timeout = options.key?(:timeout) ? options[:timeout] : 120
|
54
|
+
@http.open_timeout = options.key?(:open_timeout) ? options[:open_timeout] : 120
|
56
55
|
@raw_response = @http.post(@uri.path, @req, @headers)
|
57
56
|
@raw_response_data = @raw_response.read_body
|
58
57
|
|
@@ -62,7 +61,7 @@ module Nexpose
|
|
62
61
|
@success = true
|
63
62
|
else
|
64
63
|
@success = false
|
65
|
-
@error =
|
64
|
+
@error = 'User requested raw XML response. Not parsing failures.'
|
66
65
|
end
|
67
66
|
else
|
68
67
|
@res = parse_xml(@raw_response_data)
|
@@ -74,19 +73,19 @@ module Nexpose
|
|
74
73
|
|
75
74
|
@sid = attributes['session-id']
|
76
75
|
|
77
|
-
if (attributes['success']
|
76
|
+
if (attributes['success'] && attributes['success'].to_i == 1)
|
78
77
|
@success = true
|
79
|
-
elsif @api_version =~ /1.2/
|
78
|
+
elsif @api_version =~ /1.2/ && @res && (@res.get_elements '//Exception').count < 1
|
80
79
|
@success = true
|
81
80
|
else
|
82
81
|
@success = false
|
83
82
|
if @api_version =~ /1.2/
|
84
83
|
@res.elements.each('//Exception/Message') do |message|
|
85
|
-
|
84
|
+
@error = message.text.sub(/.*Exception: */, '')
|
85
|
+
end
|
86
|
+
@res.elements.each('//Exception/Stacktrace') do |stacktrace|
|
87
|
+
@trace = stacktrace.text
|
86
88
|
end
|
87
|
-
@res.elements.each('//Exception/Stacktrace') do |stacktrace|
|
88
|
-
@trace = stacktrace.text
|
89
|
-
end
|
90
89
|
else
|
91
90
|
@res.elements.each('//message') do |message|
|
92
91
|
@error = message.text.sub(/.*Exception: */, '')
|
@@ -97,27 +96,29 @@ module Nexpose
|
|
97
96
|
end
|
98
97
|
end
|
99
98
|
end
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
rescue OpenSSL::SSL::SSLError =>
|
99
|
+
# This is a hack to handle corner cases where a heavily loaded Nexpose instance
|
100
|
+
# drops our HTTP connection before processing. We try 5 times to establish a
|
101
|
+
# connection in these situations. The actual exception occurs in the Ruby
|
102
|
+
# http library, which is why we use such generic error classes.
|
103
|
+
rescue OpenSSL::SSL::SSLError => error
|
105
104
|
if @conn_tries < 5
|
106
105
|
@conn_tries += 1
|
106
|
+
$stderr.puts "\n\nRetrying the request due to #{error}. If you see this message please open an Issue on Github with the error.\n\n"
|
107
107
|
retry
|
108
108
|
end
|
109
|
-
rescue ::ArgumentError, ::NoMethodError =>
|
109
|
+
rescue ::ArgumentError, ::NoMethodError => error
|
110
110
|
if @conn_tries < 5
|
111
111
|
@conn_tries += 1
|
112
|
+
$stderr.puts "\n\nRetrying the request due to #{error}. If you see this message please open an Issue on Github with the error.\n\n"
|
112
113
|
retry
|
113
114
|
end
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
@error = "Nexpose did not respond within #{@http.read_timeout} seconds."
|
115
|
+
### HTTP Specific Timeout Errors.
|
116
|
+
rescue ::Net::ReadTimeout, ::Net::OpenTimeout => error
|
117
|
+
timeout_value = error.instance_of?(Net::ReadTimeout) ? @http.read_timeout : @http.open_timeout
|
118
|
+
@error = "Nexpose did not respond within #{timeout_value} seconds #{error}. Reference the Wiki for information on setting the different Timeout values."
|
119
|
+
### Catch all Timeout Error.
|
120
|
+
rescue ::Timeout::Error => error
|
121
|
+
@error = "Nexpose did not respond within #{@http.read_timeout} seconds #{error}. Reference the Wiki for information on setting the different Timeout values."
|
121
122
|
rescue ::Errno::EHOSTUNREACH, ::Errno::ENETDOWN, ::Errno::ENETUNREACH, ::Errno::ENETRESET, ::Errno::EHOSTDOWN, ::Errno::EACCES, ::Errno::EINVAL, ::Errno::EADDRNOTAVAIL
|
122
123
|
@error = 'Nexpose host is unreachable.'
|
123
124
|
# Handle console-level interrupts
|
@@ -129,7 +130,7 @@ module Nexpose
|
|
129
130
|
@error = "Error parsing response: #{exc.message}"
|
130
131
|
end
|
131
132
|
|
132
|
-
if !(@success
|
133
|
+
if !(@success || @error)
|
133
134
|
@error = "Nexpose service returned an unrecognized response: #{@raw_response_data.inspect}"
|
134
135
|
end
|
135
136
|
|
@@ -137,7 +138,7 @@ module Nexpose
|
|
137
138
|
end
|
138
139
|
|
139
140
|
def attributes(*args)
|
140
|
-
return
|
141
|
+
return unless @res.root
|
141
142
|
@res.root.attributes(*args)
|
142
143
|
end
|
143
144
|
|
data/lib/nexpose/connection.rb
CHANGED
@@ -51,14 +51,20 @@ module Nexpose
|
|
51
51
|
attr_reader :url
|
52
52
|
# The token used to login to the NSC
|
53
53
|
attr_reader :token
|
54
|
-
|
55
54
|
# The last XML request sent by this object, useful for debugging.
|
56
55
|
attr_reader :request_xml
|
57
56
|
# The last XML response received by this object, useful for debugging.
|
58
57
|
attr_reader :response_xml
|
59
|
-
|
60
58
|
# The trust store to validate connections against if any
|
61
59
|
attr_reader :trust_store
|
60
|
+
# The main HTTP read_timeout value
|
61
|
+
# For more information visit the link below:
|
62
|
+
# https://ruby-doc.org/stdlib/libdoc/net/http/rdoc/Net/HTTP.html#read_timeout-attribute-method
|
63
|
+
attr_accessor :timeout
|
64
|
+
# The optional HTTP open_timeout value
|
65
|
+
# For more information visit the link below:
|
66
|
+
# http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/Net/HTTP.html#open_timeout-attribute-method
|
67
|
+
attr_accessor :open_timeout
|
62
68
|
|
63
69
|
# A constructor to load a Connection object from a URI
|
64
70
|
def self.from_uri(uri, user, pass, silo_id = nil, token = nil, trust_cert = nil)
|
@@ -76,23 +82,23 @@ module Nexpose
|
|
76
82
|
# @param [String] token The two-factor authentication (2FA) token for Nexpose sessions.
|
77
83
|
# @param [String] trust_cert The PEM-formatted web certificate of the Nexpose console. Used for SSL validation.
|
78
84
|
def initialize(ip, user, pass, port = 3780, silo_id = nil, token = nil, trust_cert = nil)
|
79
|
-
@host
|
80
|
-
@
|
81
|
-
@
|
82
|
-
@
|
83
|
-
@
|
84
|
-
@
|
85
|
-
unless trust_cert.nil?
|
86
|
-
|
87
|
-
|
88
|
-
@
|
89
|
-
@
|
85
|
+
@host = ip
|
86
|
+
@username = user
|
87
|
+
@password = pass
|
88
|
+
@port = port
|
89
|
+
@silo_id = silo_id
|
90
|
+
@token = token
|
91
|
+
@trust_store = create_trust_store(trust_cert) unless trust_cert.nil?
|
92
|
+
@session_id = nil
|
93
|
+
@url = "https://#{@host}:#{@port}/api/API_VERSION/xml"
|
94
|
+
@timeout = 120
|
95
|
+
@open_timeout = 120
|
90
96
|
end
|
91
97
|
|
92
98
|
# Establish a new connection and Session ID
|
93
99
|
def login
|
94
100
|
begin
|
95
|
-
login_hash = {'sync-id' => 0, 'password' => @password, 'user-id' => @username, 'token' => @token}
|
101
|
+
login_hash = { 'sync-id' => 0, 'password' => @password, 'user-id' => @username, 'token' => @token }
|
96
102
|
login_hash['silo-id'] = @silo_id if @silo_id
|
97
103
|
r = execute(make_xml('LoginRequest', login_hash))
|
98
104
|
if r.success
|
@@ -106,13 +112,15 @@ module Nexpose
|
|
106
112
|
|
107
113
|
# Logout of the current connection
|
108
114
|
def logout
|
109
|
-
r = execute(make_xml('LogoutRequest', {'sync-id' => 0}))
|
115
|
+
r = execute(make_xml('LogoutRequest', { 'sync-id' => 0 }))
|
110
116
|
return true if r.success
|
111
117
|
raise APIError.new(r, 'Logout failed')
|
112
118
|
end
|
113
119
|
|
114
120
|
# Execute an API request
|
115
121
|
def execute(xml, version = '1.1', options = {})
|
122
|
+
options.store(:timeout, @timeout) unless options.key?(:timeout)
|
123
|
+
options.store(:open_timeout, @open_timeout)
|
116
124
|
@request_xml = xml.to_s
|
117
125
|
@api_version = version
|
118
126
|
response = APIRequest.execute(@url, @request_xml, @api_version, options, @trust_store)
|
@@ -127,17 +135,17 @@ module Nexpose
|
|
127
135
|
# Would need to do something more sophisticated to grab
|
128
136
|
# all the associated image files.
|
129
137
|
def download(url, file_name = nil)
|
130
|
-
return nil if url.nil?
|
131
|
-
uri
|
132
|
-
http
|
138
|
+
return nil if (url.nil? || url.empty?)
|
139
|
+
uri = URI.parse(url)
|
140
|
+
http = Net::HTTP.new(@host, @port)
|
133
141
|
http.use_ssl = true
|
134
142
|
if @trust_store.nil?
|
135
143
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE # XXX: security issue
|
136
144
|
else
|
137
145
|
http.cert_store = @trust_store
|
138
146
|
end
|
139
|
-
headers = {'Cookie' => "nexposeCCSessionID=#{@session_id}"}
|
140
|
-
resp
|
147
|
+
headers = { 'Cookie' => "nexposeCCSessionID=#{@session_id}" }
|
148
|
+
resp = http.get(uri.to_s, headers)
|
141
149
|
|
142
150
|
if file_name
|
143
151
|
::File.open(file_name, 'wb') { |file| file.write(resp.body) }
|