【问题标题】:How to enable CORS on AWS with terraform如何使用 terraform 在 AWS 上启用 CORS
【发布时间】:2020-04-30 16:51:54
【问题描述】:

我正在尝试在我的 aws 项目上启用 CORS,该项目由 API GatewayLambda 函数组成。 我正在使用GETOPTIONS 方法创建一个API 网关。 OPTIONS 是一个模拟端点,用于根据 aws documentation 启用 CORS。 有一个 lambda 函数 (aws_lambda_function.app_lambda) 由 GET 方法调用,响应头有:

"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET"

但是,我仍然无法通过 CORS。

resource "aws_api_gateway_rest_api" "rest_api" {
  name        = "appAPIGateway"
  description = "App App App"
}

resource "aws_api_gateway_resource" "rest_api_resource" {
  depends_on = ["aws_api_gateway_rest_api.rest_api"]
  rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}"
  parent_id = "${aws_api_gateway_rest_api.rest_api.root_resource_id}"
  path_part = "playground"
}

resource "aws_api_gateway_method" "opt" {
  rest_api_id   = "${aws_api_gateway_rest_api.rest_api.id}"
  resource_id   = "${aws_api_gateway_resource.rest_api_resource.id}"
  http_method   = "OPTIONS"
  authorization = "NONE"
  api_key_required = true
}

resource "aws_api_gateway_integration" "opt" {
  rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}"
  resource_id = "${aws_api_gateway_resource.rest_api_resource.id}"
  http_method = "${aws_api_gateway_method.opt.http_method}"
  type = "MOCK"
}

resource "aws_api_gateway_integration_response" "opt" {
  rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}"
  resource_id = "${aws_api_gateway_resource.rest_api_resource.id}"
  http_method = "${aws_api_gateway_method.opt.http_method}"
  status_code = 200
  response_parameters = {
    "method.response.header.Access-Control-Allow-Origin" = "'*'",
    "method.response.header.Access-Control-Allow-Headers" = "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Requested-With'",
    "method.response.header.Access-Control-Allow-Methods" = "'GET,OPTIONS,POST,PUT'"
  }
  depends_on = ["aws_api_gateway_integration.opt", "aws_api_gateway_method_response.opt"]
}

resource "aws_api_gateway_method_response" "opt" {
  rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}"
  resource_id = "${aws_api_gateway_resource.rest_api_resource.id}"
  http_method = "${aws_api_gateway_method.opt.http_method}"
  status_code = 200
  response_parameters = {
    "method.response.header.Access-Control-Allow-Origin" = true,
    "method.response.header.Access-Control-Allow-Methods" = true,
    "method.response.header.Access-Control-Allow-Headers" = true
  }
  response_models = {
    "application/json" = "Empty"
  }
  depends_on = ["aws_api_gateway_method.opt"]
}

resource "aws_api_gateway_method" "app_api_gateway_method" {
  rest_api_id      = "${aws_api_gateway_rest_api.rest_api.id}"
  resource_id      = "${aws_api_gateway_resource.rest_api_resource.id}"
  http_method      = "GET"
  authorization    = "NONE"
  api_key_required = true
}

resource "aws_api_gateway_method_response" "app_cors_method_response_200" {
    rest_api_id   = "${aws_api_gateway_rest_api.rest_api.id}"
    resource_id   = "${aws_api_gateway_resource.rest_api_resource.id}"
    http_method   = "${aws_api_gateway_method.app_api_gateway_method.http_method}"
    status_code   = "200"
    response_parameters = {
    "method.response.header.Access-Control-Allow-Origin" = true,
    "method.response.header.Access-Control-Allow-Methods" = true,
    "method.response.header.Access-Control-Allow-Headers" = true
  }
    depends_on = ["aws_api_gateway_method.app_api_gateway_method"]
}

resource "aws_api_gateway_integration" "app_api_gateway_integration" {
  rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}"
  resource_id = "${aws_api_gateway_method.app_api_gateway_method.resource_id}"
  http_method = "${aws_api_gateway_method.app_api_gateway_method.http_method}"
  integration_http_method = "POST"
  type                    = "AWS_PROXY"
  uri                     = "${aws_lambda_function.app_lambda.invoke_arn}"
  depends_on    = [
    "aws_api_gateway_method.app_api_gateway_method",
    "aws_lambda_function.app_lambda"
    ]
}

