今日 Azure Resource Manager 向けの Terraform Provider の新バージョンがリリースされていたので、リリースノートを眺めていたら Service Tags を取るための Data Source が追加されていました。
Service Tags を取るには巨大な JSON を読み取るしかないと思っていましたが、ARM REST API が Public Preview として公開されているので、それを利用して実装しているようです。
ドキュメントは微妙に typo が多いですが、パラメータが少ないので簡単に使えます。ARM REST API の仕様がイマイチで、Service Tags を取るために location を指定する必要があり、それが Service 自体の location と混同しそうになります。
App Service などの各リージョンにデプロイされているサービスで、対象リージョンを絞り込む場合には location_filter
を指定して行います。
実際に Japan East にある App Service の IP Address のリストを取得する場合には、以下のような定義を書いて terraform refresh
を実行すると表示されます。
data "azurerm_network_service_tags" "default" { location = "Japan East" service = "AppService" location_filter = "Japan East" } output "address_prefixes" { value = data.azurerm_network_service_tags.default.address_prefixes }
JSON ではなく ARM REST API を使っているからか、微妙にドキュメントに書いてある Service Tags とは名前付けが異なっているケースもありました。プレビュー中は同期されるのにラグがありそうです。
VNET と NSG を使っている場合は、直接 Service Tags を条件に指定できるので IP Address のリストを使う機会はほぼなさそうですが、App Service の IP 制限では欲しいときがたまにあります。
Service Endpoints が使えるので特定の Subnet からのトラフィックのみ許可の場合は簡単に行えますが、それ以外の場合は IP Address でチマチマと書く必要がありました。*1
サンプルとして、よく使いそうな Front Door からのトラフィックのみ許可するような定義を書いてみました。
現状 Front Door の Outbound IP Range は 1 つしかないので手動でも変わらない気もしますが、もし増えた場合には自動で対応できるメリットはあります。
data "azurerm_network_service_tags" "frontdoor" { location = "Japan East" service = "AzureFrontDoor" } resource "azurerm_resource_group" "default" { name = "appservice-test" location = "Japan East" } resource "azurerm_app_service_plan" "default" { name = "ASP-Default-01" location = azurerm_resource_group.default.location resource_group_name = azurerm_resource_group.default.name sku { tier = "PremiumV2" size = "P1v2" } } resource "azurerm_app_service" "default" { name = "backend-appservice-01" location = azurerm_resource_group.default.location resource_group_name = azurerm_resource_group.default.name app_service_plan_id = azurerm_app_service_plan.default.id site_config { dynamic "ip_restriction" { for_each = data.azurerm_network_service_tags.frontdoor.address_prefixes content { ip_address = ip_restriction.value } } } }
複数の IP Address が返ってくることを考慮して、Dynamic blocks を使って ip_restriction
を生成するようにしています。ちょっと冗長さは否めないです。
この定義を使うと、Front Door の IP Address のみ許可する設定が追加された状態で作成されます。
必要な時にサクッと Terraform の Data Source として特定リージョンのサービスの IP Address を参照できるのは便利なのですが、割とニッチな需要という感じはします。
本当なら NSG + Service Tags や Private Link などで解決したい世界でした。
*1:Service Tags を条件に使えるようになって欲しさがある