Specify client certificate with Ruby Typhoeus

608 views Asked by At

I'm trying to use Typhoeus to make an HTTP request that requires a client certificate. The Typhoeus README does not mention using client certificates at all. The only discussion I could find about specifying a client certificate with Typhoeus is this GitHub issue discussion. Based on that discussion, this is the non-functioning code I've come up with (actual URL and filenames have been changed):

require 'openssl'
require 'typhoeus'

cert = OpenSSL::X509::Certificate.new(File.read("cert.pem"))
key = OpenSSL::PKey::RSA.new(File.read("cert-key.pem"))
ca = OpenSSL::X509::Certificate.new(File.read("cert-ca.pem"))

t = Typhoeus.get(
  "https://example.com/",
  ssl_verifyhost: 0,
  ssl_verifypeer: false,
  sslcert: cert,
  sslkey: key,
  cainfo: ca
)

p t.return_code

This returns :ssl_certproblem. The response body is empty and :response_code is 0.

I confirmed that my certificate files and URL are correct. This curl command returns the response body I expect:

curl --key cert-key.pem --cert cert.pem --cacert cert-ca.pem https://example.com

I got a request to complete using Faraday, however, I also need to make requests in parallel. Faraday's way of doing this is to use Typhoeus as an adapter, which still results in a client certificate error. It seems like as long as Typhoeus is involved, I'm not going to be able to authenticate with a client certificate and I don't know of another HTTP gem that can handle parallel requests for me. For now, I'm just going to have to settle for sending requests in series with Faraday, which makes the execution of my script a LOT slower. I'll probably end up rewriting the script in another language eventually.

This is how I made the request using Faraday:

require 'faraday'
require 'openssl'

ssl_opts = {
  :client_cert => OpenSSL::X509::Certificate.new(File.read("cert.pem")),
  :client_key => OpenSSL::PKey::RSA.new(File.read("cert-key.pem")),
  :ca_file => "cert-ca.pem"
}

f = Faraday.new(
  "https://example.com",
  :ssl => ssl_opts
).get

What is the correct way to use Typhoeus to make an HTTP request that requires a client certificate? I'm open to using alternatives to Typhoeus, though I will need the ability to make parallel requests.

1

There are 1 answers

0
Jaafar.Mehdi On

In the linked Github issue there was a hint that worked for me.

I skipped cainfo, but sslcert and sslkey needed to be plain strings of the paths to the files.

Something similar to this worked for me:

t = Typhoeus.get(
  "https://example.com/",
  ssl_verifyhost: 0,
  ssl_verifypeer: false,
  sslcert: "/path/to/project/cert.pem",
  sslkey: "/path/to/project/cert-key.pem"
)