diff --git a/.changelog/26510.txt b/.changelog/26510.txt new file mode 100644 index 00000000000..f30cec313e4 --- /dev/null +++ b/.changelog/26510.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_cloudfront_distribution: Add `origin_access_control_id` to the `origin` configuration block +``` diff --git a/internal/service/cloudfront/distribution.go b/internal/service/cloudfront/distribution.go index 18d52af5f66..674e6665d0c 100644 --- a/internal/service/cloudfront/distribution.go +++ b/internal/service/cloudfront/distribution.go @@ -588,6 +588,11 @@ func ResourceDistribution() *schema.Resource { }, }, }, + "origin_access_control_id": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.NoZeroValues, + }, "origin_id": { Type: schema.TypeString, Required: true, diff --git a/internal/service/cloudfront/distribution_configuration_structure.go b/internal/service/cloudfront/distribution_configuration_structure.go index a65379742bf..bc7e6e327a4 100644 --- a/internal/service/cloudfront/distribution_configuration_structure.go +++ b/internal/service/cloudfront/distribution_configuration_structure.go @@ -720,6 +720,9 @@ func ExpandOrigin(m map[string]interface{}) *cloudfront.Origin { origin.CustomOriginConfig = ExpandCustomOriginConfig(s[0].(map[string]interface{})) } } + if v, ok := m["origin_access_control_id"]; ok { + origin.OriginAccessControlId = aws.String(v.(string)) + } if v, ok := m["origin_path"]; ok { origin.OriginPath = aws.String(v.(string)) } @@ -763,6 +766,9 @@ func FlattenOrigin(or *cloudfront.Origin) map[string]interface{} { if or.CustomOriginConfig != nil { m["custom_origin_config"] = []interface{}{FlattenCustomOriginConfig(or.CustomOriginConfig)} } + if or.OriginAccessControlId != nil { + m["origin_access_control_id"] = aws.StringValue(or.OriginAccessControlId) + } if or.OriginPath != nil { m["origin_path"] = aws.StringValue(or.OriginPath) } @@ -894,6 +900,11 @@ func OriginHash(v interface{}) int { buf.WriteString(fmt.Sprintf("%d-", customOriginConfigHash((s[0].(map[string]interface{}))))) } } + + if v, ok := m["origin_access_control_id"]; ok { + buf.WriteString(fmt.Sprintf("%s-", v.(string))) + } + if v, ok := m["origin_path"]; ok { buf.WriteString(fmt.Sprintf("%s-", v.(string))) } diff --git a/internal/service/cloudfront/distribution_test.go b/internal/service/cloudfront/distribution_test.go index 0d81f5f7078..70886fe78eb 100644 --- a/internal/service/cloudfront/distribution_test.go +++ b/internal/service/cloudfront/distribution_test.go @@ -562,6 +562,47 @@ func TestAccCloudFrontDistribution_Origin_originShield(t *testing.T) { }) } +func TestAccCloudFrontDistribution_Origin_originAccessControl(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var distribution cloudfront.Distribution + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t); acctest.PreCheckPartitionHasService(cloudfront.EndpointsID, t) }, + ErrorCheck: acctest.ErrorCheck(t, cloudfront.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDistributionDestroy, + Steps: []resource.TestStep{ + { + Config: testAccDistributionConfig_originAccessControl(rName, 0), + Check: resource.ComposeTestCheckFunc( + testAccCheckDistributionExists("aws_cloudfront_distribution.test", &distribution), + resource.TestCheckResourceAttrPair("aws_cloudfront_distribution.test", "origin.0.origin_access_control_id", "aws_cloudfront_origin_access_control.test.0", "id"), + ), + }, + { + ResourceName: "aws_cloudfront_distribution.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "retain_on_delete", + "wait_for_deployment", + }, + }, + { + Config: testAccDistributionConfig_originAccessControl(rName, 1), + Check: resource.ComposeTestCheckFunc( + testAccCheckDistributionExists("aws_cloudfront_distribution.test", &distribution), + resource.TestCheckResourceAttrPair("aws_cloudfront_distribution.test", "origin.0.origin_access_control_id", "aws_cloudfront_origin_access_control.test.1", "id"), + ), + }, + }, + }) +} + // TestAccCloudFrontDistribution_noOptionalItems runs an // aws_cloudfront_distribution acceptance test with no optional items set. // @@ -4320,3 +4361,75 @@ resource "aws_cloudfront_distribution" "main" { } `, rName, testAccDistributionRetainConfig())) } + +func testAccDistributionConfig_originAccessControl(rName string, which int) string { + return acctest.ConfigCompose( + originBucket(rName), + logBucket(rName), + fmt.Sprintf(` +locals { + rName = %[1]q +} + +resource "aws_cloudfront_origin_access_control" "test" { + count = 2 + + name = "${local.rName}-${count.index}" + origin_access_control_origin_type = "s3" + signing_behavior = "always" + signing_protocol = "sigv4" +} + +resource "aws_cloudfront_distribution" "test" { + origin { + domain_name = aws_s3_bucket.s3_bucket_origin.bucket_regional_domain_name + origin_id = "myS3Origin" + + origin_access_control_id = aws_cloudfront_origin_access_control.test[%[3]d].id + } + + enabled = true + default_root_object = "index.html" + + logging_config { + include_cookies = false + bucket = aws_s3_bucket.s3_bucket_logs.bucket_regional_domain_name + prefix = "myprefix" + } + + default_cache_behavior { + allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"] + cached_methods = ["GET", "HEAD"] + target_origin_id = "myS3Origin" + + forwarded_values { + query_string = false + + cookies { + forward = "none" + } + } + + viewer_protocol_policy = "allow-all" + min_ttl = 0 + default_ttl = 3600 + max_ttl = 86400 + } + + price_class = "PriceClass_200" + + restrictions { + geo_restriction { + restriction_type = "whitelist" + locations = ["US", "CA", "GB", "DE"] + } + } + + viewer_certificate { + cloudfront_default_certificate = true + } + + %[2]s +} +`, rName, testAccDistributionRetainConfig(), which)) +} diff --git a/website/docs/r/cloudfront_distribution.html.markdown b/website/docs/r/cloudfront_distribution.html.markdown index bbaee594f2c..4b8767fdad7 100644 --- a/website/docs/r/cloudfront_distribution.html.markdown +++ b/website/docs/r/cloudfront_distribution.html.markdown @@ -473,6 +473,8 @@ argument should not be specified. `value` parameters that specify header data that will be sent to the origin (multiples allowed). +* `origin_access_control_id` (Optional) - The unique identifier of an origin access control for this origin. + * `origin_id` (Required) - A unique identifier for the origin. * `origin_path` (Optional) - An optional element that causes CloudFront to