nexpose 6.1.1 → 7.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.
data/COPYING CHANGED
@@ -1,33 +1,29 @@
1
- Copyright (C) 2014, Rapid7, Inc.
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
- * Neither the name of Rapid7, Inc. nor the names of its contributors
15
- may be used to endorse or promote products derived from this software
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
- The copyright on this package is held by Rapid7, Inc.
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.
@@ -1,53 +1,93 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nexpose (6.1.1)
4
+ nexpose (7.0.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- addressable (2.3.7)
10
- ast (2.0.0)
11
- astrolabe (1.3.0)
12
- parser (>= 2.2.0.pre.3, < 3.0)
13
- codeclimate-test-reporter (0.4.7)
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
- crack (0.4.2)
19
+ coderay (1.1.1)
20
+ crack (0.4.3)
16
21
  safe_yaml (~> 1.0.0)
17
- diff-lcs (1.2.5)
22
+ diff-lcs (1.3)
18
23
  docile (1.1.5)
19
- multi_json (1.10.1)
20
- parser (2.2.0.3)
21
- ast (>= 1.1, < 3.0)
22
- powerpack (0.1.0)
23
- rainbow (2.0.0)
24
- rake (10.4.2)
25
- rspec (3.2.0)
26
- rspec-core (~> 3.2.0)
27
- rspec-expectations (~> 3.2.0)
28
- rspec-mocks (~> 3.2.0)
29
- rspec-core (3.2.1)
30
- rspec-support (~> 3.2.0)
31
- rspec-expectations (3.2.0)
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.2.0)
34
- rspec-mocks (3.2.1)
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.2.0)
37
- rspec-support (3.2.2)
38
- rubocop (0.29.1)
39
- astrolabe (~> 1.3)
40
- parser (>= 2.2.0.1, < 3.0)
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.4)
44
- ruby-progressbar (1.7.1)
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
@@ -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, to share your scripts, or to discuss different approaches, please visit the Rapid7 community: https://community.rapid7.com/
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
@@ -68,6 +68,7 @@ require 'nexpose/asset'
68
68
  require 'nexpose/blackout'
69
69
  require 'nexpose/common'
70
70
  require 'nexpose/console'
71
+ require 'nexpose/credential_helper'
71
72
  require 'nexpose/credential'
72
73
  require 'nexpose/site_credentials'
73
74
  require 'nexpose/shared_credential'
@@ -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 if 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
- rescue
187
- 0.0
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
- return false
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.has_key?(pref_key)
258
+ if json.key?(pref_key)
257
259
  rows = json[pref_key].to_i
258
260
  rows > 0 ? rows : 10
259
261
  else
@@ -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[:timeout] if options.key? :timeout
55
- @http.open_timeout = options.key?(:open_timeout) ? options[:open_timeout] : 60
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 = "User requested raw XML response. Not parsing failures."
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'] and attributes['success'].to_i == 1)
76
+ if (attributes['success'] && attributes['success'].to_i == 1)
78
77
  @success = true
79
- elsif @api_version =~ /1.2/ and @res and (@res.get_elements '//Exception').count < 1
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
- @error = message.text.sub(/.*Exception: */, '')
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
- # This is a hack to handle corner cases where a heavily loaded Nexpose instance
101
- # drops our HTTP connection before processing. We try 5 times to establish a
102
- # connection in these situations. The actual exception occurs in the Ruby
103
- # http library, which is why we use such generic error classes.
104
- rescue OpenSSL::SSL::SSLError => e
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 => e
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
- rescue ::Timeout::Error
115
- if @conn_tries < 5
116
- @conn_tries += 1
117
- # If an explicit timeout is set, don't retry.
118
- retry unless options.key? :timeout
119
- end
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 or @error)
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 if not @res.root
141
+ return unless @res.root
141
142
  @res.root.attributes(*args)
142
143
  end
143
144
 
@@ -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 = ip
80
- @port = port
81
- @username = user
82
- @password = pass
83
- @token = token
84
- @silo_id = silo_id
85
- unless trust_cert.nil?
86
- @trust_store = create_trust_store(trust_cert)
87
- end
88
- @session_id = nil
89
- @url = "https://#{@host}:#{@port}/api/API_VERSION/xml"
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? or url.empty?
131
- uri = URI.parse(url)
132
- http = Net::HTTP.new(@host, @port)
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 = http.get(uri.to_s, headers)
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) }