Skip to content

VPC Link v2 is not compatible with WebSocket Api Gateway #151

@detomarco

Description

@detomarco

Description

When configuring a WebSocket API (protocol_type = "WEBSOCKET") with a private VPC integration using the vpc_links variable, the module creates an aws_apigatewayv2_vpc_link resource (VPC Link v2). AWS does not support VPC Link v2 for
WebSocket APIs — only for HTTP APIs. This results in a BadRequestException at apply time when the integration is created.

The module currently has no way to wire a WebSocket integration to a VPC Link v1 (aws_api_gateway_vpc_link, NLB-based), which is the only VPC Link type supported by WebSocket APIs. Setting connection_id directly with a pre-existing
VPC Link v1 ID works as a workaround, but the module provides no managed resource path for it.

Versions

  • Module version [Required]: 6.1.0
  • Provider version(s): hashicorp/aws >= 6.28

Reproduction Code [Required]

module "api_gateway_websocket" {
  source  = "terraform-aws-modules/apigateway-v2/aws"
  version = "6.1.0"                                                                                                                                                                                                                    
 
  api_name      = "my-websocket-api"                                                                                                                                                                                                    
  protocol_type = "WEBSOCKET"
                                                                                                                                                                                                                                        
  route_selection_expression = "$request.body.action"

  routes = {                                                                                                                                                                                                                            
    "$connect" = {
      integration = {                                                                                                                                                                                                                   
        vpc_link_key    = "my_vpc_link"
        connection_type = "VPC_LINK"                                                                                                                                                                                                    
        type            = "HTTP"
        method          = "POST"                                                                                                                                                                                                        
        uri             = "http://my-internal-nlb.example.com/connect"
      }                                                                                                                                                                                                                                 
    }           
  }                                                                                                                                                                                                                                     
                
  # This creates an aws_apigatewayv2_vpc_link (VPC Link v2)                                                                                                                                                                             
  vpc_links = {
    my_vpc_link = {
      name       = "my-websocket-vpc-link"
      target_arn = "arn:aws:elasticloadbalancing:eu-west-1:123456789012:loadbalancer/net/my-nlb/1234567890abcdef"
    }
  }                                                                                                                                                                                                                                  
}               

Running terraform init && terraform apply produces the error below.

Expected behavior

The module should support private VPC integrations for WebSocket APIs. Since AWS does not support VPC Link v2 for WebSocket, the module should offer a way to manage a VPC Link v1 (aws_api_gateway_vpc_link, NLB ARN-based) and wire it
to a WebSocket integration via connection_id.

Proposed addition to the module:

  # New variable                                                                                                                                                                                                                          
  variable "vpc_links_v1" {
    description = "Map of VPC Link v1 (NLB-based) definitions to create. Required for WebSocket API private integrations."                                                                                                                
    type = map(object({                                                                                                                                                                                                                   
      name        = optional(string)                                                                                                                                                                                                      
      target_arns = list(string)                                                                                                                                                                                                          
      tags        = optional(map(string), {})
    }))                                                                                                                                                                                                                                   
    default = {}
  }                                                                                                                                                                                                                                       
                  
  # New resource
  resource "aws_api_gateway_vpc_link" "this" {
    for_each    = { for k, v in var.vpc_links_v1 : k => v if var.create }
    name        = coalesce(each.value.name, each.key)                                                                                                                                                                                     
    target_arns = each.value.target_arns
    tags        = merge(var.tags, try(each.value.tags, {}))                                                                                                                                                                               
  }                                                                                                                                                                                                                                       
   
  # And in the integration logic, extend the try() to also resolve from vpc_links_v1:                                                                                                                                 
                  
  connection_id = try(                                                                                                                                                                                                                    
    aws_apigatewayv2_vpc_link.this[each.value.vpc_link_key].id,
    aws_api_gateway_vpc_link.this[each.value.vpc_link_key].id,                                                                                                                                                                            
    each.value.connection_id
  )                                                                                                                                                                                                                                      

Actual behavior

terraform apply fails with:

  │ Error: creating API Gateway v2 Integration: operation error ApiGatewayV2: CreateIntegration,
  │ https response error StatusCode: 400, RequestID: 81d8369c-238b-467a-82a0-4f291e1cc422,                                                                                                                                                
  │ BadRequestException: VpcLink V2 are not supported for WEBSOCKET Apis. Only Http Apis are supported.                                                                                                                                   

Additional context

AWS has two distinct VPC Link implementations:

  • VPC Link v2 (aws_apigatewayv2_vpc_link) — subnet/security-group based, supported only for HTTP APIs
  • VPC Link v1 (aws_api_gateway_vpc_link) — NLB ARN-based, supported for REST APIs and WebSocket APIs

Despite WebSocket being part of API Gateway v2, it requires the older NLB-based VPC Link for private integrations. The current module only manages VPC Link v2, leaving WebSocket users with no managed path for private integrations —
they must pre-create a VPC Link v1 out-of-band and hardcode its ID via connection_id.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions