Project · Cloud Computing (AWS, Azure, Google Cloud)
Project: a secure S3 bucket with Terraform
The brief
Write Terraform for a private S3 bucket in Mumbai with versioning, default encryption, Block Public Access and the team's required tags. Write two plan checks in Python that a CI pipeline would run (a tag policy and the plan summary), then validate, plan, apply, prove the settings with the AWS CLI, and destroy everything.
Why it matters
Companies no longer click buckets into existence: every resource is code, reviewed in a pull request, checked by a pipeline and applied from a saved plan. Platform and DevOps engineers write exactly these files and checks, and "every resource must carry Project, Owner and Environment tags" is a real rule that finance teams use to split the cloud bill.
Skills you practise
- Terraform providers, variables, resources and outputs
- default_tags
- terraform init, validate, plan -out, apply and destroy
- S3 versioning, SSE-S3 encryption and Block Public Access in code
- reading terraform show -json
- policy checks on plans
You need
- A free AWS account with a budget alert set (lab cc-lab-safe-account)
- AWS CLI v2 configured with an IAM Identity Center or IAM user profile, not root, region ap-south-1
- Terraform 1.x (1.6 or newer) installed, or AWS CloudShell with Terraform installed in your home folder
What you will have at the end
main.tf for a secure S3 bucket, plan_checks.py with a tested tag policy and plan summary, and the pasted validate, plan, apply, CLI check and destroy output: a small infrastructure-as-code repository you can show an employer.
How it is marked (rubric, 100 points)
| Correct infrastructureValidate, plan and apply succeed, and the CLI shows versioning Enabled, AES256 and the three tags. | 30 |
|---|---|
| Plan checksmissing_tags and plan_summary pass every check, including replacements, deletes and untaggable resources. | 30 |
| Safe workflowThe plan was saved and reviewed before apply, state stayed out of Git, a budget was set, and everything was destroyed. | 25 |
| ExplainedYou can explain default_tags versus tags, and why a -/+ replacement in a plan needs a careful look. | 15 |
0/8 steps done
Step 1 of 8
Write main.tf and initialise
main.tf describes the four bucket resources with default tags, and terraform init has downloaded the hashicorp/aws provider.
Fill in every TODO in main.tf, in a new empty folder. In the current AWS provider the bucket, its versioning, its encryption and its public access block are four separate resources, linked by aws_s3_bucket.prices.id. default_tags in the provider block puts Project, Owner and Environment on every resource that can be tagged.
Also create terraform.tfvars with one line, bucket_name = "kirana-tf-<yourname>-<digits>". Then run terraform init, which downloads the provider, and terraform version, which now lists it.
terraform {
required_version = ">= 1.6"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
}
provider "aws" {
region = "ap-south-1" # Mumbai
default_tags {
tags = {
Project = "kirana-prices"
Owner = var.owner
Environment = "dev"
}
}
}
variable "bucket_name" {
type = string
description = "A globally unique name, for example kirana-tf-asha-4821"
}
variable "owner" {
type = string
default = "asha"
}
resource "aws_s3_bucket" "prices" {
bucket = var.bucket_name
}
resource "aws_s3_bucket_versioning" "prices" {
bucket = aws_s3_bucket.prices.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "prices" {
bucket = aws_s3_bucket.prices.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
resource "aws_s3_bucket_public_access_block" "prices" {
bucket = aws_s3_bucket.prices.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
output "bucket_name" {
value = aws_s3_bucket.prices.bucket
}$ terraform init; terraform versionAlso check yourself
Your notes: main.tf, plan_checks.py
Write down each command you ran. It goes into your project summary.