だいたいはAWSの公式ブログの通り。
上記に書いてなくてハマったことが2点。
bucket policyにGetObjectだけじゃなくてListObjectがないと403が出て混乱する
上記のAWSブログにあるやつを実装してみると404かどうかをチェックしてリサイズの処理を走らせている。
s3のファイルは GetObject
だけしかしてないからそれだけ権限あればいいやろーーとs3のbucket policyにそういう設定をすると
data "aws_iam_policy_document" "bucket-policy" { statement { sid = "1" effect = "Allow" actions = [ "s3:GetObject" ] resources = [ "arn:aws:s3:::${var.appid}", ] principals { type = "AWS" identifiers = [aws_cloudfront_origin_access_identity.oai.iam_arn] } } }
確実にないファイルを指定しているのにリサイズが動作しない。
なんでやと調べてみるとだいたいクラメソさんが用意してくれてる。たすかる。
ListObject
がないとファイルあるかわからんとなって 404
じゃなくて 403
になるらしい。
というわけで下記のように修正。
data "aws_iam_policy_document" "bucket-policy" { statement { sid = "1" effect = "Allow" actions = [ "s3:GetObject", "s3:ListBucket" ] resources = [ "arn:aws:s3:::${var.appid}", "arn:aws:s3:::${var.appid}/*" ] principals { type = "AWS" identifiers = [aws_cloudfront_origin_access_identity.oai.iam_arn] } } }
ちゃんと 404
が出るようになって、スクリプトも動くようになったのでOK。
CloudFormationでlambda@edgeを作ると関数が更新できない
lambda@edgeを使うには、普通にlambdaを作ったうえでCloudFrontのconfigにlambdaのARNを指定するという形になる。なおバージョンを指定しないとだめなので、lambdaを更新するたびにversionを作成してCloudFrontに登録しなおさないといけない。普通のlambdaみたいにdeployして適当に動かすみたいなのができない。
最初はlambda@edgeを作るのにserverless frameworkを使っていたが、lambdaを更新してもversionをアップデートしてCloudFrontを更新してくれない。
で、ドキュメントを見たら
Updates are not supported for this property.
サポートしてないんかい!!
というわけでterraformで書き直した。
terraformでlambdaというと地獄そのものみたいなイメージがあったけど、試してみたら今はそうでもなくなってたっぽい。
data "archive_file" "viewer-request" { type = "zip" source_dir = "../lambda/viewer-request/src" output_path = "../lambda/viewer-request/viewer-request.zip" } resource "aws_lambda_function" "viewer-request" { filename = data.archive_file.viewer-request.output_path function_name = "${var.appid}-viewer-request" role = aws_iam_role.lambda.arn handler = "handler.viewer_request" runtime = "nodejs14.x" memory_size = 128 timeout = 5 source_code_hash = data.archive_file.viewer-request.output_base64sha256 publish = true }
archive_file
というのができてて、パスを指定すればよしなにzipファイルを作ってくれるやつなので terraform apply
以外にやることがなくて楽。ケースによるけどserverless frameworkよりも楽なのでは。
web上の記事ではlambdaの関数作成のみterraformで行って更新はlambrollなどで行うパターンはよく見る。会社等で属人性をなくすのであればそういうことも必要かもしれないけれど、lambda@edgeの関数はそうそう更新しないだろうし、terraformで一括管理でいい気がする。CIとかは必要になったら考えましょう。
まとめ
やっぱり実際やってみるといろいろハマりどころはある。