resource "aws_api_gateway_integration_response" "app_api_gateway_integration_response" {
  rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}"
  resource_id = "${aws_api_gateway_resource.rest_api_resource.id}"
  http_method = "${aws_api_gateway_method.app_api_gateway_method.http_method}"
  status_code = 200
  response_parameters = {
    "method.response.header.Access-Control-Allow-Origin" = "'*'",
    "method.response.header.Access-Control-Allow-Headers" = "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Requested-With'",
    "method.response.header.Access-Control-Allow-Methods" = "'GET,OPTIONS,POST,PUT'"
  }
  depends_on = [
    "aws_api_gateway_integration.app_api_gateway_integration",
    "aws_api_gateway_method_response.app_cors_method_response_200",
  ]
}

resource "aws_api_gateway_deployment" "app_api_gateway_deployment" {
  rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}"
  stage_name  = "app_stage"
  depends_on = [
    "aws_api_gateway_integration_response.app_api_gateway_integration_response",
    "aws_api_gateway_integration_response.opt"
    ]
}

我们将不胜感激。

【问题讨论】:

    标签: amazon-web-services cors terraform aws-api-gateway


    【解决方案1】:

    对于较新的 HTTP API (v2),您可以使用:

    resource "aws_apigatewayv2_api" "lambda" {
      name          = "lambda_gw_api"
      protocol_type = "HTTP"
      cors_configuration {
        allow_origins = ["https://www.mywebsite.fr"]
        allow_methods = ["POST", "GET", "OPTIONS"]
        allow_headers = ["content-type"]
        max_age = 300
      }
    }
    

    PS:您可能还需要检查您的 OPTIONS 路由是否有“集成”且不返回 401。

    【讨论】:

      【解决方案2】:

      找到了一个简单的解决方案。问题是在对现有 API 网关应用更新的更改时,并没有重新部署这些网关。所以我不得不自己手动重新部署它们,并考​​虑如何在 terraform 中做到这一点。

      【讨论】:

        【解决方案3】:

        您可以使用 terraform 模块来启用 cors:

        module "api-gateway-enable-cors" {
        source  = "squidfunk/api-gateway-enable-cors/aws"
        version = "0.3.1"
        api_id          = "<your_api_id>"
        api_resource_id = "<your_api_resource_id>"
        }
        

        来源:api-gateway-enable-cors

        【讨论】:

          【解决方案4】:

          查看 Cloudwatch 中的 API GW 日志以查看状态码是很有用的。在我的场景中,我有两条使用aws_apigatewayv2_route 配置的路由,一条用于 POST,一条用于 OPTIONS,用于相同的路由键。 OPTIONS 请求失败,状态码 429 请求太多。此状态码通常在超过允许的限制时由节流设置返回。

          事实证明,由于 OPTIONS 请求没有通过 CORS,这是因为我没有在 terraform 中指定 default_route_settings 的节流,因此“默认路由节流”的默认节流默认为 0 用于突发和速率.所以我的 OPTIONS 请求没有通过 CORS,因为它受到这种默认为零的限制的影响。 AWS 控制台中的提示很明确:

          此节流限制适用于阶段中的每个路由,除了那些 为特定路线定义。

          故事的寓意 - 在您的 OPTIONS 请求中,请真正注意 API GW 返回的状态代码,并检查 API GW 的 Cloudwatch 日志。 所以:一切正常,当我在 terraform 中添加这个时,在我的 resource "aws_apigatewayv2_stage" "lambda" 下:

             default_route_settings {
                throttling_burst_limit  = 1000 
                throttling_rate_limit   = 5000
              }
          

          【讨论】:

            猜你喜欢
            • 2018-10-03
            • 2021-07-07
            • 2021-03-18
            • 2021-11-25
            • 2021-03-08
            • 2021-12-26
            • 2019-12-30
            • 2020-08-17
            • 2019-03-08
            相关资源
            最近更新 更多