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

如何通过Terraform部署带路径通配符的GCP API Gateway配置?

问题:GCP API Gateway带路径参数的Terraform部署报错

我通过Terraform部署GCP API Gateway配置,因需为后端URL使用变量,将OpenAPI文档定义在tf文件中。当路径使用带参数的格式(如/devices/{deviceID})时部署报错,不使用参数(如/device)则可正常运行。相关资源配置如下:

resource "google_api_gateway_api_config" "device_management" {
  provider             = google-beta
  project              = var.project_id
  api                  = google_api_gateway_api.device_management.api_id
  api_config_id_prefix = "${google_api_gateway_api.device_management.api_id}-"

  gateway_config {
    backend_config {
      google_service_account = google_service_account.device_registration.id
    }
  }

  openapi_documents {
    document {
      path     = "${google_api_gateway_api.device_management.api_id}_api_spec.yaml"
      contents = base64encode(
        jsonencode(
          {
            swagger : "2.0"
            info : {
              title : "Device Registration API"
              description : "Register devices and get their private keys"
              version : "0.0.1"
            }
            schemes : ["https"]
            produces : ["application/json"]
            x-google-allow : "configured"
            securityDefinitions : {
              api_key : {
                type : "apiKey"
                name : "apiKey"
                in : "query"
              }
              oauth2 : {
                authorizationUrl : ""
                flow : "implicit"
                type : "oauth2"
                x-google-issuer : google_service_account.device_registration.email
                x-google-jwks_uri : "https://www.googleapis.com/robot/v1/metadata/x509/${google_service_account.device_registration.email}"
                x-google-audiences : "device-registration"
              }
            }
            security : [
              { oauth2 : [] }
            ]
            paths : {
              "/devices/{deviceID}" : {
                post : {
                  summary : "Register a new device"
                  operationId : "registerDevice"
                  x-google-backend : {
                    address : google_cloudfunctions_function.device_management_register_device.https_trigger_url
                  }
                  responses : {
                    201 : {
                      description : "Device registered succesfully"
                      schema : {
                        type : "string"
                      }
                    }
                  }
                }
              }
            }
          }
        )
      )
    }
  }
}

部署时触发以下错误:

Error: Error creating ApiConfig: googleapi: Error 400: Cannot convert to service config.
│ 'location: "unknown location"
│ kind: ERROR
│ message: "http: undefined field 'deviceID' on message 'google.protobuf.Empty'."
│ 
│  location: "unknown location"
│ kind: ERROR
│ message: "http: undefined field 'deviceID' on message 'google.protobuf.Empty'."
│ 
│  location: "device-registration_api_spec.yaml"
│ message: "apiKey 'apiKey' is ignored. Only apiKey with 'name' as 'key' and 'in' as 'query', or 'name' as 'api_key' and 'in' as 'query', or 'name'as 'x-api-key' and 'in' as 'header' are supported"
│ 
│  location: "device-registration_api_spec.yaml: Operation 'post' in path '/devices/{deviceID}'"
│ message: "Operation does not require an API key; callers may invoke the method without specifying an associated API-consuming project. To enable API key all the SecurityRequirement Objects (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-requirement-object) inside security definition must reference at least one SecurityDefinition of type : 'apiKey'."
│ 
│  location: "device-registration_api_spec.yaml: Operation 'get' in path '/devices/{deviceID}/key'"
│ message: "Operation does not require an API key; callers may invoke the method without specifying an associated API-consuming project. To enable API key all the SecurityRequirement Objects (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-requirement-object) inside security definition must reference at least one SecurityDefinition of type : 'apiKey'."
│ '
│ com.google.apps.framework.request.BadRequestException: Cannot convert to service config.
│ 'location: "unknown location"
│ kind: ERROR
│ message: "http: undefined field 'deviceID' on message 'google.protobuf.Empty'."
│ 
│  location: "unknown location"
│ kind: ERROR
│ message: "http: undefined field 'deviceID' on message 'google.protobuf.Empty'."
│ 
│  location: "device-registration_api_spec.yaml"
│ message: "apiKey 'apiKey' is ignored. Only apiKey with 'name' as 'key' and 'in' as 'query', or 'name' as 'api_key' and 'in' as 'query', or 'name'as 'x-api-key' and 'in' as 'header' are supported"
│ 
│  location: "device-registration_api_spec.yaml: Operation 'post' in path '/devices/{deviceID}'"
│ message: "Operation does not require an API key; callers may invoke the method without specifying an associated API-consuming project. To enable API key all the SecurityRequirement Objects (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-requirement-object) inside security definition must reference at least one SecurityDefinition of type : 'apiKey'."
│ 
│  location: "device-registration_api_spec.yaml: Operation 'get' in path '/devices/{deviceID}/key'"
│ message: "Operation does not require an API key; callers may invoke the method without specifying an associated API-consuming project. To enable API key all the SecurityRequirement Objects (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-requirement-object) inside security definition must reference at least one SecurityDefinition of type : 'apiKey'."
│ '
│ 
│   with module.iot_backend.google_api_gateway_api_config.device_management,
│   on ../../modules/iot_backend/device_management.tf line 92, in resource "google_api_gateway_api_config" "device_management":
│   92: resource "google_api_gateway_api_config" "device_management" {
│ 
╵

解决方案

1. 显式定义路径参数(解决核心报错)

GCP API Gateway要求OpenAPI规范必须显式声明路径参数,否则会认为参数未定义。在对应接口的post节点下添加parameters字段,明确参数的名称、位置、必填性和类型:

parameters: [
  {
    name: "deviceID",
    in: "path",
    required: true,
    type: "string"
  }
]

2. 修正API Key配置格式

GCP仅支持三种API Key格式,原配置的name: "apiKey"不符合要求,修改为以下任一合法格式:

api_key: {
  type: "apiKey",
  name: "x-api-key", // 推荐用header传递的格式
  in: "header"
}

3. 调整安全验证规则

如果需要强制API Key验证,需在security数组中同时包含oauth2和api_key的要求;如果不需要API Key验证,可直接删除api_key相关的securityDefinitions:

  • 同时启用OAuth2和API Key验证:
security: [
  { oauth2: [], api_key: [] }
]
  • 仅保留OAuth2验证:删除securityDefinitions中的api_key节点,保留原security配置即可。

完整修正后的OpenAPI配置片段

整合修改后的内容,对应的paths部分如下:

paths : {
  "/devices/{deviceID}" : {
    post : {
      summary : "Register a new device"
      operationId : "registerDevice"
      parameters: [
        {
          name: "deviceID",
          in: "path",
          required: true,
          type: "string"
        }
      ]
      x-google-backend : {
        address : google_cloudfunctions_function.device_management_register_device.https_trigger_url
      }
      responses : {
        201 : {
          description : "Device registered succesfully"
          schema : {
            type : "string"
          }
        }
      }
    }
  }
}

内容的提问来源于stack exchange,提问作者Mr P

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 01:18:28