wsdl2ruby and failing SSL certificate validation

When You are about to use Ruby to connect to some SOAP-like API You will probably use SOAP4r gem. First step would be to generate client code from WSDL provided by API. If it is served via HTTPS and server has SSL certificate not signed by some common CA (like self signed certs) You will experience following error running wsdl2ruby.rb:

at depth 0 - 20: unable to get local issuer certificate
F, [2011-01-18T10:13:40.816069 #4035] 
FATAL -- app: Detected an exception. Stopping ... 
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: 
certificate verify failed (OpenSSL::SSL::SSLError)

HTTPClient (this is gem used by SOAP4r to do all HTTP communication) tries to validate SSL certificates by default. Good, this is what SSL was thought for :) HTTPClient allows to use own CA (which is better solution than to lower security, especially on production :) ), however I don’t know how to pass this via SOPA4r abstraction (ssl-config.set-trust-ca('path') in HTTPClient (UPDATE – OK I think here You can find info how to specify CA, client key and cert in SOAP client). We can tell HTTPClient not to check SSL certs via options of SOAP::RPC::Driver when using client code:

d = SomeSOAP::ClientClass.new
d.options['protocol.http.ssl_config.verify_mode'] = OpenSSL::SSL::VERIFY_NONE

This may be not very wise, so use that if You know what You are doing.

And what about wsdl2ruby.rb

Above example relates to scenario when You have generated client code, which should connect to HTTPS. But how to recover from certificate verify failed when running wsdl2ruby.rb (in other words – when generating client code and WSDL is on HTTPS server with self signed cert)?

First solution is to download WSDL and generate client code from local file. Will do the trick unless WSDL imports some additional XSDs via HTTPS URL…

This gist gave me idea how to solve that (BTW – very useful trick to debug HTTP traffic if You can not use proxy like Charles Proxy). I did checked out SOAP4r gem code and updated wsdl2ruby.rb adding at begin:

BEGIN {
  require 'rubygems'
  require 'httpclient'
  HTTPClient.class_eval do
    alias_method '__initialize__', 'initialize'
    	    
    def initialize(*args,&block)
      __initialize__(*args, &block)
    ensure
      self.ssl_config.verify_mode=OpenSSL::SSL::VERIFY_NONE
    end
  end
}

That’s it. Well, almost. I was unlucky – due to some configuration twists WSDL and other referenced resources were hosted in some dev environment with wrong network configuration. Fixing that was totally out of my reach.

What was wrong? WSDL was accessible via HTTPS. All resources imported inside were referenced via HTTPS, too. But. When accessing these HTTPS URLs (other than WSDL) from outside network (where I was) plain HTTP error message was displayed, so SOAP code could not be generated. When URL was changed to HTTP – proper XML file was available.

So, another hack to wsdl2ruby.rb:

class  HTTPClient
    alias_method '__get_content__', 'get_content'
    def get_content(uri, query = nil, extheader = {}, &block)
     uri = URI.parse(uri.to_s.gsub(/^https:/,'http:'))
     if block_given?
       __get_content__(uri, query, extheader) {block}
     else
       __get_content__(uri, query, extheader)
     end
    end
end

Now all requests to HTTPS are converted to plain HTTP. Again – do it when You understand what You are doing :)

Where Ruby brought me

When I started this blog (Apr 2006) I’ve just have discovered Ruby on Rails. During this almost five years many things have changed. And finally Ruby brought me to this place:

Massimo and Arduino Logo at Maker Faire 2010 in NYC
Massimo and Arduino Logo at Maker Faire 2010 in NYC
CC by http://www.flickr.com/photos/mattrichardson/

And now small announcement. As You can see I was publishing on this blog very seldom in recent months. And reason is very simple. Almost two years ago I have started side business (do freelancer have side businesses? :)) ) selling Arduinos in Poland (and whole Europe). After slow start, it have took off, and between my work as freelancer and running shop there were no time to write on this blog.

Recently I have made decision to stop freelancing and devote all my time to Arduino (and electronics) related topics. Will I stop writing about Ruby? I guess not. Shop is on some hosted platform, but I do run some custom RoR software as backend. I plan to migrate at some point to own e-commerce solution, so I’m not leaving Ruby world.

Join the Conversation

1 Comment

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.