年中アイス

いろいろつらつら

AWS API Gateway+LambdaでSlackにメッセージをPOSTする(後編)

前編中編にて、AWS API Gateway + Lambdaを使って、post-slack WebAPIを作り、テスト実行まで行いました。後編では、API keyの設定と実際に使えるようにデプロイをしていきます。

Slack Webhook URLは、それを知っていれば誰でも使うことができます。せっかくAPI Gatewayを使うので、API keyを使って制限をかけます。*1Usage PlanとAPI keyを使うと、アクセス自体の制限以外に、使用量の制限、スロットリングをかけることができます。

API GatewayのStageとUsagePlanとAPI key

今回の部分に関して、それぞれ用語とその関連を先に頭に入れると理解しやすいので、先にその説明をします。

Stage

API GatewayのStageは、いわゆる開発(dev)、検証(staging)、本番(prod)といった、動作環境を指します。これらを作ることで、一般的な開発フローと同じく、まず開発環境にデプロイしてーという流れと同じことができます。*2

Usage Plan

Webサービスなどでの、Free PlanやStandard Plan、Unlimited Planみたいなものです。スロットリングや使用量制限を定義します。Usage PlanはStageと紐付ける必要があり、Stageがないと作れません。

API key

対象ごとに発行する認可用のkeyです。API keyは、発行は単体でできますが、Usage Planと紐付けないと、実際にAPIで使うことはできません。

post-slackでの設定

前述の説明で、およそそれぞれの関連性がわかったかと思います。ここからは実際にそれを設定していきます。この部分がAWSコンソール上から作成しようとすると、先に作る必要があるものがあったりなどハマりがちなので、スムーズに行く順番で行っていきます。

API keyの必須設定と、API GatewayのStageの作成(=デプロイ)

まず引っかかりやすいのが、Stageを作成するには、そのWebAPIを1回はデプロイする必要があることです。左メニューから、Stageを選択して、[Create]で進むと、必須項目のDeploymentで選択できるものがなく、「どうやって環境作るんだろう・・・」と感じてしまいます。*3

デプロイするものができるまでStageは不要というのもわかるんですが、API keyで制限をかけるには、Usage Planが必要で、Usage Planの作成にはStageが必要でなので、ハマります。

今回は、API key必須の設定だけしてデプロイすることでAPI keyでの制限を有効にして進めていきます。

post-slack APIのResource -> / POSTを選択します。前回も使ったマス目の並ぶ画面です。Method Requestを選択します。

f:id:reiki4040:20170207233007p:plain:w400

API Key Requiredをtrueに変更します。これだけです。Authorizationというのもありますが、こちらは今回使いません。

f:id:reiki4040:20170207233027p:plain:w400

API key必須の設定ができたので、デプロイしてStageを作ります。[Action]-> Deploy APIを選択します。

f:id:reiki4040:20170207233254p:plain:w400

Deploy APIというダイアログが出てくるので、Deployment Stageで[New Stage]を選びます。そうするとフォームが出てくるので、devというStageにします。Deploymentの所は、デプロイ(リリース)の内容を入れます。今回は適当にfirst deployにしてます。*4 [Deploy]を押すとデプロイされます。

f:id:reiki4040:20170207233137p:plain:w400

URLが割り当てられます。これを後で使うので、コピー等で取っておいてください。 f:id:reiki4040:20170207233356p:plain

WebAPIのURLは以下のフォーマットです。

https://<ランダム>.execute-api.ap-northeast-1.amazonaws.com/<Stage名>

早速curlで試してみます。--dump-header -は、レスポンスヘッダの出力を標準出力に出すオプションです。

curl -XPOST -H 'Content-Type: application/json'  https://<あなたのURL> -d '{"message":"hi"}' --dump-header -

HTTP/1.1 403 Forbidden
Content-Type: application/json
Content-Length: 23
Connection: keep-alive
Date: Tue, 07 Feb 2017 13:39:33 GMT
...AWS独自ヘッダーかとか色々...

{"message":"Forbidden"}

はい。403の権限がないエラーになります。API keyがないからです。

Usage Planの作成とAPI keyの作成

次にUsagePlanを作ります。左メニューのUsagePlanを選択し、[Create]で作り始めます。

f:id:reiki4040:20170211150120p:plain:w300

ここではdevという名称で、Planを作ります。スロットリングは適当に10/secぐらい、burstも10にしておきます。使用制限は1,000/dayぐらいにしてみます。この辺の値は適当なので、適宜どうぞ。入れたら[Next]で次へ。

f:id:reiki4040:20170211150144p:plain:w400 f:id:reiki4040:20170211150153p:plain:w500

どのAPIのStageに適用するかを設定するので、[Add API Stage]を選択し、 f:id:reiki4040:20170211150253p:plain:w400

post-slack APIと先ほど作ったdev Stageを指定して、チェックを選択します。 f:id:reiki4040:20170211150358p:plain:w400

紐付けられたら、[Next]で進みます。 f:id:reiki4040:20170211150404p:plain:w400

次はAPI keyの設定に進みます。[Create API keyand Add to Usage Plan]を選択し、新しくAPI keyを発行します。

f:id:reiki4040:20170211150755p:plain:w400

Nameはnotification-programにします。ここは好きなもので構いません。keyは、Auto Generateでランダムに生成します。入れたら[Save]します。 f:id:reiki4040:20170211150907p:plain:w400

Usage PlanのAPI key一覧に戻るので、notification-programというkeyがあることを確認して、[Done]で完了します。 f:id:reiki4040:20170211151738p:plain:w400

作成後、API keyタブから、notification-programを選択すると、API keyの詳細を見ることができます。

f:id:reiki4040:20170211231517p:plain:w500

API keyのshowを選択すると、値を見ることができます。これをリクエストヘッダに入れて使います。 f:id:reiki4040:20170211151950p:plain

これでpost-slack APIにdev PlanとAPI keyが出来ました。

API keyを使ってcurlからslackへPOST

さていよいよ完成したので、curlを使ってリクエストしてみます。API keyはx-api-keyというリクエストヘッダで送ります。

curl -XPOST -H 'Content-Type: application/json' -H 'x-api-key: <あなたのAPI key>' https://<あなたのAPI URL> -d '{"message":"post slack message from my machine via API Gateway/Lambda!"}' --dump-header -

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 17
Connection: keep-alive
Date: Tue, 07 Feb 2017 14:05:37 GMT
...AWS独自ヘッダーかとか色々...

"posted to slack"

いやーレスポンスがひどい。でもSlackには表示されました! f:id:reiki4040:20170211152540p:plain:w500

これで、HTTPS+API keyでslackへのPOSTができるようになりました。後はスクリプトから叩いたり、他の人に渡す時は別のAPI keyを発行して渡して使うことができます。

参考

*1:もちろん、元のSlack Webhook URL自体へのアクセスを制限できるわけではありません

*2:加えて、簡単にStageを追加できるので、開発フロー上の環境だけでなく、個別用途での環境も作ることができます。

*3:触ってから説明書読むタイプにはハマるポイント

*4:本来はバージョン番号とかそういうのを入れる場所なのかなと。後で別のStageを作る時は、このDeploymentから選択することができます。