~~NOCACHE~~ ## Lambdaオーソライザーを理解してみる ようやくLambdaオーソライザーが理解できました(多分) 簡単に言うと、Lambdaオーソライザーは、後続のAPIを実行するポリシードキュメントを返す仕組みです。 ポリシードキュメントを返す際、キー/値ペアを含む context マップも含まることがあります。 https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-lambda-authorizer-output.html 下記は、認証に成功した場合のフロー図です。 {{:Aws:APIGateway:pasted:20210531-172514.png?direct 1000x0}} ### はじめに APIの統合リクエストは、eventをLambdaに渡したかったので「Lambda プロキシ統合の使用」を有効にしています。 気にしたことが無かったのですが、下図のメソッドリクエストの認可で、オーソライザーに設定した名前を選択しないとオーソライザーが有効にならないんですね。 オーソライザーに設定したLambdaは実行されるので、有効になっているものだと思いました・・・。※CloudWatchlogsにログ出てたら有効と思うじゃん!!! {{:Aws:APIGateway:pasted:20210526-225519.png?direct 500x0}} クライアントからの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)された場合のフロー図になります。 ※ポリシードキュメント(資格情報)に、APIの実行権限が無いためエラーとなる。 {{:Aws:APIGateway:pasted:20210531-172453.png?direct 1000x0}} #### 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)がレスポンスされる。 {{tag>AWS APIGateway Lambda オーソライザー}}