Terraformを用いてSQL ServerのFirewallにAzure App ServiceのIPアドレスを追加する
2020-04-03
azblob://2022/11/11/eyecatch/2020-04-03-app-service-possible-outbound-ip-addresses-sql-firewall-000.jpg

こんにちは。cloud.config Divの神田です。
今回はTerraformを用いてSQL ServerのFirewallにApp ServiceのIPアドレスを許可させます。

App ServiceのIPアドレスについて

Azureポータル上で App Service > プロパティ > 追加の送信IPアドレスで表示されるものが、
App Serviceが送信時に使う可能性のあるものも含めたIPアドレス一覧です。(以下画像参照)

この「追加の送信IPアドレス」ですが、構築を自動化する際に少し困るような仕様となっています。

まず、App Serviceのデプロイが完了するまでIPアドレスの値が確定しないので、
TerraformでApp ServiceとSQL Serverを同時に作成し、さらにApp ServiceのIPアドレスをFirewallで許可させるといったことはできません。

また、「追加の送信IPアドレス」で利用されるIPアドレスの数ですが、こちらはApp ServiceがホストされるAzureデータセンター内の物理基盤により左右されるので、
ユーザ側で事前に決めることができず、各リージョンやデータセンターでいくつあるのかといった情報も公開されていません。

App Serviceの「追加の送信IPアドレス」

今回の目標

今回は上記のApp Serviceの「追加の送信IPアドレス」をTerraformを用いてSQL ServerのFirewallに許可させます。

なお、上記の通りTerraformでApp ServiceとSQL Serverを作成し、同時に「追加の送信IPアドレス」をSQL ServerのFirewallに許可させることはできないので、
今回はApp ServiceとSQL Serverが作成された後にTerraformを実行し、SQL ServerのFirewallを設定します。

Terraformで既存のリソースの情報を取得する

Terraformでは「resource」ブロックを用いることでリソースを作成することができますが、
「data」ブロックを用いることで既存のリソースを取得することができます。
また「output」ブロックを用いることでリソースの特定のパラメータを取得することができます。

今回は以下のコードで既存のApp Serviceの「追加の送信IPアドレス」を取得します。
なお上記コードで取得した「追加の送信IPアドレス」はカンマ区切りの文字列として取得されます。

data "azurerm_app_service" "app_je" {
  name                = "App Serviceのリソース名"
  resource_group_name = "App Serviceが所属しているリソースグループ名"
}

output "possible_outbound_ip_addresses" {
  value = "${data.azurerm_app_service.app_je.possible_outbound_ip_addresses}"
}

Terraformでループを実装する

今回はSQL ServerのFirewallを「追加の送信IPアドレス」分追加するのでループで処理するようにします。
Terraformでは「count」というパラメータを用いることで「count」に渡した回数ループしてリソースを作成することができます。

以下のコードを用いることでSQL ServerのFirewallルールを3つ作成することができます。
またルール名は「ルール名_001」、「ルール名_002」、「ルール名_003」となります。

なお、「count」はmoduleに対応していないのでご注意ください。

resource "azurerm_sql_firewall_rule" "sql_fw_rule_je" {
  count         = 3

  name                = "${format("ルール名_%03d", count.index + 1)}"
  resource_group_name = "SQL Serverのリソースグループ名"
  server_name         = "SQL Serverのリソース名"
  start_ip_address    = "開始IPアドレス"
  end_ip_address      = "終了IPアドレス"
}

「追加の送信IPアドレス」を許可するように調整

以下のコードを用いることでApp Serviceの「追加の送信IPアドレス」を取得し、
取得したIPアドレスの数だけループを回してSQL ServerのFirewallを作成します。

resource "azurerm_sql_firewall_rule" "sql_fw_rule_je" {
  count = "${length(split(",", data.azurerm_app_service.app_je.possible_outbound_ip_addresses))}"

  name                = "${format("ルール名_%03d", count.index + 1)}"
  resource_group_name = "リソースグループ名"
  server_name         = "SQL Serverのリソース名"
  start_ip_address    = "${element(split(",", data.azurerm_app_service.app_je.possible_outbound_ip_addresses), count.index)}"
  end_ip_address      = "${element(split(",", data.azurerm_app_service.app_je.possible_outbound_ip_addresses), count.index)}"
}
上記コードの実行後

最後に

一度の実行でリソースの作成とFirewallの設定を両立させたかったのですが、
上手くいかなかったので今回は妥協しました。

Terraformには今回用いた「count」や「split()」といった便利なパラメータや組み込み関数があるので、効果的に利用していきたいです。