AzureFileSyncを試してみる その1
はじめに
Azure File Syncを試してみたかったので、Terraformで環境を作ってみました。色々とハマったところもあり、残しておきます。3回くらいに分けて書く予定。
システム構成
Azure File Syncはオンプレファイルサーバと接続してハイブリッドクラウド的な感じで使うようなサービスかと思います。今回はオンプレ側が用意できないので、Azure VM立ててそれと接続してます。細かい部分は後述してきますが、こんなイメージのものを作っていきたいと思います。以降、tfファイルごとにリソースの定義を説明してきます。
お決まり部分の定義
Terraformのバージョンやプロバイダーのバージョンを指定します。なお、このコードではバージョン固定にはしてませんが、Terraform 1.2.8、Azureのプロバイダー(azurerm 3.23.0、azuread 2.28.1)を利用しました。また、Azureで必須となるリソースグループをここで定義しています。
terraform {
required_version = "~>1.2.0"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~>3.23.0"
}
azuread = {
source = "hashicorp/azuread"
version = "~>2.28.0"
}
}
}
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "this" {
name = "dev-rg"
location = var.resource_group_location
}
変数の定義は以下のようにしてます。リソースグループのロケーションは東日本リージョンとしました。サブネットのアドレスもここで定義してます。
variable "resource_group_location" {
default = "japaneast"
description = "Location of the resource group"
}
variable "vnet_address" {
type = list(string)
default = ["10.0.0.0/16"]
description = "virtual network address"
}
variable "vnet_subnet" {
type = list(string)
default = ["10.0.1.0/24"]
description = "virtual network subnet"
}
variable "vnet_bastion_subnet" {
type = list(string)
default = ["10.0.0.192/26"]
description = "bastion subnet(require a minimum of /26)"
}
ここまでで、この部分の定義ができました。(あまり意味ない絵ですが。。)
ネットワーク周りの定義
ネットワーク周りを作ります。Azure VMへのアクセスはBastion使いたいので、プライベートなサブネット(dev-subnet1)とBastion用のサブネット(AzureBastionSubnet)を用意しています。あとストレージアカウントとはサービスエンドポイントでつなぎたいので、その定義もしてます。
resource "azurerm_virtual_network" "this" {
name = "dev-vnet"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
address_space = var.vnet_address
}
resource "azurerm_subnet" "bastion_subnet" {
name = "AzureBastionSubnet"
resource_group_name = azurerm_resource_group.this.name
virtual_network_name = azurerm_virtual_network.this.name
address_prefixes = var.vnet_bastion_subnet
}
resource "azurerm_subnet" "dev_subnet1" {
name = "dev-subnet1"
resource_group_name = azurerm_resource_group.this.name
virtual_network_name = azurerm_virtual_network.this.name
address_prefixes = var.vnet_subnet
service_endpoints = ["Microsoft.Storage"]
}
次にNSGを作ります。dev-nsg-publicではBastionに必要となる通信を開けてます。[1]dev-nsg-privateではプライベートサブネットへの外部からの接続は基本NGとし、例外としてBastionサブネットからのRDPを許可してます。プライベートサブネットからの外部接続はhttpとhttpsのみ許可してます。[2]作成したNSGを各サブネットに適用します。dev-nsg-publicはAzureBastionSubnetに、dev-nsg-privateはdev-subnet1に紐づけてます。
resource "azurerm_network_security_group" "public" {
name = "dev-nsg-public"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
}
resource "azurerm_network_security_rule" "allow_https_inbound_bastion" {
name = "AllowHttpsInbound"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "Internet"
destination_address_prefix = "*"
resource_group_name = azurerm_resource_group.this.name
network_security_group_name = azurerm_network_security_group.public.name
}
resource "azurerm_network_security_rule" "allow_communication_inbound_bastion" {
name = "AllowBastionHostCommunicationInbound"
priority = 110
direction = "Inbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_ranges = ["8080", "5701"]
source_address_prefix = "VirtualNetwork"
destination_address_prefix = "VirtualNetwork"
resource_group_name = azurerm_resource_group.this.name
network_security_group_name = azurerm_network_security_group.public.name
}
resource "azurerm_network_security_rule" "allow_gatewaymanager_inbound_bastion" {
name = "AllowGatewayManagerInbound"
priority = 120
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "GatewayManager"
destination_address_prefix = "*"
resource_group_name = azurerm_resource_group.this.name
network_security_group_name = azurerm_network_security_group.public.name
}
resource "azurerm_network_security_rule" "allow_loadbalancer_inbound_bastion" {
name = "AllowAzureLoadBalancerInbound"
priority = 130
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "AzureLoadBalancer"
destination_address_prefix = "*"
resource_group_name = azurerm_resource_group.this.name
network_security_group_name = azurerm_network_security_group.public.name
}
resource "azurerm_network_security_rule" "deny_all_inbound_bastion" {
name = "DenyAllInbound"
priority = 200
direction = "Inbound"
access = "Deny"
protocol = "*"
source_port_range = "*"
destination_port_range = "*"
source_address_prefix = "*"
destination_address_prefix = "*"
resource_group_name = azurerm_resource_group.this.name
network_security_group_name = azurerm_network_security_group.public.name
}
resource "azurerm_network_security_rule" "allow_sshrdp_outbound_bastion" {
name = "AllowSshRdpOutbound"
priority = 100
direction = "Outbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_ranges = ["22", "3389"]
source_address_prefix = "*"
destination_address_prefix = "VirtualNetwork"
resource_group_name = azurerm_resource_group.this.name
network_security_group_name = azurerm_network_security_group.public.name
}
resource "azurerm_network_security_rule" "allow_azurecloud_outbound_bastion" {
name = "AllowAzureCloudOutbound"
priority = 110
direction = "Outbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "*"
destination_address_prefix = "AzureCloud"
resource_group_name = azurerm_resource_group.this.name
network_security_group_name = azurerm_network_security_group.public.name
}
resource "azurerm_network_security_rule" "allow_communication_outbound_bastion" {
name = "AllowBastionHostCommunicationOutbound"
priority = 120
direction = "Outbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_ranges = ["8080", "5701"]
source_address_prefix = "VirtualNetwork"
destination_address_prefix = "VirtualNetwork"
resource_group_name = azurerm_resource_group.this.name
network_security_group_name = azurerm_network_security_group.public.name
}
resource "azurerm_network_security_rule" "allow_http_outbound_bastion" {
name = "AllowGetSessionInformation"
priority = 130
direction = "Outbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "80"
source_address_prefix = "*"
destination_address_prefix = "Internet"
resource_group_name = azurerm_resource_group.this.name
network_security_group_name = azurerm_network_security_group.public.name
}
resource "azurerm_network_security_rule" "deny_all_outbound_bastion" {
name = "DenyAllOutbound"
priority = 200
direction = "Outbound"
access = "Deny"
protocol = "*"
source_port_range = "*"
destination_port_range = "*"
source_address_prefix = "*"
destination_address_prefix = "*"
resource_group_name = azurerm_resource_group.this.name
network_security_group_name = azurerm_network_security_group.public.name
}
resource "azurerm_network_security_group" "private" {
name = "dev-nsg-private"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
}
resource "azurerm_network_security_rule" "allow_rdp_inbound_private" {
name = "AllowRDPInbound_private"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "3389"
source_address_prefixes = var.vnet_bastion_subnet
destination_address_prefix = "*"
resource_group_name = azurerm_resource_group.this.name
network_security_group_name = azurerm_network_security_group.private.name
}
resource "azurerm_network_security_rule" "deny_all_inbound_private" {
name = "DenyAllInbound_private"
priority = 200
direction = "Inbound"
access = "Deny"
protocol = "*"
source_port_range = "*"
destination_port_range = "*"
source_address_prefix = "*"
destination_address_prefix = "*"
resource_group_name = azurerm_resource_group.this.name
network_security_group_name = azurerm_network_security_group.private.name
}
resource "azurerm_network_security_rule" "allow_http_outbound_private" {
name = "AllowHttpOutbound_private"
priority = 100
direction = "Outbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "80"
source_address_prefix = "*"
destination_address_prefix = "*"
resource_group_name = azurerm_resource_group.this.name
network_security_group_name = azurerm_network_security_group.private.name
}
resource "azurerm_network_security_rule" "allow_https_outbound_private" {
name = "AllowHttpsOutbound_private"
priority = 110
direction = "Outbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "*"
destination_address_prefix = "*"
resource_group_name = azurerm_resource_group.this.name
network_security_group_name = azurerm_network_security_group.private.name
}
resource "azurerm_network_security_rule" "deny_all_outbound_private" {
name = "DenyAllOutbound_private"
priority = 200
direction = "Outbound"
access = "Deny"
protocol = "*"
source_port_range = "*"
destination_port_range = "*"
source_address_prefix = "*"
destination_address_prefix = "*"
resource_group_name = azurerm_resource_group.this.name
network_security_group_name = azurerm_network_security_group.private.name
}
resource "azurerm_subnet_network_security_group_association" "public" {
subnet_id = azurerm_subnet.bastion_subnet.id
network_security_group_id = azurerm_network_security_group.public.id
depends_on = [
azurerm_network_security_rule.allow_azurecloud_outbound_bastion,
azurerm_network_security_rule.allow_communication_inbound_bastion,
azurerm_network_security_rule.allow_communication_outbound_bastion,
azurerm_network_security_rule.allow_gatewaymanager_inbound_bastion,
azurerm_network_security_rule.allow_http_outbound_bastion,
azurerm_network_security_rule.allow_https_inbound_bastion,
azurerm_network_security_rule.allow_loadbalancer_inbound_bastion,
azurerm_network_security_rule.allow_sshrdp_outbound_bastion,
azurerm_network_security_rule.deny_all_inbound_bastion,
azurerm_network_security_rule.deny_all_outbound_bastion
]
}
resource "azurerm_subnet_network_security_group_association" "private" {
subnet_id = azurerm_subnet.dev_subnet1.id
network_security_group_id = azurerm_network_security_group.private.id
}
ネットワーク周りの定義ができました。
Bastionの定義
Bastionを作ります。Bastionの要件を満たすPIP[3]を作ってBastionに紐づけてます。
resource "azurerm_public_ip" "this" {
name = "dev-bastion-ip"
resource_group_name = azurerm_resource_group.this.name
location = azurerm_resource_group.this.location
allocation_method = "Static"
sku = "Standard"
}
resource "azurerm_bastion_host" "this" {
name = "dev-bastion"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
ip_configuration {
name = "public"
subnet_id = azurerm_subnet.bastion_subnet.id
public_ip_address_id = azurerm_public_ip.this.id
}
}
Bastionの定義ができました。
おわりに
今回はここまで。次回はAzure VM立ててエージェント入れる部分の定義やストレージ周りの定義について書きたいと思います。
-
https://docs.microsoft.com/ja-jp/azure/bastion/bastion-nsg ↩︎
-
Azure既定のSNATを利用。168.63.129.16や169.254.169.254、KMSのアドレスあたりは明示的に許可しなくても通信できました。 ↩︎
-
https://learn.microsoft.com/ja-jp/azure/virtual-network/ip-services/configure-public-ip-bastion ↩︎
Discussion