エムオーテックス株式会社が運営するテックブログです。

CloudFrontの標準ログ記録(v2)の設定方法と実践例

CloudFrontの標準ログ記録(v2)の設定方法と実践例

はじめに

こんにちは、SREグループの植松です。 2024年11月のアップデートにより、CloudFrontの標準ログ記録が強化され CloudWatch Logsなどへの出力や、出力形式(JSON,Parquetなど)の変更などが可能になりました。

エムオーテックスでも今回のアップデートを適用するかどうかを調査し、結局、従来のログ(レガシー)をそのまま使用することにしましたが、調査で得たナレッジを共有したいと思います。

aws.amazon.com

CloudFront標準ログ記録

CloudFront で受信するすべてのユーザー (ビューワー) リクエストに関する詳細情報を含むログファイルは、標準ログ記録(アクセスログ)と呼ばれます。 標準ログ記録はレガシーとv2の2種類があります。

標準ログ記録(レガシー)

従来のログ記録形式です。Amazon S3にログを配信できます。 S3バケットのACL(Access Control List)の有効化が必要となります。

docs.aws.amazon.com

標準ログ記録(v2)

「はじめに」で記載の通り、2024/11に追加された機能となります。S3以外にCloudWatch Logs,Kinesis Data Firehoseにログを配信できます。 ログのどの項目を配信するかを設定でき、配信するデータ量を絞ることができます。

docs.aws.amazon.com

コンソールから標準ログ記録(v2)の設定

コンソールから標準ログ記録(v2)を設定する手順は以下の公式ドキュメントに記載があります。 1つ注意点があり、ログの配信先が別のAWSアカウントの場合は、画像に示す通り手順は失敗します。 コマンドで標準ログ記録(v2)を設定したい場合は後述の手順に則る必要があります。

docs.aws.amazon.com

コマンドで標準ログ記録(v2)の設定

エムオーテックスでは複数のAWSアカウントを運用してLANSCOPE エンドポイントマネージャー クラウド版の開発、運用を行なっており、 各種 標準ログ記録は専用のアカウントで一元管理したいという要望がありました。 クロスアカウントでログを配信する設定についても上記のドキュメントに記載がありますが、 配信元、配信先どちらのアカウントでどのリージョンでコマンドを実行するかなどが、躓きやすいポイントだと思ったので補足します。

以下は、ドキュメントを読み解いてどのアカウント、リージョンに何のリソースを作成すべきかを図解したものです。 どちらのアカウントで設定するものか、注意して読んでいただければ幸いです。

[配信アカウントで実行] ログ配信の宛先設定

どのリソース(S3バケット、Firehoseなど)にログを配信するかを決定するために必要です。」以下はS3バケットを指定する例です。 us-east-1リージョンでの作成が必要です。

aws logs put-delivery-destination \
    --name cloudfront-delivery-destination \
    --delivery-destination-configuration "destinationResourceArn=arn:aws:s3:::your-bucket-name/your-prefix" \
    --region us-east-1

[配信アカウントで実行] ログ配信のポリシー設定

ログ配信の宛先のポリシー設定です。配信元のアカウントでログ配信を作成するために必要です。 以下のようなJSONファイルを作成して保存します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowCreateDelivery",
            "Effect": "Allow",
            "Principal": {"AWS": "source-account-id"},
            "Action": ["logs:CreateDelivery"],
            "Resource": "arn:aws:logs:us-east-1:destination-account-id:delivery-destination:your-delivery-destination-name"
        }
    ]
}

保存したJSONを引数に取り、以下のコマンドを実行します。 こちらもus-east-1リージョンでの作成が必要です。

aws logs put-delivery-destination-policy \
    --delivery-destination-name your-delivery-destination-name \
    --delivery-destination-policy file://your-policy-file.json \
    --region us-east-1 

[配信アカウントで実行] ログ配信バケットのバケットポリシー設定

