Creating a Secure Mock Backend Using a Self Signed Certificate
Hey there!
Ever found yourself in need of a mock backend, wrapped snugly in SSL, for your testing endeavours? Well, today’s your lucky day because we’re diving headfirst into creating exactly that using Mockoon!
Now, what’s Mockoon, you ask? It’s the superhero of mock API services, a free and open-source tool that’s as easy as pie to use. Plus, it’s cross-platform, so everyone gets a slice of the action.
Let’s paint the picture:
- Install Mockoon: First things first, get Mockoon up and running. [1]
- Add a New API: Just a few clicks and you’re there. [2]
But hey, don’t take my word for it. The real magic lies in the detailed instructions in Mockoon’s documentation [2]. Trust me, it’s a breeze.
By default Mockoon serves your API on localhost port 3000 .
Since we are going to test the SSL we will change the hostname to a different one .
For the below test I am setting the hostname as www.example.com . Which I have mapped to the 127.0.0.1 IP address using my computer’s /etc/hosts file .
127.0.0.1 www.example.com
Please refer the below screenshots for the API configurations . In here I have created a route/resource named /abc . Which will output a json response {“hello”:”world”}
Now, just to make sure our service is working fine lets start the service and invoke the API .
As we have not enabled SSL yet this API will be served over HTTP protocol via www.example.com host and 3000 port by default .
To verify we will execute the following curl command and it should retrun the response as follows.
% curl http://www.example.com:3000/abc
{"hello":"world"}
Okay , now lets make the same service SSL secured .
Let me refresh the basics of one way ssl briefly
In a one-way SSL (Secure Sockets Layer) connection, also known as SSL/TLS (Transport Layer Security), the server presents a digital certificate to the client to establish a secure connection. When the server uses a self-signed certificate, it means that the certificate is not signed by a trusted third-party Certificate Authority (CA). Instead, the server generates its own certificate.
Here’s how it typically works:
Client-Server Communication Initiation: The client initiates a connection to the server using HTTPS (HTTP over SSL/TLS).
Server Presents Its Certificate: When the client connects to the server, the server sends its digital certificate to the client. This certificate contains the server’s public key, its identity (such as the domain name), and other information.
Client Verification: The client receives the server’s certificate. It checks whether the certificate is valid and trusted. In the case of a self-signed certificate, the client doesn’t recognise the issuer as a trusted CA because it’s not signed by a globally recognized CA.
Certificate Trust Decision: If the client trusts the server, it proceeds with the connection.
Establish secure connection and Exchange Data :
Now, lets dive into how to create key pair to protect our Mockoon REST service .
To enable TLS, we must first create a public/private key pair for the API server. Using the keytool that comes with the default Java distribution.
The following command generates a key pair and stores it in keystore.p12.
keytool -genkeypair -alias tlsdemo -keyalg RSA -keysize 4096 -validity 365 -dname "CN=www.example.com,OU=self,O=example,L=colombo,S=western,C=SL" -keypass changeit -keystore keystore.p12 -storeType PKCS12 -storepass changeit
-genkeypair — Generates a key pair
-alias <alias> — Alias name of the entry to process
-keyalg <alg> — Key algorithm name
-keysize <size> — Key bit size
-validity <days> — Validity number of days
-dname <dname> — Distinguished name,
CN is CommonName of a person
OU is OrganizationUnit
O is OrganizationName
L is LocalityName
S is StateName
C is CountryName
-keypass <arg> — Key Password
-keystore <keystore> Keystore name
-storeType <type> — Keystore type
-storepass <arg> — Keystore password
The keystore file will be called keystore.p12 and protected with the password “changeit”.
Now we have the keystore file containing public/private key pair .
Lets head over to Mockoon and configure the keystore for our REST service .
1.Navigate to Settings .
2.Check “Enable Tls”
3.Switch to PFX and provide the created keystore.p12 file location to “PFX or PKCS12 path”
4.Provide password as the “Cert passphrase” ( changeit )
Reload the service if running . Sample Configurations here
Now, the service will be exposed over HTTPS protocol via www.example.com host and 3000 port .
This time, we’re curling in verbose mode, but no -k shortcuts here. We’re here to validate.
We will get the expected error as follows indicating the error in certificate validation.
% curl https://www.example.com:3000/abc -v
* Trying 127.0.0.1:3000...
* Connected to www.example.com (127.0.0.1) port 3000 (#0)
* ALPN: offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/cert.pem
* CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* SSL certificate problem: self signed certificate
* Closing connection 0
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
Since the server use our selfsigned certificate we need to tell curl to validate it using server’s public certificate .
We can parse it using the --cacert option in curl .
To export the public key from the keystore we can use the following command .
keytool -export -file tlsdemo.crt -alias tlsdemo -rfc -keystore keystore.p12 -storepass changeit
Executing the above will output a file called tlsdemo.crt which stores the public key of certificate .
Now lets invoke the API using curl parsing the public key in verbose mode .
% curl https://www.example.com:3000/abc --cacert tlsdemo.crt -v
* Trying 127.0.0.1:3000...
* Connected to www.example.com (127.0.0.1) port 3000 (#0)
* ALPN: offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* CAfile: tlsdemo.crt
* CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256
* ALPN: server accepted http/1.1
* Server certificate:
* subject: C=SL; ST=western; L=colombo; O=example; OU=self; CN=www.example.com
* start date: Apr 13 17:58:40 2024 GMT
* expire date: Apr 13 17:58:40 2025 GMT
* common name: www.example.com (matched)
* issuer: C=SL; ST=western; L=colombo; O=example; OU=self; CN=www.example.com
* SSL certificate verify ok.
* using HTTP/1.1
> GET /abc HTTP/1.1
> ...
< HTTP/1.1 200 OK
{"hello":"world"}
As expected we could see the certificate validation getting passed .
Hope you have learned something and it will help testing your front end applications .
Stay tuned ⏰ Because we’ll be revisiting this mock API service in our tech stack real soon.
Until next time, keep experimenting and keep exploring !!