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 パスを指定します。
有効な値は 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 はすべてのトラフィックを 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_audience
や disable_auth
を指定しない場合、ESPv2 では address
に一致する jwt_audience
が自動的に設定されます。address
が設定されていない場合、ESPv2 では自動的に disable_auth
が true
に設定されます。
jwt_audience
jwt_audience: string
省略可。ESPv2 がインスタンス ID トークンを取得すると、JWT オーディエンスが指定され、ターゲット バックエンド リクエストの際に使用されます。
Endpoints for Serverless を構成する場合は、ESPv2 からのトラフィックのみを許可するようにリモート バックエンドを保護する必要があります。ESPv2 は、リクエストのプロキシ時に、Authorization
ヘッダーにインスタンス ID トークンを添付します。インスタンス 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
にコピーします。 Authorization
ヘッダーをインスタンス ID トークンでオーバーライドします。
したがって、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
拡張子の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 パスパラメータを使用しない場合。
- OpenAPI パス:
/hello
- リクエストパス:
/hello
- ターゲット リクエスト URL:
https://my-project-id.appspot.com/BASE_PATH/hello
- OpenAPI パス:
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 パスパラメータを使用しない場合。
- 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 文字です。 読みやすくするために、関連する quota 制限の単位が、Google Cloud コンソールの表示名に自動的に追加されます。たとえば、表示名を「Read requests」にすると、Google Cloud コンソールには「Read requests per minute per project」と表示されます。これを指定しない場合、[IAM と管理] および [API とサービス] の [割り当て] ページでは、API コンシューマに「ラベルなしの割り当て」が表示されます。 API コンシューマに表示される [割り当て] ページの Google サービスの表示名と一貫性を保つため、次のような表示名を使用することをおすすめします。
|
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 。
|
割り当ての例
次の例は、読み取りリクエストと書き込みリクエストに指標と制限を追加する方法を示しています。
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