CloudFront + Lambda 関数 URL 構成でPOST/PUT リクエストを行うため Lambda@Edge でコンテンツハッシュを計算する
Lambda 関数 URL で POST/PUTしたい場合はペイロードのハッシュをLambda@Edgeで計算しましょう
2024.07.29
こんにちは。リテールアプリ共創部のきんじょーです。
CloudFrontとLambda関数URLの構成で、POST/PUTリクエストを行う必要があり、少し前に以下の記事を書きました。
実際のところ、Lambda 関数 URLでPUT、POSTリクエストを処理する際にはx-amz-content-sha256
ヘッダーでSHA256で計算したリクエストボディのハッシュ値を含めるのみで良く、OACの設定と併用することでSigv4の署名は不要でした。
より良い方法をこちらのIssueで教えていただいたので、Sigv4の署名を付与する場合とのコードの差分を中心にこのブログでご紹介します。
Lambda関数URLでPOST/PUTをするサンプルコードの全量は以下のリポジトリに格納しています。
やってみる
ペイロードのハッシュを計算
Sigv4の署名を生成する処理に比べて、Lambda@Edgeのコードがかなりシンプルになりました。
calculate-content-hash.ts
import { CloudFrontRequestEvent, CloudFrontRequestHandler } from "aws-lambda";
const hashPayload = async (payload) => {
const encoder = new TextEncoder().encode(payload);
const hash = await crypto.subtle.digest("SHA-256", encoder);
const hashArray = Array.from(new Uint8Array(hash));
return hashArray.map((bytes) => bytes.toString(16).padStart(2, "0")).join("");
};
export const handler: CloudFrontRequestHandler = async (
event: CloudFrontRequestEvent,
_context,
) => {
const request = event.Records[0].cf.request;
console.log("originalRequest", JSON.stringify(request));
if (!request.body?.body) {
return request;
}
const body = request.body.data;
const decodedBody = Buffer.from(body, "base64").toString("utf-8");
request.headers["x-amz-content-sha256"] = [
{ key: "x-amz-content-sha256", value: await hashPayload(decodedBody) },
];
console.log("modifiedRequest", JSON.stringify(request));
return request;
};
Lambda@Edge の CDK 実装
Lambda@Edge側ではSigv4の署名を付与しなくなったのでOACのリソースをCDKで定義する必要があります。
server-stack.ts
+ const cfnOriginAccessControl =
+ new cdk.aws_cloudfront.CfnOriginAccessControl(
+ this,
+ "OriginAccessControl",
+ {
+ originAccessControlConfig: {
+ name: "Origin Access Control for Lambda Function URLs",
+ originAccessControlOriginType: "lambda",
+ signingBehavior: "always",
+ signingProtocol: "sigv4",
+ },
+ },
+ );
+
+ const cfnDistribution = cloudFrontDistribution.node
+ .defaultChild as cdk.aws_cloudfront.CfnDistribution;
+
+ // Set OAC
+ cfnDistribution.addPropertyOverride(
+ "DistributionConfig.Origins.0.OriginAccessControlId",
+ cfnOriginAccessControl.attrId,
+ );
まとめ
Lambda関数URLのIAM認証のためのSigv4署名の付与を、Lambda@EdgeではなくOACで設定するようになり、Lambda@Edgeのコードがシンプルになりました。
今後はこちらの構成でLambda関数URLをセキュアに公開したいと思います。
以上。リテールアプリ共創部のきんじょーでした。
参考
Issueを起票していただきありがとうございました!