Partilhar via


Guia de início rápido: criar um firewall do Azure com vários endereços IP públicos - Terraform

Neste início rápido, você usa o Terraform para implantar um Firewall do Azure com vários endereços IP públicos de um prefixo de endereço IP público. O firewall implantado tem regras de coleta de regras NAT que permitem conexões RDP com duas máquinas virtuais do Windows Server 2019.

Terraform permite a definição, visualização e implantação de infraestrutura em nuvem. Usando Terraform, você cria arquivos de configuração usando a sintaxe HCL. A sintaxe HCL permite especificar o provedor de nuvem - como o Azure - e os elementos que compõem sua infraestrutura de nuvem. Depois de criar os arquivos de configuração, você cria um plano de execução que permite visualizar as alterações na infraestrutura antes que elas sejam implantadas. Depois de verificar as alterações, você aplica o plano de execução para implantar a infraestrutura.

Para obter mais informações sobre o Firewall do Azure com vários endereços IP públicos, consulte Implantar um Firewall do Azure com vários endereços IP públicos usando o Azure PowerShell.

Neste artigo, vai aprender a:

Pré-requisitos

Implementar o código Terraform

Nota

O código de exemplo para este artigo está localizado no repositório GitHub do Azure Terraform. Você pode visualizar o arquivo de log que contém os resultados do teste das versões atual e anterior do Terraform.

