This product is not supported for your selected
Datadog site. (
).
Id: a186e82c-1078-4a7b-85d8-579561fde884
Cloud Provider: aws
Framework: Terraform
Severity: Medium
Category: Networking and Firewall
Learn More
Description
This check ensures that AWS API Gateway stages are protected by an associated Web Application Firewall (WAF) using the aws_wafregional_web_acl_association
resource. Without a WAF enabled, exposed API endpoints are left unprotected against common web threats such as SQL injection, cross-site scripting (XSS), and other HTTP-based attacks, increasing the risk of data breaches or service disruption. To secure your API Gateway, associate a WAF Web ACL to your stage, as shown below:
resource "aws_wafregional_web_acl_association" "association" {
resource_arn = aws_api_gateway_stage.negative1.arn
web_acl_id = aws_wafregional_web_acl.foo.id
}
Compliant Code Examples
resource "aws_api_gateway_rest_api" "example" {
body = jsonencode({
openapi = "3.0.1"
info = {
title = "example"
version = "1.0"
}
paths = {
"/path1" = {
get = {
x-amazon-apigateway-integration = {
httpMethod = "GET"
payloadFormatVersion = "1.0"
type = "HTTP_PROXY"
uri = "https://ip-ranges.amazonaws.com/ip-ranges.json"
}
}
}
}
})
name = "example"
}
resource "aws_api_gateway_deployment" "example" {
rest_api_id = aws_api_gateway_rest_api.example.id
triggers = {
redeployment = sha1(jsonencode(aws_api_gateway_rest_api.example.body))
}
lifecycle {
create_before_destroy = true
}
}
resource "aws_api_gateway_stage" "negative2" {
deployment_id = aws_api_gateway_deployment.example.id
rest_api_id = aws_api_gateway_rest_api.example.id
stage_name = "example"
}
resource "aws_wafv2_web_acl" "foo" {
name = "foo"
scope = "REGIONAL"
default_action {
allow {}
}
visibility_config {
cloudwatch_metrics_enabled = false
metric_name = "foo"
sampled_requests_enabled = false
}
}
resource "aws_wafv2_web_acl_association" "association" {
resource_arn = aws_api_gateway_stage.negative2.arn
web_acl_arn = aws_wafv2_web_acl.foo.arn
}
resource "aws_wafregional_ipset" "ipset" {
name = "tfIPSet"
ip_set_descriptor {
type = "IPV4"
value = "192.0.7.0/24"
}
}
resource "aws_wafregional_rule" "foo" {
name = "tfWAFRule"
metric_name = "tfWAFRule"
predicate {
data_id = aws_wafregional_ipset.ipset.id
negated = false
type = "IPMatch"
}
}
resource "aws_wafregional_web_acl" "foo" {
name = "foo"
metric_name = "foo"
default_action {
type = "ALLOW"
}
rule {
action {
type = "BLOCK"
}
priority = 1
rule_id = aws_wafregional_rule.foo.id
}
}
resource "aws_api_gateway_rest_api" "example" {
body = jsonencode({
openapi = "3.0.1"
info = {
title = "example"
version = "1.0"
}
paths = {
"/path1" = {
get = {
x-amazon-apigateway-integration = {
httpMethod = "GET"
payloadFormatVersion = "1.0"
type = "HTTP_PROXY"
uri = "https://ip-ranges.amazonaws.com/ip-ranges.json"
}
}
}
}
})
name = "example"
}
resource "aws_api_gateway_deployment" "example" {
rest_api_id = aws_api_gateway_rest_api.example.id
triggers = {
redeployment = sha1(jsonencode(aws_api_gateway_rest_api.example.body))
}
lifecycle {
create_before_destroy = true
}
}
resource "aws_api_gateway_stage" "negative1" {
deployment_id = aws_api_gateway_deployment.example.id
rest_api_id = aws_api_gateway_rest_api.example.id
stage_name = "example"
}
resource "aws_wafregional_web_acl_association" "association" {
resource_arn = aws_api_gateway_stage.negative1.arn
web_acl_id = aws_wafregional_web_acl.foo.id
}
Non-Compliant Code Examples
resource "aws_wafregional_ipset" "ipset" {
name = "tfIPSet"
ip_set_descriptor {
type = "IPV4"
value = "192.0.7.0/24"
}
}
resource "aws_wafregional_rule" "foo" {
name = "tfWAFRule"
metric_name = "tfWAFRule"
predicate {
data_id = aws_wafregional_ipset.ipset.id
negated = false
type = "IPMatch"
}
}
resource "aws_wafregional_web_acl" "foo" {
name = "foo"
metric_name = "foo"
default_action {
type = "ALLOW"
}
rule {
action {
type = "BLOCK"
}
priority = 1
rule_id = aws_wafregional_rule.foo.id
}
}
resource "aws_api_gateway_rest_api" "example" {
body = jsonencode({
openapi = "3.0.1"
info = {
title = "example"
version = "1.0"
}
paths = {
"/path1" = {
get = {
x-amazon-apigateway-integration = {
httpMethod = "GET"
payloadFormatVersion = "1.0"
type = "HTTP_PROXY"
uri = "https://ip-ranges.amazonaws.com/ip-ranges.json"
}
}
}
}
})
name = "example"
}
resource "aws_api_gateway_deployment" "example" {
rest_api_id = aws_api_gateway_rest_api.example.id
triggers = {
redeployment = sha1(jsonencode(aws_api_gateway_rest_api.example.body))
}
lifecycle {
create_before_destroy = true
}
}
resource "aws_api_gateway_stage" "positive1" {
deployment_id = aws_api_gateway_deployment.example.id
rest_api_id = aws_api_gateway_rest_api.example.id
stage_name = "example"
}
resource "aws_wafregional_web_acl_association" "association" {
resource_arn = aws_api_gateway_stage.positive.arn
web_acl_id = aws_wafregional_web_acl.foo.id
}