I’m using terraform with AWS provider to create an API Gateway. Everything seems to be fine except for the CORS settings. I’m also using OpenAPI for the configuration.
My "end user" problem is that my API call to my back end is returning 404 not found because it’s making an OPTIONS request first. Enabling CORS settings in API Gateway handles CORS for you and also automatically returns the correct response for the OPTIONS request. However, CORS settings are not being enabled. I believe they should be due to the x-amazon-apigateway-cors section.
Here is my OpenAPI file:
openapi: 3.0.1
info:
title: App API
description: App API
version: 0.1.0
paths:
'/requisitions':
post:
operationId: createRequisition
summary: Create requisition
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- institutionId
properties:
institutionId:
type: string
responses:
'200':
description: 200 response
content:
application/json:
schema:
$ref: '#/components/schemas/Requisition'
'401':
$ref: '#/components/responses/Unauthenticated'
default:
$ref: '#/components/responses/Error'
x-amazon-apigateway-integration:
type: AWS_PROXY
httpMethod: POST
uri: '${gocardless_function_arn}'
payloadFormatVersion: 2.0
security:
- cognito-jwt: []
x-amazon-apigateway-cors:
allowOrigins:
- '*'
allowMethods:
- GET
- OPTIONS
- POST
allowHeaders:
- x-amzm-header
- x-apigateway-header
- x-api-key
- authorization
- x-amz-date
- content-type
components:
schemas:
AnyValue:
nullable: true
description: Can be any value - null, string, number, boolean, array or object.
Requisition:
type: object
properties:
id:
type: string
nullable: true
Error:
type: object
required:
- status
- statusCode
- error
properties:
status:
type: string
statusCode:
type: integer
requestId:
type: string
documentationUrl:
type: string
error:
type: object
required:
- code
- message
- timestamp
properties:
code:
type: string
message:
type: string
details:
$ref: '#/components/schemas/AnyValue'
timestamp:
type: string
path:
type: string
suggestion:
type: string
securitySchemes:
cognito-jwt:
type: oauth2
flows:
authorizationCode:
authorizationUrl: 'https://cognito-idp.eu-west-2.amazonaws.com/'
tokenUrl: ''
scopes: {}
x-amazon-apigateway-authorizer:
type: jwt
jwtConfiguration:
issuer: 'https://cognito-idp.eu-west-2.amazonaws.com/${cognito_user_pool_id}'
audience:
- '${cognito_app_client_id}'
identitySource: '$request.header.Authorization'
responses:
Unauthenticated:
description: Unauthenticated
headers:
www-authenticate:
schema:
type: string
content:
application/json:
schema:
type: object
required:
- message
properties:
message:
type: string
Error:
description: Error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
And here is the relevant part of my terraform:
resource "aws_apigatewayv2_api" "api_gateway" {
name = "API Gateway"
version = "0.1.0"
protocol_type = "HTTP"
description = "API gateway"
body = templatefile("${path.module}/files/api-gateway-openapi.yaml", {
gocardless_function_arn = module.gocardless_create_requisition_lambda.lambda_function_arn,
cognito_user_pool_id = aws_cognito_user_pool.pool.id,
cognito_app_client_id = aws_cognito_user_pool_client.client.id,
region = var.region
})
}
resource "aws_apigatewayv2_deployment" "api_gateway_deployment" {
api_id = aws_apigatewayv2_api.api_gateway.id
description = "API Gateway deployment"
triggers = {
redeployment = sha1(join(
",", tolist([
templatefile("${path.module}/files/api-gateway-openapi.yaml", {
gocardless_function_arn = module.gocardless_create_requisition_lambda.lambda_function_arn,
cognito_user_pool_id = aws_cognito_user_pool.pool.id,
cognito_app_client_id = aws_cognito_user_pool_client.client.id,
region = var.region
}),
jsonencode(aws_apigatewayv2_stage.api_gateway_default_stage)
])
))
}
}
resource "aws_apigatewayv2_stage" "api_gateway_default_stage" {
api_id = aws_apigatewayv2_api.api_gateway.id
name = "default"
auto_deploy = true
default_route_settings {
throttling_rate_limit = 10
throttling_burst_limit = 10
}
}
I tried enabling CORS manually through "ClickOps" in the AWS console. The request from my front end immediately started working (OPTIONS, followed by POST).
I’m expecting the x-amazon-apigateway-cors (https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-swagger-extensions-cors-configuration.html) section to already be enabling these CORS options without me having to do them manually. By doing them manually, they also get overriden every time I re-run terraform apply
.
What should I be change in the OpenAPI file to enable the CORS configuration in API GW?
2
Answers
After looking around for a few more hours, I luckily stumbled across a method that works.
Unless I'm doing something very wrong, the x-amazon-apigateway-cors extension wasn't working.
What worked was adding additional options to the terraform code. My terraform code now looks like this, with the property "cors_configuration" added:
That applies the CORS configuration correctly on the API GW and automatically makes the OPTIONS requests work.
The idea you need to add MOCK integration for OPTIONS. I have written a module for applying CORS to API Gateway and you can use it and attach to your API Gateway resource. main.tf will be.
and Variables.tf file will be
output.tf
then you can use this module