How to handle API calls to a server with self signed SSL certificate

Hello Guys,

Here is another post on a scenario some of you working with telcos, banks and other organizations are familiar with. There is a server somewhere which offers a service usually available over VPN, sometimes not, that you need to connect to. That server has a self signed certificate and you need to deal with that. To simulate this, we will use a server on AWS, an Elastic IP (static public IP) as our server node and an Ubuntu vagrant box as the client node.

I could have used 2 vagrant boxes but I am using a slightly different scenario just to show that the practice is not for private networks only.I have opted for one public box (server) and one local box (client).

We will sign the same certificate twice. One for a day (which I did yesterday) another one for 10. The idea is that by signing the first certificate for a day by now it should expire. So we will end up with an expired and valid self signed certificate.

We have generated our static IP and it’s going to be 52.70.113.80. That will be our servername on the certificate is also going to be same. We will destroy this one we are done so don’t go try to hit this, I have locked it down to my IP as well.

Signing Certificate

This is really not an article for how to self signed certificate but I guess a little memory refresh on how to do it won’t be bad. I am using an old CompanyACA.crt ROOT CA I have already used in this article. We will use it to sign our certificates.

Generating Certificate Signing Request (CSR)

With the command below we will generate the key file to use with our certificate.

Now let’s issue the CSR.

Once the CSR ready we will use our ROOT certificat to sign it for a day.

In the command above you will notice, I used a different serial number for the certificate. If I had kept it, browsers would have complained about it. The issue is that we will have same certificate signed by same Authority(ourselves) with 2 different validity days. To prevent that we need different serials for both for our browsers and components to be happy with.

Preparing Cetificate bundle for Nginx

This is also outside the purpose of the article, buuuuut for newbies I thought I would do some exception to show how to use the newly issued certificates on a server. A typical bundle certificate file used in nginx is of the following format:

Let’s create our bundle file. I will only show one but we need to to it for 2 created certificates. We don’t have any intermediate certificate so this will be actual certificate and its root CompanyACA.crt.

Setting up SSL on our server

After installing nginx on our ubuntu xenial box quickly with : sudo apt-get install nginx . We also installed php with sudo apt-get install php-fpm to simulate our server.We then changed the default configuration in /etc/nginx/sites-available/default file to look like the following

I am using a fake API build with php to take care of the call. So this is the file that is used on the server we will be calling from our vagrant box.

Using 10 days Certificates

Making call to API: CURL

Our server is ready to respond to some requests.

Using the certificates in curl call

Doing this, I have 3 types of certificates in the vagrant box:

  • CompanyACA.crt
  • 52.70.113.80_10days.crt
  • 52.70.113.80_10days_bundle.crt
Using Root certificate in the call: CompanyACA.crt

Using certificate without its root in the call: 52.70.113.80_10days.crt

Using certificate with its root in the call: 52.70.113.80_10days_bundle.crt

Making call to API: HTTPIE

In case this is new to you, you could have a look at httpie documentation.

Making call with httpie

Making httpie call with certificate without root

Making httpie call with certificate with root

Making httpie call with root certificate only

From this experience it looks like the ROOT certificate is the one needed for httpie.

Trusting the Certificate

To add the certificate to the trust store, we need to create a folder such as codingpains in /usr/share/ca-certificates/. We need to then copy the certificate to that folder and run the command dpkg-reconfigure ca-certificates.

Importing only 52.70.113.80_10days.crt

We imported the server certificate first and we will make calls with curl and httpie

Importing only 52.70.113.80_10days_bundle.crt
  • Curl call worked
  • httpie call failed for httpie installed via pip
  • httppie call worked for httpie installed via apt-get with warning

Importing CompanyACA.crt
  • Curl call worked
  • httpie call failed for httpie installed via pip
  • httppie call worked for httpie installed via apt-get with warning

Using 1 day, now expired Certificate

So to cut the long story short, all calls made to the server have failed because the certificate expired. Direct referencing of the ROOT CA and importing it into the OS trusted certificates stored all failed.

Diagnose with php

From the result above it’s clear that there is something wrong. With the php code below, let’s use php curl to understand why the request is being rejected.

This actually assumes you installed php-curl module.

Basically it doesn’t work because the certificate has expired. The only thing to do in this case is to get the server to update the certificate or choose not to verify it. That can be done with –insecure on curl and –verify-no with httpie.

By not verifying it, it doesn’t mean the call is over plain http. It simply mean you are telling your app/program not to go all out finding who signed the certificate, when it’s going to expired or whether the name on the certificate tallies with the IP or servername of the server serving it.

I hope this has been useful to someone consistently facing issues like this. And oh, if you are using java, java store is actually different as well. I am yet to try making a java app look up certificate in system trusted store.

Leave a Comment

Your email address will not be published. Required fields are marked *

captcha * Time limit is exhausted. Please reload the CAPTCHA.