Search code examples
azureterraformazure-keyvaultssh-keys

Use Terraform to create an AKS with an RSA key maintained by Key Vault


I am trying to create an AKS (Azure Kubernetes Service) with Terraform and I want to set an ssh_key for the "linux_profile" of the AKS nodes.

The only relevant tutorial for creating an AKS with terraform I found is this and it uses a local file in "~/.ssh/id_rsa.pub".

resource "azurerm_kubernetes_cluster" "k8s" {
name                = var.cluster_name
location            = azurerm_resource_group.k8s.location
resource_group_name = azurerm_resource_group.k8s.name
dns_prefix          = var.dns_prefix

linux_profile {
    admin_username = "ubuntu"

    ssh_key {
        key_data = file(var.ssh_public_key)
    }
  }
# lots of other configuration
}

I want to use a key that is managed by keyvault, so i don't have to manage any secrets locally. For that I have created a key vault with this code (I have removed the part about "access_policies" for clarity)

resource "azurerm_key_vault" "example-keyvault" {
    name                        ="example-keyvault"
    location                    =       data.azurerm_resource_group.rg.location
    resource_group_name         = data.azurerm_resource_group.rg.name

    enabled_for_disk_encryption = true
    tenant_id                   = data.azurerm_client_config.current.tenant_id
    soft_delete_enabled         = true
    purge_protection_enabled    = false
    sku_name                    = "standard"

    tags                        = merge(var.tags, {environment = terraform.workspace})
  }

I have created a key within this keyvault with this code:

resource "azurerm_key_vault_key" "ssh_key_linux_profile" 
 {
    name         = "ssh_key_linux_profile"
    key_vault_id = azurerm_key_vault.example-keyvault.id
    key_type     = "RSA"
    key_size     = 2048

    key_opts = [
      "decrypt",
      "encrypt",
      "sign",
      "unwrapKey",
      "verify",
      "wrapKey",
    ]

  }

I am trying to find a way to tell terraform to use the public component of that key as "key_data" for the "ssh_key". I tried the following: Import the "azurerm_key_vault_key" into my current scope:

data "azurerm_key_vault_key" "ssh_key_linux_profile" {
  name         = "ssh_key_linux_profile"
  key_vault_id = azurerm_key_vault.example-keyvault.id
}

and then access the public part of the key:

...
ssh_key {
        key_data = data.azurerm_key_vault_key.ssh-key-linux-profile.e
    }
...

I already figured out by now that "e" is only the "public exponent" and therefor only a small part of the public key. The corresponding terraform documentation does not give me any hints :-/

I can acutally download that key with the azure cli

az keyvault key download --vault-name "example-keyvault" -n ssh-key-linux-profile -e PEM -f mykey.pem

Is there any way to tell terraform to use this key?

Update: I found this reddit threat that had the same problem but was not able to solve it either.


Solution

  • Perhaps you can create the SSH public Key locally and then store them in the Azure Key Vault secret. Then you can use the Data Source to get the secret value as the ssh key:

    data "azurerm_key_vault_secret" "example" {
      name         = "ssh-key-linux-profile"
      key_vault_id = data.azurerm_key_vault.existing.id
    }
    
    ...
    ssh_key {
            key_data = data.azurerm_key_vault_secret.example.value
        }
    ...
    

    This is the right and simple way to store the SSH Public Key in Azure Key Vault.