IntermediateCloud Engineer

Provision infrastructure with Terraform

Use Terraform to provision an S3 bucket with versioning enabled, a CloudFront distribution fronting it, and an Origin Access Identity so the bucket is only accessible via CloudFront. Write the configuration, run terraform plan and apply, then destroy and recreate it cleanly to confirm there is no state drift.

Why this matters

Manually provisioned infrastructure is infrastructure that cannot be reproduced, audited, or handed off. Terraform turns infrastructure into reviewable code and makes disaster recovery a matter of running one command. The destroy-and-recreate discipline catches the difference between what your code says and what AWS actually created.

Before you start

Step-by-step guide

  1. 1

    Write the S3 bucket resource

    Define an aws_s3_bucket resource with a unique name. Add aws_s3_bucket_versioning to enable versioning, and aws_s3_bucket_public_access_block to block all public access. Run terraform plan; verify the plan shows 3 resources to create before applying.

  2. 2

    Create the Origin Access Identity

    Define an aws_cloudfront_origin_access_identity resource. Then write an aws_s3_bucket_policy that allows only the OAI's principal to GetObject from the bucket. This is the pattern that keeps your bucket private while allowing CloudFront to serve from it.

  3. 3

    Write the CloudFront distribution

    Define an aws_cloudfront_distribution with the S3 bucket as origin, the OAI attached, HTTPS redirect enforced, and a price_class of PriceClass_100 (cheapest, US/EU only). Output the distribution domain name so you can test it.

  4. 4

    Apply and verify

    Run terraform apply. Upload a test file to the S3 bucket and fetch it via the CloudFront domain. Confirm direct S3 access returns a 403. Confirm CloudFront access returns a 200. Check the Terraform state file to understand what state drift would look like.

  5. 5

    Destroy and recreate

    Run terraform destroy --auto-approve. Verify everything is gone in the AWS console. Run terraform apply again. Compare the output of both applies; they should be identical. If there are differences, your configuration is not fully declarative.

Relevant Axiom pages

What to do next

Back to Practice Lab