【API Gateway】API呼び出しにAPIキーを設定する

Amazon API Gatewayで公開するAPIにはAPIキーを設定できます。これにより、以下のようなことができます。

* APIキーを知っている人だけがそのAPIを呼び出すことができる
* ユーザごとにAPIキーを発行し、ユーザごとに呼び出し回数に制限をかけることができる

これを試してみました。

# 説明の前提

Amazon API Gatewayの公式ドキュメントの「[API GatewayコンソールでサンプルからAPIを作成してテストする](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-create-api-from-example.html)」の手順に従って、サンプルのAPIを作成したことを前提とします。
このAPIに対してAPIキーを設定します。

# 手順

## APIキーの作成

AWSマネジメントコンソールにサインインし、Amazon API Gatewayの管理コンソールを開きます。
画面左端の一覧の「APIキー」をクリックします。
すると、APIキー一覧が表示されますので、「アクション」ボタンをクリックし、プルダウンメニューから「APIキーの作成」を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122210/bba5cb93-2ca7-9c83-e560-68e7af4f173c.png)

APIキーの作成画面が表示されるので、以下のように入力、設定して「保存」ボタンをクリックします。

* 名前：testkey
* APIキー：自動生成

![image.png](https://qiita-image-store.s3.amazonaws.com/0/122210/c348a818-38bf-7ab0-5c17-878a384bb7f2.png)

作成したAPIキーの情報が表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122210/e22db1ca-303c-1d06-6576-dc154374d312.png)

ここで、「APIキー」の横の「表示」をクリックすると表示されるAPIキー文字列をメモしておきます。
あとで、APIを呼び出す際にこのAPIキーが必要になります。

## 使用量プランの作成

次に、使用量プランを作成します。
画面左側リストの「使用量プラン」をクリックし、「作成」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122210/c79b64e3-52a5-5aeb-01f9-4c3946b79999.png)

画面右側に「使用量プランの作成」パネルが表示されるので、以下のように入力して「次へ」ボタンをクリックします。

* 名前: TestPlan
* スロットリングの有効化：チェックあり
* レート：1
* バースト：1
* クォータを有効にする：チェックあり
* リクエスト数の指定：3リクエスト/月

![image.png](https://qiita-image-store.s3.amazonaws.com/0/122210/fdb76ee5-1418-65ec-fcb4-415a27e86e2c.png)

これで使用量プランが作成されました。作成したTestPlanの情報が画面に表示されています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122210/bbcbe751-63c8-c77f-a5f4-20e00085980d.png)

## 使用量プラン、APIステージ、APIキーの関連付け

作成した使用量プランを、作成済みのPetStoreのAPIステージに関連づけます。画面下側の「APIステージの追加」ボタンをクリックし、表示されたフォームで以下のように選択します。

* API： PetStore
* ステージ: test

選択すると、チェックマークのボタンが出てくるので、それをクリックして関連づけを確定させます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122210/3d3fb6ea-72fb-9d4f-23d4-d8bcaa80881b.png)

次に、使用量プランTestPlanと、先ほど作成したAPIキーｔestkeyを関連付けします。
画面上部の「APIキー」タブをクリックし、「APIキーを使用量プランに追加」をクリックします。
名前を入力する欄が出現するので、「testkey」と入力し、右側のチェックマークのボタンをクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122210/f859e50a-3df2-6aff-5bda-c2fd5c002869.png)

これで、使用量プランとAPIキーが関連づけられました。

## API Gateway APIの設定を変更し、APIキーを必須にする。

最後に、PetStoreのAPIの設定を変更し、APIキーを必須項目にします。
今回は例として、PetStore APIのルートリソースのGETメソッドに対して、APIキーを必須に設定します。

API Gateway コンソールの 画面左側の「API」→「PetStore」の所をクリックし、「リソース」をクリックします。
画面に表示されたリソースツリーのルート「/」の「GET」のところをクリックします。
表示されたリクエスト・レスポンスのマッピング画面の「メソッドリクエスト」のリンクをクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122210/4272fccd-342b-9f79-0f02-1db7f7a2ee67.png)

