hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.71k stars 9.07k forks source link

[Bug]: (also doc issue) importing cloudfront response header policy includes etag which is undocumented as an argument and causes apply failures #38244

Open automaticgiant opened 1 month ago

automaticgiant commented 1 month ago

Terraform Core Version

1.4.6

AWS Provider Version

5.56.1

Affected Resource(s)

resource cloudfront_response_headers_policy

Expected Behavior

one or more of the following:

Actual Behavior

generated config with etag argument

two applies of header changes after the import worked fine

the third could not apply

(plan listed an etag change)

Relevant Error/Panic Output Snippet

ā”‚ Error: updating CloudFront Response Headers Policy (edb1ee71-912d-4571-af09-1954a5cb5db0): operation error CloudFront: UpdateResponseHeadersPolicy, https response error StatusCode: 412, RequestID: 73a27780-3429-4e55-9a94-745ef688344e, PreconditionFailed: The request failed because it didn't meet the preconditions for this operation.

Terraform Configuration Files

resource "aws_cloudfront_response_headers_policy" "policy" {
  count = var.APP_IAC_STAGE == "prod" ? 1 : 0
  etag    = "E13Q6A55DBZB7M"
  name    = "REDACTED"
  custom_headers_config {
    items {
      header   = "Permissions-Policy"
      override = true
      value    = "REDACTED"
    }
  }
  security_headers_config {
    content_security_policy {
      content_security_policy = "REDACTED"
      override                = true
    }
    content_type_options {
      override = true
    }
    frame_options {
      frame_option = "SAMEORIGIN"
      override     = true
    }
    referrer_policy {
      override        = true
      referrer_policy = "strict-origin"
    }
    strict_transport_security {
      access_control_max_age_sec = 31536000
      include_subdomains         = true
      override                   = true
      preload                    = false
    }
  }
}

Steps to Reproduce

presumably, generate config with import from an existing resource (with etag), then apply changes until failure (unclear why the first two changes were ok)

Debug Output

fixed before debug logging was enabled by removing etag argument from config

Panic Output

No response

Important Factoids

No response

References

No response

Would you like to implement a fix?

None

github-actions[bot] commented 1 month ago

Community Note

Voting for Prioritization

Volunteering to Work on This Issue

acwwat commented 1 month ago

I've looked into the specifications in more details. While I couldn't find any information in the Amazon CloudFront API documentation, I was able to find a bit more information in AWS API Changes. It seems that eTag refers to the current version of the response headers policy, which is generated by AWS (probably) on creation and update.

Where ETag is used is in the optional IfMatch argument in the request payload of the UpdateResponseHeadersPolicy and DeleteResponseHeaderPolicy calls to specify a specific ETag (i.e. version) of the target response headers policy. The resource indeed sets the IfMatch param for these calls. This value would always be the most updated since both operations does a state refresh before the operation.

However, I don't see any references of ETag at all in the AWS Management Console and there's no concept of versioning that is documented AFAIK. Thus I assume that ETag is mostly for internal state management by AWS, and to end-users we can assume that the latest response headers policy. as referred to by the id, is used.

Given the above information, my proposal would be to simply set etag to Computed so that it becomes a read-only attribute.