Terraformed AWS API Gateway 自定义域名抛出 403 Forbidden

Posted

技术标签:

【中文标题】Terraformed AWS API Gateway 自定义域名抛出 403 Forbidden【英文标题】:Terraformed AWS API Gateway Custom Domain Names throws 403 Forbidden 【发布时间】:2021-03-22 03:23:30 【问题描述】:

我正在尝试通过区域自定义域公开我的区域 API 网关的所有阶段。

问题

如果我直接卷曲我的 API 网关(即https://xx.execute-api.eu-west-3.amazonaws.com/default/users),它可以工作,但如果我卷曲域名(即https://api.acme.com/default/users),我会得到一个403

配置

我的 Terraform 文件如下所示:

data "aws_route53_zone" "acme" 
  name         = "acme.com."


resource "aws_api_gateway_rest_api" "backend" 
  name        = "acme-backend-api"
  description = "Backend API"
  body        = "SOMETHING"

  endpoint_configuration 
    types = ["REGIONAL"]
  


resource "aws_api_gateway_deployment" "backend" 
  rest_api_id = aws_api_gateway_rest_api.backend.id
  stage_name  = "default"

  lifecycle 
    create_before_destroy = true
  


resource "aws_api_gateway_domain_name" "backend" 
  domain_name              = "api.acme.com"
  regional_certificate_arn = "arn:aws:acm:xx:certificate/xx"

  endpoint_configuration 
    types = ["REGIONAL"]
  


resource "aws_route53_record" "backend" 
  name    = aws_api_gateway_domain_name.backend.domain_name
  type    = "A"
  zone_id = data.aws_route53_zone.acme.id

  alias 
    evaluate_target_health = true
    name                   = aws_api_gateway_domain_name.backend.regional_domain_name
    zone_id                = aws_api_gateway_domain_name.backend.regional_zone_id
  


resource "aws_api_gateway_base_path_mapping" "backend" 
  api_id      = aws_api_gateway_rest_api.backend.id
  domain_name = aws_api_gateway_domain_name.backend.domain_name
  # No stage_name: expose all stages

根据 Terraform api_gateway_domain_name 和 api_gateway_base_path_mapping 的例子,应该没问题。

我也跟着很多howtos,我有这些元素:

    证书 API 自定义域的 A 记录 到已部署阶段的映射(如果您直接调用它就可以)

我错过了什么/做错了什么?

【问题讨论】:

您观察到哪些错误或非预期行为? 【参考方案1】:

这是今天为我工作的 v2 示例,此“aws_apigatewayv2_api_mapping”是避免 port 80: Connection refused 的关键 或 "message":"Forbidden" 错误,我看到你有,但我确实遇到了困难。

// ACM

resource "aws_acm_certificate" "cert_api" 
  domain_name       = var.api_domain
  validation_method = "DNS"

  tags = 
    Name = var.api_domain
  


resource "aws_acm_certificate_validation" "cert_api" 
  certificate_arn = aws_acm_certificate.cert_api.arn



// API Gateway V2

resource "aws_apigatewayv2_api" "lambda" 
  name          = "serverless_lambda_gw"
  protocol_type = "HTTP"


resource "aws_apigatewayv2_stage" "lambda" 
  api_id = aws_apigatewayv2_api.lambda.id

  name        = "serverless_lambda_stage"
  auto_deploy = true

  access_log_settings 
    destination_arn = aws_cloudwatch_log_group.api_gw.arn

    format = jsonencode(
      requestId               = "$context.requestId"
      sourceIp                = "$context.identity.sourceIp"
      requestTime             = "$context.requestTime"
      protocol                = "$context.protocol"
      httpMethod              = "$context.httpMethod"
      resourcePath            = "$context.resourcePath"
      routeKey                = "$context.routeKey"
      status                  = "$context.status"
      responseLength          = "$context.responseLength"
      integrationErrorMessage = "$context.integrationErrorMessage"
      
    )
  


resource "aws_apigatewayv2_integration" "testimonials" 
  api_id = aws_apigatewayv2_api.lambda.id

  integration_uri    = aws_lambda_function.testimonials.invoke_arn
  integration_type   = "AWS_PROXY"
  integration_method = "POST"


resource "aws_apigatewayv2_route" "testimonials" 
  api_id = aws_apigatewayv2_api.lambda.id

  route_key = "GET /testimonials"
  target    = "integrations/$aws_apigatewayv2_integration.testimonials.id"


resource "aws_cloudwatch_log_group" "api_gw" 
  name = "/aws/api_gw/$aws_apigatewayv2_api.lambda.name"

  retention_in_days = 30


resource "aws_lambda_permission" "api_gw" 
  statement_id  = "AllowExecutionFromAPIGateway"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.testimonials.function_name
  principal     = "apigateway.amazonaws.com"

  source_arn = "$aws_apigatewayv2_api.lambda.execution_arn/*/*"


resource "aws_apigatewayv2_domain_name" "api" 
  domain_name = var.api_domain

  domain_name_configuration 
    certificate_arn = aws_acm_certificate.cert_api.arn
    endpoint_type   = "REGIONAL"
    security_policy = "TLS_1_2"
  


resource "aws_apigatewayv2_api_mapping" "api" 
  api_id      = aws_apigatewayv2_api.lambda.id
  domain_name = aws_apigatewayv2_domain_name.api.id
  stage       = aws_apigatewayv2_stage.lambda.id




// Route53

resource "aws_route53_zone" "api" 
  name = var.api_domain


resource "aws_route53_record" "cert_api_validations" 
  allow_overwrite = true
  count           = length(aws_acm_certificate.cert_api.domain_validation_options)

  zone_id = aws_route53_zone.api.zone_id
  name    = element(aws_acm_certificate.cert_api.domain_validation_options.*.resource_record_name, count.index)
  type    = element(aws_acm_certificate.cert_api.domain_validation_options.*.resource_record_type, count.index)
  records = [element(aws_acm_certificate.cert_api.domain_validation_options.*.resource_record_value, count.index)]
  ttl     = 60


resource "aws_route53_record" "api-a" 
  name    = aws_apigatewayv2_domain_name.api.domain_name
  type    = "A"
  zone_id = aws_route53_zone.api.zone_id

  alias 
    name                   = aws_apigatewayv2_domain_name.api.domain_name_configuration[0].target_domain_name
    zone_id                = aws_apigatewayv2_domain_name.api.domain_name_configuration[0].hosted_zone_id
    evaluate_target_health = false
  

【讨论】:

以上是关于Terraformed AWS API Gateway 自定义域名抛出 403 Forbidden的主要内容,如果未能解决你的问题,请参考以下文章

GKE Terraformed 集群发布通道设置

错误 - 403 禁止 - Microsoft-Azure-Application-Gateway/v2

如何在调用 google pay API 时了解我的支付提供商名称?

如何根据域名阻止对我的 api-gateway url 的任何请求?

AWS SAM :: AWS::Serverless::Api“'Auth' 属性的值无效”

AWS CloudFormation 可以调用 AWS API 吗?