Set Up Kong API Gateway

Prev Next

1.0 Introduction

This article describes how to configure Kong API Gateway, integrated with Auth0 for authentication and the AWS SigV4 Proxy for request signing, to enable secure machine-to-machine (M2M) communication required for onboarding an Amazon Web Services (AWS) connection in Fortanix Key Insight.

Configuring the Kong API Gateway involves the following steps:

  1. Set up the AWS-Sigv4-Proxy

  2. Create a Kong service

  3. Create a Kong route

  4. Configure the JWT Route plugin

  5. Configure the Request Transformer Service plugin

  6. Create a Kong consumer

  7. Register the Auth0 public key as a JWT credential in the consumer

  8. Verify the setup

2.0 Prerequisites

Before you begin the setup, ensure the following requirements are met:

  • Auth0 Configuration

    • An Auth0 tenant is available.

    • A Machine-to-Machine (M2M) application is created.

    • You have the following Auth0 credentials:

      • Client ID

      • Client Secret

      • Domain URL

    For more information on retrieving the Auth0 credentials, refer to Auth0 Configuration for Client Credentials Authentication.

  • An AWS account with the necessary permissions to access the required AWS services (For example, Amazon S3).

3.0 Set Up AWS SigV4 Proxy

Follow the official GitHub documentation to set up the aws-sigv4-proxy Docker container.

The container exposes an http port by default. For secure communication, it is recommended to run an HTTPS reverse proxy that forwards requests to the aws-sigv4-proxy Docker container.

4.0 Create a Kong service

Run the following command to create a Kong service to route requests to the AWS SigV4 Proxy:

curl -s -X POST https://<kong host>:<admin port>/services/ \
  --data "name=aws-service" \
  --data "url=https://<sigv4-proxy-host>:<sigv4-proxy-port>"

Where,

  • <kong host>: The hostname or IP address where the Kong Admin API is accessible. For example, kong.example.com.

  • <admin port>: The port on which the Kong Admin API listens. For example, 8444.

  • <sigv4-proxy-host>: The hostname or IP of your AWS SigV4 Proxy container or service. For example, localhost.

  • <sigv4-proxy-port>: The port exposed by the SigV4 proxy container. For example, 8080.

Ensure that the preserve_host (AWS Host header) setting is enabled so that the host header is passed through to the SigV4 proxy:

curl -s -X PATCH https://<kong host>:<admin port>/services/aws-service \
  --data "preserve_host=true"

5.0 Create a Kong Route

Run the following command to create a Kong route for aws-service and forward incoming requests to the AWS SigV4 Proxy:

curl -s -X POST https://<kong host>:<admin port>/services/aws-service/routes \
  --data "name=auth0-route" \
  --data "paths[]=/aws-auth0" \
  --data "strip_path=true"

NOTE

For Auth0 client credentials configuration, the API Gateway URL should be https://<kong-host>:<kong-proxy-port>/<path>.

Where,

  • <kong-proxy-port>: The port of Kong’s proxy interface.

  • <path>:  The path configured in the Kong route above. For example, aws-auth0.

Enable the preserve_host setting to forward the incoming AWS Host header to the SigV4 proxy using the following command:

curl -s -X PATCH https://<kong host>:<admin port>/routes/auth0-route \
  --data "preserve_host=true"

This step is critical because the SigV4 proxy uses the Host header to determine which AWS service to sign the request for.

For example,  kms.us-east-1.amazonaws.com or  https://aws.amazon.com/s3/.

6.0 Configure JWT Route Plugin

Run the following command to configure a JWT plugin on the auth0-route. This plugin verifies Auth0-issued tokens using an RS256 signature algorithm and the azp claim:

curl -s -X POST https://<kong host>:<admin port>/routes/auth0-route/plugins \
  --data "name=jwt" \
  --data "config.key_claim_name=azp" \
  --data "config.claims_to_verify[]=exp" \
  --data "config.run_on_preflight=true"

7.0 Configure Request Transformer Service Plugin

Run the following command to configure the Request Transformer Service plugin on the aws-service: This plugin removes the authorization header before the request is proxied to AWS SigV4 proxy.

curl -s -X POST https://<kong host>:<admin port>/services/aws-service/plugins \
  --data "name=request-transformer" \
  --data "config.remove.headers[]=Authorization"

