Search code examples
rubysslopensslcertificatessl-certificate

How can i detect certificate issue programmatically in Ruby


I have cases that a few customers get an error while posting to our server (HTTPS). This is the error:

SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate)

I can use this method to detect what fails in the certificate chain:

openssl s_client -connect <url>:443 -CAfile <path/cacert.pem>

But, not all customers are willing to download and install openssl. So, I want to add this test using ruby code (we already have ruby installed on the customer's computer).


Solution

  • This ruby code should do the work:

    require 'openssl'
    require 'socket'
    
    CA_CERT = "<your-path-to-cert-file. e.g. cacert.pem>"
    
    def verify_host(host)
      puts "Connecting to: #{host} ..."
    
      ctx = OpenSSL::SSL::SSLContext.new(:TLSv1_2)
    
      ctx.ca_file = CA_CERT
      ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
      ctx.verify_callback = lambda do | preverify_ok, cert_store |
        cert = cert_store.current_cert
        puts "subject: #{cert.subject}, issuer: #{cert.issuer}, valid: #{preverify_ok}"
        preverify_ok
      end
    
      socket = TCPSocket.new host, 443
    
      ssl_socket = OpenSSL::SSL::SSLSocket.new socket, ctx
      ssl_socket.hostname = host
      puts "SSL Version: #{ssl_socket.ssl_version}"
    
      ssl_socket.connect
    
      ssl_socket.sysclose
      socket.close
    rescue => ex
      puts ex
    end
    

    Sample usage: verify_host('s3.amazonaws.com')

    Output:

    Connecting to: s3.amazonaws.com ...
    SSL Version: TLSv1.3
    subject: /C=IE/O=Baltimore/OU=CyberTrust/CN=Baltimore CyberTrust Root, issuer: /C=IE/O=Baltimore/OU=CyberTrust/CN=Baltimore CyberTrust Root, valid: true
    subject: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Baltimore CA-2 G2, issuer: /C=IE/O=Baltimore/OU=CyberTrust/CN=Baltimore CyberTrust Root, valid: true
    subject: /C=US/ST=Washington/L=Seattle/O=Amazon.com, Inc./CN=s3.amazonaws.com, issuer: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Baltimore CA-2 G2, valid: true