Ravindra BagaleCourses & study guides मराठी Track your progress

AWS CLI CloudFront Commands: Create a Distribution and Invalidate Cache

We serve files fast worldwide: a CloudFront distribution in front of a private S3 bucket, config updates with ETag, cache invalidation, then disable and delete.

What you'll learn in this chapter

  • Origin access control
  • Create a distribution
  • Bucket policy for CloudFront
  • Invalidate the cache
  • Update, disable and delete

1. The big picture: local milk booths

Why do we need this?

The dairy is far, so milk is kept in small booths in every area. CloudFront keeps copies of your files at edge locations near users, and only goes to the origin (S3) when a copy is missing or old.

What is it?

Commands are in aws cloudfront. It is global; updates and deletes need the current ETag as --if-match.

How to do it (step by step)

CDN workflowprivate S3 bucketcreate-origin-access-controlcreate-distributionbucket policy allows CloudFrontcreate-invalidation after deploy
A distribution takes a few minutes to deploy everywhere.

2. Origin access control

Why do we need this?

The bucket should stay private; only CloudFront may read it.

What is it?

An OAC signs CloudFront requests to S3. The bucket policy then allows cloudfront.amazonaws.com for your distribution only.

How to do it (step by step)

  1. Create the OAC.
OAC=$(aws cloudfront create-origin-access-control --origin-access-control-config Name=cli-oac,SigningProtocol=sigv4,SigningBehavior=always,OriginAccessControlOriginType=s3 --query OriginAccessControl.Id --output text)
echo $OAC

Expected output:

E2QWRUHAPOMQZL

3. Create the distribution

Why do we need this?

Users in Delhi and London should both load the site quickly over HTTPS.

What is it?

A distribution config lists origins, a default cache behavior, viewer protocol policy and a default root object. CallerReference must be unique.

How to do it (step by step)

  1. Write the config.
cat > dist.json <<J
{"CallerReference":"cli-$(date +%s)","Comment":"cli site","Enabled":true,"DefaultRootObject":"index.html",
 "Origins":{"Quantity":1,"Items":[{"Id":"s3","DomainName":"cli-site-bucket.s3.ap-south-1.amazonaws.com","OriginAccessControlId":"$OAC","S3OriginConfig":{"OriginAccessIdentity":""}}]},
 "DefaultCacheBehavior":{"TargetOriginId":"s3","ViewerProtocolPolicy":"redirect-to-https","CachePolicyId":"658327ea-f89d-4fab-a63d-7e88639e58f6"}}
J

Expected output:

(no output means success)
  1. Create and wait.
D=$(aws cloudfront create-distribution --distribution-config file://dist.json --query Distribution.[Id,DomainName] --output text)
echo $D
aws cloudfront wait distribution-deployed --id ${D%%[[:space:]]*}

Expected output:

E1ABCDEF234567  d111111abcdef8.cloudfront.net

4. Bucket policy and test

Why do we need this?

Without the policy CloudFront gets 403 from S3.

What is it?

Allow s3:GetObject to the cloudfront service principal, with AWS:SourceArn equal to your distribution ARN.

How to do it (step by step)

  1. Apply the policy.
ID=E1ABCDEF234567
cat > bp.json <<J
{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"cloudfront.amazonaws.com"},"Action":"s3:GetObject","Resource":"arn:aws:s3:::cli-site-bucket/*","Condition":{"StringEquals":{"AWS:SourceArn":"arn:aws:cloudfront::111122223333:distribution/$ID"}}}]}
J
aws s3api put-bucket-policy --bucket cli-site-bucket --policy file://bp.json

Expected output:

(no output means success)
  1. Test.
curl -sI https://d111111abcdef8.cloudfront.net/ | grep -iE "^HTTP|x-cache"

Expected output:

HTTP/2 200
x-cache: Miss from cloudfront
  1. Test again (from cache).
curl -sI https://d111111abcdef8.cloudfront.net/ | grep -i x-cache

Expected output:

x-cache: Hit from cloudfront

5. Invalidate, update, disable

Why do we need this?

You uploaded a new index.html but users still see the old one; later you want to change or remove the distribution.

What is it?

create-invalidation removes cached paths. update-distribution needs the full config and the ETag from get-distribution-config.

How to do it (step by step)

  1. Invalidate.
aws cloudfront create-invalidation --distribution-id $ID --paths "/index.html" "/css/*" --query Invalidation.Status --output text

Expected output:

InProgress
  1. Get config and ETag, then disable.
aws cloudfront get-distribution-config --id $ID > cfg.json
E=$(jq -r .ETag cfg.json)
jq .DistributionConfig cfg.json | jq ".Enabled=false" > new.json
aws cloudfront update-distribution --id $ID --if-match $E --distribution-config file://new.json --query Distribution.Status --output text

Expected output:

InProgress

6. Same action in Python, Node.js, Java, Go, .NET and PHP

Why do we need this?

Scripts start in the CLI. Apps call the same API through an SDK. Knowing both helps you move a tested command into real code.

What is it?

Each CLI command maps to one API call. For example aws cloudfront create-invalidation --distribution-id $ID --paths "/*" maps to the Invalidate API.

How to do it (step by step)

Same action (Invalidate) from code. Every SDK reads the same profile, region and credentials as the CLI.

StackCode
Python (boto3)boto3.client("cloudfront").create_invalidation(DistributionId=id,InvalidationBatch={"Paths":{"Quantity":1,"Items":["/*"]},"CallerReference":str(time.time())})
Node.js (v3)await cf.send(new CreateInvalidationCommand({DistributionId:id,InvalidationBatch:{Paths:{Quantity:1,Items:["/*"]},CallerReference:Date.now().toString()}}));
Java (v2)cf.createInvalidation(r -> r.distributionId(id).invalidationBatch(b -> b.callerReference(""+System.currentTimeMillis()).paths(p -> p.quantity(1).items("/*"))));
Go (v2)c.CreateInvalidation(ctx, &cloudfront.CreateInvalidationInput{DistributionId: aws.String(id), InvalidationBatch: batch})
.NETawait cf.CreateInvalidationAsync(new CreateInvalidationRequest{DistributionId=id,InvalidationBatch=batch});
PHP$cf->createInvalidation(["DistributionId"=>$id,"InvalidationBatch"=>$batch]);

7. Clean up so nothing keeps costing

Why do we need this?

Lab resources left running cost money and can be a security risk.

What is it?

Delete in reverse order: children first, then parents.

How to do it (step by step)

  1. Wait for the disabled state to deploy.
aws cloudfront wait distribution-deployed --id $ID

Expected output:

(no output means success)
  1. Delete with the new ETag.
E=$(aws cloudfront get-distribution --id $ID --query ETag --output text)
aws cloudfront delete-distribution --id $ID --if-match $E

Expected output:

(no output means success)
  1. Delete the OAC.
E=$(aws cloudfront get-origin-access-control --id $OAC --query ETag --output text)
aws cloudfront delete-origin-access-control --id $OAC --if-match $E

Expected output:

(no output means success)
  1. Verify.
aws cloudfront list-distributions --query "DistributionList.Items[?Id=='$ID']"

Expected output:

[]

Ravindra Bagale's Tip

"PreconditionFailed" means your ETag is old. Every update returns a new ETag, so fetch it again right before each update or delete.

8. Interview questions and answers

Q. What is an edge location?

A CloudFront site near users that caches content.

Q. OAC vs public bucket?

OAC keeps the bucket private and lets only your distribution read it.

Q. Why --if-match?

Optimistic locking with the ETag so two people do not overwrite each other.

Q. How to show new files immediately?

create-invalidation for the paths, or use versioned file names.

Q. Why disable before delete?

CloudFront only deletes distributions that are disabled and deployed.

Try at home

  1. Put an index.html in a private bucket and serve it through CloudFront over HTTPS.
  2. Change the file, invalidate it and confirm the new version.

In short

  1. OAC keeps S3 private.
  2. create-distribution.
  3. Bucket policy with SourceArn.
  4. create-invalidation.
  5. ETag + --if-match.

Practice Tasks

About this scenario

Nairobi Ride is a transport business in Nairobi. Wanjiru Kamau looks after its IT and cloud work. They count money in KES and run their AWS resources in the af-south-1 Region. In the tasks below you do real jobs for them using what this lesson teaches. All names, account IDs, IP addresses and numbers are made up for practice.

0 / 10

Easy List distributions

Why: Find the distribution ID and domain name.

What to do: List all CloudFront distributions.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Easy How many addresses in a /16?

Why: Picking a VPC size needs this count.

What to do: Nairobi Ride plans the VPC 10.205.0.0/16. How many IP addresses does it hold in total?

How:
  1. Write down the numbers the task gives you.
  2. Work it out step by step on paper.
  3. Type only the final answer in the box.
  4. Click Check answer.

Easy Port for SSH

Why: Security group rules need the right port.

What to do: Which TCP port must the security group open for SSH?

How:
  1. Write down the numbers the task gives you.
  2. Work it out step by step on paper.
  3. Type only the final answer in the box.
  4. Click Check answer.

Medium Clear the CloudFront cache

Why: After a deploy, invalidate so visitors get the new files now, not after the TTL.

What to do: Invalidate all paths (/*) on distribution E2QWRUHAPOMQZL.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Create a distribution from a config file

Why: The full config (origins, behaviors, certificate) is easiest to keep in JSON.

What to do: Create a CloudFront distribution from dist.json.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Invalidate two paths

Why: Invalidating only what changed is cheaper and faster.

What to do: On E2QWRUHAPOMQZL, invalidate /index.html and /css/site.css.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Bucket policy for CloudFront OAC

Why: With OAC, only your CloudFront distribution may read the private bucket.

What to do: Allow the service cloudfront.amazonaws.com to s3:GetObject on nairobiride-site/*, only when aws:SourceArn equals arn:aws:cloudfront::104591109902:distribution/E2QWRUHAPOMQZL.

How:
  1. Start with { "Version": "2012-10-17", "Statement": [ ... ] }.
  2. In each statement write Effect, Action and Resource.
  3. Give only what the task needs (least privilege).
  4. Use double quotes and commas correctly. Click Check answer.

Hard Create an Origin Access Control

Why: OAC lets only CloudFront read your private S3 bucket.

What to do: Create an origin access control from oac.json.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Request a free certificate for CloudFront

Why: CloudFront only uses ACM certificates from us-east-1. DNS validation renews automatically.

What to do: Request a certificate for nairobiride.co.ke and www.nairobiride.co.ke with DNS validation, in us-east-1.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Make a CloudFront signed URL

Why: Signed URLs let only paying users watch a video, for a limited time.

What to do: Sign https://d111.cloudfront.net/course/intro.mp4 with key pair ID K2JCJMDEHXQW5F, private key private_key.pem, expiring 2026-12-31.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Revision, comparison and interview cards

Revise this lesson in a few minutes. Save the cards on your phone or download them as PNG files. The QR code on each card opens this lesson.

CloudFront distribution. Milk booths near every home. OAC keeps the bucket private. create-distribution, wait deployed. Bucket policy with AWS:SourceArn.
Revision card: CloudFront distribution · Download PNG · Open card page
CloudFront invalidate. Users still see the old file. create-invalidation for paths. Updates need ETag + --if-match. Disable, wait, then delete.
Revision card: CloudFront invalidate · Download PNG · Open card page
Invalidation vs Versioned names. Remove cached paths. / New name like app.v2.css.
Comparison: Invalidation vs Versioned names · Download PNG · Open card page
CloudFront PreconditionFailed?. Your ETag is old. Every update returns a new ETag. Fetch it right before update or delete.
Interview card: CloudFront PreconditionFailed? · Download PNG · Open card page

More cards: Ravi Sir's Cards.