How to generate SSH key in Terraform using tls_private_key?

The Terraform's module tls_private_key can help you to generate the TLS Private key. Here is what happens when you use Terraform's tls_private_key module -

  1. At first you generate RSA or ECDAS private key.
  2. After generating the private key we need to encode the private key as PEM file.
  3. After that tls_private_key module will help you to download the private_key(PEM) locally
  4. Finally the tls_private_key module will also set the permission to 0600

All the above tasks are carried out behind the scene by module tls_private_key.

This blog post will help you to understand tls_private_key module as well as how to use it inside Terraform project

(Note - The complete terraform code you can find at the bottom of the page)

Table of Content

  1. Create tls_private_key resource inside Terraform file
  2. Create aws_key_pair and store public key onto AWS
  3. Verify the generated public and private keys
  4. Create AWS EC2 instance using the generated tls_private_key
  5. Conclusion

1. Create tls_private_key resource inside Terraform file

When you work with Terraform you need to define resource and since we are using the tls_private_key module, so we will be creating a resource for tls_private_key -

1# file name : main.tf
2# The following configuration will enable you to use tls_private_key module
3
4resource "tls_private_key" "terrafrom_generated_private_key" {
5  algorithm = "RSA"
6  rsa_bits  = 4096
7}

Other supported Algorithm- ECDSA P384 and ED25519

Also apart from RSA 5096 algorithm, you can use other algorithms such as - ECDSA P384 and ED25519 for generating the

Here is the code snippet for ECDSA P384 and ED25519 -

1resource "tls_private_key" "ecdsa-p384-example" {
2  algorithm   = "ECDSA"
3  ecdsa_curve = "P384"
4}
1resource "tls_private_key" "ed25519-example" {
2  algorithm = "ED25519"
3}


2. Create aws_key_pair and store the public key onto AWS

The next terraform module we are going to use is aws_key_pair. You need to keep a couple of things in your mind while working with the key generation -

  1. Private key - The private key will be generated and stored locally on your working computer
  2. Public key - Public key will be automatically uploaded to AWS.
 1resource "aws_key_pair" "generated_key" {
 2  
 3  # Name of key: Write the custom name of your key
 4  key_name   = "aws_keys_pairs"
 5  
 6  # Public Key: The public will be generated using the reference of tls_private_key.terrafrom_generated_private_key
 7  public_key = tls_private_key.terrafrom_generated_private_key.public_key_openssh
 8 
 9  # Store private key :  Generate and save private key(aws_keys_pairs.pem) in current directory 
10  provisioner "local-exec" {   
11    command = <<-EOT
12      echo '${tls_private_key.terrafrom_generated_private_key.private_key_pem}' > aws_keys_pairs.pem
13      chmod 400 aws_keys_pairs.pem
14    EOT
15  }
16} 

2.1 Run the Terraform code

Here is the complete Terraform code for generating the SSH Keys -

 1provider "aws" {
 2  region = "eu-central-1"
 3  shared_credentials_files = ["/Users/rwagh/.aws/credentials"]
 4  #access_key = ""
 5  #secret_key = ""
 6}
 7
 8resource "tls_private_key" "terrafrom_generated_private_key" {
 9  algorithm = "RSA"
10  rsa_bits  = 4096
11}
12
13resource "aws_key_pair" "generated_key" {
14
15  # Name of key : Write the custom name of your key
16  key_name   = "aws_keys_pairs"
17
18  # Public Key: The public will be generated using the reference of tls_private_key.terrafrom_generated_private_key
19  public_key = tls_private_key.terrafrom_generated_private_key.public_key_openssh
20
21  # Store private key :  Generate and save private key(aws_keys_pairs.pem) in current directory
22  provisioner "local-exec" {
23    command = <<-EOT
24      echo '${tls_private_key.terrafrom_generated_private_key.private_key_pem}' > aws_keys_pairs.pem
25      chmod 400 aws_keys_pairs.pem
26    EOT
27  }
28}

Note-

  1. Make sure to replace the access key and secret key in the above Terraform code based on your AWS account

2.2 Execute - "$ terraform init" command

Now we have our Terraform code ready and the first command we are going to run is $ terraform init.

The key points to notice over here -

  1. The $ terraform init command will find the latest version of tls
  2. After that it will download and install the same latest version.

As you can see in the following screenshot of the terminal it has downloaded all the required dependencies of tls

Run terraform init command to find and download dependencies of module tls_private_key


2.3 Execute - "$ terraform plan" command

After successfully running the $ terraform init command, let's run the next command .i.e. $ terraform plan

Here is the screenshot of the terminal after running the terraform plan command.

You will notice the following things -

  1. The terraform plan command will generate the keys with the name - aws_keys_pairs.pem
  2. Also it will create those keys using algorithm RSA and ecdsa_curve

terraform plan command for generating the private and public keys


2.4 Execute - "$ terraform apply" command

Finally, run $ terraform apply command to generate both public as well as private keys.

Here is the screenshot from the terminal -

terraform apply for generating the ssh keys



3. Verify the generated public and private keys

Let's first verify the public key which is generated on our local system. Goto your project where you have you main.tf and there you will find the private key -

Here is the screenshot -

private key generated along with the main.tf file

Verify the Public key on AWS

  1. Log into to your AWS account-> EC2 Dashboard -> Key Pair

Locate public on AWS EC2 dashboard

  1. Click on key Pair link

Public key on AWS dashboard



4. Create AWS EC2 instance using the generated tls_private_key

Now let's take one step forward and use the existing Terraform Code but this time we are going to create EC2 instance using the generated tls_private_key.

Here is the Terraform code which I have updated after the Step-3 -

 1 
 2 provider "aws" {
 3   region = "eu-central-1"
 4   shared_credentials_files = ["/Users/rwagh/.aws/credentials"]
 5 }
 6 
 7 resource "tls_private_key" "terrafrom_generated_private_key" {
 8   algorithm = "RSA"
 9   rsa_bits  = 4096
10 }
11 
12 resource "aws_key_pair" "generated_key" {
13 
14   # Name of key: Write the custom name of your key
15   key_name   = "aws_keys_pairs"
16 
17   # Public Key: The public will be generated using the reference of tls_private_key.terrafrom_generated_private_key
18   public_key = tls_private_key.terrafrom_generated_private_key.public_key_openssh
19 
20   # Store private key :  Generate and save private key(aws_keys_pairs.pem) in current directory
21   provisioner "local-exec" {
22     command = <<-EOT
23       echo '${tls_private_key.terrafrom_generated_private_key.private_key_pem}' > aws_keys_pairs.pem
24       chmod 400 aws_keys_pairs.pem
25     EOT
26   }
27 }
28 
29 # 1. EC2 Instance 
30 resource "aws_instance" "ec2_example" {
31 
32   ami = "ami-0767046d1677be5a0"
33   instance_type = "t2.micro"
34
35   # 2. Key Name
36   # Specify the key name and it should match with key_name from the resource "aws_key_pair"
37   key_name= "aws_keys_pairs"
38   tags = {
39     Name = "Terraform EC2 - using tls_private_key module"
40   }
41   
42   #3. Connection Block-
43   connection {
44     type        = "ssh"
45     host        = self.public_ip
46     user        = "ubuntu"
47     
48     # Mention the exact private key name which will be generated 
49     private_key = file("aws_keys_pairs.pem")
50     timeout     = "4m"
51   }
52 }

Here are the additional changes which I did to my Terraform code -

1. EC2 Instance - I have added one more Terraform resource .i.e. - aws_instance for provisioning the EC2 instance.

2. Key Name- You need to add a key name which should be the same which we have created using Terraform's tls_private_key module

3. Connection Block- At last you need to mention the connection block where you will connect to EC2 instance using the private key.

Refer to the following screenshot

Here is the ec2 instance which is up and running on AWS with the generated tls_private_key-

EC2 Instance running on AWS using the generated private key from Terraform's tls_private_key module

Also when you click on connect (EC2 -> Instances -> i-0fc06a99b85eac11f -> Connect to instance) then you will reference to the same private key -

Connect to EC2 instance using the private key



5. Conclusion

I hope this article will help you to understand the concept of SSL Key generation using Terraform's tls_private_key module.

If you do not want to use the Terraform's tls_private_key module then you have to manually generate the SSH Keys by yourself. Here is one more article where you will find how to generate the SSH Keys manually and use them inside your terraform project



Read More - Terragrunt -

  1. How to use Terragrunt?

Posts in this series