summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThe Bundler Bot <bot@bundler.io>2017-08-28 19:16:06 +0000
committerThe Bundler Bot <bot@bundler.io>2017-08-28 19:16:06 +0000
commit6ce61e7c6060d1d7a45a131031be472aa25e1d7e (patch)
treee9b0bdff68a460c4c45c3c7d075c121f68897b68
parent766f412f338edb1502c62fb4cc2a6ae6678f55d4 (diff)
parentdbac58918e75f8e7df9875f7363985cd3a1fae01 (diff)
downloadbundler-6ce61e7c6060d1d7a45a131031be472aa25e1d7e.tar.gz
Auto merge of #5638 - bundler:seg-warn-old-tls, r=indirect
Warn when making an outdated TLS connection to rubygems.org Right now, output looks like ``` Your Ruby version does not support TLSv1.1 or newer, which will be required to connect to https://index.rubygems.org by June 2018. Fetching gem metadata from https://rubygems.org/........... Fetching version metadata from https://rubygems.org/.. Resolving dependencies... Using rake 11.3.0 Using automatiek 0.1.2 from source at `.` Using rspec-support 3.5.0 Using diff-lcs 1.3 Using bundler 1.15.0.pre.3 Using rspec-core 3.5.4 Using rspec-expectations 3.5.0 Using rspec-mocks 3.5.0 Using rspec 3.5.0 Bundle updated! ``` Obviously this requires tests, and also backing out forcing the TLS version (which I did to make testing easier). The message could also use improvement, but I figured I'd ask for input from @indirect and @dwradcliffe
-rw-r--r--lib/bundler/fetcher.rb4
-rw-r--r--lib/bundler/vendored_persistent.rb33
-rw-r--r--spec/bundler/vendored_persistent_spec.rb72
3 files changed, 107 insertions, 2 deletions
diff --git a/lib/bundler/fetcher.rb b/lib/bundler/fetcher.rb
index 5a9617c60a..03ff528826 100644
--- a/lib/bundler/fetcher.rb
+++ b/lib/bundler/fetcher.rb
@@ -238,7 +238,7 @@ module Bundler
Bundler.settings[:ssl_client_cert]
raise SSLError if needs_ssl && !defined?(OpenSSL::SSL)
- con = Bundler::Persistent::Net::HTTP::Persistent.new "bundler", :ENV
+ con = PersistentHTTP.new "bundler", :ENV
if gem_proxy = Bundler.rubygems.configuration[:http_proxy]
con.proxy = URI.parse(gem_proxy) if gem_proxy != :no_proxy
end
@@ -277,7 +277,7 @@ module Bundler
Timeout::Error, EOFError, SocketError, Errno::ENETDOWN, Errno::ENETUNREACH,
Errno::EINVAL, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EAGAIN,
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError,
- Bundler::Persistent::Net::HTTP::Persistent::Error, Zlib::BufError, Errno::EHOSTUNREACH
+ PersistentHTTP::Error, Zlib::BufError, Errno::EHOSTUNREACH
].freeze
def bundler_cert_store
diff --git a/lib/bundler/vendored_persistent.rb b/lib/bundler/vendored_persistent.rb
index ecbf21e30a..190fed58e5 100644
--- a/lib/bundler/vendored_persistent.rb
+++ b/lib/bundler/vendored_persistent.rb
@@ -16,3 +16,36 @@ module Bundler
end
end
require "bundler/vendor/net-http-persistent/lib/net/http/persistent"
+
+module Bundler
+ class PersistentHTTP < Persistent::Net::HTTP::Persistent
+ def connection_for(uri)
+ connection = super
+ warn_old_tls_version_rubygems_connection(uri, connection)
+ connection
+ end
+
+ def warn_old_tls_version_rubygems_connection(uri, connection)
+ return unless connection.use_ssl?
+ return unless (uri.host || "").end_with?("rubygems.org")
+
+ socket = connection.instance_variable_get(:@socket)
+ socket_io = socket.io
+ return unless socket_io.respond_to?(:ssl_version)
+ ssl_version = socket_io.ssl_version
+
+ case ssl_version
+ when /TLSv([\d\.]+)/
+ version = Gem::Version.new($1)
+ if version < Gem::Version.new("1.2")
+ Bundler.ui.warn \
+ "Warning: Your Ruby version is compiled against a copy of OpenSSL that is very old. " \
+ "Starting in January 2018, RubyGems.org will refuse connection requests from these " \
+ "very old versions of OpenSSL. If you will need to continue installing gems after " \
+ "January 2018, please follow this guide to upgrade: http://ruby.to/tls-outdated.",
+ :wrap => true
+ end
+ end
+ end
+ end
+end
diff --git a/spec/bundler/vendored_persistent_spec.rb b/spec/bundler/vendored_persistent_spec.rb
new file mode 100644
index 0000000000..b1b091f2c5
--- /dev/null
+++ b/spec/bundler/vendored_persistent_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+require "bundler/vendored_persistent"
+
+RSpec.describe Bundler::PersistentHTTP do
+ describe "#warn_old_tls_version_rubygems_connection" do
+ let(:uri) { "https://index.rubygems.org" }
+ let(:connection) { instance_double(subject.http_class) }
+ let(:tls_version) { "TLSv1.2" }
+ let(:socket) { double("Socket") }
+ let(:socket_io) { double("SocketIO") }
+
+ before do
+ allow(connection).to receive(:use_ssl?).and_return(!tls_version.nil?)
+ allow(socket).to receive(:io).and_return(socket_io)
+ connection.instance_variable_set(:@socket, socket)
+
+ if tls_version
+ allow(socket_io).to receive(:ssl_version).and_return(tls_version)
+ end
+ end
+
+ shared_examples_for "does not warn" do
+ it "does not warn" do
+ allow(Bundler.ui).to receive(:warn).never
+ subject.warn_old_tls_version_rubygems_connection(URI(uri), connection)
+ end
+ end
+
+ shared_examples_for "does warn" do |*expected|
+ it "warns" do
+ expect(Bundler.ui).to receive(:warn).with(*expected)
+ subject.warn_old_tls_version_rubygems_connection(URI(uri), connection)
+ end
+ end
+
+ context "an HTTPS uri with TLSv1.2" do
+ include_examples "does not warn"
+ end
+
+ context "without SSL" do
+ let(:tls_version) { nil }
+
+ include_examples "does not warn"
+ end
+
+ context "with a different TLD" do
+ let(:uri) { "https://foo.bar" }
+ include_examples "does not warn"
+
+ context "and an outdated TLS version" do
+ let(:tls_version) { "TLSv1" }
+ include_examples "does not warn"
+ end
+ end
+
+ context "with a nonsense TLS version" do
+ let(:tls_version) { "BlahBlah2.0Blah" }
+ include_examples "does not warn"
+ end
+
+ context "with an outdated TLS version" do
+ let(:tls_version) { "TLSv1" }
+ include_examples "does warn",
+ "Warning: Your Ruby version is compiled against a copy of OpenSSL that is very old. " \
+ "Starting in January 2018, RubyGems.org will refuse connection requests from these very old versions of OpenSSL. " \
+ "If you will need to continue installing gems after January 2018, please follow this guide to upgrade: http://ruby.to/tls-outdated.",
+ :wrap => true
+ end
+ end
+end