Skip to content

Commit ffe5013

Browse files
committed
Add cross-account VPC origin support to CloudFront distribution
Fixes #45011 AWS released cross-account VPC Origins for CloudFront on November 7, 2025. The CloudFront API requires the OwnerAccountId field when referencing a VPC origin from a different account. Without this parameter, Terraform returns 404 EntityNotFound even when the VPC origin is properly shared via RAM. Changes: - Add owner_account_id field to vpc_origin_config schema (Optional, Computed) - Update expandVPCOriginConfig to include OwnerAccountId when provided - Update flattenVPCOriginConfig to read OwnerAccountId from API response - Add acceptance test TestAccCloudFrontDistribution_vpcOriginConfigOwnerAccountID - Update documentation Backward compatible: When owner_account_id is omitted, CloudFront uses the distribution's account.
1 parent cbb7100 commit ffe5013

File tree

4 files changed

+114
-2
lines changed

4 files changed

+114
-2
lines changed

.changelog/45011.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
```release-note:enhancement
2+
resource/aws_cloudfront_distribution: Add `owner_account_id` argument to `vpc_origin_config` for cross-account VPC origin support
3+
```
4+

internal/service/cloudfront/distribution.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,11 @@ func resourceDistribution() *schema.Resource {
739739
Default: 30,
740740
ValidateFunc: validation.IntAtLeast(1),
741741
},
742+
names.AttrOwnerAccountID: {
743+
Type: schema.TypeString,
744+
Optional: true,
745+
Computed: true,
746+
},
742747
"vpc_origin_id": {
743748
Type: schema.TypeString,
744749
Required: true,
@@ -2530,11 +2535,17 @@ func expandVPCOriginConfig(tfMap map[string]any) *awstypes.VpcOriginConfig {
25302535
return nil
25312536
}
25322537

2533-
return &awstypes.VpcOriginConfig{
2538+
apiObject := &awstypes.VpcOriginConfig{
25342539
OriginKeepaliveTimeout: aws.Int32(int32(tfMap["origin_keepalive_timeout"].(int))),
25352540
OriginReadTimeout: aws.Int32(int32(tfMap["origin_read_timeout"].(int))),
25362541
VpcOriginId: aws.String(tfMap["vpc_origin_id"].(string)),
25372542
}
2543+
2544+
if v, ok := tfMap[names.AttrOwnerAccountID].(string); ok && v != "" {
2545+
apiObject.OwnerAccountId = aws.String(v)
2546+
}
2547+
2548+
return apiObject
25382549
}
25392550

25402551
func flattenOriginShield(apiObject *awstypes.OriginShield) map[string]any {
@@ -2563,11 +2574,17 @@ func flattenVPCOriginConfig(apiObject *awstypes.VpcOriginConfig) map[string]any
25632574
return nil
25642575
}
25652576

2566-
return map[string]any{
2577+
tfMap := map[string]any{
25672578
"origin_keepalive_timeout": aws.ToInt32(apiObject.OriginKeepaliveTimeout),
25682579
"origin_read_timeout": aws.ToInt32(apiObject.OriginReadTimeout),
25692580
"vpc_origin_id": aws.ToString(apiObject.VpcOriginId),
25702581
}
2582+
2583+
if apiObject.OwnerAccountId != nil {
2584+
tfMap[names.AttrOwnerAccountID] = aws.ToString(apiObject.OwnerAccountId)
2585+
}
2586+
2587+
return tfMap
25712588
}
25722589

25732590
func expandCustomErrorResponses(tfList []any) *awstypes.CustomErrorResponses {

internal/service/cloudfront/distribution_test.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,6 +1591,50 @@ func TestAccCloudFrontDistribution_vpcOriginConfig(t *testing.T) {
15911591
})
15921592
}
15931593

