Home

Awesome

AWS API Gateway v2 (HTTP/Websocket) Terraform module

Terraform module which creates API Gateway v2 resources with HTTP/Websocket capabilities.

This Terraform module is part of serverless.tf framework, which aims to simplify all operations when working with the serverless in Terraform.

Usage

HTTP API Gateway

module "api_gateway" {
  source = "terraform-aws-modules/apigateway-v2/aws"

  name          = "dev-http"
  description   = "My awesome HTTP API Gateway"
  protocol_type = "HTTP"

  cors_configuration = {
    allow_headers = ["content-type", "x-amz-date", "authorization", "x-api-key", "x-amz-security-token", "x-amz-user-agent"]
    allow_methods = ["*"]
    allow_origins = ["*"]
  }

  # Custom domain
  domain_name = "terraform-aws-modules.modules.tf"

  # Access logs
  stage_access_log_settings = {
    create_log_group            = true
    log_group_retention_in_days = 7
    format = jsonencode({
      context = {
        domainName              = "$context.domainName"
        integrationErrorMessage = "$context.integrationErrorMessage"
        protocol                = "$context.protocol"
        requestId               = "$context.requestId"
        requestTime             = "$context.requestTime"
        responseLength          = "$context.responseLength"
        routeKey                = "$context.routeKey"
        stage                   = "$context.stage"
        status                  = "$context.status"
        error = {
          message      = "$context.error.message"
          responseType = "$context.error.responseType"
        }
        identity = {
          sourceIP = "$context.identity.sourceIp"
        }
        integration = {
          error             = "$context.integration.error"
          integrationStatus = "$context.integration.integrationStatus"
        }
      }
    })
  }

  # Authorizer(s)
  authorizers = {
    "azure" = {
      authorizer_type  = "JWT"
      identity_sources = ["$request.header.Authorization"]
      name             = "azure-auth"
      jwt_configuration = {
        audience         = ["d6a38afd-45d6-4874-d1aa-3c5c558aqcc2"]
        issuer           = "https://sts.windows.net/aaee026e-8f37-410e-8869-72d9154873e4/"
      }
    }
  }

  # Routes & Integration(s)
  routes = {
    "POST /" = {
      integration = {
        uri                    = "arn:aws:lambda:eu-west-1:052235179155:function:my-function"
        payload_format_version = "2.0"
        timeout_milliseconds   = 12000
      }
    }

    "GET /some-route-with-authorizer" = {
      authorizer_key = "azure"

      integration = {
        type = "HTTP_PROXY"
        uri  = "some url"
      }
    }

    "$default" = {
      integration = {
        uri = "arn:aws:lambda:eu-west-1:052235179155:function:my-default-function"
      }
    }
  }

  tags = {
    Environment = "dev"
    Terraform   = "true"
  }
}

Multiple Subdomains

API Gateway v2 supports wildcard custom domains which allow users to map multiple subdomains to the same API Gateway. This is useful when you have multiple customers and you want to provide them with a custom domain for their API endpoint and possibly use that for header based routing/rules.

module "api_gateway" {
  source = "terraform-aws-modules/apigateway-v2/aws"

  ...
  domain_name = "*.mydomain.com"
  subdomains  = ["customer1", "customer2"]
  ...
}

This will create records that allow users to access the API Gateway using the following subdomains:

Specific Hosted Zone

If you want to create the domain name in a specific hosted zone, you can use the hosted_zone_name input parameter:

module "api_gateway" {
  source = "terraform-aws-modules/apigateway-v2/aws"

  ...
  hosted_zone_name = "api.mydomain.com"
  domain_name      = "prod.api.mydomain.com"
  ...
}

Conditional Creation

The following values are provided to toggle on/off creation of the associated resources as desired:

module "api_gateway" {
  source = "terraform-aws-modules/apigateway-v2/aws"

  # Disable creation of the API and all resources
  create = false

  # Disable creation of the domain name and API mapping
  create_domain_name = false

  # Disable creation of Route53 alias record(s) for the custom domain
  create_domain_records = false

  # Disable creation of the ACM certificate for the custom domain
  create_certificate = false

  # Disable creation of the routes and integrations
  create_routes_and_integrations = false

  # Disable creation of the stage
  create_stage = false

  # ... omitted
}

Examples

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

Requirements

NameVersion
<a name="requirement_terraform"></a> terraform>= 1.3
<a name="requirement_aws"></a> aws>= 5.37

Providers

NameVersion
<a name="provider_aws"></a> aws>= 5.37

Modules

NameSourceVersion
<a name="module_acm"></a> acmterraform-aws-modules/acm/aws5.0.1

Resources

NameType
aws_apigatewayv2_api.thisresource
aws_apigatewayv2_api_mapping.thisresource
aws_apigatewayv2_authorizer.thisresource
aws_apigatewayv2_deployment.thisresource
aws_apigatewayv2_domain_name.thisresource
aws_apigatewayv2_integration.thisresource
aws_apigatewayv2_integration_response.thisresource
aws_apigatewayv2_route.thisresource
aws_apigatewayv2_route_response.thisresource
aws_apigatewayv2_stage.thisresource
aws_apigatewayv2_vpc_link.thisresource
aws_cloudwatch_log_group.thisresource
aws_route53_record.thisresource
aws_route53_zone.thisdata source

Inputs

NameDescriptionTypeDefaultRequired
<a name="input_api_key_selection_expression"></a> api_key_selection_expressionAn API key selection expression. Valid values: $context.authorizer.usageIdentifierKey, $request.header.x-api-key. Defaults to $request.header.x-api-key. Applicable for WebSocket APIsstringnullno
<a name="input_api_mapping_key"></a> api_mapping_keyThe API mapping keystringnullno
<a name="input_api_version"></a> api_versionA version identifier for the API. Must be between 1 and 64 characters in lengthstringnullno
<a name="input_authorizers"></a> authorizersMap of API gateway authorizers to create<pre>map(object({<br> authorizer_credentials_arn = optional(string)<br> authorizer_payload_format_version = optional(string)<br> authorizer_result_ttl_in_seconds = optional(number)<br> authorizer_type = optional(string, "REQUEST")<br> authorizer_uri = optional(string)<br> enable_simple_responses = optional(bool)<br> identity_sources = optional(list(string))<br> jwt_configuration = optional(object({<br> audience = optional(list(string))<br> issuer = optional(string)<br> }))<br> name = optional(string)<br> }))</pre>{}no
<a name="input_body"></a> bodyAn OpenAPI specification that defines the set of routes and integrations to create as part of the HTTP APIs. Supported only for HTTP APIsstringnullno
<a name="input_cors_configuration"></a> cors_configurationThe cross-origin resource sharing (CORS) configuration. Applicable for HTTP APIs<pre>object({<br> allow_credentials = optional(bool)<br> allow_headers = optional(list(string))<br> allow_methods = optional(list(string))<br> allow_origins = optional(list(string))<br> expose_headers = optional(list(string), [])<br> max_age = optional(number)<br> })</pre>nullno
<a name="input_create"></a> createControls if resources should be createdbooltrueno
<a name="input_create_certificate"></a> create_certificateWhether to create a certificate for the domainbooltrueno
<a name="input_create_domain_name"></a> create_domain_nameWhether to create API domain name resourcebooltrueno
<a name="input_create_domain_records"></a> create_domain_recordsWhether to create Route53 records for the domain namebooltrueno
<a name="input_create_routes_and_integrations"></a> create_routes_and_integrationsWhether to create routes and integrations resourcesbooltrueno
<a name="input_create_stage"></a> create_stageWhether to create default stagebooltrueno
<a name="input_credentials_arn"></a> credentials_arnPart of quick create. Specifies any credentials required for the integration. Applicable for HTTP APIsstringnullno
<a name="input_deploy_stage"></a> deploy_stageWhether to deploy the stage. HTTP APIs are auto-deployed by defaultbooltrueno
<a name="input_description"></a> descriptionThe description of the API. Must be less than or equal to 1024 characters in lengthstringnullno
<a name="input_disable_execute_api_endpoint"></a> disable_execute_api_endpointWhether clients can invoke the API by using the default execute-api endpoint. By default, clients can invoke the API with the default {api_id}.execute-api.{region}.amazonaws.com endpoint. To require that clients use a custom domain name to invoke the API, disable the default endpointboolnullno
<a name="input_domain_name"></a> domain_nameThe domain name to use for API gatewaystring""no
<a name="input_domain_name_certificate_arn"></a> domain_name_certificate_arnThe ARN of an AWS-managed certificate that will be used by the endpoint for the domain name. AWS Certificate Manager is the only supported sourcestringnullno
<a name="input_domain_name_ownership_verification_certificate_arn"></a> domain_name_ownership_verification_certificate_arnARN of the AWS-issued certificate used to validate custom domain ownership (when certificate_arn is issued via an ACM Private CA or mutual_tls_authentication is configured with an ACM-imported certificate.)stringnullno
<a name="input_fail_on_warnings"></a> fail_on_warningsWhether warnings should return an error while API Gateway is creating or updating the resource using an OpenAPI specification. Defaults to false. Applicable for HTTP APIsboolnullno
<a name="input_hosted_zone_name"></a> hosted_zone_nameOptional domain name of the Hosted Zone where the domain should be createdstringnullno
<a name="input_mutual_tls_authentication"></a> mutual_tls_authenticationThe mutual TLS authentication configuration for the domain namemap(string){}no
<a name="input_name"></a> nameThe name of the API. Must be less than or equal to 128 characters in lengthstring""no
<a name="input_protocol_type"></a> protocol_typeThe API protocol. Valid values: HTTP, WEBSOCKETstring"HTTP"no
<a name="input_route_key"></a> route_keyPart of quick create. Specifies any route key. Applicable for HTTP APIsstringnullno
<a name="input_route_selection_expression"></a> route_selection_expressionThe route selection expression for the API. Defaults to $request.method $request.pathstringnullno
<a name="input_routes"></a> routesMap of API gateway routes with integrations<pre>map(object({<br> # Route<br> authorizer_key = optional(string)<br> api_key_required = optional(bool)<br> authorization_scopes = optional(list(string), [])<br> authorization_type = optional(string)<br> authorizer_id = optional(string)<br> model_selection_expression = optional(string)<br> operation_name = optional(string)<br> request_models = optional(map(string), {})<br> request_parameter = optional(object({<br> request_parameter_key = optional(string)<br> required = optional(bool, false)<br> }), {})<br> route_response_selection_expression = optional(string)<br><br> # Route settings<br> data_trace_enabled = optional(bool)<br> detailed_metrics_enabled = optional(bool)<br> logging_level = optional(string)<br> throttling_burst_limit = optional(number)<br> throttling_rate_limit = optional(number)<br><br> # Stage - Route response<br> route_response = optional(object({<br> create = optional(bool, false)<br> model_selection_expression = optional(string)<br> response_models = optional(map(string))<br> route_response_key = optional(string, "$default")<br> }), {})<br><br> # Integration<br> integration = object({<br> connection_id = optional(string)<br> vpc_link_key = optional(string)<br> connection_type = optional(string)<br> content_handling_strategy = optional(string)<br> credentials_arn = optional(string)<br> description = optional(string)<br> method = optional(string)<br> subtype = optional(string)<br> type = optional(string, "AWS_PROXY")<br> uri = optional(string)<br> passthrough_behavior = optional(string)<br> payload_format_version = optional(string)<br> request_parameters = optional(map(string), {})<br> request_templates = optional(map(string), {})<br> response_parameters = optional(list(object({<br> mappings = map(string)<br> status_code = string<br> })))<br> template_selection_expression = optional(string)<br> timeout_milliseconds = optional(number)<br> tls_config = optional(object({<br> server_name_to_verify = optional(string)<br> }))<br><br> # Integration Response<br> response = optional(object({<br> content_handling_strategy = optional(string)<br> integration_response_key = optional(string)<br> response_templates = optional(map(string))<br> template_selection_expression = optional(string)<br> }), {})<br> })<br> }))</pre>{}no
<a name="input_stage_access_log_settings"></a> stage_access_log_settingsSettings for logging access in this stage. Use the aws_api_gateway_account resource to configure permissions for CloudWatch Logging<pre>object({<br> create_log_group = optional(bool, true)<br> destination_arn = optional(string)<br> format = optional(string)<br> log_group_name = optional(string)<br> log_group_retention_in_days = optional(number, 30)<br> log_group_kms_key_id = optional(string)<br> log_group_skip_destroy = optional(bool)<br> log_group_class = optional(string)<br> log_group_tags = optional(map(string), {})<br> })</pre>{}no
<a name="input_stage_client_certificate_id"></a> stage_client_certificate_idThe identifier of a client certificate for the stage. Use the aws_api_gateway_client_certificate resource to configure a client certificate. Supported only for WebSocket APIsstringnullno
<a name="input_stage_default_route_settings"></a> stage_default_route_settingsThe default route settings for the stage<pre>object({<br> data_trace_enabled = optional(bool, true)<br> detailed_metrics_enabled = optional(bool, true)<br> logging_level = optional(string)<br> throttling_burst_limit = optional(number, 500)<br> throttling_rate_limit = optional(number, 1000)<br> })</pre>{}no
<a name="input_stage_description"></a> stage_descriptionThe description for the stage. Must be less than or equal to 1024 characters in lengthstringnullno
<a name="input_stage_name"></a> stage_nameThe name of the stage. Must be between 1 and 128 characters in lengthstring"$default"no
<a name="input_stage_tags"></a> stage_tagsA mapping of tags to assign to the stage resourcemap(string){}no
<a name="input_stage_variables"></a> stage_variablesA map that defines the stage variables for the stagemap(string){}no
<a name="input_subdomain_record_types"></a> subdomain_record_typesA list of record types to create for the subdomain(s)list(string)<pre>[<br> "A",<br> "AAAA"<br>]</pre>no
<a name="input_subdomains"></a> subdomainsAn optional list of subdomains to use for API gatewaylist(string)[]no
<a name="input_tags"></a> tagsA mapping of tags to assign to API gateway resourcesmap(string){}no
<a name="input_target"></a> targetPart of quick create. Quick create produces an API with an integration, a default catch-all route, and a default stage which is configured to automatically deploy changes. For HTTP integrations, specify a fully qualified URL. For Lambda integrations, specify a function ARN. The type of the integration will be HTTP_PROXY or AWS_PROXY, respectively. Applicable for HTTP APIsstringnullno
<a name="input_vpc_link_tags"></a> vpc_link_tagsA map of tags to add to the VPC Links createdmap(string){}no
<a name="input_vpc_links"></a> vpc_linksMap of VPC Link definitions to create<pre>map(object({<br> name = optional(string)<br> security_group_ids = optional(list(string))<br> subnet_ids = optional(list(string))<br> tags = optional(map(string), {})<br> }))</pre>{}no

Outputs

NameDescription
<a name="output_acm_certificate_arn"></a> acm_certificate_arnThe ARN of the certificate
<a name="output_api_arn"></a> api_arnThe ARN of the API
<a name="output_api_endpoint"></a> api_endpointURI of the API, of the form https://{api-id}.execute-api.{region}.amazonaws.com for HTTP APIs and wss://{api-id}.execute-api.{region}.amazonaws.com for WebSocket APIs
<a name="output_api_execution_arn"></a> api_execution_arnThe ARN prefix to be used in an aws_lambda_permission's source_arn attribute or in an aws_iam_policy to authorize access to the @connections API
<a name="output_api_id"></a> api_idThe API identifier
<a name="output_authorizers"></a> authorizersMap of API Gateway Authorizer(s) created and their attributes
<a name="output_domain_name_api_mapping_selection_expression"></a> domain_name_api_mapping_selection_expressionThe API mapping selection expression for the domain name
<a name="output_domain_name_arn"></a> domain_name_arnThe ARN of the domain name
<a name="output_domain_name_configuration"></a> domain_name_configurationThe domain name configuration
<a name="output_domain_name_hosted_zone_id"></a> domain_name_hosted_zone_idThe Amazon Route 53 Hosted Zone ID of the endpoint
<a name="output_domain_name_id"></a> domain_name_idThe domain name identifier
<a name="output_domain_name_target_domain_name"></a> domain_name_target_domain_nameThe target domain name
<a name="output_integrations"></a> integrationsMap of the integrations created and their attributes
<a name="output_routes"></a> routesMap of the routes created and their attributes
<a name="output_stage_access_logs_cloudwatch_log_group_arn"></a> stage_access_logs_cloudwatch_log_group_arnArn of cloudwatch log group created
<a name="output_stage_access_logs_cloudwatch_log_group_name"></a> stage_access_logs_cloudwatch_log_group_nameName of cloudwatch log group created
<a name="output_stage_arn"></a> stage_arnThe stage ARN
<a name="output_stage_domain_name"></a> stage_domain_nameDomain name of the stage (useful for CloudFront distribution)
<a name="output_stage_execution_arn"></a> stage_execution_arnThe ARN prefix to be used in an aws_lambda_permission's source_arn attribute or in an aws_iam_policy to authorize access to the @connections API
<a name="output_stage_id"></a> stage_idThe stage identifier
<a name="output_stage_invoke_url"></a> stage_invoke_urlThe URL to invoke the API pointing to the stage
<a name="output_vpc_links"></a> vpc_linksMap of VPC links created and their attributes
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

Authors

Module managed by Anton Babenko. Check out serverless.tf to learn more about doing serverless with Terraform.

Please reach out to Betajob if you are looking for commercial support for your Terraform, AWS, or serverless project.

License

Apache 2 Licensed. See LICENSE for full details.