【问题标题】:Missing Authentication Token on Unauthenticated Method未经身份验证的方法缺少身份验证令牌
【发布时间】:2018-08-03 23:45:42
【问题描述】:

我有以下 Terraform 用于在 API Gateway 上为我的 API 设置 CORS 方法:

resource "aws_api_gateway_method" "default" {
  rest_api_id   = "${var.rest_api_id}"
  resource_id   = "${var.resource_id}"
  http_method   = "OPTIONS"
  authorization = "NONE"
}

resource "aws_api_gateway_method_response" "default" {
  rest_api_id = "${var.rest_api_id}"
  resource_id = "${var.resource_id}"
  http_method = "${aws_api_gateway_method.default.http_method}"
  status_code = "200"

  response_parameters = {
    "method.response.header.Access-Control-Allow-Headers" = true,
    "method.response.header.Access-Control-Allow-Methods" = true,
    "method.response.header.Access-Control-Allow-Origin"  = true,
  }
}

resource "aws_api_gateway_integration" "default" {
  rest_api_id          = "${var.rest_api_id}"
  resource_id          = "${var.resource_id}"
  http_method          = "${aws_api_gateway_method.default.http_method}"
  type                 = "MOCK"
  passthrough_behavior = "WHEN_NO_MATCH"

  request_templates {
    "application/json" = "{ \"statusCode\": 200 }"
  }
}

resource "aws_api_gateway_integration_response" "default" {
  rest_api_id = "${var.rest_api_id}"
  resource_id = "${var.resource_id}"
  http_method = "${aws_api_gateway_method.default.http_method}"
  status_code = "${aws_api_gateway_method_response.default.status_code}"

  response_parameters = {
    "method.response.header.Access-Control-Allow-Headers" = "'${join(",", var.allow_headers)}'",
    "method.response.header.Access-Control-Allow-Methods" = "'${join(",", var.allow_methods)}'",
    "method.response.header.Access-Control-Allow-Origin"  = "'${var.allow_origin}'",
  }
}

我的变量定义为:

variable "allow_headers" {
  type = "list"
  default = ["Content-Type", "X-Amz-Date", "Authorization", "X-Api-Key", "X-Amz-Security-Token", "X-Requested-With"]
}

variable "allow_methods" {
  type = "list"
  default = ["*"]
}

variable "allow_origin" {
  default = "*"
}

variable "resource_id" {
  description = "The API Gateway Resource id."
}

variable "rest_api_id" {
  description = "The API Gateway REST API id."
}

当我使用 API Gateway Web 控制台测试端点时,它按预期工作:

但是,当我尝试 curl 端点时,我得到一个 403:

$ curl -is -X OPTIONS https://api.naftuli.wtf/echo.json
HTTP/1.1 403 Forbidden
Content-Type: application/json
Content-Length: 42
Connection: keep-alive
Date: Fri, 23 Feb 2018 20:45:09 GMT
x-amzn-RequestId: 70089d6b-18da-11e8-9042-c3baac8eebde
x-amzn-ErrorType: MissingAuthenticationTokenException
X-Cache: Error from cloudfront
Via: 1.1 5a582ba7fbecfc5948507c13d8d2078a.cloudfront.net (CloudFront)
X-Amz-Cf-Id: VB2j87V6_wfSqXkyIPeqz8vjdDF5vBIi0DsJmIAn8kgyIjSAfkcf7A==

{"message":"Missing Authentication Token"}

该方法明确配置了authorization = "NONE",我可以从 API Gateway 控制台触发它而不会出现问题。

如何允许访问此方法?我觉得我已经尽力了。

【问题讨论】:

    标签: aws-api-gateway terraform


    【解决方案1】:

    TL;DR在添加/更改每个新资源/方法后,您必须创建一个新部署。


    Terraform 会创建一次部署,并且永远不会更新它,因为它的数据没有任何变化。我找到了解决方法:

    resource "aws_api_gateway_stage" "default" {
      stage_name = "production"
      rest_api_id = "${aws_api_gateway_rest_api.default.id}"
      deployment_id = "${aws_api_gateway_deployment.default.id}"
    
      lifecycle {
        # a new deployment needs to be created on every resource change so we do it outside of terraform
        ignore_changes = ["deployment_id"]
      }
    }
    

    我告诉舞台忽略 deployment_id 属性,这样 Terraform 就不会在没有任何更改的地方显示更改。

    为了创建一个新的部署,我简单地将这个命令添加到我的 Makefile deploy 目标中:

    deploy:
        terraform apply -auto-approve
        aws apigateway create-deployment \
            --rest-api-id $(terraform output -json | jq -r .rest_api_id.value) \
            --stage-name $(terraform output -json | jq -r .stage_name.value)
    

    这将为给定阶段创建我的 REST API 的新部署。

    我确信有更好的方法可以完全在 Terraform 中执行此操作,但目前它们让我望而却步。

    【讨论】:

    • 我对您的解决方案问题的理解不是那么舒服。为什么不考虑使用无服务器框架来完成无服务器工作,Terraform 不适合。
    【解决方案2】:

    这是一个更好的方法

    resource "aws_api_gateway_deployment" "petshop" {
      provider    = "aws.default"
      stage_description = "${md5(file("apigateway.tf"))}"
      rest_api_id = "${aws_api_gateway_rest_api.petshop.id}"
      stage_name  = "prod"
    }
    

    这样可以节省您在每次微小更改时重新部署,并且只会由 apigateway.tf 文件中的更改触发

    【讨论】:

    • 问题是我已经定义了一堆文件来分割一些东西。有没有办法在 fileglob 上进行 shasum?
    • 不确定,我会把它指向定义部署的文件
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-27
    • 2017-02-24
    • 2019-12-03
    • 2020-04-19
    • 1970-01-01
    • 2023-04-07
    • 2016-11-30
    相关资源
    最近更新 更多