Attaching API keys to usage plans for API throttling
TypeScriptTo throttle requests to your APIs and manage how your APIs are used, AWS API Gateway allows you to create usage plans and require API keys for requests. A usage plan specifies who can access one or more deployed API stages and methods—and also how much and how fast they can access them. API keys are alphanumeric string values that you distribute to app developer customers to grant access to your API.
Here's how you can create an API key and a usage plan, and then associate the API key with the usage plan using Pulumi and the AWS provider.
First, you need to define the API, its method, a stage, and a deployment. For the purpose of this example, let's assume you have a Lambda function ready to be invoked by the API Gateway.
After setting up the API with its method and a stage, you will create an API key. Following that, you'll create a usage plan and associate it with the stage of your API. Lastly, you'll link the API key to the usage plan to enforce the desired throttling limits.
Here’s a Pulumi TypeScript program that does all of this:
import * as aws from "@pulumi/aws"; // Create an API Gateway resource const api = new aws.apigateway.RestApi("myApi", { description: "This is my API for demonstration purposes", }); // Create a Lambda invocation permission for the API Gateway // Replace 'myLambdaFunctionArn' with your actual Lambda function ARN const lambdaPermission = new aws.lambda.Permission("myLambdaPermission", { action: "lambda:InvokeFunction", function: "myLambdaFunctionArn", principal: "apigateway.amazonaws.com", // Source ARN for the API Gateway to invoke the Lambda function sourceArn: api.executionArn.apply(executionArn => `${executionArn}/*/*/*`), }); // Create a resource within the API to map to a Lambda function const resource = new aws.apigateway.Resource("myResource", { restApi: api.id, parentId: api.rootResourceId, pathPart: "my-resource", }); // Define a GET method for the above resource, linking to Lambda const method = new aws.apigateway.Method("myMethod", { restApi: api.id, resourceId: resource.id, httpMethod: "GET", authorization: "NONE", }); // Deploy the API gateway with a stage const deployment = new aws.apigateway.Deployment("myDeployment", { restApi: api.id, // In production, you may want to use a dynamic value for the stageName stageName: "v1", // Associate the GET method for deployment triggers: { redeployment: JSON.stringify({ method: method.httpMethod, resource: resource.pathPart, }), }, }); // API Key creation const apiKey = new aws.apigateway.ApiKey("myApiKey", { description: "API Key for access to my API", enabled: true, }); // Usage Plan creation const usagePlan = new aws.apigateway.UsagePlan("myUsagePlan", { name: "BasicUsage", description: "Basic usage with a rate limit and burst capacity", apiStages: [{ apiId: api.id, stage: deployment.stageName, }], throttle: { // Define the rate limit (average requests per second) and burst capacity rateLimit: 10, burstLimit: 20, }, quota: { // Define the maximum number of requests within a given time period (in this case a week) limit: 1000, period: "WEEK", }, }); // Associate API Key with the Usage Plan const usagePlanKey = new aws.apigateway.UsagePlanKey("myUsagePlanKey", { keyId: apiKey.id, keyType: "API_KEY", usagePlanId: usagePlan.id, }); // The URL endpoint of our API Gateway export const endpoint = deployment.invokeUrl.apply(iu => `${iu}v1/`);
In the code above:
- We create an API gateway and a resource within it.
- We define a method (
GET
) for our resource, pointing to a placeholder Lambda function (you'll replace it with your actual Lambda ARN). - We deploy our API using the
aws.apigateway.Deployment
resource. - An API key is created with
aws.apigateway.ApiKey
. - We define our throttling with a
usagePlan
where we set a rate limit and a quota on how many requests can be made over a period. - Finally, we associate our API key with the usage plan using
aws.apigateway.UsagePlanKey
.
Please note that the properties of the
aws.apigateway.UsagePlan
andaws.apigateway.ApiKey
including names, descriptions, throttling limits, and quotas can be tailored to meet your specific requirements.Lastly, we export the
endpoint
, which represents the URL of the deployed API Gateway stage where the API is accessible. You can distribute the API key to your users, who must include it in their requests to access the API at this endpoint.Remember, this is a basic setup intended for learning purposes. In a production environment, consider aspects like secret management, environment-specific configurations, and robust error handling.