I need to spin up a bunch of EC2 boxes for different users. Each user should be sandboxed from all the others, so each EC2 box needs its own SSH key.
What's the best way to accomplish this in Terraform?
Almost all of the instructions I've found want me to manually create an SSH key and paste it into a terraform script.
(Bad) Examples:
Since I need to programmatically generate unique keys for many users, this is impractical.
This doesn't seem like a difficult use case, but I can't find docs on it anywhere.
At a pinch, I could generate Terraform scripts and inject SSH keys on the fly using Bash. But that seems like exactly the kind of thing that Terraform is supposed to do in the first place.
Create a main.tf and add the Terraform block with the TLS and Linode providers defined and configured. Now we need to add a tls_private_key resource to generate our SSH key. We will set the algorithm to RSA and the rsa_bits property to 4096, so we generate a suitable key. Great, we will now have a key generated.
Open a terminal and use the ssh-keygen command with the -C flag to create a new SSH key pair. Replace the following: KEY_FILENAME : the name for your SSH key file. For example, a filename of my-ssh-key generates a private key file named my-ssh-key and a public key file named my-ssh-key.
Terraform can generate SSL/SSH private keys using the tls_private_key
resource.
So if you wanted to generate SSH keys on the fly you could do something like this:
variable "key_name" {} resource "tls_private_key" "example" { algorithm = "RSA" rsa_bits = 4096 } resource "aws_key_pair" "generated_key" { key_name = var.key_name public_key = tls_private_key.example.public_key_openssh } data "aws_ami" "ubuntu" { most_recent = true filter { name = "name" values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"] } filter { name = "virtualization-type" values = ["hvm"] } owners = ["099720109477"] # Canonical } resource "aws_instance" "web" { ami = data.aws_ami.ubuntu.id instance_type = "t2.micro" key_name = aws_key_pair.generated_key.key_name tags { Name = "HelloWorld" } }
This will create an SSH key pair that lives in the Terraform state (it is not written to disk in files other than what might be done for the Terraform state itself when not using remote state), creates an AWS key pair based on the public key and then creates an Ubuntu 14.04 instance where the ubuntu
user is accessible with the private key that was generated.
You would then have to extract the private key from the state file and provide that to the users. You could use an output
to spit this straight out to stdout when Terraform is applied.
I should point out here that passing private keys around is generally a bad idea and you'd be much better having developers create their own key pairs and provide you with the public key that you (or them) can use to generate an AWS key pair (potentially using the aws_key_pair
resource as used in the above example) that can then be specified when creating instances.
In general I would only use something like the above way of generating SSH keys for very temporary dev environments that you are controlling so you don't need to pass private keys to anyone. If you do need to pass private keys to people you will need to make sure that you do this in a secure channel and that you make sure the Terraform state (which contains the private key in plain text) is also secured appropriately.
The code below creates myKey
to AWS
and myKey.pem
to your computer
and the created myKey
and myKey.pem
have the same private keys. (I used Terraform v0.15.4
)
resource "tls_private_key" "pk" { algorithm = "RSA" rsa_bits = 4096 } resource "aws_key_pair" "kp" { key_name = "myKey" # Create "myKey" to AWS!! public_key = tls_private_key.pk.public_key_openssh provisioner "local-exec" { # Create "myKey.pem" to your computer!! command = "echo '${tls_private_key.pk.private_key_pem}' > ./myKey.pem" } }
Don't forget to make myKey.pem
readable only by you running the code below before ssh to your ec2 instance.
chmod 400 myKey.pem
Otherwise the error below occurs.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Permissions 0664 for 'myKey.pem' are too open. It is required that your private key files are NOT accessible by others. This private key will be ignored. Load key "myKey.pem": bad permissions [email protected]: Permission denied (publickey).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With