How to Create an S3 Bucket using Terraform

How to Create an S3 Bucket using Terraform
Sharing is Caring:

How to Create an S3 Bucket using Terraform

AWS S3 or Simple Storage Service is one of the most used AWS service. When you are deploying your workload on AWS, there is high chances that you are using S3 buckets directly or indirectly.

From DevOps perspective, It always makes sense to automate your infrastructure as much as we can. In this post, I will show you how you can create an s3 bucket using one of the most popular IaC tool Terraform.

What is Terraform?

Terraform is an open source Infrastructure as Code(IaC) tool by HashiCorp. It lets you provision your infrastructure as code.

  • It lets you provision, update and version your infrastructure in efficient manner
  • You declare your required infrastructure in a configuration file and terraform creates it in correct order.
  • Configuration files are in human readable format using HashiCorp Configuration Language(HCL) or even JSON is supported.
  • Terraform is Cloud Agnostic and supports numerous cloud providers like AWS, Azure, GCP etc.

How Do You Create a Resource Using Terraform on AWS?

Unlike CloudFormation, you need to install terraform in your system before you can use it to create a resource like S3 bucket on your cloud provider(In our case case AWS).

Once installed, you create your configuration file(filename.tf – they have .tf extension), and use below set of commands to deploy your resources.

$ terraform init
$ terraform plan
$ terraform apply
$ terraform destroy

I highly recommended you to check my step by step guide to help you get started with terraform on AWS in right way. Here is the link-

Once you go through that post you will already have idea on-

  • Installing Terraform
  • Creating a Terraform IAM user
  • Setting up AWS CLI to allow Terraform to authenticate to AWS
  • Setting up your workspace using Visual Studio Code(VS Code) IDE
  • Deploying Your First Resource on AWS using Terraform

By this time, I assume you already know how to deploy a resource on AWS using Terraform.

Alright, lets get started with S3 Bucket Creation.

Prerequisite:

Create a Simple S3 Bucket using Terraform

In this article, we’ll create a very simple bucket using terraform. Later in this tutorial, we will update our bucket to enable some of the frequently used features like versioning, encryption etc.

Before we start, let me tell you that, to create an s3 bucket using terraform, you will need an aws_s3_bucket resource. Feel free to refer official documentation for up-to-date properties.

Here is how a simple s3 bucket resource looks like-

resource "aws_s3_bucket" "resource_name"{
  bucket = "bucket_name"

  tags = {
    Name = "Bucket_Tag"
  }
}

Now later when you want to access a property of this resource like bucket name ,you can do it like-

aws_s3_bucket.demo-bucket.bucket

Steps to Create an S3 Bucket using Terraform

  1. Create a Working Directory/Folder
  2. Create your Bucket Configuration File
  3. Initialize Your Directory to Download AWS Plugins
  4. Plan and Deploy

Step 1: Create a Working Directory/Folder

Create a folder in which you will keep your s3 bucket terraform configuration file.

Step 2: Create your Bucket Configuration File

Navigate inside the bucket and create your bucket configuration file. You can name it as per your wish, but to keep things simple , I will name it main.tf

I have started with just provider declaration and one simple resource to create a bucket as shown below-

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.27"
    }
  }

  required_version = ">= 0.14.9"
}

#Provider profile and region in which all the resources will create
provider "aws" {
  profile = "default"
  region  = "ap-south-1"
}

#Resource to create s3 bucket
resource "aws_s3_bucket" "demo-bucket"{
  bucket = "ck-demo-bucket"

  tags = {
    Name = "S3Bucket"
  }
}

Copy the this content and save into a file with .tf extension. You can name it main.tf conventionally as well.

Step 3: Initialize Your Directory to Download AWS Plugins

You only do this step once per folder/directory. This basically means, you are downloading relevant codes/plugins for your mentioned provider which in our case is aws.

terraform init
how to create s3 bucket using terraform

Step 4: Plan and Deploy

Configuration file is created and directory is initialized. That means, we are all ready to deploy our s3 bucket.

Now, if you want you can run the command terraform plan to see what’s actually being created.

terraform plan

However, to keep things simple, I just run terraform apply. Ideally, terraform runs terraform plan every time you hit command terraform apply. Once you review the plan and confirm yes then only resources will be created.

Terraform will look for .tf file and show you what’s being created.

Review the output and if all is fine say yes to the bucket.

How to create s3 bucket using terraform action yes

Once you confirm, terraform starts creating your bucket.

If all is well your bucket is created. However, one of the common mistake while creating an s3 bucket is choosing name.

If the name you provided is not unique, you will get error like below-

bucket creation error

It says-

Error creating S3 bucket: BucketAlreadyExists: The requested bucket name is not available. The bucket namespace is shared by all users of the system. Please select a different name and try again.

The reason is s3 bucket names are unique globally across AWS accounts. That means once someone has created a bucket “test”. No body else can create a bucket with same name in any account.

Read More about this-

In case of successful creation, you will see message like below-

That means your bucket is created and you can verify your s3 bucket in s3 console.

It was as simple as that. We are done with creation of a simple s3 bucket 🙂

Happy now? 😛 😛

Let’s be more happier by implementing some of the advanced things.

Enable Versioning on a Bucket

Enabling versioning enables multiple versions of all the objects in the bucket. You should consider enabling versioning-

  • To prevent an object from being deleted or overwritten by mistake.
  • To archive all version so that you can retrieve any version you want at any time

In latest versions of terraform, you can use a resource of type aws_s3_bucket_versioning to enable versioning on your bucket.

If we modify our existing code, this is how the section will look like-

#Resource to create an S3 bucket
resource "aws_s3_bucket" "demo-bucket"{
  bucket = "ck-demo-bucket-18th"

  tags = {
    Name = "S3Bucket"
  }


#A resource to enable versioning on bucket
resource "aws_s3_bucket_versioning" "versioning_demo" {
  bucket = aws_s3_bucket.demo-bucket.bucket
  versioning_configuration {
    status = "Enabled"
  }
}

Explanation:

  • aws_s3_bucket_versioning resource needs bucket name in the parameter bucket to enable versioning on that bucket
  • versioning_configuration status can be Enabled or Disabled to enable or disable versioning

Once configuration file is updated, run terraform apply and versioning will be enabled on the bucket.

If you go to S3 console and check your bucket properties. You can see that versioning is enabled on bucket now.

Versioning is enabled on your bucket?

I guess yes !!!

That’s good progress !!! 🙂

Important Notes: To enable versioning on an S3 bucket, we have used a separate aws_s3_bucket_versioning resource. However, please note that you can still use versioning parameter on the resource aws_s3_bucket but it’s already deprecated. So it’s recommended to use separate resource as shown here. But, don’t use both at a time as it might result in consistency.

Let’s add another feature in our cap by enabling encryption.

Enable Encryption on Bucket

Enabling default encryption on a bucket will set the default encryption behavior on a bucket. once set, all new objects are encrypted when you store them in the bucket.

In other terms, S3 encrypts an object before saving it to disk and decrypts it when you download the objects.

Well, there are two options of key when using server side encryption.

  • S3-managed keys (SSE-S3)
  • Customer master keys (CMKs) stored in AWS KMS.

In the latest terraform, similar to versioning, encryption also can be managed via a separate resource aws_s3_bucket_server_side_encryption_configuration like shown below-

resource "aws_s3_bucket_server_side_encryption_configuration" "demo-encryption" {
  bucket = aws_s3_bucket.demo-bucket.bucket

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

Important Note: Similar to versioning, to enable encryption on an S3 bucket, we have used a separate resource aws_s3_bucket_server_side_encryption_configuration. However, you can still use server_side_encryption_configuration in the aws_s3_bucket resource to enable encryption but it’s deprecated. So better to use this new way. But mind it, don’t use both together. It will cause inconsistencies.

Once you have updated your file with this configuration, run terraform apply again and you will see default encryption is enabled now.

By now we have enabled versioning and encryption. You can check your bucket property(In properties tab) to validate that as mentioned in the screenshot. Versioning and encryption are ticked here 🙂

Create an S3 Bucket using CloudFormation

Please note that we used s3 managed key here, however if you need to have KMS managed key, you can have below set of parameters. You will need to create a key in KMS first and then you need to provide the ARN as mentioned below.

resource "aws_kms_key" "demokey" {
  description             = "key to encrypt bucket objects"
  deletion_window_in_days = 7
}

resource "aws_s3_bucket_server_side_encryption_configuration" "demo_encryption" {
  bucket = aws_s3_bucket.demo-bucket.bucket

  rule {
    apply_server_side_encryption_by_default {
      kms_master_key_id = aws_kms_key.demokey.arn
      sse_algorithm     = "aws:kms"
    }
  }
}

Lastly, let’s try to configure our bucket in a way which will prevent any public access to our objects.

Prevent objects from becoming public

If you will notice the created s3 bucket access, you will see something like “Objects can be public”. What does that mean?

Well, it means that although by default bucket is not public but can be public. Anyone with the proper permissions can make objects public.

Let’s make the bucket completely private.

We will use the property AccessControl(Canned ACL) as well as PublicAccessBlockConfiguration as mentioned in the template below.

resource "aws_s3_bucket_acl" "demo_bucket_acl" {
  bucket = aws_s3_bucket.demo-bucket.bucket
  acl    = "private"
}
resource "aws_s3_bucket_public_access_block" "demo_public_block" {
  bucket = aws_s3_bucket.demo-bucket.bucket

  block_public_acls   = true
  block_public_policy = true
  ignore_public_acls = true
  restrict_public_buckets = true
}

Add these properties in the template, save it and run terraform apply again. After the successful update you will see, now your bucket access is not public.

Final Configuration File to Create S3 Bucket using Terraform

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.27"
    }
  }
}

