Hızlı Başlangıç: Azure Güvenlik Duvarı ve IP Grupları Oluşturma - Terraform

Bu hızlı başlangıçta Terraform kullanarak ağ kuralında ve uygulama kuralında kullanılan örnek IP Gruplarına sahip bir Azure Güvenlik Duvarı dağıtacaksınız. IP Grubu, IP adreslerini, aralıkları ve alt ağları tek bir nesnede tanımlamanızı ve gruplandırmanızı sağlayan en üst düzey bir kaynaktır. IP Grubu, Azure Güvenlik Duvarı kurallarında IP adreslerini yönetmek için kullanışlıdır. IP adreslerini el ile girebilir veya bir dosyadan içeri aktarabilirsiniz.

Terraform , bulut altyapısının tanımlanmasını, önizlemesini ve dağıtımını sağlar. Terraform kullanarak HCL söz dizimlerini kullanarak yapılandırma dosyaları oluşturursunuz. HCL söz dizimi, Azure gibi bulut sağlayıcısını ve bulut altyapınızı oluşturan öğeleri belirtmenize olanak tanır. Yapılandırma dosyalarınızı oluşturduktan sonra, altyapı değişikliklerinizin dağıtılmadan önce önizlemesini görüntülemenizi sağlayan bir yürütme planı oluşturursunuz. Değişiklikleri doğruladıktan sonra, altyapıyı dağıtmak için yürütme planını uygularsınız.

Bu makalede şunları öğreneceksiniz:

Önkoşullar

Terraform kodunu uygulama

Not

Bu makalenin örnek kodu Azure Terraform GitHub deposunda bulunur. Terraform'un geçerli ve önceki sürümlerinden test sonuçlarını içeren günlük dosyasını görüntüleyebilirsiniz.

