【Azure】暗黙的に構築されるDNSサーバは権威サーバなのか？

[前回の記事](https://qiita.com/hidekko/items/d2f8b4311a741a688229)のAzure版です。
最近の記事では構成図ちゃんと書いてなかったので書きました。
構成図書くほど複雑でもなかったんですけどね。
また後程時間があれば他の記事も構成図書いてアップしていきます。

![構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/4e15208c-b549-f667-bd0d-3a3baa775273.png)

この構成図内の<font color="Red">**暗黙的なAzure DNSが権威サーバかどうかを確認**</font>します。

今回も構築はTerraformでサクッと終わらせます。

# Terraform
まずは変数設定です。

## 変数設定
```variable.tf
# Import Subscription ID variable from OS's Enviroment variable
variable "ARM_SUBSCRIPTION_ID" {
  type        = string
}

# Import Tenant ID variable from OS's Enviroment variable
variable "ARM_TENANT_ID" {
  type        = string
}

# Import Client ID variable from OS's Enviroment variable
variable "ARM_CLIENT_ID" {
  type        = string
}

# Import Client Secret variable from OS's Enviroment variable
variable "ARM_CLIENT_SECRET" {
  type        = string
}

# Generate random text for a unique storage account name
resource "random_id" "random_id" {
  keepers = {
    # Generate a new ID only when a new resource group is defined
    resource_group = azurerm_resource_group.rg.name
  }
  byte_length = 8
}

# system name
variable "system_name" {
  type        = string
  default     = "AuthoritativeDNS-01"
}

# region
variable "region" {
  type        = string
  default     = "southeastasia"
}

# resource group (rg) name prefix
variable "rg_name_pre" {
  type        = string
  default     = "rg-"
}

# virtual network (vnet) name prefix
variable "vnet_name_pre" {
  type        = string
  default     = "vnet-"
}

# virtual network (vnet) name suffix
variable "vnet_name_suf" {
  type        = string
  default     = "authoritative01"
}

# vnet ip address prefix
variable "vnet_addr_pre" {
  type        = string
  default     = "192.168."
}

# vnet ip address suffix
variable "vnet_addr_suf" {
  type        = string
  default     = "200.0/23"
}

# subnet (sn) name prefix
variable "sn_name_pre" {
  type        = string
  default     = "sn-"
}

# sn name suffix for Linux
variable "sn_name_suf_lin" {
  type        = string
  default     = "lin01"
}

# sn ip address suffix for Linux
variable "sn_addr_suf_lin" {
  type        = string
  default     = "200.0/24"
}

# sn name suffix for Windows
variable "sn_name_suf_win" {
  type        = string
  default     = "win01"
}

# sn ip address suffix for Windows
variable "sn_addr_suf_win" {
  type        = string
  default     = "201.0/24"
}

# Network Interface Card (nic) name prefix
variable "nic_name_pre" {
  type        = string
  default     = "nic-"  
}

# Network Security Group (nsg) name prefix
variable "nsg_name_pre" {
  type        = string
  default     = "nsg-"  
}

# Public IP Address (pip) prefix
variable "pip_name_pre" {
  type        = string
  default     = "pip-"
}

# IP Configuration (ipconf) suffix
variable "ipconf_suf" {
  type        = string
  default     = "-configuration"
}

# Private IP Address Allocation (priv_ip_alloc)
variable "priv_ip_alloc" {
  type        = string
  default     = "Static" # or Dynamic
}

# admin user (adminuser) name
variable "adminuser" {
  type        = string
  default     = "init-Admin001"
}

# Virtual Machine OS Disk (osdisk) name prefix
variable "vm_osdisk_pre" {
  type        = string
  default     = "osdisk-"
}

# Virtual Machine OS Disk SKU (osdisk_sku)
variable "vm_osdisk_sku" {
  type        = string
  default     = "StandardSSD_LRS"
}

# Virtual Machine SKU (vmsku) name
variable "vm_sku" {
  type        = string
  default     = "Standard_D4_v5"
}

# Virtual Machine (vm) name prefix
variable "vm_name_pre" {
  type        = string
  default     = "vm-"
}

# vm name suffix for Linux
variable "vm_name_suf_lin" {
  type        = string
  default     = "lin01"
}

# vm name suffix for Windows
variable "vm_name_suf_win" {
  type        = string
  default     = "win01"
}

# Virtual Machine OS Publisher (os_pub) name
# "MicrosoftWindowsDesktop" is Client OS 
# "MicrosoftWindowsServer" is Server OS
# "Canonical" is Ubuntu
# "almalinux" is Almalinux
variable "os_pub_lin" {
  type        = string
  default     = "almalinux"
}

# Virtual Machine OS Offer (os_offer) name
# "Windows-10" is Windows 10 
# "Windows-11" is Windows 11
# "WindowsServer" os Windows Server OS
# "0001-com-ubuntu-server-jammy" is Ubuntu
# "almalinux-x86_64" is Almalinux
variable "os_offer_lin" {
  type        = string
  default     = "almalinux-x86_64"
}

# Virtual Machine OS (os_sku) name
# 2016-Datacenter
# 2019-Datacenter
# 2022-datacenter-azure-edition
# 22_04-lts-gen2 (Ubuntu 22.04 LTS)
# 9-gen2 (Almalinux 9)
variable "os_sku_lin" {
  type        = string
  default     = "9-gen2"
}

# Virtual Machine OS Publisher (os_pub) name
# "MicrosoftWindowsDesktop" is Client OS 
# "MicrosoftWindowsServer" is Server OS
# "Canonical" is Ubuntu
# "almalinux" is Almalinux
variable "os_pub_win" {
  type        = string
  default     = "MicrosoftWindowsDesktop"
}

# Virtual Machine OS Offer (os_offer) name
# "Windows-10" is Windows 10 
# "Windows-11" is Windows 11
# "WindowsServer" os Windows Server OS
# "0001-com-ubuntu-server-jammy" is Ubuntu
# "almalinux-x86_64" is Almalinux
variable "os_offer_win" {
  type        = string
  default     = "Windows-11"
}

# Virtual Machine OS (os_sku) name
# 2016-Datacenter
# 2019-Datacenter
# 2022-datacenter-azure-edition
# 22_04-lts-gen2 (Ubuntu 22.04 LTS)
# 9-gen2 (Almalinux 9)
variable "os_sku_win" {
  type        = string
  default     = "win11-22h2-pro"
}

# Virtual Machine OS Version (os_ver) name
variable "os_ver" {
  type        = string
  default     = "latest"
}
```

今回はちゃんと整理して、不要な変数は削除しています。

## プロバイダ設定
```providers.tf
terraform {
  required_providers {
        azapi = {
      source  = "azure/azapi"
      version = "~>1.5"
    }
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~>3.0"
    }
    random = {
      source  = "hashicorp/random"
      version = "~>3.0"
    }
  }
}

provider "azapi" {
}

provider "azurerm" {
  features {}
  subscription_id   = "${var.ARM_SUBSCRIPTION_ID}"
  tenant_id         = "${var.ARM_TENANT_ID}"
  client_id         = "${var.ARM_CLIENT_ID}"
  client_secret     = "${var.ARM_CLIENT_SECRET}"
}
```

Terraform自身の設定パラメーターです。

## 仮想ネットワーク
```vnet_subnet.tf
#----------------------------------------
# vnet Create
#----------------------------------------
resource "azurerm_virtual_network" "vnet" {
  resource_group_name = azurerm_resource_group.rg.name
  location = azurerm_resource_group.rg.location
  name     = "${var.vnet_name_pre}${var.vnet_name_suf}"
  address_space = [ "${var.vnet_addr_pre}${var.vnet_addr_suf}" ]
}

# sn-linux01 Create
resource "azurerm_subnet" "sn-lin" {
  resource_group_name = azurerm_resource_group.rg.name
  name = "${var.sn_name_pre}${var.sn_name_suf_lin}"
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes = [ "${var.vnet_addr_pre}${var.sn_addr_suf_lin}" ]
  service_endpoints = [ "Microsoft.Storage" ]
}

# sn-win01 Create
resource "azurerm_subnet" "sn-win" {
  resource_group_name = azurerm_resource_group.rg.name
  name = "${var.sn_name_pre}${var.sn_name_suf_win}"
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes = [ "${var.vnet_addr_pre}${var.sn_addr_suf_win}" ]
  service_endpoints = [ "Microsoft.Storage" ]
}
```
1つの仮想ネットワークに2つサブネットを切っています。
それぞれLinux用とWindows用です。

## NSG
```nsg.tf
#------------------------------------
# nsg-sn-win Create
#------------------------------------

resource "azurerm_network_security_group" "nsg-sn-win" {
  resource_group_name = azurerm_resource_group.rg.name
  location = azurerm_resource_group.rg.location
  name = "${var.nsg_name_pre}${azurerm_subnet.sn-win.name}"

## InBound Rule
  security_rule  {
    name = "AllowVnetInBound"
    priority = 100
    direction = "Inbound"
    access = "Allow"
    protocol = "*"
    source_port_range = "*"
    destination_port_range = "*"
    source_address_prefix = "VirtualNetwork"
    destination_address_prefix = "VirtualNetwork"
  }

 security_rule  {
    name = "AllowAzureLoadBalancerInBound"
    priority = 101
    direction = "Inbound"
    access = "Allow"
    protocol = "*"
    source_port_range = "*"
    destination_port_range = "*"
    source_address_prefix = "AzureLoadBalancer"
    destination_address_prefix = "*"
  }

  security_rule {
    name = "AllowInBoundSSHOnPremises"
    priority = 1001
    direction = "Inbound"
    access = "Allow"
    protocol = "Tcp"
    source_port_range = "*"
    destination_port_range = "3389"
    source_address_prefix = "123.225.10.132"
    destination_address_prefix = "*"
  }

  security_rule {
    name = "DenyAllInBound"
    priority = 4096
    direction = "Inbound"
    access = "Deny"
    protocol = "*"
    source_port_range = "*"
    destination_port_range = "*"
    source_address_prefix = "*"
    destination_address_prefix = "*"
  }

## OutBound Rule
  security_rule  {
    name = "AllowVnetOutBound"
    priority = 100
    direction = "Outbound"
    access = "Allow"
    protocol = "*"
    source_port_range = "*"
    destination_port_range = "*"
    source_address_prefix = "VirtualNetwork"
    destination_address_prefix = "VirtualNetwork"
  }

 security_rule  {
    name = "AllowAzureFrontDoor.FirstPartyHttpOutBound"
    priority = 101
    direction = "Outbound"
    access = "Allow"
    protocol = "Tcp"
    source_port_range = "*"
    destination_port_range = "80"
    source_address_prefix = "*"
    destination_address_prefix = "AzureFrontDoor.FirstParty"
    description = "Allow Windows Update Rule01"
  }

 security_rule  {
    name = "AllowAzureUpdateDeliveryHttpsOutBound"
    priority = 102
    direction = "Outbound"
    access = "Allow"
    protocol = "Tcp"
    source_port_range = "*"
    destination_port_range = "443"
    source_address_prefix = "*"
    destination_address_prefix = "AzureUpdateDelivery"
    description = "Allow Windows Update Rule02"
  }

  security_rule {
    name = "AllowAllOutBound"
    priority = 4095
    direction = "Outbound"
    access = "Allow"
    protocol = "*"
    source_port_range = "*"
    destination_port_range = "*"
    source_address_prefix = "*"
    destination_address_prefix = "*"
  }

  security_rule {
    name = "DenyAllOutBound"
    priority = 4096
    direction = "Outbound"
    access = "Deny"
    protocol = "*"
    source_port_range = "*"
    destination_port_range = "*"
    source_address_prefix = "*"
    destination_address_prefix = "*"
  }

}

# Connect nsg-sn-win to sn-win
resource "azurerm_subnet_network_security_group_association" "nsg-sn-win-to-sn-win" {
  subnet_id =  azurerm_subnet.sn-win.id
  network_security_group_id = azurerm_network_security_group.nsg-sn-win.id
}

#------------------------------------
# nsg-sn-lin Create
#------------------------------------

resource "azurerm_network_security_group" "nsg-sn-lin" {
  resource_group_name = azurerm_resource_group.rg.name
  location = azurerm_resource_group.rg.location
  name = "${var.nsg_name_pre}${azurerm_subnet.sn-lin.name}"

## InBound Rule
  security_rule  {
    name = "AllowVnetInBound"
    priority = 100
    direction = "Inbound"
    access = "Allow"
    protocol = "*"
    source_port_range = "*"
    destination_port_range = "*"
    source_address_prefix = "VirtualNetwork"
    destination_address_prefix = "VirtualNetwork"
  }

 security_rule  {
    name = "AllowAzureLoadBalancerInBound"
    priority = 101
    direction = "Inbound"
    access = "Allow"
    protocol = "*"
    source_port_range = "*"
    destination_port_range = "*"
    source_address_prefix = "AzureLoadBalancer"
    destination_address_prefix = "*"
  }

  security_rule {
    name = "AllowInBoundSSHOnPremises"
    priority = 1001
    direction = "Inbound"
    access = "Allow"
    protocol = "Tcp"
    source_port_range = "*"
    destination_port_range = "22"
    source_address_prefix = "123.225.10.132"
    destination_address_prefix = "*"
  }

  security_rule {
    name = "DenyAllInBound"
    priority = 4096
    direction = "Inbound"
    access = "Deny"
    protocol = "*"
    source_port_range = "*"
    destination_port_range = "*"
    source_address_prefix = "*"
    destination_address_prefix = "*"
  }

## OutBound Rule
  security_rule  {
    name = "AllowVnetOutBound"
    priority = 100
    direction = "Outbound"
    access = "Allow"
    protocol = "*"
    source_port_range = "*"
    destination_port_range = "*"
    source_address_prefix = "VirtualNetwork"
    destination_address_prefix = "VirtualNetwork"
  }

 security_rule  {
    name = "AllowAzureFrontDoor.FirstPartyHttpOutBound"
    priority = 101
    direction = "Outbound"
    access = "Allow"
    protocol = "Tcp"
    source_port_range = "*"
    destination_port_range = "80"
    source_address_prefix = "*"
    destination_address_prefix = "AzureFrontDoor.FirstParty"
    description = "Allow Windows Update Rule01"
  }

 security_rule  {
    name = "AllowAzureUpdateDeliveryHttpsOutBound"
    priority = 102
    direction = "Outbound"
    access = "Allow"
    protocol = "Tcp"
    source_port_range = "*"
    destination_port_range = "443"
    source_address_prefix = "*"
    destination_address_prefix = "AzureUpdateDelivery"
    description = "Allow Windows Update Rule02"
  }

  security_rule {
    name = "AllowAllOutBound"
    priority = 4095
    direction = "Outbound"
    access = "Allow"
    protocol = "*"
    source_port_range = "*"
    destination_port_range = "*"
    source_address_prefix = "*"
    destination_address_prefix = "*"
  }

  security_rule {
    name = "DenyAllOutBound"
    priority = 4096
    direction = "Outbound"
    access = "Deny"
    protocol = "*"
    source_port_range = "*"
    destination_port_range = "*"
    source_address_prefix = "*"
    destination_address_prefix = "*"
  }

}

# Connect nsg-sn-lin to sn-lin
resource "azurerm_subnet_network_security_group_association" "nsg-sn-lin-to-sn-lin" {
  subnet_id =  azurerm_subnet.sn-lin.id
  network_security_group_id = azurerm_network_security_group.nsg-sn-lin.id
}
```
NSGも2つのサブネットに割り当てています。

## Linux VM
```linux_vm.tf
#--------------------------------
# linux vm * 1 create
#--------------------------------

# nic-vm-linux Create
resource "azurerm_network_interface" "nic-vm-linux" {
  count = 1
  resource_group_name = azurerm_resource_group.rg.name
  location = azurerm_resource_group.rg.location
  name = "${var.nic_name_pre}${var.vm_name_pre}${var.vm_name_suf_lin}${count.index+1}"

  ip_configuration {
    name = "${var.nic_name_pre}${var.vm_name_pre}${var.vm_name_suf_lin}${count.index+1}${var.ipconf_suf}"
    subnet_id = azurerm_subnet.sn-lin.id
    private_ip_address_allocation = "${var.priv_ip_alloc}"
    private_ip_address = "${var.vnet_addr_pre}200.${count.index+11}"
  }
}

# linux vm Create
resource "azurerm_linux_virtual_machine" "vm-linux" {
  count = 1
  name                  = "${var.vm_name_pre}${var.vm_name_suf_lin}${count.index+1}"
  admin_username        = "${var.adminuser}"
  admin_password        = "P@ssw0rd0123"
  disable_password_authentication = false
  location              = azurerm_resource_group.rg.location
  resource_group_name   = azurerm_resource_group.rg.name
  network_interface_ids = ["${element(azurerm_network_interface.nic-vm-linux.*.id, count.index+1)}"]
  size                  = "${var.vm_sku}"
  priority              = "Spot" # or Regular
  eviction_policy       = "Deallocate"
  
  os_disk {
    name                 = "${var.vm_osdisk_pre}${var.vm_name_pre}${var.vm_name_suf_lin}${count.index+1}"
    caching              = "ReadWrite"
    storage_account_type = "${var.vm_osdisk_sku}"
  }

  source_image_reference {
    publisher = "${var.os_pub_lin}"
    offer     = "${var.os_offer_lin}"
    sku       = "${var.os_sku_lin}"
    version   = "${var.os_ver}"
  }

  computer_name  = "${var.vm_name_pre}${var.vm_name_suf_lin}${count.index+1}"

  boot_diagnostics {
    storage_account_uri = azurerm_storage_account.storage_account.primary_blob_endpoint
  }
  zone = count.index +1
  depends_on = [
    azurerm_subnet_network_security_group_association.nsg-sn-lin-to-sn-lin
  ]
}
```

いつもは意識してないのですが、念のため```depends_on```でサブネットにNSGが割り当たるまでVM構築を行わない指定にしています。

## Windows VM
```windows_vm.tf
# --------------------------------------
# Create Windows 11
# --------------------------------------

# pip01 Create
resource "azurerm_public_ip" "pip-win" {
  name                = "${var.pip_name_pre}${var.vm_name_pre}${var.vm_name_suf_win}"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  sku                 = "Standard"
  allocation_method   = "Static"
}

# nic01 (attached for vm01) Create
resource "azurerm_network_interface" "nic-win" {
  resource_group_name = azurerm_resource_group.rg.name
  location = azurerm_resource_group.rg.location
  name = "${var.nic_name_pre}${var.vm_name_pre}${var.vm_name_suf_win}"

  ip_configuration {
    name = "${var.nic_name_pre}${var.vm_name_pre}${var.vm_name_suf_win}${var.ipconf_suf}"
    subnet_id = azurerm_subnet.sn-win.id
    private_ip_address_allocation = "${var.priv_ip_alloc}"
    private_ip_address = "${var.vnet_addr_pre}201.11"
    public_ip_address_id = azurerm_public_ip.pip-win.id
  }
}

# windows vm01 Create
resource "azurerm_windows_virtual_machine" "vm-win" {
  name                  = "${var.vm_name_pre}${var.vm_name_suf_win}"
  admin_username        = "${var.adminuser}"
#  admin_password        = random_password.password.result
  admin_password        = "P@ssw0rd0123"
  location              = azurerm_resource_group.rg.location
  resource_group_name   = azurerm_resource_group.rg.name
  network_interface_ids = [azurerm_network_interface.nic-win.id]
  size                  = "${var.vm_sku}"
  priority              = "Spot" # or Regular
  eviction_policy       = "Deallocate"
  
  os_disk {
    name                 = "${var.vm_osdisk_pre}${var.vm_name_pre}${var.vm_name_suf_win}"
    caching              = "ReadWrite"
    storage_account_type = "${var.vm_osdisk_sku}"
  }

  source_image_reference {
    publisher = "${var.os_pub_win}"
    offer     = "${var.os_offer_win}"
    sku       = "${var.os_sku_win}"
    version   = "${var.os_ver}"
  }

  boot_diagnostics {
    storage_account_uri = azurerm_storage_account.storage_account.primary_blob_endpoint
  }
    depends_on = [
    azurerm_subnet_network_security_group_association.nsg-sn-win-to-sn-win
  ]
}
```
こちらもLinux VMと同じく念のため```depends_on```でサブネットにNSGが割り当たるまでVM構築を行わない指定にしています。

## Storage Account
```storage.tf
# Create storage account for boot diagnostics
resource "azurerm_storage_account" "storage_account" {
  resource_group_name      = azurerm_resource_group.rg.name
  location                 = azurerm_resource_group.rg.location
  name                     = "stdiag${random_id.random_id.hex}"
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

resource "azurerm_storage_account_network_rules" "for_multiple_subnet_id" {
  storage_account_id = azurerm_storage_account.storage_account.id
  default_action = "Deny"
  virtual_network_subnet_ids = [azurerm_subnet.sn-win.id,azurerm_subnet.sn-lin.id]
  ip_rules = ["123.225.10.132"]
}
```
VMのログ出力用のストレージアカウントです。

## 実行結果
ストレージアカウントのネットワークルール部分で他の処理(恐らくVM構築前のNIC構築の処理)と重複したようで一度コケましたが、コード修正せず再度```terraform apply```を実行したところ問題なく処理できました。

1回目コケた結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/7556ad8b-7402-38c2-cb38-29473a0b16f7.png)

コード修正なく2回目実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/34f528a5-e308-38da-8e72-b6ef1775a6f8.png)
はい。
問題なく完了しています。

# 検証結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/7c503c73-63f5-d6b6-94e3-fe0389a0e408.png)
はい。
このVMで検証しました。

|項目|設定値|
|---|---|
|OS|Windows 11|
|通信先FQDN|vm-lin011.s54gobrnmzbexkge2hgnfhkmwh.ix.internal.cloudapp.net|

はい。
こんな感じですね。
DNSは明示的に指定していないのでAzureのデフォルト、Azure DNS(168.63.129.16)になります。

結果は図の通りなのですが
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/72c3d8f1-beac-7429-db8c-6b73b4f3d1da.png)
<font color="Red">赤枠</font>の一番下ですね、AWSだとこのName:の下の行にIPアドレスが出てたんですが、Azureは出てきません。
ここに試しにPingを打ってみても
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/e59e494b-d870-a790-d3be-a71c78fde145.png)
「宛先がねーよ」って言われてPing打てません。
結論、
<font color="Red">**Azureの場合は暗黙的なDNSサーバ(Azure DNS)は権威サーバかどうかわからない。**</font>
ということになりますね。
機会があればSRで確認してみようと思います。

本日はここまで。