provider "aws" {
  profile = "default"
  region  = "ap-south-1"
}


#Resource to create s3 bucket
resource "aws_s3_bucket" "demo-bucket"{
  bucket = "ck-demo-bucket-18th"

  tags = {
    Name = "S3Bucket"
  }
}

#Resource to enable versioning 
resource "aws_s3_bucket_versioning" "versioning_demo" {
  bucket = aws_s3_bucket.demo-bucket.id
  versioning_configuration {
    status = "Enabled"
  }
}

#Resource to enable encryption
resource "aws_s3_bucket_server_side_encryption_configuration" "demo-encryption" {
  bucket = aws_s3_bucket.demo-bucket.bucket

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

#Adds an ACL to bucket
resource "aws_s3_bucket_acl" "demo_bucket_acl" {
  bucket = aws_s3_bucket.demo-bucket.bucket
  acl    = "private"
}

#Block Public Access
resource "aws_s3_bucket_public_access_block" "demo_public_block" {
  bucket = aws_s3_bucket.demo-bucket.bucket

  block_public_acls   = true
  block_public_policy = true
  ignore_public_acls = true
  restrict_public_buckets = true
}

Clean Up

Finally, if you are doing this exercise for learning purpose, you can clean up by destroying the created resource or bucket.

terraform destroy

Conclusion

In this article, we learnt how to create an S3 bucket using terraform. We created the basic bucket and then updated our configuration file gradually to enable some of the features like

  • Versioning
  • Encryption
  • Preventing public access to bucket

I know there are many other things like cors configuration and others that we can do in a bucket.

But I wanted to keep it simple and limited to most common requirements. You can ask me in comment if you want me to cover other features as well.

I hope you were able to work up with me and able to create the s3 bucket. If you get stuck at any time feel free to add a comment. I will reply to your query asap.

Well, That was my take on “How to Create an S3 Bucket using Terraform“. Please feel free to share your feedback.

Enjoyed the content?

Subscribe to our newsletter below to get awesome AWS learning materials delivered straight to your inbox.

If you liked reading my post, you can motivate me by-

  • Adding a comment below on what you liked and what can be improved.
  • Follow us on 
  • Subscribe to our newsletter to get notified each time we post new content.
  • Share this post with your friends and colleagues.

Suggested Read:

Sharing is Caring:

Leave a Reply

Your email address will not be published.