AWS CDK v2でS3 CloudFrontを使った静的ホスティングを作成 (OAC)
検証等で静的サイトをAWSにデプロイする際にコンソール上でS3、CloudFrontを作っていましたが、コンソールから作成するのは意外と手間なのでCDKで作成していきます。
今回の構成はS3、CloudFrontを使ったシンプルなものとなっています。
今回作成するサービスの構成図
CDKの作成
CDKプロジェクト
typescriptを利用します。(AWS CDK)
mkdir s3-cloudfront-sample
cd s3-cloudfront-sample
cdk init app --language typescript
普段 pnpm
を利用しているため変更します。(npmの場合は不要)
rm -rf node_modules package-lock.json
pnpm install
リソースの作成
リソース作成用のコードはs3-cloudfront-sample/lib/s3-cloudfront-sample-stack.ts
に記述していきます。
S3 バケットの作成
静的サイトを配置するためのS3バケットを作成します。(S3 CDK docs)
import * as s3 from "aws-cdk-lib/aws-s3";
...
const bucket = new s3.Bucket(this, "S3Bucket", {
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
スタック削除時にバケットが削除されるようにremovalPolicyを設定しています。(バケット内は空でないといけない)
CloudFront ディストリビューションの作成
import * as cloudfront from "aws-cdk-lib/aws-cloudfront";
import * as origins from "aws-cdk-lib/aws-cloudfront-origins";
...
const distribution = new cloudfront.Distribution(
this,
"CloudfrontDistribution",
{
defaultBehavior: { origin: new origins.S3Origin(bucket) },
defaultRootObject: "index.html",
}
);
上記で作成したバケットとアクセス時に読み込むhtmlファイルを指定します。
OAC (Origin access control)の設定
CloudFront
CloudFrontのOACの設定がL2 コンストラクトではできないため、L1を利用して設定していきます。(AWS コンストラクト)
- OACの作成(OAC CDK docs)
const cfnOriginAccessControl = new cloudfront.CfnOriginAccessControl(
this,
"OriginAccessControl",
{
originAccessControlConfig: {
name: "OriginAccessControlForS3",
originAccessControlOriginType: "s3",
signingProtocol: "sigv4",
signingBehavior: "always",
},
}
);
- CloudFrontへOACの設定(CloudFormation JSON)
cfnDistribution.addPropertyOverride(
"DistributionConfig.Origins.0.S3OriginConfig.OriginAccessIdentity",
""
);
cfnDistribution.addPropertyOverride(
"DistributionConfig.Origins.0.OriginAccessControlId",
cfnOriginAccessControl.attrId
);
OAIの設定を削除し、OACを設定しています。
OAIの設定を削除しないとデプロイ時にCannot use both Origin Acc ess Control and Origin Access Identity on an origin
のエラーが発生しました。
S3
CloudFront OACに対して読み取り許可を与えるバケットポリシーをバケットに設定します。
- ポリシーの作成(S3 Policy CDK docs)
import * as iam from "aws-cdk-lib/aws-iam";
...
const oacPolicy = new iam.PolicyStatement({
sid: "AllowGetObjectForCloudFront",
principals: [new iam.ServicePrincipal("cloudfront.amazonaws.com")],
effect: iam.Effect.ALLOW,
actions: ["s3:GetObject"],
resources: [bucket.bucketArn + "/*"],
conditions: {
StringEquals: {
"AWS:SourceArn": `arn:aws:cloudfront::${
cdk.Stack.of(this).account
}:distribution/${distribution.distributionId}`,
},
},
});
- バケットポリシーの初期化と上記で作成したポリシーの付与
const bucketPolicy = new s3.BucketPolicy(
this,
"BucketPolicy",
{
bucket: bucket,
}
);
bucketPolicy.document.addStatements(oacPolicy);
デプロイ
- CDKの作成ができたので、AWSにデプロイします。
cdk deploy
- 作成されたs3にindex.htmlをアップロードします。
<!DOCTYPE html>
<html lang="en">
<body>
<h1>Hello, World!</h1>
</body>
</html>
- CloudFrontにアクセスし、表示されることを確認します。
xxxxxxxxxxxxxx.cloudfront.net
ソースコード
aws-cdk-s3-cloudfront (Github)