配信元アカウントからのログを受け入れるため、以下のようなバケットポリシーを設定する必要があります。 アカウント名は適宜置き換えてください。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AWSLogsDeliveryWrite",
            "Effect": "Allow",
            "Principal": {
                "Service": "delivery.logs.amazonaws.com"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::your-bucket-name/*",
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": "source-account-id",
                    "s3:x-amz-acl": "bucket-owner-full-control"
                },
                "ArnLike": {
                    "aws:SourceArn": "arn:aws:logs:us-east-1:source-account-id:delivery-source:*"
                }
            }
        }
    ]
}

[配信アカウントで実行] 配信ソースの設定

どのリソースのログを配信するかを決定します。 CloudFrontはグローバルリソースのため、us-east-1リージョンでの実行が必要になります。

aws logs put-delivery-source \
    --name your-delivery-source-name \
    --resource-arn arn:aws:cloudfront::source-account-id:distribution/your-distribution-id \
    --log-type ACCESS_LOGS \
    --region us-east-1

[配信アカウントで実行] 配信設定

どの配信ソースに対し、どの宛先にログを配信するかを決定します。

aws logs create-delivery \
    --delivery-source-name your-delivery-source-name \
    --delivery-destination-arn arn:aws:logs:us-east-1:destination-account-id:delivery-destination:your-delivery-destination-name \
    --region us-east-1

これらのコマンドを実行することでログ配信設定ができます。

CloudFormationでの標準ログ記録(v2)の設定

CloudFormationで標準ログ記録(v2)の設定をする場合も、作成しなければならないリソースはコマンド実行の時と変わりません。

[配信アカウントでスタック作成] ログ配信の宛先設定

ログ配信の宛先設定は、配信先アカウントのus-east-1リージョンで作成が必要です。 yaml設定はこのようになります。

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  MyDeliveryDestination:
    Type: AWS::Logs::DeliveryDestination
    Properties:
      Name: your-delivery-destination-name
      DestinationResourceArn: arn:aws:s3:::your-bucket-name/prefix
      DeliveryDestinationPolicy: |
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "AllowCreateDelivery",
              "Effect": "Allow",
              "Principal": {"AWS": "source-account-id"},
              "Action": ["logs:CreateDelivery"],
              "Resource": "arn:aws:logs:us-east-1:destination-account-id:delivery-destination:your-delivery-destination-name"
            }
          ]
        }
      OutputFormat: json

DestinationResourceArnではプレフィックスを指定できます。 ドキュメントにもありますが、プレフィックスを指定しない場合はAWSLogs/{account-id}/CloudFrontが追加されます。 上記のテンプレート例の場合、arn:aws:s3:::your-bucket-name/AWSLogs/destination-account-id/CloudFront/ 以下にログが配信されます。

docs.aws.amazon.com

[配信アカウントでスタック作成] 配信ソースと配信設定

配信ソースと配信設定のテンプレート例です。

AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  EnvName:
    Type: String
Mappings:
  EnvMap:
    dev:
      DistributionID: 'example-dev'
    prod:
      DistributionID: 'example-prod'
Resources:
  SampleLogDeliverySource:
    Type: AWS::Logs::DeliverySource
    Properties:
      LogType: ACCESS_LOGS
      Name: !Sub sample-distribution-cloudfront-delivery-source-${EnvName}
      ResourceArn: !Sub
        - arn:aws:cloudfront::${AWS::AccountId}:distribution/${DistributionId}
        - DistributionId: !FindInMap [EnvMap, !Ref EnvName, DistributionID]
  SampleLogDelivery:
    Type: AWS::Logs::Delivery
    Properties:
      DeliveryDestinationArn: arn:aws:logs:us-east-1:destination-account-id:delivery-destination:example-destination
      DeliverySourceName: !Ref SampleLogDeliverySource
      RecordFields:
        - timestamp
        - DistributionId
        - date
        - time
        - x-edge-location
        - sc-bytes
        - c-ip
        - cs-method
        - cs(Host)
        - cs-uri-stem
        - sc-status
        - cs(Referer)
        - cs(User-Agent)
        - cs-uri-query
        - cs(Cookie)
        - x-edge-result-type
        - x-edge-request-id
        - x-host-header
        - cs-protocol
        - cs-bytes
        - time-taken
        - x-forwarded-for
        - ssl-protocol
        - ssl-cipher
        - x-edge-response-result-type
        - cs-protocol-version
        - fle-status
        - fle-encrypted-fields
        - c-port
        - time-to-first-byte
        - x-edge-detailed-result-type
        - sc-content-type
        - sc-content-len
        - sc-range-start
        - sc-range-end
        - timestamp(ms)
        - origin-fbl
        - origin-lbl
        - asn
      S3SuffixPath: !Sub ${EnvName}/{yyyy}/{MM}/{dd}
      S3EnableHiveCompatiblePath: false

名前の通りですがSampleLogDeliverySourceは配信ソース、SampleLogDeliveryは配信設定のテンプレートになります。 SampleLogDeliveryのRecordFieldsでは、ログ配信する項目名を指定します。必要だと判断した項目に絞ることができ、ログ量の削減につながります。 各項目の説明は以下のドキュメントを参照ください。

docs.aws.amazon.com

S3SuffixPathではログ配信する時のサフィックスを指定できます。今回のテンプレートの場合、ログは以下に配信されます。(青字:プレフィックスで指定、紫:サフィックスで指定)

arn:aws:s3:::your-bucket-name/prefix/${EnvName}/{yyyy}/{MM}/{dd}

おわりに

今回のブログでは、CloudFrontの標準ログ記録(v2)の設定方法について紹介しました。エムオーテックスでは、複数のAWSアカウントを運用しているため、クロスアカウントでのログ配信設定が重要な課題となっています。この記事が、同じような課題に直面している方々の参考になれば幸いです。