summaryrefslogtreecommitdiff
path: root/spec/bundler/commands/ssl_spec.rb
blob: 1172bc9da785fa711ccaa5f3388f55a6a72095a2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# frozen_string_literal: true

require "bundler/cli"
require "bundler/cli/doctor"
require "bundler/cli/doctor/ssl"
require_relative "../support/artifice/helpers/artifice"
require "bundler/vendored_persistent.rb"

RSpec.describe "bundle doctor ssl" do
  before(:each) do
    require_rack
    require_relative "../support/artifice/helpers/endpoint"

    @dummy_endpoint = Class.new(Endpoint) do
      get "/" do
      end
    end

    @previous_level = Bundler.ui.level
    Bundler.ui.instance_variable_get(:@warning_history).clear
    @previous_client = Gem::Request::ConnectionPools.client
    Bundler.ui.level = "info"
    Artifice.activate_with(@dummy_endpoint)
    Gem::Request::ConnectionPools.client = Gem::Net::HTTP
  end

  after(:each) do
    Bundler.ui.level = @previous_level
    Artifice.deactivate
    Gem::Request::ConnectionPools.client = @previous_client
  end

  context "when a diagnostic fails" do
    it "prints the diagnostic when openssl can't be loaded" do
      subject = Bundler::CLI::Doctor::SSL.new({})
      allow(subject).to receive(:require).with("openssl").and_raise(LoadError)

      expected_err = <<~MSG
        Oh no! Your Ruby doesn't have OpenSSL, so it can't connect to rubygems.org.
        You'll need to recompile or reinstall Ruby with OpenSSL support and try again.
      MSG

      expect { subject.run }.to output("").to_stdout.and output(expected_err).to_stderr
    end

    it "fails due to certificate verification" do
      net_http = Class.new(Artifice::Net::HTTP) do
        def connect
          raise OpenSSL::SSL::SSLError, "certificate verify failed"
        end
      end

      Artifice.replace_net_http(net_http)
      Gem::Request::ConnectionPools.client = net_http
      Gem::RemoteFetcher.fetcher.close_all

      expected_out = <<~MSG
        Here's your OpenSSL environment:

        OpenSSL:       #{OpenSSL::VERSION}
        Compiled with: #{OpenSSL::OPENSSL_VERSION}
        Loaded with:   #{OpenSSL::OPENSSL_LIBRARY_VERSION}

        Trying connections to https://rubygems.org:
      MSG

      expected_err = <<~MSG
        Bundler:       failed     (certificate verification)
        RubyGems:      failed     (certificate verification)

      MSG

      subject = Bundler::CLI::Doctor::SSL.new({})
      expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr
    end

    it "fails due to a too old tls version" do
      subject = Bundler::CLI::Doctor::SSL.new({})

      net_http = Class.new(Artifice::Net::HTTP) do
        def connect
          raise OpenSSL::SSL::SSLError, "read server hello A"
        end
      end

      Artifice.replace_net_http(net_http)
      Gem::Request::ConnectionPools.client = Gem::Net::HTTP
      Gem::RemoteFetcher.fetcher.close_all

      expected_out = <<~MSG
        Here's your OpenSSL environment:

        OpenSSL:       #{OpenSSL::VERSION}
        Compiled with: #{OpenSSL::OPENSSL_VERSION}
        Loaded with:   #{OpenSSL::OPENSSL_LIBRARY_VERSION}

        Trying connections to https://rubygems.org:
      MSG

      expected_err = <<~MSG
        Bundler:       failed     (SSL/TLS protocol version mismatch)
        RubyGems:      failed     (SSL/TLS protocol version mismatch)

      MSG

      expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr
    end
  end

  context "when no diagnostic fails" do
    it "prints the SSL environment" do
      expected_out = <<~MSG
        Here's your OpenSSL environment:

        OpenSSL:       #{OpenSSL::VERSION}
        Compiled with: #{OpenSSL::OPENSSL_VERSION}
        Loaded with:   #{OpenSSL::OPENSSL_LIBRARY_VERSION}

        Trying connections to https://rubygems.org:
        Bundler:       success
        RubyGems:      success

      MSG

      subject = Bundler::CLI::Doctor::SSL.new({})
      expect { subject.run }.to output(expected_out).to_stdout.and output("").to_stderr
    end
  end
end