6

I used the terraform resource tls_private_key to generate a key and push that into AWS, but it didn't give me the private key to use to access the related resources. How can I recover that key?

3 Answers 3

10

If you need to use a value like this private key for later steps, the common answer is to return it as a root module output value. Since the private key is sensitive, you can mark it as such to prevent Terraform from showing it on the screen by default:

output "private_key" {
  value     = tls_private_key.example.private_key_pem
  sensitive = true
}

When you run terraform apply, Terraform will redact the value because it's sensitive. However, you can still access it from scripts by running terraform output -raw private_key, because the value is still stored in the state and the sensitive option only prevents it from showing in human-oriented output. (The -raw option is intended for use in scripts.)

0
4

The private key is stored in the terraform state. Typically you would show the resources with the terraform state command, but sensitive values are not shared on the screen. If you use the -json option, this restriction is removed, dumping the entire state in json format.

Then you can use jq to parse the output to find the value. This value will have quotes around it and escaped newlines that you'll need to clean up in order to get a properly formatted PEM key. The -r option to jq will handle that well by dumping the value in raw format.

terraform show -json | \
jq -r '.values.root_module.resources[].values | select(.private_key_pem) |.private_key_pem' \
> ~/.ssh/terraform_private_key.pem

In the above jq command, three are three sections. The first filters down to the values of each resource. The second selects only value sets with a privatey_key_pem key in them. The third prints the value of those specific key(s). The select prevents the printing of a null line for each value set without a private_key_pem key/value pair to show.

1
  • For the record, @Martin-atkins answer is better, but this will work in a pinch with code changes.
    – Josiah
    Commented Feb 8, 2023 at 15:31
1

Using private_key_openssh

Another option is to use

terraform show -json |
  jq -r '.values.root_module.resources[] | select(.address=="tls_private_key.ssh").values.private_key_openssh'

This command also uses root_module.resources specifically, because that's where the key is created. This address corresponds to this in a main.tf,

resource "tls_private_key" "ssh" {
  algorithm   = "ECDSA"
  ecdsa_curve = "P384"
}

In your case the key may have a different name and resource. By any means, I'd rather not write it explicitly, you can find out what resource it's in with,

terraform show -json | jq -r | less

I choose not to use PEM because OpenSSH has its own key format which is different in some cases. For example, as of now OpenSSH can not read ed25519 keys in PKCS#9 (PEM).

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.