ACL (Access Control List) in S3 is a mechanism for defining permissions (read, write, full control) on objects and buckets, allowing you to grant access to specific AWS accounts or groups.
Provision an AWS S3 bucket using Terraform
Key takeaways:
Terraform as IaC tool: Terraform is a powerful infrastructure as code (IaC) tool that allows us to define and provision infrastructure using code in a safe, consistent, and efficient manner.
S3 bucket creation: Create an S3 bucket using Terraform by defining AWS credentials and specifying bucket properties such as region, public access settings, ownership controls, and ACL permissions.
Public access: Manage ownership controls and public access policies for S3 buckets.
Uploading objects to S3: Terraform also helps with uploading files.
Terraform is a software tool for infrastructure as code (IaC), a technique for provisioning computing infrastructure using machine-readable code files. Terraform is used for building, editing, and versioning infrastructure safely and efficiently. It efficiently manages the provisioning of infrastructure and does not ask how to provision the infrastructure; it just asks what to do and implement it.
First, we’ll investigate the code and then provision the infrastructure. Finally, let’s examine how to create a public S3 bucket. Then, we’ll upload an object to the bucket and finally attach a resource policy to publicly access the bucket objects.
Follow the “What does Infrastructure as Code even mean?” Answer to learn further about IaC.
Create an S3 bucket
We need to log into AWS using the provider block. The credentials access_key and the secret_key are used to log in to AWS. These credentials should be passed as environment variables to Terraform, but here, we’ll pass them in the file for learning purposes. To create an S3 bucket with public contents, we’ll specify ownership controls and allow public access to the bucket and bucket ACL permissions using resource blocks.
provider "aws"{region="us-east-1"# Do not pass access and secret access key in a file, this is for learning purposes only# Pass these values through CMD or in encrypted format.access_key = "{{access_key_id}}"secret_key = "{{secret_access_key}}"}resource "aws_s3_bucket" "my_bucket"{bucket="my-bucket-<Unique_Number/Text_Here>"}resource "aws_s3_bucket_ownership_controls" "my_bucket" {bucket = aws_s3_bucket.my_bucket.idrule {object_ownership = "BucketOwnerPreferred"}}resource "aws_s3_bucket_public_access_block" "my_bucket" {bucket = aws_s3_bucket.my_bucket.idblock_public_acls = falseblock_public_policy = falseignore_public_acls = truerestrict_public_buckets = false}resource "aws_s3_bucket_acl" "my_bucket" {depends_on = [aws_s3_bucket_ownership_controls.my_bucket,aws_s3_bucket_public_access_block.my_bucket,]bucket = aws_s3_bucket.my_bucket.idacl = "public-read"}
Explanation
Let’s take a look at the code above line by line and understand it carefully.
Lines 1–7: A provider block is used to specify that the Terraform configuration will be using AWS as the provider. It also sets the AWS region to
us-east-1and provides the AWS access key and secret key for authentication.Lines 8–10: A resource block is used to create and name the S3 bucket.
Lines 12–17: This resource block configures ownership controls of the S3 bucket. It specifies that the object ownership is set to
BucketOwnerPreferred. This ensures that the bucket owner owns objects uploaded to the bucket.Lines 19–26: This block configures public access settings for the S3 bucket. The
bucketattribute is used to reference the ID of the S3 bucket. Different attributes likeblock_public_acls,block_public_policy, etc., are set tofalse, to allow public access.Lines 28–36: This block sets the ACL for the S3 bucket to
public-read.Thedepends_onattribute ensures that this resource depends on the completion of the ownership controls and public access block configurations.
Upload an object to S3
Now that we have created a public S3 bucket on AWS. We'll upload an object index.html to our S3 bucket.
resource "aws_s3_object" "my_object" {bucket = aws_s3_bucket.my_bucket.bucketkey = "index.html"source = "index.html"content_type="text/html"}
Explanation
Let’s take a look at the above resource block and understand it carefully.
Lines 1–6: The block uploads a file
index.htmlto the S3 bucketmy_bucketwith the specified key. Thesourceattribute specifies the local file to upload. Thekeyattribute specifies the key (path) of the S3 object.
Attach a resource policy to the S3 bucket
We have created a public S3 bucket and uploaded index.html to it. To allow public access to the bucket’s contents, we would attach a resource policy. We'll attach a resource policy to the bucket using a data block.
data "aws_iam_policy_document" "allow_access" {statement {principals {type = "*"identifiers = ["*"]}actions = ["s3:GetObject"]resources = [aws_s3_bucket.my_bucket.arn,"${aws_s3_bucket.my_bucket.arn}/*",]}}resource "aws_s3_bucket_policy" "allow_access" {bucket = aws_s3_bucket.my_bucket.idpolicy = data.aws_iam_policy_document.allow_access.json}
Explanation
Let’s take a look at the above resource blocks and understand it carefully.
Lines 1–17: This block creates an IAM policy document to allow public access to objects in the S3 bucket using a data block. The policy allows the
s3:GetObjectpermission to everyone (*) for the specified S3 bucket and its objects.Lines 19–22: This block attaches the IAM policy document,
allow_access, from the data block to the S3 bucket as a bucket policy. Thebucketattribute references the S3 bucket created earlier, and thepolicyattribute references the JSON representation of the IAM policy document.
Putting it all together
Now that we have understood the code, let’s combine all the code blocks and provision the infrastructure on AWS.
Note: Replace the placeholder
<Unique_Number/Text_Here>with a unique number or text at the end of the S3 bucket name on line 5 in the widget below to ensure that the bucket name is globally unique.
provider "aws"{
region="us-east-1"
}
resource "aws_s3_bucket" "my_bucket"{
bucket="my-bucket-<Unique_Number/Text_Here>"
}
resource "aws_s3_bucket_ownership_controls" "my_bucket" {
bucket = aws_s3_bucket.my_bucket.id
rule {
object_ownership = "BucketOwnerPreferred"
}
}
resource "aws_s3_bucket_public_access_block" "my_bucket" {
bucket = aws_s3_bucket.my_bucket.id
block_public_acls = false
block_public_policy = false
ignore_public_acls = true
restrict_public_buckets = false
}
resource "aws_s3_bucket_acl" "my_bucket" {
depends_on = [
aws_s3_bucket_ownership_controls.my_bucket,
aws_s3_bucket_public_access_block.my_bucket,
]
bucket = aws_s3_bucket.my_bucket.id
acl = "public-read"
}
resource "aws_s3_object" "my_object" {
bucket = aws_s3_bucket.my_bucket.bucket
key = "index.html"
source = "index.html"
content_type="text/html"
}
data "aws_iam_policy_document" "allow_access" {
statement {
principals {
type = "*"
identifiers = ["*"]
}
actions = [
"s3:GetObject"
]
resources = [
aws_s3_bucket.my_bucket.arn,
"${aws_s3_bucket.my_bucket.arn}/*",
]
}
}
resource "aws_s3_bucket_policy" "allow_access" {
bucket = aws_s3_bucket.my_bucket.id
policy = data.aws_iam_policy_document.allow_access.json
}Click the “Run” button and type the following command to initialize the Terraform directory, terraform init is used to resolve and install dependencies. After initializing the directory, use terraform plan to see the execution plan; it’s an optional step. After this, execute the configuration file using terraform apply, it asks for confirmation, then type yes, and then Terraform will create the requested infrastructure.
terraform initterraform apply
Verify the resources
We have provisioned the infrastructure; let’s log in to our AWS account to verify the creation of the bucket. We can also check that we have uploaded index.html to our S3 bucket; take a look at the contents of our S3 bucket to verify that the object is uploaded to the bucket.
Search and select S3 in the AWS Management Console.
Go to the S3 buckets page and click the bucket name to open the bucket.
We can see the uploaded file index.html in the bucket.
To deepen your understanding of provisioning AWS resources using Terraform, consider checking out these comprehensive Cloud Labs:
Conclusion
We briefly discussed Terraform, how to provision an S3 bucket, and how to control bucket permissions. We also learned how to modify a bucket’s public permissions and uploaded an object using the Terraform configurations.
Frequently asked questions
Haven’t found what you were looking for? Contact Us
What is ACL in S3?
What are the three methods to access AWS?
What does S3 stand for?
What is the maximum size of the S3 bucket?
Free Resources