You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Terraform使用OpenAPI定义API Gateway与Cognito授权器时的循环依赖问题

API Gateway与Cognito授权器的Terraform循环依赖问题解决

问题背景

  • 目标创建一个API Gateway
  • 通过OpenAPI YAML文件定义路由规则
  • 配置Cognito用户池授权器,限制仅已登录用户可访问API

以上操作属于常规流程,但遇到了循环依赖问题:创建授权器需要引用API Gateway的ID,而创建API Gateway又需要在OpenAPI定义中引用授权器的ARN,导致Terraform报错无法部署。

现有代码

Terraform配置

data "template_file" "apig_template" {
  template = file("${var.template_path_file}/${var.template_name}")

  vars = merge(
    var.apig_template_variables,
    {
      arnCognitoAuthorizer = "${aws_api_gateway_authorizer.eva_ui_authorizer.arn}"
    }
  )
}

resource "aws_api_gateway_rest_api" "apig" {
  name           = "${var.project_name}-${var.environment}-${var.apig_name}"
  description    = var.description
  api_key_source = "HEADER"

  body = data.template_file.apig_template.rendered
}

resource "aws_api_gateway_authorizer" "eva_ui_authorizer" {
  name            = "${var.project_name}-${var.environment}-${var.apig_name}-authorizer"
  rest_api_id     = aws_api_gateway_rest_api.apig.id
  type            = "COGNITO_USER_POOLS"
  identity_source = "method.request.header.Authorization"
  provider_arns   = [var.cognito_user_pool_arn]
}

OpenAPI YAML定义

openapi: "3.0.1"
info:
  title: "${name}-api-gw"
  version: "0.1.0"
components:
  securitySchemes:
    CognitoAuthorizer:
      type: "apiKey"
      name: "Authorization"
      in: "header"
      x-amazon-apigateway-authtype: "cognito_user_pools"
      x-amazon-apigateway-authorizer:
        type: "cognito_user_pools"
        authorizerUri: ${arnCognitoAuthorizer}
        identitySource: "method.request.header.Authorization"
        authorizerResultTtlInSeconds: 300
paths:
  /read-data:
    post:
      operationId: Get Reference Data
      summary: Get Reference Data
      responses: "200"
      security:
        - CognitoAuthorizer: []
      x-amazon-apigateway-integration:
        payloadFormatVersion: "1.0"
        type: "aws_proxy"
        httpMethod: "POST"
        uri: "arn:aws:apigateway:eu-west-1:lambda:path/2015-03-31/functions/${arnLambdaReadRefData}/invocations"
        timeoutInMilis: 30000

错误信息

执行terraform init时出现以下循环依赖错误:

│ Error: Cycle: module.api_gateway_slips_website.aws_api_gateway_authorizer.eva_ui_authorizer, module.api_gateway_slips_website.data.template_file.apig_template, module.api_gateway_slips_website.aws_api_gateway_rest_api.apig

解决方案

要解决循环依赖,核心是打破API Gateway与授权器之间的双向直接引用,以下是两种可行方案:

方案一:分阶段部署,先创建基础API再更新配置

  1. 先创建不含授权器配置的基础API Gateway;
  2. 基于已创建的API Gateway创建Cognito授权器;
  3. 渲染包含授权器ARN的完整OpenAPI模板,更新API Gateway的配置。

修改后的Terraform代码示例:

# 1. 创建基础API(使用不含授权器的初始模板)
resource "aws_api_gateway_rest_api" "apig_base" {
  name           = "${var.project_name}-${var.environment}-${var.apig_name}"
  description    = var.description
  api_key_source = "HEADER"
  # 初始模板仅定义路由结构,不包含授权器配置
  body = file("${var.template_path_file}/${var.template_name_initial}")
}

# 2. 创建Cognito授权器,引用基础API的ID
resource "aws_api_gateway_authorizer" "eva_ui_authorizer" {
  name            = "${var.project_name}-${var.environment}-${var.apig_name}-authorizer"
  rest_api_id     = aws_api_gateway_rest_api.apig_base.id
  type            = "COGNITO_USER_POOLS"
  identity_source = "method.request.header.Authorization"
  provider_arns   = [var.cognito_user_pool_arn]
}

# 3. 渲染包含授权器ARN的完整OpenAPI模板
data "template_file" "apig_template_full" {
  template = file("${var.template_path_file}/${var.template_name}")

  vars = merge(
    var.apig_template_variables,
    {
      arnCognitoAuthorizer = aws_api_gateway_authorizer.eva_ui_authorizer.arn
    }
  )

  # 强制依赖授权器创建完成
  depends_on = [aws_api_gateway_authorizer.eva_ui_authorizer]
}

# 4. 更新API Gateway为完整配置
resource "aws_api_gateway_rest_api" "apig_updated" {
  name           = "${var.project_name}-${var.environment}-${var.apig_name}"
  description    = var.description
  api_key_source = "HEADER"
  rest_api_id    = aws_api_gateway_rest_api.apig_base.id
  body           = data.template_file.apig_template_full.rendered

  lifecycle {
    create_before_destroy = true
  }
}

方案二:在OpenAPI中使用授权器名称关联,避免依赖ARN

在OpenAPI配置中,将authorizerUri替换为authorizerId或直接使用授权器名称,让API Gateway自动关联同实例下的授权器,从而避免直接引用授权器ARN。

修改后的OpenAPI YAML:

openapi: "3.0.1"
info:
  title: "${name}-api-gw"
  version: "0.1.0"
components:
  securitySchemes:
    CognitoAuthorizer:
      type: "apiKey"
      name: "Authorization"
      in: "header"
      x-amazon-apigateway-authtype: "cognito_user_pools"
      x-amazon-apigateway-authorizer:
        type: "cognito_user_pools"
        # 使用授权器名称关联,而非ARN
        authorizerId: "${authorizerName}"
        identitySource: "method.request.header.Authorization"
        authorizerResultTtlInSeconds: 300
paths:
  /read-data:
    post:
      operationId: Get Reference Data
      summary: Get Reference Data
      responses: "200"
      security:
        - CognitoAuthorizer: []
      x-amazon-apigateway-integration:
        payloadFormatVersion: "1.0"
        type: "aws_proxy"
        httpMethod: "POST"
        uri: "arn:aws:apigateway:eu-west-1:lambda:path/2015-03-31/functions/${arnLambdaReadRefData}/invocations"
        timeoutInMilis: 30000

对应的Terraform模板变量调整:

data "template_file" "apig_template" {
  template = file("${var.template_path_file}/${var.template_name}")

  vars = merge(
    var.apig_template_variables,
    {
      # 传递授权器名称而非ARN
      authorizerName = aws_api_gateway_authorizer.eva_ui_authorizer.name
    }
  )
}

resource "aws_api_gateway_rest_api" "apig" {
  name           = "${var.project_name}-${var.environment}-${var.apig_name}"
  description    = var.description
  api_key_source = "HEADER"

  body = data.template_file.apig_template.rendered
}

resource "aws_api_gateway_authorizer" "eva_ui_authorizer" {
  name            = "${var.project_name}-${var.environment}-${var.apig_name}-authorizer"
  rest_api_id     = aws_api_gateway_rest_api.apig.id
  type            = "COGNITO_USER_POOLS"
  identity_source = "method.request.header.Authorization"
  provider_arns   = [var.cognito_user_pool_arn]
}

注:方案二需要确保授权器名称在当前API Gateway实例中唯一,若仍出现依赖问题,可添加depends_on强制授权器先于API更新完成。


内容的提问来源于stack exchange,提问作者Rafael Marques

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 04:57:02