AWS Lambdaには、関数をHTTPSで呼び出せるFunction URLがあります。

認証タイプをNONEにすれば、そのままブラウザやcurlから呼び出せると思っていましたが、CloudFormationで作ったFunction URLへアクセスすると、403 Forbiddenになりました。

今回は、権限を一つずつ追加しながら、どの設定が足りなかったのか確認します。

先に結果を書くと、自分の環境ではlambda:InvokeFunctionUrlを追加した時点で呼び出せました。ただし、現在のAWSドキュメントには新しいFunction URLで2つの権限が必要と書かれています。この違いも含めて、実際に確認できたところまで残します。

Lambda Function URLとは?

Lambda Function URLは、Lambda関数に専用のHTTPS URLを付ける機能です。

API Gatewayを作らなくても、次のようなURLからLambdaを呼び出せます。

https://xxxxxxxx.lambda-url.ap-northeast-1.on.aws/

認証タイプは、AWS_IAMNONEから選べます。

AWS_IAMでは、AWSの認証情報を使ってリクエストします。NONEでは、リクエスト時のIAM認証を行いません。

↑だとNONEを選んだ時点で公開されるように見えます。

自分はここを勘違いしていました。

今回作った検証環境

検証用のファイルは次のようにしました。

lambda-function-url-403/
├── template.yaml
├── deploy.sh
├── run_experiment.sh
├── show_policy.sh
└── cleanup.sh

template.yamlで作るのは、Lambda関数、実行ロール、Function URLだけです。

Lambdaは、次のJSONを返すだけにしました。

{"message": "Function URL works"}

今回は、Function URLをコンソールではなくCloudFormationで作ります。

あとで分かったことですが、コンソールまたはAWS SAMでNONEのFunction URLを作ると、公開に必要なリソースベースポリシーも自動で作られます。

AWS CLI、CloudFormation、Lambda APIから作る場合は、自分でポリシーを追加する必要があるようです。

Function URLを作る

AWS CLIへログイン済みの状態で、検証環境を作ります。

cd lambda-function-url-403
bash deploy.sh

内部では、次のCloudFormationテンプレートをデプロイしています。

DemoFunctionUrl:
  Type: AWS::Lambda::Url
  Properties:
    AuthType: NONE
    InvokeMode: BUFFERED
    TargetFunctionArn: !GetAtt DemoFunction.Arn

デプロイが終わると、Lambda関数名とFunction URLが表示されます。

Creating stack: lambda-function-url-403-demo

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - lambda-function-url-403-demo
Function name: lambda-function-url-403-demo-DemoFunction-xxxxxxx
Function URL: https://xxxxxxxxxx.lambda-url.ap-northeast-1.on.aws/
Stack created. Next: bash run_experiment.sh

認証なしなのに403になる

最初に、作成したFunction URLの設定を確認します。

bash show_config.sh

このスクリプトは、CloudFormationの出力から実際のLambda関数名を取得します。記事中の仮の関数名へ置き換える作業はありません。

Function name: lambda-function-url-403-demo-DemoFunction-xxxxxx
{
    "FunctionUrl": "https://xxxxxxx.lambda-url.ap-northeast-1.on.aws/",
    "FunctionArn": "arn:aws:lambda:ap-northeast-1:614272673503:function:lambda-function-url-403-demo-DemoFunction-xxxxx",
    "AuthType": "NONE",
    "CreationTime": "2026-09-14T00:32:31.952632176Z",
    "LastModifiedTime": "2026-09-14T00:32:31.952632176Z",
    "InvokeMode": "BUFFERED"
}

認証タイプがNONEであることを確認したら、検証用スクリプトを実行します。

bash run_experiment.sh
{"Message":"Forbidden. For troubleshooting Function URL authorization issues, see: https://docs.aws.amazon.com/lambda/latest/dg/urls-auth.html"}
HTTP_STATUS=403

403が出ました。

lambda:InvokeFunctionUrlを追加する

NONEはIAM認証を行わないという指定であり、関数のリソースベースポリシーまで不要になるわけではなかったようです。

まず、Function URLによる呼び出しを許可します。run_experiment.shでは、CloudFormationから取得した実際の関数名をDEMO_FUNCTION_NAMEへ入れています。

