Amazon CloudFront でパスパターンごとに異なる S3 オリジンを設定する構成を AWS CDK で作成する

Amazon CloudFront でパスパターンごとに異なる S3 オリジンを設定する構成を AWS CDK で作成する

Clock Icon2025.04.24

こんにちは、製造ビジネステクノロジー部の若槻です。

Amazon CloudFront では、単一のディストリビューションに複数のオリジンを設定することができます。これによりパスパターンごとにコンテンツを配信するオリジンを変更することができます。

https://repost.aws/ja/knowledge-center/cloudfront-distribution-serve-content

今回は、Amazon CloudFront でパスパターンごとに異なる S3 オリジンを設定する構成AWS CDK で作成してみました。

試してみた

CDK コード

下記は CloudFront ディストリビューションの //images/*/videos/* の 3 つのパスパターンに対してそれぞれ異なる S3 バケットをオリジンとして設定する CDK コードです。

import * as cdk from "aws-cdk-lib";
import * as cloudfront from "aws-cdk-lib/aws-cloudfront";
import * as cloudfront_origins from "aws-cdk-lib/aws-cloudfront-origins";
import * as s3 from "aws-cdk-lib/aws-s3";
import * as s3_deployment from "aws-cdk-lib/aws-s3-deployment";
import { Construct } from "constructs";

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

    // 3つの異なる S3 バケットを作成
    const defaultBucket = new s3.Bucket(this, "DefaultBucket", {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      autoDeleteObjects: true,
    });

    const imagesBucket = new s3.Bucket(this, "ImagesBucket", {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      autoDeleteObjects: true,
    });

    const videosBucket = new s3.Bucket(this, "VideosBucket", {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      autoDeleteObjects: true,
    });

    // Distribution の作成
    const distribution = new cloudfront.Distribution(this, "Distribution", {
      defaultBehavior: {
        origin:
          cloudfront_origins.S3BucketOrigin.withOriginAccessControl(
            defaultBucket
          ),
      },
      additionalBehaviors: {
        "/images/*": {
          origin:
            cloudfront_origins.S3BucketOrigin.withOriginAccessControl(
              imagesBucket
            ),
        },
        "/videos/*": {
          origin:
            cloudfront_origins.S3BucketOrigin.withOriginAccessControl(
              videosBucket
            ),
        },
      },
      defaultRootObject: "index.html",
    });

    // CloudFront のドメイン名を出力
    new cdk.CfnOutput(this, "DistributionDomainName", {
      value: distribution.distributionDomainName,
    });

    // S3 バケットへのコンテンツのデプロイ
    new s3_deployment.BucketDeployment(this, "DefaultBucketDeploy", {
      sources: [
        s3_deployment.Source.data(
          "/index.html",
          "<html><body><h1>This is default page.</h1></body></html>"
        ),
        s3_deployment.Source.data("/favicon.ico", ""),
      ],
      destinationBucket: defaultBucket,
      distribution,
      distributionPaths: ["/*"],
    });

    new s3_deployment.BucketDeployment(this, "ImagesBucketDeploy", {
      sources: [
        s3_deployment.Source.data(
          "/images/index.html",
          "<html><body><h1>This is images page.</h1></body></html>"
        ),
        s3_deployment.Source.data("/favicon.ico", ""),
      ],
      destinationBucket: imagesBucket,
      distribution,
      distributionPaths: ["/*"],
    });

    new s3_deployment.BucketDeployment(this, "VideosBucketDeploy", {
      sources: [
        s3_deployment.Source.data(
          "/videos/index.html",
          "<html><body><h1>This is videos page.</h1></body></html>"
        ),
        s3_deployment.Source.data("/favicon.ico", ""),
      ],
      destinationBucket: videosBucket,
      distribution,
      distributionPaths: ["/*"],
    });
  }
}

Distribution コンストラクトで additionalBehaviors を設定することにより、デフォルトの / に加えて追加のパスパターンのオリジンを指定することができます。

CDK 実装をデプロイすると、下記のように 3 つの S3 バケットが CloudFront のオリジンとして設定された CloudFront ディストリビューションが作成されます。

動作確認

作成された CloudFront ディストリビューションのドメイン名にブラウザで開くと、それぞれのバケットにデプロイしたコンテンツにアクセスできました。

/ へのアクセス:

/images/index.html へのアクセス:

/videos/index.html へのアクセス:

注意点

以下のように、BucketDeployment でデプロイするコンテンツのパスを URL のパスパターンと一致させない実装を例にとります

new s3_deployment.BucketDeployment(this, "ImagesBucketDeploy", {
  sources: [
    s3_deployment.Source.data(
      "/index.html", // URL とパスを一致させない場合
      "<html><body><h1>This is images page.</h1></body></html>"
    ),
    s3_deployment.Source.data("/favicon.ico", ""),
  ],
  destinationBucket: imagesBucket,
  distribution,
  distributionPaths: ["/*"],
});

new s3_deployment.BucketDeployment(this, "VideosBucketDeploy", {
  sources: [
    s3_deployment.Source.data(
      "/index.html", // URL とパスを一致させない場合
      "<html><body><h1>This is videos page.</h1></body></html>"
    ),
    s3_deployment.Source.data("/favicon.ico", ""),
  ],
  destinationBucket: videosBucket,
  distribution,
  distributionPaths: ["/*"],
});

このような実装の場合、images/index.html および videos/index.html へアクセスするとアクセス拒否エラーが発生します。

これは、CloudFront は /images/* というパスパターンで来たリクエストを imagesBucket に転送しますが、そのままのパス(/images/index.html)で転送します。しかし、S3バケットのルートには /images/ というフォルダはなく、ルートに index.html があるため、アクセス拒否エラーになるためです。このように URL と S3 バケットのパスパターンを一致させる必要がある点に注意が必要です。

おわりに

今回は、Amazon CloudFront で複数の S3 バケットをオリジンとして設定する構成を AWS CDK で実装してみました。パスパターンごとに異なるオリジンを設定することで、コンテンツの種類に応じて適切なバケットからファイルを配信することができます。この構成は、画像やビデオなど、異なる種類のコンテンツを効率的に管理・配信したい場合に有用です。

以上

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.