API Gateway stage without API Gateway usage plan associated This product is not supported for your selected
Datadog site . (
).
Id: terraform-aws-api-gateway-stage-without-api-gateway-usage-plan-associated
Provider: AWS
Platform: Terraform
Severity: Low
Category: Resource Management
Learn More Description API Gateway stages should always be associated with an API Gateway UsagePlan, which enforces throttling and quota limits for clients accessing your APIs. Without a defined aws_api_gateway_usage_plan resource and its association via the api_stages block, as shown below, the API stage can be accessed without usage restrictions, leading to potential misuse, abuse, or denial of service due to unlimited traffic.
resource "aws_api_gateway_stage" "example" {
deployment_id = "some deployment id"
rest_api_id = "some rest api id"
stage_name = "development"
}
Configuring a UsagePlan, such as the one in the example below, helps mitigate these risks by controlling consumption through quotas and throttling, protecting backend resources and maintaining predictable API performance.
resource "aws_api_gateway_usage_plan" "example" {
name = "my-usage-plan"
description = "usage plan description"
api_stages {
api_id = "some rest api id"
stage = "development"
}
}
Compliant Code Examples resource "aws_api_gateway_stage" "negative1" {
deployment_id = "some deployment id"
rest_api_id = "rest_api_1"
stage_name = "development"
}
resource "aws_api_gateway_usage_plan" "negative2" {
name = "my-usage-plan"
description = "my description"
product_code = "MYCODE"
api_stages {
api_id = "rest_api_1"
stage = "development"
}
}
resource "aws_api_gateway_rest_api" "api_a" {
name = "api-a"
}
resource "aws_api_gateway_deployment" "api_a" {
rest_api_id = aws_api_gateway_rest_api . api_a . id
}
resource "aws_api_gateway_stage" "api_a" {
stage_name = "prod"
rest_api_id = aws_api_gateway_rest_api . api_a . id
deployment_id = aws_api_gateway_deployment . api_a . id
}
resource "aws_api_gateway_usage_plan" "api_a" {
name = "api-a-usage-plan"
api_stages {
api_id = aws_api_gateway_rest_api . api_a . id
stage = "prod"
}
}
resource "aws_api_gateway_rest_api" "api_b" {
name = "api-b"
}
resource "aws_api_gateway_deployment" "api_b" {
rest_api_id = aws_api_gateway_rest_api . api_b . id
}
resource "aws_api_gateway_stage" "api_b" {
stage_name = "prod"
rest_api_id = aws_api_gateway_rest_api . api_b . id
deployment_id = aws_api_gateway_deployment . api_b . id
}
resource "aws_api_gateway_usage_plan" "api_b" {
name = "api-b-usage-plan"
api_stages {
api_id = aws_api_gateway_rest_api . api_b . id
stage = "prod"
}
}
Non-Compliant Code Examples resource "aws_api_gateway_stage" "positive1" {
rest_api_id = "some deployment id"
deployment_id = "some rest api id"
stage_name = "some name"
tags {
project = "ProjectName"
}
}
resource "aws_api_gateway_stage" "positive2" {
deployment_id = "some deployment id"
rest_api_id = "some rest api id"
stage_name = "development"
}
resource "aws_api_gateway_usage_plan" "positive3" {
name = "my-usage-plan"
description = "my description"
product_code = "MYCODE"
api_stages {
api_id = "another id"
stage = "development"
}
}
resource "aws_api_gateway_rest_api" "api" {
name = "example"
}
resource "aws_api_gateway_deployment" "example" {
rest_api_id = aws_api_gateway_rest_api . api . id
}
resource "aws_api_gateway_stage" "example" {
stage_name = "positive2-stage"
rest_api_id = aws_api_gateway_rest_api . api . id
deployment_id = aws_api_gateway_deployment . example . id
}
resource "aws_api_gateway_rest_api" "protected_api" {
name = "protected-api"
}
resource "aws_api_gateway_deployment" "protected" {
rest_api_id = aws_api_gateway_rest_api . protected_api . id
}
resource "aws_api_gateway_stage" "protected" {
stage_name = "prod"
rest_api_id = aws_api_gateway_rest_api . protected_api . id
deployment_id = aws_api_gateway_deployment . protected . id
}
resource "aws_api_gateway_usage_plan" "protected" {
name = "protected-usage-plan"
api_stages {
api_id = aws_api_gateway_rest_api . protected_api . id
stage = "prod"
}
}
resource "aws_api_gateway_rest_api" "unprotected_api" {
name = "unprotected-api"
}
resource "aws_api_gateway_deployment" "unprotected" {
rest_api_id = aws_api_gateway_rest_api . unprotected_api . id
}
resource "aws_api_gateway_stage" "unprotected" {
stage_name = "prod"
rest_api_id = aws_api_gateway_rest_api . unprotected_api . id
deployment_id = aws_api_gateway_deployment . unprotected . id
}