user2100163
user2100163

Reputation: 91

How to generate file and re-use its content with terrafrom

I would like to generate ssh keys with a local-exec then read the content of the file.

resource "null_resource" "generate-ssh-keys-pair" {
  provisioner "local-exec" {
    command = <<EOT
      ssh-keygen -t rsa -b 4096 -C "test" -P "" -f "testkey"
    EOT
  }
}

data "local_file" "public-key" {
  depends_on = [null_resource.generate-ssh-keys-pair]
  filename = "testkey.pub"
}

data "local_file" "private-key" {
  depends_on = [null_resource.generate-ssh-keys-pair]
  filename = "testkey"
}

terraform plan works but when I run the apply, I got error on testkey and testkey.pub don't exist.

Thanks

Upvotes: 2

Views: 1887

Answers (3)

dukeofgaming
dukeofgaming

Reputation: 3198

Generating an SSH key in Terraform is inherently insecure because it gets stored in the tfstate file, however I had a similar problem to solve and thought that the most secure/usable was to use a secret management service + using a cloud bucket for the backend:

terraform {
  required_providers {
    google = {
      source = "hashicorp/google"
      version = "4.3.0"
    }
  }

  backend "gcs" {
    bucket  = "tfstatebucket"
    prefix  = "terraform/production"
  }
}

//Import Ansible private key from Google Secrets Manager
resource "google_secret_manager_secret" "ansible_private_key" {
  secret_id = var.ansible_private_key_secret_id
  replication {
    automatic = true
  }
}

data "google_secret_manager_secret_version" "ansible_private_key"{
  secret  = google_secret_manager_secret.ansible_private_key.secret_id
  version = var.ansible_private_key_secret_id_version_number
}


resource "local_file" "ansible_imported_local_private_key" {
    sensitive_content   = data.google_secret_manager_secret_version.ansible_private_key.secret_data
    filename            = var.ansible_imported_local_private_key_filename
    file_permission     = "0600"
}

In the case of GCP, I would add the secret in Google Secrets Manager, then use terraform import on the secret, which will in turn write it to the backend bucket. That way it doesn't get stored in Git as plain text, you can have the key file local to your project (.terraform shouldn't be under version control), and it's arguably more secure in the bucket.

So the workflow essentially is:

Human --> Secret Manager

Secret Manager --> Terraform Import --> GCS Bucket Backend
                                    |--> Create .terraform/ssh_key 

.terraform/ssh_key --> Terraform/Ansible/Whatever

Hashicorp Vault would be another way to address this

Upvotes: 0

Martin Atkins
Martin Atkins

Reputation: 74694

Instead of generating a file using an external command and then reading it in, I would suggest to use the Terraform tls provider to generate the key within Terraform itself, using tls_private_key:

terraform {
  required_providers {
    tls = {
      source = "hashicorp/tls"
    }
  }
}

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

The tls_private_key resource type exports two attributes that are equivalent to the two files you were intending to read in your example:

  • tls_private_key.example.private_key_pem: the private key in PEM format
  • tls_private_key.example.public_key_openssh: the public key in the format OpenSSH expects to find in .ssh/authorized_keys.

Please note the warning in the tls_private_key documentation that using this resource will cause the private key data to be saved in your Terraform state, and so you should protect that state data accordingly. That would also have been true for your approach of reading files from disk using data resources, because any value Terraform has available for use in expressions must always be stored in the state.

Upvotes: 3

Marcin
Marcin

Reputation: 238957

I run your code and there are no problems with it. It correctly generates testkey and testkey.pub.

So whatever causes it to fail for you, its not this snipped of code you've provided in the question. The fault must be outside the code snipped.

Upvotes: 0

Related Questions