SSL Certificates and Net::HTTPS
I was getting tired of seeing "warning: peer certificate won't be verified in this SSL session" from Ruby's net/https library, so I started looking around for how to get it to actually verify the SSL certificate. I found lots of links on how to tell it not to bother verifying, but it wasn't until I found someone's Japanese blog that I found the clue I was looking for. Now, I don't know Japanese, but I can read Ruby. For the benefit of other English speakers/readers out there, I now present the solution.
First off, I'm giving a full example request using basic authentication (not that GMail uses basic authentication, but this is an example) because I was unable to find a good example elsewhere and made it this far by trial and error. The following will produce the warning I mentioned:
require 'net/http' require 'net/https' require 'uri' url = URI.parse 'https://myname:mypass@mail.google.com/' http = Net::HTTP.new(url.host, url.port) http.use_ssl = (url.scheme == 'https') request = Net::HTTP::Get.new(url.path) request.basic_auth url.user, url.password response = http.request(request)
To avoid the warning, we can either tell it not to warn us and blithely accept whatever certificate we receive, or we can give it enough information to authenticate the certificate against the root CA certificates. In the following example, we'll do both. If we find the file /usr/share/curl/curl-ca-bundle.crt then we will verify, otherwise we will silently ignore the issue:
require 'net/http' require 'net/https' require 'uri' RootCA = '/usr/share/curl/curl-ca-bundle.crt' url = URI.parse 'https://myname:mypass@mail.google.com/' http = Net::HTTP.new(url.host, url.port) http.use_ssl = (url.scheme == 'https') if File.exist? RootCA http.ca_file = RootCA http.verify_mode = OpenSSL::SSL::VERIFY_PEER http.verify_depth = 5 else http.verify_mode = OpenSSL::SSL::VERIFY_NONE end request = Net::HTTP::Get.new(url.path) request.basic_auth url.user, url.password response = http.request(request)
And there you have it. Not all that complicated, but poorly documented. Now it's more findably (i.e. Googleably) documented. Enjoy!
Update 2009-05-21: Thanks to a comment from Chewi, here's an even better approach:
require 'net/http' require 'net/https' require 'uri' RootCA = '/etc/ssl/certs' url = URI.parse 'https://myname:mypass@mail.google.com/' http = Net::HTTP.new(url.host, url.port) http.use_ssl = (url.scheme == 'https') if File.directory? RootCA http.ca_path = RootCA http.verify_mode = OpenSSL::SSL::VERIFY_PEER http.verify_depth = 5 else http.verify_mode = OpenSSL::SSL::VERIFY_NONE end request = Net::HTTP::Get.new(url.path) request.basic_auth url.user, url.password response = http.request(request)