hashicorp / terraform

Terraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.
https://www.terraform.io
Other
42.76k stars 9.56k forks source link

expose provider configuration values for interpolation into other resources #22781

Closed StephenWithPH closed 5 years ago

StephenWithPH commented 5 years ago

Current Terraform Version

Terraform v0.12.8

Use-cases

I find myself using local-exec in cases where a given provider is lacking some functionality I need. The local-exec command is often curling the same api that the provider uses. Those requests need authentication and a url. Today, I pass the that info via local-exec's environment block so credentials can be interpolated into the curl command.

provisioner "local-exec" {
  command = "curl -H X-My-Token: $${MY_TOKEN} ... $${URL}"
  environment = {
    MY_TOKEN = ???
    URL      = ???
  }
}

The provider's configuration usually has the authentication (and url) info I need. It would be nice if there was an elegant way to get hands on things the provider knows in order to pass that into local-exec.

Attempted Solutions

If one chooses to configure a provider using Terraform input variables rather than environment variables, this is a solved problem since the input variables can be used anywhere. This comes at the expense of effectively removing support for provider configuration via environment variables. This also is less viable for modules that expect callers to bring their own providers when the module uses local-exec.

provider "foo" {
  credentials = var.foo_credentials
}

variable "foo_credentials" {}
$ terraform apply -var foo_credentials=SECRET

Of course, one could choose to pass the same underlying value via an environment variable to the provider and an Terraform input variable to enable interpolation, but this is duplicative and brittle:

provider "foo" {
  # credentials are read from the provider-specific environment variable FOO_CREDENTIALS
}

variable "foo_credentials" {}
$ FOO_CREDENTIALS=SECRET terraform apply -var foo_credentials=SECRET

Proposal

Expose a provider's configuration values (user-provided or defaults) for interpolation.

provisioner "local-exec" {
  command = "curl -H X-My-Token: $${MY_TOKEN} ... $${URL}"
  environment = {
    MY_TOKEN = provider.foo.credentials # <-- this is the feature request
    URL      = provider.foo.url # <-- this is the feature request
  }
}

References

I didn't find any issues that seemed similar, but searching the issues for provider and credentials and interpolation returns many (not related to this request) hits. I apologize if I missed a valid, similar issue.

teamterraform commented 5 years ago

Hi @StephenWithPH! Thanks for sharing this use-case.

The existing mechanism for exposing provider-level information for interpolation elsewhere is for the provider to offer one or more special data sources to access that data. For example, the AWS provider offers aws_caller_identity to get information about the current user, although it doesn't offer the current credentials.

When using Terraform in the recommended way, Terraform Core itself does not have knowledge of the credentials: they are instead accessed from either separate files or from environment variables depending on the design of the provider in question. Therefore a feature like this must be provided by the provider itself, as a data source. You'd need to open an issue for the provider in question to see if the provider team would consider offering such a thing, though in practice provider teams have often made an intentional policy decision not to expose directly the credentials in order to avoid them accidentally leaking into Terraform state, etc, and so you may find such requests will get rejected.

A key reason why we recommend using "ambient" credentials sources for Terraform providers (vendor-specific credentials sources independent of Terraform, or environment variables) is that those credentials can also be accessed inside programs launched by local-exec without requiring Terraform to serve as a middleman. Of course curl is a generic piece of software and so doesn't understand the conventions for accessing credentials for a specific vendor, but you can use local-exec to launch a wrapper program that does know how to access vendor-specific credentials and thus avoid ever bringing those credentials into the Terraform configuration space.

The only situation where Terraform Core could potentially provide credentials directly as you requested here would be if they were being set via arguments inside the provider block, and that usage is against best practices so we would not implement any feature that would seem to encourage it.

With all of that said, we're going to close this out now for the reasons above. You could open a feature request with whatever provider(s) have the credentials you need to see if their development teams would consider offering a data source to expose that information, but as noted above some providers have already made a specific decision not to do so in order to keep credentials out of the Terraform configuration space and out of Terraform state. Our recommended way to address your use-case is to make your local-exec program access credentials directly from an ambient source using the SDK of the vendor in question, since that requires no co-operation from Terraform Core or from a Terraform Provider.

StephenWithPH commented 5 years ago

@teamterraform ... thank you for the prompt and thorough response. It all makes sense.

In the spirit of ...

Even if the functionality you need is not available in a provider today, we suggest to consider local-exec usage a temporary workaround and to also open an issue in the relevant provider's repository to discuss adding first-class provider support. Provider development teams often prioritize features based on interest, so opening an issue is a way to record your interest in the feature.

(https://www.terraform.io/docs/provisioners/index.html#first-class-terraform-provider-functionality-may-be-available)

... I do aspire to open issues / PRs on the providers where local-exec is my stopgap kludge.

ghost commented 5 years ago

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.