From cda29294a912521a72e28d773e6aa6845535616d Mon Sep 17 00:00:00 2001 From: Edouard CHIN Date: Fri, 4 Apr 2025 01:08:56 +0200 Subject: [PATCH] [rubygems/rubygems] Add the `bundle doctor subcommand` skeleton: - The command can either be run using: 1. `bundle doctor --ssl` 2. `bundle doctor ssl` The later is most useful when you need to specify custom ssl options (such as the verify mode or the TLS version when running the diagnostic). The implementation will follow in the next commits. https://github.com/rubygems/rubygems/commit/993d12874c --- lib/bundler/cli/doctor.rb | 13 ++++++++++++ lib/bundler/cli/doctor/diagnose.rb | 6 ++++++ lib/bundler/cli/doctor/ssl.rb | 32 ++++++++++++++++++++++++++++++ libexec/ssl_check.rb | 18 ----------------- spec/bundler/commands/ssl_spec.rb | 8 ++++++++ 5 files changed, 59 insertions(+), 18 deletions(-) create mode 100644 lib/bundler/cli/doctor/ssl.rb create mode 100644 spec/bundler/commands/ssl_spec.rb 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