Extensible Service Proxy(ESP)、Extensible Service Proxy V2(ESPv2)、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 パスを指定します。
有効な値は configured と all です。
デフォルト値は 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-allowはallに設定されている。- 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 はすべてのトラフィックを単一のローカル バックエンドにプロキシ処理するように構成されています。ローカル バックエンド アドレスは、--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_audience や disable_auth を指定しない場合、ESPv2 では address に一致する jwt_audience が自動的に設定されます。address が設定されていない場合、ESPv2 では自動的に disable_auth が true に設定されます。
jwt_audience
jwt_audience: string
省略可。ESPv2 がインスタンス ID トークンを取得すると、JWT オーディエンスが指定され、ターゲット バックエンド リクエストの際に使用されます。
サーバーレス用に Endpoints を構成する場合は、ESPv2 からのトラフィックのみを許可するようにリモート バックエンドを保護する必要があります。ESPv2 は、リクエストをプロキシ処理するときにインスタンス ID トークンを Authorization ヘッダーに添付します。インスタンス ID トークンは、ESPv2 のデプロイに使用されたランタイム サービス アカウントを表します。リモート バックエンドは、この添付されたトークンに基づいて、リクエストが ESPv2 からのものであることを確認できます。
たとえば、Cloud Run にデプロイされたリモート バックエンドは、IAM を使用して次のことを行うことができます。
- 特別な
allUsersプリンシパルからroles/run.invokerを取り消して、認証されていない呼び出しを制限します。 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 は次のようにします。
- 元の値を新しいヘッダー
X-Forwarded-Authorizationにコピーします。 - インスタンス ID トークンで
Authorizationヘッダーをオーバーライドします。
したがって、API クライアントが Authorization ヘッダーを設定する場合、ESPv2 の背後で実行中のバックエンドは X-Forwarded-Authorization ヘッダーを使用して JWT 全体を取得する必要があります。認証方法が設定されていない場合、ESPv2 は検証を行わないため、バックエンドがこのヘッダーで JWT を検証する必要があります。
disable_auth
disable_auth: bool
省略可。このプロパティは、ESPv2 がインスタンス ID トークンの取得を禁止し、リクエストへのアタッチを禁止すべきかどうかを決定します。
ターゲット バックエンドを構成する際、次のいずれかの条件に該当する場合、IAP または IAM を使用して ESPv2 からのリクエストの認証を行うことはできません。
- バックエンドは未認証の呼び出しを許可する必要があります。
- バックエンドには 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.1 と h2 です。
HTTP および HTTPS バックエンドのデフォルト値は http/1.1 です。
HTTP/2 をサポートするセキュア HTTP バックエンド(https://)の場合は、パフォーマンス改善のために、このフィールドを h2 に設定します。これは、 Google Cloud サーバーレス バックエンドに推奨されるオプションです。
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の URLx-google-backend拡張子に付加して計算されます。CONSTANT_ADDRESS:x-google-backend拡張子のaddressURL によって定義されるため、ターゲットのリクエストパスは定数となります。対応する OpenAPI パスにパラメータが含まれている場合、パラメータ名とその値はクエリ パラメータとなります。
例:
APPEND_PATH_TO_ADDRESSaddress: 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 パスパラメータを使用しない場合。
- OpenAPI パス:
/hello - リクエストパス:
/hello - ターゲット リクエスト URL:
https://my-project-id.appspot.com/BASE_PATH/hello
- OpenAPI パス:
CONSTANT_ADDRESSaddress: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 パスパラメータを使用しない場合。
- OpenAPI パス:
/hello - リクエストパス:
/hello - ターゲット リクエスト URL:
https://us-central1-my-project-id.cloudfunctions.net/helloGET
- OpenAPI パス:
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 セクションで使用され、JWT 認証中に JWT aud フィールドが一致する必要があるオーディエンスのリストを提供します。この拡張機能では、値をカンマで区切った単一の文字列を指定できます。ユーザー間をスペースで区切ることはできません。指定されていない場合、フラグ --disable_jwt_audience_service_name_check が使用されていない限り、JWT aud フィールドは OpenAPI ドキュメントの host フィールドと一致する必要があります。このフラグが使用されていて、x-google-audiences が指定されていない場合、JWT aud フィールドの確認は行われていません。
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 文字です。 読みやすくするために、関連する割り当て上限の単位が、Google Cloud コンソールの表示名に自動的に追加されます。たとえば、表示名を「Read requests」にすると、Google Cloud コンソールには「Read requests per minute per project」と表示されます。これらを指定しない場合、[IAM と管理] および [API とサービス] の [割り当て] ページでは、API コンシューマに「ラベルなしの割り当て」が表示されます。 API コンシューマに表示される [割り当て] ページの Google サービスの表示名と一貫性を保つため、次のような表示名を使用することをおすすめします。
|
| valueType | 必須。「INT64」でなければなりません。 |
| metricKind | 必須。「DELTA」でなければなりません。 |
quota
quota セクションでは、定義済み指標の 割り当て 制限を指定します。例:
quota:
limits:
- name: read-requests-limit
metric: read-requests
unit: 1/min/{project}
values:
STANDARD: 5000
quota.limits フィールドは、次の Key-Value ペアになったリストで構成されます。
| 要素 | 説明 |
|---|---|
| name | 必須。制限の名前。サービス内で一意でなければなりません。この名前には、大文字小文字、数字、および「-」(ダッシュ文字)を含めることができ、最大長は 64 文字です。 |
| 指標 | 必須。この制限が適用される指標の名前。この名前は、指標の名前で指定されたテキストと一致する必要があります。指定されたテキストが指標名と一致しない場合は、OpenAPI ドキュメントのデプロイ時にエラーが発生します。 |
| 単位 | 必須。制限の単位。現在のところ、「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。
|
割り当ての例
次の例は、読み取りリクエストと書き込みリクエストに指標と制限を追加する方法を示しています。
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