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
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.)
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.
-
For the record, @Martin-atkins answer is better, but this will work in a pinch with code changes.– JosiahCommented Feb 8, 2023 at 15:31
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).