Accessing a Private API Gateway (AWS)

Accessing a Private API Gateway (AWS)

Understanding how to access an API you just created in AWS should be easy, right?

I spent a significant amount of time figuring out how to deploy a private API Gateway that would be accessible from outside of the VPC in which it resides.

Let's start with some background:
You can deploy an API Gateway using one of three modes: Regional, Edge and Private. If you want your API to be open to the internet, you'll probably choose Regional or Edge. If it's an API accessed by internal clients from within your VPC, you will probably choose Private.

All clients inside the gateway's VPC should be able to access it without a problem using the invoke url (you can find the invoke url at the top of the stage page).

It gets complicated when you want clients sitting in another VPC or your colleagues from the office network to be able to access your private API Gateway.
In this case, they won't be able to access it using the invoke url, as this DNS works only inside the VPC.

What should you do to solve it?
You need to create a VPC Endpoint for the VPC your API Gateway resides in, by going to Endpoints in the VPC management page.
Then creating the endpoint, choose the service, and your VPC. Tick the Enable Private DNS Name checkbox and create or use an existing security group to restrict the access to the VPC endpoint to your internal IPs only (your office internal subnet for example).

Then, to access the API Gateway, you must send a special header with every request, stating the API you want to access. The reason for this being the fact that you have 1 VPC Endpoint, and potentially more than one API Gateway inside this VPC.
The header name is x-apigw-api-id and the value should be the unique ID of your API Gateway.

An example request should look like this:

curl -X GET https://{VPC_ENDPOINT_DNS_NAME}/{STAGE_NAME}/{ENDPOINT_NAME} -H’x-apigw-api-id:{API_GW_ID}

or using Python:

requests.get('https://{VPC_ENDPOINT_DNS_NAME}/{STAGE_NAME}/{ENDPOINT_NAME}', headers={'x-apigw-api-id': '{API_GW_ID}'})