Intro
Here's a technique I recently learned to get revertable deploys when using CloudFront in front of an S3 hosted website.
The cornerstone is manipulating the CloudFront OriginPath attribute.
With a few tweaks, this technique could be used in a CI/CD pipeline to publish with blue/green deployments.
Details
First deploy your latest website content to a unique path in the S3 bucket, eg. if using CodeBuild,
the $CODEBUILD_BUILD_ID environment variable is suitable.
Then you'll need 3 pieces of data:
- CloudFront Distribution ID, eg.
E9J9OGH9OJ9HHC - CloudFront Origin ID, eg.
public_bucket - A path in your S3 bucket to the latest build of the website, with a leading, but no trailing slash, eg.
/unique-id-from-build-process-6789
These can be obtained from the AWS console or other techniques and set variables in the deployment script:
# bash
export DISTRIBUTION_ID=E9J9OGH9OJ9HHC
export CLOUDFRONT_ORIGIN_ID="public_bucket"
export S3_LATEST_BUILD_FOLDER="/unique-id-from-build-process-6789"
In order to update a CloudFront distribution, it's necessary to first get the complete current definition.
Pipe this into a temporary file and then use jq to parse out the ETag and to update the CloudFront OriginPath.
Careful with the shell and jq command's quotes, getting them correctly escaped can be tricky.
For setting ETAG below, JQ is using -r for raw mode:
# bash
aws cloudfront get-distribution --id "${DISTRIBUTION_ID}" > cloudfront.json
ETAG="$(jq -r '.ETag' cloudfront.json )"
UPDATED_CONFIG="$(jq ".Distribution.DistributionConfig |
(select(.Origins.Items[][\"Id\"] == \"${CLOUDFRONT_ORIGIN_ID}\") |
.Origins.Items[].OriginPath ) = \"/$S3_LATEST_BUILD_FOLDER\" " cloudfront.json )"
Finally, apply the updated setting with the AWS cli:
# bash
aws cloudfront update-distribution --id "${DISTRIBUTION_ID}" --if-match "$ETAG" --distribution-config "$UPDATED_CONFIG"
With the OriginPath updated from the AWS cli, the new settings can be checked in the AWS console.
Finally
The usual website URLs will be serving the latest content, from the S3 bucket key set in OriginPath.
To revert a publish, simply reset the OriginPath to the last good build.