Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Associate AWS WAFv2 web acl to ApiGatewayV2

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
  }
}
like image 663
RKZ Avatar asked Aug 07 '20 14:08

RKZ


2 Answers

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

like image 200
Moose on the Loose Avatar answered Sep 28 '22 07:09

Moose on the Loose


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.

like image 44
Marko E Avatar answered Sep 28 '22 09:09

Marko E