Hi,
In v0.10.0, terraform validate
relies on terraform init
because the latter command pulls in the providers that the former command relies on to run properly. In certain use cases, like developing locally and using the AWS provider, this is a little annoying since it relies on individual users to have IAM credentials exported to their shell, or otherwise available in a location where the AWS SDK for Go can locate them.
A workaround - terraform validate -check-variables=false
- exists, where the state file is not downloaded since there is no graph traversal required. This, therefore, means that you don't need to have IAM credentials available to the underlying SDK. Unfortunately, however, this workaround means that you don't get told if a required variable isn't set or defined until you run terraform plan
, which is often later in the development cycle (assuming you use terraform validate
as a sanity check before pushing, or when opening a pull request).
A plan for a way of performing the functions validate
provided prior to 0.10.0 without IAM credentials would be valuable for my current use case.
Comments welcome.
Hi @ajlanghorn! Sorry for the workflow friction here.
The validate
command is in a tricky spot here because it's trying to skirt carefully around functionality that requires the providers, but that functionality is not cleanly separated from the rest today, and so a bunch of other stuff (as you've seen) gets disabled as a side-effect. We may be able to do better in future, but as of right now -- with Terraform's current internal design -- we're a bit stuck here.
In the mean time, I wonder if you could get the effect you want here by running terraform init
with the -backend=false
option. I must admit that I'm not 100% sure this will get the effect you need (I don't have a suitable config handy to test it right now) but this _may_ allow Terraform to get the provider plugins initialized without setting up the backend, and thus without needing credentials to interact with S3.
Hi @apparentlymart!
Thanks for the speedy reply. Ooh, that's a nice idea - I'll see if I can give that a go with the configuration I currently have, and see if it works. I'll try and let you know how that goes.
The suggestion to use -backend=false
by @apparentlymart worked perfectly for me. Thank you!
For the longer term I posted a proposal in #15895 that would formalize the idea that validate
is for static-only, offline checking while plan
is for more in-depth dynamic validation (including reaching out to the provider).
Since that seems particularly relevant to _this_ question I'd invite you both to take a look at that and see what you think. If you have any feedback, please leave it in the other issue so we can keep any discussion consolidated.
Using init -backend=false
unfortunately does not work for the data source terraform_remote_state
with backend = "remote"
.
Strangely, I found that it _does_ work if there's a variable in the name:
data "terraform_remote_state" "tfe_workspace" {
backend = "remote"
config = {
organization = "tfe_organization"
workspaces = {
# TFE bug causes false validation errors unless name includes a variable
name = var.region != "" ? "tfe-workspace" : "tfe-workspace"
}
}
}
@apparentlymart Any idea why including a variable would alleviate this problem?
^ I have the same issue. Related: https://github.com/hashicorp/terraform/issues/21761 (cc @apparentlymart )
I ran into this problem as we are upgrading from 0.11 to 0.12... terraform validate
in 0.11 did not have a problem with terraform_remote_state
, but in 0.12, it requires credentials and attempt to hit the remote backend
Have the same issue on Terraform 0.12 and data "terraform_remote_state"
:
$ terraform init -backend=false
$ terraform validate
Error: No valid credential sources found for AWS Provider.
Please see https://terraform.io/docs/providers/aws/index.html for more information on
providing credentials for the AWS Provider
Sharing my hack after fighting this all day today
My issue was related to our CI pipeline and it has no credentials. However it runs terraform validate
on the default
workspace while all my real infrastructure is under a specific workspace. This situation enabled me to target the default
workspace as CI was my primary concern.
Here is what works for me:
data "terraform_remote_state" "state" {
backend = terraform.workspace == "default" ? "local" : "s3"
workspace = terraform.workspace
config = (terraform.workspace == "default" ? { path = "fake_for_validation" } :
{
region = "us-west-2"
bucket = "my-terraform-states"
key = "my_key.tfstate"
}
)
}
And for clarity these are the commands I wanted to get past the credentials issue.
$ terraform init -backend=false
$ terraform validate -json
The workspace hack won't work for me. Is there any other workaround? I have team members who don't have access to the actual state (for security reasons), but would like to be able to run validate before making pull requests.
This terraform_remote_state
problem seems a bit different than the one we were originally discussing here, but it's related in the sense that it's also an example of instantiating a backend in a place where that's not appropriate.
After a little reading of the code, I think I see what's caused this change of behavior in Terraform 0.12: the validation implementation for terraform_remote_state
is sharing the same getBackend
function as we use for the "read" implementation:
...but that function does too much for what we need during validation. It _does_ call into the validation function for the selected backend, but crucially it also tries to _configure_ the backend, which is the point at which the backends try to populate their clients with credentials and in some cases reach out to network services to validate credentials.
I think the fix here would be to split this getBackend
function in two: getBackend
and getConfiguredBackend
, where the latter wraps getBackend
but then additionally calls Configure
on the result. Then the dataSourceRemoteStateValidate
function can call just getBackend
, while dataSourceRemoteStateRead
would use getConfiguredBackend
.
That change wouldn't fix the problem this issue was originally representing, but I think it _would_ address the more recent issue with terraform_remote_state
. This seems like it could be a good initial change to work on if anyone here is interested in trying Terraform development, though I won't add the "good first issue" label here because I don't want to confuse things by implying that I'm talking about the more involved problem of making terraform validate
easier to use _in general_ in an uncredentialed context, which is the broader problem to close this.
@apparentlymart did you ever get a chance to look into your proposed terraform_remote_state
fix?
I've opened a PR implementing Martin's recommendation so that terraform_remote_state
data sources are validated but not fully configured when using terraform validate
. Please 👍 that if you'd like to see this fixed!
https://github.com/hashicorp/terraform/pull/24887
Seems like the original issue isn't relevant anymore since terraform init -backend=false
downloads the providers and modules without requiring any credentials.
@bendrucker Thank you so much. I feel resolving this will add extra sanity to my terraform CI/CD: the most potentially destructive CI/CD pipeline in the entire company!
I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
Most helpful comment
Hi @ajlanghorn! Sorry for the workflow friction here.
The
validate
command is in a tricky spot here because it's trying to skirt carefully around functionality that requires the providers, but that functionality is not cleanly separated from the rest today, and so a bunch of other stuff (as you've seen) gets disabled as a side-effect. We may be able to do better in future, but as of right now -- with Terraform's current internal design -- we're a bit stuck here.In the mean time, I wonder if you could get the effect you want here by running
terraform init
with the-backend=false
option. I must admit that I'm not 100% sure this will get the effect you need (I don't have a suitable config handy to test it right now) but this _may_ allow Terraform to get the provider plugins initialized without setting up the backend, and thus without needing credentials to interact with S3.