-
Notifications
You must be signed in to change notification settings - Fork 72
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
aws_resource_missing_tags
: data source reference in tag value triggers issue instead of being ignored
#510
Comments
Example configuration that reproduces the issue is required to move forward. Avoid including any incidental configuration or dependencies. |
sorry here is an example:
Run with 0.24.0
run with 0.23.0:
|
.tflint conf
|
There are multiple potential causes here. Go ahead and remove the locals {
k = "v"
}
resource "aws_s3_bucket" "bucket" {
tags = {
Local = local.k
}
} There's a good chance this is not the case though, and the root cause here is the data source, in which case a reproduction would be: data "aws_region" "current" {}
resource "aws_s3_bucket" "bucket" {
tags = {
Region = data.aws_region.current.name
}
} In the former case, the local value must be resolved, but the value can still be known through static analysis. In the latter, the expression's value cannot be known until plan time. The rule would have to specifically evaluate the map's keys only, ignoring the unknown map values. While this should be possible, it's tricky and so seems more likely to be the issue here. |
@bendrucker looks like you are spot on. If I set a static value to the local.bucket_name it passes fine with 0.24.x. Not sure what changed in the logic on just checking key names vs not between versions. I will work on fixing locally with a workaround, but it seems you cant use any rendered data source value in the tag value. Even directly like this:
the above passes in 0.23.1 but not 0.24.1 |
Ok great, we can take it from there. @JorgeReus if you're inclined to look at this, I suspect this is caused by a lack of typing when evaluating the tags expression. Before: tflint-ruleset-aws/rules/aws_resource_missing_tags.go Lines 89 to 93 in 18ba742
After: Hard to understand why wanting |
aws_resource_missing_tags
: data source reference in tag value breaks evaluation of all tags
Going to check in a few, seems like you are right on the money @bendrucker |
The test suite passes, I wanted to add a unit test for this case, but I can't put data sources in the test contents. @bendrucker Could you point me on how I can correctly generate the provider locally? |
Found the issue, TL;DR when dynamic sources are involved (data sources, resource attributes) the rule isn't evaluated at all. When doing local test with It gets worse in the default_tags scenario since the rule is evaluated in a resource by resource basis, since the rule won't be ignored and everything will have a missing tag issue, as an example:
With dynamic tags
main.tf
.tflint.hcl
|
Created #511 |
This is not quite correct, you can declare data sources, but you will not be able to reference them. HCL is meant to be consumed through schemas. You don't dynamically decode, you tell the parser up-front about the structure of the document and have the option to either fully decode, erroring on any unknown content, or partially decode, ignoring any content not contained in the schema. TFLint does the latter, because it wants to enforce the things it knows about and ignore the things it doesn't. In the past, TFLint directly depended on Terraform. Terraform which does full decoding, since you wouldn't want new features to silently fail if the config were used on an old Terraform version. That meant TFLint releases were tightly coupled to Terraform releases. Now, TFLint does its own (partial) module decoding. In turn, this means that features that Terraform supports have to be reverse-engineered from their low-level schema. Data sources aren't included at all in the current parser: But that's probably an oversight and should be changed, more to allow rules to inspect data sources than to address a case like this. As you've noted, data sources aren't essential to reproducing this issue, as the difference between a data source, known at plan time, and a resource, known at apply time, is irrelevant here. They both are not statically evaluable and therefore "unknown."
This is not literally true but I'll explain what you're getting at here. In a literal sense, the rule is still evaluated/executed. It just has to choose how to handle unknown values (resource and data source references). This behavior of Particularly:
By passing a callback, you are telling the plugin SDK to ignore unknown value errors and only call your function when the expression can successfully be decoded into your function's argument type. So it's a bug to assume that this callback will be called. If you must evaluate the expression for any following logic to proceed, you generally shouldn't use callbacks. In general, it's best to return early if an error exists since you can't proceed with unknown values. |
aws_resource_missing_tags
: data source reference in tag value breaks evaluation of all tagsaws_resource_missing_tags
: data source reference in tag value triggers issue instead of being ignored
Repeating for clarity based on the notes above. This rule was never capable of checking these tags. It didn't matter if The regression here is that the unknown expression, a map with some unknown values, is mishandled. Previously, the error was properly handled and ignored. Evaluating only the keys would be a new feature, likely requiring SDK-level enhancements. Terraform has to do something similar for |
Thank you very much for the clarification! Would be awesome to support the checking of keys in the future, will dive deep into the core terraform code for it. So, regarding the default tags, would be difficult to know whether the tags are ignored because of the uknown values or that it's and actual violation of the rule. So is there anything you would recommend or we we can proceed with the PR? |
I'll have a look at the PR, but a note on your example, this shouldn't work literally: data "aws_region" "current" {}
resource "aws_s3_bucket" "bucket" {
}
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
Region = data.aws_region.current.name
}
}
} This effectively creates a circular reference, where the provider is configured with its own data source. But if you used multiple aliased providers or another provider (e.g., the built-in So for now we should just make sure that unknown values are ignored. A false positive is a bug, but some false negatives are inherent to static analysis. Static analysis can almost always be trivially defeated using valid configuration. data "terraform_remote_state" "aws" {
# ...
}
provider "aws" {
region = "us-east-1"
default_tags {
tags = data.terraform_remote_state.aws.outputs.default_tags
}
} TFLint is a developer productivity tool meant to catch errors early. Tools like TFLint and tfsec should not be used to enforce any critical security or organizational policy. That is the domain of tools like Sentinel and Open Policy Agent that are designed to evaluate the data (JSON) representation of a Terraform plan, as opposed to the input (HCL) configuration. We can/should try to incrementally detect more issues through static configuration analysis to maximize the early feedback developers can get. But past the limits of static analysis, we have to silently ignore by default. Users may not intuitively understand but there's not much we can do. Printing on every ignored expression would become unusably verbose in many real-world configurations. |
I tried to update to the latest ruleset (0.24.x) and something has changed where it will error with missing tags when they exist.
Downgrading to 0.23.0 works fine. I noticed there were recent changes noted int he changelog for 0.24.0 related to taht rule so I am assuming there was some breakage there
The text was updated successfully, but these errors were encountered: