Skip to content

Commit

Permalink
Check ENV for ssl file & dir info, formatting
Browse files Browse the repository at this point in the history
1. Remove abort, as console output is sometimes scrambled in CI.

2. Only show OpenSSL cert location info if net/http failure, as it
   often contains user name.

3. Misc formatting re output width.
  • Loading branch information
MSP-Greg committed Jun 26, 2020
1 parent e7cc891 commit 1e84796
Showing 1 changed file with 69 additions and 46 deletions.
115 changes: 69 additions & 46 deletions check.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
begin
require 'openssl'
rescue LoadError
abort "Oh no! Your Ruby doesn't have OpenSSL, so it can't connect to #{host}. " \
"You'll need to recompile or reinstall Ruby with OpenSSL support and try again."
puts "Oh no! Your Ruby doesn't have OpenSSL, so it can't connect to #{host}.",
"You'll need to recompile or reinstall Ruby with OpenSSL support and try again."
exit 1
end

begin
Expand All @@ -32,7 +33,7 @@
end

uri = URI("https://#{host}")
ssl_version = ARGV.shift
tls_version = ARGV.shift
verify_mode = ARGV.any? ? OpenSSL::SSL.const_get(ARGV.shift) : OpenSSL::SSL::VERIFY_PEER

if defined?(RUBY_DESCRIPTION)
Expand All @@ -46,17 +47,34 @@

puts "", "Here's your Ruby and OpenSSL environment:"
puts
puts "Ruby: %s" % ruby_version
puts "RubyGems: %s" % Gem::VERSION if defined?(Gem::VERSION)
puts "Bundler: %s" % Bundler::VERSION if defined?(Bundler::VERSION)
puts "Compiled with: %s" % OpenSSL::OPENSSL_VERSION
puts "Loaded version: %s" % OpenSSL::OPENSSL_LIBRARY_VERSION if defined?(OpenSSL::OPENSSL_LIBRARY_VERSION)
puts "SSL_CERT_FILE: %s" % OpenSSL::X509::DEFAULT_CERT_FILE
puts "SSL_CERT_DIR: %s" % OpenSSL::X509::DEFAULT_CERT_DIR
puts
puts "With that out of the way, let's see if you can connect to #{host}..."
puts "Ruby: %s" % ruby_version
puts "RubyGems: %s" % Gem::VERSION if defined?(Gem::VERSION)
puts "Bundler: %s" % Bundler::VERSION if defined?(Bundler::VERSION)
puts "OpenSSL: %s" % OpenSSL::VERSION if defined?(OpenSSL::VERSION)
puts "Compiled with: %s" % OpenSSL::OPENSSL_VERSION
puts "Loaded with: %s" % OpenSSL::OPENSSL_LIBRARY_VERSION if defined?(OpenSSL::OPENSSL_LIBRARY_VERSION)
puts

def show_ssl_certs
puts "", "Below affect only Ruby net/http connections:"
puts
t = ENV['SSL_CERT_FILE'] || OpenSSL::X509::DEFAULT_CERT_FILE
ssl_file = if Dir.exist? t
"βœ… exists #{t}"
elsif RUBY_PLATFORM.end_with? 'linux'
t = '/etc/ssl/certs/ca-certificates.crt'
Dir.exist?(t) ? "βœ… exists #{t}" : "❌ is missing #{t}"
else
"❌ is missing #{t}"
end
puts "SSL_CERT_FILE: %s" % ssl_file

t = ENV['SSL_CERT_DIR'] || OpenSSL::X509::DEFAULT_CERT_DIR
ssl_dir = Dir.exist?(t) ? "βœ… exists #{t}" : "❌ is missing #{t}"
puts "SSL_CERT_DIR: %s" % ssl_dir
puts
end

def error_reason(error)
case error.message
when /certificate verify failed/
Expand All @@ -70,80 +88,86 @@ def error_reason(error)
end
end

puts "Trying connections to #{uri.to_s}:"
puts
begin
b_uri = defined?(Bundler::URI) ? Bundler::URI(uri.to_s) : uri
Bundler::Fetcher.new(Bundler::Source::Rubygems::Remote.new(b_uri)).send(:connection).request(b_uri)
bundler_status = "success βœ…"
bundler_status = "βœ… success"
rescue => error
bundler_status = "failed ❌ (#{error_reason(error)})"
bundler_status = "❌ failed (#{error_reason(error)})"
end
puts "Bundler connection to #{host}: #{bundler_status}"
puts "Bundler: #{bundler_status}"

begin
require 'rubygems/remote_fetcher'
Gem::RemoteFetcher.fetcher.fetch_path(uri)
rubygems_status = "success βœ…"
rubygems_status = "βœ… success"
rescue => error
rubygems_status = "failed ❌ (#{error_reason(error)})"
rubygems_status = "❌ failed (#{error_reason(error)})"
end
puts "RubyGems connection to #{host}: #{rubygems_status}"
puts "RubyGems: #{rubygems_status}"

