Home > OS >  Deploy Azure Key Vault Windows VM using Terraform
Deploy Azure Key Vault Windows VM using Terraform

Time:01-01

I'm trying to learn how to deploy infrastructure using Terraform. My intention is to deploy a VM with a WinRM listener and for this reason, I need to use a certificate. As you can see, in the code below I first deploy a Key vault in which I put the certificate and then I retrieve the certificate from the Vault in order to register it into the Virtual Machine.


###############################################################################################################
# PROVIDERS
###############################################################################################################

provider "azurerm" {
  features {}
}


###############################################################################################################
# RESOURCES
###############################################################################################################

data "azurerm_client_config" "current" {}

resource "azurerm_resource_group" "rg" {
  name     = "runner"
  location = "West Europe"
}

resource "azurerm_key_vault" "testrunnerkeyvault" {
  name                = "test-runner-keyvault"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  tenant_id           = data.azurerm_client_config.current.tenant_id
  sku_name            = "standard"

  access_policy {
    tenant_id = data.azurerm_client_config.current.tenant_id
    object_id = data.azurerm_client_config.current.object_id

    certificate_permissions = [
      "create",
      "delete",
      "deleteissuers",
      "get",
      "getissuers",
      "import",
      "list",
      "listissuers",
      "managecontacts",
      "manageissuers",
      "purge",
      "recover",
      "setissuers",
      "update",
    ]

    key_permissions = [
      "backup",
      "create",
      "decrypt",
      "delete",
      "encrypt",
      "get",
      "import",
      "list",
      "purge",
      "recover",
      "restore",
      "sign",
      "unwrapKey",
      "update",
      "verify",
      "wrapKey",
    ]

    secret_permissions = [
      "backup",
      "delete",
      "get",
      "list",
      "purge",
      "recover",
      "restore",
      "set",
    ]

    storage_permissions = [
      "Backup",
      "Delete",
      "DeleteSAS",
      "Get",
      "GetSAS",
      "List",
      "ListSAS",
      "Purge",
      "Recover",
      "RegenerateKey",
      "Restore",
      "Set",
      "SetSAS",
      "Update"
    ]
  }
}

resource "azurerm_key_vault_certificate" "testrunnercertificate" {
  name         = "test-winrm-cert"
  key_vault_id = azurerm_key_vault.testrunnerkeyvault.id

  certificate {
    contents = filebase64("files/winrm_cert.pfx")
    password = "*********"
  }
}

resource "azurerm_virtual_network" "vn" {
  name                = "runner_vn"
  address_space       = ["10.0.0.0/8"]
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
}

resource "azurerm_subnet" "subnet" {
  name                 = "runner_subnet"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vn.name
  address_prefixes     = ["10.0.1.0/24"]
}

resource "azurerm_network_security_group" "nsg" {
  name                = "Runner-Security-Group"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  tags = {
    environment = "Test"
  }
}

resource "azurerm_network_security_rule" "ssh-rule" {
  name                        = "SSH"
  priority                    = 1001
  direction                   = "Inbound"
  access                      = "Allow"
  protocol                    = "Tcp"
  source_port_range           = "*"
  destination_port_range      = "22"
  source_address_prefix       = "*"
  destination_address_prefix  = "*"
  resource_group_name         = azurerm_resource_group.rg.name
  network_security_group_name = azurerm_network_security_group.nsg.name
}

resource "azurerm_network_security_rule" "winrm-https-rule" {
  name                        = "WinRM-Https"
  priority                    = 300
  direction                   = "Inbound"
  access                      = "Allow"
  protocol                    = "Tcp"
  source_port_range           = "*"
  destination_port_range      = "5986"
  source_address_prefix       = "*"
  destination_address_prefix  = "*"
  resource_group_name         = azurerm_resource_group.rg.name
  network_security_group_name = azurerm_network_security_group.nsg.name
}

resource "azurerm_network_security_rule" "winrm-http-rule" {
  name                        = "WinRM-Http"
  priority                    = 301
  direction                   = "Inbound"
  access                      = "Allow"
  protocol                    = "Tcp"
  source_port_range           = "*"
  destination_port_range      = "5985"
  source_address_prefix       = "*"
  destination_address_prefix  = "*"
  resource_group_name         = azurerm_resource_group.rg.name
  network_security_group_name = azurerm_network_security_group.nsg.name
}