Veja mais artigos e código de exemplo mostrando como usar o Terraform para gerenciar recursos do Azure

  1. Crie um diretório no qual testar o código Terraform de exemplo e torná-lo o diretório atual.

  2. Crie um arquivo chamado providers.tf e insira o seguinte código:

    terraform {
      required_providers {
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~>3.0"
        }
        random = {
          source  = "hashicorp/random"
          version = "~>3.0"
        }
      }
    }
    
    provider "azurerm" {
      features {
        virtual_machine {
          delete_os_disk_on_deletion     = true
          skip_shutdown_and_force_delete = true
        }
      }
    }
    
  3. Crie um arquivo chamado main.tf e insira o seguinte código:

    resource "random_pet" "rg_name" {
      prefix = var.resource_group_name_prefix
    }
    
    resource "random_password" "password" {
      count       = 2
      length      = 20
      min_lower   = 1
      min_upper   = 1
      min_numeric = 1
      min_special = 1
      special     = true
    }
    
    resource "azurerm_resource_group" "rg" {
      name     = random_pet.rg_name.id
      location = var.resource_group_location
    }
    
    resource "azurerm_public_ip_prefix" "pip_prefix" {
      name                = "pip-prefix"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
      sku                 = "Standard"
      prefix_length       = 31
    }
    
    resource "azurerm_public_ip" "pip_azfw" {
      name                = "pip-azfw"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
      sku                 = "Standard"
      allocation_method   = "Static"
      public_ip_prefix_id = azurerm_public_ip_prefix.pip_prefix.id
    }
    
    resource "azurerm_public_ip" "pip_azfw_2" {
      name                = "pip-azfw-1"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
      sku                 = "Standard"
      allocation_method   = "Static"
      public_ip_prefix_id = azurerm_public_ip_prefix.pip_prefix.id
    }
    
    resource "azurerm_virtual_network" "azfw_vnet" {
      name                = "azfw-vnet"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
      address_space       = ["10.10.0.0/16"]
    }
    
    resource "azurerm_subnet" "azfw_subnet" {
      name                 = "AzureFirewallSubnet"
      resource_group_name  = azurerm_resource_group.rg.name
      virtual_network_name = azurerm_virtual_network.azfw_vnet.name
      address_prefixes     = ["10.10.0.0/26"]
    }
    
    resource "azurerm_subnet" "backend_subnet" {
      name                 = "subnet-backend"
      resource_group_name  = azurerm_resource_group.rg.name
      virtual_network_name = azurerm_virtual_network.azfw_vnet.name
      address_prefixes     = ["10.10.1.0/24"]
    }
    
    resource "azurerm_network_interface" "backend_nic" {
      count               = 2
      name                = "nic-backend-${count.index + 1}"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
    
      ip_configuration {
        name                          = "ipconfig-backend-${count.index + 1}"
        subnet_id                     = azurerm_subnet.backend_subnet.id
        private_ip_address_allocation = "Dynamic"
      }
    }
    
    resource "azurerm_network_security_group" "backend_nsg" {
      name                = "nsg-backend"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
      security_rule {
        name                       = "RDP"
        priority                   = 300
        direction                  = "Inbound"
        access                     = "Allow"
        protocol                   = "Tcp"
        source_port_range          = "*"
        destination_port_range     = "3389"
        source_address_prefix      = "*"
        destination_address_prefix = "*"
      }
    }
    
    resource "azurerm_network_interface_security_group_association" "vm_backend_nsg_association" {
      count                     = 2
      network_interface_id      = azurerm_network_interface.backend_nic[count.index].id
      network_security_group_id = azurerm_network_security_group.backend_nsg.id
    }
    
    resource "azurerm_windows_virtual_machine" "vm_backend" {
      count                 = 2
      name                  = "vm-backend-${count.index + 1}"
      resource_group_name   = azurerm_resource_group.rg.name
      location              = azurerm_resource_group.rg.location
      size                  = var.virtual_machine_size
      admin_username        = var.admin_username
      admin_password        = random_password.password[count.index].result
      network_interface_ids = [azurerm_network_interface.backend_nic[count.index].id]
      os_disk {
        caching              = "ReadWrite"
        storage_account_type = "Standard_LRS"
      }
      source_image_reference {
        publisher = "MicrosoftWindowsServer"
        offer     = "WindowsServer"
        sku       = "2019-Datacenter"
        version   = "latest"
      }
    }
    
    resource "azurerm_firewall_policy" "azfw_policy" {
      name                     = "azfw-policy"
      resource_group_name      = azurerm_resource_group.rg.name
      location                 = azurerm_resource_group.rg.location
      sku                      = var.firewall_sku_tier
      threat_intelligence_mode = "Alert"
    }
    
    resource "azurerm_firewall_policy_rule_collection_group" "policy_rule_collection_group" {
      name               = "RuleCollectionGroup"
      firewall_policy_id = azurerm_firewall_policy.azfw_policy.id
      priority           = 300
      application_rule_collection {
        name     = "web"
        priority = 100
        action   = "Allow"
        rule {
          name = "wan-address"
          protocols {
            type = "Http"
            port = 80
          }
          protocols {
            type = "Https"
            port = 443
          }
          destination_fqdns = ["getmywanip.com"]
          source_addresses  = ["*"]
        }
        rule {
          name = "google"
          protocols {
            type = "Http"
            port = 80
          }
          protocols {
            type = "Https"
            port = 443
          }
          destination_fqdns = ["www.google.com"]
          source_addresses  = ["10.10.1.0/24"]
        }
        rule {
          name = "wupdate"
          protocols {
            type = "Http"
            port = 80
          }
          protocols {
            type = "Https"
            port = 443
          }
          destination_fqdn_tags = ["WindowsUpdate"]
          source_addresses      = ["*"]
        }
      }
      nat_rule_collection {
        name     = "Coll-01"
        action   = "Dnat"
        priority = 200
        rule {
          name                = "rdp-01"
          protocols           = ["TCP"]
          translated_address  = "10.10.1.4"
          translated_port     = "3389"
          source_addresses    = ["*"]
          destination_address = azurerm_public_ip.pip_azfw.ip_address
          destination_ports   = ["3389"]
        }
        rule {
          name                = "rdp-02"
          protocols           = ["TCP"]
          translated_address  = "10.10.1.5"
          translated_port     = "3389"
          source_addresses    = ["*"]
          destination_address = azurerm_public_ip.pip_azfw.ip_address
          destination_ports   = ["3389"]
        }
      }
    }
    
    resource "azurerm_firewall" "fw" {
      name                = "azfw"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
      sku_name            = "AZFW_VNet"
      sku_tier            = var.firewall_sku_tier
      ip_configuration {
        name                 = "azfw-ipconfig"
        subnet_id            = azurerm_subnet.azfw_subnet.id
        public_ip_address_id = azurerm_public_ip.pip_azfw.id
      }
      ip_configuration {
        name                 = "azfw-ipconfig-2"
        public_ip_address_id = azurerm_public_ip.pip_azfw_2.id
      }
      firewall_policy_id = azurerm_firewall_policy.azfw_policy.id
    }
    
    resource "azurerm_route_table" "rt" {
      name                          = "rt-azfw-eus"
      location                      = azurerm_resource_group.rg.location
      resource_group_name           = azurerm_resource_group.rg.name
      disable_bgp_route_propagation = false
      route {
        name                   = "azfw"
        address_prefix         = "0.0.0.0/0"
        next_hop_type          = "VirtualAppliance"
        next_hop_in_ip_address = "10.10.0.4"
      }
    }
    
    resource "azurerm_subnet_route_table_association" "jump_subnet_rt_association" {
      subnet_id      = azurerm_subnet.backend_subnet.id
      route_table_id = azurerm_route_table.rt.id
    }
    
  4. Crie um arquivo chamado variables.tf e insira o seguinte código:

    variable "resource_group_location" {
      type        = string
      description = "Location for all resources."
      default     = "eastus"
    }
    
    variable "resource_group_name_prefix" {
      type        = string
      description = "Prefix for the Resource Group Name that's combined with a random id so name is unique in your Azure subcription."
      default     = "rg"
    }
    
    variable "firewall_sku_tier" {
      type        = string
      description = "Firewall SKU."
      default     = "Premium" # Valid values are Standard and Premium
      validation {
        condition     = contains(["Standard", "Premium"], var.firewall_sku_tier)
        error_message = "The SKU must be one of the following: Standard, Premium"
      }
    }
    
    variable "virtual_machine_size" {
      type        = string
      description = "Size of the virtual machine."
      default     = "Standard_D2_v3"
    }
    
    variable "admin_username" {
      type        = string
      description = "Value of the admin username."
      default     = "azureuser"
    }
    
  5. Crie um arquivo chamado outputs.tf e insira o seguinte código:

    output "resource_group_name" {
      value = azurerm_resource_group.rg.name
    }
    output "backend_admin_password" {
      sensitive = true
      value     = azurerm_windows_virtual_machine.vm_backend[*].admin_password
    }
    

