[AWS CDK] CloudFrontの標準ログ(アクセスログ)をS3バケットに出力する

2021.06.13

こんにちは、CX事業本部の若槻です。

Amazon CloudFrontでは標準ログ(アクセスログ)の出力を設定することにより、CloudFrontが受信するユーザーリクエストの情報をS3バケットにログ出力することができるようになります。

今回は、CloudFrontの標準ログ(アクセスログ)をS3バケットに出力する設定をAWS CDKで行ってみました。

やってみた

cdkのスタック定義

frontend-stack.ts

import * as cdk from "@aws-cdk/core";
import * as cloudfront from "@aws-cdk/aws-cloudfront";
import * as s3 from "@aws-cdk/aws-s3";
import * as s3deploy from "@aws-cdk/aws-s3-deployment";
import * as iam from "@aws-cdk/aws-iam";

export class AwsCdkDeployReactStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const websiteBucket = new s3.Bucket(this, "WebsiteBucket", {
      websiteErrorDocument: "index.html",
      websiteIndexDocument: "index.html",
    });

    const websiteIdentity = new cloudfront.OriginAccessIdentity(
      this,
      "WebsiteIdentity"
    );

    const webSiteBucketPolicyStatement = new iam.PolicyStatement({
      actions: ["s3:GetObject"],
      effect: iam.Effect.ALLOW,
      principals: [websiteIdentity.grantPrincipal],
      resources: [`${websiteBucket.bucketArn}/*`],
    });

    websiteBucket.addToResourcePolicy(webSiteBucketPolicyStatement);

    const region = cdk.Stack.of(this).region;
    const accountId = cdk.Stack.of(this).account;

    //ログ出力先バケット
    const appLogBucket = new s3.Bucket(this, "AppLogBucket", {
      bucketName: `app-logs-${region}-${accountId}`,
    });

    const websiteDistribution = new cloudfront.CloudFrontWebDistribution(
      this,
      "WebsiteDistribution",
      {
        errorConfigurations: [
          {
            errorCachingMinTtl: 300,
            errorCode: 403,
            responseCode: 200,
            responsePagePath: "/index.html",
          },
          {
            errorCachingMinTtl: 300,
            errorCode: 404,
            responseCode: 200,
            responsePagePath: "/index.html",
          },
        ],
        originConfigs: [
          {
            s3OriginSource: {
              s3BucketSource: websiteBucket,
              originAccessIdentity: websiteIdentity,
            },
            behaviors: [
              {
                isDefaultBehavior: true,
              },
            ],
          },
        ],
        priceClass: cloudfront.PriceClass.PRICE_CLASS_ALL,
        //ログ出力設定
        loggingConfig: {
          bucket: appLogBucket,
          prefix: "cloudfront/",
        },
      }
    );

    new s3deploy.BucketDeployment(this, "WebsiteDeploy", {
      sources: [s3deploy.Source.asset("./web/build")],
      destinationBucket: websiteBucket,
      distribution: websiteDistribution,
      distributionPaths: ["/*"],
    });
  }
}

CloudFrontの標準ログの設定はCloudFrontWebDistributionloggingConfigで行います。出力先のS3バケットとプレフィクスを指定しています。

動作確認

前述のスタックをcdk deployし、ログ出力の動作確認をしてみます。

CloudFrontが配信するアプリにアクセスして2,3分すると、S3バケットにログが出力されていました。GZIP形式で指定のプレフィクス直下に配置されていますね。

% aws s3 ls s3://${APP_LOG_BUCKET_NAME} --recursive 
2021-06-13 20:06:53       1206 cloudfront/E1PKXWC428H2P.2021-06-13-11.e0c7f903.gz

S3 SELECTを使用した場合は下記のような指定でログの内容を確認できました。

  • 入力設定
    • 形式:CSV
    • CSV 区切り記号:タブ
    • 圧縮:GZIP
  • 出力設定
    • 形式:CSV
    • CSV 区切り記号:カンマ

S3セレクトのクエリ結果です。オリジン(S3バケット)がCloudFrontに返す301304の通信やCloudFrontがクライアントに返す200の通信が記録されていますね。

2021-06-13,11:05:16,NRT12-C4,595,XXX.XXX.XXX.XXX,GET,xxxxxxxxxxxxxx.cloudfront.net,/,301,-,"Mozilla/5.0%20(Macintosh;%20Intel%20Mac%20OS%20X%2010_15_7)%20AppleWebKit/537.36%20(KHTML,%20like%20Gecko)%20Chrome/91.0.4472.77%20Safari/537.36",-,-,Redirect,wKi888IgkVVQDH2fJfIzgPNswViUbMzdVIRBqbxKwYKEBQAjQi96KA==,xxxxxxxxxxxxxx.cloudfront.net,http,483,0.000,-,-,-,Redirect,HTTP/1.1,-,-,55224,0.000,Redirect,text/html,183,-,-
2021-06-13,11:05:16,NRT12-C4,270,XXX.XXX.XXX.XXX,GET,xxxxxxxxxxxxxx.cloudfront.net,/,304,-,"Mozilla/5.0%20(Macintosh;%20Intel%20Mac%20OS%20X%2010_15_7)%20AppleWebKit/537.36%20(KHTML,%20like%20Gecko)%20Chrome/91.0.4472.77%20Safari/537.36",-,-,Miss,Gn0_MvhEhn_lXcYiiyBkJvapgwT4UiilSt0VPNQhQTjHyycDcB6i9w==,xxxxxxxxxxxxxx.cloudfront.net,https,509,0.645,-,TLSv1.3,TLS_AES_128_GCM_SHA256,Miss,HTTP/2.0,-,-,55223,0.645,Miss,-,-,-,-
2021-06-13,11:05:17,NRT12-C4,269,XXX.XXX.XXX.XXX,GET,xxxxxxxxxxxxxx.cloudfront.net,/static/js/main.4d1d49ad.chunk.js,304,https://xxxxxxxxxxxxxx.cloudfront.net/,"Mozilla/5.0%20(Macintosh;%20Intel%20Mac%20OS%20X%2010_15_7)%20AppleWebKit/537.36%20(KHTML,%20like%20Gecko)%20Chrome/91.0.4472.77%20Safari/537.36",-,-,Miss,TySta-csO9po3hy6jMHFbCJ6dAW8t1MWU0TgH9Bp2CA2CpXyfE7dEg==,xxxxxxxxxxxxxx.cloudfront.net,https,101,0.708,-,TLSv1.3,TLS_AES_128_GCM_SHA256,Miss,HTTP/2.0,-,-,55223,0.708,Miss,-,-,-,-
2021-06-13,11:05:17,NRT12-C4,270,XXX.XXX.XXX.XXX,GET,xxxxxxxxxxxxxx.cloudfront.net,/static/css/main.ab7136cd.chunk.css,304,https://xxxxxxxxxxxxxx.cloudfront.net/,"Mozilla/5.0%20(Macintosh;%20Intel%20Mac%20OS%20X%2010_15_7)%20AppleWebKit/537.36%20(KHTML,%20like%20Gecko)%20Chrome/91.0.4472.77%20Safari/537.36",-,-,Miss,_fwJg4Vx6P6igzlMZp9sWWteJeteWO24TOSDBwkz371qg_G1mXdjXA==,xxxxxxxxxxxxxx.cloudfront.net,https,122,0.741,-,TLSv1.3,TLS_AES_128_GCM_SHA256,Miss,HTTP/2.0,-,-,55223,0.741,Miss,-,-,-,-
2021-06-13,11:05:18,NRT12-C4,42938,XXX.XXX.XXX.XXX,GET,xxxxxxxxxxxxxx.cloudfront.net,/static/js/2.7ae8f596.chunk.js,200,https://xxxxxxxxxxxxxx.cloudfront.net/,"Mozilla/5.0%20(Macintosh;%20Intel%20Mac%20OS%20X%2010_15_7)%20AppleWebKit/537.36%20(KHTML,%20like%20Gecko)%20Chrome/91.0.4472.77%20Safari/537.36",-,-,Miss,sBG9fA9HD6CZwS31nokysvDbmujY1Dq_AWr10R-bbW_TRGLFHU6_Gg==,xxxxxxxxxxxxxx.cloudfront.net,https,101,1.230,-,TLSv1.3,TLS_AES_128_GCM_SHA256,Miss,HTTP/2.0,-,-,55223,0.755,Miss,application/javascript,-,-,-

標準ログファイルの形式の詳細は以下のドキュメントを参照してください。

おわりに

CloudFrontの標準ログ(アクセスログ)をS3バケットに出力する設定をAWS CDKで行ってみました。簡単な設定でアクセスログを残せるようになるのは便利ですね。

CloudFrontのアクセスログ出力の設定には、今回の標準ログの他に下記のリアルタイムログというものもあります。リアルタイムログの方がより詳細で柔軟なログ出力設定が可能です。次回はこちらを試してみたいです。

参考

以上