Microservices Security with Ballerina

Securing Microservices with mTLS, JWT, OAuth2, and more

Chanaka Lakmal
Ballerina Swan Lake Tech Blog
8 min readAug 3, 2021

--

Overview

This article explains how to secure your microservices deployment practically using the Ballerina programming language. Ballerina has first-class support for a whole bunch of security features from transport layer security like SSL/TLS, mTLS to application layer security like Basic Authentication (Basic Auth), JWT Authentication, OAuth2, etc. Let’s see how we can apply those for microservices deployment.

Ballerina is an open-source programming language for the cloud that makes it easier to use, combine, and create network services.
Source: https://ballerina.io

Microservices (or microservices architecture) is a cloud-native architectural approach in which a single application is composed of many loosely coupled and independently deployable smaller components or services.
Source: https://www.ibm.com/cloud/learn/microservices

For the simplicity of this article, let’s consider a hypothetical e-commerce application, which has microservices and components programmed with Ballerina.

NOTE: All the Ballerina code samples in this article are tested and compatible with Ballerina 2201.0.0 (Swan Lake)

Design

At a high level, the system looks like this:

Figure 1 — High-level design diagram of e-commerce system

The end-user (customer), in this example, Alice and Bob, interacts with the system using the web/mobile app provided. This web/mobile app acts as a Client on behalf of the user’s actions.

We have two trust domains; the left side trust domain is allowed any HTTPS inbound traffic, and the right side trust domain is allowed the inbound traffic only from the left side trust domain. The system trusts the Authorization Server/STS and the Certificate Authority (CA) which are configured for this system.

In the left side trust domain, we have an API Gateway, which has both REST APIs and GraphQL APIs. The API Gateway routes the GraphQL API requests to Inventory Service, which is responsible for managing the inventory of the system, and the REST API requests to Order Service, which is responsible for processing the order for the customer.

In the right side trust domain, we have Payment Service and Delivery Service with gRPC APIs, which are called by the Order Service of the left side trust domain only to process the payment and delivery.

User Story

Scenario 1

Customer Alice wants to search for electronic items.

First, she logs into the e-commerce app (Client) with her credentials, and once her credentials are validated successfully, she will be redirected to the dashboard of the app. There, Alice searches for electronic items and she gets a list of items with their details such as code, name, price, etc.

How does scenario 1 work?

  1. Once Alice searches for electronic items from the dashboard, the Client gets an access token with the scope ‘customer’ using the OAuth2 Client Credentials grant type from the Authorization Server/STS. Here, the communication must happen over HTTPS (HTTP over SSL/TLS) which helps to protect the confidentiality and integrity of communication.
  2. The Client calls the GraphQL /inventory API using the received access token. Here also, the communication must happen over HTTPS.
  3. The API Gateway introspects the access token from STS and validates the ‘scope’ for the ‘customer’. Here also, the communication must happen over HTTPS.
  4. The API Gateway calls the Inventory Service with mTLS (Mutual TLS). Here, mTLS helps them to identify each other because they are in the same trust domain. All the certificates issued to both parties are signed by a trusted CA.
  5. The Inventory Service processes the request and returns the response to API Gateway.
  6. The API Gateway processes the response as per the GraphQL request by the Client and returns the response to the Client.
  7. Finally, the Client processes the response and displays the electronic items on the web/mobile app dashboard.

Scenario 2

Customer Bob wants to place an order.

First, he logs into the e-commerce app (Client) with his credentials and once his credentials are validated successfully, he will be redirected to the dashboard of the app. There, Bob selects an electronic item and follows the purchasing process. Once completed, he gets a confirmation with the invoice, payment details, and delivery details, etc.

How does scenario 2 work?

  1. Once Bob follows the purchasing process of electronic items from the dashboard, the Client gets an access token with the scope ‘customer’ using the OAuth2 Client Credentials grant type from the Authorization Server / STS. Here, the communication must happen over HTTPS (HTTP over SSL/TLS) which helps to protect the confidentiality and integrity of communication.
  2. The Client calls the REST /orders API using the received access token along with the customer-id and order-id. Here also, the communication must happen over HTTPS.
  3. The API Gateway introspects the access token from STS and validates the ‘scope’ for the ‘customer’. Here also, the communication must happen over HTTPS.
  4. The API Gateway calls the Order Service with mTLS (Mutual TLS) along with the data for placing the order. Here, mTLS helps to identify each other in the same trust domain. All the certificates issued to both parties are signed by a trusted CA.
  5. The Order Service processes the request and routes the request to the Payment Service and Delivery Service with a self-signed JWT by the private key of Order Service. Here also, the communication must happen over HTTPS.
  6. Also, the Order Service sends a new request to Inventory Service with mTLS (Mutual TLS) to reduce the inventory quantity of the ordered item.
  7. The Payment Service/Delivery Service validates the JWT with the public key of Order Service and processes the delivery and payment accordingly. A successful response is sent back to the Client via the Order Service and API Gateway with the details of the invoice, payment details, and delivery details, etc.
  8. Finally, the Client processes the response and displays the invoice, payment details, and delivery details, etc.

Security Implementation

Let’s take a look at how we can secure the Client, API Gateway, Inventory Service, Order Service, Payment Service, and Delivery Service using Ballerina.

NOTE: To demonstrate the security features clearly, the business logic is removed from the following sample codes. The complete implementation can be found at https://ldclakmal.me/ballerina-security/scenarios/e-commerce-system.html

