Skip to content
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

r/aws_cloudfront_distribution: Support trusted_key_groups argument #18644

Merged
merged 3 commits into from
Apr 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/18644.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_cloudfront_distribution: Add `trusted_key_groups` argument
```
66 changes: 66 additions & 0 deletions aws/cloudfront_distribution_configuration_structure.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,12 @@ func expandCloudFrontDefaultCacheBehavior(m map[string]interface{}) *cloudfront.
dcb.DefaultTTL = aws.Int64(int64(m["default_ttl"].(int)))
}

if v, ok := m["trusted_key_groups"]; ok {
dcb.TrustedKeyGroups = expandTrustedKeyGroups(v.([]interface{}))
} else {
dcb.TrustedKeyGroups = expandTrustedKeyGroups([]interface{}{})
}

if v, ok := m["trusted_signers"]; ok {
dcb.TrustedSigners = expandTrustedSigners(v.([]interface{}))
} else {
Expand Down Expand Up @@ -255,6 +261,12 @@ func expandCacheBehavior(m map[string]interface{}) *cloudfront.CacheBehavior {
cb.DefaultTTL = aws.Int64(int64(m["default_ttl"].(int)))
}

if v, ok := m["trusted_key_groups"]; ok {
cb.TrustedKeyGroups = expandTrustedKeyGroups(v.([]interface{}))
} else {
cb.TrustedKeyGroups = expandTrustedKeyGroups([]interface{}{})
}

if v, ok := m["trusted_signers"]; ok {
cb.TrustedSigners = expandTrustedSigners(v.([]interface{}))
} else {
Expand Down Expand Up @@ -299,6 +311,9 @@ func flattenCloudFrontDefaultCacheBehavior(dcb *cloudfront.DefaultCacheBehavior)
if dcb.ForwardedValues != nil {
m["forwarded_values"] = []interface{}{flattenForwardedValues(dcb.ForwardedValues)}
}
if len(dcb.TrustedKeyGroups.Items) > 0 {
m["trusted_key_groups"] = flattenTrustedKeyGroups(dcb.TrustedKeyGroups)
}
if len(dcb.TrustedSigners.Items) > 0 {
m["trusted_signers"] = flattenTrustedSigners(dcb.TrustedSigners)
}
Expand Down Expand Up @@ -339,6 +354,9 @@ func flattenCacheBehavior(cb *cloudfront.CacheBehavior) map[string]interface{} {
if cb.ForwardedValues != nil {
m["forwarded_values"] = []interface{}{flattenForwardedValues(cb.ForwardedValues)}
}
if len(cb.TrustedKeyGroups.Items) > 0 {
m["trusted_key_groups"] = flattenTrustedKeyGroups(cb.TrustedKeyGroups)
}
if len(cb.TrustedSigners.Items) > 0 {
m["trusted_signers"] = flattenTrustedSigners(cb.TrustedSigners)
}
Expand Down Expand Up @@ -366,6 +384,26 @@ func flattenCacheBehavior(cb *cloudfront.CacheBehavior) map[string]interface{} {
return m
}

func expandTrustedKeyGroups(s []interface{}) *cloudfront.TrustedKeyGroups {
var tkg cloudfront.TrustedKeyGroups
if len(s) > 0 {
tkg.Quantity = aws.Int64(int64(len(s)))
tkg.Items = expandStringList(s)
tkg.Enabled = aws.Bool(true)
} else {
tkg.Quantity = aws.Int64(0)
tkg.Enabled = aws.Bool(false)
}
return &tkg
}

func flattenTrustedKeyGroups(tkg *cloudfront.TrustedKeyGroups) []interface{} {
if tkg.Items != nil {
return flattenStringList(tkg.Items)
}
return []interface{}{}
}

func expandTrustedSigners(s []interface{}) *cloudfront.TrustedSigners {
var ts cloudfront.TrustedSigners
if len(s) > 0 {
Expand Down Expand Up @@ -1133,6 +1171,34 @@ func flattenViewerCertificate(vc *cloudfront.ViewerCertificate) []interface{} {
return []interface{}{m}
}

func flattenCloudfrontActiveTrustedKeyGroups(atkg *cloudfront.ActiveTrustedKeyGroups) []interface{} {
if atkg == nil {
return []interface{}{}
}

m := map[string]interface{}{
"enabled": aws.BoolValue(atkg.Enabled),
"items": flattenCloudfrontKGKeyPairIds(atkg.Items),
}

return []interface{}{m}
}

func flattenCloudfrontKGKeyPairIds(keyPairIds []*cloudfront.KGKeyPairIds) []interface{} {
result := make([]interface{}, 0, len(keyPairIds))

for _, keyPairId := range keyPairIds {
m := map[string]interface{}{
"key_group_id": aws.StringValue(keyPairId.KeyGroupId),
"key_pair_ids": aws.StringValueSlice(keyPairId.KeyPairIds.Items),
}

result = append(result, m)
}

return result
}

func flattenCloudfrontActiveTrustedSigners(ats *cloudfront.ActiveTrustedSigners) []interface{} {
if ats == nil {
return []interface{}{}
Expand Down
43 changes: 43 additions & 0 deletions aws/resource_aws_cloudfront_distribution.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ func resourceAwsCloudFrontDistribution() *schema.Resource {
Type: schema.TypeString,
Required: true,
},
"trusted_key_groups": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"trusted_signers": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -352,6 +357,12 @@ func resourceAwsCloudFrontDistribution() *schema.Resource {
Type: schema.TypeString,
Required: true,
},
"trusted_key_groups": {
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"trusted_signers": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -613,6 +624,35 @@ func resourceAwsCloudFrontDistribution() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"trusted_key_groups": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"enabled": {
Type: schema.TypeBool,
Computed: true,
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"key_group_id": {
Type: schema.TypeString,
Computed: true,
},
"key_pair_ids": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
},
},
},
},
},
// Terraform AWS Provider 3.0 name change:
// enables TF Plugin SDK to ignore pre-existing attribute state
// associated with previous naming i.e. active_trusted_signers
Expand Down Expand Up @@ -765,6 +805,9 @@ func resourceAwsCloudFrontDistributionRead(d *schema.ResourceData, meta interfac
}

// Update other attributes outside of DistributionConfig
if err := d.Set("trusted_key_groups", flattenCloudfrontActiveTrustedKeyGroups(resp.Distribution.ActiveTrustedKeyGroups)); err != nil {
return fmt.Errorf("error setting trusted_key_groups: %w", err)
}
if err := d.Set("trusted_signers", flattenCloudfrontActiveTrustedSigners(resp.Distribution.ActiveTrustedSigners)); err != nil {
return fmt.Errorf("error setting trusted_signers: %w", err)
}
Expand Down
101 changes: 101 additions & 0 deletions aws/resource_aws_cloudfront_distribution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,7 @@ func TestAccAWSCloudFrontDistribution_noOptionalItemsConfig(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "default_cache_behavior.0.min_ttl", "0"),
resource.TestCheckResourceAttr(resourceName, "default_cache_behavior.0.smooth_streaming", "false"),
resource.TestCheckResourceAttr(resourceName, "default_cache_behavior.0.target_origin_id", "myCustomOrigin"),
resource.TestCheckResourceAttr(resourceName, "default_cache_behavior.0.trusted_key_groups.#", "0"),
resource.TestCheckResourceAttr(resourceName, "default_cache_behavior.0.trusted_signers.#", "0"),
resource.TestCheckResourceAttr(resourceName, "default_cache_behavior.0.viewer_protocol_policy", "allow-all"),
resource.TestMatchResourceAttr(resourceName, "domain_name", regexp.MustCompile(`^[a-z0-9]+\.cloudfront\.net$`)),
Expand Down Expand Up @@ -705,6 +706,45 @@ func TestAccAWSCloudFrontDistribution_DefaultCacheBehavior_ForwardedValues_Heade
})
}

func TestAccAWSCloudFrontDistribution_DefaultCacheBehavior_TrustedKeyGroups(t *testing.T) {
var distribution cloudfront.Distribution
resourceName := "aws_cloudfront_distribution.test"

rName := acctest.RandomWithPrefix("tf-acc-test")
retainOnDelete := testAccAWSCloudFrontDistributionRetainOnDeleteFromEnv()

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(cloudfront.EndpointsID, t) },
ErrorCheck: testAccErrorCheck(t, cloudfront.EndpointsID),
Providers: testAccProviders,
CheckDestroy: testAccCheckCloudFrontDistributionDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSCloudFrontDistributionConfigDefaultCacheBehaviorTrustedKeyGroups(retainOnDelete, rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudFrontDistributionExists(resourceName, &distribution),
resource.TestCheckResourceAttr(resourceName, "trusted_key_groups.#", "1"),
resource.TestCheckResourceAttr(resourceName, "trusted_key_groups.0.enabled", "true"),
resource.TestCheckResourceAttr(resourceName, "trusted_key_groups.0.items.#", "1"),
resource.TestCheckResourceAttrSet(resourceName, "trusted_key_groups.0.items.0.key_group_id"),
resource.TestCheckResourceAttr(resourceName, "trusted_key_groups.0.items.0.key_pair_ids.#", "1"),
resource.TestCheckResourceAttr(resourceName, "default_cache_behavior.#", "1"),
resource.TestCheckResourceAttr(resourceName, "default_cache_behavior.0.trusted_key_groups.#", "1"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{
"retain_on_delete",
"wait_for_deployment",
},
},
},
})
}

func TestAccAWSCloudFrontDistribution_DefaultCacheBehavior_TrustedSigners(t *testing.T) {
var distribution cloudfront.Distribution
resourceName := "aws_cloudfront_distribution.test"
Expand Down Expand Up @@ -3035,6 +3075,67 @@ resource "aws_cloudfront_distribution" "test" {
`, retainOnDelete)
}

