Ruby and SSL Certificate Validation

If your ruby app is doing SSL, you have probably seen one of the following errors:

doc = Hpricot(open("https://www.cert.org/blogs/vuls/rss.xml")) # => /usr/lib/ruby/1.8/net/http.rb:590:in `connect': certificate verify failed (OpenSSL::SSL::SSLError)

or

warning: peer certificate won't be verified in this SSL session

The solution is to make sure ruby has access to the right set of root certificates.

The easiest way to get hold of those root certificates is by downloading this file cacert.pem (details) (updated weekly by the developers of CURL, based on the Mozilla browser). Download this file and store it somewhere in your app.

If you’re really keen on security, don’t trust the guys from CURL and download the different root certificates from their providers manually. However, in most cases, the file from CURL will suffice.

Then, in your ruby code, setup the connection like this and you’ll have a validated SSL connection:

#! /usr/bin/env ruby
require 'net/https'
require 'uri'
 
uri = URI.parse(ARGV[0] || 'https://localhost/')
http = Net::HTTP.new(uri.host, uri.port)
if uri.scheme == "https"  # enable SSL/TLS
  http.use_ssl = true
  # Only needed for ruby 1.8.6
  # http.enable_post_connection_check = true
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER
  http.ca_file = File.join(File.dirname(__FILE__), "cacert.pem")
end
http.start {
  http.request_get(uri.path) {|res|
    print res.body
  }
}
Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • email
  • Hyves
  • Reddit
  • StumbleUpon
  • Twitter
This entry was posted in ruby and tagged , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

One Comment

  1. Posted December 4, 2009 at 15:54 | Permalink

    In a recent Rails 2.3.5 and Ruby 1.8.7 project, I monkey-patched Net:HTTP in environment.rb (maybe it can be moved to a separate initializer).

    I put the cacert.pem file in the config directory.

    class Net::HTTP
      alias_method :old_initialize, :initialize
      def initialize(*args)
        old_initialize(*args)
        @ssl_context = OpenSSL::SSL::SSLContext.new
        @ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
        @ssl_context.ca_file = File.join(RAILS_ROOT, 'config', 'cacert.pem')
      end
    end

    Whenever SSL is used, the cacert.pem file is loaded. Awesome!

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">