resource "azurerm_network_security_rule" "rdp-rule" {
  name                        = "RDP"
  priority                    = 302
  direction                   = "Inbound"
  access                      = "Allow"
  protocol                    = "Tcp"
  source_port_range           = "*"
  destination_port_range      = "3389"
  source_address_prefix       = "*"
  destination_address_prefix  = "*"
  resource_group_name         = azurerm_resource_group.rg.name
  network_security_group_name = azurerm_network_security_group.nsg.name
}

resource "azurerm_subnet_network_security_group_association" "secgroup-assoc" {
  subnet_id                 = azurerm_subnet.subnet.id
  network_security_group_id = azurerm_network_security_group.nsg.id
}

resource "azurerm_public_ip" "runner_public_ip" {
  name                = "runner-ip"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  allocation_method   = "Dynamic"
  sku                 = "Basic"
}

resource "azurerm_network_interface" "network_interface" {
  name                    = "runner-network-interface"
  location                = azurerm_resource_group.rg.location
  resource_group_name     = azurerm_resource_group.rg.name
  internal_dns_name_label = "runnertest" 

  ip_configuration {
    name                          = "internal"
    subnet_id                     = azurerm_subnet.subnet.id
    private_ip_address_allocation = "static"
    private_ip_address            = "10.0.1.5"
    public_ip_address_id          = azurerm_public_ip.runner_public_ip.id
  }

}

resource "azurerm_network_interface_security_group_association" "nisecuritygroup" {
  network_interface_id      = azurerm_network_interface.network_interface.id
  network_security_group_id = azurerm_network_security_group.nsg.id

}

resource "azurerm_windows_virtual_machine" "runner" {
  name                  = "runner"
  resource_group_name   = azurerm_resource_group.rg.name
  location              = azurerm_resource_group.rg.location
  size                  = "Standard_B2s"
  admin_username        = "******"
  admin_password        = "******"
  network_interface_ids = [azurerm_network_interface.network_interface.id]

  secret {
    certificate {
      store = "/CurrentUser/My"
      url   = azurerm_key_vault_certificate.testrunnercertificate.secret_id
    }
    key_vault_id = azurerm_key_vault.testrunnerkeyvault.id
  }


  winrm_listener {
    protocol        = "Https"
    certificate_url = azurerm_key_vault_certificate.testrunnercertificate.secret_id
  }

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
    disk_size_gb         = 64
  }

  source_image_reference {
    publisher = "MicrosoftWindowsServer"
    offer     = "WindowsServer"
    sku       = "2022-datacenter-azure-edition-smalldisk"
    version   = "latest"
  }

}


data "azurerm_public_ip" "runner-ip" {
  name                = azurerm_public_ip.runner_public_ip.name
  resource_group_name = azurerm_windows_virtual_machine.runner.resource_group_name
  depends_on          = [azurerm_windows_virtual_machine.runner]
}


output "public_ip_address" {
  value = data.azurerm_public_ip.runner-ip.ip_address
}

Unfortunately, during the deployment of the virtual machine I receive the following error:

 Error: waiting for creation of Windows Virtual Machine "runner" (Resource Group "runner"): 
 Code="KeyVaultAccessForbidden" Message="Key Vault 
 https://test-runner-keyvault.vault.azure.net/secrets/test-winrm-cert/23e7d5ab76914841b2c6e58d1e68b9b1 either has not been enabled for deployment or the vault id provided, /subscriptions/<subscriptionid>/resourceGroups/runner/providers/Microsoft.KeyVault/vaults/test-runner-keyvault, does not match the Key Vault's true resource id."
│
│   with azurerm_windows_virtual_machine.runner,
│   on main.tf line 224, in resource "azurerm_windows_virtual_machine" "runner":
│  224: resource "azurerm_windows_virtual_machine" "runner" {

Ani idea? Thank you in advance

Happy new year

CodePudding user response:

You need to switch to true the following optional params (in your key-vault resource) :

  • enabled_for_deployment - (Optional) Boolean flag to specify whether Azure Virtual Machines are permitted to retrieve certificates stored as secrets from the key vault. Defaults to false.

found here : https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault#argument-reference

  • Related