Revertable Deployments with CloudFront OriginPath

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.

links

social