func testAccAWSCloudFrontDistributionConfigDefaultCacheBehaviorTrustedKeyGroups(retainOnDelete bool, rName string) string {
return fmt.Sprintf(`
resource "aws_cloudfront_distribution" "test" {
# Faster acceptance testing
enabled = false
retain_on_delete = %[1]t
wait_for_deployment = false

default_cache_behavior {
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "test"
trusted_key_groups = [aws_cloudfront_key_group.test.id]
viewer_protocol_policy = "allow-all"

forwarded_values {
query_string = false

cookies {
forward = "all"
}
}
}

origin {
domain_name = "www.example.com"
origin_id = "test"

custom_origin_config {
http_port = 80
https_port = 443
origin_protocol_policy = "https-only"
origin_ssl_protocols = ["TLSv1.2"]
}
}

restrictions {
geo_restriction {
restriction_type = "none"
}
}

viewer_certificate {
cloudfront_default_certificate = true
}
}

resource "aws_cloudfront_public_key" "test" {
comment = "test key"
encoded_key = file("test-fixtures/cloudfront-public-key.pem")
name = %[2]q
}

resource "aws_cloudfront_key_group" "test" {
comment = "test key group"
items = [aws_cloudfront_public_key.test.id]
name = %[2]q
}
`, retainOnDelete, rName)
}

func testAccAWSCloudFrontDistributionConfigDefaultCacheBehaviorTrustedSignersSelf(retainOnDelete bool) string {
return fmt.Sprintf(`
resource "aws_cloudfront_distribution" "test" {
Expand Down
9 changes: 9 additions & 0 deletions website/docs/r/cloudfront_distribution.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,9 @@ of several sub-resources - these resources are laid out below.
CloudFront to route requests to when a request matches the path pattern
either for a cache behavior or for the default cache behavior.

* `trusted_key_groups` (Optional) - A list of key group IDs that CloudFront can use to validate signed URLs or signed cookies.
See the [CloudFront User Guide](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-trusted-signers.html) for more information about this feature.

* `trusted_signers` (Optional) - List of AWS account IDs (or `self`) that you want to allow to create signed URLs for private content.
See the [CloudFront User Guide](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-trusted-signers.html) for more information about this feature.

Expand Down Expand Up @@ -539,6 +542,12 @@ In addition to all arguments above, the following attributes are exported:
distribution's information is fully propagated throughout the Amazon
CloudFront system.

* `trusted_key_groups` - List of nested attributes for active trusted key groups, if the distribution is set up to serve private content with signed URLs
* `enabled` - `true` if any of the key groups have public keys that CloudFront can use to verify the signatures of signed URLs and signed cookies
* `items` - List of nested attributes for each key group
* `key_group_id` - The ID of the key group that contains the public keys
* `key_pair_ids` - Set of CloudFront key pair IDs

* `trusted_signers` - List of nested attributes for active trusted signers, if the distribution is set up to serve private content with signed URLs
* `enabled` - `true` if any of the AWS accounts listed as trusted signers have active CloudFront key pairs
* `items` - List of nested attributes for each trusted signer
Expand Down