terraform
terraform copied to clipboard
Crash on splatting optional object in for_each (...and object is not set)
Terraform Version
Terraform v1.7.3
on darwin_arm64
+ provider registry.terraform.io/hashicorp/azurerm v3.90.0
Terraform Configuration Files
module: main.tf
...
dynamic "registry" {
for_each = var.registry_config[*]
content {
server = registry.server
username = registry.username
password_secret_name = registry.password_secret_name
}
}
...
module: variables.tf
...
variable "registry_config" {
default = null
nullable = true
sensitive = true
type = object({
server = string
username = string
password_secret_name = string
})
}
...
Debug Output
Gist crash - terraform 1.6.3 Gist crash - terraform 1.7.3
Expected Behavior
I would expect an error log saying you cannot splat nullable variables... or variables containing the null value.
Actual Behavior
Terraform crashed asking me to report
Steps to Reproduce
terraform initterraform apply
Additional Context
Ran into this crash when setting up Azure Container App
Hi @maxxiefjv,
You mention that this is Terraform version v1.7.3 but the stack trace shown is from v1.6.3. There was a similar bug fixed in the latest version, can you verify that you still see the crash using v1.7.3?
Hi @maxxiefjv,
You mention that this is Terraform version v1.7.3 but the stack trace shown is from v1.6.3. There was a similar bug fixed in the latest version, can you verify that you still see the crash using v1.7.3?
Hi @jbardin,
Yes, it does still crash for v1.7.3... forgot to update the Gist. In case it might be helpful I also kept the v1.6.3 logs. You can now find the crash for both v1.6.3 and v1.7.3 in my public gists (referenced in the bug description)
Based on the stack trace, I expect this problem is triggered by the input variable being marked as sensitive = true.
It seems that that the splat expression logic is trying to dig into the given value in a way that isn't considering that the value might be sensitive. This panic is there to reduce the risk of some code just accidentally losing track of the "sensitive" mark when evaluating.
Therefore I expect the correct behavior is to first "unmark" the value (separating the value itself from the "sensitive" metadata), perform whatever checks this logic is performing, and then re-apply the same "sensitive" metadata back to the final result.
However, in this particular case fixing this would lead only to another problem: dynamic block for_each does not accept sensitive values, because there isn't any way to avoid disclosing which blocks were generated and therefore to avoid exposing information about the content of the sensitive value.
One way to work around both problems is to tell Terraform that the object as a whole isn't sensitive but that the individual attributes are, and therefore the result of the test for whether the object is null need not be treated as sensitive:
dynamic "registry" {
for_each = nonsensitive(var.registry_config)[*]
content {
server = sensitive(registry.server)
username = sensitive(registry.username)
password_secret_name = sensitive(registry.password_secret_name)
}
}
This structure means that the decision about whether there is a registry block or not is not considered as sensitive information, but the attributes inside are.
Of course this doesn't mean that we shouldn't still fix the crashing bug when sensitive values get used with the [*] operator. That's an upstream bug in hashicorp/hcl, so will need to be fixed there. But I shared the above in the hope that it allows you to get something working with today's Terraform, particularly because us fixing this bug would only have revealed another error message caused by the for_each value being sensitive and therefore this workaround would be needed regardless of the crasher bug.
Thanks @apparentlymart, this helps. I also figured out that I - indeed - wasn't allowed to use sensitive values like this anyway, hence found myself (another) workaround. This one looks a lot cleaner though, so will change it to this example instead.
Thanks for the fast replies and have a nice day!
This is related to #29744, in that they both are missing the sensitive validation, though in different ways. Not sure how [*] is skipping the validation exactly, but both issues will probably be solved by the same validation.