Secure Your SSH Keys: Automating Key Generation and Key Vault Secret Creation with Terraform
Infrastructure-as-Code (IaC) isn’t just about provisioning resources — it’s about creating secure, scalable, and maintainable solutions. A great example of this is managing SSH keys in a secure way. In this guide, we’ll walk through the process of creating an SSH key using the tls provider in Terraform and securely storing the key in Azure Key Vault. This approach ensures that sensitive information never leaves the cloud environment, maintaining the highest security standards for your infrastructure.
First, let’s start with generating the SSH key. Terraform’s tls provider allows us to create private keys programmatically, avoiding the need to generate keys manually on your local machine. In our example, we define a tls_private_keyresource to generate an RSA key pair with a bit length of 4096, ensuring robust encryption:
resource "tls_private_key" "vm1" {
algorithm = "RSA"
rsa_bits = 4096
}
Once this resource is applied, Terraform will generate a key pair that exists solely in memory during execution. This prevents the risk of inadvertently exposing sensitive information by writing it to the local filesystem. However, these keys need to be accessible to authorized services and users in a secure manner. This is where Azure Key Vault comes into play.
To store the generated keys securely, we first need to reference the Azure Key Vault where they will be stored. Using the data block in Terraform, we fetch the details of an existing Key Vault. Here’s the configuration for retrieving a Key Vault named kv-devops-dev-grffye in the resource group rg-devops-dev:
data "azurerm_key_vault" "main" {
name = "kv-devops-dev-grffye"
resource_group_name = "rg-devops-dev"
}
This data block doesn’t create a new Key Vault but instead provides a handle to an existing one, which we can now use to provision secrets.
With the Key Vault reference in place, the next step is to store the SSH public and private keys as secrets. Terraform’s azurerm_key_vault_secret resource is used to achieve this. Each secret is defined with a unique name and is tied to the ID of the Key Vault retrieved earlier. For example, the public key is stored as follows:
resource "azurerm_key_vault_secret" "vm1_ssh_public_key" {
name = "vm1-ssh-public"
value = tls_private_key.vm1.public_key_openssh
key_vault_id = data.azurerm_key_vault.main.id
}
Similarly, the private key is stored securely in another secret:
resource "azurerm_key_vault_secret" "vm1_ssh_private_key" {
name = "vm1-ssh-private"
value = tls_private_key.vm1.private_key_openssh
key_vault_id = data.azurerm_key_vault.main.id
}
By storing both the public and private keys in Azure Key Vault, we ensure they are encrypted at rest and can only be accessed by entities with the appropriate permissions. This approach eliminates the need to handle sensitive files locally, reducing the risk of accidental exposure.
In conclusion, using Terraform to generate SSH keys and store them securely in Azure Key Vault streamlines the process of managing credentials while adhering to best practices for security and compliance. By integrating the tls provider with Azure Key Vault, you can maintain a high level of control over sensitive information, enabling a more secure and automated infrastructure. This method not only saves time but also significantly reduces the operational burden of managing SSH keys manually, making it an essential practice for modern cloud-native operations.