0

I am creating AWS EC2 instance and I am using Terraform Cloud as backend.

in ./main.tf:

terraform {

    required_version = "~> 0.12"
    backend "remote" {
    hostname     = "app.terraform.io"
    organization = "organization"
    workspaces { prefix = "test-dev-" }

  }

in ./modules/instances/function.tf


resource "aws_instance" "test" {
    ami = "${var.ami_id}"
    instance_type = "${var.instance_type}"
    subnet_id = "${var.private_subnet_id}"
    vpc_security_group_ids = ["${aws_security_group.test_sg.id}"]
    key_name      = "${var.test_key}"                                        

    tags = {
        Name = "name"
        Function = "function"
    }

  provisioner "remote-exec" {
    inline = [
      "sudo useradd someuser"
    ]

    connection {
      host = "${self.public_ip}"
      type        = "ssh"
      user        = "ubuntu"
      private_key = "${file("~/.ssh/mykey.pem")}"
    }
  }
}

and as a result, I got the following error:

Call to function "file" failed: no file exists at /home/terraform/.ssh/...

so what is happening here, is that terraform trying to find the file in Terraform Cloud instead of my local machine. How can I transfer file from my local machine and still using Terraform Cloud?

1
  • did my answer provide any help? Answer still shows open. Wanted to know if you got what you needed. Typically any file based input makes me first look at can it be a data source instead. If not and you need a file, then see if my answer helped Feb 11, 2020 at 8:25

3 Answers 3

1

May be a better way to manage private key is using protected variables into the Terraform Cloud. Otherwise you have to save it in repo that is not secure.

1

Currently when you run terraform against a remote workspace in terraform cloud the repository that you are working in gets uploaded. If your key is contained in that repo and is a relative path from your working directory then it should find it. However, as mentioned in another answer, leaving your key in your repo is not a good security practice.

I'd recommend considering something like SSM parameter store, vault, or other secure method of storing such information.

However there's one additional way you could do this. If you create the key as a resource, then you could refer to this created key as a data source and terraform and everything would be stored in the state file. If you are okay with that then you could abstract the need to have any file locally, and instead store the key value as an output from a related plan or the same plan.

Be aware this still has some security implications if you don't ensure your remote workspace and terraform cloud has security applied to different levels of users in the team plan. I'm a pretty big fan of using the state this way though when possible, Is it simplifies and removes one more extra complexity from my deployment.

The last option is the other user mentioned, is secure variables. this means you would set up a environment variable that is marked as sensitive in the settings. This would prevent it from being in plain text, and might be a viable option if you can just pass it in part of your job. There's a Python library that supports API calls to simplify updating them across the board if you don't want to use the terraform cloud provider for terraform cloud.

2
  • Thanks for your thoughts, putting the keys in the repo as you said is not a good security practice. My goal is to use Vault, but at this point I am creating the Vault, so I was wondering how can I mange the keys and secrets before having the Vault installed. I am not comfortable using Secure variables in terraform cloud (for some unknown reason). I ended up sending the keys to AWS with it's CLI and then referring their name in the terraform script. Feb 11, 2020 at 9:36
  • @kingindanord nice. Encourage you answer your own question and close this then or ask for more clarity. We don't want to leave the question unopened for providing help for others in the future Feb 11, 2020 at 13:38
0

As @Vasiliy Shakhunov and @SheldonH have mentioned, there is no straight way to do what I asked in the question. In the end I ended up uploading the keys into AWS with its CLI like this:

aws ec2 import-key-pair --key-name "name_for_the_key" --public-key-material file:///home/user/.ssh/name_for_the_key.pub

and then reference it like that:

resource "aws_instance" "test" {

    ami = "${var.ami_id}"

    ...

    key_name      = "name_for_the_key"   

    ...

}

Note Yes file:// looks like the "Windowsest" syntax ever but you have to use it on linux too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.