11

I want to associate a WAFv2 Web ACL to an API GatewayV2 HTTP stage.

Following the terraform docs, I tried this:

resource "aws_wafv2_web_acl_association" "this" {
  resource_arn = aws_apigatewayv2_stage.this.arn
  web_acl_arn  = aws_wafv2_web_acl.this.arn
}

However, this was not accepted, with the error being:

Error: WAFInvalidParameterException: Error reason: The ARN isn’t valid. A valid ARN begins with arn: and includes other information separated by colons or slashes., field: RESOURCE_ARN, parameter: arn:aws:apigateway:eu-west-2::/apis/abcd1234/stages/my-stage

From the AWS docs, the pattern for the ARN is:

arn:aws:apigateway:region::/restapis/api-id/stages/stage-name

However, only the ARNs of the old API Gateway uses "restapis" in its ARN. The v2 gateways uses just "apis.

  1. Is this why the ARN is invalid?
  2. How can I associate a AWS API GatewayV2 HTTP Stage to an AWS WAFv2 Web ACL?

As requested, here is code for a gateway:

resource "aws_apigatewayv2_api" "this" {
  name          = "example-http-api"
  protocol_type = "HTTP"
}

resource "aws_lambda_function" "this" {
  filename      = "example.zip"
  function_name = "Example"
  role          = var.lambda_arn
  handler       = "index.handler"
  runtime       = "nodejs10.x"
}

resource "aws_apigatewayv2_integration" "get" {
  api_id             = aws_apigatewayv2_api.this.id
  integration_type   = "AWS_PROXY"
  integration_method = "GET"
  integration_uri    = aws_lambda_function.this.invoke_arn
}

resource "aws_apigatewayv2_route" "get" {
  api_id    = aws_apigatewayv2_api.this.id
  route_key = "$default"
  target    = "path/${aws_apigatewayv2_integration.get.id}"
}

resource "aws_apigatewayv2_stage" "this" {
  api_id = aws_apigatewayv2_api.this.id
  name   = "example-stage"
}

And code for a Web-ACL:

 resource "aws_wafv2_web_acl" "this" {
  scope       = "REGIONAL"

  default_action {
    allow {}
  }

  rule {
    name     = "common-rule-set"
    priority = 1

    override_action {
      none {}
    }

    statement {
      managed_rule_group_statement {
        name        = "AWSManagedRulesCommonRuleSet"
        vendor_name = "AWS"
      }
    }

    visibility_config {
      cloudwatch_metrics_enabled = false
      metric_name                = "common-rule-set"
      sampled_requests_enabled   = false
    }
  }
  
  visibility_config {
    cloudwatch_metrics_enabled = false
    metric_name                = "web-acl"
    sampled_requests_enabled   = false
  }
}
RKZ
  • 111
  • 1
  • 4

2 Answers2

14

HTTP API doesn't have WAF support:

The API V1 namespace represents REST APIs and API V2 represents WebSocket APIs and the new HTTP APIs. Source: https://aws.amazon.com/blogs/compute/announcing-http-apis-for-amazon-api-gateway/

And

Currently, we do not support WAF for HTTP APIs. We have a backlog item for this request. Thank you for reaching out. https://forums.aws.amazon.com/thread.jspa?messageID=942361

Andriy Kharchuk
  • 1,165
  • 1
  • 13
  • 25
2

I think there's a mistake in your code. For the API Gateway stage, you are using this block:

resource "aws_apigatewayv2_stage" "example" {
  api_id = aws_apigatewayv2_api.this.id
  name   = "example-stage"
}

while in the WAF association you are using:

resource "aws_wafv2_web_acl_association" "this" {
  resource_arn = aws_apigatewayv2_stage.this.arn
  web_acl_arn  = aws_wafv2_web_acl.this.arn
}

Change the resource_arn = aws_apigatewayv2_stage.this.arn to resource_arn = aws_apigatewayv2_stage.example.arn. You named the API Gateway stage resource example but you were trying to access attributes of a resource named this, which doesn't exist.

Marko E
  • 13,362
  • 2
  • 19
  • 28
  • Sorry, I was quickly making some changes since you wanted more code. The error I get is not due to a terraform source code error (I'll correct the terraform in the question), but as specified, that the ARN is invalid (WAFInvalidParameterException). – RKZ Aug 09 '20 at 21:13