Lambdaオーソライザーを理解してみる
ようやくLambdaオーソライザーが理解できました(多分)
簡単に言うと、Lambdaオーソライザーは、後続のAPIを実行するポリシードキュメントを返す仕組みです。
ポリシードキュメントを返す際、キー/値ペアを含む context マップも含まることがあります。
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-lambda-authorizer-output.html
はじめに
APIの統合リクエストは、eventをLambdaに渡したかったので「Lambda プロキシ統合の使用」を有効にしています。
気にしたことが無かったのですが、下図のメソッドリクエストの認可で、オーソライザーに設定した名前を選択しないとオーソライザーが有効にならないんですね。
オーソライザーに設定したLambdaは実行されるので、有効になっているものだと思いました・・・。※CloudWatchlogsにログ出てたら有効と思うじゃん!!!
クライアントからのAPIの呼び出しは、下記の通りcurlコマンドでAuthorizationヘッダーを指定して呼び出しています。
curl -v https://XXX.execute-api.ap-northeast-1.amazonaws.com/test -H "Authorization:1"
設定値
APIGateway
■オーソライザー
・名前:LambdaAuth
・タイプ:Lambda
・Lambda関数:LambdaAuthorization
・Lambda イベントペイロード:リクエスト
・ID ソース:Authorization
・認可のキャッシュ:無効
■API
・タイプ:REST API
・エンドポイントタイプ:パブリック
・メソッド:GET
・メソッドリクエスト(認可):LambdaAuth
・Lambda プロキシ統合の使用:有効
・統合タイプ:Lambda関数(AllowResponse)
・ドメイン:https://XXX.execute-api.ap-northeast-1.amazonaws.com
・ステージ:test
Lambda(オーソライザー用)サンプル
・event情報(headersのIDソースなど)を元に、認証判定
・許可の場合:プリンシンバルID、後続処理のポリシードキュメント(資格情報)、ContexをReturn
・拒否の場合:プリンシンバルID、後続処理のポリシードキュメント(資格情報)をReturn
Contexはkey-valueで定義できて、返却した値はAPIで指定したLambda関数のevent['requestContext']['authorizer']に格納されます。
def lambda_handler(event, context): token = event['headers']['Authorization'] if token == '1': return { 'principalId' : "LambdaAuthorization", 'policyDocument' : { 'Version' : '2012-10-17', 'Statement' : [ { "Action": "execute-api:Invoke", "Effect": "Allow", #下記の形式を許可しますが、汎用的なオーソライザーにすると思うので*を用いています。 #"Resource": "arn:aws:execute-api:ap-northeast-1:{アカウントID}:{api-id}/{{stageNameOrWildcard}}/{{httpVerbOrWildcard}}/{{resourcePathOrWildcard}}" "Resource": "arn:aws:execute-api:ap-northeast-1:*" } ] }, 'context': { "sukina": "KeyValue", "wo": "settei", "dekiru": "YO" } } return { 'principalId' : "LambdaAuthorization", 'policyDocument' : { 'Version' : '2012-10-17', 'Statement' : [ { #公式ではexecute-api:Invokeに対してDenyしていますが、全てのアクションDenyで良いかなと思って下記のようにしています。 "Action": "*", "Effect": "Deny", "Resource": "*" } ] } }
Lambda(API用)サンプル
受取ったeventをbodyに渡すだけの関数です。
import json def lambda_handler(event, context): jsn_str = json.dumps(event, ensure_ascii=False, indent=2) return { 'isBase64Encoded': False, 'statusCode': 200, 'headers': {}, 'body': jsn_str }
豆知識
Lambdaオーソライザのタイムアウトと、後続の統合リクエストで呼び出すLambdaは、タイムアウトの最大値はそれぞれ29秒のようです。(Lambdaオーソライザは動作仕様で確認)
なお、Lambdaオーソライザで28秒、統合リクエストで28秒かかるLambda関数を設定してみましたが、56秒程で応答が返ってきましたのでAPIGateway全体で29秒以内となるわけでは無いようです。
クライアントにエラーが返る場合のフロー図
Lambdaオーソライザーの関数で拒否(Deny)された場合
下記コマンドのように、オーソライザーのLambda関数で拒否(Deny)される値の場合は、クライアント側にはエラー(403 Forbidden)がレスポンスされる。
curl -v https://XXX.execute-api.ap-northeast-1.amazonaws.com/test -H "Authorization:2"
定義されたヘッダーがない場合
下記コマンドのように、ヘッダーにイベントソース(Authorization)が無い場合は、クライアント側にはエラー(401 Unauthorized)がレスポンスされる。
curl -v https://XXX.execute-api.ap-northeast-1.amazonaws.com/test -H "Auth:1"
Lambdaオーソライザーの関数がエラーの場合
クライアント側にはエラー(500 Internal Server Error)がレスポンスされる。