Open mewa opened 8 months ago
Voting for Prioritization
Volunteering to Work on This Issue
Hey @mewa 👋 Thank you for taking the time to raise this, and for the great reproduction information! That was super helpful in letting me reproduce this and try to wrap my head around it.
I believe that this is the result of a Terraform Core behavior paired with an unfortunate AWS API limitation, but I'd like to leave this issue open so that someone from the team or community can take another look before I remove the bug label. The main clue to that being these lines from the plan output in step 8:
# tls_self_signed_cert.this (deposed object 8843fec5) will be destroyed
# (left over from a partially-failed replacement of this instance)
From the Terraform Glossary's definition of deposed
:
... Terraform expected to replace the existing resource by creating a new resource, then destroying the existing resource, but an error occurred in the apply before the destruction. Existing references to the resource refer to the new resource. Terraform will destroy the deposed resource on the next apply. This only can occur in resource configurations that have the lifecycle configuration block create_before_destroy argument set to true.
While tls_self_signed_cert.this
doesn't explicitly have create_before_destroy
set, aws_acm_certificate.this
does. Since aws_acm_certificate.this
is implicitly dependent on tls_self_signed_cert.this
, tls_self_signed_cert.this
inherits the create_before_destroy
configuration.
In step 7's logs, the new instance of tls_self_signed_cert.this
was successfully created, but the apply failed during the modification of aws_acm_certificate.this
-- before the previous instance of tls_self_signed_cert.this
could be destroyed. This led to the deposed instance seen in the logs in step 8.
As mentioned in the documentation linked above, any references to a resource using create_before_destroy
are updated immediately after the new resource is created. With that in mind, any interpolations of tls_self_signed_cert.this
's attributes are updated in the state despite the modification's failure (pivotally, aws_acm_certificate.this.certificate_body
). The AWS API used to manage this resource doesn't return the certificate body, which means that the difference between state and reality for that particular attribute is not detected on subsequent runs.
The difference in behavior as far as the aws_acm_certificate
outputs go is due to the not_after
attribute being Computed
. Those types of attributes are always read from the resource directly, leading to a difference in the not_after
outputs if you inspect the state.
@justinretzolk, thanks for you analysis. But I experienced the same issue in a different scenario, which leads me to the conclusion that deposed
resources are not the root cause of this issue.
I was trying to update an existing aws_acm_certificate
without create_before_destroy
resource "aws_acm_certificate" "xxx" {
certificate_body = file("cert.pem")
certificate_chain = file("chain.pem")
private_key = file("key.pem")
}
# aws_acm_certificate.xxx will be updated in-place
~ resource "aws_acm_certificate" "xxx" {
~ certificate_body = (sensitive value)
id = "arn:aws:acm:eu-central-1:xxx:certificate/xxx"
~ private_key = (sensitive value)
tags = {}
# (16 unchanged attributes hidden)
# (1 unchanged block hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
but didn't have permission to, which resulted in an
Error: importing ACM Certificate (arn:aws:acm:eu-central-1:xxx:certificate/xxx): operation error ACM: ImportCertificate, https response error StatusCode: 400, RequestID: xxx, api error AccessDeniedException: User: arn:aws:sts::xxx:assumed-role/xxx/aws-go-sdk-xxx is not authorized to perform: acm:ImportCertificate on resource: arn:aws:acm:eu-central-1:xxx:certificate/xxx with an explicit deny in a service control policy
So I changed my IAM role and tried to apply again, which gave me
No changes. Your infrastructure matches the configuration.
I compared the state (versioned in S3) and I can confirm, that the first apply updated the certificate_body
and private_key
in state without any other resource involved.
Terraform Core Version
1.6.5
AWS Provider Version
3.76.0,5.31.0
Affected Resource(s)
aws_acm_certificate
Expected Behavior
ACM state is not updated if it fails to update.
Actual Behavior
ACM
certificate_body
is updated to value rejected by AWS during update.Relevant Error/Panic Output Snippet
Terraform Configuration Files
Steps to Reproduce
terraform apply
Terraform will perform the following actions:
aws_acm_certificate.this will be created
resource "aws_acm_certificate" "this" {
tls_private_key.this will be created
resource "tls_private_key" "this" {
tls_self_signed_cert.this will be created
resource "tls_self_signed_cert" "this" {
allowed_uses = [
cert_pem = (known after apply)
early_renewal_hours = 12
id = (known after apply)
is_ca_certificate = true
key_algorithm = (known after apply)
private_key_pem = (sensitive value)
ready_for_renewal = false
set_authority_key_id = false
set_subject_key_id = false
validity_end_time = (known after apply)
validity_period_hours = 72
validity_start_time = (known after apply)
subject {
Plan: 3 to add, 0 to change, 0 to destroy.
Changes to Outputs:
tls_private_key.this: Creating... tls_private_key.this: Creation complete after 0s [id=541a7bea42183808e07377d0374f88f996357825] tls_self_signed_cert.this: Creating... tls_self_signed_cert.this: Creation complete after 0s [id=267788273987092730818475432989880164488] aws_acm_certificate.this: Creating... aws_acm_certificate.this: Creation complete after 1s [id=arn:aws:acm:::certificate/]
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
Outputs:
acm_certificate = { "cert_hash" = "b2f4057d0212c2e8c359120b37e3966b" "not_after" = "2023-12-21T15:31:07Z" } local_certificate = { "cert_hash" = "b2f4057d0212c2e8c359120b37e3966b" "not_after" = "2023-12-21T16:31:07+01:00" }
tls_private_key.this: Refreshing state... [id=541a7bea42183808e07377d0374f88f996357825] tls_self_signed_cert.this: Refreshing state... [id=267788273987092730818475432989880164488] aws_acm_certificate.this: Refreshing state... [id=arn:aws:acm:::certificate/]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: ~ update in-place +/- create replacement and then destroy
Terraform will perform the following actions:
aws_acm_certificate.this will be updated in-place
~ resource "aws_acm_certificate" "this" { ~ certificate_body = <<-EOT -----BEGIN CERTIFICATE----- MIIDIzCCAgugAwIBAgIRAMl2JUOZuV8nvKdLkVIXIIgwDQYJKoZIhvcNAQELBQAw KzETMBEGA1UEChMKQnVnZ3kgSW5jLjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcN MjMxMjE4MTUzMTA3WhcNMjMxMjIxMTUzMTA3WjArMRMwEQYDVQQKEwpCdWdneSBJ bmMuMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBAKYbVd5YZQI6PWGoT8ePSnzIKKnPlQj0fnd+ULDZs6ccLw3iylTh f18t42J3ijLwJTBNJGwHOIguXoQZoFWx6MzsTdiCQs2l1EQrUX7q/t7Ya2Rcw4iR 9gWFCOM/JOc2tSvJSO6rZMJGIWMftoKbWgWXgZanGdPS2buD5PBXzVuNjppV2O5T Zve2iSbvjSCRgZQpMxYoMsd3iXihnq9T8ouviVpmFBKdkCdQlpgAbkrmbKvaZVrX BIkDogtYIC2SKIS+VU4st3P9VcPOLeyHAtpoV9czovLdi0JL9XHqcMQQojTuoQqb XxyxWObXX1+CWylU5rOvhpG1dMZ1bnj8ArsCAwEAAaNCMEAwDgYDVR0PAQH/BAQD AgKEMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFOMYwN/tyJBC2kmMeA+NY6LD 5Mk7MA0GCSqGSIb3DQEBCwUAA4IBAQCdEPaul34YOgRCU6VaVPzJR2Rp+1Jr5/Zg tzVWCoN/X8TpxzxL+luLgY9HA/RAfD2312eGqPxbnviAHsDyvGYCgrucAuWtcp8+ F82fJqRacODghuRgPA6yAhVo052263x045Ax3/K574MuG63CZajHhf9vtBwfoLmN X0nRpweRlPS2RaYKjRvz+hRKZUl3eF9lXwsyk5szZrfafwoLGTIbfp9WD9GlKPAv yIangdLm60IXf0dFcRV2CCDCfwavaOogrojF7rPo8L32GALmDOlNLfumZvcvPgWG XgIDJr7YaDNPmGwfWvrfrKYMzHInNyLFHPLeW5YApqkydn6Bq3Hl -----END CERTIFICATE----- EOT -> (known after apply) id = "arn:aws:acm:::certificate/"
tags = {}
(16 unchanged attributes hidden)
tls_self_signed_cert.this must be replaced
+/- resource "tls_self_signed_cert" "this" { ~ allowed_uses = [ # forces replacement "cert_signing",
"digital_signature", ] ~ cert_pem = <<-EOT -----BEGIN CERTIFICATE----- MIIDIzCCAgugAwIBAgIRAMl2JUOZuV8nvKdLkVIXIIgwDQYJKoZIhvcNAQELBQAw KzETMBEGA1UEChMKQnVnZ3kgSW5jLjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcN MjMxMjE4MTUzMTA3WhcNMjMxMjIxMTUzMTA3WjArMRMwEQYDVQQKEwpCdWdneSBJ bmMuMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBAKYbVd5YZQI6PWGoT8ePSnzIKKnPlQj0fnd+ULDZs6ccLw3iylTh f18t42J3ijLwJTBNJGwHOIguXoQZoFWx6MzsTdiCQs2l1EQrUX7q/t7Ya2Rcw4iR 9gWFCOM/JOc2tSvJSO6rZMJGIWMftoKbWgWXgZanGdPS2buD5PBXzVuNjppV2O5T Zve2iSbvjSCRgZQpMxYoMsd3iXihnq9T8ouviVpmFBKdkCdQlpgAbkrmbKvaZVrX BIkDogtYIC2SKIS+VU4st3P9VcPOLeyHAtpoV9czovLdi0JL9XHqcMQQojTuoQqb XxyxWObXX1+CWylU5rOvhpG1dMZ1bnj8ArsCAwEAAaNCMEAwDgYDVR0PAQH/BAQD AgKEMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFOMYwN/tyJBC2kmMeA+NY6LD 5Mk7MA0GCSqGSIb3DQEBCwUAA4IBAQCdEPaul34YOgRCU6VaVPzJR2Rp+1Jr5/Zg tzVWCoN/X8TpxzxL+luLgY9HA/RAfD2312eGqPxbnviAHsDyvGYCgrucAuWtcp8+ F82fJqRacODghuRgPA6yAhVo052263x045Ax3/K574MuG63CZajHhf9vtBwfoLmN X0nRpweRlPS2RaYKjRvz+hRKZUl3eF9lXwsyk5szZrfafwoLGTIbfp9WD9GlKPAv yIangdLm60IXf0dFcRV2CCDCfwavaOogrojF7rPo8L32GALmDOlNLfumZvcvPgWG XgIDJr7YaDNPmGwfWvrfrKYMzHInNyLFHPLeW5YApqkydn6Bq3Hl -----END CERTIFICATE----- EOT -> (known after apply) ~ id = "267788273987092730818475432989880164488" -> (known after apply) ~ key_algorithm = "RSA" -> (known after apply) ~ validity_end_time = "2023-12-21T16:31:07.844628651+01:00" -> (known after apply) ~ validity_start_time = "2023-12-18T16:31:07.844628651+01:00" -> (known after apply)
(7 unchanged attributes hidden)
}
Plan: 1 to add, 1 to change, 1 to destroy.
Changes to Outputs: ~ acm_certificate = { ~ cert_hash = "b2f4057d0212c2e8c359120b37e3966b" -> (known after apply)
(1 unchanged attribute hidden)
~ local_certificate = { ~ cert_hash = "b2f4057d0212c2e8c359120b37e3966b" -> (known after apply) ~ not_after = "2023-12-21T16:31:07+01:00" -> (known after apply) }
tls_self_signed_cert.this: Creating... tls_self_signed_cert.this: Creation complete after 0s [id=302349904251140011571768920538688197264] aws_acm_certificate.this: Modifying... [id=arn:aws:acm:::certificate/]
╷
│ Error: importing ACM Certificate (arn:aws:acm:::certificate/): operation error ACM: ImportCertificate, https response error StatusCode: 400, RequestID: da4af74b-a878-42dd-83b0-ee0ed5f13795, api error ValidationException: New certificate is missing one or more Key Usages supported by the currently imported certificate
│
│ with aws_acm_certificate.this,
│ on main.tf line 28, in resource "aws_acm_certificate" "this":
│ 28: resource "aws_acm_certificate" "this" {
│
tls_private_key.this: Refreshing state... [id=541a7bea42183808e07377d0374f88f996357825] tls_self_signed_cert.this (deposed object 8843fec5): Refreshing state... [id=267788273987092730818475432989880164488] tls_self_signed_cert.this: Refreshing state... [id=302349904251140011571768920538688197264] aws_acm_certificate.this: Refreshing state... [id=arn:aws:acm:::certificate/]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
Terraform will perform the following actions:
tls_self_signed_cert.this (deposed object 8843fec5) will be destroyed
(left over from a partially-failed replacement of this instance)
resource "tls_self_signed_cert" "this" {
allowed_uses = [
cert_pem = <<-EOT -----BEGIN CERTIFICATE----- MIIDIzCCAgugAwIBAgIRAMl2JUOZuV8nvKdLkVIXIIgwDQYJKoZIhvcNAQELBQAw KzETMBEGA1UEChMKQnVnZ3kgSW5jLjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcN MjMxMjE4MTUzMTA3WhcNMjMxMjIxMTUzMTA3WjArMRMwEQYDVQQKEwpCdWdneSBJ bmMuMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBAKYbVd5YZQI6PWGoT8ePSnzIKKnPlQj0fnd+ULDZs6ccLw3iylTh f18t42J3ijLwJTBNJGwHOIguXoQZoFWx6MzsTdiCQs2l1EQrUX7q/t7Ya2Rcw4iR 9gWFCOM/JOc2tSvJSO6rZMJGIWMftoKbWgWXgZanGdPS2buD5PBXzVuNjppV2O5T Zve2iSbvjSCRgZQpMxYoMsd3iXihnq9T8ouviVpmFBKdkCdQlpgAbkrmbKvaZVrX BIkDogtYIC2SKIS+VU4st3P9VcPOLeyHAtpoV9czovLdi0JL9XHqcMQQojTuoQqb XxyxWObXX1+CWylU5rOvhpG1dMZ1bnj8ArsCAwEAAaNCMEAwDgYDVR0PAQH/BAQD AgKEMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFOMYwN/tyJBC2kmMeA+NY6LD 5Mk7MA0GCSqGSIb3DQEBCwUAA4IBAQCdEPaul34YOgRCU6VaVPzJR2Rp+1Jr5/Zg tzVWCoN/X8TpxzxL+luLgY9HA/RAfD2312eGqPxbnviAHsDyvGYCgrucAuWtcp8+ F82fJqRacODghuRgPA6yAhVo052263x045Ax3/K574MuG63CZajHhf9vtBwfoLmN X0nRpweRlPS2RaYKjRvz+hRKZUl3eF9lXwsyk5szZrfafwoLGTIbfp9WD9GlKPAv yIangdLm60IXf0dFcRV2CCDCfwavaOogrojF7rPo8L32GALmDOlNLfumZvcvPgWG XgIDJr7YaDNPmGwfWvrfrKYMzHInNyLFHPLeW5YApqkydn6Bq3Hl -----END CERTIFICATE----- EOT -> null
early_renewal_hours = 12 -> null
id = "267788273987092730818475432989880164488" -> null
is_ca_certificate = true -> null
key_algorithm = "RSA" -> null
private_key_pem = (sensitive value) -> null
ready_for_renewal = false -> null
set_authority_key_id = false -> null
set_subject_key_id = false -> null
validity_end_time = "2023-12-21T16:31:07.844628651+01:00" -> null
validity_period_hours = 72 -> null
validity_start_time = "2023-12-18T16:31:07.844628651+01:00" -> null
subject {
Plan: 0 to add, 0 to change, 1 to destroy.
Changes to Outputs: ~ acm_certificate = { ~ cert_hash = "b2f4057d0212c2e8c359120b37e3966b" -> "7ecaca8b9c044c727cb4244946f20d94"
(1 unchanged attribute hidden)
tls_self_signed_cert.this (deposed object 8843fec5): Destroying... [id=267788273987092730818475432989880164488] tls_self_signed_cert.this: Destruction complete after 0s
Apply complete! Resources: 0 added, 0 changed, 1 destroyed.
Outputs:
acm_certificate = { "cert_hash" = "7ecaca8b9c044c727cb4244946f20d94" "not_after" = "2023-12-21T15:31:07Z" } local_certificate = { "cert_hash" = "7ecaca8b9c044c727cb4244946f20d94" "not_after" = "2023-12-21T16:31:37+01:00" }