diff --git a/test/rubygems/test_gem_remote_fetcher.rb b/test/rubygems/test_gem_remote_fetcher.rb
index eeb548b8f7..ca858cfda5 100644
--- a/test/rubygems/test_gem_remote_fetcher.rb
+++ b/test/rubygems/test_gem_remote_fetcher.rb
@@ -2,105 +2,14 @@
require_relative "helper"
-require "webrick"
-require "webrick/https" if Gem::HAVE_OPENSSL
-
-unless Gem::HAVE_OPENSSL
- warn "Skipping Gem::RemoteFetcher tests. openssl not found."
-end
-
require "rubygems/remote_fetcher"
require "rubygems/package"
-# = Testing Proxy Settings
-#
-# These tests check the proper proxy server settings by running two
-# web servers. The web server at http://localhost:#{SERVER_PORT}
-# represents the normal gem server and returns a gemspec with a rake
-# version of 0.4.11. The web server at http://localhost:#{PROXY_PORT}
-# represents the proxy server and returns a different dataset where
-# rake has version 0.4.2. This allows us to detect which server is
-# returning the data.
-#
-# Note that the proxy server is not a *real* proxy server. But our
-# software doesn't really care, as long as we hit the proxy URL when a
-# proxy is configured.
-
class TestGemRemoteFetcher < Gem::TestCase
include Gem::DefaultUserInteraction
- SERVER_DATA = <<-EOY
---- !ruby/object:Gem::Cache
-gems:
- rake-0.4.11: !ruby/object:Gem::Specification
- rubygems_version: "0.7"
- specification_version: 1
- name: rake
- version: !ruby/object:Gem::Version
- version: 0.4.11
- date: 2004-11-12
- summary: Ruby based make-like utility.
- require_paths:
- - lib
- author: Jim Weirich
- email: jim@weirichhouse.org
- homepage: http://rake.rubyforge.org
- description: Rake is a Make-like program implemented in Ruby. Tasks and dependencies are specified in standard Ruby syntax.
- autorequire:
- bindir: bin
- has_rdoc: true
- required_ruby_version: !ruby/object:Gem::Version::Requirement
- requirements:
- -
- - ">"
- - !ruby/object:Gem::Version
- version: 0.0.0
- version:
- platform: ruby
- files:
- - README
- test_files: []
- library_stubs:
- rdoc_options:
- extra_rdoc_files:
- executables:
- - rake
- extensions: []
- requirements: []
- dependencies: []
- EOY
-
- PROXY_DATA = SERVER_DATA.gsub(/0.4.11/, "0.4.2")
-
- # Generated via:
- # x = OpenSSL::PKey::DH.new(2048) # wait a while...
- # x.to_s => pem
- TEST_KEY_DH2048 = OpenSSL::PKey::DH.new <<-_END_OF_PEM_
------BEGIN DH PARAMETERS-----
-MIIBCAKCAQEA3Ze2EHSfYkZLUn557torAmjBgPsqzbodaRaGZtgK1gEU+9nNJaFV
-G1JKhmGUiEDyIW7idsBpe4sX/Wqjnp48Lr8IeI/SlEzLdoGpf05iRYXC8Cm9o8aM
-cfmVgoSEAo9YLBpzoji2jHkO7Q5IPt4zxbTdlmmGFLc/GO9q7LGHhC+rcMcNTGsM
-49AnILNn49pq4Y72jSwdmvq4psHZwwFBbPwLdw6bLUDDCN90jfqvYt18muwUxDiN
-NP0fuvVAIB158VnQ0liHSwcl6+9vE1mL0Jo/qEXQxl0+UdKDjaGfTsn6HIrwTnmJ
-PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
------END DH PARAMETERS-----
- _END_OF_PEM_
-
def setup
- @proxies = %w[https_proxy http_proxy HTTP_PROXY http_proxy_user HTTP_PROXY_USER http_proxy_pass HTTP_PROXY_PASS no_proxy NO_PROXY]
- @old_proxies = @proxies.map {|k| ENV[k] }
- @proxies.each {|k| ENV[k] = nil }
-
super
- start_servers
- self.enable_yaml = true
- self.enable_zip = false
-
- base_server_uri = "http://localhost:#{normal_server_port}"
- @proxy_uri = "http://localhost:#{proxy_server_port}"
-
- @server_uri = base_server_uri + "/yaml"
- @server_z_uri = base_server_uri + "/yaml.Z"
@cache_dir = File.join @gemhome, "cache"
@@ -116,14 +25,6 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
@fetcher = Gem::RemoteFetcher.fetcher
end
- def teardown
- @fetcher.close_all
- stop_servers
- super
- Gem.configuration[:http_proxy] = nil
- @proxies.each_with_index {|k, i| ENV[k] = @old_proxies[i] }
- end
-
def test_self_fetcher
fetcher = Gem::RemoteFetcher.fetcher
refute_nil fetcher
@@ -140,6 +41,8 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
refute_nil fetcher
assert_kind_of Gem::RemoteFetcher, fetcher
assert_equal proxy_uri, fetcher.instance_variable_get(:@proxy).to_s
+ ensure
+ Gem.configuration[:http_proxy] = nil
end
def test_fetch_path_bad_uri
@@ -153,14 +56,6 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
assert_equal "uri scheme is invalid: nil", e.message
end
- def test_no_proxy
- use_ui @stub_ui do
- assert_data_from_server @fetcher.fetch_path(@server_uri)
- response = @fetcher.fetch_path(@server_uri, nil, true)
- assert_equal SERVER_DATA.size, response["content-length"].to_i
- end
- end
-
def test_cache_update_path
uri = Gem::URI "http://example/file"
path = File.join @tempdir, "file"
@@ -616,41 +511,6 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
assert_nil fetcher.fetch_path(Gem::URI.parse(@gem_repo), Time.at(0))
end
- def test_implicit_no_proxy
- use_ui @stub_ui do
- ENV["http_proxy"] = "http://fakeurl:12345"
- fetcher = Gem::RemoteFetcher.new :no_proxy
- @fetcher = fetcher
- assert_data_from_server fetcher.fetch_path(@server_uri)
- end
- end
-
- def test_implicit_proxy
- use_ui @stub_ui do
- ENV["http_proxy"] = @proxy_uri
- fetcher = Gem::RemoteFetcher.new nil
- @fetcher = fetcher
- assert_data_from_proxy fetcher.fetch_path(@server_uri)
- end
- end
-
- def test_implicit_upper_case_proxy
- use_ui @stub_ui do
- ENV["HTTP_PROXY"] = @proxy_uri
- fetcher = Gem::RemoteFetcher.new nil
- @fetcher = fetcher
- assert_data_from_proxy fetcher.fetch_path(@server_uri)
- end
- end
-
- def test_implicit_proxy_no_env
- use_ui @stub_ui do
- fetcher = Gem::RemoteFetcher.new nil
- @fetcher = fetcher
- assert_data_from_server fetcher.fetch_path(@server_uri)
- end
- end
-
def test_fetch_http
fetcher = Gem::RemoteFetcher.new nil
@fetcher = fetcher
@@ -712,34 +572,6 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
assert_equal "redirecting but no redirect location was given (#{url})", e.message
end
- def test_fetch_http_with_additional_headers
- ENV["http_proxy"] = @proxy_uri
- ENV["no_proxy"] = Gem::URI.parse(@server_uri).host
- fetcher = Gem::RemoteFetcher.new nil, nil, { "X-Captain" => "murphy" }
- @fetcher = fetcher
- assert_equal "murphy", fetcher.fetch_path(@server_uri)
- end
-
- def test_observe_no_proxy_env_single_host
- use_ui @stub_ui do
- ENV["http_proxy"] = @proxy_uri
- ENV["no_proxy"] = Gem::URI.parse(@server_uri).host
- fetcher = Gem::RemoteFetcher.new nil
- @fetcher = fetcher
- assert_data_from_server fetcher.fetch_path(@server_uri)
- end
- end
-
- def test_observe_no_proxy_env_list
- use_ui @stub_ui do
- ENV["http_proxy"] = @proxy_uri
- ENV["no_proxy"] = "fakeurl.com, #{Gem::URI.parse(@server_uri).host}"
- fetcher = Gem::RemoteFetcher.new nil
- @fetcher = fetcher
- assert_data_from_server fetcher.fetch_path(@server_uri)
- end
- end
-
def test_request_block
fetcher = Gem::RemoteFetcher.new nil
@fetcher = fetcher
@@ -754,112 +586,12 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
def test_yaml_error_on_size
use_ui @stub_ui do
- self.enable_yaml = false
fetcher = Gem::RemoteFetcher.new nil
@fetcher = fetcher
assert_error { fetcher.size }
end
end
- def test_ssl_connection
- ssl_server = start_ssl_server
- temp_ca_cert = File.join(__dir__, "ca_cert.pem")
- with_configured_fetcher(":ssl_ca_cert: #{temp_ca_cert}") do |fetcher|
- fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml")
- end
- end
-
- def test_ssl_client_cert_auth_connection
- ssl_server = start_ssl_server(
- { SSLVerifyClient: OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT }
- )
-
- temp_ca_cert = File.join(__dir__, "ca_cert.pem")
- temp_client_cert = File.join(__dir__, "client.pem")
-
- with_configured_fetcher(
- ":ssl_ca_cert: #{temp_ca_cert}\n" \
- ":ssl_client_cert: #{temp_client_cert}\n"
- ) do |fetcher|
- fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml")
- end
- end
-
- def test_do_not_allow_invalid_client_cert_auth_connection
- ssl_server = start_ssl_server(
- { SSLVerifyClient: OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT }
- )
-
- temp_ca_cert = File.join(__dir__, "ca_cert.pem")
- temp_client_cert = File.join(__dir__, "invalid_client.pem")
-
- with_configured_fetcher(
- ":ssl_ca_cert: #{temp_ca_cert}\n" \
- ":ssl_client_cert: #{temp_client_cert}\n"
- ) do |fetcher|
- assert_raise Gem::RemoteFetcher::FetchError do
- fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml")
- end
- end
- end
-
- def test_do_not_allow_insecure_ssl_connection_by_default
- ssl_server = start_ssl_server
- with_configured_fetcher do |fetcher|
- assert_raise Gem::RemoteFetcher::FetchError do
- fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml")
- end
- end
- end
-
- def test_ssl_connection_allow_verify_none
- ssl_server = start_ssl_server
- with_configured_fetcher(":ssl_verify_mode: 0") do |fetcher|
- fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml")
- end
- end
-
- def test_do_not_follow_insecure_redirect
- ssl_server = start_ssl_server
- temp_ca_cert = File.join(__dir__, "ca_cert.pem")
- expected_error_message =
- "redirecting to non-https resource: #{@server_uri} (https://localhost:#{ssl_server.config[:Port]}/insecure_redirect?to=#{@server_uri})"
-
- with_configured_fetcher(":ssl_ca_cert: #{temp_ca_cert}") do |fetcher|
- err = assert_raise Gem::RemoteFetcher::FetchError do
- fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/insecure_redirect?to=#{@server_uri}")
- end
-
- assert_equal(err.message, expected_error_message)
- end
- end
-
- def test_nil_ca_cert
- ssl_server = start_ssl_server
- temp_ca_cert = nil
-
- with_configured_fetcher(":ssl_ca_cert: #{temp_ca_cert}") do |fetcher|
- assert_raise Gem::RemoteFetcher::FetchError do
- fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}")
- end
- end
- end
-
- def with_configured_fetcher(config_str = nil, &block)
- if config_str
- temp_conf = File.join @tempdir, ".gemrc"
- File.open temp_conf, "w" do |fp|
- fp.puts config_str
- end
- Gem.configuration = Gem::ConfigFile.new %W[--config-file #{temp_conf}]
- end
- fetcher = Gem::RemoteFetcher.new
- yield fetcher
- ensure
- fetcher.close_all
- Gem.configuration = nil
- end
-
def assert_error(exception_class=Exception)
got_exception = false
@@ -871,152 +603,4 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
assert got_exception, "Expected exception conforming to #{exception_class}"
end
-
- def assert_data_from_server(data)
- assert_match(/0\.4\.11/, data, "Data is not from server")
- end
-
- def assert_data_from_proxy(data)
- assert_match(/0\.4\.2/, data, "Data is not from proxy")
- end
-
- class NilLog < WEBrick::Log
- def log(level, data) # Do nothing
- end
- end
-
- private
-
- attr_reader :normal_server, :proxy_server
- attr_accessor :enable_zip, :enable_yaml
-
- def start_servers
- @normal_server ||= start_server(SERVER_DATA)
- @proxy_server ||= start_server(PROXY_DATA)
- @enable_yaml = true
- @enable_zip = false
- @ssl_server = nil
- @ssl_server_thread = nil
- end
-
- def stop_servers
- if @normal_server
- @normal_server.kill.join
- @normal_server = nil
- end
- if @proxy_server
- @proxy_server.kill.join
- @proxy_server = nil
- end
- if @ssl_server
- @ssl_server.stop
- @ssl_server = nil
- end
- if @ssl_server_thread
- @ssl_server_thread.kill.join
- @ssl_server_thread = nil
- end
- WEBrick::Utils::TimeoutHandler.terminate
- end
-
- def normal_server_port
- @normal_server[:server].config[:Port]
- end
-
- def proxy_server_port
- @proxy_server[:server].config[:Port]
- end
-
- def start_ssl_server(config = {})
- pend "starting this test server fails randomly on jruby" if Gem.java_platform?
-
- null_logger = NilLog.new
- server = WEBrick::HTTPServer.new({
- Port: 0,
- Logger: null_logger,
- AccessLog: [],
- SSLEnable: true,
- SSLCACertificateFile: File.join(__dir__, "ca_cert.pem"),
- SSLCertificate: cert("ssl_cert.pem"),
- SSLPrivateKey: key("ssl_key.pem"),
- SSLVerifyClient: nil,
- SSLCertName: nil,
- }.merge(config))
- server.mount_proc("/yaml") do |_req, res|
- res.body = "--- true\n"
- end
- server.mount_proc("/insecure_redirect") do |req, res|
- res.set_redirect(WEBrick::HTTPStatus::MovedPermanently, req.query["to"])
- end
- server.ssl_context.tmp_dh_callback = proc { TEST_KEY_DH2048 }
- t = Thread.new do
- server.start
- rescue StandardError => ex
- puts "ERROR during server thread: #{ex.message}"
- raise
- ensure
- server.shutdown
- end
- while server.status != :Running
- sleep 0.1
- unless t.alive?
- t.join
- raise
- end
- end
- @ssl_server = server
- @ssl_server_thread = t
- server
- end
-
- def start_server(data)
- null_logger = NilLog.new
- s = WEBrick::HTTPServer.new(
- Port: 0,
- DocumentRoot: nil,
- Logger: null_logger,
- AccessLog: null_logger
- )
- s.mount_proc("/kill") {|_req, _res| s.shutdown }
- s.mount_proc("/yaml") do |req, res|
- if req["X-Captain"]
- res.body = req["X-Captain"]
- elsif @enable_yaml
- res.body = data
- res["Content-Type"] = "text/plain"
- res["content-length"] = data.size
- else
- res.status = "404"
- res.body = "
NOT FOUND
"
- res["Content-Type"] = "text/html"
- end
- end
- s.mount_proc("/yaml.Z") do |_req, res|
- if @enable_zip
- res.body = Zlib::Deflate.deflate(data)
- res["Content-Type"] = "text/plain"
- else
- res.status = "404"
- res.body = "NOT FOUND
"
- res["Content-Type"] = "text/html"
- end
- end
- th = Thread.new do
- s.start
- rescue StandardError => ex
- abort "ERROR during server thread: #{ex.message}"
- ensure
- s.shutdown
- end
- th[:server] = s
- th
- end
-
- def cert(filename)
- OpenSSL::X509::Certificate.new(File.read(File.join(__dir__, filename)))
- end
-
- def key(filename)
- OpenSSL::PKey::RSA.new(File.read(File.join(__dir__, filename)))
- end
-end if Gem::HAVE_OPENSSL
+end
diff --git a/test/rubygems/test_gem_remote_fetcher_local_server.rb b/test/rubygems/test_gem_remote_fetcher_local_server.rb
new file mode 100644
index 0000000000..a6bc626ede
--- /dev/null
+++ b/test/rubygems/test_gem_remote_fetcher_local_server.rb
@@ -0,0 +1,444 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+
+require "webrick"
+require "webrick/https" if Gem::HAVE_OPENSSL
+
+unless Gem::HAVE_OPENSSL
+ warn "Skipping Gem::RemoteFetcher tests. openssl not found."
+end
+
+require "rubygems/remote_fetcher"
+require "rubygems/package"
+
+# = Testing Proxy Settings
+#
+# These tests check the proper proxy server settings by running two
+# web servers. The web server at http://localhost:#{SERVER_PORT}
+# represents the normal gem server and returns a gemspec with a rake
+# version of 0.4.11. The web server at http://localhost:#{PROXY_PORT}
+# represents the proxy server and returns a different dataset where
+# rake has version 0.4.2. This allows us to detect which server is
+# returning the data.
+#
+# Note that the proxy server is not a *real* proxy server. But our
+# software doesn't really care, as long as we hit the proxy URL when a
+# proxy is configured.
+
+class TestGemRemoteFetcherLocalServer < Gem::TestCase
+ include Gem::DefaultUserInteraction
+
+ SERVER_DATA = <<-EOY
+--- !ruby/object:Gem::Cache
+gems:
+ rake-0.4.11: !ruby/object:Gem::Specification
+ rubygems_version: "0.7"
+ specification_version: 1
+ name: rake
+ version: !ruby/object:Gem::Version
+ version: 0.4.11
+ date: 2004-11-12
+ summary: Ruby based make-like utility.
+ require_paths:
+ - lib
+ author: Jim Weirich
+ email: jim@weirichhouse.org
+ homepage: http://rake.rubyforge.org
+ description: Rake is a Make-like program implemented in Ruby. Tasks and dependencies are specified in standard Ruby syntax.
+ autorequire:
+ bindir: bin
+ has_rdoc: true
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
+ requirements:
+ -
+ - ">"
+ - !ruby/object:Gem::Version
+ version: 0.0.0
+ version:
+ platform: ruby
+ files:
+ - README
+ test_files: []
+ library_stubs:
+ rdoc_options:
+ extra_rdoc_files:
+ executables:
+ - rake
+ extensions: []
+ requirements: []
+ dependencies: []
+ EOY
+
+ PROXY_DATA = SERVER_DATA.gsub(/0.4.11/, "0.4.2")
+
+ # Generated via:
+ # x = OpenSSL::PKey::DH.new(2048) # wait a while...
+ # x.to_s => pem
+ TEST_KEY_DH2048 = OpenSSL::PKey::DH.new <<-_END_OF_PEM_
+-----BEGIN DH PARAMETERS-----
+MIIBCAKCAQEA3Ze2EHSfYkZLUn557torAmjBgPsqzbodaRaGZtgK1gEU+9nNJaFV
+G1JKhmGUiEDyIW7idsBpe4sX/Wqjnp48Lr8IeI/SlEzLdoGpf05iRYXC8Cm9o8aM
+cfmVgoSEAo9YLBpzoji2jHkO7Q5IPt4zxbTdlmmGFLc/GO9q7LGHhC+rcMcNTGsM
+49AnILNn49pq4Y72jSwdmvq4psHZwwFBbPwLdw6bLUDDCN90jfqvYt18muwUxDiN
+NP0fuvVAIB158VnQ0liHSwcl6+9vE1mL0Jo/qEXQxl0+UdKDjaGfTsn6HIrwTnmJ
+PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
+-----END DH PARAMETERS-----
+ _END_OF_PEM_
+
+ def setup
+ @proxies = %w[https_proxy http_proxy HTTP_PROXY http_proxy_user HTTP_PROXY_USER http_proxy_pass HTTP_PROXY_PASS no_proxy NO_PROXY]
+ @old_proxies = @proxies.map {|k| ENV[k] }
+ @proxies.each {|k| ENV[k] = nil }
+
+ super
+ start_servers
+ self.enable_yaml = true
+ self.enable_zip = false
+
+ base_server_uri = "http://localhost:#{normal_server_port}"
+ @proxy_uri = "http://localhost:#{proxy_server_port}"
+
+ @server_uri = base_server_uri + "/yaml"
+ @server_z_uri = base_server_uri + "/yaml.Z"
+
+ @cache_dir = File.join @gemhome, "cache"
+
+ # TODO: why does the remote fetcher need it written to disk?
+ @a1, @a1_gem = util_gem "a", "1" do |s|
+ s.executables << "a_bin"
+ end
+
+ @a1.loaded_from = File.join(@gemhome, "specifications", @a1.full_name)
+
+ Gem::RemoteFetcher.fetcher = nil
+ @stub_ui = Gem::MockGemUi.new
+ @fetcher = Gem::RemoteFetcher.fetcher
+ end
+
+ def teardown
+ @fetcher.close_all
+ stop_servers
+ super
+ Gem.configuration[:http_proxy] = nil
+ @proxies.each_with_index {|k, i| ENV[k] = @old_proxies[i] }
+ end
+
+ def test_no_proxy
+ use_ui @stub_ui do
+ assert_data_from_server @fetcher.fetch_path(@server_uri)
+ response = @fetcher.fetch_path(@server_uri, nil, true)
+ assert_equal SERVER_DATA.size, response["content-length"].to_i
+ end
+ end
+
+ def test_implicit_no_proxy
+ use_ui @stub_ui do
+ ENV["http_proxy"] = "http://fakeurl:12345"
+ fetcher = Gem::RemoteFetcher.new :no_proxy
+ @fetcher = fetcher
+ assert_data_from_server fetcher.fetch_path(@server_uri)
+ end
+ end
+
+ def test_implicit_proxy
+ use_ui @stub_ui do
+ ENV["http_proxy"] = @proxy_uri
+ fetcher = Gem::RemoteFetcher.new nil
+ @fetcher = fetcher
+ assert_data_from_proxy fetcher.fetch_path(@server_uri)
+ end
+ end
+
+ def test_implicit_upper_case_proxy
+ use_ui @stub_ui do
+ ENV["HTTP_PROXY"] = @proxy_uri
+ fetcher = Gem::RemoteFetcher.new nil
+ @fetcher = fetcher
+ assert_data_from_proxy fetcher.fetch_path(@server_uri)
+ end
+ end
+
+ def test_implicit_proxy_no_env
+ use_ui @stub_ui do
+ fetcher = Gem::RemoteFetcher.new nil
+ @fetcher = fetcher
+ assert_data_from_server fetcher.fetch_path(@server_uri)
+ end
+ end
+
+ def test_fetch_http_with_additional_headers
+ ENV["http_proxy"] = @proxy_uri
+ ENV["no_proxy"] = Gem::URI.parse(@server_uri).host
+ fetcher = Gem::RemoteFetcher.new nil, nil, { "X-Captain" => "murphy" }
+ @fetcher = fetcher
+ assert_equal "murphy", fetcher.fetch_path(@server_uri)
+ end
+
+ def test_observe_no_proxy_env_single_host
+ use_ui @stub_ui do
+ ENV["http_proxy"] = @proxy_uri
+ ENV["no_proxy"] = Gem::URI.parse(@server_uri).host
+ fetcher = Gem::RemoteFetcher.new nil
+ @fetcher = fetcher
+ assert_data_from_server fetcher.fetch_path(@server_uri)
+ end
+ end
+
+ def test_observe_no_proxy_env_list
+ use_ui @stub_ui do
+ ENV["http_proxy"] = @proxy_uri
+ ENV["no_proxy"] = "fakeurl.com, #{Gem::URI.parse(@server_uri).host}"
+ fetcher = Gem::RemoteFetcher.new nil
+ @fetcher = fetcher
+ assert_data_from_server fetcher.fetch_path(@server_uri)
+ end
+ end
+
+ def test_ssl_connection
+ ssl_server = start_ssl_server
+ temp_ca_cert = File.join(__dir__, "ca_cert.pem")
+ with_configured_fetcher(":ssl_ca_cert: #{temp_ca_cert}") do |fetcher|
+ fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml")
+ end
+ end
+
+ def test_ssl_client_cert_auth_connection
+ ssl_server = start_ssl_server(
+ { SSLVerifyClient: OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT }
+ )
+
+ temp_ca_cert = File.join(__dir__, "ca_cert.pem")
+ temp_client_cert = File.join(__dir__, "client.pem")
+
+ with_configured_fetcher(
+ ":ssl_ca_cert: #{temp_ca_cert}\n" \
+ ":ssl_client_cert: #{temp_client_cert}\n"
+ ) do |fetcher|
+ fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml")
+ end
+ end
+
+ def test_do_not_allow_invalid_client_cert_auth_connection
+ ssl_server = start_ssl_server(
+ { SSLVerifyClient: OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT }
+ )
+
+ temp_ca_cert = File.join(__dir__, "ca_cert.pem")
+ temp_client_cert = File.join(__dir__, "invalid_client.pem")
+
+ with_configured_fetcher(
+ ":ssl_ca_cert: #{temp_ca_cert}\n" \
+ ":ssl_client_cert: #{temp_client_cert}\n"
+ ) do |fetcher|
+ assert_raise Gem::RemoteFetcher::FetchError do
+ fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml")
+ end
+ end
+ end
+
+ def test_do_not_allow_insecure_ssl_connection_by_default
+ ssl_server = start_ssl_server
+ with_configured_fetcher do |fetcher|
+ assert_raise Gem::RemoteFetcher::FetchError do
+ fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml")
+ end
+ end
+ end
+
+ def test_ssl_connection_allow_verify_none
+ ssl_server = start_ssl_server
+ with_configured_fetcher(":ssl_verify_mode: 0") do |fetcher|
+ fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml")
+ end
+ end
+
+ def test_do_not_follow_insecure_redirect
+ ssl_server = start_ssl_server
+ temp_ca_cert = File.join(__dir__, "ca_cert.pem")
+ expected_error_message =
+ "redirecting to non-https resource: #{@server_uri} (https://localhost:#{ssl_server.config[:Port]}/insecure_redirect?to=#{@server_uri})"
+
+ with_configured_fetcher(":ssl_ca_cert: #{temp_ca_cert}") do |fetcher|
+ err = assert_raise Gem::RemoteFetcher::FetchError do
+ fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/insecure_redirect?to=#{@server_uri}")
+ end
+
+ assert_equal(err.message, expected_error_message)
+ end
+ end
+
+ def test_nil_ca_cert
+ ssl_server = start_ssl_server
+ temp_ca_cert = nil
+
+ with_configured_fetcher(":ssl_ca_cert: #{temp_ca_cert}") do |fetcher|
+ assert_raise Gem::RemoteFetcher::FetchError do
+ fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}")
+ end
+ end
+ end
+
+ def with_configured_fetcher(config_str = nil, &block)
+ if config_str
+ temp_conf = File.join @tempdir, ".gemrc"
+ File.open temp_conf, "w" do |fp|
+ fp.puts config_str
+ end
+ Gem.configuration = Gem::ConfigFile.new %W[--config-file #{temp_conf}]
+ end
+ fetcher = Gem::RemoteFetcher.new
+ yield fetcher
+ ensure
+ fetcher.close_all
+ Gem.configuration = nil
+ end
+
+ def assert_data_from_server(data)
+ assert_match(/0\.4\.11/, data, "Data is not from server")
+ end
+
+ def assert_data_from_proxy(data)
+ assert_match(/0\.4\.2/, data, "Data is not from proxy")
+ end
+
+ class NilLog < WEBrick::Log
+ def log(level, data) # Do nothing
+ end
+ end
+
+ private
+
+ attr_reader :normal_server, :proxy_server
+ attr_accessor :enable_zip, :enable_yaml
+
+ def start_servers
+ @normal_server ||= start_server(SERVER_DATA)
+ @proxy_server ||= start_server(PROXY_DATA)
+ @enable_yaml = true
+ @enable_zip = false
+ @ssl_server = nil
+ @ssl_server_thread = nil
+ end
+
+ def stop_servers
+ if @normal_server
+ @normal_server.kill.join
+ @normal_server = nil
+ end
+ if @proxy_server
+ @proxy_server.kill.join
+ @proxy_server = nil
+ end
+ if @ssl_server
+ @ssl_server.stop
+ @ssl_server = nil
+ end
+ if @ssl_server_thread
+ @ssl_server_thread.kill.join
+ @ssl_server_thread = nil
+ end
+ WEBrick::Utils::TimeoutHandler.terminate
+ end
+
+ def normal_server_port
+ @normal_server[:server].config[:Port]
+ end
+
+ def proxy_server_port
+ @proxy_server[:server].config[:Port]
+ end
+
+ def start_ssl_server(config = {})
+ pend "starting this test server fails randomly on jruby" if Gem.java_platform?
+
+ null_logger = NilLog.new
+ server = WEBrick::HTTPServer.new({
+ Port: 0,
+ Logger: null_logger,
+ AccessLog: [],
+ SSLEnable: true,
+ SSLCACertificateFile: File.join(__dir__, "ca_cert.pem"),
+ SSLCertificate: cert("ssl_cert.pem"),
+ SSLPrivateKey: key("ssl_key.pem"),
+ SSLVerifyClient: nil,
+ SSLCertName: nil,
+ }.merge(config))
+ server.mount_proc("/yaml") do |_req, res|
+ res.body = "--- true\n"
+ end
+ server.mount_proc("/insecure_redirect") do |req, res|
+ res.set_redirect(WEBrick::HTTPStatus::MovedPermanently, req.query["to"])
+ end
+ server.ssl_context.tmp_dh_callback = proc { TEST_KEY_DH2048 }
+ t = Thread.new do
+ server.start
+ rescue StandardError => ex
+ puts "ERROR during server thread: #{ex.message}"
+ raise
+ ensure
+ server.shutdown
+ end
+ while server.status != :Running
+ sleep 0.1
+ unless t.alive?
+ t.join
+ raise
+ end
+ end
+ @ssl_server = server
+ @ssl_server_thread = t
+ server
+ end
+
+ def start_server(data)
+ null_logger = NilLog.new
+ s = WEBrick::HTTPServer.new(
+ Port: 0,
+ DocumentRoot: nil,
+ Logger: null_logger,
+ AccessLog: null_logger
+ )
+ s.mount_proc("/kill") {|_req, _res| s.shutdown }
+ s.mount_proc("/yaml") do |req, res|
+ if req["X-Captain"]
+ res.body = req["X-Captain"]
+ elsif @enable_yaml
+ res.body = data
+ res["Content-Type"] = "text/plain"
+ res["content-length"] = data.size
+ else
+ res.status = "404"
+ res.body = "NOT FOUND
"
+ res["Content-Type"] = "text/html"
+ end
+ end
+ s.mount_proc("/yaml.Z") do |_req, res|
+ if @enable_zip
+ res.body = Zlib::Deflate.deflate(data)
+ res["Content-Type"] = "text/plain"
+ else
+ res.status = "404"
+ res.body = "NOT FOUND
"
+ res["Content-Type"] = "text/html"
+ end
+ end
+ th = Thread.new do
+ s.start
+ rescue StandardError => ex
+ abort "ERROR during server thread: #{ex.message}"
+ ensure
+ s.shutdown
+ end
+ th[:server] = s
+ th
+ end
+
+ def cert(filename)
+ OpenSSL::X509::Certificate.new(File.read(File.join(__dir__, filename)))
+ end
+
+ def key(filename)
+ OpenSSL::PKey::RSA.new(File.read(File.join(__dir__, filename)))
+ end
+end if Gem::HAVE_OPENSSL