aws lambda add-permission \
  --function-name "${DEMO_FUNCTION_NAME}" \
  --statement-id FunctionURLAllowPublicAccess \
  --action lambda:InvokeFunctionUrl \
  --principal '*' \
  --function-url-auth-type NONE

もう一度アクセスしてみます。

{"message": "Function URL works"}
HTTP_STATUS=200

ここで200になりました。

最初の403は、AuthType: NONEだけを指定し、公開呼び出しを許可するリソースベースポリシーを追加していなかったことが原因だったようです。

AWSのドキュメントでは二つの権限が必要と書かれている

AWSのドキュメントを読み直すと、次の記載がありました。

2025年10月以降、新しい関数URLにはlambda:InvokeFunctionUrllambda:InvokeFunctionの両方のアクセス許可が必要です。

今回の実行結果ではlambda:InvokeFunctionUrlだけで200になっています。ドキュメントの記載と実際の挙動が一致しませんでした。

念のため、ドキュメントに合わせてもう一つのポリシーも追加しようとしました。

aws lambda add-permission \
  --function-name "${DEMO_FUNCTION_NAME}" \
  --statement-id FunctionURLInvokeAllowPublicAccess \
  --action lambda:InvokeFunction \
  --principal '*' \
  --invoked-via-function-url

ここで別の問題にハマりました。手元の環境に入っていたAWS CLIは2.15.47です。このバージョンでは--invoked-via-function-urlを認識しませんでした。

Unknown options: --invoked-via-function-url

今回確認できたのは次のところまでです。

AuthType: NONEだけ
└── 403 Forbidden

lambda:InvokeFunctionUrlを追加
└── 200 OK

lambda:InvokeFunctionも追加
└── 手元のAWS CLIがオプションに未対応で検証できず

AWS CLIを更新すれば二つ目の権限を追加できますが、すでに一つ目の権限で200になっているため、二つ目を追加したことによって直ったとは書けません。

AWS側での適用状況によるものなのか、ほかに条件があるのかまでは今回の検証では分かりませんでした。少なくとも、2026年9月に東京リージョンで試した自分の環境では、この結果になりました。

追加されたポリシーを確認する

実際のリソースベースポリシーも確認します。

bash show_policy.sh

今回の時点では、ポリシーに一つのステートメントが入っていました。

lambda:InvokeFunctionUrl
└── AuthTypeがNONEのFunction URLによる呼び出しを許可

AuthType NONEでも自動的に公開されるわけではない

今回の状態を並べると、次のようになりました。

AuthType: NONEだけ
└── 403 Forbidden

lambda:InvokeFunctionUrlを追加
└── 200 OK

NONEという名前から、IAMに関する設定はすべて不要だと思っていましたが、実際には、呼び出す側のIAM認証を省略する設定であり、Lambda側では公開を許可するリソースベースポリシーが必要でした。

コンソールやAWS SAMではポリシーが自動作成されるため、気づきにくいポイントです。CloudFormationへ置き換えたときに、急に403になることもありそうです。

ただし、現在のAWSドキュメントでは新しいFunction URLに二つの権限が必要と案内されています。今回は一つだけで動きましたが、これを一般的な挙動とは決めつけず、実際のポリシーとAWS CLIのバージョンを一緒に確認したほうがよさそうです。

やってみた感想

公式ドキュメントでは2つの権限が必要と書かれているのに、自分の環境では1つだけで200になりました。AWS CLIが古く、二つ目の権限を追加するオプションを使えなかったことも含め、想定どおりには進みませんでした。

AuthType: NONEだけでは公開できず、リソースベースポリシーが必要なことは確認できました。

参考

ここまで読んでいただき、ありがとうございます。もしこの記事の技術や考え方に少しでも興味を持っていただけたら、ネクストのエンジニアと気軽に話してみませんか。

  • 選考ではありません
  • 履歴書不要
  • 技術の話が中心
  • 所要時間30分程度
  • オンラインOK

エンジニアと話してみる

関連リンク

AI・クラウド・データ分析のご相談はネクスト株式会社までお問い合わせください。