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:
Set up the AWS-Sigv4-Proxy
Create a Kong service
Create a Kong route
Configure the JWT Route plugin
Configure the Request Transformer Service plugin
Create a Kong consumer
Register the Auth0 public key as a JWT credential in the consumer
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"
}
JSONHere, 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 -nooutThis 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.