This product is not supported for your selected
Datadog site . (
).
Id: terraform-aws-api-gateway-without-waf
Provider: AWS
Platform: 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_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
}
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
}
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
}