azureazure-keyvaultterraform-provider-azurehsm

How to activate Managed HSM and configure encryption with customer-managed keys stored in Azure Key Vault Managed HSM using Terraform


I’m working on to create Azure Key Vault Managed HSM using terraform. For that I have followed this documentation.

The above documentation contains the code for creating the HSM but not for the activation of managed HSM.

I want to provision and activate a managed HSM using Terraform. Is it possible or not through the terraform?

After Activate a managed HSM, I want to configure encryption with customer-managed keys stored in Azure Key Vault Managed HSM. For that I have followed this documentation, but it contains the Azure CLI code.


Solution

  • Unfortunately , its not directly possible to activate the Managed HSM from Terraform . Currently , you can only provision it from terraform or ARM template but for activating it has to be done only from PowerShell and Azure CLI. It is also the same while updating the storage account with customer managed key and assigning a key vault role assignment.

    If you use azurerm_storage_account_customer_managed_key, then you will get the below error:

    enter image description here

    Overall all HSM Key vault Operations needs to be performed on CLI or Powershell.

    So , For workaround you can use local-exec in terraform to directly run it without performing separate operations.

    Code:

    provider "azurerm" {
      features {}
    }
    data "azurerm_client_config" "current" {
    }
    
    resource "azurerm_resource_group" "example" {
      name     = "keyvaulthsm-resources"
      location = "West Europe"
    }
    
    resource "azurerm_key_vault_managed_hardware_security_module" "example" {
      name                       = "testKVHsm"
      resource_group_name        = azurerm_resource_group.example.name
      location                   = azurerm_resource_group.example.location
      sku_name                   = "Standard_B1"
      purge_protection_enabled   = true
      soft_delete_retention_days = 90
      tenant_id                  = data.azurerm_client_config.current.tenant_id
      admin_object_ids           = [data.azurerm_client_config.current.object_id]
    
      tags = {
        Env = "Test"
      }
    }
    
    variable "KeyName" {
      default=["C:/<Path>/cert_0.key","C:/<Path>/cert_1.key","C:/<Path>/cert_2.key"]
    }
    
    variable "CertName" {
      default=["C:/<Path>/cert_0.cer","C:/<Path>/cert_1.cer","C:/<Path>/cert_2.cer"]
    }
    
    resource "null_resource" "OPENSSLCERT" {
        count = 3
      provisioner "local-exec" {
        command = <<EOT
         cd  "C:\Program Files\OpenSSL-Win64\bin"
        ./openssl.exe req -newkey rsa:2048 -nodes -keyout ${var.KeyName[count.index]}  -x509 -days 365 -out ${var.CertName[count.index]} -subj "/C=IN/ST=Telangana/L=Hyderabad/O=exy ltd/OU=Stack/CN=domain.onmicrosoft.com"
        EOT
        interpreter = [
          "PowerShell","-Command"
        ]
      }
    }
    
    resource "null_resource" "securityDomain" {
      provisioner "local-exec" {
        command = <<EOT
        az keyvault security-domain download --hsm-name ${azurerm_key_vault_managed_hardware_security_module.example.name} --sd-wrapping-keys ./cert_0.cer ./cert_1.cer ./cert_2.cer --sd-quorum 2 --security-domain-file ${azurerm_key_vault_managed_hardware_security_module.example.name}-SD.json
        EOT
        interpreter = [
          "PowerShell","-Command"
        ]
      }
      depends_on = [
        null_resource.OPENSSLCERT
      ]
    }
    
    resource "azurerm_storage_account" "example" {
      name                     = "ansumanhsmstor1"
      resource_group_name      = azurerm_resource_group.example.name
      location                 = azurerm_resource_group.example.location
      account_tier             = "Standard"
      account_replication_type = "GRS"
    
      identity {
        type = "SystemAssigned"
      }
    }
    resource "null_resource" "roleassignkv" {
      provisioner "local-exec" {
        command = <<EOT
        az keyvault role assignment create --hsm-name ${azurerm_key_vault_managed_hardware_security_module.example.name} --role "Managed HSM Crypto Service Encryption User" --assignee ${azurerm_storage_account.example.identity[0].principal_id} --scope /keys
        az keyvault role assignment create --hsm-name ${azurerm_key_vault_managed_hardware_security_module.example.name} --role "Managed HSM Crypto User" --assignee ${data.azurerm_client_config.current.object_id} --scope /
        az keyvault key create --hsm-name ${azurerm_key_vault_managed_hardware_security_module.example.name} --name storageencryptionkey --ops wrapKey unwrapKey --kty RSA-HSM --size 3072
        EOT
        interpreter = [
          "PowerShell","-Command"
        ]
      }
      depends_on = [
        null_resource.securityDomain,
        azurerm_storage_account.example
      ]
    }
    
    resource "null_resource" "storageupdate" {
      provisioner "local-exec" {
        command = <<EOT
        az storage account update --name ${azurerm_storage_account.example.name} --resource-group ${azurerm_resource_group.example.name} --encryption-key-name storageencryptionkey --encryption-key-source Microsoft.Keyvault --encryption-key-vault ${azurerm_key_vault_managed_hardware_security_module.example.hsm_uri}
        EOT
        interpreter = [
          "PowerShell","-Command"
        ]
      }
      depends_on = [
        null_resource.securityDomain,
        azurerm_storage_account.example,
        null_resource.roleassignkv
      ]
    }
    

    Output:

    enter image description here

    enter image description here

    enter image description here

    enter image description here

    enter image description here

    enter image description here

    Note: Please make sure to enable Purge Protection on the HSM Keyvault and have all the required permissions on Management Plane (not added in code) and Control Plane (I have added in the code). To install OpenSSL you can refer this answer by mtotowamkwe on this SO thread.