OpenAPI の拡張

Extensible Service Proxy(ESP)Service Control の動作を構成するために Google が独自に開発した OpenAPI 仕様の拡張機能が、Cloud Endpoints でサポートされています。ここでは、Google 独自の OpenAPI 仕様の拡張について説明します。

以下の例は YAML 形式ですが、JSON もサポートされています。

命名規則

Google の OpenAPI 仕様拡張には、x-google- 接頭辞で始まる名前が付けられています。

x-google-allow

x-google-allow: [configured | all]

この拡張機能は、OpenAPI 仕様の最上位で使用し、ESP で許可される URL パスを指定します。

有効な値は configuredall です。

デフォルト値は configured で、OpenAPI 仕様にある API メソッドだけが ESP 経由で提供されます。

all を使用すると、(API キーやユーザー認証の有無に関係なく)未構成の呼び出しは ESP を通過して API に到達します。

ESP では API の呼び出しが大文字と小文字を区別して処理されます。たとえば、/widgets/Widgets は異なる API メソッドと見なされます。

all が使用された場合、次の 2 点に関して注意が必要です。

  • すべての API キーまたは認証ルール。
  • サービスのバックエンド パス ルーティング。

ベスト プラクティスとして、大文字小文字を区別するパス ルーティングを使用するように API を構成することをおすすめします。大文字小文字を区別するルーティングを使用すると、URL でリクエストされたメソッドが OpenAPI 仕様にリストされている API メソッドと一致しない場合、HTTP ステータス コード 404 が返されます。Node.js Express などのウェブ アプリケーション フレームワークには、大文字小文字を区別するルーティングを有効 / 無効にする設定があります。デフォルトの動作は使用しているフレームワークによって異なります。フレームワークの設定で、大文字小文字を区別するルーティングが有効になっているか確認することをおすすめします。この推奨事項は、OpenAPI 仕様 v2.0 に記載されている「仕様内のすべてのフィールド名は大文字と小文字を区別する」と一致しています。

以下を想定しています。

  • x-google-allowall に設定されている。
  • OpenAPI 仕様には API メソッド widgets がリストされているが、Widgets はされていない。
  • API キーを必要とする OpenAPI 仕様を構成している。

widgets は API 仕様にリストされており、API キーがないため、次のリクエストは ESP でブロックします。

https://my-project-id.appspot.com/widgets

Widgetsが OpenAPI 仕様にリストされていないため、次のリクエストは API キーなしでサービスに渡します。

https://my-project-id.appspot.com/Widgets/

API で大文字小文字を区別するルーティングを使用している(また「Widgets」の呼び出しをどのコードにもルーティングしていない)場合、API のバックエンドは 404 を返します。ただし、大文字小文字を区別しないルーティングを使用している場合、API バックエンドはこの呼び出しを「widgets」にルーティングします。

言語やフレームごとに、大文字小文字の区別とルーティングを制御する方法が異なります。詳細については、フレームワークのドキュメントをご覧ください。

x-google-backend

x-google-backend 拡張機能は、リクエストをローカルまたはリモートのバックエンドにルーティングする方法を指定します。拡張機能は、OpenAPI 仕様のトップレベルやオペレーション レベルで指定できます。

