Using Client SSL in a Ruby on Rails App

2019-04-08 05:56发布

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.

1条回答
戒情不戒烟
2楼-- · 2019-04-08 06:40

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.

查看更多
登录 后发表回答