こんにちは。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アドレス」を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()」といった便利なパラメータや組み込み関数があるので、効果的に利用していきたいです。