Use the Conformity Knowledge Base AI to help improve your Cloud Posture

Enable Origin Failover

Trend Cloud One™ – Conformity is a continuous assurance tool that provides peace of mind for your cloud infrastructure, delivering over 1000 automated best practice checks.

Risk Level: High (not acceptable risk)

Ensure that the Origin Failover feature is enabled for your Amazon CloudFront distributions in order to improve the availability of the web content delivered to your end users (viewers). To implement Origin Failover, you have to create an origin group to provide rerouting during a failover event. Then you can associate an origin group with a cache behavior to have requests routed from a primary origin to a secondary origin as a failover strategy. Before you can create an origin group, you must have two origins configured for your CloudFront distribution.

Reliability

With Origin Failover, you can set up two origins for your Amazon CloudFront distributions: primary and secondary. In the event of primary origin failure, your content is automatically served from the secondary origin, maintaining the distribution's availability and reliability.


Audit

To determine if your Amazon CloudFront distributions are using Origin Failover, perform the following actions:

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to Amazon CloudFront console at https://console.aws.amazon.com/cloudfront/v3/.

03 In the left navigation panel, under CloudFront, choose Distributions.

04 Click on the ID (link) of the Amazon CloudFront distribution that you want to examine.

05 Select the Origins tab to access the origins and origin groups created for the selected distribution.

06 Check for any origin groups listed in the Origin groups section. If there are no origin groups available in this section, instead the following message is displayed: "You don't have any origin groups.", there is no origin group created for the selected Amazon CloudFront distribution, therefore the Origin Failover feature is not enabled.

07 Repeat steps no. 4 – 6 for each CloudFront distribution available within your AWS cloud account.

Using AWS CLI

01 Run list-distributions command (OSX/Linux/UNIX) with custom query filters to list the ID of each Amazon CloudFront distribution created in your AWS cloud account:

aws cloudfront list-distributions
  --output table
  --query 'DistributionList.Items[*].Id'

02 The command output should return a table with the requested distribution ID(s):

--------------------
|ListDistributions |
+------------------+
|  AAAABBBBCCCCDD  |
|  ABCDABCDABCDAB  |
|  AABBCCDDAABBCC  |
+------------------+

03 Run get-distribution command (OSX/Linux/UNIX) using the ID of the Amazon CloudFront distribution that you want to examine as the identifier parameter and custom query filters to return the number of origin groups configured for the selected distribution:

aws cloudfront get-distribution
  --region us-east-1
  --id AAAABBBBCCCCDD
  --query 'Distribution.DistributionConfig.OriginGroups.Quantity'

04 The command output should return the number of origin groups available:

0

If the get-distribution command output returns 0 (zero), as shown in the example above, there is no origin group defined for the selected Amazon CloudFront distribution, therefore the Origin Failover feature is not enabled.

05 Repeat steps no. 3 and 4 for each CloudFront distribution deployed in your AWS cloud account.

Remediation / Resolution

To enable the Origin Failover feature for your existing Amazon CloudFront distributions, perform the following actions:

Using AWS CloudFormation

01 CloudFormation template (JSON):

{
	"AWSTemplateFormatVersion": "2010-09-09",
	"Resources": {
		"CloudFrontDistribution": {
			"Type": "AWS::CloudFront::Distribution",
			"Properties": {
				"DistributionConfig": {
					"Enabled": true,
					"Comment": "CloudFront CDN Web Distribution",
					"Origins": [
						{
							"Id": "cc-main-origin",
							"DomainName": "domain.com",
							"CustomOriginConfig": {
								"HTTPPort": 80,
								"HTTPSPort": 443,
								"OriginSSLProtocols": [
									"TLSv1.2"
								],
								"OriginProtocolPolicy": "https-only"
							}
						},
						{
							"Id": "cc-failover-origin",
							"DomainName": "domain1.com",
							"CustomOriginConfig": {
								"HTTPPort": 80,
								"HTTPSPort": 443,
								"OriginSSLProtocols": [
									"TLSv1.2"
								],
								"OriginProtocolPolicy": "https-only"
							}
						}
					],
					"OriginGroups": [
						{
							"Id": "cc-origin-group",
							"FailoverCriteria": {
								"StatusCodes": {
									"Items": [
										404,
										500,
										502
									],
									"Quantity": 3
								}
							},
							"Members": {
								"Items": [
									{
										"OriginId": "cc-main-origin"
									},
									{
										"OriginId": "cc-failover-origin"
									}
								],
								"Quantity": 2
							}
						}
					],
					"DefaultRootObject": "index.html",
					"DefaultCacheBehavior": {
						"Compress": true,
						"AllowedMethods": [
							"HEAD",
							"GET"
						],
						"DefaultTTL": 0,
						"ForwardedValues": {
							"Cookies": {
								"Forward": "none"
							},
							"QueryString": false
						},
						"ViewerProtocolPolicy": "https-only"
					},
					"HttpVersion": "http2",
					"ViewerCertificate": {
						"CloudFrontDefaultCertificate": true
					},
					"PriceClass": "PriceClass_All"
				}
			}
		}
	}
}

