I tried making CloudFront Distribution using AWS CDK

Hi, this is Charu from Classmethod. Recently I deployed a website in AWS using services like AWS S3, Lambda and API gateway. But, to access that website, I was using S3 endpoint URl. In order to use S3 endpoint URL, the S3 bucket objects should be public which is not a safe option to follow. Hence, we will be using AWS CloudFront distribution.

Amazon CloudFront is a globally distributed content delivery network (CDN) service offered by Amazon Web Services (AWS). You can know more about it from here.

Let's get started!

In this blog, we will be making Amazon CloudFront distribution through AWS CDK in an already built website. If you don't have one, you can follow this blog and make a simple website by yourself.

The main thing to notice is that, your S3 bucket objects SHOULD NOT have public access enabled. That's the main motive of using CloudFront.

To make CloudFront, you can write the following code in your AWS CDK stack. The code is the extended version of the code I wrote in the blog I mentioned before.

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import {
  aws_lambda,
  aws_s3,
  aws_lambda_nodejs,
  aws_apigateway,
  aws_s3_deployment,
  aws_cloudfront,
} from "aws-cdk-lib";

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

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

    const originAccessIdentity = new aws_cloudfront.OriginAccessIdentity(
      this,
      "OriginAccessIdentity",
      {
        comment: `OriginAccessIdentity for ${websiteBucket.bucketName}`,
      }
    );

    websiteBucket.grantRead(originAccessIdentity); // Grant read permissions to CloudFront

    const distribution = new aws_cloudfront.CloudFrontWebDistribution(
      this,
      "WebsiteDistribution",
      {
        originConfigs: [
          {
            s3OriginSource: {
              s3BucketSource: websiteBucket,
              originAccessIdentity: originAccessIdentity,
            },
            behaviors: [{ isDefaultBehavior: true }],
          },
        ],
      }
    );

    new aws_s3_deployment.BucketDeployment(this, "DeployWebsite", {
      sources: [aws_s3_deployment.Source.asset("src/web")],
      destinationBucket: websiteBucket,
      distribution: distribution
    });

    const lambdaFunction = new aws_lambda_nodejs.NodejsFunction(
      this,
      "LambdaFunction",
      {
        runtime: aws_lambda.Runtime.NODEJS_18_X,
        entry: "src/lambda/websiteLambda/index.ts",
        architecture: aws_lambda.Architecture.ARM_64,
      }
    );

    const api = new aws_apigateway.RestApi(this, "MyApi", {
      restApiName: "MyApi",
    });

    const integration = new aws_apigateway.LambdaIntegration(lambdaFunction);
    const resource = api.root.addResource("myresource");
    resource.addMethod("GET", integration);
  }
}

In the code above, we made an Origin Access Identity(OAI) and a CloudFront distribution.

An OAI is created to establish a secure communication between CloudFront and your Amazon S3 bucket. It helps enhance the security of your content by allowing only CloudFront to access the S3 bucket. When you associate an OAI with your CloudFront distribution, CloudFront communicates with S3 using the OAI's identity. This means that users or entities outside of CloudFront cannot directly access your S3 content using S3 URLs.

While the CloudFront distribution helps you deliver your web content.

Run cdk deploy to deploy your website. Now, you can access your website by clicking on the CloudFront distribution link from your console as shown below,

Congratulations! You have successfully deployed your website using CloudFront.

Thank you for reading!

Happy Learning :)