Skip to content

feat: Improve CDN origin control #140

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Apr 4, 2025

Conversation

jwadolowski
Copy link
Contributor

@jwadolowski jwadolowski commented Mar 25, 2025

what

  1. Enable explicit origin type definition - generic backend (default for compatibility reasons) vs S3 bucket
  2. Ignore OAC unless S3 origin was specified
  3. Add OAI support
  4. Make sure origin shield can be specified for non-default origins

why

Currently, the module aims for a backend/cloud/platform-agnostic default origin. All of its details (port, protocol, domain, etc) are placed inside custom_origin_config block. Unfortunately, custom_origin_config presence implies lack of OAC/OAI support.

Here's my use case:

  • I manage a CloudFront instance using cloudposse/cloudfront-cdn/aws in AWS account A
  • the CF distribution is pointed at an S3 bucket that's deployed to AWS account B (outside of my control)
  • the team that manages the B account would like to protect the bucket from unauthorized access by leveraging either Origin Access Identity or Origin Access Control

Technically, the module allows me to assign an S3 bucket URL to origin_domain_name, but I can associate neither OAC (even though origin_access_control_id exists) nor OAI (no such option at the moment, however OAI gets created by the module) with it.

The following code fails upon apply:

resource "aws_cloudfront_origin_access_control" "s3" {
  name                              = "example"
  origin_access_control_origin_type = "s3"
  signing_behavior                  = "always"
  signing_protocol                  = "sigv4"
}

module "cdn" {
  source    = "cloudposse/cloudfront-cdn/aws"
  version   = "1.2.0"
  namespace = "test"
  
  # ...

  origin_domain_name     = "<MY_BUCKET_NAME>.s3.us-west-2.amazonaws.com"
  origin_protocol_policy = "https-only"
  origin_shield = {
    enabled = true
    region  = "us-west-2"
  }
  origin_access_control_id = aws_cloudfront_origin_access_control.s3.id

  # ...
}

│ Error: updating CloudFront Distribution (XXXXXXXXXXXXXX): operation error CloudFront: UpdateDistribution, https response error StatusCode: 400, RequestID: yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy, IllegalOriginAccessConfiguration: Illegal configuration: The origin type and OAC origin type differ.

│   with module.myapp.module.cdn.aws_cloudfront_distribution.default[0],
│   on .terraform/modules/myapp.cdn/main.tf line 45, in resource "aws_cloudfront_distribution" "default":
│   45: resource "aws_cloudfront_distribution" "default" {

That's because OAC works only when the origin block doesn't reference the custom_origin_config sub-block inside.

All in all, currently S3 origin silently implies public access to the bucket, which would be an eyebrow-raising requirement.

At first glance, cloudposse/cloudfront-s3-cdn/aws may seem to be a viable alternative (it supports pre-existing S3 buckets), but it's not going to work - behind the scenes it assumes that both the CloudFront distribution and the bucket belong to the same AWS account (which is totally fine, that's just a different use case).

Aside from the above, this PR includes the following improvements:

  • OAC makes sense only for S3 origins, therefore its value should be zeroed if that's not the case
  • OAI support (both built-in OAI and external one can be used, see examples)
  • user can choose between OAI and OAC (when both are specified, OAC takes precedence)
  • origin shield can now be configured for any non-default origin
  • fixes deprecated map() references

references

The module is meant to be used with custom origins, but it may happen
that your origin of choice is an S3 bucket that's not managed by
yourself. `cloudposse/cloudfront-s3-cdn/aws` may seem to be a viable
alternative (it supports pre-existing buckets), but there's an implicit
assumption there - both the origin bucket and the CloudFront
distribution that points to it should be deployed to the same AWS
account. In order to secure CDN-to-S3 communication one may want to
specify either OAI or OAC. Prior to this change, it was not possible to
use OAI when S3 bucket domain name was used.
When user specifies an S3 domain name as the origin and attaches OAC to
it, Terraform fails with the following error:

Illegal configuration: The origin type and OAC origin type differ.
At the moment origin shield can be configured only for the default
origin. This commit enables the feature for all the remaining ones.
`map()` function is no longer available
When cache policy ID is specified, all TTL arguments should be zeroed,
as the policy-scoped TTLs take precedence. If non-zero `min_ttl`,
`default_ttl` or `max_ttl` is set to non-0 value and at the same time
cache policy is specified it leads to phantom changes in the plan:

default_ttl                = 0 -> 60
@mergify mergify bot added the triage Needs triage label Mar 25, 2025
This reverts commit 30ff7b9.

This should be moved to a separate PR to narrow down the scope just to
origin-related changes
@jwadolowski jwadolowski changed the title feat: Add better CDN origin controls feat: Improve CDN origin control Mar 31, 2025
@jwadolowski jwadolowski marked this pull request as ready for review March 31, 2025 21:22
@jwadolowski jwadolowski requested review from a team as code owners March 31, 2025 21:22
@mihaiplesa
Copy link
Contributor

@johncblandii @jamengual can someone start the tests please? Thanks.

@jamengual
Copy link

/terratest

@mihaiplesa
Copy link
Contributor

Looks like tests passed.

@milldr milldr removed the triage Needs triage label Apr 4, 2025
@milldr milldr added the minor New features that do not break anything label Apr 4, 2025
@milldr
Copy link
Member

milldr commented Apr 4, 2025

/terratest

@milldr milldr merged commit 7f05884 into cloudposse:main Apr 4, 2025
17 checks passed
Copy link

github-actions bot commented Apr 4, 2025

These changes were released in v1.3.0.

jwadolowski added a commit to jwadolowski/terraform-aws-cloudfront-s3-cdn that referenced this pull request May 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
minor New features that do not break anything
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants