Cloud Endpoints で作成した自社開発 OpenAPI で顧客ごとにリクエスト回数を制限する

自社で API 開発をして公開した場合、料金プランを分けたり顧客ごとにカスタマイズしたりと、API の個々の呼び出し元を区別したい時があると思います。
また、セキュリティの観点からも、API を大量のリクエストから保護する必要があります。

今回は Cloud Endpoints を使った自社開発の Open API について、個別にリクエスト回数を割り当てる方法について紹介したいと思います。

Cloud Endpoints で読み込み/書き込みのリクエスト回数を制限できるか

Cloud Endpoints の各サービスに対して、ユーザー(組織/プロジェクト)で割り当てを追加することができます。
ちなみにデフォルトでは、Read requests は 1 分あたり 10 回、Write requests は 1 分あたり 1 回となっています。

ユーザー(組織/プロジェクト)ごとにリクエスト回数上限を設定した例

API の個々の呼び出し元を区別してリクエスト回数を制限するための構成

先ほど触れた通り、Cloud Endpoints のリクエスト回数の割り当ては、プロジェクト、もしくは組織ごとに設定することができます。つまり、顧客ごとに制限を変えたい場合は、顧客ごとにプロジェクト(もしくは組織)を作成する必要があります。
そして、各プロジェクト(組織)に対して割り当てを設定します。

API の個々の呼び出し元を区別する必要がある場合、(中略)個々の呼び出し元を区別するには、呼び出し元ごとに個別の Google Cloud プロジェクトと API キーを作成する必要があります。

Google Cloud におけるプロジェクト、組織、リソースの階層構造

これを踏まえて、実際にどのようにプロジェクトを切っていくかというと、例えば、この様な構造が考えられます。

一番上の組織は自社で、下のフォルダには、商品、顧客のフォルダを切っています。
商品のフォルダに作成したプロジェクトで、API を動かします。

上の図ではプロジェクト「projectA」のなかに、バックエンドアプリや Endpoints サービスがデプロイされています。API のサービス名は「Cloud Endpoints + hoge」となっています。

プロジェクト「red」、「blue」は、区別したいAPIの呼び出し元(例えば顧客など)ごとに作成します。ここでは、公開済みの「Cloud Endpoints + hoge」APIサービスを有効化して、API キーを発行するだけで、他のリソースは使いません。

API の個々の呼び出し元を区別してリクエスト回数を制限するための手順

手順① 呼び出し元ごとに個別の Google Cloud プロジェクトを作成する

  1. 呼び出し元ごとに個別のプロジェクトを作成します。
  2. 各プロジェクトで、API を有効化して API キーを作成します。
  3. それぞれの呼び出し元に API キーを付与します。

手順② 1 分あたりのリクエスト数を制限する

  1. テキスト エディタで OpenAPIドキュメント(YAMLファイル)を開きます。
  2. x-google-management の下にインデントされた metrics 定義を追加します。
  3. metrics と同じレベルに quota フィールドを追加し、quota セクション内にネストされた limits フィールドを追加します。

x-google-management:
metrics:
    # Define a metric for read requests.
    – name: “read-requests”
      displayName: “Read requests”
      valueType: INT64
      metricKind: DELTA
  quota:
    limits:
      # Define the limit or the read-requests metric.
      – name: “read-limit”
        metric: “read-requests”
        unit: “3/min/{project}”
        values:
          STANDARD: 1000
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: []

limits フィールドで制限を追加しています。上の例では、「Read requests は、1分 あたり 3回 まで」となっています。
x-google-quota フィールドでは、「POST 1回ごとに Read requests を1回とカウント」という意味のことを書いてます。これを書かないとカウントされないので注意しましょう。

なお、2022年10月現在時点では、制限の単位の変更はできませんので注意しましょう。
例えば、「1分あたり」を「1時間あたり」「1日あたり」などに変更することはできません。
試しにminの部分をdayにしてデプロイしてみたのですが、エラーになりました。

$ gcloud endpoints services deploy hoge.yaml – project product1
ERROR: (gcloud.endpoints.services.deploy) INVALID_ARGUMENT: Cannot convert to service config.
‘location: “toplevel”’
kind: ERROR
message: “quota: Config specified QuotaLimit.Unit of \’1/day/{project}\’ in QuotaLimit \’read-limit\’, but QuotaLimit currently only supports the unit(s) \’1/day/{project}\’” 

少し残念ですが、仕方ないですね。

手順③ OpneAPI ドキュメント(YAMLファイル)を Endpoints に再デプロイする

PCのターミナルを立ち上げ、gcloud endpoints services deploy コマンドを使用してデプロイします。
なお、サービス構成(OpneAPI ドキュメント)の変更は ESPv2 には伝播されないので、ESPv2 イメージも作り直す必要があります。

詳しい手順は以下を参照してください。
Endpoints 構成をデプロイする

割り当ての異なる API キーで、それぞれ連打テストしてみた

まずはredプロジェクト。Read requests は1分あたり 3 回です。

割り当て追加後、グラフに赤い点線が追加される様になりました。

red プロジェクトの API キーで 10 回連打した結果

<エラー内容>

{“code”: 429, “message”:”RESOURCE_EXHAUSTED:Quota exceeded for quota metric ‘Read requests’ and limit ‘Read requests per minute’ of service ‘[サービスURI]’ for consumer ‘project_number: ‘[プロジェクトID]”}

ばっちり、リクエスト上限に達して 429 エラーを返してくれています。
ちなみに、1分経過後、また200で返ってくるようになりました。

ここで思ったのは、正確に 3回を超えたら制限が始まる、というのはできないっぽいなということ。

続いて、blue プロジェクト。Read requests は1分あたり 100 回です。
blue プロジェクトの API キーで 10 回連打した結果

リクエスト回数上限未達のためエラー429にならず、200でレスポンス内容も正常であることを確認できました。

まとめ

  • Cloud Endpoints を使った自社開発の OpenAPI について、個々の呼び出し元(例えば顧客など)を区別することができる
  • 個々の呼び出し元に、それぞれ違った制限をかけることもできる
  • 制限の単位「1分あたり」を「1時間あたり」「1日あたり」などに変更することはできない

関連記事

自社で API開発する前に知らなきゃ後悔する3つの基本

Cloud Endpoints を使って簡単・安全に自社サービスをAPI化する方法

Cloud Endpoints のデベロッパーポータル提供終了による影響とその対応

参考文献

呼び出し元ごとに個別の Google Cloud プロジェクトを作成する

OpenAPI ドキュメントに割り当てを追加する

割り当てについて

Rate limit your API usage with Cloud Endpoints quotas

Endpoints 構成をデプロイする