Client (Web/Mobile App)

The Client has an outbound endpoint, where it is used to call Authorization Server/STS in order to get an access token and to call the REST endpoint or GraphQL endpoint of the API Gateway using the received-access token with Authorization header.

The security of the client endpoint which is used to call the Authorization Server/STS depends on how we have configured it. In this case, we have configured the Authorization Server/STS for the OAuth2 Client Credentials grant type.

NOTE: The OAuth2 Client Credentials grant is suitable for machine-to-machine authentication or for a client making requests to an API that does not require the user’s permission. This grant should be allowed for use only by trusted clients.

For this scenario, we are using a customized Docker image of the WSO2 Identity Server as an Authorization Server/STS. You can find more details here. Also, the communication between the Client and Authorization Server/STS happens over TLS.

NOTE: TLS protects the confidentiality and integrity of the communication between two parties.

The following code sample demonstrates how to secure an HTTP client with the OAuth2 Client Credentials grant type and TLS in Ballerina.

For more information:
*
https://ballerina.io/learn/by-example/http-client-oauth2-client-credentials-grant-type.html

API Gateway

NOTE: In an ideal world, the microservices developer should worry only about the business functionality of a microservices, and the rest should be handled by specialized components with less hassle. The API Gateway is one of the architectural patterns that can help us to reach that ideal.

The API Gateway has two inbound endpoints which are REST and GraphQL and both are secured with OAuth2. Here, we introspect the access token received by the Client as an Authorization header and validate it. The API Gateway trusts the same Authorization Server/STS that the Client trusts. Also, the communication between the Client and API Gateway happens over TLS.

NOTE: In a typical microservices deployment, you have your own CA, trusted by all your microservices. And all the microservices within a single trust domain trust a single STS.

The following code sample demonstrates how to secure an HTTP listener with TLS and how to secure the attached HTTP service and GraphQL service with OAuth2 in Ballerina.

Take a look at the following examples for more information:
*
https://ballerina.io/learn/by-example/http-service-ssl-tls.html
*
https://ballerina.io/learn/by-example/http-service-oauth2.html
*
https://ballerina.io/learn/by-example/graphql-service-oauth2.html

The API Gateway also has 2 corresponding outbound endpoints, which are used to call Inventory Service and Order Service. Those communications are secured with mutual TLS (mTLS).

NOTE: mTLS helps the client and server to identify each other. With TLS, the client knows which server it’s talking to. With mTLS, the server knows the client it’s talking to as well.

The following code sample demonstrates how to secure an HTTP client with mTLS in Ballerina.

For more information take a look at the following example:
* https://ballerina.io/learn/by-example/http-client-mutual-ssl.html

Inventory Service

The Inventory Service has a REST inbound endpoint that is secured with mTLS, which means both client and server authenticate themselves before the data is transmitted.

The following code sample demonstrates how to secure an HTTP listener with mTLS in Ballerina.

More information can be found in the example below:
*
https://ballerina.io/learn/by-example/http-service-mutual-ssl.html

Order Service

The Order Service also has a REST inbound endpoint which is secured with mTLS. It is the same as the Inventory Service which was demonstrated above. Additionally, it has two gRPC outbound endpoints which are used to call Payment Service and Delivery Service. Those communications are secured with JWT. Here, we use a self-signed JWT by the private key of Order Service as the Authorization meta-data of the gRPC call. Also, the communication between the Order Service and Payment Service or Delivery Service happens over TLS.

NOTE: While TLS protects the confidentiality and integrity of the communication between two parties, JWT achieves nonrepudiation as well.

The following code sample demonstrates how to secure a gRPC client with a self-signed JWT and TLS in Ballerina.

Payment Service/Delivery Service

These microservices are in a separate trust domain which allow only the traffic from the left-hand-side trust domain. This is one way of handling the security of microservices, where the traffic is controlled by the network level according to the requirements.

The Payment Service or Delivery Service has a gRPC inbound endpoint which is secured with JWT. Here, we validate the self-signed JWT by the Order Service using its public key.

The following code sample demonstrates how to secure a gRPC listener with JWT and TLS in Ballerina.

Summary

We can categorize all the security approaches that we have taken for securing the e-commerce application under two sections.

  1. Network layer security (SSL/TLS, mTLS, Traffic control)
  2. Application layer security (JWT Auth, OAuth2)

Also, there is no such thing as absolute security. Everything depends on your use case and the level of trust you have in your microservices deployment.

The complete implementation with all the security features can be found at https://ldclakmal.me/ballerina-security/scenarios/e-commerce-system.html

Happy coding with Ballerina!

References:

  1. Microservices Security in Action by Prabath Siriwardena and Nuwan Dias
    https://www.manning.com/books/microservices-security-in-action
  2. Microservices in Practice — Key Architectural Concepts of an MSA by Kasun Indrasiri
    https://wso2.com/whitepapers/microservices-in-practice-key-architectural-concepts-of-an-msa/
  3. Ballerina by examples
    https://ballerina.io/learn/by-example/
  4. Ballerina Security by Chanaka Lakmal
    https://ldclakmal.me/ballerina-security/

--

--

Chanaka Lakmal
Ballerina Swan Lake Tech Blog

CS PhD Student at UWaterloo | ex-WSO2 (Associate Technical Lead)