Mutual SSL Between API Gateway and Backend

Shanaka Sandanayaka
6 min readJun 13, 2020

WSO2 API Manager is a leader in the open-source API Management platform. With one of my previous blogs, I have explained regarding one of the key capabilities of the API Manager. Securing API’s with the Mutual SSL. And now let us see how we can call an endpoint which is secured with the Mutual SSL. We have explained the Mutual SSL briefly in one of the previous blog. You are welcome to check that and get an idea of that.

For this, I will use 2 wso2 API Manager instances running in the same instance.

  1. Hosting the secured API with Mutual SSL (What we have created in previously).
  2. Hosting a new API which is calling the endpoint secured with Mutual SSL.
Flow

Setting up API Manager to call Mutual SSL endpoint

WSO2 API Manager used Pass-Through Transport for HTTP communication. You have to make several configuration changes in order to make WSO2 servers to negotiate a secure connection with mutual SSL. As you know, It is mainly required 3 things in this case.

  • A private key to generate a certificate for the client.
  • A Certificate for the client.
  • A public certificate of the back-end server.

There are two options for client-side certificate

  1. Use default keys shipped with product
  2. Use a brand new certificate for Mutual SSL

Use default keys shipped

WSO2 API Manager is packing a default certificate and the private key inside the wso2carbon.jks Keystore which is located in the <AM_HOME>/repository/resources/security/ folder. You can use that default keys as the client-side certificate and private key. Use the command below to extract the public certificate from that keystore.

Side Note : I have listed some useful OpenSSL and Keytool command here

keytool -exportcert -keystore wso2carbon.jks -alias wso2carbon -file wso2public-cert.crt

Use a brand new certificate for Mutual SSL

You can create a new private key and a certificate with following command.

openssl req -newkey rsa:2048 -nodes -keyout domain.key -x509 -days 365 -out domain.crt
Cert and Key genaration

Use following commands to pack those keys into a Java Keystore

openssl pkcs12 -export -out certificate-store.pfx -inkey domain.key -in domain.crr

This will create a pfx certificate store, Use the following command to convert it to JKS.

keytool -importkeystore -srckeystore certificate-store.pfx -destkeystore mutual-ssl.jks -srcstoretype pkcs12 -deststoretype JKS
Create JKS

Make Config changes in API Manager

Now you have to make the configuration changes to specifically mention the configurations for the endpoint. Add the configuration similar to following in the deployment.toml file.

[[keystore.ssl_profile.custom]]
servers = "localhost:8243"
keystore.location = "/Users/shana/Desktop/newKeys/mutual-ssl.jks"
keystore.type = "JKS"
keystore.password = "domain"
keystore.key_password = "domain"
truststore.location = "repository/resources/security/client-truststore.jks"
truststore.type = "JKS"
truststore.password = "wso2carbon"

servers : Specify the endpoint hostname

keystore.location : Location of the keystore contains the client side certificates

keystore.type : Type of the keystore.

keystore.password : Password of the keystore.

keystore.key_password : Password of the private key in keystore.

truststore.location : Location of the trusted certificate store, The backend certificate should be added here.

truststore.type : Type of the keystore.

truststore.password : Password of the keystore.

After making this configurations, You have to restart the server to affect these changes. And also make sure [[keystore.ssl_profile.custom]] is an array, You can add multiple entries there if you have multiple endpoints for mutual SSL.

Create an API

  • Log into the API Manager publisher and create a new API. This follows the regular steps. Refer the official documentation for more information.
  • After creating the API, You have to upload the server side certificate from the publisher.
  • For that, Click on Endpoins and in that page expand the General Endpoint Configurations panel.
Endpoint Configurations
  • There you find the option to upload the certificate, Click on that select the endpoint and upload the certificate.
Upload backed certificate.
  • Then save and publish the API.

From the back-end, You have to put the client-side certificate to it’s trusted certificate store in order to do the Mutual SSL. Therefore please share the exported public certificate with your back-end provider.

Since for this example we are using another API Manager as the back-end, We have uploaded that certificate to the Transport Level Security section.

API Manger transport level security (Serve as backend).

Invoking API

If everything went smooth, You should be able to call out API without any problem. You can refer to the official documentation regarding subscribe and trying an api.

Mutual SSL Flow

If you need to get a clear picture regarding the mutual SSL flow, You can enable the SSL Debug Logs and debug the flow. Following is an overlook of a successful Mutual SSL handshake SSL Debug Logs.

  1. Client Hello and initiating the Handshake (*** ClientHello, TLSv1.2)
*** ClientHello, TLSv1.2
RandomCookie: GMT: 1575293777 bytes = { 43, 249, 40, 221, 224, 50, 161, 41, 240, 179, 141, 84, 120, 167, 125, 7, 80, 202, 240, 186, 245, 193, 30, 151, 147, 224, 4, 239 }
...
So Many Content Inside, Removed to make this short
...
***

2. If the Client hello if secuccess full and validate the ciphers and versions are ok then the Server Hello (*** ServerHello)

*** ServerHello, TLSv1.2
...
So Many Content Inside, Removed to make this short
...
***

3. Server is sending the chain of certificates related to back-end (*** Certificate chain).

*** Certificate chain
chain [0] = [
[
Version: V3
Subject: CN=localhost, OU=WSO2, O=WSO2, L=Mountain View, ST=CA, C=US
Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11
...
So Many Content Inside, Removed to make this short
...

4. If a matching certificate found, Then It will be validated and printed.

***Found trusted certificate:
[
[
Version: V3
Subject: CN=localhost, OU=WSO2, O=WSO2, L=Mountain View, ST=CA, C=US
Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11
...
So Many Content Inside, Removed to make this short
...

5. Then the Server key exchange happens.

*** ECDH ServerKeyExchange
Signature Algorithm SHA512withRSA
Server key: Sun EC public key, 256 bits
public x coord: 20251435229292626180531600774099964572689659729431869921114590883703013814465
public y coord: 80554422334714838811917242567396430539926697197934970349524368406838833515016
arameters: secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)
check handshake state: unknown[13]

6. And if the mutual SSL is enabled, There will be a CertificateRequest. This is the log which can identify wether there is a mutual SSL flow is there.

*** CertificateRequest
Cert Types: RSA, DSS, ECDSA

7 . And Server hello done

*** ServerHelloDone

8. Then Client will send it’s certificate to the back-end.

*** ServerHelloDone
matching alias: 1
*** Certificate chain
chain [0] = [
[
Version: V1
Subject: EMAILADDRESS=foo@for.org, CN=foo.org, OU=FOO, O=NO_ORG, L=Badulla, ST=UVA, C=LK
Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11

9. Upon a correct certificate validation, Client side key exchange happens. and handshake finishes.

** ECDHClientKeyExchange
...
So Many Content Inside, Removed to make this short
...
*** CertificateVerify
...
So Many Content Inside, Removed to make this short
...
*** Finished

Hope this is provide some insights regarding the mutual SSL flow as well as the calling a backend with Mutual SSL enabled.

--

--