Connect to private resources from API Gateway with VPC Link

19/04/2018 Vincent Van der Kussen

Connect to private resources from API Gateway with VPC Link

Until recently it was not possible to reach services in your VPC’s private subnets from API  Gateway. This recently changed and API Gateway now supports Endpoints to Private
VPC’s . This means you can reach services in Private VPC’s without using custom headers or Lambda Proxy’s.

In this example we will create an API in API Gateway with some resources . When we access these resources, API Gateway will contact the backend which runs in a private subnet and returns the response back to the client.

The following endpoints will be created:

  • / (returns the status of the API)
  • /header (returns the host header of the request)
  • /foo/* (example to proxy everything under /foo to the backend)

To establish this connection a Network Load Balancer (NLB) will be used. A Network Load Balancer operates at level 4 of the OSI model and therefore only uses the TCP protocol. We will use HTTP to communicate with our service In this example we use Nginx as a proxy to our application.

Network Load Balancer

Open the AWS EC2 console and create a new Load Balancer of the type Network Load Balancer

  • Give it a name and choose Internal Facing (we don’t want to expose it publicly).
  • Select TCP and Choose port 80 (this is the tcp port where we will receive connections on).
  • In Availability Zones select the VPC and subnets where you want to deploy the NLB.

Configure routing

In the next step we need to create a Target Group (or use an existing one). In this example we will create a new target group. In the Health Check configuration we’ll use the same port as the traffic port.

NOTE: If your backend service is listening on another tcp port you’ll need to adjust this so that the health check doesn’t fail.

Register targets

In the next screen select the instances where you want to send traffic to. You can also skip this and add the instances later.

NOTE: Instead of a single instance you could also attach the Target Group to an Auto Scaling Group.

API Gateway

Now that we have our NLB configured we can configure our API Gateway.

Configure the VPC Link in API gateway

Open the API Gateway console and choose VPC Links. Create a new VPC Link and select the Target NLB we created earlier.

Create the API

Now we can create our API. The fasted way is to create a Swagger file and import that.

Example Swagger file:

Once created you should see your API Resources

Create VPCLink

To create the actual connection to our private subnets we need to create a VPC Link. In the API Gateway console and choose VPC Links. Create a new VPC Link and select the Target NLB we created earlier.

Deploy API

We can now deploy the API by running APIs => <your api name> => Actions => Deploy API . Choose a name for the stage (in this example we use ‘test’ ).

Once deployed you will see a ‘test’ stage under Stages. Navigate to the Stage Variables tab and add a new variable with the name vpcLinkId  and the value is the ID of the VPCLink we created earlier.

Create Custom Domainname

Because we are using Virtual Hosts in Nginx based on the incoming url we will have to make the API available on that URL. To do this we need to create a Custom Domain Name in the API Gateway Console.
In this example we are using flaskapp-api.vincent.cloudar.be

NOTE: Because Cloudfront is used for this, it can take a while until the Cloudfront Distribution is deployed.

We will also need to create a DNS record in Route 53 that will point to this Cloudfront Distribution. Use the Target Domain Name value.

Testing

The backend application used in this example is a simple Python Flask application which exposes some API endpoints:

Python Flask app:

The application is proxied by Nginx.

NOTE: The server_name parameter is important as API Gateway will send the Endpoint URL configured in the Integration Request as host header.

Nginx config:

Now let’s see if everything works.

 

 

Conclusion

If you want to use API Gateway but don’t want or can’t expose your backend services publicly VPC Link can be a good solution. However you’ll still need to find a solution to proxy the requests and do TLS/SSL offloading. Of course it will probably be a matter of time before AWS supports this natively.

 

,