すると、 メソッドリクエストの設定画面が表示されます。
「APIキーの必要性 false」となっているので、横の鉛筆アイコンをクリックして、「true」に変更し、チェックマークのボタンを押して変更を保存します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122210/ef8e11fd-9a98-57da-5271-3c9770d7f615.png)

設定変更したAPIをデプロイしましょう。「アクションボタン」→「APIのデプロイ」とクリックし...
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122210/71f669ae-42d3-fd6c-44ed-277e74ce4ce4.png)

「デプロイされるステージ」に「test」を指定して「デプロイ」ボタンをクリックです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122210/aab56457-6080-e512-71fe-769a7b5ccdae.png)

デプロイしたAPIステージのURLが表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122210/b2b46c15-57dd-f64f-f35c-580520523875.png)

これで、PetStore APIのルートに対するGETメソッドは、APIキーをヘッダにつけなければならなくなりました。

# 動作確認

先ほどデプロイしたURLにcurlでアクセスしてみましょう。

```sh
$ curl https://0puhoqspu0.execute-api.ap-northeast-1.amazonaws.com/test
{"message":"Forbidden"}
```

ルートリソースに対するGETメソッドを発行しましたが、APIキーをリクエストヘッダにつけていないので"Forbidden"と怒られてしましました。

APIキーをつけてみましょう

```sh
$ curl https://0puhoqspu0.execute-api.ap-northeast-1.amazonaws.com/test \
     --header 'x-api-key:<あなたのAPIキー>'
<html>
    <head>
        <style>
        body {
            color: #333;
            font-family: Sans-serif;
            max-width: 800px;
            margin: auto;
        }
        </style>
    </head>
    <body>
        <h1>Welcome to your Pet Store API</h1>
        <p>
            You have succesfully deployed your first API. You are seeing this HTML page because the <code>GET</code> method to the root resource of your API returns this content as a Mock integration.
        </p>
        <p>
            The Pet Store API contains the <code>/pets</code> and <code>/pets/{petId}</code> resources. By making a <a href="/test/pets/" target="_blank"><code>GET</code> request</a> to <code>/pets</code> you can retrieve a list of Pets in your API. If you are looking for a specific pet, for example the pet with ID 1, you can make a <a href="/test/pets/1" target="_blank"><code>GET</code> request</a> to <code>/pets/1</code>.
        </p>
        <p>
            You can use a REST client such as <a href="https://www.getpostman.com/" target="_blank">Postman</a> to test the <code>POST</code> methods in your API to create a new pet. Use the sample body below to send the <code>POST</code> request:
        </p>
        <pre>
{
    "type" : "cat",
    "price" : 123.11
}
        </pre>
    </body>
</html>Y
```

<あなたのAPIキー>のところは、「APIキーの作成」の節でメモしたAPIキー文字列で置き換えてください。
APIキーをつければ、期待通りにAPIの説明が書かれたHTMLが返されました。

なお、このAPIキーには使用量プランで呼び出し回数に制限をかけてあるので、上記のcurlコマンドを連発で実行すると、以下のようにエラーメッセージが返されるようになります。

```sh
{"message":"Too Many Requests"}
```

# 注意

今回デプロイしたAPIは、ルートリソース以外にはAPIキーが設定されていません。
第三者に不用意に呼び出されてしまわないよう、動作確認が終わった後は、ステージを削除しておきましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/122210/f736e61f-94ed-83b8-4733-28dba70bd28b.png)


# まとめ

APIキー、使用量プランを作成し、API Gatewayのステージと関連付けしました。これにより、API Gateway APIに対して以下を確認しました。

* APIキーを知っている人だけがアクセスできること
* APIキーに関連づけた使用量プランを超えたアクセスを制限できること