-
Notifications
You must be signed in to change notification settings - Fork 9.6k
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
Warning on Duplicate keys in a map object. #28727
Comments
Thanks for raising this, @techdragon, literally days before we ran into the same issue. Upvoted! I would even go so far as to propose it be an error and not just a warning. Here is a simple demonstration.
The above produces these outputs
Notice the loss of the 1st The same can be demonstrated with input variables as well
With this
Produces
Adding more outputs to the
Even reading from JSON silently drops the duplicate key without error or warning
|
@techdragon , I'm curious what linters you tried. I quickly tried https://github.com/terraform-linters/tflint but it didn't catch the duplicate keys in any of the examples above. |
@myronmeier Thanks for writing out the excellent examples! And yes I had the same issue tflint not catching it, but since the issue goes beyond the maps as written statically in code, I just mentioned the linters in passing as I had tried them as a workaround, but I probably should have been more clear about what I meant. |
@myronmeier I agree, this should be an error. Warning is not sufficient as it's easily missed and this can be very problematic. From what I can tell this can't be caught by variable validation either.
|
@nwsparks I didn't expect validation to fail like that... Also I'm not 100% convinced that it should always be an error. I can imagine there are users out there who may be relying on this to power various workarounds for providing default variable values that may have been inherited from older terraform modules or when needing to pass in configuration and merge defaults with more complex map related values. While it might be good to make this an error in time, I'd rather have the warning added now, with perhaps some way to configure this warning as an error, than navigate the longer path of changing behaviour like this now that Edit: Just found another example of duplicated key names that may become a common pattern in future that could conflict with making duplicate keys an error #25088 has an example where the key is defined multiple times for running different validation checks against its value. |
I struck this today, and it's very dangerous. In terraform.tfvars it will happily let you define a map with the same key multiple times as per the example above and doesn't throw an error, but it discards all but one of the map objects with that key. This can lead to non-recoverable data loss. I tried to add a test to check for duplicate keys, but it seems to discard the data right when it reads it in so there doesn't seems to be any way to test for this inside Terraform. I suggest that Terraform should error if you have multiple occurrences of the same key in a map in terraform.tfvars. |
This one is really bizarre that you can have duplicate keys for objects and maps in terraform as it can be a considerable to debug headache and potentially catastrophic if not careful. Neither Python, Java or Golang accept duplicate keys for maps so TF accepting them is just strange What's even stranger is how very few downvotes this has! I hope it gets addressed soon. |
For anyone interested in workarounds for this, I opened a SO question: |
I managed to solve it by first creating a list of items containing my key-value pair in my map. Then I converted it to a map, the conversion itself will check for duplicates and error out if any exist.
|
This ticket was referenced recently in this blog post which identified a security issue that results from this functionality: https://securitylabs.datadoghq.com/articles/exploring-github-to-aws-keyless-authentication-flaws/ When you create an AWS IAM role in terraform with a trust policy that contains two In AWS, it is not possible to have the two It looks like there is more recent discussion of this problem in #33570, where @apparentlymart stated:
If that is the case, and this will not be fixed in terraform, then should a check for this be added to tflint instead or is there a better place? https://github.com/terraform-linters/tflint I am additionally worried that beyond Github Actions and AWS IAM Roles, that the problem of silently swallowing security restrictions on resources has impact beyond just that use case. |
I can only agree with the last paragraph @scottpiper-wiz after reading both your comment and also the datadog article you linked. I highly doubt that this is limited to GitHub action and AWS IAM Roles. I don’t think this belong in a linter, this should be caught directly in Terraform thus preventing anyone actually deploying this kind of code. Like my own work around in locals. See my previous comment in this thread. |
In tracking down how this could be implemented, my understanding is terraform/internal/lang/functions.go Line 86 in 919e620
This then calls into In But the functionality into golang has not yet been merged. Implementing this could therefore be done by:
|
It's been a long time since I considered this issue and so I honestly don't really remember all of what I was considering when I responded before. My interpretation of the original idea here is that it should be an error or warning if an object constructor expression (which we might also casually call an "object literal") can see that two of the key/value pairs have key expressions that evaluate to equal values. I have a faint memory of originally having implemented it that way in my own codebase "zcl" that later became HCL 2 after HashiCorp hired me, and then having to relax that rule in response to some compatibility problem relative to Terraform v0.11. I don't remember exactly what the deal was with that, though. (Object-constructing Ultimately the handling of object constructor expressions belongs to HCL rather than to Terraform, and so if we are going to change something here I expect it would need to be an HCL change rather than a Terraform change. That presents two challenges which were perhaps what I was reacting to in earlier discussion:
I don't think it's possible to solve this at the application layer inside Terraform -- including via Terraform's built-in functions -- because by the time Terraform is holding the evaluated object result the duplicate attributes have already been discarded. With all of that said then, I think treating this as a "lint"-like check is probably the most viable path given the existing constraints. The third-party At this point I don't think there is any clear path to resolving this issue. We can keep it open to track the concern, but I don't expect anything further to happen here unless someone has a concrete proposal for what to change, how to change it, and in particular how to do it without breaking compatibility promises or impacting other callers of HCL. |
It's difficult to imagine that anyone has intentionally created a map with duplicate keys expecting that earlier entries will be discarded, but I guess anything is possible. This does seem to me as more of a bug or security issue rather than a feature which must be preserved. https://developer.hashicorp.com/terraform/language/v1-compatibility-promises#pragmatic-exceptions the promise does have exceptions that I could see this classifying under. If there is no way to resolve this in 1.x could it not just be targeted as a fix in 2.0, hopefully altering the behavior so that it returns an error? |
Another +1 for this being an error, our team ran into this one today where a later definition overrode permissions from an earlier definition. |
I agree with the sentiment that this issue should be interpreted as a bug rather than a behaviour worth preserving. This issue also emerges when converting JSON to HCL with
This can hardly be desirable behavior, given that the last assignments of Specifically, Terraform can interpret these HCL lists without issue and encode it to JSON:
|
Same story. I think this is a bug as no any other language accept this including terraform vars. for some reason locals in terraform do. How do we escalate this issue? As I see it was open since May 2021 ?
|
Just ran into this where no warning or error was generated for duplicate map keys added by different developers and one entry into the map was hiding values from the true map entry. I am surprised that terraform acts this way and hides this error as map types almost universally across languages and even mathematics has the key value be unique in a singular map |
TF 1.9.2 — just ran into this too and was quite surprised TF doesn't throw error. |
tflint-ruleset-terraform 0.9.0 and above has a rule for duplicate keys in a map. See terraform-linters/tflint-ruleset-terraform#194. But this one doesn't seem to handle .tfvars files |
This seems to have been reverted in v0.9.1 https://github.com/terraform-linters/tflint-ruleset-terraform/releases/tag/v0.9.1 |
As far as I can see, the revert does not handle tfvars files |
Just ran across this problem myself. The duplicate was unintentional and undesirable, and only caught during a review of the resulting plan. I really can't see this as anything other than a bug which needs to be corrected. |
This was very helpful to find a few idiomatic-enough-ways to get by for now. Thank you! |
Current Terraform Version
Use-cases
Avoiding duplicate keys in maps.
Attempted Solutions
Linter scripts and third party tools.
Proposal
Duplicate keys in maps should raise some kind of warning. This would help prevent mistakes when working with larger and more complex maps. In particular dynamic maps and merged maps where the keys may not be visible in the terraform configuration as written, only being populated when terraform is run.
References
N.A.
The text was updated successfully, but these errors were encountered: