How to set up an Amazon S3 Bucket using AWS CDK


This how-to guide will explain what is required to create an Amazon S3 bucket in AWS CDK TypeScript. The example code that is provided comes with all steps required to run and deploy the AWS CDK code in AWS Cloud.

First, you’ll learn how to install AWS CDK and configure an IAM profile for your AWS account so that it enables you to deploy the code from the AWS CLI.

Once you’ve learned how to synthesize the Amazon S3 Bucket construct, you can then proceed to deploy it and after you’re done you can clean up the resources using AWS CDK destroy.

Here are the steps that allow you to set up and configure an Amazon S3 Bucket using AWS CDK:

How to set up an Amazon S3 Bucket Using AWS CDK TypeScript

Before we start building the Amazon S3 Bucket construct, you’re required to have done the following prerequisites before you can run AWS CDK code in TypeScript.

  • Install AWS CDK and TypeScript NPM packages
  • Install the AWS CLI and configure an AWS profile
  • Create an AWS CDK TypeScript project

If you’ve already done this, you can proceed to step 4.

1. Install AWS CDK

Use the NPM package manager in your terminal to install AWS CDK and TypeScript globally on your system:

➜ npm install -g aws-cdk typescript

added 180 packages, and audited 181 packages in 7s
found 0 vulnerabilities
~ took 7s

Once you’ve installed AWS CDK you can validate that you’re running on the latest version by running the following command in the terminal:

➜ cdk version

2.23.0 (build 50444aa)

2. Install AWS CLI and configure an AWS profile

The AWS CLI is a command line tool that allows you to interact with AWS services in your terminal. Depending on if you’re running Linux, macOS, or Windows the installation goes like this:

# macOS install method:
brew install awscli

# Windows install method:
wget https://awscli.amazonaws.com/AWSCLIV2.msi
msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi

# Linux (Ubuntu) install method:
sudo apt install awscli

In order to access your AWS account with the AWS CLI, you first need to configure an AWS Profile. There are 2 ways of configuring a profile:

  • Access and secret key credentials from an IAM user
  • AWS Single Sign-on (SSO) user

In this article, I’ll briefly explain how to configure the first method so that you can proceed more quickly to set up the Amazon S3 Bucket in AWS CDK.

If you wish to set up the AWS profile more securely, then I’d suggest you read and apply the steps described in setting up AWS CLI with AWS Single Sign-On (SSO).

In order to configure the AWS CLI with your IAM user’s access and secret key credentials, you need to login to the AWS Console. Go to IAM > Users, select your IAM user and click on the Security credentials tab to create an access and secret key.

Then configure the AWS profile on the AWS CLI as follows:

➜ aws configure
AWS Access Key ID [None]: <insert_access_key>
AWS Secret Access Key [None]: <insert_secret_key>
Default region name [None]: <insert_aws_region>
Default output format [json]: json

Your was credentials are stored in ~/.aws/credentials and you can validate that your AWS profile is working by running the command:

➜ aws sts get-caller-identity
{
    "UserId": "AIDA5BRFSNF24CDMD7FNY",
    "Account": "012345678901",
    "Arn": "arn:aws:iam::012345678901:user/test-user"
}

3. Create a new AWS CDK TypeScript Project

Now that we’ve configured our profile and installed the packages, it’s time to create an AWS CDK TypeScript project where you’re going to build the Amazon S3 Bucket construct.

You can generate a new AWS CDK TypeScript project by running the following command in an empty directory:

➜ cdk init sample-app --language=typescript

Applying project template sample-app for typescript
# Welcome to your CDK TypeScript project!
You should explore the contents of this project. It demonstrates a CDK app with an instance of a stack (`CdkProjectStack`)
which contains an Amazon SQS queue that is subscribed to an Amazon SNS topic.
The `cdk.json` file tells the CDK Toolkit how to execute your app.
## Useful commands
 * `npm run build`   compile typescript to js
 * `npm run watch`   watch for changes and compile
 * `npm run test`    perform the jest unit tests
 * `cdk deploy`      deploy this stack to your default AWS account/region
 * `cdk diff`        compare deployed stack with current state
 * `cdk synth`       emits the synthesized CloudFormation template
Initializing a new git repository...
Executing npm install...
βœ… All done!

4. Create an Amazon S3 Bucket construct in AWS CDK

The following example defines an Amazon S3 bucket in a stack by creating an instance of the Bucket class which is an L2 construct.

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

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

    const s3Bucket = new s3.Bucket(this, 'exampleBucket', {
      objectOwnership: s3.ObjectOwnership.BUCKET_OWNER_ENFORCED,
      blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
      encryptionKey: new kms.Key(this, 's3BucketKMSKey'),
    });

    s3Bucket.grantRead(new iam.AccountRootPrincipal());
  }
}

const app = new cdk.App();
new S3BucketStack(app, 'S3BucketStack');
app.synth();

You can create an S3 bucket in a simple oneliner, but I’ve chosen to add 3 important properties that help secure the S3 Bucket. Let’s go over these properties:

objectOwnership – Allows you to disable access control lists (ACLs)Β and take ownership of every object in your bucket. This will simplify the way you manage access to objects that are stored in your Amazon S3 bucket.

blockPublicAccess – Permissions on new objects that are stored in the S3 bucket are private by default and don’t allow public access.

encryptionKey – Allows you to use a customer managed KMS key to encrypt the S3 bucket objects in rest.

At last, we use the s3Bucket.grantRead method to give the AWS account owner read access to the specified exampleBucket.

5. Synthesize your Amazon S3 Bucket in AWS CDK

The Amazon S3 Bucket construct has been created in a stack. Now you can generate the CloudFormation template by running AWS CDK Synthesize:

➜ cdk synth

Resources:
  exampleBucketB33BA2C4:
    Type: AWS::S3::Bucket
    Properties:
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              KMSMasterKeyID:
                Fn::GetAtt:
                  - s3BucketKMSKey2D51E7FB
                  - Arn
              SSEAlgorithm: aws:kms
      OwnershipControls:
        Rules:
          - ObjectOwnership: BucketOwnerEnforced
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
    Metadata:
      aws:cdk:path: S3BucketStack/exampleBucket/Resource
....
....

As you can see in the command output above, it will print the stack output in YAML format in stdout.

You can ignore that, the generated template is stored in JSON format in the cdk.out folder of your AWS CDK project.

.
β”œβ”€β”€ cdk.json
β”œβ”€β”€ cdk.out
β”‚  β”œβ”€β”€ cdk.out
β”‚  β”œβ”€β”€ manifest.json
β”‚  β”œβ”€β”€ S3BucketStack.assets.json
β”‚  β”œβ”€β”€ S3BucketStack.template.json
β”‚  └── tree.json
β”œβ”€β”€ main.ts
β”œβ”€β”€ package-lock.json
β”œβ”€β”€ package.json
β”œβ”€β”€ README.md
└── tsconfig.json

6. Deploy your Amazon S3 Bucket to AWS Cloud using AWS CDK

To deploy the S3 bucket to your AWS account, run the deploy command:

➜ cdk deploy

✨  Synthesis time: 16.66s

This deployment will make potentially sensitive changes according to your current security approval level (--require-approval broadening).
Please confirm you intend to make the following modifications:

IAM Statement Changes
β”Œβ”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   β”‚ Resource                                  β”‚ Effect β”‚ Action                                    β”‚ Principal                                  β”‚ Condition β”‚
β”œβ”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ + β”‚ ${exampleBucket.Arn}                      β”‚ Allow  β”‚ s3:GetBucket*                             β”‚ AWS:arn:${AWS::Partition}:iam::${AWS::Acco β”‚           β”‚
β”‚   β”‚ ${exampleBucket.Arn}/*                    β”‚        β”‚ s3:GetObject*                             β”‚ untId}:root                                β”‚           β”‚
β”‚   β”‚                                           β”‚        β”‚ s3:List*                                  β”‚                                            β”‚           β”‚
β”œβ”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ + β”‚ ${s3BucketKMSKey.Arn}                     β”‚ Allow  β”‚ kms:*                                     β”‚ AWS:arn:${AWS::Partition}:iam::${AWS::Acco β”‚           β”‚
β”‚   β”‚                                           β”‚        β”‚                                           β”‚ untId}:root                                β”‚           β”‚
β”‚ + β”‚ ${s3BucketKMSKey.Arn}                     β”‚ Allow  β”‚ kms:Decrypt                               β”‚ AWS:arn:${AWS::Partition}:iam::${AWS::Acco β”‚           β”‚
β”‚   β”‚                                           β”‚        β”‚ kms:DescribeKey                           β”‚ untId}:root                                β”‚           β”‚
β””β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)

Do you wish to deploy these changes (y/n)? y
S3BucketStack: deploying...
[0%] start: Publishing a26790c45fb73467eeeccc9ae55cffac604567459906d91c75237364eaf42df9:current_account-current_region
[100%] success: Published a26790c45fb73467eeeccc9ae55cffac604567459906d91c75237364eaf42df9:current_account-current_region
S3BucketStack: creating CloudFormation changeset...

 βœ…  S3BucketStack

✨  Deployment time: 167.98s

Stack ARN:
arn:aws:cloudformation:eu-central-1:896653224309:stack/S3BucketStack/109c23d0-0697-11ed-8de7-06dec59fa0d6

✨  Total time: 184.64s

7. Destroy Your Amazon S3 Bucket Using AWS CDK

To clean up the AWS resources that were created for this project, run the destroy command:

➜ cdk destroy
Are you sure you want to delete: S3BucketStack (y/n)? y
S3BucketStack: destroying...

 βœ…  S3BucketStack: destroyed

Conclusion

You were able to successfully set up an Amazon S3 Bucket using AWS CDK TypeScript.

The additional S3 Bucket properties allow you to further secure access and encrypt the objects that are stored on the bucket.

Elevate Your AWS CDK App with Expert Review & Guidance

Unlock the full potential of your AWS CDK app with our Expert AWS CDK App Code Review Service, conveniently delivered through AWS IQ.

Gain invaluable insights, minimize risks, and set a clear path forward for your project’s success.


Want to join us? Join for tips, strategies, and resources that I use in my solo cloud agency to build well-architected, resilient, and cost-optimized AWS solutions on AWS.

Join 1k+ AWS Cloud enthusiasts
Loved by engineers worldwide


Danny Steenman

A Senior AWS Cloud Engineer with over 9 years of experience migrating workloads from on-premises to AWS Cloud.

I have helped companies of all sizes shape their cloud adoption strategies, optimizing operational efficiency, reducing costs, and improving organizational agility.

Connect with me todayΒ to discuss your cloud aspirations, and let’s work together to transform your business by leveraging the power of AWS Cloud.

I need help with..
stacked cubes
Improving or managing my CDK App.Maximize the potential of your AWS CDK app by leveraging the expertise of a seasoned CDK professional.
Reducing AWS Costs.We can start by doing a thorough assessment of your current AWS infrastructure, identifying areas with potential for cost reduction and efficiency improvement.
Verifying if my infrastructure is reliable and efficient.We’ve created a comprehensive AWS Operations Checklist that you can utilize to quickly verify if your AWS Resources are set up reliably and efficiently.