概要
前回の Lambda と ElastiCache は VPC 内に引きこもるため(そういうセキュリティグループに配置したので)、インターネットからアクセスすることはできません。
simplestar-tech.hatenablog.com
API Gateway からトークン認証付きで Lambda を呼べるようにして、高速かつ安全に ElastiCache 操作をインターネットから実現してみます。
API Gateway を作る
適当な REST API を作成すると、アクションメニューからリソース or メソッドを作成できるようになります。
リソースは階層を形成し、メソッドは HTTP メソッドに対応し GET や POST, PUT を意味します。
今回はリソースに cubewalkblocks を追加し、そこに GET メソッドを追加しました。GET メソッドを選択すると次のデザイナー表示が確認できます。いや、もうすでに色々いじってしまっていますが…
Authorizer 機能を持つ Lambda を作る
目的は公開する API ですから、秘密の文字列を知る者だけが呼び出し可能となるようにするためです。
手順はこちら
docs.aws.amazon.com
Lambda を作ったら、その後は API Gateway の「オーソライザー」にて新しく Authorizer を作ります。ここで注意したいのが Lambda を呼べるように API Gateway を許可すること
新規作成時に許可ダイアログが出るからいいけど、既存のものをコピーすると気づかず、API 呼び出しにてサーバー内エラー 500 ステータスコードが返るから気をつけて(ハマった)
ここでトークンのソースを token としているので、リクエストヘッダーには token を入れないといけなくなります。
また、正規表現でチェックしているので、まずはこれに引っかからない者は、Lambda 呼び出し前に弾かれることになります。(攻撃されてもお金かからなくて良い)
ここで指定した token の値が Lambda の var token = event.authorizationToken; の値として手に入るというワケ
いろいろと繋がりましたでしょうか?
API Gateway と Lambda との接続
メソッドの実行を開いて、Lambda を選ぶだけで OK権限付与する話を進めれば、このとおり Lambda の方も勝手に API Gateway とつながったことになります。
Lambda 側の注意点として、レスポンスは status code 200 の json とすること
今回は python 実装だったので、こんな感じ
return { "statusCode": 200, "body": "\"\"" }
理由は統合レスポンスを「パススルー」に設定しているからこれで Lambda の戻り値をそのまま、呼び出し元に与えることができます。
デプロイ
ずっと作ってきた API ですが、デプロイしない限りは外部から呼び出すことができません。
アクション > API のデプロイ を選択してデプロイします。
デプロイ先は prod にするのが一般的みたい
デプロイに成功すると url が確定します。
curl で呼び出しテスト
curl はコマンドラインで http 通信を試せるツールですが(色々な環境にインストール可能なもので、 Windows なら git for windows 入れたら git bash のコンソールから叩ける)
さて、Authorizer の Lambda の実装に依存しますが、ここまで作ってきた API を外部から呼び出すと次の通り
$ curl -X GET -H 'token:cubewalk-allow' https://xxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/cubewalkblocks -v { [35 bytes data] 100 35 100 35 0 0 39 0 --:--:-- --:--:-- --:--:-- 39{"statusCode": 200, "body": "\"\""}
OK
ちなみに token を間違えると。。。
$ curl -X GET -H 'token:arere' https://xxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/cubewalkblocks -v { [26 bytes data] 100 26 100 26 0 0 101 0 --:--:-- --:--:-- --:--:-- 101{"message":"Unauthorized"}
こんな感じで、認証エラーのメッセージが返ってきます。
まとめ
・REST API を API Gateway から作るまでは簡単
・Authorizer の Lambda も手順通りなら作れるがAPI Gateway にて Authorizer を作り切るところまでが覚えゲー(トークンソースと Authorizer Lambda実装がつながればこっちのもの)
・Lambda 呼び出し権限の付与には注意(特に既存の API をコピーしたときは)
・レスポンスをパススルーするなら json で statusCode 200 も返すこと
・デプロイして初めて外部から呼び出せる API の url が確定する
ひとまずこれで、認証付き API から Lambda が呼び出せるようになりました。
前の記事で Lambda から ElastiCache の Redis の get/set してましたけど、今回の API Gateway からつないで実行することができました。