8.0 Create a Kong Consumer

A Consumer is an entity that represents an external client, in this case, Fortanix Key Insight, that interacts with the APIs managed by Kong Gateway.

Run the following command to create a consumer (ki-consumer) for Fortanix Key Insight:

curl -s -X POST https://<kong host>:<kong admin port>/consumers \
  --data "username=ki-consumer"

9.0 Register Auth0 public Key as a JWT Credential in the Consumer

Kong requires an Auth0 Public Key to verify the JSON Web Token (JWT) presented by Fortanix Key Insight when scanning AWS.

The following sections describe the steps to retrieve the public key and add it to Kong:

9.1 Retrieve an Access Token from Auth0

Run the following command to retrieve a client-credentials access token from Auth0 to read information such as the kid (key ID):

curl -s --request POST \
  --url https://<AUTH0 DOMAIN>/oauth/token \
  --header 'content-type: application/json' \
  --data @- <<JSON
{
  "client_id": "<AUTH0 CLIENT ID>",
  "client_secret": "<AUTH0 CLIENT SECRET>",
  "audience": "KI-Scanner",
  "grant_type": "client_credentials"
}
JSON

Here, replace <AUTH0 DOMAIN>, <AUTH0 CLIENT ID>, and <AUTH0 CLIENT SECRET> with the Auth0 credentials you collected earlier.

9.2 Extract the kid from the JWT Access Token

Use the following Python snippet to extract the kid from the JWT access token:

import sys, json, base64, os
token=os.environ.get('<ACCESS TOKEN FROM AUTH0>')
header_b64=token.split('.')[0]
pad = '=' * (-len(header_b64) % 4)
header=json.loads(base64.urlsafe_b64decode(header_b64+pad))
print(header.get('kid',''))

Here, replace <ACCESS TOKEN FROM AUTH0> with the access token obtained in Section 9.1: Retrieve an Access Token from Auth0.

9.3 Retrieve the Auth0 Certificate Corresponding to kid

Use the following Python snippet to retrieve the Auth0 certificate that matches the kid obtained in Section 9.2: Extract the kid from the JWT Access Token:

import os, json, urllib.request
jwks_url = 'https://<AUTH0 DOMAIN>/.well-known/jwks.json'
kid = os.environ['KID']
with urllib.request.urlopen(jwks_url) as resp:
    data = json.loads(resp.read().decode())
key = next((k for k in data.get('keys', []) if k.get('kid') == kid), None)
if not key:
    print('', end='')
    raise SystemExit(0)
x5c = key.get('x5c', [None])[0]
if not x5c:
    print('', end='')
    raise SystemExit(0)
print('-----BEGIN CERTIFICATE-----')
for i in range(0, len(x5c), 64):
    print(x5c[i:i+64])
print('-----END CERTIFICATE-----')

Save the output as auth0-cert.pem.

Run the following command to extract the public key from the certificate (auth0-cert.pem):

cat auth0-cert.pem | openssl x509 -pubkey -noout

This command prints the public key to the console.

9.4 Add the Public Key to the Kong Consumer

Run the following command to add the extracted public key (<public key>) to the Kong consumer (ki-consumer) to verify Auth0 RS256-signed tokens:

curl -s -X POST https://<kong host>:<admin port>/consumers/ki-consumer/jwt \
  --data-urlencode "key=<AUTH0 CLIENT ID>" \
  --data-urlencode "algorithm=RS256" \
  --data-urlencode "rsa_public_key=<public key>"

10.0 Verify the Setup

Run the following AWS KMS request to validate that the entire integration is working end-to-end: (You may need to obtain a fresh access token from Auth0 and use it as <ACCESS TOKEN> .)

curl -s \
  -H "Authorization: Bearer <ACCESS TOKEN>" \
  -H "Host: kms.us-east-1.amazonaws.com" \
  -H "Content-Type: application/x-amz-json-1.1" \
  -H "X-Amz-Target: TrentService.ListKeys" \
  -X POST https://<kong host>:<kong porxy-port>/aws-auth0/ \
  -d '{}'

If the setup is correct, the response displays the AWS Key Management Service (KMS) keys accessible using the AWS credentials configured in the SigV4 proxy.