Search code examples
amazon-web-servicesterraformamazon-elastic-beanstalkaws-api-gatewayterraform-provider-aws

API Gateway integration to an elastic beanstalk app with a VPC_LINK fails with AWS ARN for integration must contain path or action


I have an elastic beanstalk(EB) app setup in a private subnet in my current VPC. I want to have an API REST Gateway that will forward the traffic to elastic beanstalk(EB) app via an VPC_LINK as lambda is too expensive and all i need is proxy the traffic.

NLB targeting EB ALB

module "nlb" {
  source  = "terraform-aws-modules/alb/aws"
  version = "~> 6.0"
    
  name = "${var.eb_env_name}-${var.environment}-internal-nlb"
    
  load_balancer_type = "network"
  internal           = true
  
  vpc_id  = module.vpc.vpc_id
  subnets = module.vpc.private_subnets
  access_logs = {
    bucket = "${var.eb_env_name}-${var.environment}-internal-nlb-logs"
  }
    
  target_groups = [
    {
      name             = "${var.eb_env_name}-${var.environment}-internal-tg"
      backend_protocol = "TCP"
      backend_port     = 80
      target_type      = "alb"
      health_check = {
        enabled             = true
        interval            = 30
        path                = "/health"
        port                = "traffic-port"
        healthy_threshold   = 3
        unhealthy_threshold = 3
        timeout             = 6
      }
      targets = [
        {
          target_id = aws_elastic_beanstalk_environment.eb_env.load_balancers[0]
          port      = 80
        }
      ]
    }
  ]
    
  http_tcp_listeners = [
    {
       port               = 80
       protocol           = "TCP"
       target_group_index = 0
    }
  ]
}

VPC LINK

resource "aws_api_gateway_vpc_link" "eb_vpc_link" {
  name        = "${var.eb_app_name}-vpc-link"
  target_arns = [module.nlb.lb_arn]
}

API Gateway integration

resource "aws_api_gateway_integration" "rest_api_get_destinationId_method_integration" {
  rest_api_id = aws_api_gateway_rest_api.rest_api.id
  resource_id = aws_api_gateway_resource.rest_api_destinationId_resource.id
  http_method = aws_api_gateway_method.rest_api_destination_get_method.http_method
  integration_http_method = "POST"
  type                    = "AWS_PROXY"
  uri                     = module.nlb.http_tcp_listener_arns[0]
  connection_type         = "VPC_LINK"
  connection_id           = aws_api_gateway_vpc_link.eb_vpc_link.id
 //request_tempates is required to explicitly set the statusCode to an integer value of 200
  request_templates = {
    "application/json" = jsonencode({
       statusCode = 200
    })
  }
    
  depends_on = [
    aws_api_gateway_resource.rest_api_destinationId_resource,
    aws_api_gateway_resource.rest_api_destination_resource, 
    aws_api_gateway_method.rest_api_destination_get_method,
     aws_api_gateway_vpc_link.eb_vpc_link
  ]
}

I keep getting the following error message.

Creating API Gateway Integration: BadRequestException: AWS ARN for integration must contain path or action

The aws_api_gateway_integration above should point to /destination/{destinationId}


Solution

  • As per the CloudFormation documentation, you need to specify the Network Load Balancer DNS name in the uri argument:

    Uri Specifies Uniform Resource Identifier (URI) of the integration endpoint. [...] If connectionType is VPC_LINK specify the Network Load Balancer DNS name. [...]

    So in your case, that would be:

    uri = module.nlb.lb_dns_name
    

    EDIT: As per the comments, the type should be HTTP_PROXY:

    type = "HTTP_PROXY"