1594+
func TestAccCloudFrontDistribution_vpcOriginConfigOwnerAccountID(t *testing.T) {
1595+
ctx := acctest.Context(t)
1596+
var distribution awstypes.Distribution
1597+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
1598+
resourceName := "aws_cloudfront_distribution.test"
1599+
1600+
resource.ParallelTest(t, resource.TestCase{
1601+
PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, names.CloudFrontEndpointID) },
1602+
ErrorCheck: acctest.ErrorCheck(t, names.CloudFrontServiceID),
1603+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
1604+
CheckDestroy: testAccCheckDistributionDestroy(ctx),
1605+
Steps: []resource.TestStep{
1606+
{
1607+
Config: testAccDistributionConfig_vpcOriginConfigOwnerAccountID(rName),
1608+
Check: resource.ComposeTestCheckFunc(
1609+
testAccCheckDistributionExists(ctx, resourceName, &distribution),
1610+
resource.TestCheckResourceAttr(resourceName, "origin.#", "1"),
1611+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "origin.*", map[string]string{
1612+
"custom_header.#": "0",
1613+
"custom_origin_config.#": "0",
1614+
names.AttrDomainName: "www.example.com",
1615+
"origin_id": "test",
1616+
"origin_shield.#": "0",
1617+
"s3_origin_config.#": "0",
1618+
"vpc_origin_config.#": "1",
1619+
"vpc_origin_config.0.origin_keepalive_timeout": "5",
1620+
"vpc_origin_config.0.origin_read_timeout": "30",
1621+
}),
1622+
resource.TestCheckResourceAttrSet(resourceName, fmt.Sprintf("vpc_origin_config.0.%s", names.AttrOwnerAccountID)),
1623+
),
1624+
},
1625+
{
1626+
ResourceName: resourceName,
1627+
ImportState: true,
1628+
ImportStateVerify: true,
1629+
ImportStateVerifyIgnore: []string{
1630+
"retain_on_delete",
1631+
"wait_for_deployment",
1632+
},
1633+
},
1634+
},
1635+
})
1636+
}
1637+
15941638
func TestAccCloudFrontDistribution_responseCompletionTimeout(t *testing.T) {
15951639
ctx := acctest.Context(t)
15961640
var distribution awstypes.Distribution
@@ -4883,6 +4927,52 @@ resource "aws_cloudfront_distribution" "test" {
48834927
`)
48844928
}
48854929

4930+
func testAccDistributionConfig_vpcOriginConfigOwnerAccountID(rName string) string {
4931+
return acctest.ConfigCompose(testAccVPCOriginConfig_basic(rName), `
4932+
data "aws_caller_identity" "current" {}
4933+
4934+
resource "aws_cloudfront_distribution" "test" {
4935+
enabled = false
4936+
retain_on_delete = false
4937+
4938+
default_cache_behavior {
4939+
allowed_methods = ["GET", "HEAD"]
4940+
cached_methods = ["GET", "HEAD"]
4941+
target_origin_id = "test"
4942+
viewer_protocol_policy = "allow-all"
4943+
4944+
forwarded_values {
4945+
query_string = false
4946+
4947+
cookies {
4948+
forward = "all"
4949+
}
4950+
}
4951+
}
4952+
4953+
origin {
4954+
domain_name = "www.example.com"
4955+
origin_id = "test"
4956+
4957+
vpc_origin_config {
4958+
vpc_origin_id = aws_cloudfront_vpc_origin.test.id
4959+
owner_account_id = data.aws_caller_identity.current.account_id
4960+
}
4961+
}
4962+
4963+
restrictions {
4964+
geo_restriction {
4965+
restriction_type = "none"
4966+
}
4967+
}
4968+
4969+
viewer_certificate {
4970+
cloudfront_default_certificate = true
4971+
}
4972+
}
4973+
`)
4974+
}
4975+
48864976
func testAccDistributionConfig_responseCompletionTimeout(enabled, retainOnDelete bool, responseCompletionTimeout int) string {
48874977
return fmt.Sprintf(`
48884978
resource "aws_cloudfront_distribution" "test" {

website/docs/r/cloudfront_distribution.html.markdown

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,7 @@ argument should not be specified.
568568

569569
* `origin_keepalive_timeout` - (Optional) Specifies how long, in seconds, CloudFront persists its connection to the origin. The minimum timeout is 1 second, the maximum is 60 seconds. Defaults to `5`.
570570
* `origin_read_timeout` - (Optional) Specifies how long, in seconds, CloudFront waits for a response from the origin. This is also known as the _origin response timeout_. The minimum timeout is 1 second, the maximum is 60 seconds. Defaults to `30`.
571+
* `owner_account_id` - (Optional) The AWS account ID that owns the VPC origin. Required when referencing a VPC origin from a different AWS account for cross-account VPC origin access.
571572
* `vpc_origin_id` (Required) - The VPC origin ID.
572573

573574
#### Origin Group Arguments

0 commit comments

Comments
 (0)