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

2021/2/85 min read
bookmark this
Responsive image

This blog shows how to create a private REST API, and then will consume by the EC2 Linux Instance. It will use the AWS API Gateway to build a private REST API and use the existing VPC endpoint to communicate from EC2 to REST API. The traffic from EC2 to REST API will not go through the public internet. 

The scenario below assumes AWS EC2 will consume private REST API, and the REST API will integrate with lambda functions. There are few steps this blog as pre requirement

  • Already set up an AWS account.
  • You already set up VPC, Public Subnet, and Security Group with port 80 is open.
  • You have an EC2 instance running under the public subnet and use the VPC.

Create Lambda Function

First, we'll just create a simple Lambda function because later the Private REST API will call the Lambda function. So go to the AWS Lambda and create a function and we can leave everything as default is fine, because create the Lambda function is not the main purpose here.  

Create Endpoints

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

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

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

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

Make sure to memo the Endpoint ID, because 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, click the build under REST API Private. 

Choose the New API, Enter any name for the API Name. Change the Endpoint Type to Private.

At the VPC Endpoint IDs, enter the VPC Endpoint ID we have created before, click the Create API button to create API. 

Create Resource

For creating REST API, first, we'll need to create resources, click the Actions and click create a resource, enter any resource name and resource path, then click create resource button.

Create Method

Click Actions then click create method, choose Any, make sure the Integration type is Lambda Function and select the Lambda you create before and click save.

Test the API

Test the API to make sure the response is what is expected. 

Publish API

Click Deploy API, enter Deployment Stage, enter any name and then deploy the API. Now API is deployed and you should see some URL as follow. Please memo the x4aiqshkvj, will later use this 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 at the API, open the Resource Policy then replace the following vpceID with the endpoint ID we create 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 the IAM Policies and create a new policy as follow.  You'll need to replace your account ID, region, API key, and specify API scope. Once is custom policy is finish, make sure this policy is attached to the EC2.

{
    "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 put the API to the browser and make sure DNS can't reach it. 

Now, in the next test, we'd like to access the private link within the VPC to make sure the API is working. 

Let's ssh into the EC2 which using the same VPC as the private VPC API. Run following at your EC2, assume running on the Linux Amazon AMI, if this response is the same result from your Lambda, then you are successfully testing the private rest API is working.

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

Conclusion

Building the private REST API with API Gateway is a little more work compared to the public REST API, but once you follow the step it should be fine, and your request won't go through the public internet and can run within your VPC. That means if you use any other AWS Service and running the same VPC and you can access the same private API.