10/07/2012

Ruby, SSL and Untrusted Certs

It has been a long time since focusing exclusively on writing Ruby code. So much fun.

The last two years have been groovy only which is a great language but there is something pure and simple about Ruby that just takes your breath away.

Enough of the emotional stuff, why, on earth, is it so hard to disable SSL cert trust verification. Such a common problem, google is full of Rails ActionMailer solutions but of coarse that doesn't help the rest of us.

Ruby 1.8.7

I approached the problem from Net:HTTP library makes it pretty easy. You just have to remember to require the correct classes and note that you are not disabling SSL just the trust verification part. # irb(main):001:0> require "net/https" # => true # irb(main):020:0> h = Net::HTTP.new("YOUR_SSL_SERVER",443) # => #<Net::HTTP YOUR_SSL_SERVER:443 open=false> # irb(main):021:0> h.use_ssl = true # => true # irb(main):022:0> h.verify_mode = OpenSSL::SSL::VERIFY_NONE # => 0 # irb(main):023:0> h.get("/") # => #<Net::HTTPOK 200 OK readbody=true>

My actual goal was to access a WSDL, over SSL, with an untrusted cert. This was not so easy. Took me about 5 hours to work out this solution. Expensive.

I used the Soap4R gem and since performance is not an issue I figured the dynamic proxy from the WSDL parsing would be the way to go:

factory = SOAP::WSDLDriverFactory.new("#{@url}?WSDL")

The problem was that there is no simple API to set the verify_mode of the connection so you have to root around in the code until you find where to monkey patch. This is what I came up with.

# # Monkey Patch HTTP Client # Sets SSL verify mode to NONE so that we can connect to an SSL server # that does not have a trusted certificate. # class HTTPAccess2::Client def initialize(*args) super(args[0], args[1]) @session_manager.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE end end

If someone has a cleaner solution I would love to hear it.

Ruby 1.9.3

Upgrading to 1.9.3 broke my Monkey Patch as expected so here is the updated one that handles both for the time being:

# # Monkey Patch HTTP Client # Sets SSL verify mode to NONE so that we can connect to an SSL server # that does not have a trusted certificate. # # The 1.8.7 patch adds a new constructor. # The 1.9.3 patch intercepts the existing constructor now that the class # name has changed. if RUBY_VERSION == "1.8.7" class HTTPAccess2::Client def initialize(*args) super(args[0], args[1]) @session_manager.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE #@session_manager.debug_dev = STDOUT end end else # > 1.8.7 class HTTPClient alias_method :original_initialize, :initialize def initialize(*args) original_initialize(args[0], args[1]) @session_manager.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE #@session_manager.debug_dev = STDOUT end end end