0%
view

Secure your VPC endpoint for API Gateway with Winglang

March 25, 2024
By
Ruslan
5
min read
Share article
API Gateway is a common method to build robust and secure APIs especially if AWS is a cloud provider of your choice. While it is quite straightforward to build public facing API endpoints within API Gateway, developers often struggle with securing their API Gateway instances.

VPCs, VPC endpoints, subnets, security groups — it is very easy to mess things up. Complexity goes up one level when you need to use an Infra as Code solution to keep the state of your infrastructure. Thankfully, there is a great and modern solution which we are going to discuss in this article.

Winglang

Winglang is a versatile programming language, intended for the development of comprehensive cloud applications, encompassing both their infrastructure and application code. The goal is to merge infrastructure and runtime code into one language, providing developers complete control over all aspects of backend service development and infrastructure within a single codebase.

At the time of this writing, AWS support was fully implemented, while partial support was provided for other platforms such as Azure and GCP.

Create a new project

In the article Building Efficient APIs and Infrastructure from one code base with Winglang we have covered in detail how to get started with Wing project, and develop and test a simple API Gateway endpoint.

In this article, we will expand on the same use case. We will recreate a Wing project, making the endpoint private and secure.

Create a Private API project

Check your Winglang version and make sure you have the latest version. The latest version at the time of writing is 0.59.24.

$ wing -V
0.59.24

Next, create a new project using the private-api boilerplate.

wing new private-api

You should have the following file structure after running the command.

wing-api/
├── main.w
├── package-lock.json
├── package.json
└── wing.toml    <----

Note that the file structure is identical to a standard Winglang project, with the addition of a wing.toml file. The platform-level configuration is described using the TOML format, known for its minimalism and conciseness.

Set up your platform-level configuration

There are two ways we can configure our platform configuration:

  1. We have no previous network infrastructure (VPC and subnets) and we are starting from scratch
  2. Our networking infrastructure is already set up and we would like to configure our API Gateway endpoint to use existing VPC

Refer to a recent blog post on Winglang official website for more information.

Create new infrastructure

To orchestrate a new infrastructure for our API Gateway we will use the following wing.toml configuration.

[ tf-aws ]
vpc = "new"
vpc_lambda = true
vpc_api_gateway = true

We use the Winglang platform (tf-aws) to deploy our infrastructure on AWS. In the following lines, we instruct Wing to create a new VPC and ensure that Lambda functions and API Gateway instances are provisioned within this VPC on the private subnet.

Use existing infrastructure

If we want Wing to use an existing VPC, we need to provide an additional configuration in wing.toml.

[ tf-aws ]
vpc = "existing"
vpc_lambda = true
vpc_api_gateway = true
vpc_id = "vpc-123abc"
private_subnet_ids = ["subnet-234bcd"]
public_subnet_ids = ["subnet-345cde"]

We need to provide the VPC ID (vpc_id), which can be found in AWS Console → Virtual private cloud → Your VPCs section.

Additionally, we need to supply a list of private (private_subnet_ids) and/or public (public_subnet_ids) Subnets IDs where we plan to provision our API Gateway instance. Subnets details can be found in AWS Console → Virtual private cloud → Subnets section.

API Gateway endpoint code

We are going to reuse a simple API Gateway endpoint code from Building efficient APIs and infrastructure from one code base with Winglang article.

bring cloud;
bring http;

let api = new cloud.Api();

let githubToken = new cloud.Secret(
  name: "github-token",
);

let host = "";
let owner = "bear-plus";
let repo = "codeceptjs-playwright-typescript-boilerplate";
let workflow_id = "e2e-test-automation.yml";
let endpoint = "repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches";

api.get("/trigger", inflight (req: cloud.ApiRequest): cloud.ApiResponse => {
 let token = githubToken.value();
 
  let response = http.post("{host}/{endpoint}", {
    headers: {
      "Authorization": "Bearer {token}",
      "Accept": "application/vnd.github+json",
      "X-GitHub-Api-Version": "2022-11-28",
    },
    body: Json.stringify({ "ref": "main" }),
  });
  if response.status == 204 {
    return cloud.ApiResponse {
      status: 200,
      body: "E2E pipeline triggered successfully.",
    };
  }
  return cloud.ApiResponse {
    status: response.status,
    body: response.body,
  };
});

Note, there is no change in the code about as to secure this endpoint we will only need to redefine Winglang platform level configuration, while the about code is at the application level. Refer to a Winglang blog post for more details.

Deploy your Winglang project

To deploy the Winglang project run the apply command from your project’s root folder.

cd target/main.tfaws && terraform apply

Before the infrastructure is orchestrated Terraform will display the changes that are going to be made. Ensure everything is as intended before typing “yes”.

AWS Console shows API Gateway instance deployed as Private

After our API Gateway endpoint is deployed we can notice the API endpoint type is set to Private compared to the other endpoint (Edge) with the identical application level code but without extra platform level TOML configuration.

Conclusion

In this article, we expand on the Winglang project described in the Building Efficient APIs and infrastructure from one code base with Winglang article. By introducing additional platform-level configuration in Winglang, we managed to secure our endpoint, making it private and enhancing our solution to meet our clients’ networking requirements.

Other things to keep in mind

If you would like to explore further how to secure API Gateway, refer to Private API Gateway Wing Plugin which aims to provide the same functionality with a different approach.

Source code

The source code described in this article is hosted in Winglang AWS Private API Gateway repo and available in Bear Plus GitHub space.