Skip to content
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

Can't create TLS Certificate: ${file("${path.module}/ca.key")}: no such file (file is created by another resource) #16136

Closed
sirmax123 opened this issue Sep 20, 2017 · 4 comments

Comments

@sirmax123
Copy link

Hi Team!

I faced with issue trying to create self-signed certificate:

resource "null_resource" "generate_key" {
...
    provisioner "local-exec" {
        command = <<_EOT
            openssl genrsa \
                -out ${path.module}/consul-ca.key 4096
        _EOT
...
}

resource "tls_self_signed_cert" "consul_ca" {

    depends_on = ["null_resource.generate_key"]

    key_algorithm   = "RSA"
    private_key_pem = "${file("${path.module}/consul-ca.key")}"
    subject {
        common_name  = "server.${var.region}.consul"
   ...
    }
  validity_period_hours = 12
  is_ca_certificate = true
  allowed_uses = [
...
  ]
}

So I create key file first and try to use it.
I got the following error:

1 error(s) occurred:

* module.consul_ca.tls_self_signed_cert.consul_ca: 1 error(s) occurred:

* module.consul_ca.tls_self_signed_cert.consul_ca: file: open <some-path/>modules/b5c864c6402ea8f70c71c742ee6a6478/consul-ca.key: no such file or directory in:

${file("${path.module}/consul-ca.key")}

It looks like ${file()} checks if file exist before actual run.

As workaround I have empty pre-created file.

@sirmax123 sirmax123 changed the title Can't create TLS Certificate: ${file("${path.module}/ca.key")} (file is created by another resource) Can't create TLS Certificate: ${file("${path.module}/ca.key")}: no such file (file is created by another resource) Sep 20, 2017
@apparentlymart
Copy link
Contributor

Hi @sirmax123! Sorry for this unfortunate behavior.

The file function is primarily for loading static files that exist as part of the configuration, such as templates and scripts. Since it's a function, it doesn't participate in the dependency graph and instead just gets resolved as part of configuration parsing.

For your specific use-case here, Terraform has its own tls_private_key resource that does a similar thing to what you are doing here with the provisioner:

resource "tls_private_key" "consul_ca" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

resource "tls_self_signed_cert" "consul_ca" {
  key_algorithm   = "RSA"
  private_key_pem = "${tls_private_key.consul_ca.private_key_pem}"
  # ...
}

Using this resource also solves a different problem: provisioners only run during resource creation, and so if you were to try to plan updates to the config using a subsequent terraform plan you would need to ensure that the consul-ca.key file on disk is preserved between those two runs to avoid errors. Using the resource means that the key is stored in the state (which you must then store securely, of course) and is thus automatically available to subsequent runs.


TLS keys aside, the general solution to this problem of generating custom data for use would be hashicorp/terraform-provider-external#5, which would add a resource type called external that behaves similarly to the data source of the same name but participates in the managed resource lifecycle, including retaining the generated data in the state so that subsequent Terraform runs can update or destroy the data in the usual way.

@sirmax123
Copy link
Author

Thank you for you reply.

Unfortunately I can't use resource "tls_private_key" because can't save state secure.

I guess this issue can be closed with 'by design' resolution, it is not a bug but expected behaviour.

@apparentlymart
Copy link
Contributor

Hi again @sirmax123! Sorry for the delay in following up.

In general Terraform can't guarantee that sensitive information included in configuration -- whether via file() interpolations or otherwise -- will not also get written to the state. Certain attributes are able to obscure such data via hashing, but at this time it is not generally possible and so we advise secure state storage as the solution.

There are other mechanisms to load data from external files that do obey the dependency graph, such as using the template_file data source, but all such mechanism would result in the file contents being included in the state.

In future we plan to invest more in first-class support for storing state securely at rest, along with other features to make sensitive information in state less troublesome.

@ghost
Copy link

ghost commented Apr 6, 2020

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.

@ghost ghost locked and limited conversation to collaborators Apr 6, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants