こんにちは。会員システムグループでエンジニアをしている山田です。
昨年末、CloudFrontの標準ログに待望のアップデートが入りました。
今までの標準ログはレガシーな仕様を抱えており、特にすべてのログが同じパスに出力されてしまうという点が問題になっていました。Athenaでの検索などのために、ログを日付別パーティションに移動させるLambdaを動かしている方も多かったのではないでしょうか。
今回のアップデートにより
- S3の出力先パスに日付・時間を含めることが可能に
- JSONなどのフォーマットをサポート、カラムの取捨選択も可能に
- S3バケットポリシーに対応
など、今まで困っていた部分が解消されるようになります。さらにCloudWatch LogsやFirehoseへの出力もできるようになりました。
そして最近になってこの標準ログv2はTerraformでも設定できるようになりました。まだTerraformでの設定方法を解説した記事は少なそうですので、紹介したいと思います。
前提知識
まず大前提として、実はこの標準ログv2、CloudFrontに設定する機能ではありません。
これは公式ドキュメントのAWS CLIでの設定方法を見るとわかるのですが、CloudWatch Logs Delivery(v2)という汎用的なCloudWatchのログ配信機能になっています。これにCloudFrontが対応したというのが実際のようです。
登場するリソースは以下の3つです。
- DeliverySource
- DeliveryDestination
- Delivery
これらの関係性は以下のようになっています。

ログ出力元(DeliverySource)とログ出力先(DeliveryDestination)を作った後、これらをつなぐDeliveryを作成するとログが送られるようになります。DeliverySourceにCloudFront、DeliveryDestinationにS3を設定することで従来の標準ログを代替できます。
Terraformでもこれらのリソースを作成していくことになります。
Terraformでの実装例
従来と同様、S3へ送る設定を紹介します。
Terraform AWS Providerはv5.89.0以上が必要です。作成できるようになったのはv5.83.0ですが、apply後に状態不一致(tainted)となる複数のバグが修正されています。
S3の許可設定
S3の許可設定はバケットポリシーを設定します。もうACLを使う必要はありません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AWSLogDeliveryWrite", "Effect": "Allow", "Principal": { "Service": "delivery.logs.amazonaws.com" }, "Action": "s3:PutObject", "Resource": "<S3バケットARN>/<ログファイルまでのパス>/*", "Condition": { "StringEquals": { "aws:SourceAccount": "<AWSアカウントID>", "s3:x-amz-acl": "bucket-owner-full-control" }, "ArnLike": { "aws:SourceArn": "arn:aws:logs:us-east-1:<AWSアカウントID>:delivery-source:*" } } } ] } |
delivery.logs.amazonaws.com
をprincipalとし、S3オブジェクトに対する許可設定を行います。上記設定ではアカウント内の全てのDeliverySourceからの操作を許可していますが、厳密にはDeliverySourceを作成後、そのARNを指定するとよいでしょう。
Log Deliveryの作成
次に本命となるLog Deliveryです。AWSコンソール上で以下のように設定する値がどこに入るのかを見ていきます。
なおLog Delivery関連リソースはいずれもus-east-1で作る必要がある点に注意してください。送信先S3バケットは別リージョンでも問題ありません。

まずはDeliverySourceとDeliveryDestinationを作成し、CloudFrontとS3を指定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
resource "aws_cloudwatch_log_delivery_source" "this" { name = "<適当なsource名>" log_type = "ACCESS_LOGS" resource_arn = "<CloudFrontのARN>" } resource "aws_cloudwatch_log_delivery_destination" "this" { name = "<適当なdestination名>" # AWSコンソールの「Output Format」に相当 # 従来どおりの場合は"w3c" output_format = "json" delivery_destination_configuration { # AWSコンソールの「送信先S3バケット」に相当 destination_resource_arn = "<宛先S3のARN>/<ログまでのパス>" } } |
DeliveryDestinationではフォーマットや出力先パスを指定でき、日付別パスなどの設定ができます。後述しますが、destination_resource_arn
にパス部分を書かない場合、Deliveryの設定に影響するので注意してください。
最後にDeliveryを作ることで完成です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
resource "aws_cloudwatch_log_delivery" "this" { delivery_source_name = aws_cloudwatch_log_delivery_source.this.name delivery_destination_arn = aws_cloudwatch_log_delivery_destination.this.arn # AWSコンソールの「Field Delimiter」に相当 # JSONの場合は指定できない # field_delimiter = "," # AWSコンソールの「フィールド選択」に相当 # 未指定の場合はデフォルト値(legacyと同等)が設定される # record_fields = [ ... ] s3_delivery_configuration { # AWSコンソールの「パーティショニング」に相当 # 年月日時以外に{accountid}、{DitributionId}を指定可能 suffix_path = "/{yyyy}/{MM}/{dd}/{HH}" # AWSコンソールの「ハイブ互換のファイル名形式」に相当 # trueの場合、プレースホルダの挿入値が"year=2025"のようになる enable_hive_compatible_path = false } } |
suffix_pathはDeliveryDestinationで設定したdestination_resource_arn
の後に続くパスになります。ここの指定が厄介で、destination_resource_arn
の値によって実際の設定値が変わります。
- パスを指定した場合
- 指定した
suffix_path
がそのまま使われる
- 指定した
- パスを指定しなかった場合
- 指定した
suffix_path
の先頭にAWSLogs/{account-id}/CloudFront
/が追加される
- 指定した
このあたりの仕様はややこしいため、公式ドキュメントに載っているパスの設定例を参照することをおすすめします。
注意
標準ログ(legacy)について
標準ログv2は従来の標準ログ(legacy)とは独立した機能です。v2用の設定を追加しただけだと二重出力になってしまうため、無効化を忘れないようにしましょう。
AWSコンソール上から操作した場合
AWSコンソール上から標準ログv2を作成した場合、その裏で先述の3リソースが作成されます。このうちDeliverySourceはログを無効化しても消えず、残り続けます。1つのリソースに対してDeliverySourceは1つしか作成できないため、残っているとTerraformからの作成も失敗します。
AWSコンソール上からは削除する手段がないため、AWS CLIから削除してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# 既存のDeliverySourceを検索 % aws logs describe-delivery-sources --region us-east-1 { "deliverySources": [ { # 自動作成されたDeliverySourceはCreatedByCloudFront-XXXの命名になっています "name": "CreatedByCloudFront-XXXXXXXXXX", "arn": "arn:aws:logs:us-east-1:{my-account}:delivery-source:CreatedByCloudFront-XXXXXXXXXX", "resourceArns": [ "arn:aws:cloudfront::{my-account}:distribution/XXXXXXXXXX" ], "service": "cloudfront", "logType": "ACCESS_LOGS" } ] } # DeliverySourceを削除 % aws logs delete-delivery-source --name CreatedByCloudFront-XXXXXXXXXX --region us-east-1 |
まとめ
TerraformでのCloudFront 標準ログv2の設定方法をご紹介しました。
標準ログv2の登場により、CloudFrontのログ周りの辛さが一気に解消されるようになります。S3に送信する上では料金も変わらないため、積極的に移行をおすすめしたい機能です。
また実体となるCloudWatch Log Delivery(v2)はCloudFrontに限らない汎用的な仕組みになっており、他サービスへ展開していくことが期待されます。ALBのログなども対応すればより自由な設定が可能になるため、今後の展開に期待したいところです。
本記事が皆様の良きTerraformライフの一助になれば幸いです。