Azure kaynaklarını yönetmek için Terraform'un nasıl kullanılacağını gösteren diğer makalelere ve örnek koda bakın

  1. Örnek Terraform kodunu test etmek ve geçerli dizin yapmak için bir dizin oluşturun.

  2. adlı providers.tf bir dosya oluşturun ve aşağıdaki kodu ekleyin:

    terraform {
      required_providers {
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~>3.0"
        }
        random = {
          source  = "hashicorp/random"
          version = "~>3.0"
        }
        azapi = {
          source  = "azure/azapi"
          version = "~>1.5"
        }
      }
    }
    
    provider "azurerm" {
      features {}
    }
    
  3. adlı ssh.tf bir dosya oluşturun ve aşağıdaki kodu ekleyin:

    resource "random_pet" "ssh_key_name" {
      prefix    = "ssh"
      separator = ""
    }
    
    resource "azapi_resource_action" "ssh_public_key_gen" {
      type        = "Microsoft.Compute/sshPublicKeys@2022-11-01"
      resource_id = azapi_resource.ssh_public_key.id
      action      = "generateKeyPair"
      method      = "POST"
    
      response_export_values = ["publicKey", "privateKey"]
    }
    
    resource "azapi_resource" "ssh_public_key" {
      type      = "Microsoft.Compute/sshPublicKeys@2022-11-01"
      name      = random_pet.ssh_key_name.id
      location  = azurerm_resource_group.rg.location
      parent_id = azurerm_resource_group.rg.id
    }
    
    output "key_data" {
      value = jsondecode(azapi_resource_action.ssh_public_key_gen.output).publicKey
    }
    
  4. adlı main.tf bir dosya oluşturun ve aşağıdaki kodu ekleyin:

    resource "random_pet" "rg_name" {
      prefix = var.resource_group_name_prefix
    }
    
    resource "random_string" "storage_account_name" {
      length  = 8
      lower   = true
      numeric = false
      special = false
      upper   = false
    }
    
    resource "random_password" "password" {
      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" "pip_azfw" {
      name                = "pip-azfw"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
      allocation_method   = "Static"
      sku                 = "Standard"
    }
    
    resource "azurerm_storage_account" "sa" {
      name                     = random_string.storage_account_name.result
      resource_group_name      = azurerm_resource_group.rg.name
      location                 = azurerm_resource_group.rg.location
      account_tier             = "Standard"
      account_replication_type = "LRS"
      account_kind             = "StorageV2"
    }
    
    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" "prcg" {
      name               = "prcg"
      firewall_policy_id = azurerm_firewall_policy.azfw_policy.id
      priority           = 300
      application_rule_collection {
        name     = "app-rule-collection-1"
        priority = 101
        action   = "Allow"
        rule {
          name = "someAppRule"
          protocols {
            type = "Https"
            port = 443
          }
          destination_fqdns = ["*bing.com"]
          source_ip_groups  = [azurerm_ip_group.ip_group_1.id]
        }
      }
      network_rule_collection {
        name     = "net-rule-collection-1"
        priority = 200
        action   = "Allow"
        rule {
          name                  = "someNetRule"
          protocols             = ["TCP", "UDP", "ICMP"]
          source_ip_groups      = [azurerm_ip_group.ip_group_1.id]
          destination_ip_groups = [azurerm_ip_group.ip_group_2.id]
          destination_ports     = ["90"]
        }
      }
    }
    
    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
      }
      firewall_policy_id = azurerm_firewall_policy.azfw_policy.id
    }
    
    resource "azurerm_ip_group" "ip_group_1" {
      name                = "ip-group_1"
      resource_group_name = azurerm_resource_group.rg.name
      location            = azurerm_resource_group.rg.location
      cidrs               = ["13.73.64.64/26", "13.73.208.128/25", "52.126.194.0/23"]
    }
    resource "azurerm_ip_group" "ip_group_2" {
      name                = "ip_group_2"
      resource_group_name = azurerm_resource_group.rg.name
      location            = azurerm_resource_group.rg.location
      cidrs               = ["12.0.0.0/24", "13.9.0.0/24"]
    }
    
    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" "server_subnet" {
      name                 = "subnet-server"
      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_subnet" "jump_subnet" {
      name                 = "subnet-jump"
      resource_group_name  = azurerm_resource_group.rg.name
      virtual_network_name = azurerm_virtual_network.azfw_vnet.name
      address_prefixes     = ["10.10.2.0/24"]
    }
    
    resource "azurerm_public_ip" "vm_jump_pip" {
      name                = "pip-jump"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
      allocation_method   = "Static"
      sku                 = "Standard"
    }
    
    resource "azurerm_network_interface" "vm_server_nic" {
      name                = "nic-server"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
    
      ip_configuration {
        name                          = "ipconfig-workload"
        subnet_id                     = azurerm_subnet.server_subnet.id
        private_ip_address_allocation = "Dynamic"
      }
    }
    
    resource "azurerm_network_interface" "vm_jump_nic" {
      name                = "nic-jump"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
    
      ip_configuration {
        name                          = "ipconfig-jump"
        subnet_id                     = azurerm_subnet.jump_subnet.id
        private_ip_address_allocation = "Dynamic"
        public_ip_address_id          = azurerm_public_ip.vm_jump_pip.id
      }
    }
    
    resource "azurerm_network_security_group" "vm_server_nsg" {
      name                = "nsg-server"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
    }
    
    resource "azurerm_network_security_group" "vm_jump_nsg" {
      name                = "nsg-jump"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
      security_rule {
        name                       = "Allow-SSH"
        priority                   = 1000
        direction                  = "Inbound"
        access                     = "Allow"
        protocol                   = "Tcp"
        source_port_range          = "*"
        destination_port_range     = "22"
        source_address_prefix      = "*"
        destination_address_prefix = "*"
      }
    }
    
    resource "azurerm_network_interface_security_group_association" "vm_server_nsg_association" {
      network_interface_id      = azurerm_network_interface.vm_server_nic.id
      network_security_group_id = azurerm_network_security_group.vm_server_nsg.id
    }
    
    resource "azurerm_network_interface_security_group_association" "vm_jump_nsg_association" {
      network_interface_id      = azurerm_network_interface.vm_jump_nic.id
      network_security_group_id = azurerm_network_security_group.vm_jump_nsg.id
    }
    
    resource "azurerm_linux_virtual_machine" "vm_server" {
      name                = "server-vm"
      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_ssh_key {
        username   = var.admin_username
        public_key = jsondecode(azapi_resource_action.ssh_public_key_gen.output).publicKey
      }
      network_interface_ids = [azurerm_network_interface.vm_server_nic.id]
      os_disk {
        caching              = "ReadWrite"
        storage_account_type = "Standard_LRS"
      }
      source_image_reference {
        publisher = "Canonical"
        offer     = "UbuntuServer"
        sku       = "18.04-LTS"
        version   = "latest"
      }
      boot_diagnostics {
        storage_account_uri = azurerm_storage_account.sa.primary_blob_endpoint
      }
    }
    
    resource "azurerm_linux_virtual_machine" "vm_jump" {
      name                  = "jump-vm"
      resource_group_name   = azurerm_resource_group.rg.name
      location              = azurerm_resource_group.rg.location
      size                  = var.virtual_machine_size
      network_interface_ids = [azurerm_network_interface.vm_jump_nic.id]
      admin_username        = var.admin_username
      os_disk {
        caching              = "ReadWrite"
        storage_account_type = "Standard_LRS"
      }
      admin_ssh_key {
        username   = var.admin_username
        public_key = jsondecode(azapi_resource_action.ssh_public_key_gen.output).publicKey
      }
      source_image_reference {
        publisher = "Canonical"
        offer     = "UbuntuServer"
        sku       = "18.04-LTS"
        version   = "latest"
      }
      boot_diagnostics {
        storage_account_uri = azurerm_storage_account.sa.primary_blob_endpoint
      }
      computer_name = "JumpBox"
    
    }
    
    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                   = "azfwDefaultRoute"
        address_prefix         = "0.0.0.0/0"
        next_hop_type          = "VirtualAppliance"
        next_hop_in_ip_address = azurerm_firewall.fw.ip_configuration[0].private_ip_address
      }
    }
    
    resource "azurerm_subnet_route_table_association" "jump_subnet_rt_association" {
      subnet_id      = azurerm_subnet.server_subnet.id
      route_table_id = azurerm_route_table.rt.id
    }
    
  5. adlı variables.tf bir dosya oluşturun ve aşağıdaki kodu ekleyin:

    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"
    }
    
  6. adlı outputs.tf bir dosya oluşturun ve aşağıdaki kodu ekleyin:

    output "resource_group_name" {
      value = azurerm_resource_group.rg.name
    }
    
    output "firewall_name" {
      value = azurerm_firewall.fw.name
    }
    

