Crash Code-10 (Terraform EC2 SSH Keys & Cloud-Config Guide)

Learn how to generate secure RSA SSH keys and render an AWS EC2 cloud-config YAML file using Terraform's tls and local providers in this concise guide

BLZR

CodeTerraform

Crash CodeDevOps

760 Words [Mind Tax: 3:27m]

06 September 2026, 6:30:00 PM


Problem Description

Your company has started using AWS, and needs an EC2 instance containing generated SSH keys. Your task is to prepare its configuration.

Requirements

  1. Add the following providers to your solution using Terraform 0.14.5 syntax:
  • local(version 2.0.0)
  • tls(version 3.0.0)
  1. Reference the above providers in your solution via the provider keyword and add their configuration if required.
  2. Don’t add any more providers.
  3. Use the correct resource from the tls provider to generate private and public SSH keys (RSA - 4096 bit) using one of the aforementioned providers. The name of this resource should be ssh_key.
  4. Use the correct resource from the local provider to generate cloud-config.yaml by rendering cloud-config.yaml.tpl and filling placeholders with the following keys:
  • public_key with the result of creating the public key
  • private_key with the result of creating the private key
  1. The name of this resource should be cloud_config. Remember to use correct indentation.

Assumptions

  • You don’t need to write any code to set up any resources in AWS.
  • cloud-config.yaml.tpl follows precisely the following format (don’t copy it, assume it is located in the same directory as cloud-config.yaml.tpl, simply read it):
# cloud-config.yaml.tpl
write_files:
- path: /etc/app/key
  permissions: '0600'
  content: |
    ${private_key}
- path: /etc/app/key.pub
  permissions: '0644'
  content: |
    ${public_key}
  • Indents in the YAML file are four single spaces.
  • The version of Terraform in use is 0.14.5.

Hints

  • Do not use deprecated Terraform syntax; e.g. use var.whatever instead of ${var.whatever}.
  • Use template functions in place of deprecated template providers.

Approach

To fulfill these requirements, we must construct a Terraform solution that generates cryptographic materials natively and writes them to a local file formatted for AWS cloud-init.

Step 1: Provider Block Configuration

Terraform version 0.14.5 introduced a stricter, cleaner dependency management model. We will use the terraform { required_providers { ... } } block to strictly pin the local and tls providers to versions 2.0.0 and 3.0.0 respectively. Following this, we explicitly instantiate them using the provider keyword.

Step 2: Generating the Cryptographic Keys

We utilize the tls_private_key resource from the TLS provider. Setting the algorithm to RSA and the bit length to 4096 ensures a highly secure SSH key pair. The attributes private_key_pem and public_key_openssh will be dynamically exposed upon creation.

Step 3: Template Rendering

Older Terraform versions relied on the template_file data source, but modern industry standards dictate using the built-in templatefile() function. This function reads a file from disk and parses it, swapping out placeholder variables (like ${private_key}) with dynamic values injected via a map. Finally, the local_file resource outputs the rendered content to cloud-config.yaml.

Solve

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
terraform {
  required_version = ">= 0.14.5" required_providers{
    local = {
      source = "hashicorp/local" version = "2.0.0"
    } tls ={
      source = "hashicorp/tls" version = "3.0.0"
    }
  }
}

provider "local" {
}

provider "tls" {
}

resource "tls_private_key" "ssh_key" {
  algorithm = "RSA" rsa_bits = 4096
}

resource "local_file" "cloud_config" {
  filename = "${path.module}/cloud-config.yaml"
  content  = templatefile("${path.module}/cloud-config.yaml.tpl",{
    private_key = tls_private_key.ssh_key.private_key_pem
    public_key = tls_private_key.ssh_key.public_key_openssh
  } )
}

Why This Solution Is Correct

  1. Syntax Compliance: By declaring variables in the templatefile function map directly as private_key = tls_private_key.ssh_key.private_key_pem instead of wrapping them in string interpolation ("${…}"), we follow the modern HCL2 best practices outlined in the hints.
  2. Built-in Functions: The deprecated template provider is entirely avoided. templatefile() securely and efficiently evaluates the file at the supplied path.
  3. No Unnecessary AWS Resources: As specified in the assumptions, we rely entirely on the tls and local providers to generate the needed configuration without actually calling the AWS provider.

Additional Information

While this solution effectively generates a local configuration file, standard security principles apply when dealing with cryptographic assets in Terraform:

  • State File Security: The generated private_key_pem will be stored in plain text inside your terraform.tfstate file. In a production environment, ensure your state file backend (like an S3 bucket) is encrypted at rest and tightly controls access via IAM policies.
  • Ephemeral Usage: Generating SSH keys via the tls provider is great for bootstrapping ephemeral environments, CI/CD pipelines, or bastion hosts. For long-lived enterprise environments, it is generally recommended to import existing keys from a secure vault like AWS Secrets Manager or HashiCorp Vault.