'Terraform Apply Error: Code="InvalidResourceName" Message="Resource name is invalid" When creating VPN-GW Module

I'm receiving the following error when executing the Terraform Apply Command.


│ Error: Creating/Updating Virtual Network Gateway: (Name "VPN-GW-HUB-dev" / Resource Group "RG-HUB-dev"): network.VirtualNetworkGatewaysClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="InvalidResourceName" Message="Resource name  is invalid. The name can be up to 80 characters long. It must begin with a word character, and it must end with a word character or with '_'. The name may contain word characters or '.', '-', '_'." Details=[]
│ 
│   with module.MOD-VPN-GW.azurerm_virtual_network_gateway.vpngw,
│   on Modules/10.VPN-GW/main.tf line 31, in resource "azurerm_virtual_network_gateway" "vpngw":
│   31: resource "azurerm_virtual_network_gateway" "vpngw" {


What was I trying to do?

My Terraform code creates a complete Hub-and-Spoke infrastructure in Azure. It worked very well until I decided to modularise the VPN GW part.

My Terraform code structure is the usual format:

--Modules/{module-name}/main.tf
--main.tf

So within the {module-name} - I have a folder called:

10.VPN-GW\main.tf

What have I tried?

Well, I have tried to reformat the code, I double checked it against all other modules that worked OK. I have NO idea why this error is happening, and it has been 3 days now non stop debugging this.

The module file is here:

#------------------------------
# VPN GW MODULE FILE - ALso contains GW SUBNET
#-------------------------------

resource "azurerm_subnet" "gwSubnet" {
  name                 =    var.subnet_name
  resource_group_name  =    var.subnet_resource_group_name
  virtual_network_name =    var.subnet_virtual_network_name
  address_prefixes     =    var.subnet_address_prefixes

}

variable "subnet_name" {
    type = string
}

variable "subnet_resource_group_name" {
    type = string
}

variable "subnet_virtual_network_name" {
    type = string
}

variable "subnet_address_prefixes" {
    type = list(string)
}


output "outSubnetIDVPNGW" {
    value = azurerm_subnet.gwSubnet.id
}
 

resource "azurerm_virtual_network_gateway" "vpngw" {
  name                = "${var.vpn-gw-name}"
  location            = "${var.vpn-gw-location}"
  resource_group_name = "${var.vpngw_resource_group_name}"

  type     = "Vpn"
  vpn_type = "RouteBased"
  
  active_active = false
  enable_bgp    = false
  sku           = "VpnGw1"

  ip_configuration {
    name                          = "${var.ip_configuration_name}"
    public_ip_address_id          = "${var.ip_configuration_public_ip_address_id}"
    private_ip_address_allocation = "Dynamic"
    subnet_id                     = azurerm_subnet.gwSubnet.id
  }

    vpn_client_configuration {
        address_space = "${var.vpn_client_configuration_address_space}"

        root_certificate {
        name = "${var.root_certificate_name}"
        public_cert_data = "${var.cert}"
    }

    revoked_certificate {
      name       = "${var.revoked_certificate_name}"
      thumbprint = "${var.revoked_certificate_thumbprint}"
    }
  }
}

variable "vpn-gw-name" {
    type = string
    //default = ""
}

variable "vpn-gw-location" {
    //default = ""
    type = string
}

variable "vpngw_resource_group_name" {
    default = ""
}

variable "ip_configuration_name" {
    default = ""
}

variable "ip_configuration_public_ip_address_id" {
    default = ""
}

/*
variable "ip_configuration_private_ip_address_allocation" {
    //default = ""
   // type = string
}
*/

variable "vpn_client_configuration_address_space" {
    default = []
}

variable "root_certificate_name" {
    default = ""
}

variable "cert" {  
    default = ""
}

variable "revoked_certificate_name" {
  default = ""
}

variable "revoked_certificate_thumbprint" {
    default = ""
}

variable "ip_configuration" {
    type = map(string)
}


variable "vpn_client_configuration" {
  type = object({
    address_space           = list(string)
    root_certificate        = map(string)
    revoked_certificate     = map(string)
  })
} 

/*
variable "revoked_certificate" {
  type = map(string)
}
*/

The main.tf file -- that calls each module, is given below - (I'm only adding the snippet for the part causing the error) - i.e. creation of the VPN GW


#-----------------------------------------
# Create GW SUBNET & VPN GW
#-----------------------------------------

module "MOD-VPN-GW" {
  source              = "./Modules/10.VPN-GW"

  subnet_name                 = "GatewaySubnet"
  subnet_resource_group_name  = "RG-HUB-${var.environmentCode}"
  subnet_virtual_network_name =  "VNET-HUB-${var.environmentCode}"
  subnet_address_prefixes     = ["10.0.1.0/27"]

  vpn-gw-name                 = "VPN-GW-HUB-${var.environmentCode}"
  vpn-gw-location               = "westeurope"
  vpngw_resource_group_name   = "RG-HUB-${var.environmentCode}"
  
  ip_configuration = {
    name        = "VNetGatewayConfig"
    public_ip_address_id                    = "${module.MOD-VPNGW-PIP.id}"
    private_ip_address_allocation  = "Dynamic"
    subnet_id                   = module.MOD-VPN-GW.outSubnetIDVPNGW
  }

  vpn_client_configuration = {
    address_space = ["172.16.10.0/24"]

    root_certificate = {
      name = "dev.vpn.macos.com"
      public_cert_data  = data.azurerm_key_vault_certificate.akv-certificate.certificate_data_base64

    }

    revoked_certificate  = {
      name       = "Verizon-Global-Root-CA"
      thumbprint = "912198EEF23DCAC40939312FEE97DD560BAE49B1"
    }
  }

   depends_on = [
     module.MOD-RG-HUB, module.MOD-VNET-HUB, azurerm_linux_virtual_machine.label-vm-spoke-01
  ]

}

What did I search for?

I cannot seem to find this particular error code in a google search. Its not telling me that name given to my VPN GW is incorrect - its giving me the name (in the error message) and telling me that there is no name given. Which is odd. Or have I misunderstood the error message?

The terraform init command succeeds. The terraform validate command succeeds. The terraform plan command succeeds.

This fails when applying



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source