MoA’s “end-to-end” security system: JWT with AWS KMS

The updated MoA will handle various decentralized financial activities. One of its key functionalities would be to handle automated financial transactions at the exchanges. The following discusses how we built our monitoring system where the two entities, service that request transaction and the server that communicates with the exchanges, perform end-to-end verification for the entire process.

Get early access to the latest updates on the MoA

We chose JWT system over legacy protocol

Json Web Token (JWT) is a standard protocol used to send claim. More developers choose JWT protocol as it has characteristics are ideal for building a scalable Microservice architecture. However, there lies need for fortifying the bay for key management. The following discussion details how supplemented JWT system with AWS KMS to increase the security of the our system while satisfying the following critical aspects.

  1. JWT protocol for efficient management scalable to expasion
  2. AWS KMS to fortify security at all levels
Diagram of JWT Protocol

JWT enables efficient management

The legacy web protocol is a token-based authentication system. It publishes a token after successfully performing authentication or authorization, and it relies on the central server for testing the validity of each token. Complications arise when one is building a Microservice architecture as the validation process follows a centralized flow. For instance, when a Microservice based server tries to gain access to another server, it needs to first make a pit stop at the central server to gain authorization. This adds an extra burden to the system maintenance.

JWT differs from the legacy protocol as it carries with it a server with all the information pertinent to process a claim, eg. token validate date, expiration date, and service details. Additionally, the JWT protocol requires systems to leave signatures, which protects the data from malicious data fabrication.

As a result, JWT dramatically improves the autonomy of Microservices. The protocol enables Microservice to perform localized token validation testing, automate claim handling, and to create a new JWT to a client needing to use the Service. In short, JWT lets Microservice independently manage its authorization process.

These characteristics make JWT an ideal claim protocol to implement for REST (Representational state transfer) API. As such, we best utilize these features to build our end-to-end security system between services that request transactions and servers that communicate with exchanges.

AWS KMS to fortify security at all levels 

AWS Key management System (KMS)

In implementing the JWT Token system, one key issue is how to best manage the key used for encryption/decryption. We need to consider the following scenario.

  1. Can the key be leaked/exposed?
  2. Is there an audit for key use?
  3. Is the management for key use done within the internal systems?

For key management, we could either develop the system from scratch that uses a Hardware Security Module (HSM), or use what is already available. We chose the latter and decided to implement Key Management Service (KMS) provided by AWS.

AWS KMS supports HSM. It supports both Encrypt/Verify by providing an RBAC/ABAC authorization process. Also, it provides a Cloud Trail that tracks each API that is called.

The following shows a simplified flowchart. I notate what is implemented to help you understand the process.

Process of JWT protocol with AWS KMS

Let me explain how we implemented JWT in the flow in two categories.

  1. JWT Sign/Verify
  2. Permission

RS 265 for JWT Sign / Verify

JWT provides two methods to sign: shared secret and PKI. The basic method is the one using HS256 (HMAC), and it operates as follows.

HMAC requires a secret. For that, AWS uses GenerateDataKey() to create a unique key. In order for the encryption to work, one must maintain the same EncryptionContext chosen at the encryption stage (signing process). This makes it possible for the other system to retrieve the key at the later phase, JWT Verification. The big issue here is the possibility of key leak in the process of maintaining the EncryptionContext. When the key is leaked, a fake token can be created using the key, and it disrupts the auditing process. Therefore, our service chose not to use the HS method.

RS256 method uses the RSA signing method. During this process, JWT is RSA signed with a private key, and KMS Access Service RSA verifies with a public key.

RSA signing method has the following advantages:

  1. It carries out signing and verification within KMS. As such, there is no risk for key export.
  2. Each operation is atomically carried out, all of which leave marks on the Cloud Trail. This is an excellent feature for API auditing.
  3. No need to create an extra key. This enhances security while lessening the burden for the developers.

When using python, use pyJWT. You can interoperate with a KMS client via boto3 client, making signing and verifying very easy.

Customized Permission on AWS

Managing various permission levels is easily done through the JWT sign process via AWS KMS.

The following is authorization for sign and verify, which you can designate by role or by attribute per node.

  1. For sign: kms:Sign
  2. For verify: kms:Verify

Authorization can be designated per user or per EC2 Node. RBAC is used when designated per user, while ABAC is used when designated per AWS entities. Designated per user may appear to be more friendly for easier maintenance at the earlier stage, however, having to create ACCESS KEY ID credential file could present more complications down the road. As such, we decided to use ABAC based on the IAM Role service provided by AWS.

There are two problems with implementing the ABAC system.

First, the process of ABAC authorization based on the AWS IAM Role service is slower than performing user-based authorization. The speed is not a big issue if the session prolongs. However, if the session repeats stop-and-go, it is hard to maintain a good speed. As such the usability is inadvertently diminished.

Second, when using AWS EKS (Elastic Kubernetes Service), there can be more than pods in a given node. However, AWS IAM Role service recognizes nodes as the minimum scale; it lacks the capability to differentiate multiple pods needing varying levels of authorization in a given node. This may result in giving higher authority than a pod is allowed to have in the process of granting access to the node.

We employed Kubernetes Service-Account to tackle those two issues. We built our EKS by first assigning SA to pod, then giving a role to each SA. In doing so, the speed increased by 10 fold when initializing the authorization process. Also, the new structure that grants authorization is now given per pod, enhancing the system’s security.

Additionally, there is a 12 hour limit when SA grants role to pod through the AWS STS (Security Token Service). As STS has a 12 hour limit, you can extend to 12 hours the frame in the AWS IAM Role service (the default is set at 1 hour). It is not a problem when you could potentially create long-live-sessions using botoclient if you want to prolong the session. However, if what you want is to repeat continue-and-discontinue, this limitation of the time frame could be a critical issue. Depending on the design, you may want to reissue STS token regularly to set the environment that best serves your purpose.

How secure is your crypto portfolio? Check for free now!

Get early access to the latest updates on the MoA Investment Solutions