Terraform'u başlatma

Terraform dağıtımını başlatmak için terraform init komutunu çalıştırın. Bu komut, Azure kaynaklarınızı yönetmek için gereken Azure sağlayıcısını indirir.

terraform init -upgrade

Önemli noktalar:

  • -upgrade parametresi, gerekli sağlayıcı eklentilerini yapılandırmanın sürüm kısıtlamalarına uygun en yeni sürüme yükseltir.

Terraform yürütme planı oluşturma

Terraform planını çalıştırarak yürütme planı oluşturun.

terraform plan -out main.tfplan

Önemli noktalar:

  • komutu terraform plan bir yürütme planı oluşturur ancak yürütmez. Bunun yerine, yapılandırma dosyalarınızda belirtilen yapılandırmayı oluşturmak için hangi eylemlerin gerekli olduğunu belirler. Bu düzen, gerçek kaynaklarda değişiklik yapmadan önce yürütme planının beklentilerinizle eşleşip eşleşmediğini doğrulamanızı sağlar.
  • İsteğe bağlı -out parametresi, plan için bir çıkış dosyası belirtmenize olanak tanır. parametresinin -out kullanılması, gözden geçirdiğiniz planın tam olarak uygulanan plan olmasını sağlar.

Terraform yürütme planı uygulama

Yürütme planını bulut altyapınıza uygulamak için terraform apply komutunu çalıştırın.

terraform apply main.tfplan

Önemli noktalar:

  • Örnek terraform apply komut, daha önce komutunu çalıştırdığınızı terraform plan -out main.tfplanvarsayar.
  • parametresi için -out farklı bir dosya adı belirttiyseniz, çağrısında terraform applyaynı dosya adını kullanın.
  • parametresini -out kullanmadıysanız, parametresiz olarak çağırın terraform apply .

Sonuçları doğrulama

  1. Azure kaynak grubu adını alın.

    resource_group_name=$(terraform output -raw resource_group_name)
    
  2. İki yeni IP Grubunu görüntülemek için az network ip-group list komutunu çalıştırın.

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

Kaynakları temizleme

Terraform aracılığıyla oluşturulan kaynaklara artık ihtiyacınız kalmadığında aşağıdaki adımları uygulayın:

  1. terraform planını çalıştırın ve bayrağını destroy belirtin.

    terraform plan -destroy -out main.destroy.tfplan
    

    Önemli noktalar:

    • komutu terraform plan bir yürütme planı oluşturur ancak yürütmez. Bunun yerine, yapılandırma dosyalarınızda belirtilen yapılandırmayı oluşturmak için hangi eylemlerin gerekli olduğunu belirler. Bu düzen, gerçek kaynaklarda değişiklik yapmadan önce yürütme planının beklentilerinizle eşleşip eşleşmediğini doğrulamanızı sağlar.
    • İsteğe bağlı -out parametresi, plan için bir çıkış dosyası belirtmenize olanak tanır. parametresinin -out kullanılması, gözden geçirdiğiniz planın tam olarak uygulanan plan olmasını sağlar.
  2. Yürütme planını uygulamak için terraform apply komutunu çalıştırın.

    terraform apply main.destroy.tfplan
    

Azure'da Terraform sorunlarını giderme

Azure'da Terraform kullanırken karşılaşılan yaygın sorunları giderme

Sonraki adımlar