Inicializar o Terraform

Execute terraform init para inicializar a implantação do Terraform. Este comando baixa o provedor do Azure necessário para gerenciar seus recursos do Azure.

terraform init -upgrade

Pontos principais:

  • O -upgrade parâmetro atualiza os plug-ins de provedor necessários para a versão mais recente que está em conformidade com as restrições de versão da configuração.

Criar um plano de execução do Terraform

Execute o plano de terraforma para criar um plano de execução.

terraform plan -out main.tfplan

Pontos principais:

  • O terraform plan comando cria um plano de execução, mas não o executa. Em vez disso, ele determina quais ações são necessárias para criar a configuração especificada em seus arquivos de configuração. Esse padrão permite que você verifique se o plano de execução corresponde às suas expectativas antes de fazer quaisquer alterações nos recursos reais.
  • O parâmetro opcional -out permite especificar um arquivo de saída para o plano. O uso do -out parâmetro garante que o plano revisado seja exatamente o que é aplicado.

Aplicar um plano de execução Terraform

Execute terraform apply para aplicar o plano de execução à sua infraestrutura de nuvem.

terraform apply main.tfplan

Pontos principais:

  • O comando de exemplo terraform apply pressupõe que você executou terraform plan -out main.tfplananteriormente o .
  • Se você especificou um nome de arquivo diferente para o -out parâmetro, use esse mesmo nome de arquivo na chamada para terraform apply.
  • Se você não usou o -out parâmetro, ligue terraform apply sem nenhum parâmetro.

Verificar os resultados

  1. Obtenha o nome do grupo de recursos do Azure.

    resource_group_name=$(terraform output -raw resource_group_name)
    
  2. Execute az network ip-group list para exibir os dois novos IP Groups.

    az network ip-group list --resource-group $resource_group_name
    

Clean up resources (Limpar recursos)

Quando você não precisar mais dos recursos criados via Terraform, execute as seguintes etapas:

  1. Execute o plano de terraforma e especifique o destroy sinalizador.

    terraform plan -destroy -out main.destroy.tfplan
    

    Pontos principais:

    • O terraform plan comando cria um plano de execução, mas não o executa. Em vez disso, ele determina quais ações são necessárias para criar a configuração especificada em seus arquivos de configuração. Esse padrão permite que você verifique se o plano de execução corresponde às suas expectativas antes de fazer quaisquer alterações nos recursos reais.
    • O parâmetro opcional -out permite especificar um arquivo de saída para o plano. O uso do -out parâmetro garante que o plano revisado seja exatamente o que é aplicado.
  2. Execute terraform apply para aplicar o plano de execução.

    terraform apply main.destroy.tfplan
    

Solucionar problemas do Terraform no Azure

Solucionar problemas comuns ao usar o Terraform no Azure

Próximos passos