aws cdkcloud frontS32025/4/25 • 読了時間:6分

aws cdkでs3にoacを適用しcloud frontからのみ参照出来るようにする

ブログ記事のメイン画像

前置き

Next.jsでaws lambda × cloud frontのサーバレス構成にした際にNext.jsから出力されるpublicフォルダをS3に配置したときの備忘録です。

画像などをビルド対象に含めるとプロジェクトが重くなることがあるので静的ファイルはS3に配置しようという考えです。

実装についてはTypeScriptで記載しています。 環境構築などは出来ているものとして書いているので構築方法などは割愛しています。

ゴール

以下の状態とすることを最終的なゴールとします。

  • cloud front経由でS3の参照をすることができる
  • S3に保存しているファイルを直接参照ができない

実装

プロジェクトの作成

はじめにcdkプロジェクトを作成します。 以降はこのプロジェクト内で作業を行います。

powershell
cd aws
npx cdk init app --language typescript

AWSへデプロイするための準備

プロジェクトを作成した直後の状態だとAWSへの適用ができません。 「/bin/〇〇.ts」で環境情報を設定する必要があるので調整を行います。 ※〇〇はプロジェクトの作成時に指定したフォルダ名とかになっているはず

typescript
#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib';
import { TestStack } from '../lib/test-stack';

const app = new cdk.App();
new TestStack(app, 'TestStack', {
  env: {
    account: 'aws account id', // AWS認証情報
    region: 'ap-northeast-1',
  },
});

次にpackage.jsonに以下のscriptを追加します。

typescript
{
  ...,
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w",
    "test": "jest",
    "cdk": "cdk",
+    "cdk:deploy": "cdk deploy", // これと
+   "cdk:destroy": "cdk destroy" // これ
  },
  ...,
}

上記の実装が終わったら次のコマンドを実行します。

powershell
npm run cdk:deploy

コマンド実行後AWSコンソールへログインを行い「CloudFormation」にスタックが作成されていれば準備完了です。

画像

AWS ECRにCDK上からDocker Imageをデプロイするpackageの追加

必要なライブラリを追加します。

powershell
npm install --save-dev cdk-ecr-deployment

AWS S3を構築するプログラムの実装

「/lib/〇〇-stack.ts」にてAWS環境を構築するためのプログラムを実装するファイルがあるため、S3を構築するための実装を行います。

typescript
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';

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

		// S3バケットの作成
    const bucket = new s3.Bucket(this, `S3-Bucket`, {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      autoDeleteObjects: true,
    });
    
    // S3バケットの出力
    new cdk.CfnOutput(this, 'S3BucketName', {
      value: bucket.bucketName,
      description: 'Name of the S3 bucket',
      exportName: 'S3BucketName',
    });

    // S3バケットのURLの出力
    new cdk.CfnOutput(this, 'S3BucketUrl', {
      value: bucket.bucketWebsiteUrl,
      description: 'URL of the S3 bucket',
      exportName: 'S3BucketUrl',
    });
  }
}

一旦この状態で再度デプロイしてS3が生成されいているか確認してみます。 以下の画像の通りCloudFormationを確認してS3が生成されていれば成功です。 ※この状態だと直接参照を有効にしていないのでファイルをアップしても見れないです。

画像

Cloud Front部分の実装とS3の直接参照を無効化

Cloud Frontの構築部分の処理とS3を直リンクで参照できないようにします。 Cloud Front ⇒ S3間ではOACを設定し実行できるように調整を行います。

typescript
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as origins from 'aws-cdk-lib/aws-cloudfront-origins';
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';

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

		// S3バケットの作成
    const bucket = new s3.Bucket(this, `S3-Bucket`, {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      autoDeleteObjects: true,
    });
    
    // S3バケットの出力
    new cdk.CfnOutput(this, 'S3BucketName', {
      value: bucket.bucketName,
      description: 'Name of the S3 bucket',
      exportName: 'S3BucketName',
    });

    // S3バケットのURLの出力
    new cdk.CfnOutput(this, 'S3BucketUrl', {
      value: bucket.bucketWebsiteUrl,
      description: 'URL of the S3 bucket',
      exportName: 'S3BucketUrl',
    });

    // Cloud Frontの作成
    const distribution = new cloudfront.Distribution(this, 'MyDistribution', {
      defaultBehavior: {
        origin: origins.S3BucketOrigin.withOriginAccessControl(bucket)
      },
    });

    // CloudFrontのURLの出力
    new cdk.CfnOutput(this, 'CloudFrontUrl', {
      value: distribution.distributionDomainName,
      description: 'URL of the CloudFront distribution',
      exportName: 'CloudFrontUrl',
    });
  }
}

再度デプロイを行うとCloud FrontのURLとS3のURLがログで出力されます。 今アクセスしてもファイルが存在しないのでS3に適当な画像ファイルをアップしましょう。 そのあと「各URL/アップしたファイル」にアクセスして以下のように動けば成功です。

  • Cloud FrontのURLにアクセス⇒アップした画像が表示
  • S3のURLにアクセス⇒AccessDeniedの表示

終わり

以上で「aws cdk でS3にoacを適用しcloud frontからのみ参照出来るようにする」実装が出来ました。

この構成はNuxt3やNextをAWS Lambda × Cloud Front(サーバーレス構成)の構成でも使えるので是非参考にしてもらえればと思います。

 

最新の記事

生成系AIサービスのv0を良く使っているのですが、そのままWebサービスに展開するときに個人的に修正をするのが大変だったので調整したプロンプトになります。...

Next.jsでaws lambda × cloud frontのサーバレス構成にした際にLambda Web Adapterを使ったのですが、その際にdocker周りの動きで詰まった備忘録です。以下...

Next.jsでaws lambda × cloud frontのサーバレス構成にしつつ、aws lambdaを直接参照できないようにしたときの備忘録になります。 以下の状態とすることを最終的なゴール...