begin
# Try to connect using HTTPS
Net::HTTP.new(uri.host, uri.port).tap do |http|
http.use_ssl = true
if ssl_version
if tls_version
if http.respond_to? :min_version=
vers = ssl_version.sub("v", "").to_sym
vers = tls_version.sub("v", "").to_sym
http.min_version = vers
http.max_version = vers
else
http.ssl_version = ssl_version.to_sym
http.ssl_version = tls_version.to_sym
end
end
http.verify_mode = verify_mode
end.start

puts "Ruby net/http connection to #{host}: success βœ…"
puts "Ruby net/http: βœ… success"
puts
rescue => error
puts "Ruby net/http connection to #{host}: failed ❌"
puts "Ruby net/http: ❌ failed"
puts
puts "Unfortunately, this Ruby can't connect to #{host}. 😑"

case error.message
# Check for certificate errors
when /certificate verify failed/
abort "Your Ruby can't connect to #{host} because you are missing the certificate\n" \
"files OpenSSL needs to verify you are connecting to the genuine #{host} servers."
show_ssl_certs
puts "\nYour Ruby can't connect to #{host} because you are missing the certificate",
"files OpenSSL needs to verify you are connecting to the genuine #{host} servers.", ""
# Check for TLS version errors
when /read server hello A/, /tlsv1 alert protocol version/
if ssl_version == "TLSv1_3"
abort "Your Ruby can't connect to #{host} because #{ssl_version} isn't supported yet."
if tls_version == "TLSv1_3"
puts "\nYour Ruby can't connect to #{host} because #{tls_version} isn't supported yet.\n\n"
else
abort "Your Ruby can't connect to #{host} because your version of OpenSSL is too old.\n" \
"You'll need to upgrade your OpenSSL install and/or recompile Ruby to use a newer OpenSSL."
puts "\nYour Ruby can't connect to #{host} because your version of OpenSSL is too old.",
"You'll need to upgrade your OpenSSL install and/or recompile Ruby to use a newer OpenSSL.", ""
end
# OpenSSL doesn't support TLS version specified by argument
when /unknown SSL method/
puts "\nYour Ruby can't connect because #{tls_version} isn't supported by your version of OpenSSL.\n\n"
else
puts "Even worse, we're not sure why. πŸ˜•"
puts "\nEven worse, we're not sure why. πŸ˜•"
puts
puts "Here's the full error information:"
puts "#{error.class}: #{error.message}"
puts " " << error.backtrace.join("\n ")
puts "Here's the full error information:",
"#{error.class}: #{error.message}",
" #{error.backtrace.join("\n ")}"
puts
puts "You might have more luck using Mislav's SSL doctor.rb script. You can get it here:"
puts "https://github.com/mislav/ssl-tools/blob/8b3dec4/doctor.rb"
puts "Read more about the script and how to use it in this blog post:"
puts "https://mislav.net/2013/07/ruby-openssl/"
abort
puts "You might have more luck using Mislav's SSL doctor.rb script. You can get it here:",
"https://github.com/mislav/ssl-tools/blob/8b3dec4/doctor.rb",
"Read more about the script and how to use it in this blog post:",
"https://mislav.net/2013/07/ruby-openssl/", ""
end
exit 1
end

guide_url = "http://ruby.to/ssl-check-failed"
if bundler_status =~ /success/ && rubygems_status =~ /success/
# Whoa, it seems like it's working!
puts "Hooray! This Ruby can connect to #{host}.",
"You are all set to use Bundler and RubyGems. πŸ‘Œ", ""
"You are all set to use Bundler and RubyGems. πŸ‘Œ", ""
elsif rubygems_status !~ /success/
puts "It looks like Ruby and Bundler can connect to #{host}, but RubyGems itself",
"cannot. You can likely solve this by manually downloading and installing a",
Expand All @@ -156,9 +180,9 @@ def error_reason(error)
"check out the troubleshooting guide at #{guide_url} πŸ“¦"
else
puts "For some reason, your Ruby installation can connect to #{host}, but neither",
"RubyGems nor Bundler can. The most likely fix is to manually upgrade RubyGems by",
"following the instructions at #{guide_url}. After you've done that, run `gem install",
"bundler` to upgrade Bundler, and then run this script again to make sure everything worked. ❣️"
"RubyGems nor Bundler can. The most likely fix is to manually upgrade RubyGems by",
"following the instructions at #{guide_url}. After you've done that, run `gem install",
"bundler` to upgrade Bundler, and then run this script again to make sure everything worked. ❣️"
end

def tls12_supported?
Expand All @@ -174,10 +198,9 @@ def tls12_supported?

# We were able to connect, but perhaps this Ruby will have trouble when we require TLSv1.2
unless tls12_supported?
puts
puts "WARNING: Although your Ruby can connect to #{host} today, your OpenSSL is very old! πŸ‘΄"
puts "WARNING: You will need to upgrade OpenSSL to use #{host}."
abort
puts "\nWARNING: Although your Ruby can connect to #{host} today, your OpenSSL is very old! πŸ‘΄",
"WARNING: You will need to upgrade OpenSSL to use #{host}."
exit 1
end

exit 0

0 comments on commit 1e84796

Please sign in to comment.