How to tell OpenSSL about new certificates for an outgoing API call using a Rails ssl_post?

644 Views Asked by At

FedEx recently updated their certificates for their API, which is causing a Rails ssl_post to their servers in the active_shipping module to throw the error The SSL connection to the remote server could not be established.

The application is Rails 5.0 & Ruby 2.3.1, served on AWS EC2 (Amazon Linux) via OpsWorks.

The new certificate files are more or less these:

  • gateway.fedex.com.pem (contains one certificate)
  • gateway-intermediate.pem (contains two certificates)
  • DigiCertGlobalRoot.pem (contains one certificate)

OpenSSL config:

  • openssl version returns OpenSSL 1.0.1k-fips 8 Jan 2015.
  • openssl version -d returns OPENSSLDIR: "/etc/pki/tls"

Inside /etc/pki/tls/ is cert.pem and a certs directory. I've tried both adding the certificates to cert.pem and adding them to the certs directory. I've also tried adding them to /etc/ssl/certs, and appending them to both /etc/ssl/certs/ca-bundle.crt and /etc/ssl/certs/ca-bundle.trust.crt. I've tried creating an SSL_CERT_DIR environment variable and then a SSL_CERT_FILE environment variable pointing to each of these locations.

So I have these new certificates; how do I tell OpenSSL about them? Where do I put them? I'm finding lots of documentation and advice about how to set up a certificate to secure the primary domain for web requests, but very little on how to configure a secondary certificate provided by a third-party. I feel like anyone using active_shipping and trying to access the FedEx API must be having this same problem, but I have yet to find anyone discussing it.

(As a bonus, FedEx reported they would be renewing their certificates on October 4, 2020, then renewed them a week early on 9/26, then went back and edited their announcement page on 9/28 to show the certificates would be renewed on 9/26.)

1

There are 1 best solutions below

0
campfire On

I finally got to the bottom of this.

ActiveShipping uses ActiveUtils to connect to third-party servers. ActiveUtils uses its own certfile.pem, which needs to be updated.

I followed the advice here, though I also had to add an override the CA_FILE for ActiveUtils, so to be explicit:

  1. Download the latest bundle from here: https://curl.haxx.se/docs/caextract.html
  2. Place the file somewhere in your project. I chose config/ssl/cacert.pem as in benjaminwood's example. I had to create the ssl directory, as it didn't exist.
  3. Create an initializer like the following:
# config/initializers/00_monkeypatch_updated_ca_cert.rb

module ActiveMerchant
  class Connection
    CA_FILE = Rails.root.join('config', 'ssl', 'cacert.pem').to_s
  end
end

module ActiveUtils
  class Connection
    CA_FILE = Rails.root.join('config', 'ssl', 'cacert.pem').to_s
  end
end

...and that got me up and running again.