Score:0

Subnet is not creating with terraform on azure, how to fix it?

cn flag

I am trying to create two centos 8 machines with terraform on azure.

My templates github link

When I try to apply, I am getting below error related to policy. Could you please suggest how to fix this?

>     │ Error: creating Subnet: (Name "subnetforAutomation" / Virtual Network Name "vnetforAutomation" / Resource Group "automation_mart"):
> network.SubnetsClient#CreateOrUpdate: Failure sending request:
> StatusCode=0 -- Original Error: Code="RequestDisallowedByPolicy"
> Message="Resource 'subnetforAutomation' was disallowed by policy.
> Policy identifiers:
> '[{\"policyAssignment\":{\"name\":\"Deny-Subnet-Without-Nsg\",\"id\":\"/providers/Microsoft.Management/managementGroups/QSFT-landingzones/providers/Microsoft.Authorization/policyAssignments/Deny-Subnet-Without-Nsg\"},\"policyDefinition\":{\"name\":\"Subnets
> should have a Network Security Group
> \",\"id\":\"/providers/Microsoft.Management/managementGroups/QSFT/providers/Microsoft.Authorization/policyDefinitions/Deny-Subnet-Without-Nsg\"}}]'."
> Target="subnetforAutomation"
> AdditionalInfo=[{"info":{"evaluationDetails":{"evaluatedExpressions":[{"expression":"type","expressionKind":"Field","expressionValue":"Microsoft.Network/virtualNetworks/subnets","operator":"Equals","path":"type","result":"True","targetValue":"Microsoft.Network/virtualNetworks/subnets"},{"expression":"Microsoft.Network/virtualNetworks/subnets/networkSecurityGroup.id","expressionKind":"Field","operator":"Exists","path":"properties.networkSecurityGroup.id","result":"True","targetValue":"false"}]},"policyAssignmentDisplayName":"Deny-Subnet-Without-Nsg","policyAssignmentId":"/providers/Microsoft.Management/managementGroups/QSFT-landingzones/providers/Microsoft.Authorization/policyAssignments/Deny-Subnet-Without-Nsg","policyAssignmentName":"Deny-Subnet-Without-Nsg","policyAssignmentScope":"/providers/Microsoft.Management/managementGroups/QSFT-landingzones","policyDefinitionDisplayName":"Subnets
> should have a Network Security Group
> ","policyDefinitionEffect":"Deny","policyDefinitionId":"/providers/Microsoft.Management/managementGroups/QSFT/providers/Microsoft.Authorization/policyDefinitions/Deny-Subnet-Without-Nsg","policyDefinitionName":"Deny-Subnet-Without-Nsg"},"type":"PolicyViolation"}]
> 
>     │
>     │   with azurerm_subnet.subnet,
>     │   on main.tf line 24, in resource "azurerm_subnet" "subnet":
>     │   24: resource "azurerm_subnet" "subnet" {
>     │

I tried keeping inline, the subnet inside vnet. And the issue comes now when referring the subnet from VM instance resource block at the plan stage itself.

 Error: Unsupported attribute
│
│   on network.tf line 26, in resource "azurerm_network_interface" "example":
│   26:     subnet_id                     =  azurerm_virtual_network.vnet.subnet.id #azurerm_subnet.subnet.id
│
│ Can't access attributes on a set of objects. Did you mean to access an attribute across all elements of the set?
╵

//main.tf

## <https://www.terraform.io/docs/providers/azurerm/r/windows_virtual_machine.html>
resource "azurerm_windows_virtual_machine" "example" {
  name                = var.machine_details.name
  computer_name       = var.machine_details.name
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  size                = var.machine_details.size
  admin_username      = var.machine_details.username
  admin_password      = var.machine_details.password
  network_interface_ids = [
    azurerm_network_interface.example.id,
  ]

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

  source_image_reference {
    publisher = "MicrosoftWindowsServer"
    offer     = "WindowsServer"
    sku       = "2019-Datacenter"
    version   = "latest"
  }
}

//network.tf

## <https://www.terraform.io/docs/providers/azurerm/r/virtual_network.html>
resource "azurerm_virtual_network" "vnet" {
  name                = "vNet"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

subnet{
 name = "internal"
 address_prefix     = "10.0.2.0/24"
 security_group = azurerm_network_security_group.example.id
}

}


## <https://www.terraform.io/docs/providers/azurerm/r/network_interface.html>
resource "azurerm_network_interface" "example" {
  name                = "example-nic"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  ip_configuration {
    name                          = "internal"
    subnet_id                     =  azurerm_virtual_network.vnet.subnet.id #azurerm_subnet.subnet.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.myvm1publicip.id
  }
}

resource "azurerm_public_ip" "myvm1publicip" {
  name                = var.public_ip.name
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  allocation_method   = var.public_ip.allocation_method
  sku                 = var.public_ip.sku
}

resource "azurerm_network_security_group" "example" {
  name                = var.nsg
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  security_rule {
    name                       = "test123"
    priority                   = 100
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "*"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
}

//provider.tf

## <https://www.terraform.io/docs/providers/azurerm/index.html>
provider "azurerm" {
  features {}
}

//rg.tf

## <https://www.terraform.io/docs/providers/azurerm/r/resource_group.html>
resource "azurerm_resource_group" "rg" {
  name     = "TerraformTesting2"
  location = var.location
}

//variables.tf

variable "location" {
  type        = string
  description = "Azure Region where all these resources will be provisioned"
  default     = "eastus2"
}

variable "public_ip" {
 

  default = {
      name              = "pip1"
      allocation_method = "Dynamic"
      sku               = "Basic"
    }
  
  
}

variable "nsg" {
  type        = string
  description = "Azure NSG"
  default     = "example-nsg"
}

variable "machine_details" {
  
  default = {
      name             = "example-vm2"
      size = "Standard_E2s_v3" #"Standard_F2"
      username               = "adminnasme"
      password = "MyPaword!@3"
    }
  
}
Mat avatar
cn flag
Mat
"Subnets should have a Network Security Group"
Sara June avatar
cn flag
i added, still getting same issue
Score:1
ng flag

The subnet is failing to be created because it is not compliant with a policy your administrators have applied. This indicates that the subnet must have an NSG applied to it before it can be created. Unfortunately the way Terraform does creation of the resources is that you create the subnet first, then associate the NSG with it. This is two API calls, and the first one is failing because it doesn't have an NSG associated with it. Policy is not aware that a second call is coming to associate the NSG with the subnet.

This is the downside to the way Terraform builds on top of the ARM API. There isn't a great solution to this, other than getting your admins to relax this policy.

Edit:

So looking at this issue which is pretty similar to what you are seeing, it seems you can work around this by defining your subnets inside your virtual_network resource, rather than as separate subnet resources. Using this you can define the NSG association inline and it this may do it in a single cale:

resource "azurerm_virtual_network" "example" {
  name                = "virtualNetwork1"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
  address_space       = ["10.0.0.0/16"]
  dns_servers         = ["10.0.0.4", "10.0.0.5"]

  ddos_protection_plan {
    id     = azurerm_network_ddos_protection_plan.example.id
    enable = true
  }


  subnet {
    name           = "subnet3"
    address_prefix = "10.0.3.0/24"
    security_group = azurerm_network_security_group.example.id
  }

  tags = {
    environment = "Production"
  }
}
Sara June avatar
cn flag
Thanks for the reply Sam but our security team not allowing this solution, any alternate way other than skipping this policy?
ng flag
See edit, defining everything inline the the virtual network object I think may work. If not then the only way to do it would be to create an ARM template and call this using the Terraform ARM template resource, or a script using the local exec option.
Sara June avatar
cn flag
Hi @sam-cogan .I have tried keeping the subnet in the vnet portion but getting error during plan itself. can you please see the details I added above.
Sara June avatar
cn flag
it seems working if I access that as azurerm_virtual_network.vnet.subnet.*.id[0]
Score:0
al flag

Facing the same issue we've reassigned the policy with 'Audit' action instead of 'Deny'. If you have the permissions to do so.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.