02 CloudFormation template (YAML):

AWSTemplateFormatVersion: '2010-09-09'
	Resources:
	CloudFrontDistribution:
		Type: AWS::CloudFront::Distribution
		Properties:
		DistributionConfig:
			Enabled: true
			Comment: CloudFront CDN Web Distribution
			Origins:
			- Id: cc-main-origin
				DomainName: domain.com
				CustomOriginConfig:
				HTTPPort: 80
				HTTPSPort: 443
				OriginSSLProtocols:
					- TLSv1.2
				OriginProtocolPolicy: https-only
			- Id: cc-failover-origin
				DomainName: domain1.com
				CustomOriginConfig:
				HTTPPort: 80
				HTTPSPort: 443
				OriginSSLProtocols:
					- TLSv1.2
				OriginProtocolPolicy: https-only
			OriginGroups:
			- Id: cc-origin-group
				FailoverCriteria:
				StatusCodes:
					Items:
					- 404
					- 500
					- 502
					Quantity: 3
				Members:
				Items:
					- OriginId: cc-main-origin
					- OriginId: cc-failover-origin
				Quantity: 2
			DefaultRootObject: index.html
			DefaultCacheBehavior:
			Compress: true
			AllowedMethods:
				- HEAD
				- GET
			DefaultTTL: 0
			ForwardedValues:
				Cookies:
				Forward: none
				QueryString: false
			ViewerProtocolPolicy: https-only
			HttpVersion: http2
			ViewerCertificate:
			CloudFrontDefaultCertificate: true
			PriceClass: PriceClass_All

Using Terraform (AWS Provider)

01 Terraform configuration file (.tf):

terraform {
	required_providers {
		aws = {
			source  = "hashicorp/aws"
			version = "~> 4.0"
		}
	}

	required_version = ">= 0.14.9"
}

provider "aws" {
	profile = "default"
	region  = "us-east-1"
}

resource "aws_cloudfront_distribution" "cloudfront-distribution" {

	enabled             = true
	default_root_object = "index.html"
	comment             = "CloudFront CDN Web Distribution"

	origin {
		origin_id   = "cc-main-origin"
		domain_name = "domain.com"
		custom_origin_config = {
			http_port                = 80
			https_port               = 443
			origin_ssl_protocols     = ["TLSv1.2"]
			origin_protocol_policy   = "https-only"
		}
	}

	origin {
		origin_id   = "cc-failover-origin"
		domain_name = "domain1.com"
		custom_origin_config = {
			http_port                = 80
			https_port               = 443
			origin_ssl_protocols     = ["TLSv1.2"]
			origin_protocol_policy   = "https-only"
		}
	}

	origin_group {
		origin_id = "cc-origin-group"
		failover_criteria {
			status_codes = [404, 500, 502]
		}
		member {
			origin_id = "cc-main-origin"
		}
		member {
			origin_id = "cc-failover-origin"
		}
	}

	default_cache_behavior {
		compress         = true
		target_origin_id = "cc-domain-origin"
		allowed_methods  = ["GET", "HEAD"]
		cached_methods   = ["GET", "HEAD"]
		forwarded_values {
			query_string = false
			cookies {
				forward = "none"
			}
		}
		min_ttl                = 0
		default_ttl            = 3600
		max_ttl                = 86400
		viewer_protocol_policy = "https-only"
	}

	viewer_certificate {
		cloudfront_default_certificate = true
	}

	price_class = "PriceClass_All"

}

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to Amazon CloudFront console at https://console.aws.amazon.com/cloudfront/v3/.

03 In the left navigation panel, under CloudFront, choose Distributions.

04 Click on the ID (link) of the Amazon CloudFront distribution that you want to configure.

