アジェンダは以下になります。
1. LambdaFunctionURLsを直接配信する際の問題点
2. CloudFrontでLambdaFunctionURLsを配信する際の以前までのワークアラウンド
3. CDKでの構築
1. LambdaFunctionURLsを直接配信する際の問題点
LambdaFunctionURLsをそのままで配信すると以下の点でセキュリティ的に気になる部分があります。
- 独自ドメインの設定ができない
- CloudFrontのキャッシュやWAFを設定するなどのメリットが受けられない
そのためCloudFrontをLambdaFunctionURLsの前段に配置する必要があります。
2. CloudFrontでLambdaFunctionURLsを配信する際の以前までのワークアラウンド
これまでもCloudFront経由でLambdaFunctionURLsを配信することはできましたが、FunctionURLs向けのOACが登場するまでは、少し遠回りな対応が必要でした。
- LambdaFunctionURLsの認証をIAM認証で設定する(こちらは現在も同じ)
- CloudFrontにLambda@Edgeを紐づけ、その中でIAM署名を行いLambdaFunctionURLsへのIAM認証を通す。
こちらについては下記記事の詳細を参照ください。
3. CDKでの構築
それではCDKでCloudFrontの構築とOACの設定するポイントを紹介します。
今回検証に使用したリポジトリはこちらになります。
https://github.com/shoet/aws-cdk-sandbox/tree/main/ts-nextjs-lambda-example-oac
ベースは以前の記事「Next.jsのSSR StreamingをLambdaFunctionURLsで検証する」で 作成したものをベースとしています。
構築手順は大まかに下記になります。
1. LambdaFunctionURLsをIAM認証にする
2. CloudFrontDistributionを作成する
3. DistributionのOriginにFunctionURLsを指定する
4. FunctionURLsにOACを適用する
5. LambdaFunctionにCloudFrontからの実行を許可する
1.LambdaFunctionURLsをIAM認証にする
authTypeをAWS_IAMに設定します。
this.functionUrl = new FunctionUrl(this, "NextJsLambdaFunctionUrl", {
function: this.function,
authType: cdk.aws_lambda.FunctionUrlAuthType.AWS_IAM,
invokeMode: cdk.aws_lambda.InvokeMode.RESPONSE_STREAM,
});
infrastracture/lib/lambda-function-stack.ts
2.CloudFrontDistributionを作成する / 3.DistributionのOriginにFunctionURLsを指定する
const lambdaFunctionOAC =
new cdk.aws_cloudfront.FunctionUrlOriginAccessControl(
this,
"LambdaFunctionOAC",
{
signing: cdk.aws_cloudfront.Signing.SIGV4_ALWAYS,
}
);
const functionUrlOrigin = new cdk.aws_cloudfront_origins.FunctionUrlOrigin(
lambdaFunctionUrl,
{
originAccessControlId: lambdaFunctionOAC.originAccessControlId,
}
);
infrastracture/lib/CloudFront.ts
4.FunctionURLsにOACを適用する
OACのsigningは常に署名を設定します。
const lambdaFunctionOAC =
new cdk.aws_cloudfront.FunctionUrlOriginAccessControl(
this,
"LambdaFunctionOAC",
{
signing: cdk.aws_cloudfront.Signing.SIGV4_ALWAYS,
}
);
infrastracture/lib/CloudFront.ts
5.LambdaFunctionにCloudFrontからの実行を許可する
このままではLambdaにCloudFrontからの実行権限がないためaddPermissionを行います。
lambdaFunction.addPermission("AllowInfokeCloudFront", {
action: "lambda:InvokefunctionUrl",
principal: new cdk.aws_iam.ServicePrincipal("cloudfront.amazonaws.com"),
sourceArn: `arn:aws:cloudfront::${cdk.Aws.ACCOUNT_ID}:distribution/${distribution.distributionId}`,
});
infrastracture/lib/CloudFront.ts
関連ドキュメントには以下のように手動での権限付与が明記されています。
ここまで適用すると、LambdaFunctionURLsへの直接アクセスが403となりアクセス不可となっていることが確認できます。
おわりに
これで、LambdaFunctionsURLの直接アクセスを制御しつつ、CloudFrontのメリットを活かした安全な公開が実現できます。
ぜひ今回のリポジトリをベースに、ご自身のアプリでも試してみてください。今後のAWSアップデートにも注目して、より便利な機能が追加されれば、さらに活用の幅が広がるはずです!