デフォルトでは、ESP はすべてのトラフィックを 1 つのローカル バックエンドにプロキシするように構成されています。ローカル バックエンド アドレスは、--backend フラグによって指定されます(デフォルトは http://127.0.0.1:8081)。x-google-backend 拡張機能を使用すると、このデフォルトの動作をオーバーライドし、リクエストを受信できる 1 つ以上のローカル またはリモート バックエンドを指定できます。

x-google-backend 拡張機能は、認証やタイムアウトなど、ローカル バックエンドとリモート バックエンドのその他の設定を構成することもできます。これらの構成はすべて、オペレーションごとに適用できます。

x-google-backend 拡張機能には以下のフィールドが含まれます。

address

address: URL

省略可。ターゲット バックエンドの URL。 アドレスのスキームは http または https のいずれかである必要があります。

リモート バックエンド(サーバーレス)へのルーティング時は、アドレスを設定し、スキーム部分は https にします。

x-google-backend を使用するオペレーションで address を指定しない場合、ESPv2 は --backend フラグで指定されたローカル バックエンドにリクエストをルーティングします。

jwt_audience | disable_auth

これらの 2 つのプロパティの 1 つのみを設定する必要があります。

オペレーションで x-google-backend を使用するものの、jwt_audiencedisable_auth を指定しない場合、ESPv2 では address に一致する jwt_audience が自動的に設定されます。address が設定されていない場合、ESPv2 では自動的に disable_authtrue に設定されます。

jwt_audience

jwt_audience: string

省略可。ESPv2 がインスタンス ID トークンを取得すると、JWT オーディエンスが指定され、ターゲット バックエンド リクエストの際に使用されます。

サーバーレス用に Endpoints を構成する場合、リモート バックエンドを ESPv2 からのトラフィックのみを許可するように保護する必要があります。ESPv2 は、リクエストをプロキシするときにインスタンス ID トークンを Authorization ヘッダーに添付します。インスタンス ID トークンは、ESPv2 のデプロイに使用されたランタイム サービス アカウントを表します。リモート バックエンドは、この接続されたトークンに基づいて、ESPv2 からのリクエストであることを確認します。

たとえば、Cloud Run にデプロイされたリモート バックエンドでは、IAM を使用して次のことができます。

  1. 特別な allUsers プリンシパルから roles/run.invoker を取り消して、認証されていない呼び出しを制限します。
  2. roles/run.invoker ロールを ESPv2 ランタイム サービス アカウントに付与して、ESPv2 にのみバックエンドの呼び出しを許可します。

デフォルトでは、ESPv2 は address フィールドと一致する JWT オーディエンスを持つインスタンス ID トークンを作成します。手動で jwt_audience を指定する必要があるのは、ターゲット バックエンドが JWT ベースの認証を使用し、想定されるオーディエンスが address フィールドで指定された値と異なる場合のみです。App Engine または IAP にデプロイされたリモート バックエンドの場合、JWT オーディエンスをオーバーライドする必要があります。App Engine と IAP では、想定されるオーディエンスとして OAuth クライアント ID が使用されます。

この機能を有効にすると、ESPv2 はリクエスト内のヘッダーを変更します。リクエストにすでに Authorization ヘッダーが設定されている場合、ESPv2 は次のようにします。

  1. 元の値を新しいヘッダー X-Forwarded-Authorization にコピーします。
  2. Authorization ヘッダーをインスタンス ID トークンでオーバーライドします。

したがって、API クライアントが Authorization ヘッダーを設定する場合、ESPv2 の背後で実行中のバックエンドは X-Forwarded-Authorization ヘッダーを使用して JWT 全体を取得する必要があります。認証方法が設定されていない場合、ESPv2 は検証を行わないため、バックエンドがこのヘッダーで JWT を検証する必要があります

disable_auth

disable_auth: bool

省略可。このプロパティは、ESPv2 がインスタンス ID トークンの取得を禁止し、リクエストへのアタッチを禁止すべきかどうかを決定します。

ターゲット バックエンドを構成する際、次のいずれかの条件に該当する場合、IAP または IAM を使用して ESPv2 からのリクエストの認証を行うことはできません。

  1. バックエンドでは、未認証の呼び出しを許可する必要があります。
  2. バックエンドには API クライアントからの元の Authorization ヘッダーが必要であり、X-Forwarded-Authorization は使用できません(jwt_audience のセクションで説明)。

この場合、このフィールドを true に設定します。

path_translation

path_translation: [ APPEND_PATH_TO_ADDRESS | CONSTANT_ADDRESS ]

省略可。ターゲット バックエンドにリクエストをプロキシするときに ESPv2 が使用するパス変換ストラテジを設定します。

パス変換の詳細については、パス変換についてのセクションをご覧ください。

x-google-backend が OpenAPI 仕様の最上位レベルで使用される場合、path_translation のデフォルトは APPEND_PATH_TO_ADDRESS になり、x-google-backend が OpenAPI 仕様のオペレーション レベルで使用される場合、path_translation のデフォルトは CONSTANT_ADDRESS になります。address フィールドがない場合、path_translation は未指定のままになり、検出されません。

deadline

deadline: double

省略可。リクエストに対する完全な応答を待機する秒数。構成された期限よりも時間がかかる応答はタイムアウトします。デフォルトの期限は 15.0 秒です。

正でない値は受け入れられません。その場合、ESPv2 では自動的にデフォルト値が使用されます。

期限を無効にすることはできませんが、たとえば 1 時間を表す 3600.0 などの高い数値に設定することは可能です。

protocol

protocol: [ http/1.1 | h2 ]

省略可。バックエンドにリクエストを送信するために使用されるプロトコル。サポートされている値は http/1.1h2 です。

HTTP および HTTPS バックエンドのデフォルト値は http/1.1 です。

HTTP/2 をサポートするセキュア HTTP バックエンド(https://)の場合は、パフォーマンス改善のために、このフィールドを h2 に設定します。 これは、GCP サーバーレス バックエンドに推奨されるオプションです。

ESP でのバックエンド サポートの有効化

x-google-backend が構成されると、ESPv2 が自動的に検出します。

この機能を有効にするには、ESP を手動で構成を変更する必要があります。ESP コンテナを実行する際に、--enable_backend_routing 引数を入力し、ESP の x-google-backend サポートを有効にする。(ESP コンテナ オプションを管理しないランタイムの場合、このオプションはすでに追加されています。次では、ESP コンテナを GKE にデプロイする際に、x-google-backend サポートを有効にする例を紹介します(この例は Endpoints on GKE チュートリアルを基にしています)。

- name: esp
  image: gcr.io/endpoints-release/endpoints-runtime:1
  args: [
    "--http_port", "8081",
    "--service", "SERVICE_NAME",
    "--rollout_strategy", "managed",
    "--enable_backend_routing"
  ]

パス変換について

ESP はリクエストを処理すると、ターゲット バックエンドにリクエストする前に元のリクエストパスを受け取り変換します。この変換がどのように行われるかは、使用しているパス変換方法によって異なります。パス変換には次の 2 つの方法があります。

  • APPEND_PATH_TO_ADDRESS: ターゲットのバックエンド リクエストパスは、元のリクエストパスを address の URL x-google-backend 拡張子に付加して計算されます。
  • CONSTANT_ADDRESS: x-google-backend 拡張子の address URL によって定義されるため、ターゲットのリクエストパスは定数となります。対応する OpenAPI パスにパラメータが含まれている場合、パラメータ名とその値はクエリ パラメータとなります。

例:

  • APPEND_PATH_TO_ADDRESS
    • address: https://my-project-id.appspot.com/BASE_PATH
    • OpenAPI パスパラメータ
        を使用する場合
      • OpenAPI パス: /hello/{name}
      • リクエストパス: /hello/world
      • ターゲット リクエスト URL: https://my-project-id.appspot.com/BASE_PATH/hello/world
    • OpenAPI パスパラメータを使用しない場合。
      • OpenAPI パス: /hello
      • リクエストパス: /hello
      • ターゲット リクエスト URL: https://my-project-id.appspot.com/BASE_PATH/hello
  • CONSTANT_ADDRESS
    • address: https://us-central1-my-project-id.cloudfunctions.net/helloGET
    • OpenAPI パスパラメータ
        を使用する場合
      • OpenAPI パス: /hello/{name}
      • リクエストパス: /hello/world
      • ターゲット リクエスト URL: https://us-central1-my-project-id.cloudfunctions.net/helloGET?name=world
    • OpenAPI パスパラメータを使用しない場合。
      • OpenAPI パス: /hello
      • リクエストパス: /hello
      • ターゲット リクエスト URL: https://us-central1-my-project-id.cloudfunctions.net/helloGET

x-google-endpoints

このセクションでは、x-google-endpoints 拡張子の使用方法について説明します。

cloud.goog ドメインでの DNS の設定

アプリケーションを Compute Engine または Google Kubernetes Engine にデプロイした場合、OpenAPI ドキュメントに以下を追加して、cloud.goog ドメインで Endpoints サービスの DNS エントリを作成できます。

x-google-endpoints:
- name: "API_NAME.endpoints.PROJECT_ID.cloud.goog"
  target: "IP_ADDRESS"

OpenAPI ドキュメントのトップレベル(インデントやネストのないレベル)での x-google-endpoints 拡張機能に追加します。ドメイン名は、.endpoints.PROJECT_ID.cloud.goog の形式で設定する必要があります。

例:

swagger: "2.0"
host: "my-cool-api.endpoints.my-project-id.cloud.goog"
x-google-endpoints:
- name: "my-cool-api.endpoints.my-project-id.cloud.goog"
  target: "192.0.2.1"

.cloud.goog ドメインは Google が管理し、Google Cloud のお客様と共有します。Google Cloud プロジェクト ID はグローバルに一意なので、ドメイン名は .endpoints.PROJECT_ID.cloud.goog API の一意のドメイン名です。

簡略化するため、host フィールドと x-google-endpoints.name フィールドは同じに設定します。OpenAPI ドキュメントをデプロイするとき、Service Management によって次のものが作成されます。

  • host フィールドで指定した名前のマネージド サービス。
  • x-google-endpoints 拡張機能で設定した名前と IP アドレスを使用した DNS の A レコード。

App Engine フレキシブル環境でホストされている API の場合、appspot.com ドメインを使用できます。詳細については、Endpoints を構成するをご覧ください。

CORS リクエストを許可するための ESP の構成

別の異なるオリジンのウェブ アプリケーションから API が呼び出される場合、その API はクロスオリジン リソース シェアリング(CORS)をサポートする必要があります。CORS をサポートするように ESP を構成する方法については、ESP に CORS サポートを追加するをご覧ください。

カスタム CORS サポートをバックエンド コードに実装する必要がある場合は、ESP がすべての CORS リクエストをバックエンド コードに通過するように allowCors: True を設定します。

x-google-endpoints:
- name: "API_NAME.endpoints.PROJECT_ID.cloud.goog"
  allowCors: True

OpenAPI ドキュメントのトップレベル(インデントやネストのないレベル)の x-google-endpoints 拡張機能を追加します。例を次に示します。

swagger: "2.0"
host: "my-cool-api.endpoints.my-project-id.cloud.goog"
x-google-endpoints:
- name: "my-cool-api.endpoints.my-project-id.cloud.goog"
  allowCors: True

x-google-issuer

x-google-issuer: URI | EMAIL_ADDRESS

この拡張機能は、OpenAPI securityDefinitions セクションで認証情報の発行者を指定するために使用されます。ホスト名またはメールアドレスを指定します。

x-google-jwks_uri

x-google-jwks_uri: URI

JSON ウェブトークンの署名検証に使用されるプロバイダの公開鍵の URI です。

ESP では、x-google-jwks_uri OpenAPI 拡張機能で定義された、次の 2 つの非対称公開鍵形式がサポートされています。

  • JWK セット形式 次に例を示します。
    x-google-jwks_uri: "https://YOUR_ACCOUNT_NAME.YOUR_AUTH_PROVIDER_URL/.well-known/jwks.json"
    
  • X509例:
    x-google-jwks_uri: "https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken@system.gserviceaccount.com"
    

対称鍵形式を使用する場合は、Base64URL エンコードされた鍵文字列を含むファイルの URI に x-google-jwks_uri を設定します。

x-google-jwks_uri を省略すると、ESP は OpenID Connect Discovery プロトコルに従って、指定された OpenID プロバイダの JWKS URI を自動的に検出します。ESP は x-google-issuer/.well-known/openid-configuration に対してリクエストを行い、JSON レスポンスを解析し、トップレベルの jwks_uri フィールドから JWKS URI を読み取ります。

ESP は起動時に追加のリモート呼び出しを行う必要があるため、x-google-jwks_uri を省略するとコールド スタート時間が長くなります。したがって、JWKS URI が頻繁に変更される場合のみ、このフィールドを省略することをおすすめします。ほとんどの認定 OpenID プロバイダ(Google、Auth0、Okta など)には、安定した JWKS URI があります。

x-google-jwt-locations

デフォルトでは、JWT は Authorization ヘッダー(接頭辞 "Bearer ")、X-Goog-Iap-Jwt-Assertion ヘッダー、または access_token クエリ パラメータのいずれかで渡されます。JWT を渡す例については、Endpoints API への認証済み呼び出しの実行をご覧ください。

または、OpenAPI セキュリティ定義セクションの x-google-jwt-locations 拡張機能を使用して、JWTを使用して、JWT トークンを抽出する場所をカスタマイズします。

x-google-jwt-locations 拡張機能は、JWT ロケーションのリストを受け入れます。各 JWT ロケーションには、次のフィールドがあります。

要素 説明
header/query 必須。JWT を含むヘッダーの名前、または JWT を含むクエリ パラメータの名前です。
value_prefix 省略可。ヘッダーの場合のみ。value_prefix が設定されている場合、その値は JWT を含むヘッダー値の接頭辞と一致する必要があります。

例:

x-google-jwt-locations:
  # Expect header "Authorization": "MyBearerToken <TOKEN>"
  - header: "Authorization"
    value_prefix: "MyBearerToken "
  # expect header "jwt-header-foo": "jwt-prefix-foo<TOKEN>"
  - header: "jwt-header-foo"
    value_prefix: "jwt-prefix-foo"
  # expect header "jwt-header-bar": "<TOKEN>"
  - header: "jwt-header-bar"
  # expect query parameter "jwt_query_bar=<TOKEN>"
  - query: "jwt_query_bar"

デフォルトのJWTロケーションのサブセットのみをサポートする場合は、x-google-jwt-locations 拡張機能で明示的にリストします。たとえば、"Bearer " 接頭辞を持つ Authorization ヘッダーのみのサポートを含める場合は以下のようにします。

  x-google-jwt-locations:
    # Support the default header "Authorization": "Bearer <TOKEN>"
    - header: "Authorization"
      value_prefix: "Bearer "

x-google-audiences

x-google-audiences: STRING

この拡張機能は、OpenAPI securityDefinitions セクションで使用され、API が受け入れるオーディエンスのリストを提供します。この拡張機能では、値をカンマで区切った単一の文字列を指定できます。ユーザー間をスペースで区切ることはできません。

securityDefinitions:
  google_id_token:
    type: oauth2
    authorizationUrl: ""
    flow: implicit
    x-google-issuer: "https://accounts.google.com"
    x-google-jwks_uri: "https://www.googleapis.com/oauth2/v1/certs"
    x-google-audiences: "848149964201.apps.googleusercontent.com,841077041629.apps.googleusercontent.com"

x-google-management

x-google-management 拡張機能は API 管理のさまざまなアスペクトを制御します。このセクションでは、それらのフィールドについても説明します。

metrics

割り当てx-google-quota を組み合わせて metrics を使用し、API の割り当てを設定できます。クォータでは、API でメソッドを呼び出すことのできるレートを制御できます。例:

x-google-management:
  metrics:
    - name: read-requests
      displayName: Read requests
      valueType: INT64
      metricKind: DELTA

metrics フィールドは、次の Key-Value ペアのリストで構成されます。

要素 説明
name 必須。この指標の名前。通常、これは指標を一意に識別するリクエストのタイプ(たとえば、「read-requests」または「write-requests」)です。
displayName

これは省略可能ですが、指定することをおすすめします。Google Cloud コンソールの [エンドポイント] > [サービス] ページの [割り当て] タブに表示される指標を表すテキスト。このテキストは、[IAM と管理] および [API とサービス] の [割り当て] ページで、API ユーザーに対しても表示されます。表示名の最大文字数は 40 文字です。

読みやすくするために、関連する quota 制限の単位が、Google Cloud コンソールの表示名に自動的に追加されます。たとえば、表示名を「Read requests」にすると、Google Cloud コンソールには「Read requests per minute per project」と表示されます。これを指定しない場合、[IAM と管理] および [API とサービス] の [割り当て] ページでは、API コンシューマに「ラベルなしの割り当て」が表示されます。

API コンシューマに表示される [割り当て] ページの Google サービスの表示名と一貫性を保つため、次のような表示名を使用することをおすすめします。

  • 指標が 1 つしかない場合は、「Requests」を使用する。
  • 指標が複数ある場合は、それぞれがリクエストのタイプを示し、「requests」という単語を含める(「read-requests」または「write-requests」など)。
  • 指標に関連するコストのいずれかが 1 より大きい場合、「requests」の代わりに割り当ての単位を使用する。
valueType 必須。「INT64」でなければなりません。
metricKind 必須。「DELTA」でなければなりません。

quota

quota セクションでは、定義済み指標の quota 制限を指定します。例:

quota:
  limits:
    - name: read-requests-limit
      metric: read-requests
      unit: 1/min/{project}
      values:
        STANDARD: 5000

quota.limits フィールドは、次の Key-Value ペアになったリストで構成されます。

要素 説明
name 必須。制限の名前。サービス内で一意でなければなりません。この名前には、大文字小文字、数字、および「-」(ダッシュ文字)を含めることができ、最大長は 64 文字です。
metric 必須。この制限が適用される指標の名前。この名前は、指標の名前で指定されたテキストと一致する必要があります。指定されたテキストが指標名と一致しない場合は、OpenAPI ドキュメントのデプロイ時にエラーが発生します。
unit 必須。制限の単位。現在のところ、「1/min/{project}」に限りサポートされています。つまり、プロジェクトごとに制限が適用され、1 分ごとに使用率がリセットされます。
必須。指標の制限。これは、Key-Value ペアとして、次の形式で指定する必要があります。

STANDARD: YOUR-LIMIT-FOR-THE-METRIC
YOUR-LIMIT-FOR-THE-METRIC の代わりに、指定されたユニットで許可される最大リクエスト数の整数値を指定します。次に例を示します。

values:
  STANDARD: 5000

x-google-quota

API のメソッドを指標に関連付けるために、OpenAPI の paths セクションで x-google-quota 拡張機能を使用します。x-google-quota が定義されていないメソッドには割り当て上限が適用されません。例:

x-google-quota:
  metricCosts:
    read-requests: 1

x-google-quota 拡張機能は、次の項目で構成されます。

要素 説明
metricCosts ユーザー定義のキー: Key-Value ペア: "YOUR-METRIC-NAME": METRIC-COST
  • "YOUR-METRIC-NAME":: "YOUR-METRIC-NAME" のテキストは定義された指標名と一致する必要があります。
  • METRIC-COST:: 各リクエストのコストを定義する整数値。要求が行われると、関連する指標が指定されたコストで増分されます。コストを使用することによって、さまざまなメソッドから同じ指標を異なるレートで消費できます。たとえば、指標の割り当て上限が 1,000 で、コストが 1 の場合、呼び出し元のアプリケーションは、1 分間に 1,000 回のリクエストを行えます。同じ指標に対してコストが 2 に指定されると、呼び出し元のアプリケーションは、1 分間に 500 回のリクエストしか実行できません。

割り当ての例

次の例は、読み取りリクエストと書き込みリクエストに指標と制限を追加する方法を示しています。

x-google-management:
  metrics:
    # Define a metric for read requests.
    - name: "read-requests"
      displayName: "Read requests"
      valueType: INT64
      metricKind: DELTA
    # Define a metric for write requests.
    - name: "write-requests"
      displayName: "Write requests"
      valueType: INT64
      metricKind: DELTA
  quota:
    limits:
      # Rate limit for read requests.
      - name: "read-requests-limit"
        metric: "read-requests"
        unit: "1/min/{project}"
        values:
          STANDARD: 5000
      # Rate limit for write requests.
      - name: "write-request-limit"
        metric: "write-requests"
        unit: "1/min/{project}"
        values:
          STANDARD: 5000

paths:
  "/echo":
    post:
      description: "Echo back a given message."
      operationId: "echo"
      produces:
      - "application/json"
      responses:
        200:
          description: "Echo"
          schema:
            $ref: "#/definitions/echoMessage"
      parameters:
      - description: "Message to echo"
        in: body
        name: message
        required: true
        schema:
          $ref: "#/definitions/echoMessage"
      x-google-quota:
        metricCosts:
          read-requests: 1
      security:
      - api_key: []

x-google-api-name

サービスに含まれる API が 1 つのみの場合、API 名は Endpoints サービス名と同じになります。Endpoints では、OpenAPI ドキュメントの host フィールドで指定した名前がサービスの名前として使用されます。サービスに複数の API が含まれている場合、OpenAPI ドキュメントに x-google-api-name 拡張を追加して API 名を指定します。x-google-api-name 拡張機能を使用すると、個々の API に明示的に名前を付けて、API ごとに独立したバージョニングを確立できます。

たとえば、producer と consumer という 2 つの API で、以下の OpenAPI ドキュメントのフラグメントを使用して api.example.com という名前のサービスを設定できます。

  • Producer API を定義する producer.yaml の例

    swagger: 2.0
    host: api.example.com
    x-google-api-name: producer
    info:
      version: 1.0.3
    

  • Consumer API を定義する consumer.yaml の例

    swagger: 2.0
    host: api.example.com
    x-google-api-name: consumer
    info:
      version: 1.1.0
    

次に、2 つの OpenAPI ドキュメントをまとめて次のようにデプロイできます。

gcloud endpoints services deploy producer.yaml consumer.yaml