logo

Deploy a S3 Bucket and CloudFront using AWS CDK

Deploy a S3 bucket along with a CloudFront Distribution using AWS CDK with TypeScript. This method is used to access the S3 bucket assets publicly.

Published Feb 6, 2024
In this article, I'm going to explain about how to create a S3 bucket and expose it publicly with CloudFront using AWS Cloud Development Kit(CDK). CDK allows developers to define infrastructure as code, making it easier to manage and deploy AWS resources. Those stacks can be written in different languages but in this article I'm using TypeScript which is the most commonly used language.
CDK should be bootstrapped, you can follow Getting Started with the AWS CDK document. Once CDK and the AWS account is properly configured, required Node and npm modules should be installed for TypeScript and this Working with the AWS CDK in TypeScript document explain it clearly.
Once all the prerequisites are done. Add the below code blocks inside the CDK stack in the lib folder.
1
2
3
4
5
6
7
8
9
10
11
12
13
const s3CorsRule: s3.CorsRule = {
allowedMethods: [s3.HttpMethods.GET, s3.HttpMethods.HEAD],
allowedOrigins: ['*'],
allowedHeaders: ['*'],
maxAge: 300,
};

const s3Bucket = new s3.Bucket(this, 'S3Bucket', {
bucketName: 'medium-s3-cloudfront',
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
accessControl: s3.BucketAccessControl.PRIVATE,
cors: [s3CorsRule]
});
Above code is to create the S3 bucket and required CORS rules. If you want to grant read/write access to a user or a role in AWS it is possible to create the required code blocks in this CDK stack.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const oai = new cloudfront.OriginAccessIdentity(this, 'OAI');
s3Bucket.grantRead(oai);

const backendCloudfront = new cloudfront.CloudFrontWebDistribution(this, 'BackendCF', {
originConfigs: [
{
s3OriginSource: {
s3BucketSource: s3Bucket,
originAccessIdentity: oai,
},
behaviors: [{isDefaultBehavior: true}, { pathPattern: '/*', allowedMethods: cloudfront.CloudFrontAllowedMethods.GET_HEAD }]
},
],
});
In the same file add above code blocks to create the CloudFront distribution and required OAI configuration. I have not configured HTTPS since I do not have a domain and a certificate. If you own a domain and SSL certificate there are extra configuration blocks to add in this same function.
After creating the proper code blocks and stack, it is possible to check what will be created and configured using below command,
cdk diff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Stack S3CdkStack
IAM Statement Changes
┌───┬──────────────────────────────────┬────────┬────────────────────────────────────┬────────────────────────────────────────┬───────────┐
│ │ Resource │ Effect │ Action │ Principal │ Condition │
├───┼──────────────────────────────────┼────────┼────────────────────────────────────┼────────────────────────────────────────┼───────────┤
│ + │ ${S3Bucket.Arn} │ Allow │ s3:GetBucket* │ CanonicalUser:${OAI.S3CanonicalUserId} │ │
│ │ ${S3Bucket.Arn}/* │ │ s3:GetObject* │ │ │
│ │ │ │ s3:List* │ │ │
├───┼──────────────────────────────────┼────────┼────────────────────────────────────┼────────────────────────────────────────┼───────────┤
│ + │ ${S3Bucket.Arn}/* │ Allow │ s3:GetObject │ CanonicalUser:${OAI.S3CanonicalUserId} │ │
└───┴──────────────────────────────────┴────────┴────────────────────────────────────┴────────────────────────────────────────┴───────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)

Parameters
[+] Parameter BootstrapVersion BootstrapVersion: {"...Shortened..."}

Conditions
[+] Condition CDKMetadata/Condition CDKMetadataAvailable: {"...Shortened..."}

Resources
[+] AWS::S3::Bucket S3Bucket S3Bucket07682993
[+] AWS::S3::BucketPolicy S3Bucket/Policy S3BucketPolicyF560589A
[+] AWS::CloudFront::CloudFrontOriginAccessIdentity OAI OAIE1EFC67F
[+] AWS::CloudFront::Distribution BackendCF/CFDistribution BackendCFCFDistribution7FE8ADFE

Other Changes
[+] Unknown Rules: {"...Shortened..."}

✨ Number of stacks with differences: 1
To deploy the components use the below command with the correct stack name,
cdk deploy S3CdkStack
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
✨ Synthesis time: 1.97s

S3CdkStack: start: Building f0bd3dfa6f82269945359bad08c4c291fbd7995742d61629dfd325df399b7234:current_account-current_region
S3CdkStack: success: Built f0bd3dfa6f82269945359bad08c4c291fbd7995742d61629dfd325df399b7234:current_account-current_region
S3CdkStack: start: Publishing f0bd3dfa6f82269945359bad08c4c291fbd7995742d61629dfd325df399b7234:current_account-current_region
S3CdkStack: success: Published f0bd3dfa6f82269945359bad08c4c291fbd7995742d61629dfd325df399b7234:current_account-current_region
S3CdkStack: deploying... [1/1]
S3CdkStack: creating CloudFormation changeset...

✅ S3CdkStack

✨ Deployment time: 280.03s

Stack ARN:
arn:aws:cloudformation:us-east-1:xxxxxxxxxxxxxxx:stack/S3CdkStack/8f4afa30-bafa-11ee-af3e-0e37b8297d99

✨ Total time: 282s
After all the components are created, it is possible to access S3 bucket using cloudfront distribution domain. I have added a temporary index.html file into S3 bucket and it is possible to access that page now,
Test Web Page
Web URL with CloudFront
To destroy the stack simply execute below command,
cdk destroy S3CdkStack
1
2
3
4
Are you sure you want to delete: S3CdkStack (y/n)? y
S3CdkStack: destroying... [1/1]

✅ S3CdkStack: destroyed
Well done! You’ve created an S3 bucket and configured CloudFront using CDK and TypeScript. This infrastructure as code solution provides a clear and controllable way to manage AWS resources, making it easier to grow and maintain your applications. Explore further CDK features and AWS services to improve your cloud infrastructure.