diff --git a/lib/bundler/cli/doctor.rb b/lib/bundler/cli/doctor.rb index 21437fc89f..5fd6a73d91 100644 --- a/lib/bundler/cli/doctor.rb +++ b/lib/bundler/cli/doctor.rb @@ -12,9 +12,22 @@ module Bundler D method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile" method_option "quiet", type: :boolean, banner: "Only output warnings and errors." + method_option "ssl", type: :boolean, default: false, banner: "Diagnose SSL problems." def diagnose require_relative "doctor/diagnose" Diagnose.new(options).run end + + desc "ssl [OPTIONS]", "Diagnose SSL problems" + long_desc <<-D + Diagnose SSL problems, especially related to certificates or TLS version while connecting to https://rubygems.org. + D + method_option "host", type: :string, banner: "The host to diagnose." + method_option "tls-version", type: :string, banner: "Specify the SSL/TLS version when running the diagnostic. Accepts either <1.1> or <1.2>" + method_option "verify-mode", type: :string, banner: "Specify the mode used for certification verification. Accepts either or " + def ssl + require_relative "doctor/ssl" + SSL.new(options).run + end end end diff --git a/lib/bundler/cli/doctor/diagnose.rb b/lib/bundler/cli/doctor/diagnose.rb index c32a1b5369..c5da23acb8 100644 --- a/lib/bundler/cli/doctor/diagnose.rb +++ b/lib/bundler/cli/doctor/diagnose.rb @@ -69,10 +69,16 @@ module Bundler Bundler::CLI::Check.new({}).run end + def diagnose_ssl + require_relative "ssl" + Bundler::CLI::Doctor::SSL.new({}).run + end + def run Bundler.ui.level = "warn" if options[:quiet] Bundler.settings.validate! check! + diagnose_ssl if options[:ssl] definition = Bundler.definition broken_links = {} diff --git a/lib/bundler/cli/doctor/ssl.rb b/lib/bundler/cli/doctor/ssl.rb new file mode 100644 index 0000000000..ecc5cb00bb --- /dev/null +++ b/lib/bundler/cli/doctor/ssl.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module Bundler + class CLI::Doctor::SSL + attr_reader :options + + def initialize(options) + @options = options + end + + def run + end + + private + + def host + @options[:host] || "rubygems.org" + end + + def tls_version + @options[:"tls-version"].then do |version| + "TLS#{version.sub(".", "_")}".to_sym if version + end + end + + def verify_mode + mode = @options[:"verify-mode"] || :peer + + @verify_mode ||= mode.then {|mod| OpenSSL::SSL.const_get("verify_#{mod}".upcase) } + end + end +end diff --git a/libexec/ssl_check.rb b/libexec/ssl_check.rb index 09dbede5e4..de761e0ab3 100644 --- a/libexec/ssl_check.rb +++ b/libexec/ssl_check.rb @@ -1,22 +1,6 @@ #!/usr/bin/env ruby # Encoding: utf-8 -if RUBY_VERSION < "2.7" - warn "!!! WARNING !!!", - "Ruby #{RUBY_VERSION} has reached end-of-life, and is unsupported.", - "This script may not work.", - "" -end - -if ARGV.include?("-h") || ARGV.include?("--help") - puts "USAGE: check.rb [HOSTNAME] [TLS_VERSION] [VERIFY]" - puts " default: check.rb rubygems.org auto VERIFY_PEER" - puts " example: check.rb github.com TLSv1_2 VERIFY_NONE" - exit 0 -end - -host = ARGV.shift || "rubygems.org" - require 'uri' require 'net/http' @@ -40,8 +24,6 @@ rescue LoadError end uri = URI("https://#{host}") -tls_version = ARGV.shift -verify_mode = ARGV.any? ? OpenSSL::SSL.const_get(ARGV.shift) : OpenSSL::SSL::VERIFY_PEER if defined?(RUBY_DESCRIPTION) ruby_version = RUBY_DESCRIPTION diff --git a/spec/bundler/commands/ssl_spec.rb b/spec/bundler/commands/ssl_spec.rb new file mode 100644 index 0000000000..78afa39814 --- /dev/null +++ b/spec/bundler/commands/ssl_spec.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +require "bundler/cli" +require "bundler/cli/doctor" +require "bundler/cli/doctor/ssl" + +RSpec.describe "bundle doctor ssl" do +end