DEV Community

Cover image for AWS API Gateway MTLS authentication - with SmallStep & Pulumi
Karanbir Singh for AWS Community Builders

Posted on • Updated on

AWS API Gateway MTLS authentication - with SmallStep & Pulumi

Introduction

During the 2022 Christmas holidays, I got (re-)introduced to Smallstep and believe me it is a very promising tech in PKI space, It eases a good number of complex problems that occur if you were self managing the PKI all by yourself from scratch.

This blog post's main focus is going to be about - Securing the APIs deployed on AWS API gateway using MTLS.

The second focus is on how we can leverage Smallstep for the PKI part.

Third most important part being the infra provisioning using Pulumi


Prerequisites

  • basic knowledge of mtls & PKI.
  • above average knowledge of AWS.
  • must own a domain. buy it from AWS route 53, or buy it from somewhere else and configure in AWS route 53 using NS entries.
  • AWS CLI installed.
  • configure AWS credentials on local, profile based.
  • some knowledge of Pulumi IAC.
  • Pulumi CLI on local machine.
  • account at Pulumi
  • account at Smallstep
  • step CLI on the developer machine. (OPTIONAL)

Stack Diagram & Details

The stack diagram

The following are the important stacks which are part of this POC:-

  1. infra stack (REQUIRED)

    • manages the Certificates required for the API gateway custom domains, using the AWS certificate Manager.
    • holds the s3 bucket that is required for the trust store certificate chain.
  2. functions stack (REQUIRED)

    • manages the lambda function(s), presently a very basic single lambda function, and related permissions, etc.
  3. mtls-apis stack (REQUIRED)

    • manages the API gateway related configuration, routes, integration, etc.
    • it refers the infra stack to pull certificate ARNs etc.
    • it refers the infra stack to pull s3 bucket & the ca.pem reference for the API gateway.
    • it refers the functions stack to pull lambda function ARNs etc.
  4. non-mtls-apis stack (OPTIONAL)

    • manages the API gateway related configuration, routes, integration, etc.
    • it refers the infra stack to pull certificate ARNs etc.
    • it refers the functions stack to pull lambda function ARNs etc.

Code details

The code repository for the successful POC is here

The folder structure is same as per the above stack diagram.

Important points:-

  1. The Public DNS zone in AWS route 53 was created manually. That is not part of the stack provisioning.
  2. The order of executing the stack is infra, functions & then mtls-apis
  3. Change the config in the pulumi yaml files in respective folders of all stack, for AWS credentials, region, and DNS domain related changes
  4. The ca.pem in the infra stack needs to be replaced based on the own set of smallstep account. It is currently related to my own smallstep account.

create the ca trust store file.

  1. Make sure you have a SmallStep Account & you are logged in to same.
  2. By default intermediate and root are created for your account. Click on view details by clicking three dots against the entries of root and intermediate certificates and copy both of certificates into a single file.
    List of certificates

  3. Place the ca.pem in the infra stack's folder.


create client certificate

  1. In the smallstep dashboard goto -> Authorities -> Click on the authority -> create certificate using UI, fill subject & expiration, as shown below:- Create Certificate
  2. Authorize. Authorize
  3. Download key and certificate, key is only downloadable at this time, later on it will not be available, keep it safe, otherwise the MTLS protected API endpoint might be compromised Download key and certificate

Testing the API endpoint using POSTMAN

  1. Configure the client cert and key in the certificates section in the settings of POSTMAN

  2. If client cert not provided, the we will get -** Error: read ECONNRESET**

  3. If the client cert and key combo is not correct we will get 403

  4. If all successful, the API will response back as below:-

the path is going to be https://domain.com/v1/ping

{
    "ping": "pong",
    "success": true,
    "timestamp": 1676617772241
}
Enter fullscreen mode Exit fullscreen mode

Please feel free to reach out to me over Linkedin here for further questions, doubts or suggestions.

Top comments (0)