Amazon API Gateway の Lambda オーソライザー(旧カスタムオーソライザー)を使ってアクセス制御をするときに,Authorization ヘッダーは正しいはずなのに {"Message":"User is not authorized to access this resource"}
というエラーが出てしまう場合,Lambda オーソライザーの設定「認可のキャッシュ (Authorization caching)」に関係してる場合がある💡
前提
今回はサンプルとして Amazon API Gateway に /users
リソースを追加して POST
と GET
をサポートする.そしてどちらにも Lambda オーソライザー(トークンタイプ)によるアクセス制御を設定しておく👌
/users (POST) /users (GET)
そして,Lambda オーソライザーの実装はドキュメントに載っている Python のサンプルコードをそのまま使う📝実装としては簡易的で Authorization ヘッダーに allow
と設定すれば OK という仕組みになっている.
ポイントはこの Lambda オーソライザーの実装では以下のようなポリシーが生成されるところ💡(POST の場合)
Allow
{ "principalId": "user", "policyDocument": { "Version": "2012-10-17", "Statement": [ { "Action": "execute-api:Invoke", "Effect": "Allow", "Resource": "arn:aws:execute-api:ap-northeast-1:111111111111:xxxxxxxxxx/Prod/POST/users" } ] }, "context": { "stringKey": "stringval", "numberKey": 123, "booleanKey": true } }
Deny
{ "principalId": "user", "policyDocument": { "Version": "2012-10-17", "Statement": [ { "Action": "execute-api:Invoke", "Effect": "Deny", "Resource": "arn:aws:execute-api:ap-northeast-1:111111111111:xxxxxxxxxx/Prod/POST/users" } ] }, "context": { "stringKey": "stringval", "numberKey": 123, "booleanKey": true } }
動作確認
Amazon API Gateway の /users
リソースに POST リクエストを送信した後すぐに GET リクエストを送信する.すると {"Message":"User is not authorized to access this resource"}
というエラーが返ってくる🔥キャッシュの仕組みを理解してないと「なぜー?」となってしまう.キャッシュの TTL はデフォルトで「300秒」に設定されている👀
$ curl -X POST -H 'Authorization: allow' ${ENDPOINT}/users $ curl -X GET -H 'Authorization: allow' ${ENDPOINT}/users {"Message":"User is not authorized to access this resource"}
対策
選択肢は大きく2つあると思う👌
選択肢1
Lambda オーソライザーで生成するポリシーの条件を緩和する選択肢がある.AWS re:Post の記事にも Resource
を /*/*
にすれば OK という解決策が紹介されている💡もちろんワイルドカードで許可できない場合もあると思うし,最小権限の原則を考慮すると闇雲にワイルドカードっていう判断が危険なこともあると思う.
ちなみに前に紹介記事を書いた Powertools for AWS Lambda (Python) の Event Source Data Classes で APIGatewayAuthorizerResponse
を使ってポリシーを生成する場合,allow_all_routes()
を使うと以下のようにワイルドカードでポリシーが生成される.allow_route()
を使うと HTTP メソッド・リソースを細かく指定できる.
{ "principalId": "user", "policyDocument": { "Version": "2012-10-17", "Statement": [ { "Action": "execute-api:Invoke", "Effect": "Allow", "Resource": "arn:aws:execute-api:ap-northeast-1:111111111111:xxxxxxxxxx/Prod/*/*" } ] } }
選択肢2
次にキャッシュの TTL を短くする(もしくはキャッシュを無効化する)選択肢がある.キャッシュによる影響はなくなるけど,毎回 Lambda オーソライザーを呼び出すことになるため,パフォーマンスなどの観点で検討が必要になる.
デフォルトで 300 秒、API 所有者が 0~3600 の範囲で設定可能。