无法使用 azure 上的 terraform 创建子网,如何修复?

无法使用 azure 上的 terraform 创建子网,如何修复?

我正在尝试在 Azure 上使用 terraform 创建两台 centos 8 机器。

我的模板 github关联

当我尝试申请时,出现了以下与政策相关的错误。您能建议如何修复此问题吗?

>     │ 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" {
>     │

我尝试保持内联,子网位于虚拟网络内。现在,在规划阶段从虚拟机实例资源块引用子网时,问题就出现了。

 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?

//主.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"
  }
}

//网络.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 = "*"
  }
}

//提供者.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
}

//变量.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"
    }
  
}

答案1

子网创建失败,因为它不符合管理员应用的策略。这表明必须先将 NSG 应用于子网,然后才能创建子网。不幸的是,Terraform 创建资源的方式是先创建子网,然后将 NSG 与其关联。这是两个 API 调用,第一个调用失败,因为它没有关联的 NSG。策略不知道第二个调用即将将 NSG 与子网关联。

这是 Terraform 在 ARM API 之上构建方式的缺点。除了让您的管理员放宽此政策外,没有其他很好的解决方案。

编辑:

所以看看这个问题这与您看到的非常相似,似乎您可以通过在资源内部定义子网virtual_network(而不是将其定义为单独的子网资源)来解决此问题。使用此功能,您可以内联定义 NSG 关联,并且这可以在单个范围内完成:

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"
  }
}

答案2

面对同样的问题,我们已将策略重新分配为“审核”操作,而不是“拒绝”。如果您有权限这样做。

答案3

政策管理员还可以授予暂时豁免内置到期时间。豁免可以非常细化,因此他们可以将其缩小到您的用例。可能值得与政策管理员一起探讨该选项。

相关内容