05 Select the Origins tab to access the origins and origin groups created for the selected distribution.

06 In the Origins section, choose Create origin to set up the secondary origin for your distribution.

07 On the Create origin setup page, perform the following operations:

  1. Click inside the Origin domain box and specify the domain name for your secondary origin. This can be an S3 bucket, an Elastic Load Balancer, an API Gateway API, a MediaStore container, a MediaPackage container, or a web server from which you want Amazon CloudFront to get your web content.
  2. (Optional) For Origin path - optional, enter the URL path to append to the origin domain name for origin requests.
  3. For Name, enter the name of your new distribution origin.
  4. For Origin access, choose Origin access control settings (recommended), and select an existing origin access control (recommended) from the Origin access control list. Choose Create control setting if you want to create a new Origin Access Control (OAC) configuration.
  5. (Optional) For Add custom header – optional, use the Add header button to create the custom header keys and values to be included in every request made to the secondary origin.
  6. Choose Yes under Enable Origin Shield to enable and configure the Origin Shield feature. Select the appropriate AWS region from the Origin Shield region dropdown list.
  7. (Optional) Choose Additional settings if you need to change the default connection settings available for the secondary origin.
  8. Choose Create origin to create your new distribution origin.

08 In the Origin groups section, choose Create origin group to set up the required origin group.

09 On the Create origin group setup page, perform the following actions:

  1. Add the primary and the secondary origins from the Origins dropdown list.
  2. (Optional) Configure the priority order for your distribution origins.
  3. Enter a unique name for the new origin group in the Name box.
  4. For Failover criteria, select one or more status codes (i.e. 4xx and 4xx status codes) to use as the failover criteria. When the codes that you select are returned by your primary origin, requests are rerouted to the secondary origin.
  5. Choose Create origin group to deploy the new origin group. This action will enable the Origin Failover feature for the selected CloudFront distribution. From now on, Amazon CloudFront can automatically switch to the secondary origin when the primary origin returns the status code(s) configured for the origin group at the previous step.

10 Repeat steps no. 4 – 9 for each Amazon CloudFront distribution available within your AWS cloud account.

Using AWS CLI

01 Run get-distribution-config command (OSX/Linux/UNIX) to extract all the configuration information from the Amazon CloudFront distribution that you want to configure:

aws cloudfront get-distribution-config
  --id ABCDABCDABCDAB
  --query 'DistributionConfig'

02 The command output should return the requested configuration information:

{
	"CallerReference": "abcd1234-abcd-1234-abcd-1234abcd1234",
	"Aliases": {
		"Quantity": 0
	},
	"DefaultRootObject": "",
	"Origins": {
		"Quantity": 1,
		"Items": [
			{
				"Id": "cloudconformity.com",
				"DomainName": "cloudconformity.com",
				"OriginPath": "",
				"CustomHeaders": {
					"Quantity": 0
				},
				"CustomOriginConfig": {
					"HTTPPort": 80,
					"HTTPSPort": 443,
					"OriginProtocolPolicy": "https-only",
					"OriginSslProtocols": {
						"Quantity": 1,
						"Items": [
							"TLSv1.2"
						]
					},
					"OriginReadTimeout": 30,
					"OriginKeepaliveTimeout": 5
				},
				"ConnectionAttempts": 3,
				"ConnectionTimeout": 10,
				"OriginShield": {
					"Enabled": false
				}
			}
		]
	},
	"OriginGroups": {
		"Quantity": 0
	},
	"DefaultCacheBehavior": {
		"TargetOriginId": "cloudconformity.com",
		"TrustedSigners": {
			"Enabled": false,
			"Quantity": 0
		},
		"TrustedKeyGroups": {
			"Enabled": false,
			"Quantity": 0
		},
		"ViewerProtocolPolicy": "allow-all",
		"AllowedMethods": {
			"Quantity": 2,
			"Items": [
				"HEAD",
				"GET"
			],
			"CachedMethods": {
				"Quantity": 2,
				"Items": [
					"HEAD",
					"GET"
				]
			}
		},
		"SmoothStreaming": false,
		"Compress": true,
		"LambdaFunctionAssociations": {
			"Quantity": 0
		},
		"FunctionAssociations": {
			"Quantity": 0
		},
		"FieldLevelEncryptionId": "",
		"ForwardedValues": {
			"QueryString": false,
			"Cookies": {
				"Forward": "none"
			},
			"Headers": {
				"Quantity": 0
			},
			"QueryStringCacheKeys": {
				"Quantity": 0
			}
		},
		"MinTTL": 0,
		"DefaultTTL": 86400,
		"MaxTTL": 31536000
	},
	"CacheBehaviors": {
		"Quantity": 1,
		"Items": [
			{
				"PathPattern": "/images",
				"TargetOriginId": "cloudconformity.com",
				"TrustedSigners": {
					"Enabled": false,
					"Quantity": 0
				},
				"TrustedKeyGroups": {
					"Enabled": false,
					"Quantity": 0
				},
				"ViewerProtocolPolicy": "allow-all",
				"AllowedMethods": {
					"Quantity": 2,
					"Items": [
						"HEAD",
						"GET"
					],
					"CachedMethods": {
						"Quantity": 2,
						"Items": [
							"HEAD",
							"GET"
						]
					}
				},
				"SmoothStreaming": false,
				"Compress": true,
				"LambdaFunctionAssociations": {
					"Quantity": 0
				},
				"FunctionAssociations": {
					"Quantity": 0
				},
				"FieldLevelEncryptionId": "",
				"ForwardedValues": {
					"QueryString": false,
					"Cookies": {
						"Forward": "none"
					},
					"Headers": {
						"Quantity": 0
					},
					"QueryStringCacheKeys": {
						"Quantity": 0
					}
				},
				"MinTTL": 0,
				"DefaultTTL": 86400,
				"MaxTTL": 31536000
			}
		]
	},
	"CustomErrorResponses": {
		"Quantity": 0
	},
	"Comment": "",
	"Logging": {
		"Enabled": false,
		"IncludeCookies": false,
		"Bucket": "",
		"Prefix": ""
	},
	"PriceClass": "PriceClass_100",
	"Enabled": true,
	"ViewerCertificate": {
		"CloudFrontDefaultCertificate": true,
		"MinimumProtocolVersion": "TLSv1",
		"CertificateSource": "cloudfront"
	},
	"Restrictions": {
		"GeoRestriction": {
			"RestrictionType": "none",
			"Quantity": 0
		}
	},
	"WebACLId": "",
	"HttpVersion": "http1.1",
	"IsIPV6Enabled": false
}

03 Run get-distribution-config command (OSX/Linux/UNIX) to describe the current version of the configuration available for the selected distribution (i.e. eTag):

aws cloudfront get-distribution-config
  --id ABCDABCDABCDAB
  --query 'ETag'

04 The command output should return the requested information:

"AAAABBBBCCCCD"

05 Modify the configuration document returned at step no. 2 to enable the Origin Failover feature by adding a secondary origin to the selected distribution and creating a new origin group (see the "Origins" and "OriginGroups" objects). Save the document with the modified distribution configuration to a JSON file named enable-origin-failover.json:

{
	"CallerReference": "abcd1234-abcd-1234-abcd-1234abcd1234",
	"Aliases": {
		"Quantity": 0
	},
	"DefaultRootObject": "",
	"Origins": {
		"Quantity": 2,
		"Items": [
			{
				"Id": "trendmicro.com",
				"DomainName": "trendmicro.com",
				"OriginPath": "",
				"CustomHeaders": {
					"Quantity": 0
				},
				"CustomOriginConfig": {
					"HTTPPort": 80,
					"HTTPSPort": 443,
					"OriginProtocolPolicy": "https-only",
					"OriginSslProtocols": {
						"Quantity": 1,
						"Items": [
							"TLSv1.2"
						]
					},
					"OriginReadTimeout": 30,
					"OriginKeepaliveTimeout": 5
				},
				"ConnectionAttempts": 3,
				"ConnectionTimeout": 10,
				"OriginShield": {
					"Enabled": false
				}
			},
			{
				"Id": "trendmicro1.com",
				"DomainName": "trendmicro1.com",
				"OriginPath": "",
				"CustomHeaders": {
					"Quantity": 0
				},
				"CustomOriginConfig": {
					"HTTPPort": 80,
					"HTTPSPort": 443,
					"OriginProtocolPolicy": "https-only",
					"OriginSslProtocols": {
						"Quantity": 1,
						"Items": [
							"TLSv1.2"
						]
					},
					"OriginReadTimeout": 30,
					"OriginKeepaliveTimeout": 5
				},
				"ConnectionAttempts": 3,
				"ConnectionTimeout": 10,
				"OriginShield": {
					"Enabled": false
				}
			}
		]
	},
	"OriginGroups": {
		"Items": [
			{
				"Id": "trendmicro.com-origin-group",
				"Members": {
					"Items": [
						{
							"OriginId": "trendmicro.com"
						},
						{
							"OriginId": "trendmicro1.com"
						}
					],
					"Quantity": 2
				},
				"FailoverCriteria": {
					"StatusCodes": {
						"Items": [
							500
						],
						"Quantity": 1
					}
				}
			}
		],
		"Quantity": 1
	},
	"DefaultCacheBehavior": {
		"TargetOriginId": "trendmicro.com",
		"TrustedSigners": {
			"Enabled": false,
			"Quantity": 0
		},
		"TrustedKeyGroups": {
			"Enabled": false,
			"Quantity": 0
		},
		"ViewerProtocolPolicy": "allow-all",
		"AllowedMethods": {
			"Quantity": 2,
			"Items": [
				"HEAD",
				"GET"
			],
			"CachedMethods": {
				"Quantity": 2,
				"Items": [
					"HEAD",
					"GET"
				]
			}
		},
		"SmoothStreaming": false,
		"Compress": true,
		"LambdaFunctionAssociations": {
			"Quantity": 0
		},
		"FunctionAssociations": {
			"Quantity": 0
		},
		"FieldLevelEncryptionId": "",
		"ForwardedValues": {
			"QueryString": false,
			"Cookies": {
				"Forward": "none"
			},
			"Headers": {
				"Quantity": 0
			},
			"QueryStringCacheKeys": {
				"Quantity": 0
			}
		},
		"MinTTL": 0,
		"DefaultTTL": 86400,
		"MaxTTL": 31536000
	},
	"CacheBehaviors": {
		"Quantity": 1,
		"Items": [
			{
				"PathPattern": "/images",
				"TargetOriginId": "trendmicro.com",
				"TrustedSigners": {
					"Enabled": false,
					"Quantity": 0
				},
				"TrustedKeyGroups": {
					"Enabled": false,
					"Quantity": 0
				},
				"ViewerProtocolPolicy": "allow-all",
				"AllowedMethods": {
					"Quantity": 2,
					"Items": [
						"HEAD",
						"GET"
					],
					"CachedMethods": {
						"Quantity": 2,
						"Items": [
							"HEAD",
							"GET"
						]
					}
				},
				"SmoothStreaming": false,
				"Compress": true,
				"LambdaFunctionAssociations": {
					"Quantity": 0
				},
				"FunctionAssociations": {
					"Quantity": 0
				},
				"FieldLevelEncryptionId": "",
				"ForwardedValues": {
					"QueryString": false,
					"Cookies": {
						"Forward": "none"
					},
					"Headers": {
						"Quantity": 0
					},
					"QueryStringCacheKeys": {
						"Quantity": 0
					}
				},
				"MinTTL": 0,
				"DefaultTTL": 86400,
				"MaxTTL": 31536000
			}
		]
	},
	"CustomErrorResponses": {
		"Quantity": 0
	},
	"Comment": "",
	"Logging": {
		"Enabled": false,
		"IncludeCookies": false,
		"Bucket": "",
		"Prefix": ""
	},
	"PriceClass": "PriceClass_100",
	"Enabled": true,
	"ViewerCertificate": {
		"CloudFrontDefaultCertificate": true,
		"MinimumProtocolVersion": "TLSv1",
		"CertificateSource": "cloudfront"
	},
	"Restrictions": {
		"GeoRestriction": {
			"RestrictionType": "none",
			"Quantity": 0
		}
	},
	"WebACLId": "",
	"HttpVersion": "http1.1",
	"IsIPV6Enabled": false
}

06 Run update-distribution command (OSX/Linux/UNIX) using the document modified at the previous step (i.e. enable-origin-failover.json) as the new distribution configuration document, to configure the selected Amazon CloudFront distribution in order to enable the Origin Failover feature. --if-match parameter represents the current version of the configuration, returned at step no. 4:

aws cloudfront update-distribution
  --id ABCDABCDABCDAB
  --if-match AAAABBBBCCCCD
  --distribution-config file://enable-origin-failover.json
  --query 'Distribution.Status'

07 The command output should return the status of the modified CloudFront distribution:

"InProgress"

08 Repeat steps no. 1 – 7 for each Amazon CloudFront distribution deployed in your AWS cloud account.

References

Publication date Jan 27, 2019