How to Build Private REST API with Lambda and Used By EC2

2021/02/085 min read
bookmark this
Responsive image

Table of Contents

Introduction

This blog shows how to create a private REST API that will be consumed by an EC2 Linux Instance. It uses the AWS API Gateway to build a private REST API and the existing VPC endpoint to communicate from EC2 to the REST API. The traffic from EC2 to the REST API will not go through the public internet.

The scenario below assumes AWS EC2 will consume a private REST API, and the REST API will integrate with Lambda functions. There are a few prerequisites for this blog:

  • You have already set up an AWS account.

  • You have already set up a VPC, Public Subnet, and Security Group with port 80 open.

  • You have an EC2 instance running under the public subnet using the VPC.

Create Lambda Function

First, we'll create a simple Lambda function because later the Private REST API will call it. Go to AWS Lambda and create a function. We can leave everything as default since creating the Lambda function is not the main purpose here.

Create Endpoints

Here, we'll need to create endpoints at VPC. On the VPC page's left panel, click Endpoints and then click the Create Endpoint button. We need to create VPC endpoints because the Private REST API will require them.

On the Create Endpoints page, choose AWS services for the Service category. For Service Name, search for execute-api. You should be able to find something similar to com.amazonaws.us-west-1.execute-api, then choose the service.

For the VPC, choose the VPC you want to use for the private REST API. Also, choose the corresponding subnet for that VPC.

Check Enable DNS name, select the security group, and then click the Create Endpoint button.

Make sure to note down the Endpoint ID, because you will need it later for the private REST API.

Create Private REST API

Now, we'll create a private REST API by using the API Gateway. Go to the API Gateway and click Build under REST API Private.

Choose New API, enter any name for the API Name, and change the Endpoint Type to Private.

At the VPC Endpoint IDs field, enter the VPC Endpoint ID we created before, then click the Create API button.

Create Resource

For the REST API, first we'll need to create resources. Click Actions and then click Create Resource. Enter any resource name and resource path, then click the Create Resource button.

Create Method

Click Actions, then click Create Method. Choose Any, make sure the Integration type is Lambda Function, select the Lambda you created before, and click Save.

Test the API

Test the API to make sure the response is what you expect.

Publish API

Click Deploy API, enter a Deployment Stage name, and then deploy the API. Now the API is deployed and you should see a URL like the following. Please note down the API ID (e.g., x4aiqshkvj), as you will use it later to create a custom policy.

https://x4aiqshkvj.execute-api.us-west-1.amazonaws.com/test

Create Resource Policy

We'll need to create a resource policy for the API. Open the Resource Policy and replace vpceID with the endpoint ID we created earlier.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "execute-api:/*",
            "Condition": {
                "StringNotEquals": {
                    "aws:sourceVpce": "vpceID"
                }
            }
        },
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "execute-api:/*"
        }
    ]
}

Create Custom Policy and Attach to EC2 Role

We'll need to create a custom policy for EC2 to execute the API Gateway. Go to IAM Policies and create a new policy as follows. You'll need to replace your account ID, region, API key, and specify the API scope. Once the custom policy is finished, make sure it is attached to the EC2 instance's role.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "execute-api:Invoke"
            ],
            "Resource": [
                "arn:aws:execute-api:us-west-1:{AWS Account ID}:fqmufdbru6/*/GET/test"
            ]
        }
    ]
}

Test Private REST API via EC2

To test the private API we just created, first enter the API URL in a browser and confirm that DNS can't reach it from outside the VPC.

Now, for the next test, we want to access the private link from within the VPC to make sure the API is working.

SSH into the EC2 instance that is using the same VPC as the private API. Run the following command on your EC2 instance (assuming it is running Amazon Linux AMI). If the response matches the result from your Lambda function, then you have successfully confirmed that the private REST API is working.

curl https://xxx.execute-api.us-west-1.amazonaws.com/test

Conclusion

Building a private REST API with API Gateway requires a little more work compared to a public REST API, but once you follow the steps, it should be straightforward. Your requests won't go through the public internet and will run within your VPC. That means if you use any other AWS service running in the same VPC, you can access the same private API.