Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Client SSL in a Ruby on Rails App

I'm working on an app for a client that requires an SSL connection with an API. I've been provided with three files; a trust root certificate (.cer) file, an intermediate certificate (.cer) file and a signed response file. The instructions I've been given to install this relate to either IIS or the Java keytool program; I'm building the app in Ruby on Rails so neither is an option (as far as I am aware).

The certificates are self-signed by the organisation who runs the API service and it appears I get given client certificates to mutually authenticate an https connection. I'm unsure how to

  1. use the certificates in my application to connect and use the API
  2. what the signed response file does

I've read "Using a self-signed certificate" and this article on OpenSSL in Ruby but neither seems to quite hit the spot (and both have some reliance on Java/JRuby which confuses things).

Any pointers would be greatly appreciated.

like image 492
jkale Avatar asked Nov 02 '11 14:11

jkale


People also ask

How do I enable SSL client?

Log into the SSL VPN web interface. Go to the Manage System > ACCESS CONTROL > Security Settings page. In the Client Certificates section, configure the client certificates settings. Click Save Changes.


1 Answers

Based on your comments, I'm assuming that the certificates are in DER format, which you can convert to PEM with the openssl x509 command (see: openssl x509 command):

openssl x509 -inform DER -outform PEM -in certfile.cer -out certfile.pem

After that, you can instruct the Ruby OpenSSL library to use the trusted root certificate to authenticate the SSL connection with something like this:

require 'socket'
require 'openssl'

tcp_sock = TCPSocket.new("my.host.tld", 443)
ctx = OpenSSL::SSL::SSLContext.new
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
#You may need to specify the absolute path to the file
ctx.ca_file = "certfile.pem"

ssl_sock = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx)
ssl_sock.sync_close = true
ssl_sock.connect
begin
  ssl_sock.post_connection_check('my.host.tld')
rescue
  puts "Certificate host did not match expected hostname"
end

After that, you should be able to read and write to ssl_sock like any other Ruby IO object. If you are given a client certificate to use to allow the server to authenticate you, you can configure the SSL context with:

ctx.cert = OpenSSL::X509::Certificate.new(File.read("my_cert.pem"))
ctx.key = OpenSSL::PKey::RSA.new(File.read("my_key.rsa"))

before you create ssl_sock. The OpenSSL library also supports other key types besides RSA, such as DSA (see: OpenSSL::PKey module.)

Finally, a last piece of advice, if you are accessing a RESTful API, you may want to consider using a gem like rest-client instead of handling all of the HTTP/S connection stuff directly. Whether or not such a library is appropriate or useful will depend on the service you are using, of course.

like image 167
Ian Eccles Avatar answered Oct 13 '22 12:10

Ian Eccles