~~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 オーソライザー}}