Export SSH Private Keys into Local File Using local-exec

I’m trying to use Terraform to create a key pairs for my EC2 instances and store the private keys locally on my machine.

I seem to be having an issue when attempting to pass in the Terraform generated ssh keys into the bash script. Terraform is complaining of a “Invalid template interpolation value” when passing in the list of private keys. It looks like it is expecting a string, but that will not work with what I’m trying to do.

Any ideas on how to get around this? The code I used and the corresponding error are below:

The code I used to create the key pairs is:

#create ssh keys
resource "tls_private_key" "my-ssh-keys" {
  count        = 3
  algorithm = "RSA"
  rsa_bits     = 4096
}

#get private keys
locals {
  priv_keys = tolist(tls_private_key.my-ssh-keys[*].private_key_pem)
}

#create aws key pairs
resource "aws_key_pair" "my-key-pairs" {
  count           = var.my-instance-count
  key_name   = "key-pair-${count.index + 1}"
  public_key = tls_private_key.my-ssh-keys[count.index].public_key_openssh

  #store private keys in local directory
  provisioner "local-exec" {
    command = <<-EOT
      declare -a keys=(${local.priv_keys})

      for ssh_key in "$${!keys[@]}";
        do
          echo "$${keys[$ssh_key]}" > aws_key_pair_"$keys".pem

          chmod 400 aws_key_pair_"$keys".pem
        done
      EOT
  }
}

Error message:

│ Error: Invalid template interpolation value
│
│   on workers.tf line 27, in resource "aws_key_pair" "my-key-pairs":
│   26:     command = <<-EOT
│   27:       declare -a keys=(${local.priv_keys})
│   28:       for ssh_key in "$${!keys[@]}";
│   29:         do
│   30:           echo "$${keys[$ssh_key]}" > aws_key_pair_"$keys".pem
│   31:           chmod 400 aws_key_pair_"$keys".pem
│   32:         done
│   33:       EOT
│     ├────────────────
│     │ local.priv_keys is list of string with 3 elements
│
│ Cannot include the given value in a string template: string required.

I was able to solve this by reading the documentation :slight_smile:

I over complicated the whole thing by using local-exec when I could achieve the same result using the file resource. If anyone else discovers this in the future, the following block of code was used to store the private keys in local files:

resource "local_file" "my-keys" {
  count = var.my-instance-count
  content = tls_private_key.k8s-worker-ssh[count.index].private_key_pem
  filename = "${aws_key_pair.my-key-pairs[count.index].key_name}.pem"
}

A much simpler and platform agnostic approach :smiley: